From 6be38de8b3a48e451cae3b9c15bdd4747a0cdc48 Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Wed, 23 Dec 2015 16:34:07 +0000
Subject: [PATCH] 3d re-writing in progress

---
 Mesh/delaunay3d.cpp                | 263 +++++++++++++++++++----------
 Mesh/delaunay3d_private.h          |   9 +-
 Mesh/delaunay_refinement.cpp       |  92 +++++++---
 Mesh/meshGRegion.cpp               |   9 +-
 Mesh/meshGRegionRelocateVertex.cpp |  23 +--
 Mesh/meshGRegionRelocateVertex.h   |   2 +-
 6 files changed, 268 insertions(+), 130 deletions(-)

diff --git a/Mesh/delaunay3d.cpp b/Mesh/delaunay3d.cpp
index ce3ebac442..9c29cab96d 100644
--- a/Mesh/delaunay3d.cpp
+++ b/Mesh/delaunay3d.cpp
@@ -322,13 +322,12 @@ void computeAdjacencies (Tet *t, int iFace, connContainer &faceToTet){
   }
 }
 
-void delaunayCavity (Tet *t,
-		     Tet *prev,
-		     Vertex *v,
-		     cavityContainer &cavity,
-		     connContainer &bnd,
-		     int thread, int iPnt){
-
+static void delaunayCavity2 (Tet *t, 
+			    Tet *prev,
+			    Vertex *v, 
+			    cavityContainer &cavity,    
+			    connContainer &bnd, 
+			    int thread, int iPnt, int PP){
   t->set(thread, iPnt); // Mark the triangle
   cavity.push_back(t);
   for (int iNeigh=0; iNeigh<4 ; iNeigh++){
@@ -337,15 +336,40 @@ void delaunayCavity (Tet *t,
       bnd.push_back(conn(t->getFace(iNeigh),iNeigh,NULL));
     }
     else if (neigh == prev){
+      if (PP == 40)printf("coucou\n");
     }
     else if (!neigh->inSphere(v,thread)){
-      // look if v sees face t->getFace(iNeigh)
       Face f = t->getFace(iNeigh);
       bnd.push_back(conn(f,iNeigh,neigh));
-      neigh->set(thread, iPnt);
+      //      neigh->set(thread, iPnt);
     }
     else if (!(neigh->isSet(thread, iPnt))) {
-      delaunayCavity (neigh, t, v, cavity,bnd,thread, iPnt);
+      delaunayCavity2 (neigh, t, v, cavity,bnd,thread, iPnt,PP); 
+    }
+  }
+}
+
+static void delaunayCavity (Tet *t, 
+			    Tet *prev,
+			    Vertex *v, 
+			    cavityContainer &cavity,    
+			    connContainer &bnd, 
+			    int thread, int iPnt, int PP){
+
+  t->set(thread, iPnt); // Mark the triangle
+  cavity.push_back(t);
+  for (int iNeigh=0; iNeigh<4 ; iNeigh++){  
+    Tet *neigh = t->T[iNeigh];
+    if (neigh == NULL){
+      bnd.push_back(conn(t->getFace(iNeigh),iNeigh,NULL));
+    }
+    else if (neigh->inSphere(v,thread)){
+      if (!(neigh->isSet(thread, iPnt))) {
+	delaunayCavity (neigh, t, v, cavity,bnd,thread, iPnt,PP); 
+      }
+    }
+    else {
+      bnd.push_back(conn( t->getFace(iNeigh),iNeigh,neigh));
     }
   }
 }
@@ -366,7 +390,7 @@ bool straddling_segment_intersects_triangle(Vertex *p1, Vertex *p2,
 }
 
 void print (Vertex *v){
-  printf("%3d ",v->getNum());
+  printf("%p ",v);
 }
 
 void print (Tet *t, bool recur = true){
@@ -424,64 +448,45 @@ Tet* walk (Tet *t, Vertex *v, int maxx, double &totSearch, int thread){
 }
 
 
-Tet* walk1 (Tet *t, Vertex *v, int maxx, double &totSearch, int thread){
-  int NUMSEARCH = 0;
-  int STARTER = 0;
-
-  maxx = std::max(100,maxx);
 
-  while (1){
-    if (NUMSEARCH++ > 9*maxx) {
-      if (t->T[0] && t->T[0]->T[0]) t = t->T[0]->T[0];
-      else if (t->T[1] && t->T[1]->T[0]) t = t->T[1]->T[0];
-      else if (t->T[2] && t->T[2]->T[0]) t = t->T[2]->T[0];
-      if (NUMSEARCH > 10*maxx) {
-	printf("trying to find a path from %p to %p: datastructure broken (%d searches, maxx %d)\n",v,t,NUMSEARCH,maxx);
-	NUMSEARCH=0;
-	return NULL;
-      }
-    }
-    if (t == NULL) {
-      Msg::Warning("search went through the boundary of the mesh without finding a tet");
-      return NULL; // we should NEVER return here
-    }
-    if (t->inSphere(v,thread)) {totSearch += NUMSEARCH; return t;}
-    Vertex c = t->centroid();
-    Tet *oldt=t;
-    for (int iNeigh=STARTER; iNeigh<(STARTER+4) ; iNeigh++){
-      const int NEIGH = iNeigh %4;
-      Face f = t->getFace (NEIGH);
-      bool inters = straddling_segment_intersects_triangle(&c, v, f.V[0], f.V[1], f.V[2]);
-      if (inters){
-	t = t->T[NEIGH];
-	break;
-      }
-    }
-    if (t==oldt){
-      printf("trying to find a path from %p to %p, ",v,t);
-      printf("strange : no intersection\n");
-      for (int iNeigh=0; iNeigh<20 ; iNeigh++){
-	int rr = rand()%4;
-	if (t->T[rr])t =t->T[rr];
-      }
-    }
-    STARTER++;
+void __print (const char *name, connContainer &conn){
+  FILE *f = fopen(name,"w");
+  fprintf(f,"View \"\"{\n");
+  
+  for (unsigned int i=0;i<conn.size();i++){
+    fprintf(f,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
+	    conn[i].f.V[0]->x(),conn[i].f.V[0]->y(),conn[i].f.V[0]->z(),
+	    conn[i].f.V[1]->x(),conn[i].f.V[1]->y(),conn[i].f.V[1]->z(),
+	    conn[i].f.V[2]->x(),conn[i].f.V[2]->y(),conn[i].f.V[2]->z(),1.,1.,1.);
   }
+  fprintf(f,"};\n");
+  fclose(f);
 }
 
-void print (const char *name, std::vector<Tet*> &T){
+void __print (const char *name, std::vector<Tet*> &T, Vertex *v){
   FILE *f = fopen(name,"w");
   fprintf(f,"View \"\"{\n");
+  if (v)fprintf(f,"SP(%g,%g,%g){%d};\n",v->x(),v->y(),v->z(),v->getNum());
+  
   for (unsigned int i=0;i<T.size();i++){
     if (T[i]->V[0]){
       //      double val = robustPredicates::orient3d((double*)T[i]->V[0],(double*)T[i]->V[1],(double*)T[i]->V[2],(double*)T[i]->V[3]);
-
-      fprintf(f,"SS(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
-	      T[i]->V[0]->x(),T[i]->V[0]->y(),T[i]->V[0]->z(),
-	      T[i]->V[1]->x(),T[i]->V[1]->y(),T[i]->V[1]->z(),
-	      T[i]->V[2]->x(),T[i]->V[2]->y(),T[i]->V[2]->z(),
-	      T[i]->V[3]->x(),T[i]->V[3]->y(),T[i]->V[3]->z(),
-	      T[i]->V[0]->lc(),T[i]->V[1]->lc(),T[i]->V[2]->lc(),T[i]->V[3]->lc());
+      if (!v){
+	fprintf(f,"SS(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
+		T[i]->V[0]->x(),T[i]->V[0]->y(),T[i]->V[0]->z(),
+		T[i]->V[1]->x(),T[i]->V[1]->y(),T[i]->V[1]->z(),
+		T[i]->V[2]->x(),T[i]->V[2]->y(),T[i]->V[2]->z(),
+		T[i]->V[3]->x(),T[i]->V[3]->y(),T[i]->V[3]->z(),
+		T[i]->V[0]->lc(),T[i]->V[1]->lc(),T[i]->V[2]->lc(),T[i]->V[3]->lc());
+      }
+      else{
+	fprintf(f,"SS(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%d,%d,%d,%d};\n",
+		T[i]->V[0]->x(),T[i]->V[0]->y(),T[i]->V[0]->z(),
+		T[i]->V[1]->x(),T[i]->V[1]->y(),T[i]->V[1]->z(),
+		T[i]->V[2]->x(),T[i]->V[2]->y(),T[i]->V[2]->z(),
+		T[i]->V[3]->x(),T[i]->V[3]->y(),T[i]->V[3]->z(),
+		T[i]->V[0]->getNum(),T[i]->V[1]->getNum(),T[i]->V[2]->getNum(),T[i]->V[3]->getNum());
+      }
     }
   }
   fprintf(f,"};\n");
@@ -550,11 +555,63 @@ static Tet* stoopidSearch (Tet *t, Vertex *v, int thread){
   return NULL;
 }
 
+static void stoopidCavity (Tet *t, Vertex *v, int thread, std::vector<Tet*> &cavity){
+  cavity.clear();
+  std::stack<Tet*> _stack;
+  _stack.push(t);
+  std::set<Tet*> all;
+  while(!_stack.empty()){
+    t = _stack.top();
+    all.insert(t);
+    _stack.pop();
+    if (t->inSphere(v,thread)){cavity.push_back(t);}
+    for (int i=0;i<4;i++){
+      if (t->T[i]){
+	if (all.find(t->T[i]) == all.end()){
+	  all.insert(t->T[i]);
+	  _stack.push(t->T[i]);
+	}
+      }
+    }
+  }
+}
+
+void checkCavity (std::vector<Tet*> &c, Vertex *v){
+  std::set<Face> ff;
+  for (unsigned int i=0; i<c.size(); i++) {
+    for (int j=0;j<4;j++){
+      std::set<Face>::iterator it = ff.find(c[i]->getFace(j));
+      if (it != ff.end())ff.erase(it);
+      else ff.insert(c[i]->getFace(j));
+    }
+  }
+  printf("%d free faces\n",ff.size());
+
+  std::vector<Tet*> bad;
+  for (unsigned int i=0; i<c.size(); i++) {
+    for (int j=0;j<4;j++){
+      std::set<Face>::iterator it = ff.find(c[i]->getFace(j));
+      if (it != ff.end()){
+	Tet *neigh = c[i]->T[j];
+	if (neigh){
+	  int val = neigh->inSphere(v,0);
+	  if (val){printf("arghhhh %p %p set %d\n",neigh,c[i], neigh->isSet(0,0));
+	    bad.push_back(neigh);
+	    //	    bad.push_back(c[i]);
+	  }
+	}
+	std::vector<Tet*>::iterator it2= std::find(c.begin(),c.end(),neigh);
+	if (it2 != c.end())printf("datastructure broken\n");
+      }
+    }
+  }
+  __print("bad.pos",bad);
+}
 
-void delaunayTrgl (const unsigned int numThreads,
-		   const unsigned int NPTS_AT_ONCE,
-		   unsigned int Npts,
-		   std::vector<Tet*> &T,
+void delaunayTrgl (const unsigned int numThreads, 
+		   const unsigned int NPTS_AT_ONCE, 
+		   unsigned int Npts, 
+		   std::vector<Tet*> &T, 
 		   std::vector<Vertex*> assignTo[]){
   double totSearchGlob=0;
   double totCavityGlob=0;
@@ -664,14 +721,35 @@ void delaunayTrgl (const unsigned int numThreads,
 	}
       }
       //      double c1 = Cpu();
+
+      // FIXME TEST
+      //      int NBNULL;
       for (unsigned int K=0; K< NPTS_AT_ONCE; K++) {
 	if(vToAdd[K]){
 	  cavityContainer &cavityK = cavity[K];
 	  connContainer   &bndK = bnd[K];
 	  for (unsigned int i=0; i<cavityK.size(); i++)cavityK[i]->unset(myThread,K);
-	  for (unsigned int i=0; i<   bndK.size(); i++)if(bndK[i].t)bndK[i].t->unset(myThread,K);
+	  //	  for (unsigned int i=0; i<   bndK.size(); i++)if(bndK[i].t)bndK[i].t->unset(myThread,K);
 	  cavityK.clear(); bndK.clear();
-	  delaunayCavity(t[K], NULL, vToAdd[K], cavityK, bndK, myThread, K);
+	  delaunayCavity(t[K], NULL, vToAdd[K], cavityK, bndK, myThread, K,iPGlob);
+	  for (unsigned int i=0; i<cavityK.size(); i++)cavityK[i]->unset(myThread,K);
+	  //	  for (unsigned int i=0; i<   bndK.size(); i++)if(bndK[i].t)bndK[i].t->unset(myThread,K);
+	  //// FIXME TEST
+	  //	  NBNULL = 0;
+	  //	  for (unsigned int i=0; i<cavityK.size(); i++) {
+	  //	    for (int j=0;j<4;j++)if(!cavityK[i]->T[j])NBNULL++;
+	  //	  }
+	  /*	  if (iPGlob==40){
+	    char name[245];
+	    printf("cavity for point %d size %d shell %d NBNULL %d\n",
+		   iPGlob,cavityK.size(),bndK.size(),NBNULL);
+	    sprintf(name,"Cavity%d.pos",iPGlob);
+	    __print(name,cavityK,vToAdd[K]);
+	    sprintf(name,"Bnd%d.pos",iPGlob);
+	    __print(name,bndK);
+	    checkCavity(cavityK,vToAdd[K]);
+	  }
+	  */
 	  // verify the cavity
 	  for (unsigned int i=0; i< bndK.size(); i++) {
 	    double val =   robustPredicates::orient3d((double*)bndK[i].f.V[0],
@@ -679,10 +757,20 @@ void delaunayTrgl (const unsigned int numThreads,
 						      (double*)bndK[i].f.V[2],
 						      (double*)vToAdd[K]);
 	    if (val <= 0 ) {
-	      //	      char name[245];
-	      //	      sprintf(name,"invalidCavity%d.pos",invalidCavities [myThread]);
-	      //	      print(name,cavityK);
-	      //	      printf("val = %22.15E\n",val);
+	      //	      	      char name[245];
+	      //	      	      sprintf(name,"invalidCavity%d.pos",invalidCavities [myThread]);
+	      //	      	      __print(name,cavityK,vToAdd[K]);
+	      //	      	      printf("val = %22.15E\n",val);
+	      //	      	      std::vector<Tet*> temp;
+	      //	      	      stoopidCavity (t[K], vToAdd[K], myThread, temp);	  
+	      //	      	      sprintf(name,"validCavity%d.pos",invalidCavities [myThread]);
+	      //	      	      __print(name,temp,vToAdd[K]);
+	      //	      	      printf("---> cavity %d vs. %d elements in cavity\n",temp.size(),cavityK.size());
+	      //		      sprintf(name,"Bnd%d.pos",invalidCavities [myThread]);
+	      //		      __print(name,bndK);
+		      //	      for (unsigned int i=0; i<temp.size(); i++) {
+		      //	      		print(temp[i]);
+		      //	      	      }	      
 	      vToAdd[K] = NULL;
 	      invalidCavities [myThread]++;
 	      break;
@@ -712,6 +800,8 @@ void delaunayTrgl (const unsigned int numThreads,
 	  const unsigned int bSize = bndK.size();
 	  totCavity+= cSize;
 	  Choice[K] = cavityK[0];
+	  // FIXME TEST
+	  std::vector<Tet*> _news;
 	  for (unsigned int i=0; i<bSize; i++) {
 	    // reuse memory slots of invalid elements
 	    Tet *t;
@@ -723,17 +813,8 @@ void delaunayTrgl (const unsigned int numThreads,
 	      allocatedTable.push_back(t);
 	      newCounter = allocatedTable.size();
 	    }
-	    //	    if (newCounter >= allocatedSize){
-	    //	      Msg::Fatal("JF : write the reallocation now !");
-	    //	    }
 	    if (i < cSize && t->V[0]->_thread != myThread)cashMisses[myThread]++;
-	    int sign = t->setVertices (bndK[i].f.V[0], bndK[i].f.V[1], bndK[i].f.V[2], vToAdd[K]);
-	    if (sign <= 0){
-	      // A coplanar hull face. We need to test if this hull face is
-	      //   Delaunay or not. We test if the adjacent tet (not faked)
-	      //   of this hull face is Delaunay or not.
-	      Msg::Fatal ("JF: Fix Invalid Cavity %d",sign);
-	    }
+	    t->setVerticesNoTest (bndK[i].f.V[0], bndK[i].f.V[1], bndK[i].f.V[2], vToAdd[K]);
 	    Tet *neigh = bndK[i].t;
 	    t->T[0] = neigh;
 	    t->T[1] = t->T[2] = t->T[3] = NULL;
@@ -747,7 +828,19 @@ void delaunayTrgl (const unsigned int numThreads,
 	    computeAdjacencies (t,1,faceToTet);
 	    computeAdjacencies (t,2,faceToTet);
 	    computeAdjacencies (t,3,faceToTet);
+	    _news.push_back(t);
 	  }
+	  // FIXME TEST
+	  //	  int NBNULL2 = 0;	 
+	  //	  for (unsigned int i=0; i<_news.size(); i++) {
+	  //	    for (int j=0;j<4;j++)if(!_news[i]->T[j])NBNULL2++;
+	  //	  }
+	  //	  if (NBNULL != NBNULL2){
+	  //	    char name[245];
+	  //	    sprintf(name,"invalidConnexion%d.pos",iPGlob);
+	  //	    __print(name,_news,vToAdd[K]);
+	  //	    printf("%d %d\n",NBNULL,NBNULL2);
+	  //	  }
 	  for (unsigned int i=bSize; i<cSize; i++) {
 	    counterMiss++;
 	    cavityK[i]->V[0] = cavityK[i]->V[1] = cavityK[i]->V[2] = cavityK[i]->V[3] = NULL;
@@ -774,7 +867,7 @@ void delaunayTrgl (const unsigned int numThreads,
     #pragma omp barrier
   }
 
-  printf("%d invalid cavities\n",invalidCavities[0]);
+  if (invalidCavities[0])Msg::Warning("%d invalid cavities",invalidCavities[0]);
 
 #ifdef _VERBOSE
   double _t2 = walltime(&_t);
@@ -906,7 +999,7 @@ void delaunayTriangulation (const int numThreads,
   //  _t = 0;
   //  double _t2 = walltime(&_t);
   //  printf("WALL CLOCK TIME %12.5E\n",_t2-_t1);
-  print ("finalTetrahedrization.pos",T);
+  __print ("finalTetrahedrization.pos",T);
 }
 
 
@@ -930,9 +1023,9 @@ void delaunayTriangulation (const int numThreads,
   for (unsigned int i=0;i<N;i++){
     MVertex *mv = S[i];
     // FIXME : should be zero !!!!
-    double dx = d*1.e-16 * (double)rand() / RAND_MAX;
-    double dy = d*1.e-16 * (double)rand() / RAND_MAX;
-    double dz = d*1.e-16 * (double)rand() / RAND_MAX;
+    double dx = d*1.e-14 * (double)rand() / RAND_MAX;
+    double dy = d*1.e-14 * (double)rand() / RAND_MAX;
+    double dz = d*1.e-14 * (double)rand() / RAND_MAX;
     mv->x() += dx;
     mv->y() += dy;
     mv->z() += dz;
diff --git a/Mesh/delaunay3d_private.h b/Mesh/delaunay3d_private.h
index 343b701db2..4abd71e548 100644
--- a/Mesh/delaunay3d_private.h
+++ b/Mesh/delaunay3d_private.h
@@ -161,6 +161,11 @@ struct Tet {
     T[0] = T[1] = T[2] = T[3] = NULL;
     setAllDeleted();    
   }
+  int setVerticesNoTest (Vertex *v0, Vertex *v1, Vertex *v2, Vertex *v3){
+    _modified=true;
+    V[0] = v0; V[1] = v1; V[2] = v2; V[3] = v3;
+    return 1;
+  }
   int setVertices (Vertex *v0, Vertex *v1, Vertex *v2, Vertex *v3){
     _modified=true;
     double val = robustPredicates::orient3d((double*)v0,(double*)v1,(double*)v2,(double*)v3);
@@ -169,10 +174,12 @@ struct Tet {
       return 1;
     }
     else if (val < 0){
+      //      throw;
       V[0] = v1; V[1] = v0; V[2] = v2; V[3] = v3;
       return -1;
     }
     else {
+      //      throw;
       return 0;
     }
   }
@@ -232,7 +239,7 @@ typedef std::vector<conn>   connContainer;
 
 void SortHilbert (std::vector<Vertex*>& v, std::vector<int> &indices);
 void computeAdjacencies (Tet *t, int iFace, connContainer &faceToTet);
-void print (const char *name, std::vector<Tet*> &T);
+void __print (const char *name, std::vector<Tet*> &T, Vertex *v = 0);
 void delaunayTrgl (const unsigned int numThreads, 
 		   const unsigned int NPTS_AT_ONCE, 
 		   unsigned int Npts, 
diff --git a/Mesh/delaunay_refinement.cpp b/Mesh/delaunay_refinement.cpp
index 857db4ab39..76f0d4de74 100644
--- a/Mesh/delaunay_refinement.cpp
+++ b/Mesh/delaunay_refinement.cpp
@@ -35,14 +35,6 @@ struct edgeContainer
     _hash2.insert(e);
     return true;
   }
-  bool isNewEdge (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;}
-    return true;
-  }
-
   bool addNewEdge (const Edge &e)
   {
     size_t h = (size_t) e.first >> 3;
@@ -148,9 +140,9 @@ void saturateEdge (Edge &e, std::vector<Vertex*> &S, double (*f)(const SPoint3 &
       else {
 	SPoint3 p = p1 * (1.-t) + p2*t;
 	double lc = e.first->lc() * (1.-t) + e.second->lc()*t;
-	const double dx = 1.e-16 * (double) rand() / RAND_MAX;
-	const double dy = 1.e-16 * (double) rand() / RAND_MAX;
-	const double dz = 1.e-16 * (double) rand() / RAND_MAX;
+	const double dx = 1.e-10 * (double) rand() / RAND_MAX;
+	const double dy = 1.e-10 * (double) rand() / RAND_MAX;
+	const double dz = 1.e-10 * (double) rand() / RAND_MAX;
 	S.push_back(new Vertex(p.x()+dx,p.y()+dy,p.z()+dz,lc));
 	L += interval;
       }
@@ -198,16 +190,16 @@ public :
     double d = sqrt ((p->_v->x() - _v->x()) * (p->_v->x() - _v->x())+
 		     (p->_v->y() - _v->y()) * (p->_v->y() - _v->y())+
 		     (p->_v->z() - _v->z()) * (p->_v->z() - _v->z()));
-    return d < .7*p->_v->lc();//_l;
+    return d < .8*p->_v->lc();//_l;
   }
   void minmax (double _min[3], double _max[3]) const
   {
-    _min[0] = _v->x() - 1.1*_v->lc();
-    _min[1] = _v->y() - 1.1*_v->lc();
-    _min[2] = _v->z() - 1.1*_v->lc();
-    _max[0] = _v->x() + 1.1*_v->lc();
-    _max[1] = _v->y() + 1.1*_v->lc();
-    _max[2] = _v->z() + 1.1*_v->lc();
+    _min[0] = _v->x() - 1.01*_v->lc();
+    _min[1] = _v->y() - 1.01*_v->lc();
+    _min[2] = _v->z() - 1.01*_v->lc();
+    _max[0] = _v->x() + 1.01*_v->lc();
+    _max[1] = _v->y() + 1.01*_v->lc();
+    _max[2] = _v->z() + 1.01*_v->lc();
   }
 };
 
@@ -317,13 +309,14 @@ void edgeBasedRefinement (const int numThreads,
 
   // fill up old Datastructures
 
-  std::vector<MTetrahedron*> T = gr->tetrahedra;
   std::vector<Tet*> _tets;
-  _tets.resize(T.size());
   std::vector<Vertex *> _vertices;
   edgeContainer ec;
+  std::map<Vertex*,MVertex*> _ma;
 
   {
+    std::vector<MTetrahedron*> &T = gr->tetrahedra;
+    _tets.resize(T.size());
     std::set<MVertex *> all;
     for (int i=0;i<T.size();i++){
       for (int j=0;j<4;j++){
@@ -338,6 +331,7 @@ void edgeBasedRefinement (const int numThreads,
       mv->setIndex(counter);
       Vertex *v = new Vertex (mv->x(),mv->y(),mv->z(),1.e22, counter);
       _vertices[counter] = v;
+      _ma[v] = mv;
       counter++;
     }
     connSet faceToTet;
@@ -352,9 +346,11 @@ void edgeBasedRefinement (const int numThreads,
       computeAdjacencies (t,2,faceToTet);
       computeAdjacencies (t,3,faceToTet);
       _tets[i] = t;
+      delete T[i];
     }
+    T.clear();
   }
-
+  
   // do not allow to saturate boundary edges
   {
     for (unsigned int i=0;i<_tets.size();i++) {
@@ -377,12 +373,13 @@ void edgeBasedRefinement (const int numThreads,
     for (unsigned int i=0;i<_tets.size();i++) {
       for (int j=0;j<6;j++){
 	Edge e = _tets[i]->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();}
+	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<Vertex*> add_all;
   {
     vertexFilter _filter;
     int iter = 1;
@@ -410,8 +407,9 @@ void edgeBasedRefinement (const int numThreads,
       double t4 = Cpu();
       //      sprintf(name,"PointsFiltered%d.pos",iter);
       //      _print (name,add);
-      delaunayTrgl (1,1,add.size(), _tets, &add);
-      double t5 = Cpu();
+      delaunayTrgl (1,1,add.size(), _tets, &add);  
+      add_all.insert (add_all.end(), add.begin(), add.end());
+      clock_t t5 = clock();
       Msg::Info("IT %3d %6d points added, timings %5.2f %5.2f %5.2f %5.2f %5.2f %5d",iter,add.size(),
 		(t2-t1),
 		(t3-t2),
@@ -421,6 +419,48 @@ void edgeBasedRefinement (const int numThreads,
 		_tets.size());
       iter++;
     }
-    print ("afterRefinement.pos",_tets);
+    //    print ("afterRefinement.pos",_tets);
+  }
+
+  std::map<Edge,double> _sizes;
+  for (unsigned int i=0; i<_tets.size();i++){
+    MVertex *mvs[4];
+
+
+    if (_tets[i]->V[0]){      
+      for (int j=0;j<6;j++){
+	Edge e =  _tets[i]->getEdge(j);
+	std::map<Edge,double>::iterator it = _sizes.find(e);
+	if (it == _sizes.end()){
+	  double l = sqrt ((e.first->x() -  e.second->x()) * (e.first->x() -  e.second->x()) +
+			   (e.first->y() -  e.second->y()) * (e.first->y() -  e.second->y()) +
+			   (e.first->z() -  e.second->z()) * (e.first->z() -  e.second->z()));
+	  _sizes[e]= 2* l / (e.first->lc() + e.second->lc());
+	}
+      }
+      for (int j=0;j<4;j++){
+	Vertex *v = _tets[i]->V[j];
+	std::map<Vertex*,MVertex*>::iterator it = _ma.find(v);
+	if (it == _ma.end()){
+	  MVertex *mv = new MVertex (v->x(),v->y(),v->z(),gr);
+	  gr->mesh_vertices.push_back(mv);
+	  _ma[v] = mv;
+	  mvs[j] = mv;
+	}
+	else mvs[j] = it->second;
+      }
+      gr->tetrahedra.push_back(new MTetrahedron(mvs[0],mvs[1],mvs[2],mvs[3]));
+    }
+    delete _tets[i];
   }
+
+  std::map<Edge,double>::iterator it = _sizes.begin();
+  double sum = 0;
+  for (; it !=_sizes.end();++it){
+    double d = it->second;
+    double tau = d < 1 ? d - 1 : 1./d - 1;
+    sum += tau;
+  }
+  Msg::Info("MESH EFFICIENCY : %22.15E",exp (sum / _sizes.size()));
+
 }
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index 20e13256c1..b826362385 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -628,17 +628,14 @@ static void MeshDelaunayVolumeNewCode(std::vector<GRegion*> &regions) {
 
   // restore the initial set of faces
   gr->set(faces);
-
-
-#if 1
+  
   void edgeBasedRefinement (const int numThreads, 
 			    const int nptsatonce, 
 			    GRegion *gr);
+  // just to remove tets that are not to be meshed
   insertVerticesInRegion(gr,0);
   edgeBasedRefinement (1,1,gr);
-#else
-  insertVerticesInRegion(gr,200000000);
-#endif
+  //  RelocateVertices (regions,-1);
 }
 
 
diff --git a/Mesh/meshGRegionRelocateVertex.cpp b/Mesh/meshGRegionRelocateVertex.cpp
index 1c004f84d7..10085b9596 100644
--- a/Mesh/meshGRegionRelocateVertex.cpp
+++ b/Mesh/meshGRegionRelocateVertex.cpp
@@ -34,15 +34,14 @@ static double objective_function (double xi, MVertex *ver,
 
 #define sqrt5 2.236067977499789696
 
-static int Stopping_Rule(double x0, double x1) 
+static int Stopping_Rule(double x0, double x1, double tol) 
 {
-  double tolerance = 1.e-2;
-  return ( fabs( x1 - x0 ) < tolerance ) ? 1 : 0;
+  return ( fabs( x1 - x0 ) < tol) ? 1 : 0;
 }
 
 double Maximize_Quality_Golden_Section( MVertex *ver, 
 					double xTarget, double yTarget, double zTarget,
-					const std::vector<MElement*> &lt )
+					const std::vector<MElement*> &lt , double tol)
 {
   
   static const double lambda = 0.5 * (sqrt5 - 1.0);
@@ -55,18 +54,20 @@ double Maximize_Quality_Golden_Section( MVertex *ver,
   double fx1 = objective_function (x1, ver, xTarget, yTarget, zTarget , lt );
   double fx2 = objective_function (x2, ver, xTarget, yTarget, zTarget , lt );
 
-  while ( ! Stopping_Rule( a, b ) ) {
+  if (tol < 0.0)return fx1 > fx2 ? x1 : x2;
+
+  while ( ! Stopping_Rule( a, b , tol) ) {
     //    printf("GOLDEN : %g %g (%12.5E,%12.5E)\n",a,b,fa,fb);
     if (fx1 < fx2) {
       a = x1;
-      if ( Stopping_Rule( a, b ) ) break;
+      if ( Stopping_Rule( a, b , tol) ) break;
       x1 = x2;
       fx1 = fx2;
       x2 = b - mu * (b - a);
       fx2 = objective_function (x2, ver, xTarget, yTarget, zTarget , lt );
     } else {
       b = x2;
-      if ( Stopping_Rule( a, b ) ) break;
+      if ( Stopping_Rule( a, b , tol) ) break;
       x2 = x1;
       fx2 = fx1;
       x1 = a + mu * (b - a);
@@ -78,7 +79,7 @@ double Maximize_Quality_Golden_Section( MVertex *ver,
 }
 
 static void _relocateVertex(MVertex *ver,
-			    const std::vector<MElement*> &lt)
+			    const std::vector<MElement*> &lt, double tol)
 {
   if(ver->onWhat()->dim() != 3) return;
   double x = 0, y=0, z=0;
@@ -96,13 +97,13 @@ static void _relocateVertex(MVertex *ver,
     N += lt[i]->getNumVertices();
   }
 
-  double xi = Maximize_Quality_Golden_Section( ver, x/N, y/N, z/N, lt );
+  double xi = Maximize_Quality_Golden_Section( ver, x/N, y/N, z/N, lt , tol);
   ver->x() = (1.-xi) * ver->x() + xi * x/N;
   ver->y() = (1.-xi) * ver->y() + xi * y/N;
   ver->z() = (1.-xi) * ver->z() + xi * z/N;
 }
 
-void RelocateVertices (std::vector<GRegion*> &regions) {
+void RelocateVertices (std::vector<GRegion*> &regions, double tol) {
   for(unsigned int k = 0; k < regions.size(); k++){
     v2t_cont adj;
     buildVertexToElement(regions[k]->tetrahedra, adj);
@@ -111,7 +112,7 @@ void RelocateVertices (std::vector<GRegion*> &regions) {
     buildVertexToElement(regions[k]->hexahedra, adj);
     v2t_cont::iterator it = adj.begin();
     while (it != adj.end()){
-      _relocateVertex( it->first, it->second);
+      _relocateVertex( it->first, it->second, tol);
       ++it;
     }
   }
diff --git a/Mesh/meshGRegionRelocateVertex.h b/Mesh/meshGRegionRelocateVertex.h
index 678403aade..5a1b49e429 100644
--- a/Mesh/meshGRegionRelocateVertex.h
+++ b/Mesh/meshGRegionRelocateVertex.h
@@ -2,5 +2,5 @@
 #define _MESHGREGIONRELOCATEVERTEX_
 #include <vector>
 class GRegion;
-void RelocateVertices (std::vector<GRegion*> &regions);
+void RelocateVertices (std::vector<GRegion*> &regions, double tol = 1.e-2);
 #endif
-- 
GitLab