diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
index cb47ed375b2fc155dc6fb9bfbe12fa2338e737aa..449bec78de8b668ec4d7237ca15191a07c259570 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
@@ -810,33 +810,34 @@ void HighOrderMeshOptimizerNew(GModel *gm, OptHomParameters &p)
   par.verbose = 4;
 
   ObjContribScaledNodeDispSq<ObjContribFuncSimple> nodeDistFunc(p.weightFixed, p.weightFree);
-  ObjContribScaledJac<ObjContribFuncBarrierMin> minJacBarFunc(1.);
+  ObjContribScaledJac<ObjContribFuncBarrierMovMin> minJacBarFunc(1.);
   minJacBarFunc.setTarget(p.BARRIER_MIN, 1.);
-  ObjContribScaledJac<ObjContribFuncBarrierMinMax> minMaxJacBarFunc(1.);
+  ObjContribScaledJac<ObjContribFuncBarrierFixMinMovMax> minMaxJacBarFunc(1.);
   minMaxJacBarFunc.setTarget(p.BARRIER_MAX, 1.);
-  par.allContrib.resize(3);
-  par.allContrib[0] = &nodeDistFunc;
-  par.allContrib[1] = &minJacBarFunc;
-  par.allContrib[2] = &minMaxJacBarFunc;
+  ObjContribCADDist<ObjContribFuncSimple> CADDistFunc(p.optCADWeight, p.discrTolerance);
 
   MeshOptParameters::PassParameters minJacPass;
   minJacPass.barrierIterMax = p.optPassMax;
   minJacPass.optIterMax = p.itMax;
-  minJacPass.contribInd.resize(2);
-  minJacPass.contribInd[0] = 0;
-  minJacPass.contribInd[1] = 1;
+  minJacPass.contrib.resize(2);
+  minJacPass.contrib[0] = &nodeDistFunc;
+  minJacPass.contrib[1] = &minJacBarFunc;
   par.pass.push_back(minJacPass);
 
   if (p.BARRIER_MAX > 0.) {
     MeshOptParameters::PassParameters minMaxJacPass;
     minMaxJacPass.barrierIterMax = p.optPassMax;
     minMaxJacPass.optIterMax = p.itMax;
-    minMaxJacPass.contribInd.resize(2);
-    minMaxJacPass.contribInd[0] = 0;
-    minMaxJacPass.contribInd[1] = 2;
+    minMaxJacPass.contrib.resize(2);
+    minMaxJacPass.contrib[0] = &nodeDistFunc;
+    minMaxJacPass.contrib[1] = &minMaxJacBarFunc;
     par.pass.push_back(minMaxJacPass);
   }
 
+  if (p.optCAD) {
+
+  }
+
   MeshOptResults res;
 
   meshOptimizer(gm, par, res);
diff --git a/contrib/MeshOptimizer/MeshOpt.cpp b/contrib/MeshOptimizer/MeshOpt.cpp
index 1ffb8678b17f4a2c86b0a3fd3fb9cce52dead85a..d483b0d8a289b4acc9a599a25dead50d7b36671b 100644
--- a/contrib/MeshOptimizer/MeshOpt.cpp
+++ b/contrib/MeshOptimizer/MeshOpt.cpp
@@ -66,18 +66,23 @@ void printProgressFunc(const alglib::real_1d_array &x, double Obj, void *MOInst)
 
 MeshOpt::MeshOpt(const std::map<MElement*,GEntity*> &element2entity,
                  const std::set<MElement*> &els, std::set<MVertex*> &toFix,
-                 bool fixBndNodes, const std::vector<ObjContrib*> &allContrib) :
-  patch(element2entity, els, toFix, fixBndNodes), _verbose(0),
+                 const MeshOptParameters &par) :
+  patch(element2entity, els, toFix, par.fixBndNodes), _verbose(0),
   _iPass(0), _objFunc(), _iter(0), _intervDisplay(0), _initObj(0)
 {
-  _allContrib.resize(allContrib.size());
-  for (int i = 0; i < allContrib.size(); i++) _allContrib[i] = allContrib[i]->copy();
+  _allObjFunc.resize(par.pass.size());
+  for (int iPass=0; iPass<par.pass.size(); iPass++) {
+    _allObjFunc[iPass].resize(par.pass[iPass].contrib.size());
+    for (int iC=0; iC<par.pass[iPass].contrib.size(); iC++)
+      _allObjFunc[iPass][iC] = par.pass[iPass].contrib[iC]->copy();
+  }
 }
 
 
 MeshOpt::~MeshOpt()
 {
-  for (int i = 0; i < _allContrib.size(); i++) delete _allContrib[i];
+  for (int iPass=0; iPass<_allObjFunc.size(); iPass++)
+    for (int iC=0; iC<_allObjFunc[iPass].size(); iC++) delete _allObjFunc[iPass][iC];
 }
 
 
@@ -85,8 +90,8 @@ void MeshOpt::evalObjGrad(const alglib::real_1d_array &x, double &obj,
                                          alglib::real_1d_array &gradObj)
 {
   patch.updateMesh(x.getcontent());
-  _objFunc.compute(obj, gradObj);
-  if (_objFunc.targetReached()) {
+  _objFunc->compute(obj, gradObj);
+  if (_objFunc->targetReached()) {
     if (_verbose > 2) Msg::Info("Reached target values, setting null gradient");
     obj = 0.;
     for (int i = 0; i < gradObj.length(); i++) gradObj[i] = 0.;
@@ -100,7 +105,7 @@ void MeshOpt::printProgress(const alglib::real_1d_array &x, double Obj)
 
   if ((_verbose > 2) && (_iter % _intervDisplay == 0))
     Msg::Info(("--> Iteration %3d --- OBJ %12.5E (relative decrease = %12.5E)" +
-              _objFunc.minMaxStr()).c_str(), _iter, Obj, Obj/_initObj);
+              _objFunc->minMaxStr()).c_str(), _iter, Obj, Obj/_initObj);
 }
 
 
@@ -120,7 +125,7 @@ void MeshOpt::calcScale(alglib::real_1d_array &scale)
 
 void MeshOpt::updateResults(MeshOptResults &res)
 {
-  _objFunc.updateResults(res);
+  _objFunc->updateResults(res);
 }
 
 
@@ -169,7 +174,7 @@ void MeshOpt::runOptim(alglib::real_1d_array &x,
 }
 
 
-int MeshOpt::optimize(MeshOptParameters &par)
+int MeshOpt::optimize(const MeshOptParameters &par)
 {
   _intervDisplay = par.optDisplay;
   _verbose = par.verbose;
@@ -188,15 +193,15 @@ int MeshOpt::optimize(MeshOptParameters &par)
   for (_iPass=0; _iPass<par.pass.size(); _iPass++) {
 
     // Set objective function Output if required
-    _objFunc = ObjectiveFunction(_allContrib, par.pass[_iPass].contribInd);
+    _objFunc = &_allObjFunc[_iPass];
     if (_verbose > 2) {
-      std::string msgStr = "* Pass %d with contributions: " + _objFunc.contribNames();
+      std::string msgStr = "* Pass %d with contributions: " + _objFunc->contribNames();
       Msg::Info(msgStr.c_str(), _iPass);
     }
 
     // Initialize contributions
-    _objFunc.initialize(&patch);
-    _objFunc.updateParameters();
+    _objFunc->initialize(&patch);
+    _objFunc->updateParameters();
 
     // Calculate initial objective function value and gradient
    _initObj = 0.;
@@ -206,14 +211,14 @@ int MeshOpt::optimize(MeshOptParameters &par)
     evalObjGrad(x, _initObj, gradObj);
 
     // Loop for update of objective function parameters (barrier movement)
-    bool targetReached = _objFunc.targetReached();
+    bool targetReached = _objFunc->targetReached();
     for (int iBar=0; (iBar<par.pass[_iPass].barrierIterMax) && (!targetReached); iBar++) {
       if (_verbose > 2) Msg::Info("--- Optimization run %d", iBar);
-      _objFunc.updateParameters();
+      _objFunc->updateParameters();
       runOptim(x, gradObj, par.pass[_iPass].optIterMax);
-      _objFunc.updateMinMax();
-      targetReached = _objFunc.targetReached();
-      if (_objFunc.stagnated()) {
+      _objFunc->updateMinMax();
+      targetReached = _objFunc->targetReached();
+      if (_objFunc->stagnated()) {
         if (_verbose > 2) Msg::Info("Stagnation detected, stopping optimization");
         break;
       }
@@ -221,7 +226,7 @@ int MeshOpt::optimize(MeshOptParameters &par)
 
     // Check results of pass and output if required
     if (!targetReached) result = 0;
-    std::string failMeasures = _objFunc.failMeasures();
+    std::string failMeasures = _objFunc->failMeasures();
     if (!failMeasures.empty()) {
       result = -1;
       if (_verbose > 2)
@@ -232,7 +237,7 @@ int MeshOpt::optimize(MeshOptParameters &par)
       if (targetReached)
         Msg::Info("Target reached for pass %d", _iPass);
       else {
-        std::string failedTargets = _objFunc.targetsNotReached();
+        std::string failedTargets = _objFunc->targetsNotReached();
         Msg::Warning("Failed to reach target in pass %d for "
                       "contributions %s", _iPass, failedTargets.c_str());
       }
diff --git a/contrib/MeshOptimizer/MeshOpt.h b/contrib/MeshOptimizer/MeshOpt.h
index b3fd41e72cdc99a7e3a4990a1ef1e534aad95ab3..fc3f881f05617e9a8ade7a95b36df9d9ff31a7c5 100644
--- a/contrib/MeshOptimizer/MeshOpt.h
+++ b/contrib/MeshOptimizer/MeshOpt.h
@@ -49,9 +49,9 @@ public:
   Patch patch;
   MeshOpt(const std::map<MElement*,GEntity*> &element2entity,
           const std::set<MElement*> &els, std::set<MVertex*> &toFix,
-          bool fixBndNodes, const std::vector<ObjContrib*> &allContrib);
+          const MeshOptParameters &par);
   ~MeshOpt();
-  int optimize(MeshOptParameters &par);
+  int optimize(const MeshOptParameters &par);
   void updateMesh(const alglib::real_1d_array &x);
   void updateResults(MeshOptResults &res);
   void evalObjGrad(const alglib::real_1d_array &x,
@@ -61,10 +61,10 @@ public:
  private:
   int _verbose;
   int _iPass;
-  std::vector<ObjContrib*> _allContrib;                                             // All contributions to objective function for all passes
-  ObjectiveFunction _objFunc;                                                       // Contributions to objective function for current pass
-  int _iter, _intervDisplay;                                                        // Current iteration, interval of iterations for reporting
-  double _initObj;                                                                  // Values for reporting
+  std::vector<ObjectiveFunction> _allObjFunc;                                        // Contributions to objective function for current pass
+  ObjectiveFunction *_objFunc;                                                       // Contributions to objective function for current pass
+  int _iter, _intervDisplay;                                                         // Current iteration, interval of iterations for reporting
+  double _initObj;                                                                   // Values for reporting
   void calcScale(alglib::real_1d_array &scale);
   void runOptim(alglib::real_1d_array &x,
                 const alglib::real_1d_array &initGradObj, int itMax);
diff --git a/contrib/MeshOptimizer/MeshOptCommon.h b/contrib/MeshOptimizer/MeshOptCommon.h
index c2e2f2f3660942931c685ef72239fe25afff9c5b..4b5ade040fad9eeab1aad385631acce27e7e2f03 100644
--- a/contrib/MeshOptimizer/MeshOptCommon.h
+++ b/contrib/MeshOptimizer/MeshOptCommon.h
@@ -53,7 +53,7 @@ private:
 struct MeshOptParameters {                             // Parameters controlling the strategy
   enum { STRAT_CONNECTED, STRAT_ONEBYONE };
   struct PassParameters {                              // Parameters controlling the optimization procedure in each pass
-    std::vector<int> contribInd;                       // Indices of contributions to objective function
+    std::vector<ObjContrib*> contrib;                  // Indices of contributions to objective function
     int optIterMax;                                    // Max. number of opt. iterations each time the barrier is moved
     int barrierIterMax;                                // Max. number of times the barrier is moved
   };
@@ -75,7 +75,6 @@ struct MeshOptParameters {                             // Parameters controlling
   bool onlyVisible ;                                    // Apply optimization to visible entities ONLY
   bool fixBndNodes;                                     // If points can move on boundaries
   PatchDefParameters *patchDef;
-  std::vector<ObjContrib*> allContrib;                  // All contributions to objective functions for all passes
   std::vector<PassParameters> pass;
   int optDisplay;                                       // Sampling rate in opt. iterations for display
   int verbose;                                          // Level of information displayed and written to disk
diff --git a/contrib/MeshOptimizer/MeshOptObjContribFunc.cpp b/contrib/MeshOptimizer/MeshOptObjContribFunc.cpp
index e585b7dadcf2e581268936eeca7ff6f1559b7b63..c811ef8fd9018316c3f1072be3bfdfd30a04afd8 100644
--- a/contrib/MeshOptimizer/MeshOptObjContribFunc.cpp
+++ b/contrib/MeshOptimizer/MeshOptObjContribFunc.cpp
@@ -22,34 +22,34 @@ void ObjContribFuncBarrier::setTarget(double target, double opt)
 }
 
 
-void ObjContribFuncBarrierMin::updateParameters(double vMin, double vMax)
+void ObjContribFuncBarrierMovMin::updateParameters(double vMin, double vMax)
 {
   _init = vMin;
   _barrier = vMin > 0. ? LOWMARGINMULT*vMin : UPMARGINMULT*vMin;
 }
 
 
-bool ObjContribFuncBarrierMin::stagnated(double vMin, double vMax)
+bool ObjContribFuncBarrierMovMin::stagnated(double vMin, double vMax)
 {
   return (fabs((vMin-_init)/_init) < STAGTHRESHOLD);
 }
 
 
-void ObjContribFuncBarrierMax::updateParameters(double vMin, double vMax)
+void ObjContribFuncBarrierMovMax::updateParameters(double vMin, double vMax)
 {
   _init = vMax;
   _barrier = vMax > 0. ? UPMARGINMULT*vMax : LOWMARGINMULT*vMax;
 }
 
 
-bool ObjContribFuncBarrierMax::stagnated(double vMin, double vMax)
+bool ObjContribFuncBarrierMovMax::stagnated(double vMin, double vMax)
 {
   return (fabs((vMax-_init)/_init) < STAGTHRESHOLD);
 }
 
 
-void ObjContribFuncBarrierMinMax::initialize(double vMin, double vMax)
+void ObjContribFuncBarrierFixMinMovMax::initialize(double vMin, double vMax)
 {
-  ObjContribFuncBarrierMax::initialize(vMin, vMax);
+  ObjContribFuncBarrierMovMax::initialize(vMin, vMax);
   _fixedMinBarrier = vMin > 0. ? LOWMARGINMULT*vMin : UPMARGINMULT*vMin;
 }
diff --git a/contrib/MeshOptimizer/MeshOptObjContribFunc.h b/contrib/MeshOptimizer/MeshOptObjContribFunc.h
index c6bf29f47cd92e31b296e5cb71a4b48710445183..fc2ee71de6abc9ab85feafcf807f8b3180d2c800 100644
--- a/contrib/MeshOptimizer/MeshOptObjContribFunc.h
+++ b/contrib/MeshOptimizer/MeshOptObjContribFunc.h
@@ -35,10 +35,10 @@ protected:
 };
 
 
-class ObjContribFuncBarrierMin : public ObjContribFuncBarrier
+class ObjContribFuncBarrierMovMin : public ObjContribFuncBarrier
 {
 protected:
-  std::string getNamePrefix() { return "BarrierMin"; }
+  std::string getNamePrefix() { return "BarrierMovMin"; }
   void initialize(double vMin, double vMax) {}
   void updateParameters(double vMin, double vMax);
   bool targetReached(double vMin, double vMax) { return (vMin >= _target); }
@@ -48,10 +48,10 @@ protected:
 };
 
 
-class ObjContribFuncBarrierMax : public ObjContribFuncBarrier
+class ObjContribFuncBarrierMovMax : public ObjContribFuncBarrier
 {
 protected:
-  std::string getNamePrefix() { return "BarrierMax"; }
+  std::string getNamePrefix() { return "BarrierMovMax"; }
   void initialize(double vMin, double vMax) {}
   void updateParameters(double vMin, double vMax);
   bool targetReached(double vMin, double vMax) { return (vMax <= _target); }
@@ -61,10 +61,10 @@ protected:
 };
 
 
-class ObjContribFuncBarrierMinMax : public ObjContribFuncBarrierMax
+class ObjContribFuncBarrierFixMinMovMax : public ObjContribFuncBarrierMovMax
 {
 protected:
-  std::string getNamePrefix() { return "BarrierMinMax"; }
+  std::string getNamePrefix() { return "BarrierFixMinMovMax"; }
   void initialize(double vMin, double vMax);
   inline double compute(double v);
   inline double computeDiff(double v);
@@ -88,35 +88,35 @@ inline double ObjContribFuncBarrier::diffLogBarrier(double v, double barrier, do
 }
 
 
-inline double ObjContribFuncBarrierMin::compute(double v)
+inline double ObjContribFuncBarrierMovMin::compute(double v)
 {
   if (v > _barrier) return logBarrier(v, _barrier, _opt);
   else return 1e300;
 }
 
 
-inline double ObjContribFuncBarrierMin::computeDiff(double v)
+inline double ObjContribFuncBarrierMovMin::computeDiff(double v)
 {
   if (v > _barrier) return diffLogBarrier(v, _barrier, _opt);
   else return -1e300;
 }
 
 
-inline double ObjContribFuncBarrierMax::compute(double v)
+inline double ObjContribFuncBarrierMovMax::compute(double v)
 {
   if (v < _barrier) return logBarrier(v, _barrier, _opt);
   else return 1e300;
 }
 
 
-inline double ObjContribFuncBarrierMax::computeDiff(double v)
+inline double ObjContribFuncBarrierMovMax::computeDiff(double v)
 {
   if (v < _barrier) return diffLogBarrier(v, _barrier, _opt);
   else return 1e300;
 }
 
 
-inline double ObjContribFuncBarrierMinMax::compute(double v)
+inline double ObjContribFuncBarrierFixMinMovMax::compute(double v)
 {
   double obj;
   if (v < _barrier) obj = logBarrier(v, _barrier, _opt);
@@ -129,7 +129,7 @@ inline double ObjContribFuncBarrierMinMax::compute(double v)
 }
 
 
-inline double ObjContribFuncBarrierMinMax::computeDiff(double v)
+inline double ObjContribFuncBarrierFixMinMovMax::computeDiff(double v)
 {
   double dobj;
   if (v < _barrier) dobj = diffLogBarrier(v, _barrier, _opt);
diff --git a/contrib/MeshOptimizer/MeshOptObjectiveFunction.cpp b/contrib/MeshOptimizer/MeshOptObjectiveFunction.cpp
index 3b03d3010c3900d6d904b31b1073def2d1a95a98..3fac82abecf625c5614ae8b3467c70941efdeb4e 100644
--- a/contrib/MeshOptimizer/MeshOptObjectiveFunction.cpp
+++ b/contrib/MeshOptimizer/MeshOptObjectiveFunction.cpp
@@ -5,14 +5,6 @@
 #include "MeshOptObjectiveFunction.h"
 
 
-ObjectiveFunction::ObjectiveFunction(const std::vector<ObjContrib*> &allContrib,
-                                              const std::vector<int> &contribInd)
-{
-  resize(contribInd.size());
-  for (int i=0; i<contribInd.size(); i++) operator[](i) = allContrib[contribInd[i]];
-}
-
-
 void ObjectiveFunction::initialize(Patch *mesh)
 {
    for (std::vector<ObjContrib*>::iterator it=begin(); it!=end(); it++)
diff --git a/contrib/MeshOptimizer/MeshOptObjectiveFunction.h b/contrib/MeshOptimizer/MeshOptObjectiveFunction.h
index 116c7dc32f413d75685881a6b0024c83009c625f..08e5c95ab1a6ed460f78aabf932649c4baf4a060 100644
--- a/contrib/MeshOptimizer/MeshOptObjectiveFunction.h
+++ b/contrib/MeshOptimizer/MeshOptObjectiveFunction.h
@@ -12,12 +12,9 @@ class MeshOptResults;
 class Patch;
 
 
-class ObjectiveFunction : protected std::vector<ObjContrib*>    // Contributions to objective function in each pass
+class ObjectiveFunction : public std::vector<ObjContrib*>    // Contributions to objective function in each pass
 {
 public:
-  ObjectiveFunction() {}
-  ObjectiveFunction(const std::vector<ObjContrib*> &model,
-                        const std::vector<int> &contribInd);
   void initialize(Patch *mesh);
   std::string contribNames();
   std::string minMaxStr();
diff --git a/contrib/MeshOptimizer/MeshOptimizer.cpp b/contrib/MeshOptimizer/MeshOptimizer.cpp
index 4aa3958d6cfc3c16f184c745f737e2f9da4716ae..240a6351e1aa3271ce241dca71abf165e16e9afa 100644
--- a/contrib/MeshOptimizer/MeshOptimizer.cpp
+++ b/contrib/MeshOptimizer/MeshOptimizer.cpp
@@ -266,8 +266,8 @@ static void optimizeConnectedPatches
     if (par.verbose > 1)
       Msg::Info("Optimizing patch %i/%i composed of %i elements", iPatch,
                       toOptimize.size()-1, toOptimize[iPatch].first.size());
-    MeshOpt opt(element2entity, toOptimize[iPatch].first, toOptimize[iPatch].second,
-                                                      par.fixBndNodes, par.allContrib);
+    MeshOpt opt(element2entity, toOptimize[iPatch].first,
+                            toOptimize[iPatch].second, par);
     if (par.verbose > 3) {
       std::ostringstream ossI1;
       ossI1 << "initial_patch-" << iPatch << ".msh";
@@ -356,7 +356,7 @@ static void optimizeOneByOne
       if (par.verbose > 1)
         Msg::Info("Optimizing patch %i (max. %i remaining) composed of %4d elements",
                                             iBadEl, badElts.size(), toOptimize.size());
-      MeshOpt opt(element2entity, toOptimize, toFix, par.fixBndNodes, par.allContrib);
+      MeshOpt opt(element2entity, toOptimize, toFix, par);
       if (par.verbose > 3) {
         std::ostringstream ossI1;
         ossI1 << "initial_patch-" << iBadEl << ".msh";