diff --git a/contrib/HighOrderMeshOptimizer/OptHOM.cpp b/contrib/HighOrderMeshOptimizer/OptHOM.cpp
index b5517ddf80d067b3b3b8293596ea9187d1935a28..3b3efd9d5820cfb01a252f759898991f1190605d 100644
--- a/contrib/HighOrderMeshOptimizer/OptHOM.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHOM.cpp
@@ -16,8 +16,8 @@
 
 
 // Constructor
-OptHOM::OptHOM(GEntity *ge, std::set<MVertex*> & toFix, int method) :
-       mesh(ge, toFix, method)
+OptHOM::OptHOM(GEntity *ge, const std::set<MElement*> &els, std::set<MVertex*> & toFix, int method) :
+       mesh(ge, els, toFix, method)
 {
 };
 
diff --git a/contrib/HighOrderMeshOptimizer/OptHOM.h b/contrib/HighOrderMeshOptimizer/OptHOM.h
index 093411aabb1624fe9c6e63454cc56b3cda36d10a..2678c196da4088d32e7bf9e170b16e4dd9e07a90 100644
--- a/contrib/HighOrderMeshOptimizer/OptHOM.h
+++ b/contrib/HighOrderMeshOptimizer/OptHOM.h
@@ -22,7 +22,7 @@ public:
 
   Mesh mesh;
 
-  OptHOM(GEntity *gf, std::set<MVertex*> & toFix, int method);
+  OptHOM(GEntity *gf, const std::set<MElement*> &els, std::set<MVertex*> & toFix, int method);
   // returns 1 if the mesh has been optimized with success i.e. all jacobians are in the range
   // returns 0 if the mesh is valid (all jacobians positive, JMIN > 0) but JMIN < barrier_min || JMAX > barrier_max
   // returns -1 if the mesh is invalid : some jacobians cannot be made positive
diff --git a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp
index 6f1f46a5b70748101a584d65c4c044e9cf64012a..1525a0a9510b91d04a0878182781b2cd831b6fe8 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp
@@ -66,7 +66,7 @@ std::vector<double> Mesh::computeJB(const polynomialBasis *lagrange, const bezie
 
 
 
-Mesh::Mesh(GEntity *ge, std::set<MVertex*> &toFix, int method) :
+Mesh::Mesh(GEntity *ge, const std::set<MElement*> &els, std::set<MVertex*> &toFix, int method) :
     _ge(ge)
 {
   _dim = _ge->dim();
@@ -93,15 +93,17 @@ Mesh::Mesh(GEntity *ge, std::set<MVertex*> &toFix, int method) :
   else Msg::Debug("METHOD: Fixing vertices on geometric points and \"toFix\" boundary");
 
   // Initialize elements, vertices, free vertices and element->vertices connectivity
+  const int nElements = els.size();
   _nPC = 0;
-  _el.resize(_ge->getNumMeshElements());
-  _el2FV.resize(_ge->getNumMeshElements());
-  _el2V.resize(_ge->getNumMeshElements());
-  _nBezEl.resize(_ge->getNumMeshElements());
-  _nNodEl.resize(_ge->getNumMeshElements());
-  _indPCEl.resize(_ge->getNumMeshElements());
-  for (int iEl = 0; iEl < nEl(); iEl++) {
-    MElement *el = _ge->getMeshElement(iEl);
+  _el.resize(nElements);
+  _el2FV.resize(nElements);
+  _el2V.resize(nElements);
+  _nBezEl.resize(nElements);
+  _nNodEl.resize(nElements);
+  _indPCEl.resize(nElements);
+  int iEl = 0;
+  for(std::set<MElement*>::const_iterator it = els.begin(); it != els.end(); ++it, ++iEl) {
+    MElement *el = *it;
     _el[iEl] = el;
     const polynomialBasis *lagrange = el->getFunctionSpace();
     const bezierBasis *bezier = JacobianBasis::find(lagrange->type)->bezier;
@@ -478,7 +480,7 @@ void Mesh::writeMSH(const char *filename)
   for (int iEl = 0; iEl < nEl(); iEl++) {
 //    MElement *MEl = _el[iEl];
     fprintf(f, "%d %d 2 0 %d", iEl+1, _el[iEl]->getTypeForMSH(), _ge->tag());
-    for (int iVEl = 0; iVEl < _el2V[iEl].size(); iVEl++) fprintf(f, " %d", _el2V[iEl][iVEl] + 1);
+    for (size_t iVEl = 0; iVEl < _el2V[iEl].size(); iVEl++) fprintf(f, " %d", _el2V[iEl][iVEl] + 1);
     fprintf(f, "\n");
   }
   fprintf(f, "$EndElements\n");
diff --git a/contrib/HighOrderMeshOptimizer/OptHomMesh.h b/contrib/HighOrderMeshOptimizer/OptHomMesh.h
index 2e2741fbb413a9002338c3170577b4339357fe5b..dcdfd6fc4814c7c8ad4b82057c993a2d1e665e93 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomMesh.h
+++ b/contrib/HighOrderMeshOptimizer/OptHomMesh.h
@@ -17,7 +17,7 @@ class Mesh
 
 public:
 
-  Mesh(GEntity *ge, std::set<MVertex*> & toFix, int method);
+  Mesh(GEntity *ge, const std::set<MElement*> &els, std::set<MVertex*> & toFix, int method);
 
   inline const int &nPC() { return _nPC; }
   inline int nVert() { return _vert.size(); }
diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
index 50a99c88bbe04d9c5c60b704960e1f7fb41056d7..41c41c7f14d200804345906a5eadeda8c5f9669b 100644
--- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
+++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp
@@ -96,7 +96,7 @@ void exportMeshToDassault (GModel *gm, const std::string &fn, int dim){
     int count = 1;
     for (GModel::fiter itf = gm->firstFace(); itf != gm->lastFace(); ++itf){
       std::vector<MTriangle*> &tris = (*itf)->triangles; 
-      for (int i=0;i<tris.size();i++){
+      for (size_t i=0;i<tris.size();i++){
 	MTriangle *t = tris[i];
 	fprintf(f,"%d ",count++);
 	for (int j=0;j<t->getNumVertices();j++){
@@ -114,7 +114,7 @@ void exportMeshToDassault (GModel *gm, const std::string &fn, int dim){
     count = 1;
     for (GModel::eiter ite = gm->firstEdge(); ite != gm->lastEdge(); ++ite){
       std::vector<MLine*> &l = (*ite)->lines; 
-      for (int i=0;i<l.size();i++){
+      for (size_t i=0;i<l.size();i++){
 	MLine *t = l[i];
 	fprintf(f,"%d ",count++);
 	for (int j=0;j<t->getNumVertices();j++){
@@ -229,66 +229,40 @@ MElement* getTheWorstElementUp (const ITERATOR &beg, const ITERATOR &end, double
   return worst;
 }
 
-
-std::set<MVertex*> filter3D(GRegion *gr, int nbLayers, double _qual)
-{
-  std::set<MVertex*> touched;
-  std::set<MVertex*> not_touched;
-  std::set<MTetrahedron *> ts;
-  for (int i=0;i<gr->tetrahedra.size();i++){
-    MTetrahedron *t = gr->tetrahedra[i];
-    if (t->distoShapeMeasure() < _qual){
-      ts.insert(t);
-      for(int j=0;j<t->getNumVertices();j++)touched.insert(t->getVertex(j));
-    }
-    //    if (ts.size() == 1)break;
-  }  
-
-  printf("FILTER3D : %d bad tets found among %6d\n",ts.size(),gr->tetrahedra.size());
-
-  // add layers of elements around bad elements
-  for (int layer = 0;layer<nbLayers; layer++){
-    for (int i=0;i<gr->tetrahedra.size();i++){
-      MTetrahedron *t = gr->tetrahedra[i];
-      bool add_ = false;
-      for(int j=0;j<t->getNumVertices();j++){
-	if(touched.find(t->getVertex(j)) != touched.end()){
-	  add_ = true;
-	}
-      }
-      if (add_)ts.insert(t);
-    }
-
-    for (std::set<MTetrahedron*>::iterator it = ts.begin(); it != ts.end() ; ++it){
-      for(int j=0;j<(*it)->getNumVertices();j++){
-	touched.insert((*it)->getVertex(j));
-      }
+static std::set<MVertex*> filterSimple(GEntity *ge, 
+					  int nbLayers, 
+					  double _qual_min, 
+					  double _qual_max, 
+            std::set<MElement*> &result) {
+  std::vector<MElement*> badElements, allElements;
+  for (int i = 0; i < ge->getNumMeshElements(); ++i) {
+    MElement *e = ge->getMeshElement(i);
+    double Q = e->distoShapeMeasure();
+    allElements.push_back(e);
+    if (Q < _qual_min || Q > _qual_max) {
+      badElements.push_back(e);
     }
   }
-
-  for (int i=0;i<gr->tetrahedra.size();i++){
-    if (ts.find(gr->tetrahedra[i]) == ts.end()){
-      for(int j=0;j<gr->tetrahedra[i]->getNumVertices();j++){
-	if (touched.find(gr->tetrahedra[i]->getVertex(j)) != touched.end())
-	  not_touched.insert(gr->tetrahedra[i]->getVertex(j));
+  getTopologicalNeighbors(nbLayers, allElements, badElements,result);  
+  std::set<MVertex*> vs;
+  for (int i = 0; i < allElements.size(); i++) {
+    if (result.find(allElements[i]) == result.end()) {
+      for (int j = 0; j < allElements[i]->getNumVertices(); j++) {
+        vs.insert(allElements[i]->getVertex(j));
       }
     }
   }
-
-  gr->tetrahedra.clear();
-  gr->tetrahedra.insert(gr->tetrahedra.begin(),ts.begin(),ts.end());
-
-  printf("FILTER3D : AFTER FILTERING %d tets remain %d nodes on the boundary\n",gr->tetrahedra.size(),not_touched.size());
-  return not_touched;
+  return vs;
 }
 
-
 std::set<MVertex*> filter2D_boundaryLayer(GFace *gf, 
 					  int nbLayers, 
 					  double _qual_min, 
 					  double _qual_max, 
 					  double F , 
-					  std::set<MElement*> & badasses) {
+					  std::set<MElement*> & badasses,
+            std::set<MElement*> & result
+            ) {
   
   double jmin, jmax;
   MElement *worstDown = getTheWorstElementDown(badasses.begin(),badasses.end(),jmin);
@@ -308,19 +282,9 @@ std::set<MVertex*> filter2D_boundaryLayer(GFace *gf,
   getTopologicalNeighbors(nbLayers, all, vworst,result1);  
   std::set<MElement*> result2;
   getGeometricalNeighbors (worst, all, F, result2);
-  std::set<MElement*> result;
   intersection (result1,result2,result);
   //  printf("intsersection(%d,%d) = %d\n",result1.size(),result2.size(),result.size()); 
   
-
-  gf->triangles.clear();
-  gf->quadrangles.clear();
-  for (std::set<MElement*>::iterator it = result.begin(); it != result.end(); ++it){
-    MElement *e = *it;
-    if (e->getType() == TYPE_QUA)gf->quadrangles.push_back((MQuadrangle*)e);
-    else if (e->getType() == TYPE_TRI)gf->triangles.push_back((MTriangle*)e);
-  }
-
   std::set<MVertex*> vs;
   for (int i = 0; i < all.size(); i++) {
     if (result.find(all[i]) == result.end()) {
@@ -337,7 +301,8 @@ std::set<MVertex*> filter3D_boundaryLayer(GRegion *gr,
 					  int nbLayers, 
 					  double _qual_min, 
 					  double _qual_max, 
-					  double F ) {
+					  double F,
+            std::set<MElement *> &result) {
   double jmin,jmax;
   MElement *worst = compare_worst (getTheWorstElementDown(gr->tetrahedra.begin(),gr->tetrahedra.end(),jmin),
 				   getTheWorstElementDown(gr->prisms.begin(),gr->prisms.end(),jmin)); 
@@ -352,21 +317,9 @@ std::set<MVertex*> filter3D_boundaryLayer(GRegion *gr,
   getTopologicalNeighbors(nbLayers, all, vworst,result1);  
   std::set<MElement*> result2;
   getGeometricalNeighbors (worst, all, F, result2);
-  std::set<MElement*> result;
   intersection (result1,result2,result);
   //  printf("intsersection(%d,%d) = %d\n",result1.size(),result2.size(),result.size()); 
   
-
-  gr->tetrahedra.clear();
-  gr->hexahedra.clear();
-  gr->prisms.clear();
-  for (std::set<MElement*>::iterator it = result.begin(); it != result.end(); ++it){
-    MElement *e = *it;
-    if (e->getType() == TYPE_TET)gr->tetrahedra.push_back((MTetrahedron*)e);
-    else if (e->getType() == TYPE_HEX)gr->hexahedra.push_back((MHexahedron*)e);
-    else if (e->getType() == TYPE_PRI)gr->prisms.push_back((MPrism*)e);
-  }
-
   std::set<MVertex*> vs;
   for (int i = 0; i < all.size(); i++) {
     if (result.find(all[i]) == result.end()) {
@@ -378,77 +331,6 @@ std::set<MVertex*> filter3D_boundaryLayer(GRegion *gr,
   return vs;
 }
 
-
-std::set<MVertex*> filter2D(GFace *gf, 
-			    int nbLayers, 
-			    double _qual_min, 
-			    double _qual_max)
-{
-  std::set<MVertex*> touched;
-  std::set<MVertex*> not_touched;
-  std::set<MElement*> elements;
-  std::set<MTriangle*> tt;
-  std::set<MQuadrangle*> qq;
-
-  for (int i = 0; i < gf->triangles.size(); i++) {
-    MTriangle *t = gf->triangles[i];
-    double jmin,jmax;
-    t->scaledJacRange(jmin,jmax);
-    if (jmin < _qual_min || jmax > _qual_max) {
-      elements.insert(t);
-      tt.insert(t);
-      for (int j = 0; j < t->getNumVertices(); j++)
-	touched.insert(t->getVertex(j));
-    }
-  }
-  for (int i = 0; i < gf->quadrangles.size(); i++) {
-    MQuadrangle *q = gf->quadrangles[i];
-    double jmin,jmax;
-    q->scaledJacRange(jmin,jmax);
-    if (jmin < _qual_min || jmax > _qual_max) {
-      elements.insert(q);
-      qq.insert(q);
-      for (int j = 0; j < q->getNumVertices(); j++)
-	touched.insert(q->getVertex(j));
-    }
-  }
-  
-  // add layers of elements around bad elements
-  for (int layer = 0; layer < nbLayers; layer++) {
-    for (unsigned int i = 0; i < gf->getNumMeshElements(); ++i) {
-      MElement *el = gf->getMeshElement(i);
-      for (int j = 0; j < el->getNumVertices(); ++j) {
-        if (touched.find(el->getVertex(j)) != touched.end()) {
-          elements.insert(el);
-	  if (el->getType() == TYPE_TRI)tt.insert((MTriangle*)el);
-	  if (el->getType() == TYPE_QUA)qq.insert((MQuadrangle*)el);
-          break;
-        }
-      }
-    }
-    for (std::set<MElement *>::iterator it = elements.begin(); it != elements.end(); ++it) {
-      MElement *el = *it;
-      for (int j = 0; j < el->getNumVertices(); ++j) {
-        touched.insert(el->getVertex(j));
-      }
-    }
-  }
-
-  for (int i = 0; i < gf->getNumMeshElements(); i++) {
-    if (elements.find(gf->getMeshElement(i)) == elements.end()) {
-      for (int j = 0; j < gf->getMeshElement(i)->getNumVertices(); j++) {
-	if (touched.find(gf->getMeshElement(i)->getVertex(j)) != touched.end()) not_touched.insert(gf->getMeshElement(i)->getVertex(j));
-      }
-    }
-  }
-  gf->triangles.clear();
-  gf->triangles.insert(gf->triangles.begin(),tt.begin(),tt.end());
-  gf->quadrangles.clear();
-  gf->quadrangles.insert(gf->quadrangles.begin(),qq.begin(),qq.end());
-
-  return not_touched;
-}
-
 static std::vector<std::set<MElement*> > splitConnex(const std::set<MElement*> &in)
 {
   std::map<int, std::vector<int> > vertex2elements;
@@ -481,11 +363,11 @@ static std::vector<std::set<MElement*> > splitConnex(const std::set<MElement*> &
       color ++;
     }
   }
-  std::vector<std::set<MElement*> > splitted(color);
+  std::vector<std::set<MElement*> > split(color);
   for (size_t i = 0; i < elements.size(); ++i) {
-    splitted[colors[i]].insert(elements[i]);
+    split[colors[i]].insert(elements[i]);
   }
-  return splitted;
+  return split;
 }
 
 void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p)
@@ -536,36 +418,33 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p)
 	if (badasses.size() == 0)continue;
       }
       while (1){
-	std::vector<MTriangle*> tris = (*itf)->triangles;
-	std::vector<MQuadrangle*> quas = (*itf)->quadrangles;
 	std::set<MVertex*> toFix;
+  std::set<MElement*> toOptimize;
 
-	if (p.filter == 1) toFix = filter2D_boundaryLayer(*itf, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, p.DistanceFactor, badasses);
-	else toFix = filter2D(*itf, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX);
-	OptHOM *temp = new OptHOM(*itf, toFix, method);
-	//	temp->recalcJacDist();
+	if (p.filter == 1) toFix = filter2D_boundaryLayer(*itf, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, p.DistanceFactor, badasses, toOptimize);
+	else toFix = filterSimple(*itf, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, toOptimize);
+	OptHOM temp(*itf, toOptimize, toFix, method);
+	//	temp.recalcJacDist();
 
-	temp->getDistances(distMaxBND, distAvgBND,minJac, maxJac);
+	temp.getDistances(distMaxBND, distAvgBND,minJac, maxJac);
 	//	if (minJac < 1.e2)OptHomMessage("Optimizing a blob of %4d elements  minJ %12.5E -- maxJ %12.5E",(*itf)->getNumMeshElements(), minJac, maxJac);
 	std::ostringstream ossI;
 	ossI << "initial_" << (*itf)->tag() << "ITER_" << ITER << ".msh";
-	temp->mesh.writeMSH(ossI.str().c_str());
-	(*itf)->triangles = tris;
-	(*itf)->quadrangles = quas;
+	temp.mesh.writeMSH(ossI.str().c_str());
 	if (minJac > p.BARRIER_MIN && maxJac < p.BARRIER_MAX) break;
 	
-	p.SUCCESS = std::min(p.SUCCESS,temp->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, samples, p.itMax));
+	p.SUCCESS = std::min(p.SUCCESS,temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, samples, p.itMax));
 
-	temp->getDistances(distMaxBND, distAvgBND,minJac, maxJac);
-	//	temp->getJacDist(p.minJac, p.maxJac, distMaxBND, distAvgBND);
-	temp->mesh.updateGEntityPositions();
+	temp.getDistances(distMaxBND, distAvgBND,minJac, maxJac);
+	//	temp.getJacDist(p.minJac, p.maxJac, distMaxBND, distAvgBND);
+	temp.mesh.updateGEntityPositions();
 	if (p.SUCCESS == -1) break;
 	ITER ++;
 	if (p.filter == 1 && ITER > badasses.size() * 2)break;
 
 	//      std::ostringstream ossF;
 	//      ossF << "final_" << (*itf)->tag() << ".msh";
-	//      temp->mesh.writeMSH(ossF.str().c_str());
+	//      temp.mesh.writeMSH(ossF.str().c_str());
       }
       double DTF = (double)(clock()-tf1) / CLOCKS_PER_SEC;
       if (p.SUCCESS == 1){
@@ -587,35 +466,34 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p)
       Msg::Info("Model region %4d is considered",(*itr)->tag());
       p.SUCCESS = true;
       while (1){
-      std::vector<MTetrahedron*> tets = (*itr)->tetrahedra;
       std::set<MVertex*> toFix;
+      std::set<MElement*> toOptimize;
 
-      if (p.filter == 1) toFix = filter3D_boundaryLayer(*itr, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, p.DistanceFactor);
-      else toFix = filter3D(*itr, p.nbLayers, p.BARRIER_MIN);
+      if (p.filter == 1) toFix = filter3D_boundaryLayer(*itr, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, p.DistanceFactor, toOptimize);
+      else toFix = filterSimple(*itr, p.nbLayers, p.BARRIER_MIN, p.BARRIER_MAX, toOptimize);
 
 //      if ((*itr)->tetrahedra.size() > 0) {
-        OptHOM *temp = new OptHOM(*itr, toFix, method);
+        OptHOM temp(*itr, toOptimize, toFix, method);
         double distMaxBND, distAvgBND, minJac, maxJac;
-	temp->getDistances(distMaxBND, distAvgBND,minJac, maxJac);
-	//        temp->recalcJacDist();
-	//        temp->getJacDist(minJac, maxJac, distMaxBND, distAvgBND);
+	temp.getDistances(distMaxBND, distAvgBND,minJac, maxJac);
+	//        temp.recalcJacDist();
+	//        temp.getJacDist(minJac, maxJac, distMaxBND, distAvgBND);
         if (minJac < 1.e2)Msg::Info("Optimizing a blob of %4d elements  minJ %12.5E -- maxJ %12.5E",(*itr)->getNumMeshElements(), minJac, maxJac);
-        (*itr)->tetrahedra = tets;
         std::ostringstream ossI;
         ossI << "initial_" << (*itr)->tag() << "ITER_" << ITER << ".msh";
-        temp->mesh.writeMSH(ossI.str().c_str());
+        temp.mesh.writeMSH(ossI.str().c_str());
         if (minJac > p.BARRIER_MIN  && maxJac < p.BARRIER_MAX) break;
-        p.SUCCESS = temp->optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, samples, p.itMax);
-	temp->getDistances(distMaxBND, distAvgBND,minJac, maxJac);
-	//        temp->getJacDist(p.minJac, p.maxJac, distMaxBND, distAvgBND);
-        temp->mesh.updateGEntityPositions();
+        p.SUCCESS = temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, samples, p.itMax);
+	temp.getDistances(distMaxBND, distAvgBND,minJac, maxJac);
+	//        temp.getJacDist(p.minJac, p.maxJac, distMaxBND, distAvgBND);
+        temp.mesh.updateGEntityPositions();
         if (!p.SUCCESS) break;
 //      }
       ITER ++;
       }
       Msg::Info("Model region %4d is done (%d subdomains were computed) SUCCESS %1d",(*itr)->tag(),ITER,p.SUCCESS);
       Msg::Info("----------------------------------------------------------------");
-      //      temp->mesh.writeMSH("final.msh");
+      //      temp.mesh.writeMSH("final.msh");
     }
   }  
   clock_t t2 = clock();