diff --git a/CMakeLists.txt b/CMakeLists.txt
index b51131fae09b115b84c3afeea8baa490ab07b49d..dc333dda9b7d7ae09617d4570fac3d010093af33 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1419,8 +1419,7 @@ endif()
 # don't issue warnings for contributed libraries
 check_cxx_compiler_flag("-w" NOWARN)
 if(NOWARN)
-  file(GLOB_RECURSE NOWARN_SRC contrib/*.cpp contrib/*.cc contrib/*.cxx contrib/*.c
-      ${CMAKE_CURRENT_BINARY_DIR}/contrib/taucs/*.c)
+  file(GLOB_RECURSE NOWARN_SRC contrib/*.cpp contrib/*.cc contrib/*.cxx contrib/*.c)
   set_compile_flags(NOWARN_SRC "-w")
 endif()
 
diff --git a/Solver/elasticityTerm.cpp b/Solver/elasticityTerm.cpp
index 28f153dd5baf4907a2286586782e8975fc4a939a..aae9fdc5d68de87f7eeeead9a7cdc76311cf39b3 100644
--- a/Solver/elasticityTerm.cpp
+++ b/Solver/elasticityTerm.cpp
@@ -37,8 +37,6 @@ void elasticityTerm::createData(MElement *e) const
     d.w.push_back(w);
     d.weight.push_back(weight);
   }
-  //  printf("coucou creation of a data for %d with %d
-  //  points\n",e->getTypeForMSH(),npts);
   _data[e->getTypeForMSH()] = d;
 }
 
@@ -87,7 +85,6 @@ void elasticityTerm::elementMatrix(SElement *se, fullMatrix<double> &m) const
     BT.setAll(0.);
 
     if(se->getShapeEnrichement() == se->getTestEnrichement()) {
-      //      printf("coucou\n");
       for(int j = 0; j < nbSF; j++) {
         BT(j, 0) = B(0, j) = Grads[j][0];
         BT(j, 3) = B(3, j) = Grads[j][1];
@@ -125,7 +122,6 @@ void elasticityTerm::elementMatrix(SElement *se, fullMatrix<double> &m) const
     BTH.gemm(BT, H);
     m.gemm(BTH, B, weight * detJ, 1.);
   }
-  return;
 }
 
 void elasticityTerm::elementVector(SElement *se, fullVector<double> &m) const
diff --git a/Solver/linearSystemPETSc.hpp b/Solver/linearSystemPETSc.hpp
index b3cb7ceffb9956497a5b1d57ed038849c514817b..a7772834faef53e0f57cb1135ae0af428b9fcb97 100644
--- a/Solver/linearSystemPETSc.hpp
+++ b/Solver/linearSystemPETSc.hpp
@@ -124,7 +124,7 @@ template <class scalar> void linearSystemPETSc<scalar>::preAllocateEntries()
   int blockSize = _getBlockSizeFromParameters();
   std::vector<int> nByRowDiag(_localSize), nByRowOffDiag(_localSize);
   if(_sparsity.getNbRows() == 0) {
-    PetscInt prealloc = 500;
+    PetscInt prealloc = 100;
     PetscBool set;
     PetscOptionsGetInt(PETSC_NULL, "-petsc_prealloc", &prealloc, &set);
     prealloc = std::min(prealloc, _localSize);
diff --git a/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.cpp b/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.cpp
index a6e7d17fbb931a0f8a1d49e6ba4b556a34495ea6..6a59092af074c8ae37f11dd0c7cd3c5ae23f6cbf 100644
--- a/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.cpp
+++ b/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.cpp
@@ -100,7 +100,7 @@ void HighOrderMeshElasticAnalogy(GModel *m, bool onlyVisible)
                  t2 - t1);
 }
 
-void highOrderTools::moveToStraightSidedLocation(MElement *e) const
+void highOrderTools::_moveToStraightSidedLocation(MElement *e) const
 {
   for(int i = 0; i < e->getNumVertices(); i++) {
     MVertex *v = e->getVertex(i);
@@ -239,21 +239,16 @@ void highOrderTools::ensureMinimumDistorsion(double threshold)
   ensureMinimumDistorsion(v, threshold);
 }
 
-void highOrderTools::computeMetricInfo(GFace *gf, MElement *e,
-                                       fullMatrix<double> &J,
-                                       fullMatrix<double> &JT,
-                                       fullVector<double> &D)
+void highOrderTools::_computeMetricInfo(GFace *gf, MElement *e,
+                                        fullMatrix<double> &J,
+                                        fullMatrix<double> &JT,
+                                        fullVector<double> &D)
 {
   int nbNodes = e->getNumVertices();
-  //  printf("ELEMENT --\n");
   for(int j = 0; j < nbNodes; j++) {
     SPoint2 param;
     reparamMeshVertexOnFace(e->getVertex(j), gf, param);
-    //    printf("%g %g vs %g %g %g\n",param.x(),param.y(),
-    //	   e->getVertex(j)->x(),e->getVertex(j)->y(),e->getVertex(j)->z());
-
     Pair<SVector3, SVector3> der = gf->firstDer(param);
-
     int XJ = j;
     int YJ = j + nbNodes;
     int ZJ = j + 2 * nbNodes;
@@ -283,11 +278,12 @@ void highOrderTools::computeMetricInfo(GFace *gf, MElement *e,
 
 void highOrderTools::applySmoothingTo(std::vector<MElement *> &all, GFace *gf)
 {
-#ifdef HAVE_TAUCS
-  linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>;
+#if !defined(HAVE_PETSC)
+  Msg::Error("Elastic analogy smoother on surface %d requires PETSc",
+             gf->tag());
 #else
   linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>;
-#endif
+
   // compute the straight sided positions of high order nodes that are
   // on the edges of the face in the UV plane
   dofManager<double> myAssembler(lsys);
@@ -303,6 +299,7 @@ void highOrderTools::applySmoothingTo(std::vector<MElement *> &all, GFace *gf)
   }
 
   if(!v.size()) return;
+
   Msg::Info(
     "Smoothing surface %d (%d elements considered in elastic analogy, "
     "worst mapping %12.5E, %3d bad elements)",
@@ -323,7 +320,7 @@ void highOrderTools::applySmoothingTo(std::vector<MElement *> &all, GFace *gf)
 
   // fix all vertices that cannot move
   for(std::size_t i = 0; i < v.size(); i++) {
-    moveToStraightSidedLocation(v[i]);
+    _moveToStraightSidedLocation(v[i]);
     for(int j = 0; j < v[i]->getNumVertices(); j++) {
       MVertex *vert = v[i]->getVertex(j);
       if(vert->onWhat()->dim() < 2) {
@@ -344,12 +341,12 @@ void highOrderTools::applySmoothingTo(std::vector<MElement *> &all, GFace *gf)
     }
   }
 
-  double dx0 = smooth_metric_(v, gf, myAssembler, verticesToMove, El);
+  double dx0 = _smoothMetric(v, gf, myAssembler, verticesToMove, El);
   double dx = dx0;
   Msg::Debug(" dx0 = %12.5E", dx0);
   int iter = 0;
   while(0) {
-    double dx2 = smooth_metric_(v, gf, myAssembler, verticesToMove, El);
+    double dx2 = _smoothMetric(v, gf, myAssembler, verticesToMove, El);
     Msg::Debug(" dx2  = %12.5E", dx2);
     if(fabs(dx2 - dx) < 1.e-4 * dx0) break;
     if(iter++ > 2) break;
@@ -374,12 +371,13 @@ void highOrderTools::applySmoothingTo(std::vector<MElement *> &all, GFace *gf)
     }
   }
   delete lsys;
+#endif
 }
 
-double highOrderTools::smooth_metric_(std::vector<MElement *> &v, GFace *gf,
-                                      dofManager<double> &myAssembler,
-                                      std::set<MVertex *> &verticesToMove,
-                                      elasticityTerm &El)
+double highOrderTools::_smoothMetric(std::vector<MElement *> &v, GFace *gf,
+                                     dofManager<double> &myAssembler,
+                                     std::set<MVertex *> &verticesToMove,
+                                     elasticityTerm &El)
 {
   std::set<MVertex *>::iterator it;
   double dx = 0.0;
@@ -402,7 +400,7 @@ double highOrderTools::smooth_metric_(std::vector<MElement *> &v, GFace *gf,
       K33.setAll(0.0);
       SElement se(e);
       El.elementMatrix(&se, K33);
-      computeMetricInfo(gf, e, J32, J23, D3);
+      _computeMetricInfo(gf, e, J32, J23, D3);
       J23K33.gemm(J23, K33, 1, 0);
       K22.gemm(J23K33, J32, 1, 0);
       J23K33.mult(D3, R2);
@@ -440,7 +438,7 @@ double highOrderTools::smooth_metric_(std::vector<MElement *> &v, GFace *gf,
 
 highOrderTools::highOrderTools(GModel *gm) : _gm(gm), _tag(111), _dim(2)
 {
-  computeStraightSidedPositions();
+  _computeStraightSidedPositions();
 }
 
 highOrderTools::highOrderTools(GModel *gm, GModel *mesh, int order)
@@ -449,10 +447,10 @@ highOrderTools::highOrderTools(GModel *gm, GModel *mesh, int order)
   GeomMeshMatcher::instance()->forceTomatch(gm, mesh, 1.e-5);
   GeomMeshMatcher::instance()->destroy();
   SetOrderN(gm, order, false, false);
-  computeStraightSidedPositions();
+  _computeStraightSidedPositions();
 }
 
-void highOrderTools::computeStraightSidedPositions()
+void highOrderTools::_computeStraightSidedPositions()
 {
   _clean();
   // compute straigh sided positions that are actually X,Y,Z positions
@@ -605,26 +603,31 @@ void highOrderTools::computeStraightSidedPositions()
 
 // apply a displacement that does not create elements that are distorted over a
 // value "thres"
-double highOrderTools::apply_incremental_displacement(
+double highOrderTools::_applyIncrementalDisplacement(
   double max_incr, std::vector<MElement *> &v, bool mixed, double thres,
   char *meshName, std::vector<MElement *> &disto)
 {
-#ifdef HAVE_PETSC
+#if !defined(HAVE_PETSC)
+  Msg::Error("Elastic analogy smoother requires PETSc");
+#else
+  if(v.empty()) return 1.;
+
   // assume that the mesh is OK, yet already curved
-  // linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>;
   linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>;
-  lsys->setParameter("petscOptions", "-pc_type ilu");
-  lsys->setParameter("petscOptions", "-ksp_monitor");
-
+  char opt[256];
+  sprintf(opt, "-pc_type ilu -ksp_monitor -petsc_prealloc %d",
+          100 * (v[0]->getPolynomialOrder() + 2));
+  lsys->setParameter("petscOptions", opt);
+  Msg::Info("Assembling linear system...");
   dofManager<double> myAssembler(lsys);
   elasticityMixedTerm El_mixed(0, 1.0, .333, _tag);
   elasticityTerm El(0, 1.0, .333, _tag);
 
   std::set<MVertex *> _vertices;
 
-  //+++++++++ Boundary Conditions & Numbering +++++++++++++++++++++++++++++++
-  // fix all dof that correspond to vertices on the boundary
-  // the value is equal
+  // Boundary Conditions & Numbering
+
+  // fix all dof that correspond to vertices on the boundary the value is equal
   for(std::size_t i = 0; i < v.size(); i++) {
     for(int j = 0; j < v[i]->getNumVertices(); j++) {
       MVertex *vert = v[i]->getVertex(j);
@@ -632,7 +635,7 @@ double highOrderTools::apply_incremental_displacement(
     }
   }
 
-  //+++++++++ Fix d tr(eps) = 0 +++++++++++++++++++++++++++++++
+  // Fix d tr(eps) = 0
   if(mixed) {
     for(std::size_t i = 0; i < disto.size(); i++) {
       for(int j = 0; j < disto[i]->getNumVertices(); j++) {
@@ -658,7 +661,6 @@ double highOrderTools::apply_incremental_displacement(
       myAssembler.fixVertex(vert, 1, _tag, 0);
       myAssembler.fixVertex(vert, 2, _tag, 0);
     }
-    //    }
     if(_dim == 2) myAssembler.fixVertex(vert, 2, _tag, 0);
     // number vertices
     myAssembler.numberVertex(vert, 0, _tag);
@@ -679,6 +681,7 @@ double highOrderTools::apply_incremental_displacement(
       else
         El.addToMatrix(myAssembler, &se);
     }
+    Msg::Info("Solving linear system (%d unknowns)...", myAssembler.sizeOfR());
     // solve the system
     lsys->systemSolve();
   }
@@ -757,17 +760,21 @@ double highOrderTools::applySmoothingTo(std::vector<MElement *> &all,
   int ITER = 0;
   double minD;
   std::vector<MElement *> disto;
+
   // move the points to their straight sided locations
   for(std::size_t i = 0; i < all.size(); i++)
-    moveToStraightSidedLocation(all[i]);
+    _moveToStraightSidedLocation(all[i]);
+
   // apply the displacement
 
   // _gm->writeMSH("straightSided.msh");
 
   char sm[] = "sm.msh";
-  double percentage_of_what_is_left =
-    apply_incremental_displacement(1., all, mixed, -100000000, sm, all);
-  //  ensureMinimumDistorsion (all, threshold);
+  double percentage_of_what_is_left = _applyIncrementalDisplacement
+    (1., all, mixed, -100000000, sm, all);
+
+  // ensureMinimumDistorsion (all, threshold);
+
   return 1.;
 
   double percentage = 0.0;
@@ -775,7 +782,7 @@ double highOrderTools::applySmoothingTo(std::vector<MElement *> &all,
     char NN[256];
     sprintf(NN, "smoothing-%d.msh", ITER++);
     percentage_of_what_is_left =
-      apply_incremental_displacement(1., all, mixed, threshold, NN, all);
+      _applyIncrementalDisplacement(1., all, mixed, threshold, NN, all);
     percentage += (1. - percentage) * percentage_of_what_is_left / 100.;
     Msg::Info("Smoother was able to do %3d percent of the motion",
               (int)(percentage * 100.));
diff --git a/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.h b/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.h
index e631334c52d04be52dd61425e9f7c7d964ed60f1..8ea6f8e6a406dc44555b6e8633f91108b009efdd 100644
--- a/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.h
+++ b/contrib/HighOrderMeshOptimizer/HighOrderMeshElasticAnalogy.h
@@ -44,12 +44,12 @@ class GFace;
 class GRegion;
 
 class highOrderTools {
+private:
   GModel *_gm;
   const int _tag;
   // contains the position of vertices in a straight sided mesh
   std::map<MVertex *, SVector3> _straightSidedLocation;
-  // contains the position of vertices in the best curvilinear mesh
-  // available
+  // contains the position of vertices in the best curvilinear mesh available
   std::map<MVertex *, SVector3> _targetLocation;
   int _dim;
   void _clean()
@@ -57,18 +57,18 @@ class highOrderTools {
     _straightSidedLocation.clear();
     _targetLocation.clear();
   }
-  double smooth_metric_(std::vector<MElement *> &v, GFace *gf,
-                        dofManager<double> &myAssembler,
-                        std::set<MVertex *> &verticesToMove,
-                        elasticityTerm &El);
-  void computeMetricInfo(GFace *gf, MElement *e, fullMatrix<double> &J,
-                         fullMatrix<double> &JT, fullVector<double> &D);
-  double apply_incremental_displacement(double max_incr,
-                                        std::vector<MElement *> &v, bool mixed,
-                                        double thres, char *meshName,
-                                        std::vector<MElement *> &disto);
-  void moveToStraightSidedLocation(MElement *) const;
-  void computeStraightSidedPositions();
+  double _smoothMetric(std::vector<MElement *> &v, GFace *gf,
+                       dofManager<double> &myAssembler,
+                       std::set<MVertex *> &verticesToMove,
+                       elasticityTerm &El);
+  void _computeMetricInfo(GFace *gf, MElement *e, fullMatrix<double> &J,
+                          fullMatrix<double> &JT, fullVector<double> &D);
+  double _applyIncrementalDisplacement(double max_incr,
+                                       std::vector<MElement *> &v, bool mixed,
+                                       double thres, char *meshName,
+                                       std::vector<MElement *> &disto);
+  void _moveToStraightSidedLocation(MElement *) const;
+  void _computeStraightSidedPositions();
 
 public:
   highOrderTools(GModel *gm);
diff --git a/contrib/HighOrderMeshOptimizer/HighOrderMeshOptimizer.cpp b/contrib/HighOrderMeshOptimizer/HighOrderMeshOptimizer.cpp
index 8195726b66d4848b11930cb016db189de4d89df9..a44487a9e2c0a3ac5e517a0bae7215c1b5d63277 100644
--- a/contrib/HighOrderMeshOptimizer/HighOrderMeshOptimizer.cpp
+++ b/contrib/HighOrderMeshOptimizer/HighOrderMeshOptimizer.cpp
@@ -307,7 +307,8 @@ void HighOrderMeshOptimizer(std::vector<GEntity *> &entities,
   bool order1 = false;
   for(std::size_t i = 0; i < entities.size(); i++){
     for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++){
-      if(entities[i]->getMeshElement(j)->getPolynomialOrder() < 2){
+      if(entities[i]->dim() > 0 &&
+         entities[i]->getMeshElement(j)->getPolynomialOrder() < 2){
         order1 = true;
         break;
       }
diff --git a/contrib/MeshOptimizer/MeshOptimizer.cpp b/contrib/MeshOptimizer/MeshOptimizer.cpp
index 5434dbd5e7095ab38d88c7404db1c9c579ddf386..cf1e1fd9c3f8353d72ac6f72f0d775c1d82354dc 100644
--- a/contrib/MeshOptimizer/MeshOptimizer.cpp
+++ b/contrib/MeshOptimizer/MeshOptimizer.cpp
@@ -467,6 +467,10 @@ namespace {
                            bndElts[iPatch], par);
     }
     if(par.nCurses) displayResultTable(nbPatchSuccess, toOptimize.size());
+
+#if defined(_OPENMP)
+//#pragma omp parallel for schedule(dynamic)
+#endif
     for(int iPatch = 0; iPatch < toOptimize.size(); ++iPatch) {
       // Initialize optimization and output if asked
       if(par.nCurses) {
@@ -502,25 +506,37 @@ namespace {
 
       // Evaluate mesh and update it if (partial) success
       opt.updateResults();
-      if(newObjFunctionRange.size() == 0) {
-        newObjFunctionRange = opt.objFunction()->minMax();
-        objFunctionNames = opt.objFunction()->names();
-      }
-      else {
-        for(int i = 0; i < newObjFunctionRange.size(); i++) {
-          newObjFunctionRange[i].first = std::min(
-            newObjFunctionRange[i].first, opt.objFunction()->minMax()[i].first);
-          newObjFunctionRange[i].second =
-            std::max(newObjFunctionRange[i].second,
-                     opt.objFunction()->minMax()[i].second);
+
+#if defined(_OPENMP)
+//#pragma omp critical
+#endif
+      {
+        if(newObjFunctionRange.size() == 0) {
+          newObjFunctionRange = opt.objFunction()->minMax();
+          objFunctionNames = opt.objFunction()->names();
+        }
+        else {
+          for(int i = 0; i < newObjFunctionRange.size(); i++) {
+            newObjFunctionRange[i].first =
+              std::min(newObjFunctionRange[i].first,
+                       opt.objFunction()->minMax()[i].first);
+            newObjFunctionRange[i].second =
+              std::max(newObjFunctionRange[i].second,
+                       opt.objFunction()->minMax()[i].second);
+          }
         }
       }
+
       if(success >= 0) opt.patch.updateGEntityPositions();
 
-      //#pragma omp critical
-      par.success = std::min(par.success, success);
+#if defined(_OPENMP)
+//#pragma omp critical
+#endif
+      {
+        par.success = std::min(par.success, success);
+        nbPatchSuccess[success + 1]++;
+      }
 
-      nbPatchSuccess[success + 1]++;
       if(par.nCurses) {
         displayMinMaxVal(nbPatchSuccess, objFunctionNames, newObjFunctionRange);
         displayResultTable(nbPatchSuccess, toOptimize.size());
@@ -528,6 +544,7 @@ namespace {
                                   iPatch, -1);
       }
     }
+
     while(_patchHistory.size() > 0) {
       delete[] _patchHistory.back();
       _patchHistory.pop_back();