From a029b66711d752ff039b4fb4976fd19fc1e48eec Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Wed, 1 Feb 2012 11:32:23 +0000
Subject: [PATCH] Worked a lot oncurvilinear meshing : projection of point on
 surafces work, matching meshes andgeometry works better, added some test
 examples...

---
 Common/OpenFile.cpp                 |   2 +-
 Fltk/statisticsWindow.cpp           | 329 ++++++++++++++--------------
 Geo/GFace.cpp                       |  74 +++++--
 Geo/Geo.cpp                         |   2 +-
 Geo/GeoInterpolation.cpp            |  79 ++++++-
 Geo/GeomMeshMatcher.cpp             |  37 ++--
 Geo/MElement.cpp                    |  11 +-
 Geo/gmshEdge.cpp                    |   4 +-
 Geo/gmshFace.cpp                    |   5 +-
 Geo/gmshFace.h                      |   2 -
 Geo/gmshVertex.cpp                  |  37 ++++
 Mesh/BackgroundMesh.cpp             |  20 ++
 Mesh/HighOrder.cpp                  |  80 ++++++-
 Mesh/meshGEdge.cpp                  |   1 +
 Mesh/meshGFaceDelaunayInsertion.cpp |  64 ++++++
 Mesh/meshGFaceOptimize.cpp          |  11 +-
 Mesh/qualityMeasures.cpp            |  21 +-
 Solver/elasticitySolver.cpp         |   2 +-
 Solver/elasticitySolver.h           |   2 +-
 benchmarks/2d/recombine.geo         |   2 +-
 benchmarks/2d/transfinite_b.geo     |   2 +-
 21 files changed, 543 insertions(+), 244 deletions(-)

diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index a1881b2695..eba6ade46b 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -366,7 +366,7 @@ int MergeFile(std::string fileName, bool warnIfMissing)
       // mesh matcher
       if(CTX::instance()->geom.matchGeomAndMesh && !GModel::current()->empty()) {
         GModel* tmp2 = GModel::current();
-        GModel* tmp = new GModel();
+        GModel* tmp = new GModel();	
         tmp->readMSH(fileName);
         status = GeomMeshMatcher::instance()->match(tmp2, tmp);
         delete tmp;
diff --git a/Fltk/statisticsWindow.cpp b/Fltk/statisticsWindow.cpp
index 89cf92139d..789230bfdf 100644
--- a/Fltk/statisticsWindow.cpp
+++ b/Fltk/statisticsWindow.cpp
@@ -199,183 +199,188 @@ statisticsWindow::statisticsWindow(int deltaFontSize)
 
 void statisticsWindow::compute(bool elementQuality)
 {
-#if 0
-  // MINIMUM ANGLES
-  double minAngle = 120.0;
-  double meanAngle = 0.0;
-  int count = 0;
-  std::vector<GEntity*> entities;
-  GModel::current()->getEntities(entities);
-  std::map<int, std::vector<double> > d;
-  for(unsigned int i = 0; i < entities.size(); i++){
-    if(entities[i]->dim() < 2) continue;
-    for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
-      MElement *e = entities[i]->getMeshElement(j);
-      double angle = e->angleShapeMeasure();
-      minAngle = std::min(minAngle, angle);
-      meanAngle += angle;
-      count++;
+#if 1
+  {
+    // MINIMUM ANGLES
+    double minAngle = 120.0;
+    double meanAngle = 0.0;
+    int count = 0;
+    std::vector<GEntity*> entities;
+    GModel::current()->getEntities(entities);
+    std::map<int, std::vector<double> > d;
+    for(unsigned int i = 0; i < entities.size(); i++){
+      if(entities[i]->dim() < 2) continue;
+      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
+	MElement *e = entities[i]->getMeshElement(j);
+	double angle = e->angleShapeMeasure();
+	minAngle = std::min(minAngle, angle);
+	meanAngle += angle;
+	count++;
+      }
     }
+    meanAngle  = meanAngle / count;
+    printf("Angles = min=%g av=%g \n", minAngle, meanAngle);
   }
-  meanAngle  = meanAngle / count;
-  printf("Angles = min=%g av=%g \n", minAngle, meanAngle);
 
-  // MESH DEGREE VERTICES
-  std::set<MEdge, Less_Edge> edges;
-  GModel::current()->getEntities(entities);
-  std::map<MVertex*, int > vert2Deg;
-  for(unsigned int i = 0; i < entities.size(); i++){
-    if(entities[i]->dim() < 2 ) continue;
-    if(entities[i]->tag() < 100) continue;
-    for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
-      MElement *e =  entities[i]->getMeshElement(j);
-      for(unsigned int k = 0; k < e->getNumEdges(); k++){
-  	edges.insert(e->getEdge(k));
-      }
-      for(unsigned int k = 0; k < e->getNumVertices(); k++){
-  	MVertex *v = e->getVertex(k);
-  	if (v->onWhat()->dim() < 2) continue; 
-  	std::map<MVertex*, int >::iterator it = vert2Deg.find(v);
-  	if (it == vert2Deg.end()) {
-  	  vert2Deg.insert(std::make_pair(v,1));
-  	}
-  	else{
-  	  int nbE = it->second+1;
-  	  it->second = nbE;
-  	}
+  {
+    // MESH DEGREE VERTICES
+    std::vector<GEntity*> entities;
+    std::set<MEdge, Less_Edge> edges;
+    GModel::current()->getEntities(entities);
+    std::map<MVertex*, int > vert2Deg;
+    for(unsigned int i = 0; i < entities.size(); i++){
+      if(entities[i]->dim() < 2 ) continue;
+      //      if(entities[i]->tag() < 100) continue;
+      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
+	MElement *e =  entities[i]->getMeshElement(j);
+	for(unsigned int k = 0; k < e->getNumEdges(); k++){
+	  edges.insert(e->getEdge(k));
+	}
+	for(unsigned int k = 0; k < e->getNumVertices(); k++){
+	  MVertex *v = e->getVertex(k);
+	  if (v->onWhat()->dim() < 2) continue; 
+	  std::map<MVertex*, int >::iterator it = vert2Deg.find(v);
+	  if (it == vert2Deg.end()) {
+	    vert2Deg.insert(std::make_pair(v,1));
+	  }
+	  else{
+	    int nbE = it->second+1;
+	    it->second = nbE;
+	  }
+	}
       }
     }
-  }
-  int dMin = 10;
-  int dMax = 0;
-  int d4 = 0;
-  int nbElems = vert2Deg.size();
-  std::map<MVertex*, int >::const_iterator itmap = vert2Deg.begin();
-  for(; itmap !=vert2Deg.end(); itmap++){
-    MVertex *v = itmap->first;
-    int nbE =  itmap->second;
-    dMin = std::min(nbE, dMin);
-    dMax = std::max(nbE, dMax);
-    if (nbE == 4) d4 += 1;
-  }
-  if (nbElems > 0)
-    printf("Stats degree vertices: dMin=%d , dMax=%d, d4=%g \n",
-           dMin, dMax, (double)d4/nbElems);
-
-  FieldManager *fields = GModel::current()->getFields();
-  Field *f = fields->get(fields->background_field);
-  int nbEdges = edges.size();
-  printf("nb edges =%d \n", nbEdges);
-  system("rm qualEdges.txt");
-  FILE *fp = fopen("qualEdges.txt", "w");
-  std::vector<int> qualE;
-  int nbS = 50;
-  qualE.resize(nbS);
-  if(fields->background_field > 0){
-    printf("found field \n");
-    std::set<MEdge, Less_Edge>::iterator it = edges.begin();
-    double sum = 0;
-    for (; it !=edges.end();++it){
-      MVertex *v0 = it->getVertex(0);
-      MVertex *v1 = it->getVertex(1);
-      double l = sqrt((v0->x()-v1->x())*(v0->x()-v1->x())+
-  		      (v0->y()-v1->y())*(v0->y()-v1->y())+
-  		      (v0->z()-v1->z())*(v0->z()-v1->z()));
-      double lf =  (*f)(0.5*(v0->x()+v1->x()), 0.5*(v0->y()+v1->y()),
-                        0.5*(v0->z()+v1->z()),v0->onWhat());
-      double el = l/lf;
-      int index = (int) ceil(el*nbS*0.5);
-      qualE[index]+= 1;
-      double e = (l>lf) ? lf/l : l/lf;
-      sum += e - 1.0;
+    int dMin = 10;
+    int dMax = 0;
+    int d4 = 0;
+    int nbElems = vert2Deg.size();
+    std::map<MVertex*, int >::const_iterator itmap = vert2Deg.begin();
+    for(; itmap !=vert2Deg.end(); itmap++){
+      MVertex *v = itmap->first;
+      int nbE =  itmap->second;
+      dMin = std::min(nbE, dMin);
+      dMax = std::max(nbE, dMax);
+      if (nbE == 4) d4 += 1;
     }
-    double tau = exp ((1./edges.size()) * sum);
-    printf("N edges = %d tau = %g\n",(int)edges.size(),tau);
-
-    double ibegin = 2./(2*nbS);
-    double inext = 2./nbS;
-    for (int i= 0; i< qualE.size(); i++){
-      fprintf(fp, "0 0 0 0 %g 0 0 %g \n", ibegin+i*inext , (double)qualE[i]/nbEdges);
+    if (nbElems > 0)
+      printf("Stats degree vertices: dMin=%d , dMax=%d, d4=%g \n",
+	     dMin, dMax, (double)d4/nbElems);
+    FieldManager *fields = GModel::current()->getFields();
+    Field *f = fields->get(fields->background_field);
+    int nbEdges = edges.size();
+    printf("nb edges =%d \n", nbEdges);
+    system("rm qualEdges.txt");
+    FILE *fp = fopen("qualEdges.txt", "w");
+    std::vector<int> qualE;
+    int nbS = 50;
+    qualE.resize(nbS);
+    if(fields->background_field > 0){
+      printf("found field \n");
+      std::set<MEdge, Less_Edge>::iterator it = edges.begin();
+      double sum = 0;
+      for (; it !=edges.end();++it){
+	MVertex *v0 = it->getVertex(0);
+	MVertex *v1 = it->getVertex(1);
+	double l = sqrt((v0->x()-v1->x())*(v0->x()-v1->x())+
+			(v0->y()-v1->y())*(v0->y()-v1->y())+
+			(v0->z()-v1->z())*(v0->z()-v1->z()));
+	double lf =  (*f)(0.5*(v0->x()+v1->x()), 0.5*(v0->y()+v1->y()),
+			  0.5*(v0->z()+v1->z()),v0->onWhat());
+	double el = l/lf;
+	int index = (int) ceil(el*nbS*0.5);
+	qualE[index]+= 1;
+	double e = (l>lf) ? lf/l : l/lf;
+	sum += e - 1.0;
+      }
+      double tau = exp ((1./edges.size()) * sum);
+      printf("N edges = %d tau = %g\n",(int)edges.size(),tau);
+      
+      double ibegin = 2./(2*nbS);
+      double inext = 2./nbS;
+      for (int i= 0; i< qualE.size(); i++){
+	fprintf(fp, "0 0 0 0 %g 0 0 %g \n", ibegin+i*inext , (double)qualE[i]/nbEdges);
+      }
+      
     }
-
+    fclose(fp);
   }
-  fclose(fp);
-
-  std::vector<GEntity*> entities;
-  std::set<MEdge, Less_Edge> edges;
-  GModel::current()->getEntities(entities);
-  std::map<MVertex*, int > vert2Deg;
-  for(unsigned int i = 0; i < entities.size(); i++){
-	if(entities[i]->dim() < 2 ) continue;
-	if(entities[i]->tag() != 10) continue;
-	for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
-	  MElement *e =  entities[i]->getMeshElement(j);
-	  for(unsigned int k = 0; k < e->getNumEdges(); k++){
-	    edges.insert(e->getEdge(k));
+  {
+    std::vector<GEntity*> entities;
+    std::set<MEdge, Less_Edge> edges;
+    GModel::current()->getEntities(entities);
+    std::map<MVertex*, int > vert2Deg;
+    for(unsigned int i = 0; i < entities.size(); i++){
+      if(entities[i]->dim() < 2 ) continue;
+      if(entities[i]->tag() != 10) continue;
+      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
+	MElement *e =  entities[i]->getMeshElement(j);
+	for(unsigned int k = 0; k < e->getNumEdges(); k++){
+	  edges.insert(e->getEdge(k));
+	}
+	for(unsigned int k = 0; k < e->getNumVertices(); k++){
+	  MVertex *v = e->getVertex(k);
+	  if (v->onWhat()->dim() < 2) continue; 
+	  std::map<MVertex*, int >::iterator it = vert2Deg.find(v);
+	  if (it == vert2Deg.end()){
+	    vert2Deg.insert(std::make_pair(v,1));
 	  }
-	  for(unsigned int k = 0; k < e->getNumVertices(); k++){
-	    MVertex *v = e->getVertex(k);
-   	    if (v->onWhat()->dim() < 2) continue; 
-   	    std::map<MVertex*, int >::iterator it = vert2Deg.find(v);
-   	    if (it == vert2Deg.end()){
-   	      vert2Deg.insert(std::make_pair(v,1));
-   	    }
-   	    else{
-   	      int nbE = it->second+1;
-   	      it->second = nbE;
-   	    }
+	  else{
+	    int nbE = it->second+1;
+	    it->second = nbE;
 	  }
 	}
-  }
-  int dMin = 10;
-  int dMax = 0;
-  int d4 = 0;
-  int nbElems = vert2Deg.size();
-  std::map<MVertex*, int >::const_iterator itmap = vert2Deg.begin();
-  for(; itmap !=vert2Deg.end(); itmap++){
-    MVertex *v = itmap->first;
-	int nbE =  itmap->second;
-	dMin = std::min(nbE, dMin);
-	dMax = std::max(nbE, dMax);
-	if (nbE == 4) d4 += 1;
-  }
-  if (nbElems > 0) printf("Stats degree vertices: dMin=%d , dMax=%d, d4=%g \n",
-                          dMin, dMax, (double)d4/nbElems);
-  FieldManager *fields = GModel::current()->getFields();
-  Field *f = fields->get(fields->background_field);
-  int nbEdges = edges.size();
-  system("rm qualEdges.txt");
-  FILE *fp = fopen("qualEdges.txt", "w");
-  std::vector<int> qualE;
-  int nbS = 50;
-  qualE.resize(nbS);
-  if(fields->background_field > 0){
-    std::set<MEdge, Less_Edge>::iterator it = edges.begin();
-    double sum = 0;
-    for (; it !=edges.end();++it){
-      MVertex *v0 = it->getVertex(0);
-      MVertex *v1 = it->getVertex(1);
-      double l = sqrt((v0->x()-v1->x())*(v0->x()-v1->x())+
-                      (v0->y()-v1->y())*(v0->y()-v1->y())+
-                      (v0->z()-v1->z())*(v0->z()-v1->z()));
-      double lf =  (*f)(0.5*(v0->x()+v1->x()), 0.5*(v0->y()+v1->y()),
-                        0.5*(v0->z()+v1->z()),v0->onWhat());
-      double el = l/lf;
-      int index = (int) ceil(el*nbS*0.5);
-      qualE[index]+= 1;
-      double e = (l>lf) ? lf/l : l/lf;
-      sum += e - 1.0;
+      }
+    }
+    int dMin = 10;
+    int dMax = 0;
+    int d4 = 0;
+    int nbElems = vert2Deg.size();
+    std::map<MVertex*, int >::const_iterator itmap = vert2Deg.begin();
+    for(; itmap !=vert2Deg.end(); itmap++){
+      MVertex *v = itmap->first;
+      int nbE =  itmap->second;
+      dMin = std::min(nbE, dMin);
+      dMax = std::max(nbE, dMax);
+      if (nbE == 4) d4 += 1;
     }
-    double tau = exp ((1./edges.size()) * sum);
-    double ibegin = 2./(2*nbS);
-    double inext = 2./nbS;
-    for (int i= 0; i< qualE.size(); i++){
-      fprintf(fp, "0 0 0 0 %g 0 0 %g \n", ibegin+i*inext , (double)qualE[i]/nbEdges);
+    if (nbElems > 0) printf("Stats degree vertices: dMin=%d , dMax=%d, d4=%g \n",
+			    dMin, dMax, (double)d4/nbElems);
+    FieldManager *fields = GModel::current()->getFields();
+    Field *f = fields->get(fields->background_field);
+    int nbEdges = edges.size();
+    system("rm qualEdges.txt");
+    FILE *fp = fopen("qualEdges.txt", "w");
+    std::vector<int> qualE;
+    int nbS = 50;
+    qualE.resize(nbS);
+    if(fields->background_field > 0){
+      std::set<MEdge, Less_Edge>::iterator it = edges.begin();
+      double sum = 0;
+      for (; it !=edges.end();++it){
+	MVertex *v0 = it->getVertex(0);
+	MVertex *v1 = it->getVertex(1);
+	double l = sqrt((v0->x()-v1->x())*(v0->x()-v1->x())+
+			(v0->y()-v1->y())*(v0->y()-v1->y())+
+			(v0->z()-v1->z())*(v0->z()-v1->z()));
+	double lf =  (*f)(0.5*(v0->x()+v1->x()), 0.5*(v0->y()+v1->y()),
+			  0.5*(v0->z()+v1->z()),v0->onWhat());
+	double el = l/lf;
+	int index = (int) ceil(el*nbS*0.5);
+	qualE[index]+= 1;
+	double e = (l>lf) ? lf/l : l/lf;
+	sum += e - 1.0;
+      }
+      double tau = exp ((1./edges.size()) * sum);
+      double ibegin = 2./(2*nbS);
+      double inext = 2./nbS;
+      for (int i= 0; i< qualE.size(); i++){
+	fprintf(fp, "0 0 0 0 %g 0 0 %g \n", ibegin+i*inext , (double)qualE[i]/nbEdges);
+      }
     }
+    fclose(fp);
   }
-  fclose(fp);
 #endif
-
+  
   int num = 0;
   static double s[50];
   static char label[50][256];
diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp
index 455a53e182..53cefb61b4 100644
--- a/Geo/GFace.cpp
+++ b/Geo/GFace.cpp
@@ -908,7 +908,7 @@ SPoint2 GFace::parFromPoint(const SPoint3 &p, bool onSurface) const
   return SPoint2(U, V);
 }
 
-#if defined(QUASINEWTON)
+#if defined(HAVE_BFGS)
 // Callback function for BFGS
 void bfgs_callback(const alglib::real_1d_array& x, double& func, alglib::real_1d_array& grad, void* ptr) {
   data_wrapper* w = static_cast<data_wrapper*>(ptr);
@@ -917,26 +917,29 @@ void bfgs_callback(const alglib::real_1d_array& x, double& func, alglib::real_1d
 
   // Value of the objective
   GPoint pnt = gf->point(x[0], x[1]);
-  SPoint3 spnt(pnt.x(), pnt.y(), pnt.z());
-  func = p.distance(spnt);
+  func = 0.5 * 
+    ( p.x() - pnt.x() ) * ( p.x() - pnt.x() ) +
+    ( p.y() - pnt.y() ) * ( p.y() - pnt.y() ) +
+    ( p.z() - pnt.z() ) * ( p.z() - pnt.z() ) ;
   //printf("func : %f\n", func);
 
   // Value of the gradient
-  std::vector<double> values(2);
   Pair<SVector3, SVector3> der = gf->firstDer(SPoint2(x[0], x[1]));
-  grad[0] = -2./(2.0*func) * (der.left().x() + der.left().y() + der.left().z());
-  grad[1] = -2./(2.0*func) * (der.right().x() + der.right().y() + der.right().z());
-  //printf("Gradients %f %f\n", grad[0], grad[1]);
+  grad[0] = -(p.x() - pnt.x()) * der.left().x()  - (p.y() - pnt.y()) * der.left().y()  - (p.z() - pnt.z()) * der.left().z(); 
+  grad[1] = -(p.x() - pnt.x()) * der.right().x() - (p.y() - pnt.y()) * der.right().y() - (p.z() - pnt.z()) * der.right().z(); 
+  //  printf("func %22.15E Gradients %22.15E %22.15E der %g %g %g\n",func, grad[0], grad[1],der.left().x(),der.left().y(),der.left().z());
 }
 #endif
 
 GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[2]) const
 {
-#if defined(QUASINEWTON)
-
+#if defined(HAVE_BFGS)
   //
   // Creating the optimisation problem
   //
+
+  //  printf("STARTING OPTIMIZATION\n");
+
   alglib::ae_int_t dim = 2;
   alglib::ae_int_t corr = 2; // Num of corrections in the scheme in [3,7]
   alglib::minlbfgsstate state;
@@ -950,16 +953,21 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[
   Range<double> uu = parBounds(0);
   Range<double> vv = parBounds(1);
 
-  double initial_guesses = 1000.0;
-  for(double u = uu.low(); u<=uu.high(); u+=(uu.high()-uu.low())/initial_guesses) {
-    printf("%f\n", u);
-    for(double v = vv.low(); v<=vv.high(); v+=(vv.high()-vv.low())/initial_guesses) {
+  //  FILE *F = fopen ("hop.pos","w");
+  //  fprintf(F,"View \" \" {\n");
+  //  fprintf(F,"SP(%g,%g,%g) {%g};\n",queryPoint.x(),queryPoint.y(),queryPoint.z(),0.0);
+  double initial_guesses = 10.0;
+  for(double u = uu.low(); u<=uu.high()+1.e-5; u+=(uu.high()-uu.low())/initial_guesses) {
+    //    printf("%f\n", u);
+    for(double v = vv.low(); v<=vv.high()+1.e-5; v+=(vv.high()-vv.low())/initial_guesses) {
       GPoint pnt = point(u, v);
-      printf("(point) : %f %f %f\n", pnt.x(), pnt.y(), pnt.z());
       SPoint3 spnt(pnt.x(), pnt.y(), pnt.z());
       double dist = queryPoint.distance(spnt);
+      //      fprintf(F,"SP(%g,%g,%g) {%g};\n",pnt.x(), pnt.y(), pnt.z(),dist);
+      //      printf("lmocal (%12.5E %12.5E) (point) : %12.5E %12.5E %12.5E (query) : %12.5E %12.5E %12.5E DSIT %12.5E\n",u,v, pnt.x(), pnt.y(), pnt.z(),queryPoint.x(),queryPoint.y(),queryPoint.z(),
+      //	     dist);
       if (dist < min_dist) {
-	printf("min_dist %f\n", dist);
+	//	printf("min_dist %f\n", dist);
 	min_dist = dist;
 	min_u = u;
 	min_v = v;
@@ -967,25 +975,27 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[
       }
     }
   }
-
+  //  fprintf(F,"};\n");
+  //  fclose(F);
+  //  getchar();
   initial_conditions[0] = min_u;
   initial_conditions[1] = min_v;
 
-  printf("Initial conditions : %f %f\n", min_u, min_v);
+  //  printf("Initial conditions : %f %f %12.5E\n", min_u, min_v,min_dist);
   GPoint pnt = point(min_u, min_v);
-  printf("Initial conditions (point) : %f %f %f\n", pnt.x(), pnt.y(), pnt.z());
+  //    printf("Initial conditions (point) : %f %f %f local (%g %g) Looking for %f %f %f DIST = %12.5E\n", 
+  //  	 pnt.x(), pnt.y(), pnt.z(),min_u,min_v,
+  //  	 queryPoint.x(),queryPoint.y(),queryPoint.z(),
+  //  	 min_dist);
 
   x.setcontent(dim, &initial_conditions[0]);
 
-
-
-
   minlbfgscreate(2, corr, x, state);
 
   //
   // Defining the stopping criterion
   //
-  double epsg = 0.0;
+  double epsg = 1.e-12;
   double epsf = 0.0;
   double epsx = 0.0;
   alglib::ae_int_t maxits = 500;
@@ -1009,7 +1019,25 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[
 
   minlbfgsresults(state,x,rep);
 
-  return point(x[0],x[1]);
+  GPoint pntF = point(x[0], x[1]);
+  if (rep.terminationtype != 4){
+    //    printf("Initial conditions (point) : %f %f %f local (%g %g) Looking for %f %f %f DIST = %12.5E at the end (%f %f) %f %f %f\n", 
+    //  	 pnt.x(), pnt.y(), pnt.z(),min_u,min_v,
+    //  	 queryPoint.x(),queryPoint.y(),queryPoint.z(),
+    //  	 min_dist,x[0],x[1],pntF.x(), pntF.y(), pntF.z());
+    //    double DDD = 
+    //      ( queryPoint.x() - pntF.x()) * ( queryPoint.x() - pntF.x()) +
+    //      ( queryPoint.y() - pntF.y()) * ( queryPoint.y() - pntF.y()) +
+    //      ( queryPoint.z() - pntF.z()) * ( queryPoint.z() - pntF.z());
+    //    if (sqrt(DDD) > 1.e-4)
+      /*
+      printf("Initial conditions (point) : %f %f %f local (%g %g) Looking for %f %f %f DIST = %12.5E at the end (%f %f) %f %f %f termination %d\n", 
+	     pnt.x(), pnt.y(), pnt.z(),min_u,min_v,
+	     queryPoint.x(),queryPoint.y(),queryPoint.z(),
+	     min_dist,x[0],x[1],pntF.x(), pntF.y(), pntF.z(),rep.terminationtype);      
+      */
+  }
+  return pntF;
 #else
   Msg::Error("Closest point not implemented for this type of surface");
   SPoint2 p = parFromPoint(queryPoint, false);
diff --git a/Geo/Geo.cpp b/Geo/Geo.cpp
index c17f99e359..607b603716 100644
--- a/Geo/Geo.cpp
+++ b/Geo/Geo.cpp
@@ -3259,7 +3259,7 @@ bool ProjectPointOnSurface(Surface *s, Vertex &p, double uv[2])
       p = InterpolateSurface(s, x(0), x(1), 0, 0);
       uv[0] = x(0);
       uv[1] = x(1);
-      if (ITER > 0)
+      if (ITER >= 0)
         Msg::Info("ProjectPoint (%g,%g,%g) On Surface %d converged after %d iterations",
                   p.Pos.X, p.Pos.Y, p.Pos.Z, s->Num, ITER);
       return true;
diff --git a/Geo/GeoInterpolation.cpp b/Geo/GeoInterpolation.cpp
index 464dcd318f..ed1e23b88a 100644
--- a/Geo/GeoInterpolation.cpp
+++ b/Geo/GeoInterpolation.cpp
@@ -295,8 +295,8 @@ Vertex InterpolateCurve(Curve *c, double u, int derivee)
   switch (c->Typ) {
 
   case MSH_SEGM_LINE:
-#if defined(QUASINEWTON)
-    printf("MSH_SEGM_LINE\n");
+#if defined(HAVE_BFGS)
+    //    printf("MSH_SEGM_LINE\n");
 #endif
     N = List_Nbr(c->Control_Points);
     i = (int)((double)(N - 1) * u);
@@ -418,8 +418,8 @@ Vertex InterpolateCurve(Curve *c, double u, int derivee)
     break;
 
   case MSH_SEGM_DISCRETE:
-#if defined(QUASINEWTON)
-    printf("MSH_SEGM_DISCRETE\n");
+#if defined(HAVE_BFGS)
+    //    printf("MSH_SEGM_DISCRETE\n");
 #endif
 
     Msg::Debug("Cannot interpolate discrete curve");
@@ -463,9 +463,41 @@ static Vertex TransfiniteQua(Vertex c1, Vertex c2, Vertex c3, Vertex c4,
 
 // Interpolation transfinie sur un triangle : TRAN_QUA avec s1=s4=c4
 // f(u,v) = u c2 (v) + (1-v) c1(u) + v c3(u) - u(1-v) s2 - uv s3
+//           
+//            s3(1,1)
+//              +
+//            / |
+//      c3  /   |       
+//        /     |  c2
+//      /       |
+//    /   c1    |
+//   +----------+
+//  s1(0,0)     s2(1,0)
+
+// u = v = 0     -----> x = c1(0) = s1 --> OK  
+// u = 1 ; v = 0 -----> x = c2(0) + c1(1) - s2 =  s2 --> OK  
+// u = 1 ; v = 1 -----> x = c2(1) + c3(1) - s3 =  s3 --> OK  
+// v = 0 --> u s2 + c1(u) - u s2 --> x = c1(u) --> OK
+// u = 1 --> c2(v) + (1-v) s2 + v s3 -(1-v) s2  - v s3 --> x = c2(v) --> OK
+// u = 0 --> (1-v) s1 + v s1 = s1 !!! not terrible (singular)
+
+// Transfinite approximation on a triangle
+
+// f(u,v) = (1-u) (c1(u-v) + c3(1-v)     - s1) +
+//          (u-v) (c2(v)   + c1(u)       - s2) +
+//            v   (c3(1-u) + c2(1-u+v)   - s3) 
+// 
+// u = v = 0 --> f(0,0) = s1 + s1 - s1     = s1 
+// u = v = 1 --> f(1,1) = s3 + s3 - s3     = s3 
+// u = 1 ; v = 0 --> f(1,1) = s2 + s2 - s2 = s2 
+// v = 0 --> (1-u)c1(u) + u c1(u) = c1(u) --> COOL
+
 
 #define TRAN_TRI(c1,c2,c3,s1,s2,s3,u,v) u*c2+(1.-v)*c1+v*c3-(u*(1.-v)*s2+u*v*s3);
 
+#define TRAN_TRIB(c1,c1b,c2,c2b,c3,c3b,s1,s2,s3,u,v) (1.-u)*(c1+c3b-s1)+(u-v)*(c2+c1b-s2)+v*(c3+c2b-s3);
+
+
 static Vertex TransfiniteTri(Vertex c1, Vertex c2, Vertex c3,
                              Vertex s1, Vertex s2, Vertex s3, double u, double v)
 {
@@ -480,6 +512,23 @@ static Vertex TransfiniteTri(Vertex c1, Vertex c2, Vertex c3,
                      s1.Pos.Z, s2.Pos.Z, s3.Pos.Z, u, v);
   return V;
 }
+static Vertex TransfiniteTriB(Vertex c1, Vertex c1b, Vertex c2,
+			      Vertex c2b, Vertex c3, Vertex c3b,
+			      Vertex s1, Vertex s2, Vertex s3, 
+			      double u, double v)
+{
+  Vertex V;
+  V.lc = TRAN_TRIB(c1.lc,c1b.lc, c2.lc,c2b.lc, c3.lc, c3b.lc, s1.lc, s2.lc, s3.lc, u, v);
+  V.w = TRAN_TRIB(c1.w, c1b.w, c2.w,c2b.w, c3.w,c3b.w, s1.w, s2.w, s3.w, u, v);
+  V.Pos.X = TRAN_TRIB(c1.Pos.X, c1b.Pos.X,c2.Pos.X, c2b.Pos.X,c3.Pos.X,c3b.Pos.X,
+                     s1.Pos.X, s2.Pos.X, s3.Pos.X, u, v);
+  V.Pos.Y = TRAN_TRIB(c1.Pos.Y, c1b.Pos.Y,c2.Pos.Y, c2b.Pos.Y,c3.Pos.Y,c3b.Pos.Y,
+                     s1.Pos.Y, s2.Pos.Y, s3.Pos.Y, u, v);
+  V.Pos.Z = TRAN_TRIB(c1.Pos.Z, c1b.Pos.Z,c2.Pos.Z, c2b.Pos.Z,c3.Pos.Z,c3b.Pos.Z,
+                     s1.Pos.Z, s2.Pos.Z, s3.Pos.Z, u, v);
+  return V;
+}
+
 
 static void TransfiniteSph(Vertex S, Vertex center, Vertex *T)
 {
@@ -592,7 +641,7 @@ static Vertex InterpolateRuledSurface(Surface *s, double u, double v)
     }
   }
   
-  Vertex *S[4], V[4], T;
+  Vertex *S[4], V[4],VB[3], T;
   if(s->Typ == MSH_SURF_REGL && List_Nbr(s->Generatrices) >= 4){
     S[0] = C[0]->beg;
     S[1] = C[1]->beg;
@@ -602,8 +651,9 @@ static Vertex InterpolateRuledSurface(Surface *s, double u, double v)
     V[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * v, 0);
     V[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - u), 0);
     V[3] = InterpolateCurve(C[3], C[3]->ubeg + (C[3]->uend - C[3]->ubeg) * (1. - v), 0);
-#if defined(QUASINEWTON)
-    printf("----- u %f v %f\n", u, v);
+    /*
+#if defined(HAVE_BFGS)
+    printf("----- u %f v %f %g %g\n", u, v,C[1]->ubeg,C[1]->uend);
     printf("S[0] %f %f %f\n", S[0]->Pos.X, S[0]->Pos.Y,S[0]->Pos.Z);
     printf("S[1] %f %f %f\n", S[1]->Pos.X, S[1]->Pos.Y,S[1]->Pos.Z);
     printf("S[2] %f %f %f\n", S[2]->Pos.X, S[2]->Pos.Y,S[2]->Pos.Z);
@@ -613,6 +663,7 @@ static Vertex InterpolateRuledSurface(Surface *s, double u, double v)
     printf("V[2] %f %f %f\n", V[2].Pos.X, V[2].Pos.Y,V[2].Pos.Z);
     printf("V[3] %f %f %f\n", V[3].Pos.X, V[3].Pos.Y,V[3].Pos.Z);
 #endif
+    */
     T = TransfiniteQua(V[0], V[1], V[2], V[3], *S[0], *S[1], *S[2], *S[3], u, v);
     if(isSphere) TransfiniteSph(*S[0], *O, &T);
   }
@@ -620,11 +671,23 @@ static Vertex InterpolateRuledSurface(Surface *s, double u, double v)
     S[0] = C[0]->beg;
     S[1] = C[1]->beg;
     S[2] = C[2]->beg;
+    /*
     V[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * u, 0);
     V[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * v, 0);
     V[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - u), 0);
     T = TransfiniteTri(V[0], V[1], V[2], *S[0], *S[1], *S[2], u, v);
-    if(isSphere) TransfiniteSph(*S[0], *O, &T);
+    */
+    V[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * (u-v), 0);
+    V[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * v, 0);
+    V[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - u), 0);
+    VB[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * u, 0);
+    VB[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * (1-u+v), 0);
+    VB[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - v), 0);
+    T = TransfiniteTriB(V[0],VB[0], V[1],VB[1], V[2],VB[2], *S[0], *S[1], *S[2], u, v);
+    
+    if(isSphere) {
+      TransfiniteSph(*S[0], *O, &T);
+    }
   }
 
   return T;
diff --git a/Geo/GeomMeshMatcher.cpp b/Geo/GeomMeshMatcher.cpp
index e498931d95..76f9ec1030 100644
--- a/Geo/GeomMeshMatcher.cpp
+++ b/Geo/GeomMeshMatcher.cpp
@@ -132,7 +132,7 @@ GeomMeshMatcher::matchVertices(GModel* m1, GModel *m2, bool& ok)
     }
 
     if (best_score != DBL_MAX) {
-      Msg::Info("Vertices %i (geom) and %i (mesh) match.\n",
+      Msg::Info("Model Vertex %i (geom) and %i (mesh) match",
                 (*entity1)->tag(),
                 best_candidate_ge->tag());
 
@@ -154,7 +154,7 @@ GeomMeshMatcher::matchVertices(GModel* m1, GModel *m2, bool& ok)
   //vert++)
     //m2->add(*vert);
 
-  Msg::Info("Vertices matched : %i / %i (%i)\n", num_matched_vertices, num_total_vertices, num_mesh_vertices);
+  Msg::Info("Vertices matched : %i / %i (%i)", num_matched_vertices, num_total_vertices, num_mesh_vertices);
   //if(num_matched_vertices != num_total_vertices) ok = false;
   return (coresp_v);
 }
@@ -570,7 +570,7 @@ int GeomMeshMatcher::forceTomatch(GModel *geom, GModel *mesh, const double TOL)
       }
     }
   }
-  printf("creating faces\n");
+  //  printf("creating faces\n");
   for (GModel::fiter it = mesh->firstFace(); it != mesh->lastFace(); ++it){
     for (int i=0;i<(*it)->triangles.size();i++){
       MVertex *v1 = geom->getMeshVertexByTag((*it)->triangles[i]->getVertex(0)->getNum());
@@ -608,6 +608,7 @@ static void copy_vertices (GVertex *to, GVertex *from, std::map<MVertex*,MVertex
   }
 }
 static void copy_vertices (GRegion *to, GRegion *from, std::map<MVertex*,MVertex*> &_mesh_to_geom){
+  to->deleteMesh();
   for (int i=0;i<from->mesh_vertices.size();i++){
     MVertex *v_from = from->mesh_vertices[i];
     MVertex *v_to = new MVertex (v_from->x(),v_from->y(),v_from->z(), to);
@@ -621,23 +622,30 @@ static void copy_vertices (GEdge *to, GEdge *from, std::map<MVertex*,MVertex*> &
     MVertex *v_from = from->mesh_vertices[i];
     double t;
     GPoint gp = to->closestPoint(SPoint3(v_from->x(),v_from->y(),v_from->z()), t );
-    MEdgeVertex *v_to = new MEdgeVertex (v_from->x(),v_from->y(),v_from->z(), to, t );
+    MEdgeVertex *v_to = new MEdgeVertex (gp.x(),gp.y(),gp.z(), to, gp.u() );
     to->mesh_vertices.push_back(v_to);
     _mesh_to_geom[v_from] = v_to;
   }
+  //  printf("Ending Edge %d %d vertices to match\n",from->tag(),from->mesh_vertices.size());
 }
-static void copy_vertices (GFace *to, GFace *from, std::map<MVertex*,MVertex*> &_mesh_to_geom){
-  printf("Starting Face %d, with %d vertices\n", to->tag(),  from->mesh_vertices.size());
-  for (int i=0;i<from->mesh_vertices.size();i++){
-    MVertex *v_from = from->mesh_vertices[i];
+static void copy_vertices (GFace *geom, GFace *mesh, std::map<MVertex*,MVertex*> &_mesh_to_geom){
+  //  printf("Starting Face %d, with %d vertices\n", geom->tag(),  mesh->mesh_vertices.size());
+  for (int i=0;i<mesh->mesh_vertices.size();i++){
+    MVertex *v_from = mesh->mesh_vertices[i];
     double uv[2];
-    GPoint gp = to->closestPoint ( SPoint3(v_from->x(),v_from->y(),v_from->z()), uv );
-    printf("Original point %f %f %f\n", v_from->x(), v_from->y(), v_from->z());
-    printf("New point %f %f %f\n", gp.x(), gp.y(), gp.z());
-    MFaceVertex *v_to = new MFaceVertex (v_from->x(),v_from->y(),v_from->z(), to, uv[0],uv[1] );
-    to->mesh_vertices.push_back(v_to);
+    GPoint gp = geom->closestPoint ( SPoint3(v_from->x(),v_from->y(),v_from->z()), uv );
+    //    printf("Original point %f %f %f\n", v_from->x(), v_from->y(), v_from->z());
+    //    printf("New point %f %f %f\n", gp.x(), gp.y(), gp.z());
+    double DDD = ( v_from->x() - gp.x()) * ( v_from->x() - gp.x()) +
+      ( v_from->y() - gp.y()) * ( v_from->y() - gp.y()) +
+      ( v_from->z() - gp.z()) * ( v_from->z() - gp.z()) ;
+    if (sqrt(DDD) > 1.e-3)Msg::Error("Impossible to match one point Original point %f %f %f New point %f %f %f",
+				     v_from->x(), v_from->y(), v_from->z(),gp.x(), gp.y(), gp.z());
+    MFaceVertex *v_to = new MFaceVertex (v_from->x(),v_from->y(),v_from->z(), geom, gp.u(),gp.v() );
+    geom->mesh_vertices.push_back(v_to);
     _mesh_to_geom[v_from] = v_to;
   }
+  //  printf("Ending Face %d %d vertices to match\n",geom->tag(),geom->mesh_vertices.size());
 }
 
 template <class ELEMENT>
@@ -669,7 +677,7 @@ void copy_vertices (GModel *geom, GModel *mesh, std::map<MVertex*,MVertex*> &_me
 void copy_elements (GModel *geom, GModel *mesh, std::map<MVertex*,MVertex*> &_mesh_to_geom){
   // copy all elements
   for (GModel::viter vit = geom->firstVertex() ; vit != geom->lastVertex(); ++vit)
-    copy_elements<MPoint>((*vit)->points,mesh->getVertexByTag((*vit)->tag())->points,_mesh_to_geom);
+    if (mesh->getVertexByTag((*vit)->tag())) copy_elements<MPoint>((*vit)->points,mesh->getVertexByTag((*vit)->tag())->points,_mesh_to_geom);
   for (GModel::eiter eit = geom->firstEdge() ; eit != geom->lastEdge(); ++eit)
     copy_elements<MLine>((*eit)->lines,mesh->getEdgeByTag((*eit)->tag())->lines,_mesh_to_geom);
   for (GModel::fiter fit = geom->firstFace() ; fit != geom->lastFace(); ++fit) {
@@ -688,6 +696,7 @@ void copy_elements (GModel *geom, GModel *mesh, std::map<MVertex*,MVertex*> &_me
 int GeomMeshMatcher::match(GModel *geom, GModel *mesh)
 {
   mesh->createTopologyFromMesh();
+  GModel::setCurrent(geom);
   bool ok = true;
   // This will match VERTICES
   std::vector<Pair<GVertex*, GVertex*> > *coresp_v = matchVertices(geom, mesh,ok);
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index a47a61cc9e..5881e05096 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -271,13 +271,14 @@ double MElement::getJacobian(double u, double v, double w, double jac[3][3])
   double gsf[1256][3];
   getGradShapeFunctions(u, v, w, gsf);
   for (int i = 0; i < getNumShapeFunctions(); i++) {
-    const MVertex *v = getShapeFunctionNode(i);
+    const MVertex *ver = getShapeFunctionNode(i);
     double* gg = gsf[i];
-    for (int j = 0; j < 3; j++) {
-      jac[j][0] += v->x() * gg[j];
-      jac[j][1] += v->y() * gg[j];
-      jac[j][2] += v->z() * gg[j];
+    for (int j = 0; j < getDim(); j++) {
+      jac[j][0] += ver->x() * gg[j];
+      jac[j][1] += ver->y() * gg[j];
+      jac[j][2] += ver->z() * gg[j];
     }
+    //    printf("GSF (%d,%g %g) = %g %g \n",i,u,v,gg[0],gg[1]); 
   }
   return _computeDeterminantAndRegularize(this, jac);
 }
diff --git a/Geo/gmshEdge.cpp b/Geo/gmshEdge.cpp
index 41a1e62572..956763aae2 100644
--- a/Geo/gmshEdge.cpp
+++ b/Geo/gmshEdge.cpp
@@ -270,11 +270,11 @@ SPoint2 gmshEdge::reparamOnFace(const GFace *face, double epar,int dir) const
     }
     else if (C[2]->Num == c->Num) {
       U = 1-(epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ;
-      V = 1;
+      V = U;
     }
     else if (C[2]->Num == -c->Num) {
       U = 1-(C[2]->uend - epar - C[2]->ubeg) / (C[2]->uend - C[2]->ubeg) ;
-      V = 1;
+      V = U;
     }
     else{
       Msg::Info("Reparameterizing edge %d on face %d", c->Num, s->Num);
diff --git a/Geo/gmshFace.cpp b/Geo/gmshFace.cpp
index d2ae3d350d..4057afbdbd 100644
--- a/Geo/gmshFace.cpp
+++ b/Geo/gmshFace.cpp
@@ -217,9 +217,11 @@ GPoint gmshFace::point(double par1, double par2) const
   }
 }
 
-#if not defined(QUASINEWTON)
 GPoint gmshFace::closestPoint(const SPoint3 & qp, const double initialGuess[2]) const
 {
+#if defined(HAVE_BFGS)
+  return GFace::closestPoint(qp, initialGuess);
+#endif
   if (s->Typ == MSH_SURF_PLAN && !s->geometry){
     double XP = qp.x();
     double YP = qp.y();
@@ -258,7 +260,6 @@ GPoint gmshFace::closestPoint(const SPoint3 & qp, const double initialGuess[2])
     return GPoint(-1.e22, -1.e22, -1.e22, 0, u);
   return GPoint(v.Pos.X, v.Pos.Y, v.Pos.Z, this, u);
 }
-#endif
 
 SPoint2 gmshFace::parFromPoint(const SPoint3 &qp, bool onSurface) const
 {
diff --git a/Geo/gmshFace.h b/Geo/gmshFace.h
index ecd59489b9..b70242b3ef 100644
--- a/Geo/gmshFace.h
+++ b/Geo/gmshFace.h
@@ -22,10 +22,8 @@ class gmshFace : public GFace {
   Range<double> parBounds(int i) const; 
   void setModelEdges(std::list<GEdge*> &);
   virtual GPoint point(double par1, double par2) const;
-#if not defined(QUASINEWTON)
   virtual GPoint closestPoint(const SPoint3 &queryPoint, 
                               const double initialGuess[2]) const; 
-#endif
   virtual bool containsPoint(const SPoint3 &pt) const;  
   virtual double getMetricEigenvalue(const SPoint2 &);  
   virtual SVector3 normal(const SPoint2 &param) const; 
diff --git a/Geo/gmshVertex.cpp b/Geo/gmshVertex.cpp
index b4bf4ac2cd..985580e0ee 100644
--- a/Geo/gmshVertex.cpp
+++ b/Geo/gmshVertex.cpp
@@ -39,8 +39,11 @@ GEntity::GeomType gmshVertex::geomType() const
 
 SPoint2 gmshVertex::reparamOnFace(const GFace *face, int dir) const
 {
+
   Surface *s = (Surface*)face->getNativePtr();
 
+  //  printf("coucou HERE I AM %d\n",s->Typ);
+
   if(s->geometry){
     // It is not always right if it is periodic.
     if(l_edges.size() == 1 && 
@@ -91,6 +94,40 @@ SPoint2 gmshVertex::reparamOnFace(const GFace *face, int dir) const
     }
     return SPoint2(U, V);
   }
+  else if(s->Typ ==  MSH_SURF_TRIC){
+    //    printf("coucou HERE I AM TRIC\n");
+    Curve *C[3];
+    for(int i = 0; i < 3; i++)
+      List_Read(s->Generatrices, i, &C[i]);
+
+    double U, V;    
+    if ((C[0]->beg == v && C[2]->beg == v) ||
+        (C[0]->end == v && C[2]->beg == v) ||
+        (C[0]->beg == v && C[2]->end == v) ||
+        (C[0]->end == v && C[2]->end == v)){
+      U = V = 0;
+    }
+    else if ((C[0]->beg == v && C[1]->beg == v) ||
+             (C[0]->end == v && C[1]->beg == v) ||
+             (C[0]->beg == v && C[1]->end == v) ||
+             (C[0]->end == v && C[1]->end == v)){
+      U = 1;
+      V = 0;
+    }
+    else if ((C[2]->beg == v && C[1]->beg == v) ||
+             (C[2]->end == v && C[1]->beg == v) ||
+             (C[2]->beg == v && C[1]->end == v) ||
+             (C[2]->end == v && C[1]->end == v)){
+      U = 1;
+      V = 1;
+    }
+    else{
+      Msg::Info("Reparameterizing point %d on face %d", v->Num, s->Num);
+      return GVertex::reparamOnFace(face, dir);
+    }
+    //    printf("coucou1 %g %g\n",U,V);
+    return SPoint2(U, V);
+  }
   else{
     return GVertex::reparamOnFace(face, dir);
   }
diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp
index 605db6ccf9..4787d8071e 100644
--- a/Mesh/BackgroundMesh.cpp
+++ b/Mesh/BackgroundMesh.cpp
@@ -735,6 +735,17 @@ double backgroundMesh::operator() (double u, double v, double w) const
 
 double backgroundMesh::getAngle(double u, double v, double w) const
 {
+
+  // HACK FOR LEWIS 
+  // h = 1+30(y-x^2)^2  + (1-x)^2
+  //  double x = u;
+  //  double y = v;
+  //  double dhdx = 30 * 2 * (y-x*x) * (-2*x) - 2 * (1-x); 
+  //  double dhdy = 30 * 2 * (y-x*x); 
+  //  double angles = atan2(y,x*x);
+  //  crossField2d::normalizeAngle (angles);
+  //  return angles;
+
   double uv[3] = {u, v, w};
   double uv2[3];
   MElement *e = _octree->find(u, v, w, 2, true);
@@ -776,6 +787,15 @@ void backgroundMesh::print(const std::string &filename, GFace *gf,
               v1->x(),v1->y(),v1->z(),
               v2->x(),v2->y(),v2->z(),
               v3->x(),v3->y(),v3->z(),itv1->second,itv2->second,itv3->second);
+      /*
+      fprintf(f,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%g,%g,%g};\n",
+              v1->x(),v1->y(),v1->z(),
+              v2->x(),v2->y(),v2->z(),
+              v3->x(),v3->y(),v3->z(),
+	      getAngle(v1->x(),v1->y(),v1->z()),
+	      getAngle(v2->x(),v2->y(),v2->z()),
+	      getAngle(v3->x(),v3->y(),v3->z()));
+      */
     }
     else {
       /*
diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp
index 50461ab573..c7e17705f0 100644
--- a/Mesh/HighOrder.cpp
+++ b/Mesh/HighOrder.cpp
@@ -41,7 +41,28 @@ static void myresid(int N, GEdge *ge, double *u, fullVector<double> &r)
   for (int i = 0; i < N - 2; i++) r(i) = L[i + 1] - L[i];
 }
 
-static bool computeEquidistantParameters(GEdge *ge, double u0, double uN, int N, 
+static bool computeEquidistantParameters1(GEdge *ge, double u0, double uN, int N, 
+                                         double *u, double underRelax)
+{
+  GPoint p0 = ge->point(u0);
+  GPoint p1 = ge->point(uN);
+  double du = 1. / (N - 1);
+  u[0] = u0;
+  //  printf("starting with %g %g %g\n",p0.x(),p0.y(),u0);
+  //  printf("ending   with %g %g %g\n",p1.x(),p1.y(),uN);
+  for (int i = 1; i < N; i++){
+    SPoint3 pi (p0.x() + i * du * (p1.x()-p0.x()),
+		p0.y() + i * du * (p1.y()-p0.y()),
+		p0.z() + i * du * (p1.z()-p0.z()));
+    double t;
+    GPoint gp = ge->closestPoint(pi, t);		
+    u[i] = gp.u();
+    //    printf("going to %g %g u %g\n",pi.x(),pi.y(),gp.u());
+  }  
+  return true;
+}
+
+static bool computeEquidistantParameters0(GEdge *ge, double u0, double uN, int N, 
                                          double *u, double underRelax)
 {
   const double PRECISION = 1.e-6;
@@ -100,6 +121,15 @@ static bool computeEquidistantParameters(GEdge *ge, double u0, double uN, int N,
   }
   return false;
 }
+// 1 = geodesics
+static int method_for_computing_intermediary_points = 0;
+static bool computeEquidistantParameters(GEdge *ge, double u0, double uN, int N, 
+                                         double *u, double underRelax){
+  if (method_for_computing_intermediary_points == 0) // use linear abscissa
+    return computeEquidistantParameters0(ge,u0,uN,N,u,underRelax);
+  else if (method_for_computing_intermediary_points == 1) // use projection
+    return computeEquidistantParameters1(ge,u0,uN,N,u,underRelax);  
+}
 
 static double mylength(GFace *gf, int i, double *u, double *v)
 {
@@ -113,7 +143,31 @@ static void myresid(int N, GFace *gf, double *u, double *v, fullVector<double> &
   for (int i = 0; i < N - 2; i++) r(i) = L[i + 1] - L[i];
 }
 
-static bool computeEquidistantParameters(GFace *gf, double u0, double uN, 
+static bool computeEquidistantParameters1(GFace *gf, double u0, double uN, 
+					  double v0, double vN, int N,
+					  double *u, double *v){
+  //  printf("coucou\n");
+  GPoint p0 = gf->point(u0,v0);
+  GPoint p1 = gf->point(uN,vN);
+  double du = 1. / (N - 1);
+  u[0] = u0;
+  u[0] = u0;
+  v[0] = v0;
+  //  printf("starting with %g %g %g\n",p0.x(),p0.y(),u0);
+  //  printf("ending   with %g %g %g\n",p1.x(),p1.y(),uN);
+  for (int i = 1; i < N; i++){
+    SPoint3 pi (p0.x() + i * du * (p1.x()-p0.x()),
+		p0.y() + i * du * (p1.y()-p0.y()),
+		p0.z() + i * du * (p1.z()-p0.z()));
+    SPoint2 t;
+    GPoint gp = gf->closestPoint(pi, t);		
+    u[i] = gp.u();
+    v[i] = gp.v();
+  }  
+  return true;
+}
+
+static bool computeEquidistantParameters0(GFace *gf, double u0, double uN, 
                                          double v0, double vN, int N,
                                          double *u, double *v)
 {
@@ -191,6 +245,16 @@ static bool computeEquidistantParameters(GFace *gf, double u0, double uN,
   return false;
 }
 
+static bool computeEquidistantParameters(GFace *gf, double u0, double uN, 
+                                         double v0, double vN, int N,
+                                         double *u, double *v){
+  if (method_for_computing_intermediary_points == 0) // use linear abscissa
+    return computeEquidistantParameters0(gf,u0,uN,v0,vN,N,u,v);
+  else if (method_for_computing_intermediary_points == 1) // use projection
+    return computeEquidistantParameters1(gf,u0,uN,v0,vN,N,u,v);
+}
+
+
 static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve,
                             edgeContainer &edgeVertices, bool linear,
                             int nPts = 1, highOrderSmoother *displ2D = 0,
@@ -236,6 +300,9 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve,
                "for edge %d-%d parametrized with %g %g on GEdge %d linear %d",
                relax, US[1], v0->getNum(), v1->getNum(),u0,u1,ge->tag(), linear);
         }
+	else{
+	  Msg::Error("Cannot reparam a mesh Vertex in high order meshing");
+	}
       }
       for(int j = 0; j < nPts; j++){
         const double t = (double)(j + 1)/(nPts + 1);
@@ -247,12 +314,13 @@ static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector<MVertex*> &ve,
 			 v0->getNum(), v1->getNum());
           // we don't have a (valid) parameter on the curve
           SPoint3 pc = edge.interpolate(t);
-          v = new MVertex(pc.x(), pc.y(), pc.z(), ge);
+          v = new MVertex(pc.x(), pc.y(), pc.z(), ge);	  
         }
         else {          
-          GPoint pc = ge->point(US[u0<u1? j + 1 : nPts - 1 - (j + 1)]);
-          v = new MEdgeVertex(pc.x(), pc.y(), pc.z(), ge, 
-                              US[u0 < u1 ? j + 1 : nPts - 1 - (j + 1)]);
+	  int count = u0<u1? j + 1 : nPts + 1  - (j + 1);
+	  GPoint pc = ge->point(US[count]);
+          v = new MEdgeVertex(pc.x(), pc.y(), pc.z(), ge,pc.u()); 
+	  //	  printf("Edge %d(%g) %d(%g) new vertex %g %g at %g\n",v0->getNum(),u0,v1->getNum(),u1,v->x(),v->y(), US[count]);
           if (displ2D || displ3D){
             SPoint3 pc2 = edge.interpolate(t);          
             if(displ2D) displ2D->add(v, SVector3(pc2.x(), pc2.y(), pc2.z()));
diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp
index 80d87b475c..088898a79b 100644
--- a/Mesh/meshGEdge.cpp
+++ b/Mesh/meshGEdge.cpp
@@ -397,6 +397,7 @@ void meshGEdge::operator() (GEdge *ge)
     // FIXME JF : MAYBE WE SHOULD NOT ALWAYS SMOOTH THE 1D MESH SIZE FIELD ??
     //printFandPrimitive(ge->tag(), Points);
     // a =  smoothPrimitive (ge,CTX::instance()->mesh.smoothRatio*CTX::instance()->mesh.smoothRatio,Points);
+    //    printf(" coucou %g\n",a);
     //printFandPrimitive(ge->tag()+10000, Points);
     
     N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.));
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index 83f1026d9d..5849d5c0f5 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -999,6 +999,70 @@ void optimalPointFrontal (GFace *gf,
 }
 
 
+void optimalPointFrontalB (GFace *gf, 
+			   MTri3* worst, 
+			   int active_edge,
+			   std::vector<double> &Us,
+			   std::vector<double> &Vs,
+			   std::vector<double> &vSizes,
+			   std::vector<double> &vSizesBGM,			  
+			   double newPoint[2],
+			   double metric[3]){
+  double center[2],r2;
+  MTriangle *base = worst->tri();
+  circUV(base, Us, Vs, center, gf);
+  double pa[2] = {(Us[base->getVertex(0)->getIndex()] + 
+		   Us[base->getVertex(1)->getIndex()] + 
+		   Us[base->getVertex(2)->getIndex()]) / 3.,
+		  (Vs[base->getVertex(0)->getIndex()] + 
+		   Vs[base->getVertex(1)->getIndex()] + 
+		   Vs[base->getVertex(2)->getIndex()]) / 3.};
+  buildMetric(gf, pa, metric);
+  circumCenterMetric(worst->tri(), metric, Us, Vs, center, r2); 
+  // compute the middle point of the edge
+  int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
+  int ip2 = active_edge;
+
+  double P[2] =  {Us[base->getVertex(ip1)->getIndex()],  
+		  Vs[base->getVertex(ip1)->getIndex()]};
+  double Q[2] =  {Us[base->getVertex(ip2)->getIndex()], 
+		  Vs[base->getVertex(ip2)->getIndex()]};
+  double midpoint[2] = {0.5 * (P[0] + Q[0]), 0.5 * (P[1] + Q[1])};
+      
+  // now we have the edge center and the center of the circumcircle, 
+  // we try to find a point that would produce a perfect triangle while
+  // connecting the 2 points of the active edge
+  
+  double dir[2] = {center[0] - midpoint[0], center[1] - midpoint[1]};
+  double norm = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
+  dir[0] /= norm;
+  dir[1] /= norm;
+  const double RATIO = sqrt(dir[0] * dir[0] * metric[0] +
+			    2 * dir[1] * dir[0] * metric[1] +
+			    dir[1] * dir[1] * metric[2]);    
+  
+  const double p = 0.5 * lengthMetric(P, Q, metric); // / RATIO;
+  const double q = lengthMetric(center, midpoint, metric);
+  const double rhoM1 = 0.5 * 
+    (vSizes[base->getVertex(ip1)->getIndex()] + 
+     vSizes[base->getVertex(ip2)->getIndex()] ) / sqrt(3.);// * RATIO;
+  const double rhoM2 = 0.5 * 
+    (vSizesBGM[base->getVertex(ip1)->getIndex()] + 
+     vSizesBGM[base->getVertex(ip2)->getIndex()] ) / sqrt(3.);// * RATIO;
+  const double rhoM  = Extend1dMeshIn2dSurfaces() ? std::min(rhoM1, rhoM2) : rhoM2;
+  
+  const double rhoM_hat = std::min(std::max(rhoM, p), (p * p + q * q) / (2 * q));
+  const double d = (rhoM_hat + sqrt (rhoM_hat * rhoM_hat - p * p)) / RATIO;
+  
+  //  printf("(%g %g) (%g %g) %g %g %g %g %g %g\n",P[0],P[1],Q[0],Q[1],RATIO,p,q,rhoM,rhoM_hat,d);
+
+
+  newPoint[0] = midpoint[0] + d * dir[0]; 
+  newPoint[1] = midpoint[1] + d * dir[1];
+}
+
+
+
 void bowyerWatsonFrontal(GFace *gf)
 {
   std::set<MTri3*,compareTri3Ptr> AllTris;
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index e11c4d7c7e..59fae4b688 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -798,7 +798,6 @@ static int _removeDiamonds(GFace *gf)
     touched.insert(gf->triangles[i]->getVertex(2));
   }
 
-
   for(unsigned int i = 0; i < gf->quadrangles.size(); i++){
     MQuadrangle *q = gf->quadrangles[i];
     MVertex *v1 = q->getVertex(0);
@@ -836,7 +835,7 @@ static int _removeDiamonds(GFace *gf)
 	deleted.insert(v1);
 	diamonds.insert(q);
       }
-      else if (v2->onWhat()->dim() == 2 &&
+      else if (0 && v2->onWhat()->dim() == 2 &&
 	       v4->onWhat()->dim() == 2 &&
 	       v1->onWhat()->dim() == 2 &&
 	       v3->onWhat()->dim() == 2 &&
@@ -908,9 +907,11 @@ static int _removeDiamonds(GFace *gf)
       mesh_vertices2.push_back(gf->mesh_vertices[i]);
     }
     else {
-      delete gf->mesh_vertices[i];
+      // FIXME : GMSH SOMETIMES CRASHES IF DELETED ....
+      //      delete gf->mesh_vertices[i];
     }
   }
+
   gf->mesh_vertices = mesh_vertices2;
 
   return diamonds.size();
@@ -1109,7 +1110,7 @@ int _edgeSwapQuadsForBetterQuality(GFace *gf)
 {
   e2t_cont adj;
   //  buildEdgeToElement(gf->triangles, adj);
-  buildEdgeToElement(gf->quadrangles, adj);
+  buildEdgeToElement(gf, adj);
 
   std::vector<MQuadrangle*>created;
   std::set<MElement*>deleted;
@@ -1196,7 +1197,7 @@ int _edgeSwapQuadsForBetterQuality(GFace *gf)
 }
 
 static int  edgeSwapQuadsForBetterQuality ( GFace *gf ) {
-  //    return 0;
+  //  return 0;
   int COUNT = 0;
   while(1){
     int k = _edgeSwapQuadsForBetterQuality (gf);
diff --git a/Mesh/qualityMeasures.cpp b/Mesh/qualityMeasures.cpp
index 8301a624e5..31ee8bfcd4 100644
--- a/Mesh/qualityMeasures.cpp
+++ b/Mesh/qualityMeasures.cpp
@@ -188,9 +188,7 @@ double mesh_functional_distorsion(MElement *t, double u, double v)
   double v2[3] = {mat[1][0], mat[1][1], mat[1][2]};
   double normal1[3];
   prodve(v1, v2, normal1);
-  double nn = sqrt(normal1[0]*normal1[0] + 
-                   normal1[1]*normal1[1] + 
-                   normal1[2]*normal1[2]);
+  double nn = norm3(normal1);
   
   // compute uncurved element jacobian d_u x and d_v x
   
@@ -200,14 +198,19 @@ double mesh_functional_distorsion(MElement *t, double u, double v)
   double normal[3];
   prodve(v1b, v2b, normal);
   
+  //  printf("%g %g %g -- %g %g %g - %g\n",mat[0][0], mat[0][1], mat[0][2],mat[1][0], mat[1][1], mat[1][2],nn);
+
   double sign = 1.0;
   prosca(normal1, normal, &sign);
-  double det = norm3(normal) * (sign > 0 ? 1. : -1.) / nn;  
+  //  double det = (norm3(normal) / nn)  * (sign > 0 ? 1. : -1.);  
 
   //  printf("%g %g : %g : %g n1 (%g,%g,%g)\n",u,v,sign,det, normal1[0], normal1[1], normal1[2]);
-  //  printf("n (%g,%g,%g)\n", normal[0], normal[1], normal[2]);
+  //  for (int i=0;i<t->getNumVertices();i++){
+  //    printf("COORD (%d) = %g %g %g\n",i,t->getVertex(i)->x(),t->getVertex(i)->y(),t->getVertex(i)->z());
+  //  }
+  //  printf("n (%g,%g,%g)\n", normal1[0], normal1[1], normal1[2]);
   
-  return det;
+  return sign/(nn*nn);
 }
 
 static double MINQ (double a, double b, double c){
@@ -324,9 +327,9 @@ double mesh_functional_distorsion_pN(MElement *t)
   fullVector<double> Bi( jac->matrixLag2Bez.size1() );
   jac->matrixLag2Bez.mult(Ji,Bi);   
 
-  //  for (int i=0;i<jac->points.size1();i++){
-  //    printf("J(%d) = %12.5E\n",i,Bi(i));
-  //  }
+  //    for (int i=0;i<jac->points.size1();i++){
+  //      printf("J(%d) = %12.5E B(%d) = %12.5E\n",i,Ji(i),i,Bi(i));
+  //    }
 
   /*   
   if (t->getType() == TYPE_QUA){
diff --git a/Solver/elasticitySolver.cpp b/Solver/elasticitySolver.cpp
index eb9a2145ac..d9cf9cd6c6 100644
--- a/Solver/elasticitySolver.cpp
+++ b/Solver/elasticitySolver.cpp
@@ -380,7 +380,7 @@ void elasticitySolver::assemble(linearSystem<double> *lsys)
   }
   // Neumann conditions
   GaussQuadrature Integ_Boundary(GaussQuadrature::Val);
-  std::cout <<  "Neumann BC"<< std::endl;
+
   for (unsigned int i = 0; i < allNeumann.size(); i++)
   {
     LoadTerm<SVector3> Lterm(*LagSpace,*allNeumann[i]._f);
diff --git a/Solver/elasticitySolver.h b/Solver/elasticitySolver.h
index 899dc9c68a..7b4f7e683e 100644
--- a/Solver/elasticitySolver.h
+++ b/Solver/elasticitySolver.h
@@ -57,7 +57,7 @@ struct neumannBC  : public BoundaryCondition
 // an elastic solver ...
 class elasticitySolver
 {
- protected:
+ public:
   GModel *pModel;
   int _dim, _tag;
   dofManager<double> *pAssembler;
diff --git a/benchmarks/2d/recombine.geo b/benchmarks/2d/recombine.geo
index 7594af00aa..1ac40be9eb 100644
--- a/benchmarks/2d/recombine.geo
+++ b/benchmarks/2d/recombine.geo
@@ -9,5 +9,5 @@ Line(3) = {3,4} ;
 Line(4) = {4,1} ;
 Line Loop(5) = {4,1,-2,3} ;
 Plane Surface(6) = {5} ;
-//Recombine Surface{6};
+Recombine Surface{6};
 //Mesh.RecombinationAlgorithm=1;
diff --git a/benchmarks/2d/transfinite_b.geo b/benchmarks/2d/transfinite_b.geo
index 1a209a14a2..8efc8c4535 100644
--- a/benchmarks/2d/transfinite_b.geo
+++ b/benchmarks/2d/transfinite_b.geo
@@ -16,4 +16,4 @@ Transfinite Line {4} = 20 Using Progression 1./1.2;
 Transfinite Line {3,2} = 10 Using Progression 1;
 Transfinite Line {5} = 19 Using Progression 1;
 Transfinite Surface {7} = {3,6,4,2} Alternated;
-//Recombine Surface {7};
+Recombine Surface {7};
-- 
GitLab