diff --git a/Numeric/CMakeLists.txt b/Numeric/CMakeLists.txt
index 97a3c6fec00afe0e01d5242fcbc40086a0829563..e4449b7522e9d0458c1fcc04bdd4eee30d9873e0 100644
--- a/Numeric/CMakeLists.txt
+++ b/Numeric/CMakeLists.txt
@@ -37,8 +37,8 @@ set(SRC
  decasteljau.cpp
   mathEvaluator.cpp
   Iso.cpp
-#  approximationError.cpp
-#  ConjugateGradients.cpp
+  approximationError.cpp
+  ConjugateGradients.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h) 
diff --git a/Numeric/ConjugateGradients.cpp b/Numeric/ConjugateGradients.cpp
index 9720f14e3e9eea6ff15aab0395b86c81d88b9324..666267c31e9696693be81f02fe3883654d4a8013 100644
--- a/Numeric/ConjugateGradients.cpp
+++ b/Numeric/ConjugateGradients.cpp
@@ -113,7 +113,7 @@ double GradientDescent(void (*func)(std::vector<double> &x,
   std::vector<double> dir(N);
   double f;
 
-  printf("entering gradient descent (%d unknowns)...\n",N);
+//  printf("entering gradient descent (%d unknowns)...\n",N);
 
   for (int iter = 0; iter < MAXIT; iter++){
     // compute gradient of func
diff --git a/contrib/HighOrderMeshOptimizer/OptHOM.cpp b/contrib/HighOrderMeshOptimizer/OptHOM.cpp
index 0684d5fca1e4f7ac3686e79a2e8179f57a6fa735..eeecc02386cec7c00f32d8b1084fa04a23d1085b 100644
--- a/contrib/HighOrderMeshOptimizer/OptHOM.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHOM.cpp
@@ -36,7 +36,7 @@ static int NEVAL = 0;
 #include "OptHomRun.h"
 #include "GmshMessage.h"
 #include "GmshConfig.h"
-//#include "ConjugateGradients.h"
+#include "ConjugateGradients.h"
 #include "MLine.h"
 #include "MTriangle.h"
 #include "GModel.h"
@@ -142,21 +142,21 @@ bool OptHOM::addJacObjGrad(double &Obj, std::vector<double> &gradObj)
 }
 
 
-//bool OptHOM::addApproximationErrorObjGrad(double factor, double &Obj, alglib::real_1d_array &gradObj, simpleFunction<double>& fct)
-//{
-//  std::vector<double> gradF;
-//  for (int iEl = 0; iEl < mesh.nEl(); iEl++) {
-//    double f;
-//    mesh.approximationErrorAndGradients(iEl, f, gradF, 1.e-6, fct);
-//    Obj += f * factor;
-//    for (size_t i = 0; i < mesh.nPCEl(iEl); ++i){
-//      gradObj[mesh.indPCEl(iEl, i)] += gradF[i] * factor;
-//    }
-//  }
-//  //  printf("DIST = %12.5E\n",DISTANCE);
-//  return true;
-//
-//}
+bool OptHOM::addApproximationErrorObjGrad(double factor, double &Obj, alglib::real_1d_array &gradObj, simpleFunction<double>& fct)
+{
+  std::vector<double> gradF;
+  for (int iEl = 0; iEl < mesh.nEl(); iEl++) {
+    double f;
+    mesh.approximationErrorAndGradients(iEl, f, gradF, 1.e-6, fct);
+    Obj += f * factor;
+    for (size_t i = 0; i < mesh.nPCEl(iEl); ++i){
+      gradObj[mesh.indPCEl(iEl, i)] += gradF[i] * factor;
+    }
+  }
+  //  printf("DIST = %12.5E\n",DISTANCE);
+  return true;
+
+}
 
 static void computeGradSFAtNodes (MElement *e, std::vector<std::vector<SVector3> > &gsf)
 {
@@ -804,12 +804,12 @@ void OptHOM::calcScale(alglib::real_1d_array &scale)
   }
 }
 
-//void OptHOM::OptimPass(std::vector<double> &x, int itMax)
-//{
-//  Msg::Info("--- In-house Optimization pass with initial jac. range (%g, %g), jacBar = %g",
-//            minJac, maxJac, jacBar);
-//  GradientDescent (evalObjGradFunc, x, this);
-//}
+void OptHOM::OptimPass(std::vector<double> &x, int itMax)
+{
+  Msg::Info("--- In-house Optimization pass with initial jac. range (%g, %g), jacBar = %g",
+            minJac, maxJac, jacBar);
+  GradientDescent (evalObjGradFunc, x, this);
+}
  
 
 void OptHOM::OptimPass(alglib::real_1d_array &x, int itMax)
@@ -981,100 +981,100 @@ int OptHOM::optimize(double weightFixed, double weightFree, double weightCAD, do
 }
 
 
-//int OptHOM::optimize_inhouse(double weightFixed, double weightFree, double weightCAD, double b_min,
-//			     double b_max, bool optimizeMetricMin, int pInt,
-//			     int itMax, int optPassMax, int optCAD, double distanceMax, double tolerance)
-//{
-//  barrier_min = b_min;
-//  barrier_max = b_max;
-//  distance_max = distanceMax;
-//  progressInterv = pInt;
-////  powM = 4;
-////  powP = 3;
-//
-//  _optimizeMetricMin = optimizeMetricMin;
-//  _optimizeCAD = optCAD;
-//  // Set weights & length scale for non-dimensionalization
-//  lambda = weightFixed;
-//  lambda2 = weightFree;
-//  lambda3 = weightCAD;
-//  geomTol = tolerance;
-//  std::vector<double> dSq(mesh.nEl());
-//  mesh.distSqToStraight(dSq);
-//  const double maxDSq = *max_element(dSq.begin(),dSq.end());
-//  if (maxDSq < 1.e-10) {                                        // Length scale for non-dim. distance
-//    std::vector<double> sSq(mesh.nEl());
-//    mesh.elSizeSq(sSq);
-//    const double maxSSq = *max_element(sSq.begin(),sSq.end());
-//    invLengthScaleSq = 1./maxSSq;
-//  }
-//  else invLengthScaleSq = 1./maxDSq;
-//
-//  // Set initial guess
-//  std::vector<double> x(mesh.nPC());
-//  mesh.getUvw(x.data());
-//
-//  // Calculate initial performance
-//  recalcJacDist();
-//  initMaxDist = maxDist;
-//  initAvgDist = avgDist;
-//
-//  const double jacBarStart = (minJac > 0.) ? 0.9*minJac : 1.1*minJac;
-//  jacBar = jacBarStart;
-//
-//  _optimizeBarrierMax = false;
-//  // Calculate initial objective function value and gradient
-//  initObj = 0.;
-//  std::vector<double>gradObj(mesh.nPC());
-//  for (int i = 0; i < mesh.nPC(); i++) gradObj[i] = 0.;
-//  evalObjGrad(x, initObj, true, gradObj);
-//
-//  Msg::Info("Start optimizing %d elements (%d vertices, %d free vertices, %d variables) "
-//            "with min barrier %g and max. barrier %g", mesh.nEl(), mesh.nVert(),
-//            mesh.nFV(), mesh.nPC(), barrier_min, barrier_max);
-//
-//  int ITER = 0;
-//  bool minJacOK = true;
-//
-//  while (minJac < barrier_min || (maxDistCAD > distance_max && _optimizeCAD)) {
-//    const double startMinJac = minJac;
-//    OptimPass(x, itMax);
-//    recalcJacDist();
-//    jacBar = (minJac > 0.) ? 0.9*minJac : 1.1*minJac;
-//    if (_optimizeCAD)   jacBar = std::min(jacBar,barrier_min);
-//    if (ITER ++ > optPassMax) {
-//      minJacOK = (minJac > barrier_min && (maxDistCAD < distance_max || !_optimizeCAD));
-//      break;
-//    }
-//    if (fabs((minJac-startMinJac)/startMinJac) < 0.01) {
-//      Msg::Info("Stagnation in minJac detected, stopping optimization");
-//      minJacOK = false;
-//      break;
-//    }
-//  }
-//
-//  ITER = 0;
-//  if (minJacOK && (!_optimizeMetricMin)) {
-//    _optimizeBarrierMax = true;
-//    jacBar =  1.1 * maxJac;
-//    while (maxJac > barrier_max ) {
-//      const double startMaxJac = maxJac;
-//      OptimPass(x, itMax);
-//      recalcJacDist();
-//      jacBar =  1.1 * maxJac;
-//      if (ITER ++ > optPassMax) break;
-//      if (fabs((maxJac-startMaxJac)/startMaxJac) < 0.01) {
-//        Msg::Info("Stagnation in maxJac detected, stopping optimization");
-//        break;
-//      }
-//    }
-//  }
-//
-//  Msg::Info("Optimization done Range (%g,%g)", minJac, maxJac);
-//
-//  if (minJac > barrier_min && maxJac < barrier_max) return 1;
-//  if (minJac > 0.0) return 0;
-//  return -1;
-//}
+int OptHOM::optimize_inhouse(double weightFixed, double weightFree, double weightCAD, double b_min,
+			     double b_max, bool optimizeMetricMin, int pInt,
+			     int itMax, int optPassMax, int optCAD, double distanceMax, double tolerance)
+{
+  barrier_min = b_min;
+  barrier_max = b_max;
+  distance_max = distanceMax;
+  progressInterv = pInt;
+//  powM = 4;
+//  powP = 3;
+
+  _optimizeMetricMin = optimizeMetricMin;
+  _optimizeCAD = optCAD;
+  // Set weights & length scale for non-dimensionalization
+  lambda = weightFixed;
+  lambda2 = weightFree;
+  lambda3 = weightCAD;
+  geomTol = tolerance;
+  std::vector<double> dSq(mesh.nEl());
+  mesh.distSqToStraight(dSq);
+  const double maxDSq = *max_element(dSq.begin(),dSq.end());
+  if (maxDSq < 1.e-10) {                                        // Length scale for non-dim. distance
+    std::vector<double> sSq(mesh.nEl());
+    mesh.elSizeSq(sSq);
+    const double maxSSq = *max_element(sSq.begin(),sSq.end());
+    invLengthScaleSq = 1./maxSSq;
+  }
+  else invLengthScaleSq = 1./maxDSq;
+
+  // Set initial guess
+  std::vector<double> x(mesh.nPC());
+  mesh.getUvw(x.data());
+
+  // Calculate initial performance
+  recalcJacDist();
+  initMaxDist = maxDist;
+  initAvgDist = avgDist;
+
+  const double jacBarStart = (minJac > 0.) ? 0.9*minJac : 1.1*minJac;
+  jacBar = jacBarStart;
+
+  _optimizeBarrierMax = false;
+  // Calculate initial objective function value and gradient
+  initObj = 0.;
+  std::vector<double>gradObj(mesh.nPC());
+  for (int i = 0; i < mesh.nPC(); i++) gradObj[i] = 0.;
+  evalObjGrad(x, initObj, true, gradObj);
+
+  Msg::Info("Start optimizing %d elements (%d vertices, %d free vertices, %d variables) "
+            "with min barrier %g and max. barrier %g", mesh.nEl(), mesh.nVert(),
+            mesh.nFV(), mesh.nPC(), barrier_min, barrier_max);
+
+  int ITER = 0;
+  bool minJacOK = true;
+
+  while (minJac < barrier_min || (maxDistCAD > distance_max && _optimizeCAD)) {
+    const double startMinJac = minJac;
+    OptimPass(x, itMax);
+    recalcJacDist();
+    jacBar = (minJac > 0.) ? 0.9*minJac : 1.1*minJac;
+    if (_optimizeCAD)   jacBar = std::min(jacBar,barrier_min);
+    if (ITER ++ > optPassMax) {
+      minJacOK = (minJac > barrier_min && (maxDistCAD < distance_max || !_optimizeCAD));
+      break;
+    }
+    if (fabs((minJac-startMinJac)/startMinJac) < 0.01) {
+      Msg::Info("Stagnation in minJac detected, stopping optimization");
+      minJacOK = false;
+      break;
+    }
+  }
+
+  ITER = 0;
+  if (minJacOK && (!_optimizeMetricMin)) {
+    _optimizeBarrierMax = true;
+    jacBar =  1.1 * maxJac;
+    while (maxJac > barrier_max ) {
+      const double startMaxJac = maxJac;
+      OptimPass(x, itMax);
+      recalcJacDist();
+      jacBar =  1.1 * maxJac;
+      if (ITER ++ > optPassMax) break;
+      if (fabs((maxJac-startMaxJac)/startMaxJac) < 0.01) {
+        Msg::Info("Stagnation in maxJac detected, stopping optimization");
+        break;
+      }
+    }
+  }
+
+  Msg::Info("Optimization done Range (%g,%g)", minJac, maxJac);
+
+  if (minJac > barrier_min && maxJac < barrier_max) return 1;
+  if (minJac > 0.0) return 0;
+  return -1;
+}
 
 #endif
diff --git a/contrib/HighOrderMeshOptimizer/OptHOM.h b/contrib/HighOrderMeshOptimizer/OptHOM.h
index 4cb3fc7bf91489a858cdd601e37361a03df551c0..3eaf09d89c35f325f15b60934dc4c530dcd282a5 100644
--- a/contrib/HighOrderMeshOptimizer/OptHOM.h
+++ b/contrib/HighOrderMeshOptimizer/OptHOM.h
@@ -53,9 +53,9 @@ public:
   // mesh is invalid : some jacobians cannot be made positive
   int optimize(double lambda, double lambda2, double lambda3, double barrier_min, double barrier_max,
                bool optimizeMetricMin, int pInt, int itMax, int optPassMax, int optimizeCAD, double optCADDistMax, double tolerance);
-//  int optimize_inhouse(double weightFixed, double weightFree, double weightCAD, double b_min,
-//		       double b_max, bool optimizeMetricMin, int pInt,
-//		       int itMax, int optPassMax, int optCAD, double distanceMax, double tolerance);
+  int optimize_inhouse(double weightFixed, double weightFree, double weightCAD, double b_min,
+		       double b_max, bool optimizeMetricMin, int pInt,
+		       int itMax, int optPassMax, int optCAD, double distanceMax, double tolerance);
   void recalcJacDist();
   inline void getJacDist(double &minJ, double &maxJ, double &maxD, double &avgD);
   void updateMesh(const alglib::real_1d_array &x);
@@ -77,7 +77,7 @@ public:
                             // true : fixed barrier min + moving barrier max
   bool _optimizeCAD; // false : do not minimize the distance between mesh and CAD
                      // true : minimize the distance between mesh and CAD
-//  bool addApproximationErrorObjGrad(double Fact, double &Obj, alglib::real_1d_array &gradObj, simpleFunction<double>& fct);
+  bool addApproximationErrorObjGrad(double Fact, double &Obj, alglib::real_1d_array &gradObj, simpleFunction<double>& fct);
   bool addJacObjGrad(double &Obj, alglib::real_1d_array &gradObj);
   bool addJacObjGrad(double &Obj, std::vector<double> &);
   bool addBndObjGrad (double Fact, double &Obj, alglib::real_1d_array &gradObj);
@@ -90,7 +90,7 @@ public:
                       alglib::real_1d_array &gradObj);
   void calcScale(alglib::real_1d_array &scale);
   void OptimPass(alglib::real_1d_array &x, int itMax);
-//  void OptimPass(std::vector<double> &x, int itMax);
+  void OptimPass(std::vector<double> &x, int itMax);
 };
 
 void OptHOM::getJacDist(double &minJ, double &maxJ, double &maxD, double &avgD)
diff --git a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp
index ef905a18a55e48e6d20c46136b2d6d2747f68e6f..dbea55ed27232527a68af49daad108a5ab78548c 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp
@@ -335,68 +335,68 @@ void Mesh::metricMinAndGradients(int iEl, std::vector<double> &lambda,
   }
 }
 
-//void Mesh::approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps,
-//					  simpleFunction<double> &fct)
-//{
-//  std::vector<SPoint3> _xyz_temp;
-//  for (int iV = 0; iV < nVert(); iV++){
-//    _xyz_temp.push_back(SPoint3( _vert[iV]->x(), _vert[iV]->y(), _vert[iV]->z()));
-//    _vert[iV]->setXYZ(_xyz[iV].x(),_xyz[iV].y(),_xyz[iV].z());
-//  }
-//
-//  MElement *element = _el[iEl];
-//
-//  f = approximationError (fct, element);
-//  // FIME
-//  //  if (iEl < 1)printf("approx error elem %d = %g\n",iEl,f);
-//  int currentId = 0;
-//  // compute the size of the gradient
-//  // depends on how many dofs exist per vertex (0,1,2 or 3)
-//  for (size_t i = 0; i < element->getNumVertices(); ++i) {
-//    if (_el2FV[iEl][i] >= 0) {// some free coordinates
-//      currentId += _nPCFV[_el2FV[iEl][i]];
-//    }
-//  }
-//  gradF.clear();
-//  gradF.resize(currentId, 0.);
-//  currentId = 0;
-//  for (size_t i = 0; i < element->getNumVertices(); ++i) {
-//    if (_el2FV[iEl][i] >= 0) {// some free coordinates
-//      MVertex *v =  element->getVertex(i);
-//      // vertex classified on a model edge
-//      if (_nPCFV[_el2FV[iEl][i]] == 1){
-//	double t = _uvw[_el2FV[iEl][i]].x();
-//	GEdge *ge = (GEdge*)v->onWhat();
-//	SPoint3 p (v->x(),v->y(),v->z());
-//	GPoint d = ge->point(t+eps);
-//	v->setXYZ(d.x(),d.y(),d.z());
-//	double f_d = approximationError (fct, element);
-//	gradF[currentId++] = (f_d-f)/eps;
-//	if (iEl < 1)printf("df = %g\n",(f_d-f)/eps);
-//	v->setXYZ(p.x(),p.y(),p.z());
-//      }
-//      else if (_nPCFV[_el2FV[iEl][i]] == 2){
-//	double uu = _uvw[_el2FV[iEl][i]].x();
-//	double vv = _uvw[_el2FV[iEl][i]].y();
-//	GFace *gf = (GFace*)v->onWhat();
-//	SPoint3 p (v->x(),v->y(),v->z());
-//	GPoint  d = gf->point(uu+eps,vv);
-//	v->setXYZ(d.x(),d.y(),d.z());
-//	double f_u = approximationError (fct, element);
-//	gradF[currentId++] = (f_u-f)/eps;
-//	d = gf->point(uu,vv+eps);
-//	v->setXYZ(d.x(),d.y(),d.z());
-//	double f_v = approximationError (fct, element);
-//	gradF[currentId++] = (f_v-f)/eps;
-//	v->setXYZ(p.x(),p.y(),p.z());
-//	//	if (iEl < 1)printf("df = %g %g\n",(f_u-f)/eps,(f_v-f)/eps);
-//      }
-//    }
-//  }
-//  for (int iV = 0; iV < nVert(); iV++)
-//    _vert[iV]->setXYZ(_xyz_temp[iV].x(),_xyz_temp[iV].y(),_xyz_temp[iV].z());
-//
-//}
+void Mesh::approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps,
+					  simpleFunction<double> &fct)
+{
+  std::vector<SPoint3> _xyz_temp;
+  for (int iV = 0; iV < nVert(); iV++){
+    _xyz_temp.push_back(SPoint3( _vert[iV]->x(), _vert[iV]->y(), _vert[iV]->z()));
+    _vert[iV]->setXYZ(_xyz[iV].x(),_xyz[iV].y(),_xyz[iV].z());
+  }
+
+  MElement *element = _el[iEl];
+
+  f = approximationError (fct, element);
+  // FIME
+  //  if (iEl < 1)printf("approx error elem %d = %g\n",iEl,f);
+  int currentId = 0;
+  // compute the size of the gradient
+  // depends on how many dofs exist per vertex (0,1,2 or 3)
+  for (size_t i = 0; i < element->getNumVertices(); ++i) {
+    if (_el2FV[iEl][i] >= 0) {// some free coordinates
+      currentId += _nPCFV[_el2FV[iEl][i]];
+    }
+  }
+  gradF.clear();
+  gradF.resize(currentId, 0.);
+  currentId = 0;
+  for (size_t i = 0; i < element->getNumVertices(); ++i) {
+    if (_el2FV[iEl][i] >= 0) {// some free coordinates
+      MVertex *v =  element->getVertex(i);
+      // vertex classified on a model edge
+      if (_nPCFV[_el2FV[iEl][i]] == 1){
+	double t = _uvw[_el2FV[iEl][i]].x();
+	GEdge *ge = (GEdge*)v->onWhat();
+	SPoint3 p (v->x(),v->y(),v->z());
+	GPoint d = ge->point(t+eps);
+	v->setXYZ(d.x(),d.y(),d.z());
+	double f_d = approximationError (fct, element);
+	gradF[currentId++] = (f_d-f)/eps;
+	if (iEl < 1)printf("df = %g\n",(f_d-f)/eps);
+	v->setXYZ(p.x(),p.y(),p.z());
+      }
+      else if (_nPCFV[_el2FV[iEl][i]] == 2){
+	double uu = _uvw[_el2FV[iEl][i]].x();
+	double vv = _uvw[_el2FV[iEl][i]].y();
+	GFace *gf = (GFace*)v->onWhat();
+	SPoint3 p (v->x(),v->y(),v->z());
+	GPoint  d = gf->point(uu+eps,vv);
+	v->setXYZ(d.x(),d.y(),d.z());
+	double f_u = approximationError (fct, element);
+	gradF[currentId++] = (f_u-f)/eps;
+	d = gf->point(uu,vv+eps);
+	v->setXYZ(d.x(),d.y(),d.z());
+	double f_v = approximationError (fct, element);
+	gradF[currentId++] = (f_v-f)/eps;
+	v->setXYZ(p.x(),p.y(),p.z());
+	//	if (iEl < 1)printf("df = %g %g\n",(f_u-f)/eps,(f_v-f)/eps);
+      }
+    }
+  }
+  for (int iV = 0; iV < nVert(); iV++)
+    _vert[iV]->setXYZ(_xyz_temp[iV].x(),_xyz_temp[iV].y(),_xyz_temp[iV].z());
+
+}
 
 
 bool Mesh::bndDistAndGradients(int iEl, double &f , std::vector<double> &gradF, double eps)
diff --git a/contrib/HighOrderMeshOptimizer/OptHomMesh.h b/contrib/HighOrderMeshOptimizer/OptHomMesh.h
index 894cde318160544e2ede08e1cb3ecd4674d0bc42..696a19b0c286562d3db711d8cf5d0bf9f473b292 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomMesh.h
+++ b/contrib/HighOrderMeshOptimizer/OptHomMesh.h
@@ -38,7 +38,7 @@
 #include "ParamCoord.h"
 #include "polynomialBasis.h"
 #include "simpleFunction.h"
-//#include "approximationError.h"
+#include "approximationError.h"
 
 class Mesh
 {
@@ -58,7 +58,7 @@ public:
   inline const int &nBezEl(int iEl) { return _nBezEl[iEl]; }
   int getFreeVertexStartIndex(MVertex* vert);
 
-//  void approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps, simpleFunction<double> &fct);
+  void approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps, simpleFunction<double> &fct);
   void metricMinAndGradients(int iEl, std::vector<double> &sJ, std::vector<double> &gSJ);
   void scaledJacAndGradients(int iEl, std::vector<double> &sJ, std::vector<double> &gSJ);
   bool bndDistAndGradients(int iEl, double &f , std::vector<double> &gradF, double eps);
@@ -142,10 +142,10 @@ private:
     return indJB3DBase(_nNodEl[iEl],l,i,j,m);
   }
 public: 
-//  double approximationErr(int iEl, simpleFunction<double> &f)
-//  {
-//    return approximationError (f, _el[iEl]);
-//  }
+  double approximationErr(int iEl, simpleFunction<double> &f)
+  {
+    return approximationError (f, _el[iEl]);
+  }
 };