diff --git a/Geo/discreteDiskFace.cpp b/Geo/discreteDiskFace.cpp
index a1433ccc66017057254c03198d331463933982de..6556c860e9d6f3582224e74f5d090b8d5d6ea830 100644
--- a/Geo/discreteDiskFace.cpp
+++ b/Geo/discreteDiskFace.cpp
@@ -19,8 +19,6 @@
 #include "Context.h"
 #include "OS.h"
 #include "ANN/ANN.h"
-#include "laplaceTerm.h"
-#include "convexLaplaceTerm.h"
 #include "convexCombinationTerm.h"
 
 #if defined(HAVE_MESH)
@@ -291,8 +289,8 @@ discreteDiskFace::discreteDiskFace(GFace *gf, triangulation* diskTriangulation,
   orderVertices(_totLength, _U0, _coords);
   parametrize();
   buildOct(CAD);
-  printParamMesh();
-  Msg::Info("Parameterization done (GFace %d)",gf->tag());
+  //putOnView(gf->tag(),diskTriangulation->idNum,true,true);
+  //printParamMesh();  
 }
 /*end BUILDER*/
 
@@ -301,7 +299,7 @@ discreteDiskFace::~discreteDiskFace()
   triangles.clear();
   if (_ddft) delete[] _ddft;
   if (oct) Octree_Delete(oct);
-  if(geoTriangulation) delete geoTriangulation;
+  if (geoTriangulation) delete geoTriangulation;
 }
 
 void discreteDiskFace::buildOct(std::vector<GFace*> *CAD) const
@@ -314,10 +312,10 @@ void discreteDiskFace::buildOct(std::vector<GFace*> *CAD) const
   oct = Octree_Create(maxElePerBucket, origin, ssize, discreteDiskFaceBB,
 		      discreteDiskFaceCentroid, discreteDiskFaceInEle);
   
-  _ddft = new discreteDiskFaceTriangle[discrete_triangles.size()/*-geoTriangulation->fillingHoles.size()*/];
+  _ddft = new discreteDiskFaceTriangle[discrete_triangles.size()];
   int c = 0;
   for(unsigned int i = 0; i < discrete_triangles.size(); ++i){
-    //    if(geoTriangulation->fillingHoles.find(i)==geoTriangulation->fillingHoles.end()){
+
     MElement *t = discrete_triangles[i];
     discreteDiskFaceTriangle* my_ddft = &_ddft[c++];
     my_ddft->p.resize(_n);
@@ -328,49 +326,13 @@ void discreteDiskFace::buildOct(std::vector<GFace*> *CAD) const
     my_ddft->tri = t;
 
     Octree_Insert(my_ddft, oct);
-    //    }
+    
   }
   Octree_Arrange(oct);
 }
 
-/*
-void discreteDiskFace::OneToOneParametrization () {
-  v2t_cont adj;
-  buildVertexToTriangle(discrete_triangles, adj);
-  int count=0;
-  {
-    v2t_cont :: iterator it = adj.begin();
-    while (it != adj.end()) {
-      it->first->setIndex(count++);
-      ++it;
-    }
-  }  
-  double *rhs = new double [2*count];
-  double *x   = new double [2*count];
-  {
-    for(size_t i = 0; i < _U0.size(); i++){
-      MVertex *v = _U0[i];
-      const double theta = 2 * M_PI * _coords[i];
-      myAssemblerU.fixVertex(v, 0, 1,cos(theta));
-      myAssemblerV.fixVertex(v, 0, 1,sin(theta));
-    }  
-  }
-
-  {
-    v2t_cont :: iterator it = adj.begin();
-    while (it != adj.end()) {
-      it->first->setIndex(i++);
-      ++it;
-    }
-  }  
-
-  std::vector<int> ij;
-  std::vector<double> val;
-  
-}
-*/
 
-bool discreteDiskFace::parametrize()// const
+bool discreteDiskFace::parametrize() const
 { // #improveme
 
   linearSystem<double> * lsys_u, *lsys_v;
@@ -379,7 +341,7 @@ bool discreteDiskFace::parametrize()// const
 #ifdef HAVE_MUMPS
   lsys_u = new linearSystemMUMPS<double>;
   lsys_v = new linearSystemMUMPS<double>;
-#else
+#else  
   linearSystemCSRGmm<double> * lsys_u1 = new linearSystemCSRGmm<double>;
   linearSystemCSRGmm<double> * lsys_v1 = new linearSystemCSRGmm<double>;
   lsys_u1->setGmres(1);
@@ -393,14 +355,8 @@ bool discreteDiskFace::parametrize()// const
   for(size_t i = 0; i < _U0.size(); i++){
     MVertex *v = _U0[i];
     const double theta = 2 * M_PI * _coords[i];
-    if(i%_order==0){
-      myAssemblerU.fixVertex(v, 0, 1,cos(theta));
-      myAssemblerV.fixVertex(v, 0, 1,sin(theta));
-    }
-    else{//#TEST
-      myAssemblerU.fixVertex(v, 0, 1,1./_order*((_order-(i%_order))*cos(2*M_PI*_coords[i-(i%_order)])+(i%_order)*cos(2*M_PI*_coords[i+(_order-(i%_order))])));
-      myAssemblerV.fixVertex(v, 0, 1,1./_order*((_order-(i%_order))*sin(2*M_PI*_coords[i-(i%_order)])+(i%_order)*sin(2*M_PI*_coords[i+(_order-(i%_order))])));
-    }
+    myAssemblerU.fixVertex(v, 0, 1,cos(theta));
+    myAssemblerV.fixVertex(v, 0, 1,sin(theta));
   }
 
   for(size_t i = 0; i < discrete_triangles.size(); ++i){
@@ -458,9 +414,7 @@ bool discreteDiskFace::parametrize()// const
   return true;
 }
 
-//void discreteDiskFace::checklsys(linearSystemCSR<double>* lsys,dofManager<double>* myAssembler,int U)
-//{
-//}
+
 
 void discreteDiskFace::getTriangleUV(const double u,const double v,
 				     discreteDiskFaceTriangle **mt,
@@ -544,6 +498,7 @@ bool discreteDiskFace::checkOrientationUV()
   }
 }
 
+// for second order parameterization
 void discreteDiskFace::optimize()
 { // #improve . . .
 #if defined(HAVE_OPTHOM)
@@ -952,6 +907,8 @@ GPoint discreteDiskFace::intersectionWithCircle(const SVector3 &n1, const SVecto
 						const SVector3 &p, const double &R,
 						double uv[2]) const
 {
+
+  
   SVector3 n = crossprod(n1,n2);
   n.normalize();
   //  printf("n %g %g %g\n",n.x(), n.y(), n.z());
@@ -1064,6 +1021,7 @@ GPoint discreteDiskFace::intersectionWithCircle2(const SVector3 &n1, const SVect
 						const SVector3 &p, const double &d,
 						double uv[2]) const
 {
+
   // n2 is exterior
   SVector3 n = crossprod(n1,n2);
   n.normalize();
@@ -1331,11 +1289,11 @@ double triangulation::geodesicDistance ()
     if (Fixed.size() == v2t.size())break;
   }
 
-  /*
+  
   char name[256];
-  sprintf(name,"geodesicDistance%d.pos",idNum);
+  sprintf(name,"geodesicDistance%d.pos",iter);
   FILE *f = fopen(name,"w");
-  fprintf(f,"View \"\"{\n");
+  fprintf(f,"View \"%d\"{\n",iter);
   for (unsigned int i=0;i<tri.size();i++){
     double d0 = Fixed[tri[i]->getVertex(0)];
     double d1 = Fixed[tri[i]->getVertex(1)];
@@ -1348,7 +1306,7 @@ double triangulation::geodesicDistance ()
   }
   fprintf(f,"};\n");
   fclose(f);
-  */
+  
 
   return CLOSEST;
 }
@@ -1364,9 +1322,9 @@ void discreteDiskFace::printAtlasMesh()
   std::set<MVertex*> meshvertices;
 	
   for(unsigned int i=0; i<initialTriangulation->tri.size(); ++i){
-    MElement* tri = initialTriangulation->tri[i];
-    for(unsigned int j=0; j<3; j++)
-      if (meshvertices.find(tri->getVertex(j))==meshvertices.end()) meshvertices.insert(tri->getVertex(j));
+      MElement* tri = initialTriangulation->tri[i];
+      for(unsigned int j=0; j<3; j++)
+	if (meshvertices.find(tri->getVertex(j))==meshvertices.end()) meshvertices.insert(tri->getVertex(j));
   }
 	
   fprintf(pmesh,"$MeshFormat\n2.2 0 8\n$EndMeshFormat\n$Nodes\n%u\n",(unsigned int)meshvertices.size());
@@ -1376,15 +1334,21 @@ void discreteDiskFace::printAtlasMesh()
     mv2int[*it] = count;
     count++;
   }
-  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)initialTriangulation->tri.size());
+  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)initialTriangulation->tri.size()-initialTriangulation->fillingHoles.size());
+  unsigned int mycount = 0;//#####
   for(unsigned int i=0; i<initialTriangulation->tri.size(); i++){
-    MElement* tri = initialTriangulation->tri[i];
-    fprintf(pmesh,"%d 2 2 0 0",i+1);
-    for(int j=0; j<3; j++){
-      MVertex* mv = tri->getVertex(j);
-      fprintf(pmesh," %d",mv2int[mv]);
-    }
-    fprintf(pmesh,"\n");
+        std::set<int>::iterator it = initialTriangulation->fillingHoles.find(i);
+	//if (it == initialTriangulation->fillingHoles.end()){
+
+	  MElement* tri = initialTriangulation->tri[i];
+	  fprintf(pmesh,"%d 2 2 0 %d",mycount+1,initialTriangulation->idNum);//#####
+	  for(int j=0; j<3; j++){
+	    MVertex* mv = tri->getVertex(j);
+	    fprintf(pmesh," %d",mv2int[mv]);
+	  }
+	  fprintf(pmesh,"\n");
+	  mycount++;//###
+	  //}
   }
   fprintf(pmesh,"$EndElements\n");
   fclose(pmesh);
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 6160dcc61410077c7fc07f438e4783df439e6339..665b6ba103da83061c56d8aaf2b4d9d7ec0c7d97 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -169,6 +169,7 @@ void discreteFace::secondDer(const SPoint2 &param,
 
 void discreteFace::createGeometry()
 {
+
   checkAndFixOrientation();
 
 
@@ -176,27 +177,30 @@ void discreteFace::createGeometry()
 
 
 
-  int order = 2;
+  int order = 1;
   int nPart = 2;
   double eta = 5/(2.*3.14);
   if (!_atlas.empty())return;
 
   double dtSplit = 0.0;
 
-  int id=1;
+  int id=1, iter=1;
   std::stack<triangulation*>  toSplit;
   std::vector<triangulation*> toParam;
 
   std::vector<MElement*> tem(triangles.begin(),triangles.end());
   triangulation* init = new triangulation(-1, tem,this);
+  init->iter = iter++;
   allEdg2Tri = init->ed2tri;
-
+  
   toSplit.push(init);
-  if((toSplit.top())->genus()!=0 || (toSplit.top())->aspectRatio() > eta ||
-				       (toSplit.top())->seamPoint){
+  if((toSplit.top())->genus()!=0 ||
+     (toSplit.top())->aspectRatio() > eta ||
+     (toSplit.top())->seamPoint){
+    
     while( !toSplit.empty()){
       std::vector<triangulation*> part;
-      triangulation* tosplit = toSplit.top();
+      triangulation* tosplit = toSplit.top();      
       toSplit.pop();
 
       double ts0 = Cpu();
@@ -206,6 +210,7 @@ void discreteFace::createGeometry()
       delete tosplit;
 
       for(unsigned int i=0; i<part.size(); i++){
+	part[i]->iter = iter++;
 	if(part[i]->genus()!=0 || part[i]->aspectRatio() > eta || part[i]->seamPoint)
 	  toSplit.push(part[i]);
 	else{
@@ -221,6 +226,32 @@ void discreteFace::createGeometry()
   }
   updateTopology(toParam);
 
+
+  /*
+  FILE* debug = Fopen("tralala-init.pos","w");
+  fprintf(debug,"View \"discreteEdges\"{\n");
+  for(unsigned int j=0; j<toParam.size(); j++){
+    
+    std::list<GEdge*> ge = toParam[j]->my_GEdges;
+    for(std::list<GEdge*>::iterator it = ge.begin(); it!=ge.end(); ++it){
+      if((*it)->tag()==112 ){
+	
+	std::vector<MLine*> ml = (*it)->lines;
+	printf("___(init) map %d, ge %d___ (%p)\n",j+1,(*it)->tag(),(*it));
+	for(unsigned int i=0; i<ml.size(); i++){
+	  ml[i]->writePOS(debug,true,false,false,false,false,false,1.,(*it)->tag());
+	  printf("%d[%d;%d]--",ml[i]->getNum(),ml[i]->getVertex(0)->getNum(),ml[i]->getVertex(1)->getNum());
+	}
+	printf("\n");
+	
+      }	
+	
+    }
+  }
+  fprintf(debug,"};");
+  fclose(debug);
+  */
+  
   for(unsigned int i=0; i<toParam.size(); i++){
 
     fillHoles(toParam[i]);
@@ -228,15 +259,16 @@ void discreteFace::createGeometry()
     //toParam[i]->print(name, toParam[i]->idNum);
   }
 
+  
   for(unsigned int i=0; i<toParam.size(); i++){
     discreteDiskFace *df = new discreteDiskFace (this,toParam[i], order,(_CAD.empty() ? NULL : &_CAD));
-    //    df->printAtlasMesh();
-    //    df->putOnView(tag(), i, true,true);
+    df->printAtlasMesh();
+    df->printParamMesh();
+    //df->putOnView(tag(), i, true,true);
     df->replaceEdges(toParam[i]->my_GEdges);
     _atlas.push_back(df);
   }
-
-  crossField();
+  complex_crossField();
 #endif
 }
 
@@ -288,10 +320,39 @@ void discreteFace::gatherMeshes()
 
 void discreteFace::mesh(bool verbose)
 {
+
+
+  for(unsigned int j=0; j<_atlas.size(); j++){
+    
+    std::list<GEdge*> ge = _atlas[j]->edges();
+    for(std::list<GEdge*>::iterator it = ge.begin(); it!=ge.end(); ++it){
+
+      char myname[256];
+      sprintf(myname,"tralala%d_%d.pos",(*it)->tag(),j+1);
+      FILE* debug = Fopen(myname,"w");
+      fprintf(debug,"View \"discreteEdges\"{\n");
+      std::vector<MLine*> ml = (*it)->lines;
+
+      //printf("___map %d (%d), ge %d___ (%p)\n",j+1,_atlas[j]->tag(),(*it)->tag(),(*it));
+      for(unsigned int i=0; i<ml.size(); i++){
+	ml[i]->writePOS(debug,false,true,false,false,false,false,1.,(*it)->tag());
+	//printf("%d[%d;%d]--",ml[i]->getNum(),ml[i]->getVertex(0)->getNum(),ml[i]->getVertex(1)->getNum());
+      }
+      //printf("\n");
+	
+      fprintf(debug,"};");
+      fclose(debug);
+    }
+  }
+  
+  
+
+
+  
 #if defined(HAVE_ANN) && defined(HAVE_SOLVER) && defined(HAVE_MESH)
   if (!CTX::instance()->meshDiscrete) return;
 
-  Msg::Info("Discrete Face %d is going to be meshed",tag());
+  //Msg::Info("Discrete Face %d is going to be meshed",tag());
   for (unsigned int i=0;i<_atlas.size();i++){
     //    {
       //      void openProblemsON(void);
@@ -426,11 +487,14 @@ void discreteFace::setupDiscreteEdge(discreteEdge*de,std::vector<MLine*>mlines,
 // split old GEdge's
 void discreteFace::splitDiscreteEdge(GEdge *de , GVertex *gv, discreteEdge* newE[2])
 {
-  MVertex *vend = de->getEndVertex()->mesh_vertices[0];
 
-  newE[0] = new discreteEdge (de->model(),model()->getMaxElementaryNumber(1) + 1,de->getBeginVertex(),gv);
-  newE[1] = new discreteEdge (de->model(),model()->getMaxElementaryNumber(1) + 1,gv, de->getEndVertex());
+  MVertex *vend = de->getEndVertex()->mesh_vertices[0];
 
+  int mytag = this->model()->getMaxElementaryNumber(1) + 1;
+  newE[0] = new discreteEdge (de->model(),mytag,de->getBeginVertex(),gv);
+  mytag++;
+  newE[1] = new discreteEdge (de->model(),mytag,gv, de->getEndVertex());
+  
   int current = 0;
   std::vector<MLine*> mlines;
   // assumption: the MLine's are sorted
@@ -549,7 +613,7 @@ void discreteFace::split(triangulation* trian,std::vector<triangulation*> &parti
       }// end for j
     }// end while
     if(!celem.empty()){// if the set is empty, it means that the part was connected
-      Msg::Info("discreteFace::split(), a partition (%d) is not connected: it is going to be fixed.",p);
+      //Msg::Info("discreteFace::split(), a partition (%d) is not connected: it is going to be fixed.",p);
       std::vector<MElement*> relem(celem.begin(),celem.end());// new part
       for(unsigned int ie=0; ie<relem.size(); ie++)// updating the id part of the element belonging to the new part
 	el2part[relem[ie]] = nPartitions;
@@ -645,7 +709,7 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
 	  }// end else oe==end()
 	}// end imvt
 	// the new GEdge can be created with its GVertex
-	discreteEdge* internalE = new discreteEdge (this->model(),model()->getMaxElementaryNumber(1) + 1,v[0],v[1]);
+	discreteEdge* internalE = new discreteEdge (this->model(),this->model()->getMaxElementaryNumber(1) + 1,v[0],v[1]);
 	setupDiscreteEdge(internalE,myLines,&todelete);
 	gGEdges.insert(internalE);
 
@@ -664,7 +728,7 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
 	}
 	v = new discreteVertex (this->model(),model()->getMaxElementaryNumber(0) + 1);
 	setupDiscreteVertex(v,cv0,&todelete);
-	discreteEdge* gloop = new discreteEdge (this->model(),model()->getMaxElementaryNumber(1) + 1,v,v);
+	discreteEdge* gloop = new discreteEdge (this->model(),this->model()->getMaxElementaryNumber(1) + 1,v,v);
 	setupDiscreteEdge(gloop,my_MLines,&todelete);
 	gGEdges.insert(gloop);
       }// end while v02edg.empty()
@@ -788,6 +852,7 @@ void discreteFace::complex_crossField()
   Msg::Error("Petsc is required (we do need complex in discreteFace::crossField())");
   return;
 #endif
+  
   std::complex<double> i1(0,1);
   dofManager<std::complex<double> > myAssembler(lsys);
 
@@ -802,12 +867,9 @@ void discreteFace::complex_crossField()
       int mini = iTri[0];
       if (iTri.size()>1)
 	mini = iTri[0] < iTri[1] ? iTri[0] : iTri[1];
-      else{
-	double alpha = getAlpha(tri,j);
-	printf("CL: ed[%f,%f]--[%f,%f]\t theta: %f \n",ed.getSortedVertex(0)->x(),ed.getSortedVertex(0)->y(),ed.getSortedVertex(1)->x(),ed.getSortedVertex(1)->y(),alpha*180./M_PI);
-	myAssembler.fixDof(3*mini+j,0,std::complex<double>(std::exp(-4.*i1*alpha))); // #tocheck
-      }
-
+      else
+	myAssembler.fixDof(3*mini+j,0,std::complex<double>(1)); // #tocheck
+      
       int num,s;
       triangles[mini]->getEdgeInfo(ed,num,s);
       myAssembler.numberDof(3*mini+num,0);
@@ -860,26 +922,36 @@ void discreteFace::complex_crossField()
     fprintf(myfile,"VT(");
     MTriangle* tri = triangles[i];
     MEdge ed = tri->getEdge(0);
-    MVertex *v0 = ed.getSortedVertex(0), *v1=ed.getSortedVertex(1);
-    SVector3 e(v1->x()-v0->x(),v1->y()-v0->y(),v1->z()-v0->z()); e.normalize();
-    MEdge ed1 = tri->getEdge(1); MVertex *v10 = ed1.getVertex(0), *v11=ed1.getVertex(1);
-    SVector3 e1(v11->x()-v10->x(),v11->y()-v10->y(),v11->z()-v10->z());
-    SVector3 n = crossprod(e,e1); n.normalize();
-    SVector3 d = crossprod(e,n); d.normalize();
+    
+    MVertex *v0, *v1, *v2;
+
+    v0 = tri->getVertex(0);
+    v1 = tri->getVertex(1);
+    v2 = tri->getVertex(2);
 
+    SVector3 a(v1->x()-v0->x(),v1->y()-v0->y(),v1->z()-v0->z());
+    SVector3 b(v2->x()-v0->x(),v2->y()-v0->y(),v2->z()-v0->z());
+    SVector3 n = crossprod(a,b); n.normalize();
+
+    v0 = ed.getSortedVertex(0);
+    v1 = ed.getSortedVertex(1);
+    SVector3 e(v1->x()-v0->x(),v1->y()-v0->y(),v1->z()-v0->z());
+    e.normalize();
+    SVector3 d = crossprod(n,e); d.normalize();
+   
     std::vector<double> U; U.resize(3);
     std::vector<double> V; V.resize(3);
     for(int j=0; j<3; j++){
       fprintf(myfile,"%f,%f,%f",tri->getVertex(j)->x(),tri->getVertex(j)->y(),tri->getVertex(j)->z());
       if (j<2) fprintf(myfile,",");
       MEdge ed = tri->getEdge(j);
-      double alpha = getAlpha(tri,j);
-      std::complex<double> cross, Cross(std::exp(4.*i1*alpha));
-      myAssembler.getDofValue(ed2key[ed],0,cross); // conjugate dof in the local edge basis
-      Cross *= std::conj(cross); // dof of the local tri basis
-      U[j] = std::real(Cross);
-      V[j] = std::imag(Cross);
-      printf("sol: ed%d %f (tri) ~ %f (ed) \n",j,std::atan2(V[j],U[j])*180./(4.*M_PI),(std::atan2(-std::imag(cross),std::real(cross)))*180./(4.*M_PI));
+      std::complex<double> fstar; // edge basis
+      myAssembler.getDofValue(ed2key[ed],0,fstar); // conjugate dof in the local edge basis
+      double alpha = getAlpha(tri,j); // triangle basis
+      std::complex<double> F(std::exp(4.*i1*alpha)); 
+      F *= std::conj(fstar); // dof of the local tri basis
+      U[j] = std::real(F);
+      V[j] = std::imag(F);      
     }
     fprintf(myfile,")");
     std::vector<double> Fu, Fv;
@@ -887,9 +959,10 @@ void discreteFace::complex_crossField()
     crouzeixRaviart(V,Fv);
     fprintf(myfile,"{");
     for(int j=0; j<3; j++){
-      double u = Fu[j], v = Fv[j];
-      printf("sol: ve%d (%f %f)\n",j,u,v);
-      fprintf(myfile,"%f,%f,%f",u*e.x()+v*d.x(),u*e.y()+v*d.y(),u*e.z()+v*d.z());
+      double u = Fu[j], v = Fv[j]; double theta = std::atan2(v,u)/4.;
+      SVector3 cf(cos(theta)*e.x()+sin(theta)*d.x(),cos(theta)*e.y()+sin(theta)*d.y(),cos(theta)*e.z()+sin(theta)*d.z());
+      cf = cf*sqrt(u*u+v*v);
+      fprintf(myfile,"%f,%f,%f",cf.x(),cf.y(),cf.z());
       if (j<2) fprintf(myfile,",");
     }
     fprintf(myfile,"};\n");
@@ -928,8 +1001,7 @@ void discreteFace::crossField()
       if (iTri.size()>1)
 	mini = iTri[0] < iTri[1] ? iTri[0] : iTri[1];
       else{
-	double alpha = getAlpha(tri,j);
-	printf("CL: ed[%f,%f]--[%f,%f]\t Theta: %f \n",ed.getSortedVertex(0)->x(),ed.getSortedVertex(0)->y(),ed.getSortedVertex(1)->x(),ed.getSortedVertex(1)->y(),alpha*180./M_PI);
+	//printf("CL: ed[%f,%f]--[%f,%f]\t Theta: %f \n",ed.getSortedVertex(0)->x(),ed.getSortedVertex(0)->y(),ed.getSortedVertex(1)->x(),ed.getSortedVertex(1)->y(),alpha*180./M_PI);
 	myAssembler.fixDof(3*mini+j,0,1.); // setting theta and not Theta
 	myAssembler.fixDof(3*mini+j,1,0.);
       }
@@ -942,7 +1014,6 @@ void discreteFace::crossField()
     }// end for j
   }// end for unsigned int i
 
-
   double grad[3][3] = {{0.,-2.,0.},{2.,2.,0.},{-2.,0.,0.}};
   for (unsigned int i=0; i<triangles.size(); i++){
 
@@ -972,7 +1043,7 @@ void discreteFace::crossField()
 	    for(int kk=0; kk<3; kk++)
 	      K_jk += grad[j][jj] * invjac[l][jj] * invjac[l][kk] * grad[k][kk];
 	K_jk *= dJac/2.;
-	printf("%f\t",K_jk);
+	//printf("%f\t",K_jk);
 	//printf("%f \t %f \n %f \t %f \n",cos(4.*(alpha_j-alpha_k))*K_jk,sin(4.*(alpha_j-alpha_k))*K_jk,sin(4.*(alpha_k-alpha_j))*K_jk,cos(4.*(alpha_j-alpha_k))*K_jk);
 
 
@@ -981,10 +1052,10 @@ void discreteFace::crossField()
 	myAssembler.assemble(Rv,Cu,sin(4.*(alpha_k-alpha_j))*K_jk);
 	myAssembler.assemble(Rv,Cv,cos(4.*(alpha_j-alpha_k))*K_jk);
       }// end for k
-      printf("\n");
+      //printf("\n");
 
     }// end for j
-    printf("\n");
+    //printf("\n");
   }// end for unsigned int
 
 
@@ -1010,9 +1081,9 @@ void discreteFace::crossField()
     v1 = ed.getSortedVertex(1);
     SVector3 e(v1->x()-v0->x(),v1->y()-v0->y(),v1->z()-v0->z());
     e.normalize();
-    printf("e=(%f %f)\n",e.x(),e.y());
+    //printf("e=(%f %f)\n",e.x(),e.y());
     SVector3 d = crossprod(n,e); d.normalize();
-    printf("d=(%f %f)\n",d.x(),d.y());
+    //printf("d=(%f %f)\n",d.x(),d.y());
 
 
     std::vector<double> U; U.resize(3);
@@ -1024,10 +1095,12 @@ void discreteFace::crossField()
       double  u, v;// edge basis
       myAssembler.getDofValue(ed2key[ed],0,u);// u
       myAssembler.getDofValue(ed2key[ed],1,v);// v
+      if(std::abs(u*u+v*v-1)>1e-12)
+	printf("/!\\ ---> warning unit vector \t %f  \n",sqrt(u*u+v*v));
       double alpha = getAlpha(tri,j);// triangle basis
       U[j] = cos(4.*alpha)*u - sin(4.*alpha)*v;// U, not u
       V[j] = sin(4.*alpha)*u + cos(4.*alpha)*v;// V, not v
-      printf("sol: ed%d[%f,%f]--[%f,%f] \t Theta = %f (tri) ~ theta = %f (ed) ~ alpha = %f ~u=%f, v=%f VS U=%f, V=%f \n",j,ed.getSortedVertex(0)->x(),ed.getSortedVertex(0)->y(),ed.getSortedVertex(1)->x(),ed.getSortedVertex(1)->y(),std::atan2(V[j],U[j])*180./(4.*M_PI),std::atan2(v,u)*180./(4.*M_PI),alpha*180./M_PI,u,v,U[j],V[j]);
+      //printf("sol: ed%d[%f,%f]--[%f,%f] \t Theta = %f (tri) ~ theta = %f (ed) ~ alpha = %f ~u=%f, v=%f VS U=%f, V=%f \n",j,ed.getSortedVertex(0)->x(),ed.getSortedVertex(0)->y(),ed.getSortedVertex(1)->x(),ed.getSortedVertex(1)->y(),std::atan2(V[j],U[j])*180./(4.*M_PI),std::atan2(v,u)*180./(4.*M_PI),alpha*180./M_PI,u,v,U[j],V[j]);
     }
     fprintf(myfile,")");
     std::vector<double> Fu, Fv;
@@ -1036,8 +1109,13 @@ void discreteFace::crossField()
     fprintf(myfile,"{");
     for(int j=0; j<3; j++){
       double u = Fu[j], v = Fv[j]; double theta = std::atan2(v,u)/4.;
-      printf("theta_%d = %f\n",j,theta*180./M_PI);
-      fprintf(myfile,"%f,%f,%f",cos(theta)*e.x()-sin(theta)*e.y(),sin(theta)*e.x()+cos(theta)*e.y(),e.z());
+      //printf("theta_%d = %f\n",j,theta*180./M_PI);
+      SVector3 cf(cos(theta)*e.x()+sin(theta)*d.x(),cos(theta)*e.y()+sin(theta)*d.y(),cos(theta)*e.z()+sin(theta)*d.z());
+      //cf = cf*sqrt(u*u+v*v);
+      fprintf(myfile,"%f,%f,%f",cf.x(),cf.y(),cf.z());//cos(theta)*e.x()-sin(theta)*e.y(),sin(theta)*e.x()+cos(theta)*e.y(),e.z());
+      
+      if( std::abs(dot(cf,n)) > 1e-12)
+	printf("/!\\ ---> warning orthogonality \t %f \n",dot(cf,n));
       if (j<2) fprintf(myfile,",");
     }
     fprintf(myfile,"};\n");
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 186cb9078daa658952d0d25b98ea842e813cea10..1a23ebe052d88c7fd15055c4aacadaa32451b047 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -556,10 +556,12 @@ static bool recoverEdge(BDS_Mesh *m, GEdge *ge,
         BDS_Edge *e = m->recover_edge(pstart->iD, pend->iD, _fatallyFailed, e2r, notRecovered);
         if(e) e->g = g;
         else {
-          if (_fatallyFailed)
-            Msg::Error("Unable to recover an edge %g %g && %g %g (%d/%d)",
-                       vstart->x(), vstart->y(), vend->x(), vend->y(), i,
-                       ge->mesh_vertices.size());
+          if (_fatallyFailed){
+            Msg::Error("Unable to recover the edge %d (%d/%d) on GEdge %d (on GFace %d)",
+                       ge->lines[i]->getNum(),i+1,ge->lines.size(),ge->tag(),ge->faces().back()->tag());
+	    outputScalarField(m->triangles, "wrongmesh.pos", 0);
+	    outputScalarField(m->triangles,"wrongparam.pos",1);
+	  }
           return !_fatallyFailed;
         }
       }
@@ -2389,7 +2391,7 @@ void deMeshGFace::operator() (GFace *gf)
 }
 
 // for debugging, change value from -1 to -100;
-int debugSurface = -1; //-1;
+int debugSurface = -100; //-100;
 
 void meshGFace::operator() (GFace *gf, bool print)
 {