diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp
index c8b28aff4290bcf31edb0f72c1184fd4c4bf6326..c90c4f2c58b46794b18847dfffc3baff83e2ac22 100644
--- a/Geo/GModelIO_OCC.cpp
+++ b/Geo/GModelIO_OCC.cpp
@@ -933,13 +933,12 @@ GRegion* OCC_Internals::addRegionToModel(GModel *model, TopoDS_Solid region)
   GRegion *gr = getOCCRegionByNativePtr(model, region);
   if(gr) return gr;
 
-  // FIXME THE PREVIOUS IMPLEMENTATION WAS BETTER FOR SOME USERS :-)
+  //   FIXME THE PREVIOUS IMPLEMENTATION WAS BETTER FOR SOME USERS :-)
   buildShapeFromLists(region);
   model->destroy();
   buildLists();
   buildGModel(model);
   return getOCCRegionByNativePtr(model, region);
-
   //  _addShapeToMaps(region);
   //  buildShapeFromLists(region);
   //  buildGModel(model);
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 5958aef6b33c5b0abf12806011298e474ffd7930..92e5649694d1a2f6a9dca480bce3265717fc9014 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -179,7 +179,7 @@ void discreteFace::createGeometry()
 
   int order = 1;
   int nPart = 2;
-  double eta = 5/(2.*3.14);
+  double eta = .5*5/(2.*3.14);
   if (!_atlas.empty())return;
 
   double dtSplit = 0.0;
@@ -192,8 +192,8 @@ void discreteFace::createGeometry()
   triangulation* init = new triangulation(-1, tem,this);
   init->iter = iter++;
   allEdg2Tri = init->ed2tri;
-
   toSplit.push(init);
+  //  printf("%12.5E\n",(toSplit.top())->aspectRatio() );
   if((toSplit.top())->genus()!=0 ||
      (toSplit.top())->aspectRatio() > eta ||
      (toSplit.top())->seamPoint){
diff --git a/Geo/gmshRegion.cpp b/Geo/gmshRegion.cpp
index 2c1de3b2c2a536b979151dcaf505ba633566b946..7583907d0ff5e5fba3dcf694ed0282008acdfa00 100644
--- a/Geo/gmshRegion.cpp
+++ b/Geo/gmshRegion.cpp
@@ -38,17 +38,17 @@ gmshRegion::gmshRegion(GModel *m, ::Volume *volume)
     else
       Msg::Error("Unknown surface %d", is);
   }
-  if(v->EmbeddedSurfaces){
-    for(int i = 0; i < List_Nbr(v->EmbeddedSurfaces); i++){
-      Surface *s;
-      List_Read(v->EmbeddedSurfaces, i, &s);
-      GFace *gf = m->getFaceByTag(abs(s->Num));
-      if(gf)
-	addEmbeddedFace(gf);
-      else
-	Msg::Error("Unknown surface %d", s->Num);
-    }
-  }
+  //  if(v->EmbeddedSurfaces){
+  //    for(int i = 0; i < List_Nbr(v->EmbeddedSurfaces); i++){
+  //      Surface *s;
+  //      List_Read(v->EmbeddedSurfaces, i, &s);
+  //      GFace *gf = m->getFaceByTag(abs(s->Num));
+  //      if(gf)
+  //	addEmbeddedFace(gf);
+  //      else
+  //	Msg::Error("Unknown surface %d", s->Num);
+  //    }
+  //  }
   resetMeshAttributes();
 }
 
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 55ddb9adfb4321899ef3c7c8f37fbc8bc0abda54..8f4042452deb0364259f1ea37b567eb21fe5430e 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -49,6 +49,74 @@
 #include "PViewData.h"
 #endif
 
+class TEST_IF_MESH_IS_COMPATIBLE_WITH_EMBEDDED_ENTITIES {
+public:
+  void operator () (GRegion *gr) {
+    std::list<GEdge*> e = gr->embeddedEdges();
+    std::list<GFace*> f = gr->embeddedFaces();
+    if (e.empty() && f.empty())return;
+    std::map<MEdge,GEdge*,Less_Edge> edges;
+    std::map<MFace,GFace*,Less_Face> faces;
+    std::list<GEdge*>::iterator it = e.begin();
+    std::list<GFace*>::iterator itf = f.begin();
+    for ( ; it != e.end() ; ++it){
+      for (unsigned int i=0;i<(*it)->lines.size(); ++i){
+	if (distance ((*it)->lines[i]->getVertex(0),(*it)->lines[i]->getVertex(1)) > 1.e-12)
+	  edges.insert(std::make_pair(MEdge((*it)->lines[i]->getVertex(0),(*it)->lines[i]->getVertex(1)),*it));
+      }
+    }
+    for ( ; itf != f.end() ; ++itf){
+      for (unsigned int i=0;i<(*itf)->triangles.size(); ++i){
+	faces.insert(std::make_pair(MFace((*itf)->triangles[i]->getVertex(0),(*itf)->triangles[i]->getVertex(1),(*itf)->triangles[i]->getVertex(2)),*itf));
+      }
+    }
+    Msg::Info ("Searching for %d embedded mesh edges and %d embedded mesh faces in region %d", edges.size(),  faces.size(), gr->tag()); 
+    for (unsigned int k=0;k<gr->getNumMeshElements();k++){
+      for (int j=0;j<gr->getMeshElement(k)->getNumEdges();j++){
+	edges.erase (gr->getMeshElement(k)->getEdge(j));
+      }
+      for (int j=0;j<gr->getMeshElement(k)->getNumFaces();j++){
+	faces.erase (gr->getMeshElement(k)->getFace(j));
+      }
+    }
+    if (edges.empty() && faces.empty()) {
+      Msg::Info ("All embedded edges and faces are present in the final mesh"); 
+    }
+    if (edges.size()) {
+      char name[256];
+      sprintf(name,"missingEdgesOnRegion%d.pos",gr->tag());
+      Msg::Error("Region %d : %d mesh edges that should be embedded are missing in the final mesh",gr->tag(), (int)edges.size());
+      Msg::Error("Saving the missing edges in file %s",name);
+      FILE *f = fopen(name,"w");
+      fprintf(f,"View \" \" {\n");
+      for (std::map<MEdge,GEdge*,Less_Edge>::iterator it =  edges.begin() ; it != edges.end(); ++it){
+	MVertex *v1 = it->first.getVertex(0);
+	MVertex *v2 = it->first.getVertex(1);
+	fprintf(f,"SL(%g,%g,%g,%g,%g,%g){%d,%d};\n",v1->x(),v1->y(),v1->z(),v2->x(),v2->y(),v2->z(), it->second->tag(),it->second->tag());
+      }
+      fprintf(f,"};\n");
+      fclose(f);
+    }
+    if (faces.size()) {
+      char name[256];
+      sprintf(name,"missingFacesOnRegion%d.pos",gr->tag());
+      Msg::Error("Region %d : %d mesh faces that should be embedded are missing in the final mesh",gr->tag(), (int)faces.size());
+      Msg::Error("Saving the missing faces in file %s",name);
+      FILE *f = fopen(name,"w");
+      fprintf(f,"View \" \" {\n");
+      for (std::map<MFace,GFace*,Less_Face>::iterator it =  faces.begin() ; it != faces.end(); ++it){
+	MVertex *v1 = it->first.getVertex(0);
+	MVertex *v2 = it->first.getVertex(1);
+	MVertex *v3 = it->first.getVertex(2);
+	fprintf(f,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%d,%d,%d};\n",v1->x(),v1->y(),v1->z(),v2->x(),v2->y(),v2->z(),
+		v3->x(),v3->y(),v3->z(),it->second->tag(),it->second->tag(),it->second->tag());
+      }
+      fprintf(f,"};\n");
+      fclose(f);
+    }
+  }
+};
+
 template<class T>
 static void GetQualityMeasure(std::vector<T*> &ele,
                               double &gamma, double &gammaMin, double &gammaMax,
@@ -835,6 +903,10 @@ static void Mesh3D(GModel *m)
   // ensure that all volume Jacobians are positive
   m->setAllVolumesPositive();
 
+  //  std::for_each(m->firstRegion(), m->lastRegion(), optimizeMeshGRegionNetgen());
+  if (Msg::GetVerbosity() > 98) 
+    std::for_each(m->firstRegion(), m->lastRegion(), TEST_IF_MESH_IS_COMPATIBLE_WITH_EMBEDDED_ENTITIES ());
+  
   CTX::instance()->mesh.changed = ENT_ALL;
   double t2 = Cpu();
   CTX::instance()->meshTimer[2] = t2 - t1;
@@ -850,6 +922,9 @@ void OptimizeMeshNetgen(GModel *m)
   // Ensure that all volume Jacobians are positive
   m->setAllVolumesPositive();
 
+  if (Msg::GetVerbosity() > 98) 
+    std::for_each(m->firstRegion(), m->lastRegion(), TEST_IF_MESH_IS_COMPATIBLE_WITH_EMBEDDED_ENTITIES ());
+  
   double t2 = Cpu();
   Msg::StatusBar(true, "Done optimizing 3D mesh with Netgen (%g s)", t2 - t1);
 }
@@ -863,6 +938,9 @@ void OptimizeMesh(GModel *m)
   // Ensure that all volume Jacobians are positive
   m->setAllVolumesPositive();
 
+  if (Msg::GetVerbosity() > 98) 
+    std::for_each(m->firstRegion(), m->lastRegion(), TEST_IF_MESH_IS_COMPATIBLE_WITH_EMBEDDED_ENTITIES ());
+  
   CTX::instance()->mesh.changed = ENT_ALL;
   double t2 = Cpu();
   Msg::StatusBar(true, "Done optimizing 3D mesh (%g s)", t2 - t1);
diff --git a/Mesh/delaunay3d.cpp b/Mesh/delaunay3d.cpp
index 97d459f7dd93be6c41d3f5f061c4bb02cefdf715..ee88ae6978fc34e4fe0ffd5781ba54556fe73d05 100644
--- a/Mesh/delaunay3d.cpp
+++ b/Mesh/delaunay3d.cpp
@@ -249,7 +249,7 @@ void HilbertSortB::Sort(Vert** vertices, int arraysize, int e, int d,
 
   if (maxDepth > 0) {
     if ((depth + 1) == maxDepth) {
-      printf("ARGH\n");
+      //      printf("ARGH max depth attained\n");
       return;
     }
   }
@@ -544,8 +544,7 @@ static void edgeSwapPass (tetContainer &T)
 */
 
 static void starShapeness (Vert *v, connContainer &bndK,
-			   std::vector<unsigned int> &_negatives,
-			   double threshold)
+			   std::vector<unsigned int> &_negatives)
 {
   _negatives.clear();
   for (unsigned int i=0; i< bndK.size(); i++) {
@@ -554,7 +553,7 @@ static void starShapeness (Vert *v, connContainer &bndK,
 						    (double*)bndK[i].f.V[1],
 						    (double*)bndK[i].f.V[2],
 						    (double*)v);
-    if (val <= threshold ) {
+    if (val <= 0.0 ) {
       _negatives.push_back(i);
     }
   }
@@ -679,17 +678,16 @@ static Tet *tetInsideCavityWithFAce (Face &f, cavityContainer &cavity)
   return NULL;
 }
 
-static bool fixDelaunayCavity (double threshold,
-			       Vert *v,
+static bool fixDelaunayCavity (Vert *v,
 			       cavityContainer &cavity,
 			       connContainer &bndK,
 			       int myThread, int K,
 			       std::vector<unsigned int> & _negatives)
 {
-  starShapeness (v, bndK, _negatives, threshold);
+  starShapeness (v, bndK, _negatives);
 
   if (_negatives.empty())return false;
-
+  //  return true;
   // unset all tets of the cavity
   for (unsigned int i=0; i< cavity.size(); i++)cavity[i]->unset(myThread,K);
   for (unsigned int i=0; i<bndK.size(); i++)if(bndK[i].t)bndK[i].t->unset(myThread,K);
@@ -715,7 +713,7 @@ static bool fixDelaunayCavity (double threshold,
     }
     removeIsolatedTets(containsV, cavity,bndK,myThread,K);
     buildDelaunayBall (cavity,bndK);
-    starShapeness (v, bndK, _negatives, threshold);
+    starShapeness (v, bndK, _negatives);
   }
   return false;
 }
@@ -751,6 +749,7 @@ Tet* walk (Tet *t, Vert *v, int maxx, double &totSearch, int thread)
   while (1){
     totSearch++;
     if (t == NULL) {
+      //      printf("in an embedded edge\n");
       return NULL; // we should NEVER return here
     }
     //    if (t->inSphere(v,thread)) {return t;}
@@ -905,13 +904,39 @@ static Tet* randomTet (int thread,  tetContainer &allocator)
 }
 
 
+int isCavityCompatibleWithEmbeddedEdges(cavityContainer &cavity, 
+					connContainer &bndK,   
+					edgeContainer &allEmbeddedEdges){
+  
+  const unsigned int bSize = bndK.size();
+  std::vector<Edge> ed;
+  for (unsigned int i=0; i<bSize; i++) {
+    for (unsigned int j=0; j<3; j++) {
+      if (bndK[i].f.V[j] > bndK[i].f.V[(j+1)%3]){
+	ed.push_back(Edge(bndK[i].f.V[j], bndK[i].f.V[(j+1)%3]));
+      }
+    }
+  }
+  
+  for (unsigned int i=0; i<cavity.size(); i++){
+    for (int j=0;j<6;j++){
+      Edge e = cavity[i]->getEdge(j);
+      if (std::find(ed.begin(), ed.end(), e) == ed.end() && allEmbeddedEdges.find(e)){
+	return 0;
+      }
+    }
+  }
+  return 1;
+} 
+
+
 //#define _VERBOSE 1
 void delaunayTrgl (const unsigned int numThreads,
 		   const unsigned int NPTS_AT_ONCE,
 		   unsigned int Npts,
 		   std::vector<Vert*> assignTo[],
 		   tetContainer &allocator,
-		   double threshold)
+		   edgeContainer *embeddedEdges)
 {
 #if defined(_VERBOSE)
   double totSearchGlob=0;
@@ -983,6 +1008,7 @@ void delaunayTrgl (const unsigned int numThreads,
     ////////////////////////////////////////////////////////////////////////////////////
 
     for (unsigned int iPGlob=0 ; iPGlob < maxLocSizeK; iPGlob++){
+      //      printf("%d vs %d\n",iPGlob,maxLocSizeK);
 #if defined(_OPENMP)
 #pragma omp barrier
 #endif
@@ -995,9 +1021,11 @@ void delaunayTrgl (const unsigned int numThreads,
 	if(vToAdd[K]){
 	  // In 3D, insertion of a point may lead to deletion of tets !!
 	  if (!Choice[K]->V[0])Choice[K] = randomTet (myThread, allocator);
+	  //	  int nbCoucou=0;
 	  while(1){
 	    t[K] = walk ( Choice[K] , vToAdd[K], Npts, totSearch, myThread);
 	    if (t[K])break;
+	    //	    printf("coucou %d\n",nbCoucou++);
 	    // the domain may not be convex. we then start from a random tet and
 	    // walk from there
 	    Choice[K] = randomTet(rand() % numThreads, allocator);
@@ -1017,7 +1045,11 @@ void delaunayTrgl (const unsigned int numThreads,
 	  cavityK.clear(); bndK.clear();
 	  delaunayCavity2(t[K], NULL, vToAdd[K], cavityK, bndK, myThread, K);
 	  // verify the cavity
-	  if (fixDelaunayCavity (threshold, vToAdd[K],  cavityK, bndK, myThread, K, _negatives)){
+	  if (fixDelaunayCavity (vToAdd[K],  cavityK, bndK, myThread, K, _negatives)){
+	    vToAdd[K] = NULL;
+	    invalidCavities [myThread]++;
+	  }
+	  if (embeddedEdges && !isCavityCompatibleWithEmbeddedEdges(cavityK, bndK, *embeddedEdges)){
 	    vToAdd[K] = NULL;
 	    invalidCavities [myThread]++;
 	  }
@@ -1093,7 +1125,8 @@ void delaunayTrgl (const unsigned int numThreads,
 
   //checkLocalDelaunayness(T,"final");
 
-
+  
+  
   //  printf(" %12.5E %12.5E  %12.5E tot  %12.5E \n",t2,t3,t4,t2+t3+t4);
 
 #if defined(_VERBOSE)
diff --git a/Mesh/delaunay3d_private.h b/Mesh/delaunay3d_private.h
index fb330ccf28fa6bd59d9c8c115744f06d6cc05ed5..a0360dc244dd27709ab721e111d8d6c3f437cb8a 100644
--- a/Mesh/delaunay3d_private.h
+++ b/Mesh/delaunay3d_private.h
@@ -126,9 +126,10 @@ inline double orientationTestFast (Vert *va, Vert *vb, Vert *vc, Vert *vd)
   return orientationTestFast ((double*)va,(double*)vb,(double*)vc,(double*)vd);
 }
 
-struct Edge {
+class Edge {
+public :
   Vert *first, *second;
-  Edge (Vert *v1, Vert *v2) : first(v1), second(v2)
+  Edge (Vert *v1, Vert *v2) : first(std::min(v1,v2)), second(std::max(v1,v2))
   {
   }
   bool operator == (const Edge &e) const{
@@ -142,6 +143,37 @@ struct Edge {
   }
 };
 
+struct edgeContainer
+{
+  std::vector<std::vector<Edge> > _hash;
+  size_t _size;
+  edgeContainer(unsigned int N = 1000000)
+  {
+    _size = 0;
+    _hash.resize(N);
+  }
+
+  inline bool find (const Edge &e) const {
+    size_t h = ((size_t) e.first >> 8) ;
+    const std::vector<Edge> &v = _hash[h %_hash.size()];
+    for (unsigned int i=0; i< v.size();i++)if (e == v[i]) {return true;}
+    return false;
+  }
+
+  bool empty () const {return _size == 0;}
+  
+  bool addNewEdge (const Edge &e)
+  {
+    size_t h = ((size_t) e.first >> 8) ;
+    std::vector<Edge> &v = _hash[h %_hash.size()];
+    for (unsigned int i=0; i< v.size();i++)if (e == v[i]) {return false;}
+    v.push_back(e);
+    _size++;
+    return true;
+  }
+};
+
+
 struct Face {
   Vert *v[3];
   Vert *V[3];
@@ -181,6 +213,7 @@ struct Tet {
     T[0] = T[1] = T[2] = T[3] = NULL;
     setAllDeleted();
   }
+  //  inline bool isFace () const {return V[3]==NULL;}
   int setVerticesNoTest (Vert *v0, Vert *v1, Vert *v2, Vert *v3)
   {
     _modified=true;
@@ -358,7 +391,7 @@ void delaunayTrgl(const unsigned int numThreads,
                   const unsigned int NPTS_AT_ONCE,
                   unsigned int Npts,
                   std::vector<Vert*> assignTo[],
-                  tetContainer &allocator, double threshold = 0.0);
+                  tetContainer &allocator, edgeContainer *embedded = 0);
 bool edgeSwap(Tet *tet, int iLocalEdge,  tetContainer &T, int myThread);
 
 #endif
diff --git a/Mesh/delaunay_refinement.cpp b/Mesh/delaunay_refinement.cpp
index a2a1b18123ab1ce54394c6343280b078fa9957e7..4bc2ebf72eea873a16d15d3283d6981bd59f2047 100644
--- a/Mesh/delaunay_refinement.cpp
+++ b/Mesh/delaunay_refinement.cpp
@@ -22,52 +22,47 @@
 #include "MTriangle.h"
 #include "GRegion.h"
 #include "GFace.h"
+#include "MLine.h"
+#include "Context.h"
 #include "SBoundingBox3d.h"
+#include "GModel.h"
+#include "Field.h"
 
-typedef  std::set< Edge > edgeContainer2;
-
-long int AVGSEARCH;
-
-struct edgeContainer
-{
-  std::set< Edge > _hash2;
-  std::vector<std::vector<Edge> > _hash;
-  edgeContainer(unsigned int N = 1000000)
-  {
-    _hash.resize(N);
-  }
-  bool addNewEdge2 (const Edge &e)
-  {
-    std::set< Edge >::iterator it = _hash2.find(e);
-    if (it != _hash2.end())return false;
-    _hash2.insert(e);
-    return true;
-  }
-  bool addNewEdge (const Edge &e)
-  {
-    size_t h = ((size_t) e.first >> 3) ;
-    std::vector<Edge> &v = _hash[h %_hash.size()];
-    AVGSEARCH+=v.size();
-    for (unsigned int i=0; i< v.size();i++)if (e == v[i]) {return false;}
-    v.push_back(e);
-    return true;
-  }
-};
+#define SQR(X) (X)*(X)
+const double EXCLUSION_FACTOR = 0.8;
 
 struct IPT {
-  double _x1,_x2,_x3,_x4;
+  double _x1,_x2,_x3,_x4, _x5;
   IPT(double x1, double x2, double x3, double x4)
-    : _x1(x1), _x2(x2), _x3(x3), _x4(x4)
+    : _x1(x1), _x2(x2), _x3(x3), _x4(x4),_x5(0.0)
   {
   };
 };
 
+////int C_COUNT = 0;
+
+//double _C1, _C2, _C3, _C4;
+static double GMSHSIZE (const SPoint3 &p, Field *f, double lc_nodal) {
+  double f_field = 1.e22;
+  if (!CTX::instance()->mesh.lcExtendFromBoundary) lc_nodal = 1.e22;
+  //  double _a = Cpu();
+  if (f)f_field = (*f)(p.x(), p.y(), p.z());
+  //  _C3 += Cpu() - _a;  
+
+  double lc = std::min (lc_nodal,f_field);
+  lc = std::max(lc, CTX::instance()->mesh.lcMin);
+  lc = std::min(lc, CTX::instance()->mesh.lcMax);
+  //  C_COUNT++;
+  return lc;
+}
+
+
 double adaptiveTrapezoidalRule(SPoint3 p1 , SPoint3 p2 ,
                                double lc1 , double lc2 ,
-                               double (*f)(const SPoint3 &p, void *),
-                               void *data, std::vector< IPT > & _result,
+                               std::vector< IPT > & _result,
                                double &dl, std::stack<IPT> &_stack,
-                               double epsilon = 1.e-5)
+			       Field *bgm,
+                               double epsilon = 5.e-2)
 {
   //  _stack.clear();
   _result.clear();
@@ -78,12 +73,18 @@ double adaptiveTrapezoidalRule(SPoint3 p1 , SPoint3 p2 ,
   SPoint3 dp = p2-p1;
 
   // value of f on both sides
-  double f1 = lc1; //f(p1 + dp*t1,data);
-  double f2 = lc2; //f(p1 + dp*t2,data);
-
+  double f1 = lc1;//GMSHSIZE(p1, bgm, lc1); //f(p1 + dp*t1,data);
+  double f2 = lc2;//GMSHSIZE(p2, bgm, lc2); //f(p1 + dp*t2,data);  
+  
   dl = p1.distance(p2);
 
-  //  printf ("edge length %g lc %g %g\n",dl,f1,f2);
+  //     adim_lenght of half the edge should be bigger than EXCLUSION_FACTOR
+  // +------x--------+
+  
+  if (dl / (2*std::min(lc1,lc2))  <= EXCLUSION_FACTOR){
+    //    printf ("edge length %g lc %g %g\n",dl,f1,f2);
+    return EXCLUSION_FACTOR;
+  }
 
   // add one subsegment on the stack
   IPT top (t1,t2,f1,f2);
@@ -98,40 +99,68 @@ double adaptiveTrapezoidalRule(SPoint3 p1 , SPoint3 p2 ,
     f1 = pp._x3;
     f2 = pp._x4;
     // mid point
-    double t12 = 0.5* (t1+t2);
-    SPoint3 pmid = p1 + dp*t12;
-    double dt = t2-t1;
+    const double t12 = 0.5* (t1+t2);
+    const SPoint3 pmid = p1 + dp*t12;
+    const double dt = t2-t1;
     // average should be compared to mid value
-    double f12 = 0.5* (f1+f2);
-    if (fabs (f12 - 0.5*(f1+f2)) > epsilon*dt ) {
+    //    double f12 = 0.5* (f1+f2);
+    double f12 = GMSHSIZE(pmid, bgm, lc1 + t12 *(lc2-lc1) ); //f(p1 + dp*t2,data);
+    const double AA = dt * dl;
+    const double I1 = AA / f12;
+    const double I2 = 2 * AA / (f1+f2);
+
+    if (fabs (I1 - I2) > epsilon) {
       IPT left  (t1,t12,f1,f12);
       IPT right (t12,t2,f12,f2);
       _stack.push(left);
       _stack.push(right);
     }
     else {
-      _result.push_back (pp);
       // compute the integral using trapezoidal rule on both sides
       totalValue += 1./((0.5*f12+0.25*(f1+f2)))*dt;
+      pp._x5 = totalValue*dl;
+      _result.push_back (pp);
     }
   }
   // take into account the real length of the edge
   totalValue *= dl;
-  //  printf("adimensional length %g\n",totalValue);
+  //  printf("adimensional length %g %d evals\n",totalValue,_result.size() );
   return totalValue;
 }
 
 
-void saturateEdge(Edge &e, std::vector<Vert*> &S,
-                  double (*f)(const SPoint3 &p, void *),
-                  void *data, std::stack<IPT> &temp)
+void saturateEdge(Edge &e, std::vector<Vert*> &S, std::stack<IPT> &temp)
 {
   std::vector< IPT > _result;
   double dl;
   SPoint3 p1 = e.first->point();
   SPoint3 p2 = e.second->point();
+
+  FieldManager *fields = GModel::current()->getFields();
+  Field *bgm = NULL;
+  if(fields->getBackgroundField() > 0){
+    bgm = fields->get(fields->getBackgroundField());
+  }  
+
+  if (1){
+    const double length = p1.distance(p2);
+    const double lc_avg = (e.first->lc() + e.second->lc())*.5;
+    const double l_adim_approx =   length / lc_avg;
+    if (l_adim_approx > 10.){
+      SPoint3 pmid = (p1+p2)*0.5;
+      const double lc = GMSHSIZE(pmid, bgm, lc_avg);
+      S.push_back(new Vert(pmid.x(),pmid.y(),pmid.z(),lc));
+      return;
+    }
+  }
+  
+  //  double _a = Cpu();
+  
   const double dN = adaptiveTrapezoidalRule(p1,p2,e.first->lc(), e.second->lc(),
-                                            f, data, _result, dl, temp);
+                                            _result, dl, temp, bgm);
+  //  _C1 += Cpu() - _a;  
+  //  _a = Cpu();
+
   const int N = (int) (dN+0.1);
   const double interval = dN/N;
   double L = 0.0;
@@ -139,33 +168,40 @@ void saturateEdge(Edge &e, std::vector<Vert*> &S,
   // printf("edge length %g %d intervals of size %g (%d results)\n",
   //        dl,N,interval,_result.size());
   const unsigned int Nr = _result.size();
+  double _f = interval;
   for (unsigned int i=0; i< Nr ; i++) {
     const IPT & rr = _result[i];
     const double t1 = rr._x1;
     const double t2 = rr._x2;
     const double f1 = rr._x3;
     const double f2 = rr._x4;
+    const double l1 = rr._x3;
+    const double l2 = rr._x4;
     const double dL = 2.*(t2-t1) * dl / (f1+f2);
 
+    const double _f1 = i ? _result[i-1]._x5 : 0.0;
+    const double _f2 = rr._x5;
+
     // printf("%g --> %g for %g --> %g\n",L,dL,t1,t2);
-    double L0 = L;
     while (1) {
-      const double t = t1 + (L+interval-L0)*(t2-t1) / dL;
-      if (t >= t2*.999) {
+      const double  t = t1 + (L+interval-_f1)*(t2-t1) / dL;
+      if (t >=  t2*.999) {
 	break;
       }
       else {
 	// printf("%g ",t);
 	SPoint3 p = p1 * (1.-t) + p2*t;
-	double lc = e.first->lc() * (1.-t) + e.second->lc()*t;
-	const double dx = 0;//1.e-12 * (double) rand() / RAND_MAX;
-	const double dy = 0;//1.e-12 * (double) rand() / RAND_MAX;
-	const double dz = 0;//1.e-12 * (double) rand() / RAND_MAX;
+	const double lc = l1 + (_f-_f1)*(l2-l1) / (_f2-_f1);
+        const double dx = 0;//lc * 1.e-12 * (double) rand() / RAND_MAX;
+        const double dy = 0;//lc * 1.e-12 * (double) rand() / RAND_MAX;
+        const double dz = 0;//lc * 1.e-12 * (double) rand() / RAND_MAX;
 	S.push_back(new Vert(p.x()+dx,p.y()+dy,p.z()+dz,lc));
 	L += interval;
+        _f += interval;
       }
     }
   }
+  //  _C2 += Cpu() - _a;  
   //  printf(" press enter\n");
   //  getchar();
   //  printf("%d points added\n",S.size());
@@ -176,11 +212,11 @@ void saturateEdge(Edge &e, std::vector<Vert*> &S,
 void saturateEdges(edgeContainer &ec,
                    tetContainer &T,
                    int nbThreads,
-                   std::vector<Vert*> &S,
-                   double (*f)(const SPoint3 &p, void *), void *data)
+                   std::vector<Vert*> &S)
 {
+  //  _C1 = 0;
+  //  _C2 = 0;
   std::stack<IPT> temp;
-  AVGSEARCH= 0;
   // FIXME
   const int N = T.size(0);
   for (int i=0;i<N;i++){
@@ -191,16 +227,17 @@ void saturateEdges(edgeContainer &ec,
 	Edge ed = t->getEdge(iEdge);
 	bool isNew = ec.addNewEdge(ed);
 	if (isNew){
-	  saturateEdge (ed, S, f, data, temp);
+	  //	  saturateEdge_A_LA_FACON_PaulLouis(ed, S);
+	  saturateEdge (ed, S, temp);
 	}
       }
     }
   }
+  //  printf("timings %12.5E  %12.5E\n",_C1,_C2);
 }
 
 // F I L T E R I N G
 
-#define SQR(X) (X)*(X)
 
 class volumePointWithExclusionRegion {
 public :
@@ -209,8 +246,7 @@ public :
 
   inline bool inExclusionZone (volumePointWithExclusionRegion *p) const
   {
-    const double FACTOR = 0.8;
-    const double K = FACTOR*p->_v->lc();
+    const double K = EXCLUSION_FACTOR*p->_v->lc();
     const double d =
       SQR(p->_v->x() - _v->x())+
       SQR(p->_v->y() - _v->y())+
@@ -269,9 +305,7 @@ public:
 
 void filterVertices(const int numThreads,
                     vertexFilter &_filter,
-                    std::vector<Vert*> &add,
-                    double (*f)(const SPoint3 &p, void *),
-                    void *data)
+                    std::vector<Vert*> &add)
 {
   std::vector<int> indices;
   SortHilbert(add, indices);
@@ -307,11 +341,6 @@ void filterVertices(const int numThreads,
   }
 }
 
-double _fx (const SPoint3 &p, void *)
-{
-  return fabs(0.0125 + .02*p.x());
-}
-
 /*
 static void _print (const char *name, std::vector<Vert*> &T)
 {
@@ -338,7 +367,7 @@ void computeAdjacencies (Tet *t, int iFace, connSet &faceToTet)
   else{
     t->T[iFace] = it->t;
     it->t->T[it->i] =t;
-    faceToTet.erase(it);
+    //    faceToTet.erase(it);
   }
 }
 
@@ -348,12 +377,92 @@ bool edgeSwaps(tetContainer &T, int myThread)
   return false;
 }
 
+void updateSize (MVertex *v, std::map<MVertex*, double> &s, double d){
+  d = std::max(d,  CTX::instance()->mesh.lcMin);
+  d = std::min(d,  CTX::instance()->mesh.lcMax);
+  std::map<MVertex*, double>::iterator it = s.find(v);
+  if (it == s.end())s[v]=d;
+  else it->second = std::min(it->second, d);
+}
+
+void createEmbeddedEdges (GRegion *gr,
+			  edgeContainer &embedded,
+			  std::vector<Vert *> &_vertices){
+  std::list<GEdge*> e = gr->embeddedEdges();
+  for (std::list<GEdge*>::iterator it = e.begin() ; it != e.end(); ++it){
+    for (unsigned int i = 0; i < (*it)->lines.size(); i++){
+      Vert *v0 = _vertices[(*it)->lines[i]->getVertex(0)->getIndex()];
+      Vert *v1 = _vertices[(*it)->lines[i]->getVertex(1)->getIndex()];
+      Edge e (v0,v1);
+      embedded.addNewEdge(e);
+    }
+  }
+}
+
+
+void disconnectEmbeddedFaces (GRegion *gr, connSet &faceToTet, std::vector<Vert *> &_vertices){
+  std::list<GFace*> f = gr->embeddedFaces();
+  for (std::list<GFace*>::iterator it = f.begin() ; it != f.end(); ++it){
+    for (unsigned int i = 0; i < (*it)->triangles.size(); i++){
+      bool ok1 = false;
+      bool ok2 = false;
+      Vert *v0 = _vertices[(*it)->triangles[i]->getVertex(0)->getIndex()];
+      Vert *v1 = _vertices[(*it)->triangles[i]->getVertex(1)->getIndex()];
+      Vert *v2 = _vertices[(*it)->triangles[i]->getVertex(2)->getIndex()];
+      Face f (v0,v1,v2);
+      conn c(f,0,NULL);
+      connSet::iterator itf = faceToTet.find(c);
+      if (itf != faceToTet.end()){
+	Tet *t1 = itf->t;
+	Tet *t2 = itf->t->T[itf->i];
+	//	if (!(f == t1->getFace(itf->i)))printf("aie\n");
+	for (int k=0;k<4;k++){	  
+	  if (t1 && t1->T[k] == t2){t1->T[k]=NULL;ok1=true;}
+	  if (t2 && t2->T[k] == t1){t2->T[k]=NULL;ok2=true;}
+	}
+	if (!ok1 || !ok2)printf("oops %d %d %p %p\n",ok1,ok2,t1,t2);
+      }
+      else printf("oops2\n");
+    }
+  }
+}
+
+void computeMeshSizes (GRegion *gr, std::map<MVertex*, double> &s){
+  std::list<GEdge*> e = gr->embeddedEdges();
+  for (std::list<GEdge*>::iterator it = e.begin() ; it != e.end(); ++it){
+    for (unsigned int i = 0; i < (*it)->lines.size(); i++){
+      double d = distance((*it)->lines[i]->getVertex(0), (*it)->lines[i]->getVertex(1));
+      updateSize ((*it)->lines[i]->getVertex(0), s, d);      
+      updateSize ((*it)->lines[i]->getVertex(1), s, d);      
+    }
+  }
+  std::list<GFace*> f ;
+  std::list<GFace*> f1 = gr->faces();
+  std::list<GFace*> f2 = gr->embeddedFaces();
+  f.insert(f.end(),f1.begin(), f1.end());
+  f.insert(f.end(),f2.begin(), f2.end());
+  for (std::list<GFace*>::iterator it = f.begin() ; it != f.end(); ++it){
+    for (unsigned int i = 0; i < (*it)->triangles.size(); i++){
+      for (unsigned int j = 0; j < 3; j++){
+	double d = distance((*it)->triangles[i]->getVertex(j), (*it)->triangles[i]->getVertex((j+1)%3));
+	updateSize ((*it)->triangles[i]->getVertex(j), s, d);
+	updateSize ((*it)->triangles[i]->getVertex((j+1)%3), s, d);
+      }
+    }
+  }    
+}
+
 void edgeBasedRefinement(const int numThreads,
                          const int nptsatonce,
                          GRegion *gr)
 {
   // fill up old Datastructures
 
+  edgeContainer embeddedEdges (10000);
+  
+  std::map<MVertex*, double> sizes;
+  computeMeshSizes (gr, sizes);  
+  
   tetContainer allocator (numThreads,1000000);
 
   SBoundingBox3d bb;
@@ -383,7 +492,10 @@ void edgeBasedRefinement(const int numThreads,
     for (std::set<MVertex*>::iterator it = all.begin();it !=all.end(); ++it){
       MVertex *mv = *it;
       mv->setIndex(counter);
-      Vert *v = new Vert (mv->x(),mv->y(),mv->z(),1.e22, counter);
+      double size = CTX::instance()->mesh.lcMax;
+      std::map<MVertex*,double>::iterator itv = sizes.find(mv);
+      if (itv != sizes.end())size = itv->second;
+      Vert *v = new Vert (mv->x(),mv->y(),mv->z(),size, counter);
       _vertices[counter] = v;
       bb += SPoint3(v->x(),v->y(),v->z());
       _ma[v] = mv;
@@ -408,9 +520,12 @@ void edgeBasedRefinement(const int numThreads,
 	delete tt;
       }
       T.clear();
+      disconnectEmbeddedFaces (gr, faceToTet, _vertices);
+      createEmbeddedEdges (gr, embeddedEdges, _vertices);
     }
   }
 
+
   // do not allow to saturate boundary edges
   {
     for (unsigned int i=0;i< allocator.size(0);i++) {
@@ -421,36 +536,22 @@ void edgeBasedRefinement(const int numThreads,
 	  for (int k=0;k<3;k++){
 	    Vert *vi = f.V[k];
 	    Vert *vj = f.V[(k+1)%3];
-	    double l = sqrt ((vi->x()-vj->x())*(vi->x()-vj->x())+
-			     (vi->y()-vj->y())*(vi->y()-vj->y())+
-			     (vi->z()-vj->z())*(vi->z()-vj->z()));
 	    ec.addNewEdge(Edge(vi,vj));
-	    vi->lc() = std::min (l,vi->lc() );
-	    vj->lc() = std::min (l,vj->lc() );
 	  }
 	}
       }
     }
-    for (unsigned int i=0;i< allocator.size(0);i++) {
-      Tet  *tt = allocator (0,i);
-      for (int j=0;j<6;j++){
-	Edge e = tt->getEdge(j);
-	if(e.first->lc() == 1.e22){/*printf("coucou\n");*/e.first->lc() = e.second->lc();}
-	else if(e.second->lc() == 1.e22){/*printf("coucou\n");*/e.second->lc() = e.first->lc();}
-      }
-    }
   }
 
   std::vector<Vert*> add_all;
   {
-    //   vertexFilter _filter (bb, 20);
+    //    vertexFilter _filter (bb, 20);
     vertexFilter _filter;
     for (unsigned int i=0;i<_vertices.size();i++){
       _filter.insert( _vertices[i] );
     }
 
     int iter = 1;
-
     Msg::Info("------------------------------------- SATUR FILTR SORTH DELNY TIME  TETS");
 
     double __t__ = Cpu();
@@ -458,9 +559,12 @@ void edgeBasedRefinement(const int numThreads,
     while(1){
       std::vector<Vert*> add;
       double t1 = Cpu();
-      saturateEdges (ec, allocator, numThreads, add, _fx, NULL);
+      //      C_COUNT = 0;
+      saturateEdges (ec, allocator, numThreads, add);
+      //      printf("%d calls %d points added",C_COUNT,add.size());
       double t2 = Cpu();
-      filterVertices (numThreads, _filter, add, _fx, NULL);
+      filterVertices (numThreads, _filter, add);
+      //      printf(" %d points remain\n",add.size());
       double t3 = Cpu();
       if (add.empty())break;
       // randomize vertices (EXTREMELY IMPORTANT FOR NOT DETERIORATING PERFORMANCE)
@@ -469,7 +573,7 @@ void edgeBasedRefinement(const int numThreads,
       std::vector<int> indices;
       SortHilbert(add, indices);
       double t4 = Cpu();
-      delaunayTrgl (1,1,add.size(), &add,allocator,1.e-28);
+      delaunayTrgl (1,1,add.size(), &add,allocator,embeddedEdges.empty() ? NULL : &embeddedEdges);
       double t5 = Cpu();
       add_all.insert (add_all.end(), add.begin(), add.end());
       Msg::Info("IT %3d %8d points added, timings %5.2f %5.2f %5.2f %5.2f %5.2f %5d",
diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp
index d689a6656879f4504bf93bcaa909e98cf2bc0d48..f11748bdc53e8c4847356b91136fb06b2716b833 100644
--- a/Mesh/meshGEdge.cpp
+++ b/Mesh/meshGEdge.cpp
@@ -543,8 +543,14 @@ void meshGEdge::operator() (GEdge *ge)
     return;
   }
 
-  Msg::Info("Meshing curve %d (%s)", ge->tag(), ge->getTypeString().c_str());
-
+  if (ge->model()->getNumEdges() > 1000){    
+    if (ge->tag() % 1000 == 1){
+      Msg::Info("Meshing curve %d/%d (%s)", ge->tag(), ge->model()->getNumEdges(), ge->getTypeString().c_str());
+      }
+  }
+  else {
+    Msg::Info("Meshing curve %d (%s)", ge->tag(), ge->getTypeString().c_str());
+  }
   // compute bounds
   Range<double> bounds = ge->parBounds(0);
   double t_begin = bounds.low();
@@ -576,7 +582,7 @@ void meshGEdge::operator() (GEdge *ge)
   int N;
   int filterMinimumN = 1;
   if(length == 0. && CTX::instance()->mesh.toleranceEdgeLength == 0.){
-    Msg::Warning("Curve %d has a zero length", ge->tag());
+    Msg::Debug("Curve %d has a zero length", ge->tag());
     a = 0.;
     N = 1;
   }
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index b89bc6a4563af94d77c693c10b0166be7bc866b1..771dd07a3af152be5bd03c04f978e6e65b8424a7 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -1407,8 +1407,9 @@ void bowyerWatsonFrontal(GFace *gf,
                    gf->mesh_vertices.size(), worst->getRadius());
       double newPoint[2], metric[3];
       //optimalPointFrontal (gf,worst,active_edge,Us,Vs,vSizes,vSizesBGM,newPoint,metric);
-      if (optimalPointFrontalB (gf,worst,active_edge,DATA,newPoint,metric))
+      if (optimalPointFrontalB (gf,worst,active_edge,DATA,newPoint,metric)){
 	insertAPoint(gf, AllTris.end(), newPoint, metric, DATA, AllTris, &ActiveTris, worst);
+      }
     }
 
     /*   if(ITER % 1== 0){
@@ -1419,7 +1420,6 @@ void bowyerWatsonFrontal(GFace *gf,
     */
   }
 
-
   nbSwaps = edgeSwapPass(gf, AllTris, SWCR_QUAL, DATA);
   /*
   char name[245];
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index 3b4e541267159e44e5ca61234955c6ef22800a56..eebbf65d53cd63623eb8cb14c7e7eca1fe3b9fd2 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -43,6 +43,8 @@
 #include "ANN/ANN.h"
 #endif
 
+
+
 // hybrid mesh recovery structure
 class splitQuadRecovery {
   std::multimap<GEntity*, std::pair<MVertex*,MFace> >_data;
@@ -639,9 +641,9 @@ void MeshDelaunayVolumeTetgen(std::vector<GRegion*> &regions)
 
   // now do insertion of points
   if(CTX::instance()->mesh.algo3d == ALGO_3D_FRONTAL_DEL)
-    bowyerWatsonFrontalLayers(gr, false);
+    Msg::Error ("Frontal Layers Algo deprecated");
   else if(CTX::instance()->mesh.algo3d == ALGO_3D_FRONTAL_HEX)
-    bowyerWatsonFrontalLayers(gr, true);
+    Msg::Error ("Frontal Layers Algo deprecated");
   else if(CTX::instance()->mesh.algo3d == ALGO_3D_MMG3D){
     refineMeshMMG(gr);
   }
@@ -652,6 +654,7 @@ void MeshDelaunayVolumeTetgen(std::vector<GRegion*> &regions)
       insertVerticesInRegion(gr,2000000000,true);
     }
   }
+  
   // crete an initial mesh
   if (sqr.buildPyramids (gr->model())){
     RelocateVertices(regions, 3);
diff --git a/Mesh/meshGRegionBoundaryRecovery.cpp b/Mesh/meshGRegionBoundaryRecovery.cpp
index 2fd2c789db56a30005f6ba91f52c4d91d897e32f..55ccb56ac340b71d2fdcf76c6028fd95530495f3 100644
--- a/Mesh/meshGRegionBoundaryRecovery.cpp
+++ b/Mesh/meshGRegionBoundaryRecovery.cpp
@@ -425,8 +425,11 @@ bool tetgenmesh::reconstructmesh(void *p)
     // Construct a map from points to subfaces.
     makepoint2submap(subfaces, idx2shlist, shperverlist);
 
+    //    printf("coucou1\n");
+    
     // Process the set of PSC edges.
     // Remeber that all segments have default marker '-1'.
+    //    int COUNTER = 0;
     for (std::list<GEdge*>::iterator it = e_list.begin(); it != e_list.end();
 	 ++it) {
       GEdge *ge = *it;
@@ -480,7 +483,7 @@ bool tetgenmesh::reconstructmesh(void *p)
 	  // It is a dangling segment (not belong to any facets).
 	  // Check if segment [p[0],p[1]] already exists.
 	  // TODO: Change the brute-force search. Slow!
-	  point *ppt;
+	  /*	  point *ppt;
 	  subsegs->traversalinit();
 	  segloop.sh = shellfacetraverse(subsegs);
 	  while (segloop.sh != NULL) {
@@ -492,7 +495,7 @@ bool tetgenmesh::reconstructmesh(void *p)
 	      break;
 	    }
 	    segloop.sh = shellfacetraverse(subsegs);
-	  }
+	    }*/
 	  if (newseg.sh == NULL) {
 	    makeshellface(subsegs, &newseg);
 	    setshvertices(newseg, p[0], p[1], NULL);
@@ -522,9 +525,12 @@ bool tetgenmesh::reconstructmesh(void *p)
   // Boundary recovery.
 
   clock_t t;
+  //    printf("coucou2\n");
   recoverboundary(t);
+  //    printf("coucou3\n");
 
   carveholes();
+  //    printf("coucou4\n");
 
   if (subvertstack->objects > 0l) {
     suppresssteinerpoints();
diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp
index eedd1c829ff628d9c58eff060831954fb91ce770..e6054d0a4e47112439a3004ca6b5dc3baf057d7f 100644
--- a/Mesh/meshGRegionDelaunayInsertion.cpp
+++ b/Mesh/meshGRegionDelaunayInsertion.cpp
@@ -22,7 +22,6 @@
 #include "MLine.h"
 
 int MTet4::radiusNorm = 2;
-static double LIMIT_ = 1;
 
 static void createAllEmbeddedEdges (GRegion *gr, std::set<MEdge, Less_Edge> &allEmbeddedEdges)
 {
@@ -45,18 +44,6 @@ static void createAllEmbeddedFaces (GRegion *gr, std::set<MFace, Less_Face> &all
   }
 }
 
-static bool isActive(MTet4 *t, double limit_, int &active)
-{
-  if (t->isDeleted()) return false;
-  for (active = 0; active < 4; active++){
-    MTet4 *neigh = t->getNeigh(active);
-    if (!neigh || (neigh->getRadius() < limit_ && neigh->getRadius() > 0)) {
-      return true;
-    }
-  }
-  return false;
-}
-
 
 int MTet4::inCircumSphere(const double *p) const
 {
@@ -90,33 +77,29 @@ struct faceXtet{
     MVertex *v1 = t1->tet()->getVertex(faces[iFac][1]);
     MVertex *v2 = t1->tet()->getVertex(faces[iFac][2]);
 
-    unsorted[0] = v0;
-    unsorted[1] = v1;
-    unsorted[2] = v2;
-
-    v[0] = std::min(std::min(v0,v1),v2);
-    v[2] = std::max(std::max(v0,v1),v2);
-    v[1] = (v0 != v[0] && v0 != v[2]) ? v0 : (v1 != v[0] && v1 != v[2]) ? v1 : v2;
-    //
-    //    std::sort(v, v + 3);
+    unsorted[0] = v[0] = v0;
+    unsorted[1] = v[1] = v1;
+    unsorted[2] = v[2] = v2;
+    MVertexLessThanNum lll;
+    std::sort(v, v + 3, lll);
   }
 
   inline MVertex * getVertex (int i) const { return unsorted[i];}
 
  inline bool operator < (const faceXtet & other) const
   {
-    if (v[0] < other.v[0]) return true;
-    if (v[0] > other.v[0]) return false;
-    if (v[1] < other.v[1]) return true;
-    if (v[1] > other.v[1]) return false;
-    if (v[2] < other.v[2]) return true;
+    if (v[0]->getNum() < other.v[0]->getNum()) return true;
+    if (v[0]->getNum() > other.v[0]->getNum()) return false;
+    if (v[1]->getNum() < other.v[1]->getNum()) return true;
+    if (v[1]->getNum() > other.v[1]->getNum()) return false;
+    if (v[2]->getNum() < other.v[2]->getNum()) return true;
     return false;
   }
   inline bool operator == (const faceXtet & other) const
   {
-    return (v[0] == other.v[0] &&
-	    v[1] == other.v[1] &&
-	    v[2] == other.v[2] );
+    return (v[0]->getNum() == other.v[0]->getNum() &&
+	    v[1]->getNum() == other.v[1]->getNum() &&
+	    v[2]->getNum() == other.v[2]->getNum() );
   }
   bool visible (MVertex *v){
     MVertex* v0 = t1->tet()->getVertex(faces[i1][0]);
@@ -184,35 +167,6 @@ void connectTets(ITER beg, ITER end, std::set<MFace, Less_Face> *allEmbeddedFace
 }
 
 
-static void updateActiveFaces(MTet4 *t, double limit_, std::set<MFace,Less_Face> &front)
-{
-  if (t->isDeleted()) return;
-  for (int active = 0; active < 4; active++){
-    MTet4 *neigh = t->getNeigh(active);
-    if (!neigh || (neigh->getRadius() < limit_ && neigh->getRadius() > 0)) {
-      faceXtet fxt (t,active);
-      MFace me (fxt.v[0],fxt.v[1],fxt.v[2]);
-      front.insert(me);
-    }
-  }
-}
-
-static bool isActive(MTet4 *t, double limit_, int &i, std::set<MFace,Less_Face> *front)
-{
-  if (t->isDeleted()) return false;
-  for (i = 0; i < 4; i++){
-    MTet4 *neigh = t->getNeigh(i);
-    if (!neigh || (neigh->getRadius() < limit_ && neigh->getRadius() > 0)) {
-      faceXtet fxt (t,i);
-      MFace me (fxt.v[0],fxt.v[1],fxt.v[2]);
-      if(front->find(me) != front->end()){
-	return true;
-      }
-    }
-  }
-  return false;
-}
-
 void connectTets(std::list<MTet4*> &l) { connectTets(l.begin(), l.end()); }
 void connectTets(std::vector<MTet4*> &l) { connectTets(l.begin(), l.end()); }
 
@@ -367,25 +321,17 @@ void printTets (const char *fn, std::list<MTet4*> &cavity, bool force = false )
 bool insertVertexB(std::list<faceXtet> &shell,
 		   std::list<MTet4*> &cavity,
 		   MVertex *v,
+		   double lc1,
+		   double lc2,
+		   std::vector<double> &vSizes,
+		   std::vector<double> &vSizesBGM,
 		   MTet4 *t,
 		   MTet4Factory &myFactory,
-		   std::set<MTet4*,compareTet4Ptr> &allTets,
-		   std::vector<double> & vSizes,
-		   std::vector<double> & vSizesBGM,
-		   std::set<MTet4*,compareTet4Ptr> *activeTets = 0 )
+		   std::set<MTet4*,compareTet4Ptr> &allTets)
 {
   std::vector<faceXtet> conn;
   std::vector<MTet4*> new_cavity;
-  // check that volume is conserved
-    double newVolume = 0;
-    double oldVolume = 0;
 
-  std::list<MTet4*>::iterator ittet = cavity.begin();
-  std::list<MTet4*>::iterator ittete = cavity.end();
-    while (ittet != ittete){
-      oldVolume += fabs((*ittet)->getVolume());
-      ++ittet;
-    }
 
   MTet4** newTets = new MTet4*[shell.size()];
   int k = 0;
@@ -395,31 +341,18 @@ bool insertVertexB(std::list<faceXtet> &shell,
   bool onePointIsTooClose = false;
   while (it != shell.end()){
     MTetrahedron *tr = new MTetrahedron(it->getVertex(0), it->getVertex(1), it->getVertex(2), v);
-
-        double lc = .25 * (vSizes[tr->getVertex(0)->getIndex()] +
-    		       vSizes[tr->getVertex(1)->getIndex()] +
-    		       vSizes[tr->getVertex(2)->getIndex()] +
-    		       vSizes[tr->getVertex(3)->getIndex()]);
-        double lcBGM = .25 * (vSizesBGM[tr->getVertex(0)->getIndex()] +
-    			  vSizesBGM[tr->getVertex(1)->getIndex()] +
-    			  vSizesBGM[tr->getVertex(2)->getIndex()] +
-    			  vSizesBGM[tr->getVertex(3)->getIndex()]);
-        double LL = std::min(lc, lcBGM);
-
-    MTet4 *t4 = myFactory.Create(tr, vSizes, vSizesBGM);
+    MTet4 *t4 = myFactory.Create(tr, vSizes, vSizesBGM, lc1, lc2);
     t4->setOnWhat(t->onWhat());
 
-    double d1 = sqrt((it->v[0]->x() - v->x()) * (it->v[0]->x() - v->x()) +
-                     (it->v[0]->y() - v->y()) * (it->v[0]->y() - v->y()) +
-                     (it->v[0]->z() - v->z()) * (it->v[0]->z() - v->z()));
-    double d2 = sqrt((it->v[1]->x() - v->x()) * (it->v[1]->x() - v->x()) +
-                     (it->v[1]->y() - v->y()) * (it->v[1]->y() - v->y()) +
-                     (it->v[1]->z() - v->z()) * (it->v[1]->z() - v->z()));
-    double d3 = sqrt((it->v[2]->x() - v->x()) * (it->v[2]->x() - v->x()) +
-                     (it->v[2]->y() - v->y()) * (it->v[2]->y() - v->y()) +
-                     (it->v[2]->z() - v->z()) * (it->v[2]->z() - v->z()));
-
-    if (d1 < LL * .05 || d2 < LL * .05 || d3 < LL * .05) onePointIsTooClose = true;
+    double d1 = distance (it->v[0],v);
+    double d2 = distance (it->v[1],v);
+    double d3 = distance (it->v[2],v);
+    
+    double lc = Extend2dMeshIn3dVolumes() ? std::min(lc1, lc2) : lc2;
+    if (d1 < lc * .05 || d2 < lc * .05 || d3 < lc * .05) {
+      //      printf("coucou %g %g %g %g\n",lc,d1,d2,d3);
+      onePointIsTooClose = true;
+    }
 
     newTets[k++] = t4;
     // all new tets are pushed front in order to ba able to destroy
@@ -431,44 +364,19 @@ bool insertVertexB(std::list<faceXtet> &shell,
 
     if (otherSide)
       new_cavity.push_back(otherSide);
-    //      if (!it->t1->isDeleted())throw;
-        newVolume += fabs(t4->getVolume());
     ++it;
   }
-  // OK, the cavity is star shaped
-  //  if (onePointIsTooClose)printf("One point is too close\n");
-  //if (fabs(oldVolume - newVolume) > 1.e-10 * oldVolume)printf("Volume do not match %22.15E %22.15E %22.15E\n",oldVolume,newVolume,fabs(oldVolume-newVolume)/newVolume);
-  //    if (!onePointIsTooClose){
-      if (fabs(oldVolume - newVolume) < 1.e-10 * oldVolume &&
-	            !onePointIsTooClose){
-	connectTets_vector2(new_cavity,conn);
+  if (!onePointIsTooClose){
+    connectTets_vector2(new_cavity,conn);
     allTets.insert(newTets, newTets + shell.size());
-
-    if (activeTets){
-      for (std::vector<MTet4*>::iterator i = new_cavity.begin(); i != new_cavity.end(); ++i){
-        int active_face;
-        if(isActive(*i, LIMIT_, active_face) && (*i)->getRadius() > LIMIT_){
-          if ((*activeTets).find(*i) == (*activeTets).end())
-            (*activeTets).insert(*i);
-        }
-      }
-    }
-
     delete [] newTets;
-
     return true;
   }
-  else { // The cavity is NOT star shaped
-    //    printf("hola %d %g %g %22.15E\n",onePointIsTooClose, oldVolume, newVolume, 100.*fabs(oldVolume - newVolume) / oldVolume);
-    //    new_cavity.clear();
-    //    for (unsigned int i = 0; i <shell.size(); i++) new_cavity.push_back(newTets[i]);
-    //    printTets ("oldCavity.pos",cavity,true);
-    //    printTets ("newCavity.pos",new_cavity);
-    //    Msg::Fatal("");
+  else /* one point is too close */ {
     for (unsigned int i = 0; i <shell.size(); i++) myFactory.Free(newTets[i]);
     delete [] newTets;
-    ittet = cavity.begin();
-    ittete = cavity.end();
+    std::list<MTet4*>::iterator ittet = cavity.begin();
+    std::list<MTet4*>::iterator ittete = cavity.end();
     while(ittet != ittete){
       (*ittet)->setDeleted(false);
       ++ittet;
@@ -477,24 +385,8 @@ bool insertVertexB(std::list<faceXtet> &shell,
   }
 }
 
-bool insertVertex(MVertex *v,
-                  MTet4 *t,
-                  MTet4Factory &myFactory,
-                  std::set<MTet4*,compareTet4Ptr> &allTets,
-		  std::vector<double> & vSizes,
-                  std::vector<double> & vSizesBGM,
-		  std::set<MTet4*,compareTet4Ptr> *activeTets = 0 )
-{
-  std::list<faceXtet> shell;
-  std::list<MTet4*> cavity;
-
-  findCavity(shell, cavity, v, t);
-
-  return insertVertexB(shell,cavity,v,t,myFactory,allTets,vSizes,vSizesBGM,activeTets);
-}
-
-static void setLcs(MTriangle *t, std::map<MVertex*, double> &vSizes,
-                   std::set<MVertex*> &bndVertices)
+static void setLcs(MTriangle *t, std::map<MVertex*, double, MVertexLessThanNum> &vSizes,
+                   std::set<MVertex*,MVertexLessThanNum> &bndVertices)
 {
 
   for(int i = 0; i < 3; i++){
@@ -506,8 +398,8 @@ static void setLcs(MTriangle *t, std::map<MVertex*, double> &vSizes,
     double dy = vi->y()-vj->y();
     double dz = vi->z()-vj->z();
     double l = sqrt(dx * dx + dy * dy + dz * dz);
-    std::map<MVertex*,double>::iterator iti = vSizes.find(vi);
-    std::map<MVertex*,double>::iterator itj = vSizes.find(vj);
+    std::map<MVertex*,double, MVertexLessThanNum>::iterator iti = vSizes.find(vi);
+    std::map<MVertex*,double, MVertexLessThanNum>::iterator itj = vSizes.find(vj);
     // use largest edge length
     if (iti == vSizes.end() || iti->second < l) vSizes[vi] = l;
     if (itj == vSizes.end() || itj->second < l) vSizes[vj] = l;
@@ -539,8 +431,8 @@ static void setLcs(MTriangle *t, std::map<MVertex*, double> &vSizes,
   */
 }
 
-static void setLcs(MTetrahedron *t, std::map<MVertex*, double> &vSizes,
-                   std::set<MVertex*> &bndVertices)
+static void setLcs(MTetrahedron *t, std::map<MVertex*, double,MVertexLessThanNum> &vSizes,
+                   std::set<MVertex*,MVertexLessThanNum> &bndVertices)
 {
   for (int i = 0; i < 4; i++){
     for (int j = i + 1; j < 4; j++){
@@ -550,10 +442,10 @@ static void setLcs(MTetrahedron *t, std::map<MVertex*, double> &vSizes,
       double dy = vi->y()-vj->y();
       double dz = vi->z()-vj->z();
       double l = sqrt(dx * dx + dy * dy + dz * dz);
-      std::map<MVertex*,double>::iterator iti = vSizes.find(vi);
-      std::map<MVertex*,double>::iterator itj = vSizes.find(vj);
-      std::set<MVertex*>::iterator itvi = bndVertices.find(vi);
-      std::set<MVertex*>::iterator itvj = bndVertices.find(vj);
+      std::map<MVertex*,double,MVertexLessThanNum>::iterator iti = vSizes.find(vi);
+      std::map<MVertex*,double,MVertexLessThanNum>::iterator itj = vSizes.find(vj);
+      std::set<MVertex*,MVertexLessThanNum>::iterator itvi = bndVertices.find(vi);
+      std::set<MVertex*,MVertexLessThanNum>::iterator itvj = bndVertices.find(vj);
       // smallest tet edge
       if (itvi == bndVertices.end() &&
           (iti == vSizes.end() || iti->second > l)) vSizes[vi] = l;
@@ -886,7 +778,7 @@ void optimizeMesh(GRegion *gr, const qmTetrahedron::Measures &qm)
         double qq = (*it)->getQuality();
         if (qq < qMin){
           for (int i = 0; i < 4; i++){
-            if (faceSwap(newTets, *it, i, qm)){
+            if (0 && faceSwap(newTets, *it, i, qm)){
               nbFSwap++;
               break;
             }
@@ -1138,8 +1030,8 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
   createAllEmbeddedEdges (gr, allEmbeddedEdges);
 
   { // leave this in a block so the map gets deallocated directly
-    std::map<MVertex*, double> vSizesMap;
-    std::set<MVertex*> bndVertices;
+    std::map<MVertex*, double,MVertexLessThanNum> vSizesMap;
+    std::set<MVertex*,MVertexLessThanNum> bndVertices;
 
     std::set<MEdge, Less_Edge>::iterator it = allEmbeddedEdges.begin();
     while (it != allEmbeddedEdges.end()){
@@ -1149,8 +1041,8 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
       double dy = vi->y()-vj->y();
       double dz = vi->z()-vj->z();
       double l = sqrt(dx * dx + dy * dy + dz * dz);
-      std::map<MVertex*,double>::iterator iti = vSizesMap.find(vi);
-      std::map<MVertex*,double>::iterator itj = vSizesMap.find(vj);
+      std::map<MVertex*,double,MVertexLessThanNum>::iterator iti = vSizesMap.find(vi);
+      std::map<MVertex*,double,MVertexLessThanNum>::iterator itj = vSizesMap.find(vj);
       // smallest tet edge
       if (iti == vSizesMap.end() || iti->second > l) vSizesMap[vi] = l;
       if (itj == vSizesMap.end() || itj->second > l) vSizesMap[vj] = l;
@@ -1165,7 +1057,7 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
     }
     for(unsigned int i = 0; i < gr->tetrahedra.size(); i++)
       setLcs(gr->tetrahedra[i], vSizesMap, bndVertices);
-    for(std::map<MVertex*, double>::iterator it = vSizesMap.begin();
+    for(std::map<MVertex*, double, MVertexLessThanNum>::iterator it = vSizesMap.begin();
         it != vSizesMap.end(); ++it){
       it->first->setIndex(NUM++);
       vSizes.push_back(it->second);
@@ -1245,6 +1137,7 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
 
   double t1 = Cpu();
   // MAIN LOOP IN DELAUNAY INSERTION STARTS HERE
+
   while(1){
     if (COUNT_MISS_2 > 100000)break;
     if (ITER >= maxVert)break;
@@ -1281,8 +1174,9 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
 		      base->getVertex(3)->y(),
 		      base->getVertex(3)->z()};
 
-      tetcircumcenter(pa,pb,pc,pd, center,&uvw[0],&uvw[1],&uvw[2] );
-
+      tetcircumcenter(pa,pb,pc,pd, center, NULL, NULL, NULL);
+      
+      
       //// A TEST !!!
       std::list<faceXtet> shell;
       std::list<MTet4*> cavity;
@@ -1325,14 +1219,18 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
 	  NB_CORRECTION_OF_CAVITY ++;
 	  if(!isCavityCompatibleWithEmbeddedEdges(cavity, shell, allEmbeddedEdges)){
 	    correctedCavityIncompatibleWithEmbeddedEdge = true;
-	    //	    printf("ARGH\n");
 	  }
 	}
-	//	    printTets ("after.pos", cavity, true);
-	// compute mesh spacing there
-	if(correctedCavityIncompatibleWithEmbeddedEdge || !starShaped || !insertVertexB(shell,cavity,v, worst, myFactory, allTets, vSizes,vSizesBGM)){
+	double lc1 =
+	  (1 - uvw[0] - uvw[1] - uvw[2]) * vSizes[worst->tet()->getVertex(0)->getIndex()] +
+	  uvw[0] * vSizes[worst->tet()->getVertex(1)->getIndex()] +
+	  uvw[1] * vSizes[worst->tet()->getVertex(2)->getIndex()] +
+	  uvw[2] * vSizes[worst->tet()->getVertex(3)->getIndex()];
+	double lc2 = BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]);
+
+	
+	if(correctedCavityIncompatibleWithEmbeddedEdge || !starShaped || !insertVertexB(shell,cavity,v, lc1, lc2, vSizes, vSizesBGM, worst, myFactory, allTets)){
 	  COUNT_MISS_1++;
-	  //	  printf("coucou 1 %d %d\n",correctedCavityIncompatibleWithEmbeddedEdge, starShaped);
 	  myFactory.changeTetRadius(allTets.begin(), 0.);
 	  for (std::list<MTet4*>::iterator itc = cavity.begin(); itc != cavity.end(); ++itc)
 	    (*itc)->setDeleted(false);
@@ -1340,16 +1238,8 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
 	  NUM--;
 	}
 	else{
-	//}
-	  double lc1 =
-	    (1 - uvw[0] - uvw[1] - uvw[2]) * vSizes[worst->tet()->getVertex(0)->getIndex()] +
-	    uvw[0] * vSizes[worst->tet()->getVertex(1)->getIndex()] +
-	    uvw[1] * vSizes[worst->tet()->getVertex(2)->getIndex()] +
-	    uvw[2] * vSizes[worst->tet()->getVertex(3)->getIndex()];
-	  double lc = BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]);
-	  // double lc = std::min(lc1, BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]));
 	  vSizes.push_back(lc1);
-	  vSizesBGM.push_back(lc);
+	  vSizesBGM.push_back(lc2);
 	  REALCOUNT++;
 	  v->onWhat()->mesh_vertices.push_back(v);
 	}
@@ -1409,222 +1299,6 @@ void insertVerticesInRegion (GRegion *gr, int maxVert, bool _classify)
   }
 }
 
-MVertex * optimalPointFrontal(GRegion *gr,
-                              MTet4 *worst,
-                              int active_face,
-                              std::vector<double> &vSizes,
-                              std::vector<double> &vSizesBGM)
-{
-  double centerTet[3], centerFace[3];
-  faceXtet fxt ( worst, active_face );
-  double pa[3] = {fxt.v[0]->x(),fxt.v[0]->y(),fxt.v[0]->z()};
-  double pb[3] = {fxt.v[1]->x(),fxt.v[1]->y(),fxt.v[1]->z()};
-  double pc[3] = {fxt.v[2]->x(),fxt.v[2]->y(),fxt.v[2]->z()};
-  circumCenterXYZ(pa, pb, pc, centerFace);
-  worst->circumcenter(centerTet);
-
-  SVector3 dir (centerTet[0] - centerFace[0],
-		centerTet[1] - centerFace[1],
-		centerTet[2] - centerFace[2]);
-  dir.normalize();
-
-  SVector3 rDir (pa[0] - centerFace[0],
-		 pa[1] - centerFace[1],
-		 pa[2] - centerFace[2]);
-
-  //  const double a = 2*p *3 /sqrt(3);
-  const double a = .025;
-  const double tt = a*sqrt(6.)/3;
-
-  MVertex *vert = new MVertex(centerFace[0] + tt * dir[0],
-			      centerFace[1] + tt * dir[1],
-			      centerFace[2] + tt * dir[2],
-			      gr);
-  return vert;
-}
-
-
-void bowyerWatsonFrontalLayers(GRegion *gr, bool hex)
-{
-  std::vector<double> vSizes;
-  std::vector<double> vSizesBGM;
-  MTet4Factory myFactory(1600000);
-  std::set<MTet4*, compareTet4Ptr> &allTets = myFactory.getAllTets();
-  std::set<MTet4*, compareTet4Ptr> activeTets;
-  int NUM = 0;
-
-//  if (!backgroundMesh::current()) {
-//    // TODO !!!
-//  }
-
-  if (hex){
-    LIMIT_ = sqrt(2.) * .99;
-    MTet4::radiusNorm =-1;
-  }
-
-  { // leave this in a block so the map gets deallocated directly
-    std::map<MVertex*, double> vSizesMap;
-    std::set<MVertex*> bndVertices;
-    for(GModel::fiter it = gr->model()->firstFace(); it != gr->model()->lastFace(); ++it){
-      GFace *gf = *it;
-      for(unsigned int i = 0; i < gf->triangles.size(); i++){
-        setLcs(gf->triangles[i], vSizesMap, bndVertices);
-      }
-    }
-    for(unsigned int i = 0; i < gr->tetrahedra.size(); i++)
-      setLcs(gr->tetrahedra[i], vSizesMap, bndVertices);
-    for(std::map<MVertex*, double>::iterator it = vSizesMap.begin();
-        it != vSizesMap.end(); ++it){
-      it->first->setIndex(NUM++);
-      vSizes.push_back(it->second);
-      vSizesBGM.push_back(it->second);
-    }
-  }
-
-  for(unsigned int i = 0; i < gr->tetrahedra.size(); i++)
-    allTets.insert(myFactory.Create(gr->tetrahedra[i], vSizes,vSizesBGM));
-
-  gr->tetrahedra.clear();
-  connectTets(allTets.begin(), allTets.end());
-
-  fs_cont search;
-  buildFaceSearchStructure(gr->model(), search);
-
-  for(MTet4Factory::iterator it = allTets.begin(); it != allTets.end(); ++it){
-    if(!(*it)->onWhat()){
-      std::list<MTet4*> theRegion;
-      std::set<GFace *> faces_bound;
-      GRegion *bidon = (GRegion*)123;
-      double _t1 = Cpu();
-      Msg::Debug("start with a non classified tet");
-      non_recursive_classify(*it, theRegion, faces_bound, bidon, gr->model(), search);
-      double _t2 = Cpu();
-      Msg::Debug("found %d tets with %d faces (%g sec for the classification)",
-                 theRegion.size(), faces_bound.size(), _t2 - _t1);
-      GRegion *myGRegion = getRegionFromBoundingFaces(gr->model(), faces_bound);
-      // Msg::Info("a region is found %p",myGRegion);
-      if(myGRegion) // a geometrical region associated to the list of faces has been found
-        for(std::list<MTet4*>::iterator it2 = theRegion.begin();
-            it2 != theRegion.end(); ++it2) (*it2)->setOnWhat(myGRegion);
-      else // the tets are in the void
-        for(std::list<MTet4*>::iterator it2 = theRegion.begin();
-            it2 != theRegion.end(); ++it2)(*it2)->setDeleted(true);
-    }
-  }
-  search.clear();
-
-  for(MTet4Factory::iterator it = allTets.begin(); it!=allTets.end(); ++it){
-    (*it)->setNeigh(0, 0);
-    (*it)->setNeigh(1, 0);
-    (*it)->setNeigh(2, 0);
-    (*it)->setNeigh(3, 0);
-  }
-  std::set<MFace, Less_Face> allEmbeddedFaces;
-  createAllEmbeddedFaces (gr, allEmbeddedFaces);
-  connectTets(allTets.begin(),allTets.end(),&allEmbeddedFaces);
-
-  int ITER = 0, active_face;
-
-  std::set<MFace,Less_Face> _front;
-  for(MTet4Factory::iterator it = allTets.begin(); it!=allTets.end(); ++it){
-    if(isActive(*it,LIMIT_,active_face) && (*it)->getRadius() > LIMIT_){
-      activeTets.insert(*it);
-      updateActiveFaces(*it, LIMIT_, _front);
-    }
-    else if ((*it)->getRadius() < LIMIT_)break;
-  }
-
-  // insert points
-  int ITERATION = 1;
-  while (1){
-    if (ITERATION == 8)break;
-    ITERATION ++;
-
-    std::set<MTet4*, compareTet4Ptr> activeTetsNotInFront;
-
-    while (1){
-
-      if (!activeTets.size())break;
-
-      //      printf("%d active tets %d tets\n",activeTets.size(),allTets.size());
-
-      std::set<MTet4*,compareTet4Ptr>::iterator WORST_ITER = activeTets.begin();
-      MTet4 *worst = (*WORST_ITER);
-      if(worst->isDeleted()){
-	activeTets.erase(WORST_ITER);
-	//	myFactory.Free(worst);
-      }
-      else {
-	activeTets.erase(WORST_ITER);
-	if (isActive(worst, LIMIT_, active_face,&_front)  &&
-	    worst->getRadius() > LIMIT_){
-	  //	  printf("worst = %12.5E\n",worst->getRadius());
-
-	  if(ITER++ % 5000 == 0)
-	    Msg::Info("%d points created -- Worst tet radius is %g",
-		      vSizes.size(), worst->getRadius());
-
-	  MVertex *v = optimalPointFrontal (gr,worst,active_face,vSizes,vSizesBGM);
-	  v->setIndex(NUM++);
-	  vSizes.push_back(.025);
-	  vSizesBGM.push_back(.025);
-
-	  if(!worst->inCircumSphere(v) ||
-	     !insertVertex(v, worst, myFactory, allTets, vSizes,vSizesBGM,&activeTets)){
-	    myFactory.changeTetRadius(allTets.begin(), 0.);
-	    if(v) delete v;
-	  }
-	  else{
-	    //	    printf("yeah ! one new vertex \n");
-	    v->onWhat()->mesh_vertices.push_back(v);
-	    //	    if (ITER == 100)break;
-	  }
-	}
-	else if (worst->getRadius() > LIMIT_){
-	  activeTetsNotInFront.insert(worst);
-	}
-      }
-    }
-    _front.clear();
-    MTet4Factory::iterator it = activeTetsNotInFront.begin();
-    for ( ; it!=activeTetsNotInFront.end();++it){
-      if((*it)->getRadius() > LIMIT_ && isActive(*it,LIMIT_,active_face)){
-	activeTets.insert(*it);
-	updateActiveFaces(*it, LIMIT_, _front);
-      }
-    }
-    if (!activeTets.size())break;
-  }
-
-
-  int nbReloc = 0;
-  for (int SM=0;SM<CTX::instance()->mesh.nbSmoothing;SM++){
-    for(MTet4Factory::iterator it = allTets.begin(); it != allTets.end(); ++it){
-      if (!(*it)->isDeleted()){
-	double qq = (*it)->getQuality();
-	if (qq < .4)
-	  for (int i = 0; i < 4; i++){
-	    if (smoothVertex(*it, i, qmTetrahedron::QMTET_GAMMA)) nbReloc++;
-	  }
-      }
-    }
-  }
-
-
-  while(1){
-    if(allTets.begin() == allTets.end()) break;
-    MTet4 *worst = *allTets.begin();
-    if(!worst->isDeleted()){
-      worst->onWhat()->tetrahedra.push_back(worst->tet());
-      worst->tet() = 0;
-    }
-    myFactory.Free(worst);
-    allTets.erase(allTets.begin());
-  }
-  MTet4::radiusNorm = 2;
-  LIMIT_ = 1;
-}
-
 
 ///// do a 3D delaunay mesh assuming a set of vertices
 
diff --git a/Mesh/meshGRegionDelaunayInsertion.h b/Mesh/meshGRegionDelaunayInsertion.h
index cc75283d2b84dc57ea54ac1bde0551fafea3dad9..a586cd4055e7fae52eae103efe061b2aaa57a7a9 100644
--- a/Mesh/meshGRegionDelaunayInsertion.h
+++ b/Mesh/meshGRegionDelaunayInsertion.h
@@ -89,8 +89,7 @@ class MTet4
     double B[4] = {v1->x(), v1->y(), v1->z()};
     double C[4] = {v2->x(), v2->y(), v2->z()};
     double D[4] = {v3->x(), v3->y(), v3->z()};
-    double x,y,z;
-    tetcircumcenter (A,B,C,D,res,&x,&y,&z);
+    tetcircumcenter (A,B,C,D,res,NULL,NULL,NULL);
   }
 
   void setup(MTetrahedron *t, std::vector<double> &sizes, std::vector<double> &sizesBGM)
@@ -103,6 +102,19 @@ class MTet4
     const double dy = base->getVertex(0)->y() - center[1];
     const double dz = base->getVertex(0)->z() - center[2];
     circum_radius = sqrt(dx * dx + dy * dy + dz * dz);
+    /*
+    if (base->getVertex(0)->getIndex() >= sizes.size() ||
+	base->getVertex(1)->getIndex() >= sizes.size() ||
+	base->getVertex(2)->getIndex() >= sizes.size() ||
+	base->getVertex(3)->getIndex() >= sizes.size()){
+      printf("ERROR %d vs %d %d %d %d\n",sizes.size() ,
+	     base->getVertex(0)->getIndex(),
+	     base->getVertex(1)->getIndex(),
+	     base->getVertex(2)->getIndex(),
+	     base->getVertex(3)->getIndex());
+
+    }
+    */	
     double lc1 = 0.25*(sizes[base->getVertex(0)->getIndex()]+
                       sizes[base->getVertex(1)->getIndex()]+
                        sizes[base->getVertex(2)->getIndex()]+
@@ -115,6 +127,43 @@ class MTet4
     circum_radius /= lc;
     deleted = false;
   } 
+
+  void setup(MTetrahedron *t, std::vector<double> &sizes, std::vector<double> &sizesBGM, double lcA, double lcB)
+  {
+    base = t;
+    neigh[0] = neigh[1] = neigh[2] = neigh[3] = 0;
+    double center[3];
+    circumcenter(center);
+    const double dx = base->getVertex(0)->x() - center[0];
+    const double dy = base->getVertex(0)->y() - center[1];
+    const double dz = base->getVertex(0)->z() - center[2];
+    circum_radius = sqrt(dx * dx + dy * dy + dz * dz);
+
+    /*
+    if (base->getVertex(0)->getIndex() >= sizes.size() ||
+	base->getVertex(1)->getIndex() >= sizes.size() ||
+	base->getVertex(2)->getIndex() >= sizes.size()){
+      printf("ERROR %d vs %d %d %d %d\n",sizes.size() ,
+	     base->getVertex(0)->getIndex(),
+	     base->getVertex(1)->getIndex(),
+	     base->getVertex(2)->getIndex(),
+	     base->getVertex(3)->getIndex());
+
+    }
+    */	
+    double lc1 = 0.25*(sizes[base->getVertex(0)->getIndex()]+
+                      sizes[base->getVertex(1)->getIndex()]+
+                       sizes[base->getVertex(2)->getIndex()]+
+                       lcA);
+    double lcBGM = 0.25*(sizesBGM[base->getVertex(0)->getIndex()]+
+                         sizesBGM[base->getVertex(1)->getIndex()]+
+                         sizesBGM[base->getVertex(2)->getIndex()]+
+                         lcB);
+    double lc = Extend2dMeshIn3dVolumes() ? std::min(lc1, lcBGM) : lcBGM;
+    circum_radius /= lc;
+    deleted = false;
+  } 
+
   inline GRegion *onWhat() const { return gr; }
   inline void setOnWhat(GRegion *g) { gr = g; }
   inline bool isDeleted() const { return deleted; }
@@ -181,7 +230,7 @@ void bowyerWatsonFrontalLayers(GRegion *gr, bool hex);
 GRegion *getRegionFromBoundingFaces(GModel *model,
                                     std::set<GFace *> &faces_bound);
 
-class compareTet4Ptr
+class compareTet4Ptr 
 {
  public:
   inline bool operator () (const MTet4 *a, const MTet4 *b)  const
@@ -245,6 +294,18 @@ class MTet4Factory
     t4->setup(t, sizes, sizesBGM);
     return t4;
   }
+  MTet4 *Create(MTetrahedron * t, std::vector<double> &sizes, 
+                std::vector<double> &sizesBGM, double lc1, double lc2)
+  {
+#ifdef _GMSH_PRE_ALLOCATE_STRATEGY_
+    MTet4 *t4 = getAnEmptySlot();
+#else
+    MTet4 *t4 = new MTet4;
+#endif
+    t4->setup(t, sizes, sizesBGM, lc1, lc2);
+    return t4;
+  }
+
   void Free(MTet4 *t)
   {
     if (t->tet()) delete t->tet();
diff --git a/Mesh/meshGRegionLocalMeshMod.cpp b/Mesh/meshGRegionLocalMeshMod.cpp
index e4cc66e88c27df3bd8e2996db2ed3965c6aa9bda..7091b9c8e3c79d2aba80947e3407d8bbdfb8b323 100644
--- a/Mesh/meshGRegionLocalMeshMod.cpp
+++ b/Mesh/meshGRegionLocalMeshMod.cpp
@@ -206,6 +206,12 @@ bool edgeSwap(std::vector<MTet4 *> &newTets,
               int iLocalEdge,
               const qmTetrahedron::Measures &cr)
 {
+
+  //static int edges[6][2] =    {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}};
+  int permut[6] = {0,3,1,2,5,4};
+  iLocalEdge = permut[iLocalEdge];
+  
+  
   std::vector<MTet4*> cavity;
   std::vector<MTet4*> outside;
   std::vector<MVertex*> ring;
diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp
index ac01ba6ad64998b8e8311b920fab11cd29a139e8..c8cc6c0e9e78a5a0db51b0c5e81b0955af6ad072 100644
--- a/Numeric/Numeric.cpp
+++ b/Numeric/Numeric.cpp
@@ -665,9 +665,13 @@ bool newton_fd(bool (*func)(fullVector<double> &, fullVector<double> &, void *),
   fullMatrix<double> J(N, N);
   fullVector<double> f(N), feps(N), dx(N);
 
-  for (int iter = 0; iter < MAXIT; iter++){
-    if(!func(x, f, data)) return false;
-
+  
+  for (int iter = 0; iter < MAXIT; iter++){    
+    if (x.norm() > 1.e6)return false;
+    if(!func(x, f, data)) {
+      return false;
+    }
+      
     bool isZero = false;
     for (int k=0; k<N; k++) {
       if (f(k) == 0. ) isZero = true;
@@ -680,7 +684,9 @@ bool newton_fd(bool (*func)(fullVector<double> &, fullVector<double> &, void *),
       double h = EPS * fabs(x(j));
       if(h == 0.) h = EPS;
       x(j) += h;
-      if(!func(x, feps, data)) return false;
+      if(!func(x, feps, data)) {
+	return false;
+      }
       for (int i = 0; i < N; i++){
         J(i, j) = (feps(i) - f(i)) / h;
       }
@@ -690,13 +696,16 @@ bool newton_fd(bool (*func)(fullVector<double> &, fullVector<double> &, void *),
     if (N == 1)
       dx(0) = f(0) / J(0, 0);
     else
-      if (!J.luSolve(f, dx))
+      if (!J.luSolve(f, dx)){
         return false;
+      }
 
     for (int i = 0; i < N; i++)
       x(i) -= relax * dx(i);
 
-    if(dx.norm() < tolx) return true;
+    if(dx.norm() < tolx) {
+      return true;
+    }
   }
   return false;
 }
diff --git a/benchmarks/boolean/aneurysmBL.py b/benchmarks/boolean/aneurysmBL.py
index c5b15484aef5249d1751ff0f51d1bc34279b4ce1..e1bb89787a96415fc3c435dbbd2cadbe30b1aa66 100644
--- a/benchmarks/boolean/aneurysmBL.py
+++ b/benchmarks/boolean/aneurysmBL.py
@@ -1,4 +1,4 @@
-from dgpy import *
+from gmshpy import *
 
 GmshSetOption('General', 'Verbosity', 99.0) 
 GmshSetOption('Mesh', 'SaveAll', 1.0)