diff --git a/Geo/discreteDiskFace.cpp b/Geo/discreteDiskFace.cpp
index 3f205ee6b46fe37c9358f4a95e4bcbc279c8f9d5..b7724e6bea6804d6444d876541dacbdc4dfb7d8d 100644
--- a/Geo/discreteDiskFace.cpp
+++ b/Geo/discreteDiskFace.cpp
@@ -3,7 +3,7 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to the public mailing list <gmsh@geuz.org>.
 
-#include <queue> // #mark
+#include <queue> 
 #include <stdlib.h>
 #include "GmshConfig.h"
 
@@ -19,14 +19,12 @@
 #include "Context.h"
 #include "OS.h"
 #include "ANN/ANN.h"
-#include "linearSystemCSR.h"
-#include "dofManager.h"
 #include "laplaceTerm.h"
 #include "convexLaplaceTerm.h"
-#include "convexCombinationTerm.h"  // #FIXME
+#include "convexCombinationTerm.h"
 
 #if defined(HAVE_MESH)
-#include "qualityMeasuresJacobian.h" // #temporary?
+#include "qualityMeasuresJacobian.h"
 #endif
 
 #if defined(HAVE_OPTHOM)
@@ -286,20 +284,18 @@ discreteDiskFace::discreteDiskFace(GFace *gf, triangulation* diskTriangulation,
   _totLength = geoTriangulation->bord.rbegin()->first;
   _U0 = geoTriangulation->bord.rbegin()->second;
   orderVertices(_totLength, _U0, _coords);
-  parametrize(false);
+  parametrize();
   buildOct(CAD);
-
-
-  if (!checkOrientationUV()){
-    Msg::Info("discreteDiskFace:: parametrization is not one-to-one; fixing "
-              "the discrete system.");
-    parametrize(true);
+  printParamMesh();
+  if (_order > 1 && !checkOrientationUV()){
+    Msg::Info("discreteDiskFace:: parametrization is not one-to-one; the parametric mesh is going to be corrected.");
+    optimize();
     buildOct(CAD);
+    printParamMesh();
   }
   putOnView(true,false);
-  printParamMesh();
-  if(!checkOrientationUV()) Msg::Fatal("discreteDiskFace:: failing to fix the discrete system");
-  //  else Msg::Info("Parameterization done :-)");
+  if(!checkOrientationUV()) Msg::Fatal("discreteDiskFace:: failing to compute a one-to-one mapping");
+  else Msg::Info("Parameterization done :-)");
 }
 /*end BUILDER*/
 
@@ -320,36 +316,32 @@ void discreteDiskFace::buildOct(std::vector<GFace*> *CAD) const
   const int maxElePerBucket = 15;
   oct = Octree_Create(maxElePerBucket, origin, ssize, discreteDiskFaceBB,
 		      discreteDiskFaceCentroid, discreteDiskFaceInEle);
-
+  
   _ddft = new discreteDiskFaceTriangle[discrete_triangles.size()/*-geoTriangulation->fillingHoles.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);
-      for(int io=0; io<_N; io++)
-	my_ddft->p[io] = coordinates[t->getVertex(io)];
+    MElement *t = discrete_triangles[i];
+    discreteDiskFaceTriangle* my_ddft = &_ddft[c++];
+    my_ddft->p.resize(_N);
+    for(int io=0; io<_N; io++)
+      my_ddft->p[io] = coordinates[t->getVertex(io)];
 
-      my_ddft->gf = CAD ? (*CAD)[i] : _parent;
-      my_ddft->tri = t;
+    my_ddft->gf = CAD ? (*CAD)[i] : _parent;
+    my_ddft->tri = t;
 
-      Octree_Insert(my_ddft, oct);
-      //    }
+    Octree_Insert(my_ddft, oct);
+    //    }
   }
   Octree_Arrange(oct);
 }
 
-bool discreteDiskFace::parametrize(bool one2one) const
+bool discreteDiskFace::parametrize()// const
 { // #improveme
 
-  if (one2one)
-    Msg::Info("Parametrizing surface %d with 'one-to-one map'", tag());
-  else
-    Msg::Info("Parametrizing surface %d with 'harmonic map'", tag());
 
-  linearSystem<double> *lsys_u;
-  linearSystem<double> *lsys_v;
+  linearSystemCSRTaucs<double> *lsys_u;
+  linearSystemCSRTaucs<double> *lsys_v;
 
   lsys_u = new linearSystemCSRTaucs<double>; // taucs :-)
   lsys_v = new linearSystemCSRTaucs<double>; // taucs :-)
@@ -357,20 +349,21 @@ bool discreteDiskFace::parametrize(bool one2one) const
   dofManager<double> myAssemblerU(lsys_u);   // hashing
   dofManager<double> myAssemblerV(lsys_v);
 
-  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))])));
+  if(_order>1){
+    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))])));
+      }
     }
   }
 
-
   for(size_t i = 0; i < discrete_triangles.size(); ++i){
     MElement *t = discrete_triangles[i];
     for(int j=0; j<t->getNumVertices(); j++){
@@ -386,28 +379,21 @@ bool discreteDiskFace::parametrize(bool one2one) const
   double t1 = Cpu();
 
   simpleFunction<double> ONE(1.0);
+  laplaceTerm mappingU(0, 1, &ONE);
+  laplaceTerm mappingV(0, 1, &ONE);
 
-  if (one2one){
-    convexLaplaceTerm mappingU(0, 1, &ONE);
-    convexLaplaceTerm mappingV(0, 1, &ONE);
-
-    for(unsigned int i = 0; i < discrete_triangles.size(); ++i){
-      SElement se(discrete_triangles[i]);
-      mappingU.addToMatrix(myAssemblerU, &se);
-      mappingV.addToMatrix(myAssemblerV, &se);
-    }
+  for(unsigned int i = 0; i < discrete_triangles.size(); ++i){
+    SElement se(discrete_triangles[i]);
+    mappingU.addToMatrix(myAssemblerU, &se);
+    mappingV.addToMatrix(myAssemblerV, &se);
   }
-  else{
-    laplaceTerm mappingU(0, 1, &ONE);
-    laplaceTerm mappingV(0, 1, &ONE);
 
-    for(unsigned int i = 0; i < discrete_triangles.size(); ++i){
-      SElement se(discrete_triangles[i]);
-      mappingU.addToMatrix(myAssemblerU, &se);
-      mappingV.addToMatrix(myAssemblerV, &se);
-    }
-  }
 
+  if(_order==1){
+    checklsys(lsys_u,&myAssemblerU,1);
+    checklsys(lsys_v,&myAssemblerV,0);
+  }
+     
   double t2 = Cpu();
   Msg::Debug("Assembly done in %8.3f seconds", t2 - t1);
   lsys_u->systemSolve();
@@ -439,6 +425,91 @@ bool discreteDiskFace::parametrize(bool one2one) const
   return true;
 }
 
+void discreteDiskFace::checklsys(linearSystemCSRTaucs<double>* lsys,dofManager<double>* myAssembler,int U)
+{
+     
+  INDEX_TYPE *ai;
+  INDEX_TYPE *jptr;
+  double *a;
+  //double b;
+  lsys->getMatrix(jptr,ai,a);
+  int NbUnk = lsys->getNbUnk();
+  //  int NNZ = lsys->getNNZ();
+  double tr = 0.;
+  //printf("------------------------%d\n######################%d\n______________________\n",NNZ,NbUnk);
+  for(int i=0; i<NbUnk; i++){
+    tr += a[jptr[i]];
+    /*lsys->getFromRightHandSide(i,b);
+    printf("%d: %d->%d\n",i,jptr[i],jptr[i+1]);
+    for(int j=jptr[i]; j<jptr[i+1]; j++)
+      printf("%d: %f \t",ai[j],a[j]);
+      printf("=%f \n",b);*/
+  }
+  tr /= NbUnk;
+
+  double alpha = .1;
+  for(int i=0; i<NbUnk; i++)
+    for(int j=jptr[i]+1; j<jptr[i+1]; j++)
+      if(a[j] > -alpha*tr){
+	double delta = a[j] + alpha*tr;
+	a[jptr[i]] += delta;
+	a[jptr[ai[j]]] += delta;
+	a[j] -= delta;
+      }
+  /*
+  printf("\n");
+  for(int i=0; i<NbUnk; i++){
+    lsys->getFromRightHandSide(i,b);
+    printf("%d: %d->%d\n",i,jptr[i],jptr[i+1]);
+    for(int j=jptr[i]; j<jptr[i+1]; j++)
+      printf("%d: %f \t",ai[j],a[j]);
+    printf("=%f \n",b);
+  }
+  */
+  std::map<int,int> dirichlet;
+  for(unsigned int i=0; i<_U0.size(); i++)
+    dirichlet[myAssembler->getDofNumber(Dof(_U0[i]->getNum(),10000))] = i;
+
+
+  for(int i=0; i<NbUnk; i++){
+    if(dirichlet.find(i)!=dirichlet.end()){
+      lsys->addToMatrix(i,i,-a[jptr[i]]+1);
+      double theta = 2 * M_PI *  _coords[dirichlet[i]];
+      double val = U*cos(theta) + (1-U)*sin(theta);
+      lsys->addToRightHandSide(i,val);
+      for(int j=jptr[i]+1; j<jptr[i+1]; j++){
+	if(dirichlet.find(ai[j])==dirichlet.end())
+	   lsys->addToRightHandSide(ai[j],-a[j]*val);
+	a[j] = 0;
+      }
+    }
+    else{
+      for(int j=jptr[i]+1; j<jptr[i+1]; j++){
+	if(dirichlet.find(ai[j])!=dirichlet.end()){
+	  double theta = 2 * M_PI *  _coords[dirichlet[ai[j]]];
+	  double val = U*cos(theta) + (1-U)*sin(theta);
+	  lsys->addToRightHandSide(i,-a[j]*val);
+	  a[j] = 0;
+	}
+      }
+    }//end else
+  }//end for i
+  /*
+  lsys->getMatrix(jptr,ai,a);
+  NbUnk = lsys->getNbUnk();
+  NNZ = lsys->getNNZ();
+  printf("--#--#--#--\n");
+  for(int i=0; i<NbUnk; i++){
+    lsys->getFromRightHandSide(i,b);
+    printf("%d: %d->%d\n",i,jptr[i],jptr[i+1]);
+    for(int j=jptr[i]; j<jptr[i+1]; j++)
+      printf("%d: %f \t",ai[j],a[j]);
+    printf("=%f \n",b);
+  }
+ */
+  
+}
+
 void discreteDiskFace::getTriangleUV(const double u,const double v,
 				     discreteDiskFaceTriangle **mt,
 				     double &_xi, double &_eta)const{
@@ -479,7 +550,7 @@ bool discreteDiskFace::checkOrientationUV()
       else nbP++;
     }
     if (nbP*nbM){
-      Msg::Error("Map %d of the atlas : Triangles have different orientations (%d + / %d -)",tag(),nbP,nbM);
+      Msg::Info("Map %d of the atlas : Triangles have different orientations (%d + / %d -)",tag(),nbP,nbM);
       return false;
     }
     return true;
@@ -508,17 +579,20 @@ bool discreteDiskFace::checkOrientationUV()
 }
 
 void discreteDiskFace::optimize()
-{
+{ // #improve . . .
 #if defined(HAVE_OPTHOM)
 
   // parameters for mesh optimization
   // -- high order
   OptHomParameters optParams;
   optParams.dim = 2;
-  optParams.optPassMax = 10;
+  optParams.optPassMax = 100;
   optParams.TMAX = 300;
   optParams.fixBndNodes = true;
-  optParams.strategy = 1;
+  optParams.optPrimSurfMesh = true;
+  optParams.BARRIER_MIN = 1e-3;
+  optParams.BARRIER_MAX = 1e3;
+  optParams.strategy = 0;
   // -- linear
   MeshQualOptParameters opt;
   opt.dim = 2;
@@ -544,32 +618,47 @@ void discreteDiskFace::optimize()
       paramTriangles[i] = new MTriangle6(mv);
   }
   // -- generation of the parametric topology #mark what about the GFace for the GModel ?
-  std::map<int,std::vector<MElement*> > e2e;
+  std::map<int,std::vector<MElement*> > e2e;// entity to element
   e2e[0] = paramTriangles;
   std::vector<int> v;
   v.push_back(0);
-  std::map<int,std::vector<int> > e2p;
+  std::map<int,std::vector<int> > e2p;// entity to physical
   e2p[0] = v;
+  std::set<MVertex*> todelete;
   GModel* paramDisk = GModel::createGModel(e2e,e2p);
-  discreteVertex dv(paramDisk,NEWPOINT());
-  dv.mesh_vertices.push_back(sp2mv[coordinates[_U0[0]]]);
-  sp2mv[coordinates[_U0[0]]]->setEntity(&dv);
-  paramDisk->add(&dv);
-  discreteEdge de(paramDisk,NEWLINE(),&dv,&dv);
-  paramDisk->add(&de);
+  // ---- discrete vertex
+  std::set<GFace*, GEntityLessThan>::iterator it = paramDisk->firstFace();
+  GFace *dgf = *it;
+  discreteVertex *dv = new discreteVertex(paramDisk,paramDisk->getMaxElementaryNumber(0)+1);
+  sp2mv[coordinates[_U0[0]]]->setEntity(dv);
+  dv->mesh_vertices.push_back(sp2mv[coordinates[_U0[0]]]);
+  todelete.insert(sp2mv[coordinates[_U0[0]]]);
+  paramDisk->add(dv);
+  // ---- discrete edge
+  discreteEdge *de = new discreteEdge(paramDisk,paramDisk->getMaxElementaryNumber(1)+1,dv,dv);
+  paramDisk->add(de);
+  std::vector<MLine*> lines;
   for(unsigned int i=1; i<_U0.size(); i++){
-    sp2mv[coordinates[_U0[i]]]->setEntity(&de);
-    de.mesh_vertices.push_back(sp2mv[coordinates[_U0[i]]]);
-    de.lines.push_back(new MLine(sp2mv[coordinates[_U0[i-1]]],sp2mv[coordinates[_U0[i]]]));
+    sp2mv[coordinates[_U0[i]]]->setEntity(de);
+    de->mesh_vertices.push_back(sp2mv[coordinates[_U0[i]]]);
+    todelete.insert(sp2mv[coordinates[_U0[i]]]);
+    lines.push_back(new MLine(sp2mv[coordinates[_U0[i-1]]],sp2mv[coordinates[_U0[i]]]));
   }
-  de.createGeometry();
-
+  lines.push_back(new MLine(sp2mv[coordinates[_U0[_U0.size()-1]]],sp2mv[coordinates[_U0[0]]]));
+  de->setTopo(lines);
+  de->createGeometry();// !!!! setTopo ... MLine's
+ 
+  
+  
   // optimization
   if(_order >1)
     HighOrderMeshOptimizer(paramDisk, optParams);
   else
     MeshQualityOptimizer(paramDisk,opt);
 
+ 
+  
+  
   // update the parametrization
   paramTriangles = e2e[0];
   for(unsigned int i=0; i< paramTriangles.size(); i++){
@@ -583,8 +672,19 @@ void discreteDiskFace::optimize()
     }
   }
 
+  // update GFace's mesh_vertices
+  std::vector<MVertex*> newMV;
+  for(unsigned int imv=0; imv<dgf->mesh_vertices.size(); imv++){
+    MVertex* current = dgf->mesh_vertices[imv];
+    std::set<MVertex*>::iterator itmv = todelete.find(current);
+    if (itmv==todelete.end()) newMV.push_back(current);
+  }
+  dgf->mesh_vertices.clear();
+  dgf->mesh_vertices = newMV;
+  
   // cleaning
   delete paramDisk;
+  
 #endif
 }
 
@@ -738,7 +838,7 @@ void discreteDiskFace::secondDer(const SPoint2 &param,
 }
 
 void discreteDiskFace::putOnView(bool Xu, bool Ux)
-{
+{// #improveme  using built-in methods
 
   char mybuffer [64];
 
@@ -979,35 +1079,6 @@ GPoint discreteDiskFace::intersectionWithCircle(const SVector3 &n1, const SVecto
   return pp;
 }
 
-void discreteDiskFace::printParamMesh()
-{
-  std::map<MVertex*,int> mv2int;
-  char buffer[256];
-  sprintf(buffer,"param_mesh%d.msh",tag());
-  FILE* pmesh = fopen(buffer,"w");
-  int count = 1;
-  fprintf(pmesh,"$MeshFormat\n2.2 0 8\n$EndMeshFormat\n$Nodes\n%u\n",(unsigned int)allNodes.size());
-  for(std::set<MVertex*>::iterator it = allNodes.begin(); it!=allNodes.end(); ++it){
-    fprintf(pmesh,"%d %f %f 0\n",count,(coordinates[(*it)]).x(),(coordinates[(*it)]).y());
-    mv2int[*it] = count;
-    count++;
-  }
-  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)discrete_triangles.size());
-  for(unsigned int i=0; i<discrete_triangles.size(); i++){
-    MElement* tri = discrete_triangles[i];
-    int p;
-    _order == 1 ? p=2 : p=9;
-      fprintf(pmesh,"%d %d 2 0 0",i+1,p);
-    for(int j=0; j<_N; j++){
-      MVertex* mv = tri->getVertex(j);
-      fprintf(pmesh," %d",mv2int[mv]);
-    }
-    fprintf(pmesh,"\n");
-  }
-  fprintf(pmesh,"$EndElements\n");
-  fclose(pmesh);
-}
-
 // computes some kind of maximal distance in a mesh
 
 static void addTo (std::map<MVertex*, std::vector<MElement*> > &v2t, MVertex *v, MElement *t)
@@ -1036,7 +1107,7 @@ static MEdge getEdge (MElement *t, MVertex *v)
   return MEdge();
 }
 
-/* warning
+/* #warning
 static double computeDistanceLinePoint (MVertex *v1, MVertex *v2, MVertex *v){
 
   SVector3 U  = v2->point() - v1->point();
@@ -1196,4 +1267,71 @@ double triangulation::geodesicDistance ()
   return CLOSEST;
 }
 
+void discreteDiskFace::printAtlasMesh()
+{
+#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
+  std::map<MVertex*,int> mv2int;
+  char buffer[256];
+  sprintf(buffer,"atlas_mesh%d.msh",initialTriangulation->idNum);
+  FILE* pmesh = Fopen(buffer,"w");
+	
+  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));
+  }
+	
+  fprintf(pmesh,"$MeshFormat\n2.2 0 8\n$EndMeshFormat\n$Nodes\n%u\n",(unsigned int)meshvertices.size());
+  int count = 1;
+  for(std::set<MVertex*>::iterator it = meshvertices.begin(); it!=meshvertices.end(); ++it){
+    fprintf(pmesh,"%d %f %f %f\n",count,(*it)->x(),(*it)->y(),(*it)->z());
+    mv2int[*it] = count;
+    count++;
+  }
+  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)initialTriangulation->tri.size());
+  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");
+  }
+  fprintf(pmesh,"$EndElements\n");
+  fclose(pmesh);
+#endif
+}
+
+void discreteDiskFace::printParamMesh()
+{
+  std::map<MVertex*,int> mv2int;
+  char buffer[256];
+  sprintf(buffer,"param_mesh%d.msh",tag());
+  FILE* pmesh = fopen(buffer,"w");
+  int count = 1;
+  fprintf(pmesh,"$MeshFormat\n2.2 0 8\n$EndMeshFormat\n$Nodes\n%u\n",(unsigned int)allNodes.size());
+  for(std::set<MVertex*>::iterator it = allNodes.begin(); it!=allNodes.end(); ++it){
+    fprintf(pmesh,"%d %f %f 0\n",count,(coordinates[(*it)]).x(),(coordinates[(*it)]).y());
+    mv2int[*it] = count;
+    count++;
+  }
+  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)discrete_triangles.size());
+  for(unsigned int i=0; i<discrete_triangles.size(); i++){
+    MElement* tri = discrete_triangles[i];
+    int p;
+    _order == 1 ? p=2 : p=9;
+    fprintf(pmesh,"%d %d 2 0 0",i+1,p);
+    for(int j=0; j<_N; j++){
+      MVertex* mv = tri->getVertex(j);
+      fprintf(pmesh," %d",mv2int[mv]);
+    }
+    fprintf(pmesh,"\n");
+  }
+  fprintf(pmesh,"$EndElements\n");
+  fclose(pmesh);
+}
+
 #endif
diff --git a/Geo/discreteDiskFace.h b/Geo/discreteDiskFace.h
index 170d87df7f9a57107a9b284351d330edd78339f0..b5aed56fa930f0c7791b5ff736f73b2056aeda80 100644
--- a/Geo/discreteDiskFace.h
+++ b/Geo/discreteDiskFace.h
@@ -23,6 +23,8 @@
 #include "PView.h"
 #include "robustPredicates.h"
 #include "MLine.h"
+#include "linearSystemCSR.h"
+#include "dofManager.h"
 
 inline int nodeLocalNum(MElement* e, MVertex* v)
 {
@@ -145,7 +147,7 @@ class triangulation {
 
       std::map<MVertex*,std::vector<MVertex*> >::iterator im = firstNode2Edge.find(first);
       if (im != firstNode2Edge.end()){
-        Msg::Info("Supposed seam point for discreteFace %d", gf->tag());
+        Msg::Info("Assumed seam point for discreteFace %d", gf->tag());
 	seamPoint = true;
 	break;
       }
@@ -198,7 +200,7 @@ class triangulation {
     fprintf(f,"};\n");
     fclose(f);
   }
-
+  
   triangulation() : gf(0) {}
   triangulation(int id, std::vector<MElement*> input, GFace* gface)
     : idNum(id), tri(input), gf(gface) { assign(); }
@@ -217,11 +219,11 @@ class  discreteDiskFaceTriangle {
 class discreteDiskFace : public GFace {
   GFace *_parent;
   void buildOct(std::vector<GFace*> *CAD = NULL) const;
-  bool parametrize(bool one2one = false) const;
+  bool parametrize();// const;
+  void checklsys(linearSystemCSRTaucs<double>*,dofManager<double>*,int);
   void putOnView(bool,bool);
   bool checkOrientationUV();
   void optimize();
-  void printParamMesh();
 
  public:
   discreteDiskFace(GFace *parent, triangulation* diskTriangulation,
@@ -241,14 +243,19 @@ class discreteDiskFace : public GFace {
   GPoint intersectionWithCircle(const SVector3 &n1, const SVector3 &n2,
 				const SVector3 &p, const double &d,
 				double uv[2]) const;
+  void printAtlasMesh () ;
+  void printParamMesh () ;
+  
 
 
   std::vector<MElement*> discrete_triangles;
+
+
+
  protected:
   // a copy of the mesh that should not be destroyed
   triangulation* initialTriangulation;
   triangulation* geoTriangulation;// parametrized triangulation
-
   std::vector<MVertex*> discrete_vertices;
 
   int _order;
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 0f94d4cd450dcd89c93b2a577e9fcf4912ae9513..ea1c672c1e31e972dd201ba14370f8b02f99728d 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -14,6 +14,8 @@
 #include <stack>
 #include <queue>
 
+#include "MPoint.h"
+
 #if defined(HAVE_METIS)
 extern "C" {
 #include <metis.h>
@@ -109,8 +111,9 @@ void discreteFace::secondDer(const SPoint2 &param,
 
 void discreteFace::createGeometry()
 {
-  checkAndFixOrientation();
 
+  checkAndFixOrientation();
+  
 #if defined(HAVE_SOLVER) && defined(HAVE_ANN)
   int order = 1;
   int nPart = 2;
@@ -121,19 +124,16 @@ void discreteFace::createGeometry()
   int id=1;
   std::stack<triangulation*>  toSplit;
   std::vector<triangulation*> toParam;
+  
   std::vector<MElement*> tem(triangles.begin(),triangles.end());
-
   triangulation* init = new triangulation(-1, tem,this);
   toSplit.push(init);
   if((toSplit.top())->genus()!=0 || (toSplit.top())->aspectRatio() > eta ||
-     (toSplit.top())->seamPoint){
-
+				       (toSplit.top())->seamPoint){
     while( !toSplit.empty()){
       std::vector<triangulation*> part;
       triangulation* tosplit = toSplit.top();
       toSplit.pop();
-      //      printf("genus %d ar %12.5E\n",tosplit->genus(), tosplit->aspectRatio());
-      //      getchar();
       split(tosplit,part,nPart);
       delete tosplit;
 
@@ -143,7 +143,6 @@ void discreteFace::createGeometry()
 	else{
 	  toParam.push_back(part[i]);
 	  part[i]->idNum=id++;
-	  //	  printf("part %d is OK\n",  part[i]->idNum);
 	}
       }// end for i
     }// !.empty()
@@ -152,24 +151,23 @@ void discreteFace::createGeometry()
     toParam.push_back(toSplit.top());
     toSplit.top()->idNum=id++;
   }
-  double t1 = Cpu();
-  printf("split done\n");
   updateTopology(toParam);
-  double t2 = Cpu();
-  printf("topology done in %8.3f sec\n",t2-t1);
-
+  
   for(unsigned int i=0; i<toParam.size(); i++){
-    printf("MAP(%d) : aspect ratio = %12.5E\n",toParam[i]->idNum,toParam[i]->aspectRatio());
+    /*
     char name[256];
     sprintf(name,"map%d.pos",i);
     toParam[i]->print(name,i);
+    */
     fillHoles(toParam[i]);
-    sprintf(name,"mapFilled%d.pos",i);
-    toParam[i]->print(name, toParam[i]->idNum);
+    //sprintf(name,"mapFilled%d.pos",i);
+    //toParam[i]->print(name, toParam[i]->idNum);
   }
-  for(unsigned int i=0; i<toParam.size(); i++){
+
+  for(unsigned int i=0; i<toParam.size(); i++){    
     std::vector<MElement*> mytri = toParam[i]->tri;
     discreteDiskFace *df = new discreteDiskFace (this,toParam[i], order,(_CAD.empty() ? NULL : &_CAD));
+    df->printAtlasMesh();
     df->replaceEdges(toParam[i]->my_GEdges);
     _atlas.push_back(df);
   }
@@ -224,96 +222,26 @@ void discreteFace::mesh(bool verbose)
 {
 #if defined(HAVE_ANN) && defined(HAVE_SOLVER) && defined(HAVE_MESH)
   if (!CTX::instance()->meshDiscrete) return;
+
   for (unsigned int i=0;i<_atlas.size();i++){
     Msg::Info("Discrete Face %d is going to be meshed",i);
-    printAtlasMesh(_atlas[i]->discrete_triangles,i);
-    _atlas[i]->mesh(verbose);
-    //printAtlasMesh(_atlas[i],i);
+    _atlas[i]->mesh(verbose);/*
+    const char *name = "atlas%d";
+    char filename[256];
+    sprintf(filename,name,i);
+    _atlas[i]->printPhysicalMesh(filename);*/
   }
-
+  
   gatherMeshes();
   meshStatistics.status = GFace::DONE;
 #endif
 }
 
-void discreteFace::printAtlasMesh(std::vector<MElement*> elm, int I)
-{
-
-  std::map<MVertex*,int> mv2int;
-  char buffer[256];
-  sprintf(buffer,"atlas_mesh%d.msh",I);
-  FILE* pmesh = Fopen(buffer,"w");
 
-  std::set<MVertex*> meshvertices;
-
-  for(unsigned int i=0; i<elm.size(); ++i){
-    MElement* tri = elm[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());
-  int count = 1;
-  for(std::set<MVertex*>::iterator it = meshvertices.begin(); it!=meshvertices.end(); ++it){
-    fprintf(pmesh,"%d %f %f %f\n",count,(*it)->x(),(*it)->y(),(*it)->z());
-    mv2int[*it] = count;
-    count++;
-  }
-  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)elm.size());
-  for(unsigned int i=0; i<elm.size(); i++){
-    MElement* tri = elm[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");
-  }
-  fprintf(pmesh,"$EndElements\n");
-  fclose(pmesh);
-
-}
-
-void discreteFace::printAtlasMesh(discreteDiskFace* ddf, int I)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  std::map<MVertex*,int> mv2int;
-  char buffer[16];
-  sprintf(buffer,"atlas_mesh%d.msh",I);
-  FILE* pmesh = Fopen(buffer,"w");
-
-  std::set<MVertex*> meshvertices;
-
-  for(unsigned int i=0; i<ddf->triangles.size(); ++i){
-    MTriangle* tri = ddf->triangles[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());
-  int count = 1;
-  for(std::set<MVertex*>::iterator it = meshvertices.begin(); it!=meshvertices.end(); ++it){
-    fprintf(pmesh,"%d %f %f %f\n",count,(*it)->x(),(*it)->y(),(*it)->z());
-    mv2int[*it] = count;
-    count++;
-  }
-  fprintf(pmesh,"$EndNodes\n$Elements\n%u\n",(unsigned int)ddf->triangles.size());
-  for(unsigned int i=0; i<ddf->triangles.size(); i++){
-    MTriangle* tri = ddf->triangles[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");
-  }
-  fprintf(pmesh,"$EndElements\n");
-  fclose(pmesh);
-#endif
-}
 
 void discreteFace::checkAndFixOrientation()
 {
+
   // first of all, all the triangles have to be oriented in the same way
   std::map<MEdge,std::vector<MElement*>,Less_Edge> ed2tri; // edge to 1 or 2 triangle(s)
 
@@ -393,10 +321,12 @@ void discreteFace::checkAndFixOrientation()
   } // end while
 }
 
+
 void discreteFace::setupDiscreteVertex(GVertex*dv,MVertex*mv,std::set<MVertex*>*trash){
-  dv->mesh_vertices.push_back(mv);
   mv->setEntity(dv);
+  dv->mesh_vertices.push_back(mv);
   this->model()->add(dv);
+  dv->points.push_back(new MPoint(dv->mesh_vertices.back()));
   if (trash) trash->insert(mv);
 }
 
@@ -404,15 +334,16 @@ void discreteFace::setupDiscreteEdge(discreteEdge*de,std::vector<MLine*>mlines,
                                      std::set<MVertex*>*trash)
 {
   this->model()->add(de);// new GEdge
-  de->lines = mlines;// associated MLine's
+  de->setTopo(mlines);// associated MLine's
   for(unsigned int i=1; i<mlines.size(); i++){//not the first vertex of the GEdge (neither the last one)
     mlines[i]->getVertex(0)->setEntity(de);
     de->mesh_vertices.push_back(mlines[i]->getVertex(0));
     if(trash) trash->insert(mlines[i]->getVertex(0));
   }
   de->createGeometry();
-  if(de->getBeginVertex()->mesh_vertices[0]!=de->lines[0]->getVertex(0))// small hack ... #mark
-    de->reverse();
+  de->getBeginVertex()->addEdge(de);
+  de->getEndVertex()->addEdge(de);
+  
 }
 
 // split old GEdge's
@@ -420,9 +351,9 @@ void discreteFace::splitDiscreteEdge(GEdge *de , GVertex *gv, discreteEdge* newE
 {
   MVertex *vend = de->getEndVertex()->mesh_vertices[0];
 
-  newE[0] = new discreteEdge (de->model(),NEWLINE(),de->getBeginVertex(),gv);
-  newE[1] = new discreteEdge (de->model(),NEWLINE(),gv, de->getEndVertex());
-
+  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());
+  
   int current = 0;
   std::vector<MLine*> mlines;
   // assumption: the MLine's are sorted
@@ -435,6 +366,8 @@ void discreteFace::splitDiscreteEdge(GEdge *de , GVertex *gv, discreteEdge* newE
       current++;
     }
   }
+  de->getBeginVertex()->delEdge(de);
+  de->getEndVertex()->delEdge(de);
   de->mesh_vertices.clear();
   de->lines.clear();
 
@@ -569,7 +502,7 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
   std::set<MVertex*> todelete; // vertices that do not belong to the GFace anymore
   std::set<GEdge*> gGEdges(l_edges.begin(),l_edges.end());// initial GEdges of the GFace (to be updated)
 
-  for(int i=0; i<nPartitions; i++){// each part is going ot be compared with the other ones
+  for(int i=0; i<nPartitions; i++){// each part is going to be compared with the other ones
     const std::set<MEdge,Less_Edge> &bordi = partition[i]->borderEdg;// edges defining the border(s) of the i-th new triangulation
     for(int ii=i+1; ii<nPartitions; ii++){// compare to the ii-th partitions, with ii > i since ii < i have already been compared
       std::map<MVertex*,MLine*> v02edg;//first vertex of the MLine
@@ -606,25 +539,25 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
 	mvt.resize(2);
 	mvt[0] = *itf;
 	mvt[1] = cv0;
-
 	// creation of the GVertex, for new nonloop GEdge's
 	for(int imvt=0; imvt<2; imvt++){
 	  std::set<GEdge*>::iterator oe=gGEdges.begin();// find the old GEdge that has the current new GVertex
 	  while(oe !=gGEdges.end() && mvt[imvt]->onWhat() != *oe && mvt[imvt]->onWhat() != (*oe)->getBeginVertex() && mvt[imvt]->onWhat() != (*oe)->getEndVertex())
-	    ++oe;
+	    ++oe;	    
+
 
 	  if (oe == gGEdges.end()){// not on an existing GEdge: new internal GVertex
-	    v[imvt] = new discreteVertex (this->model(),NEWPOINT());
+	    v[imvt] = new discreteVertex (this->model(),model()->getMaxElementaryNumber(0) + 1);
 	    setupDiscreteVertex(v[imvt],mvt[imvt],&todelete);
 	  }
 	  else{// on an existing GEdge
 	    GEdge* onit = *oe;// the new GVertex can already exist; if it is the case, there is no need to create a new one
 	    if(mvt[imvt] == onit->getBeginVertex()->mesh_vertices[0])
-	      v[imvt] = onit->getBeginVertex();
+	      v[imvt] = onit->getBeginVertex();	    
 	    else if (mvt[imvt] == onit->getEndVertex()->mesh_vertices[0])
-	      v[imvt] = onit->getEndVertex();
+	      v[imvt] = onit->getEndVertex();	      
 	    else{
-	      v[imvt] = new discreteVertex (this->model(),NEWPOINT());
+	      v[imvt] = new discreteVertex (this->model(),model()->getMaxElementaryNumber(0) + 1);
 	      setupDiscreteVertex(v[imvt],mvt[imvt],NULL);
 	      discreteEdge* de[2];
 	      splitDiscreteEdge(onit,v[imvt],de);
@@ -635,11 +568,9 @@ 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(),NEWLINE(),v[0],v[1]);
-	//	printf("creating new discrete edge %d with %d lines (%p %p)\n", internalE->tag(), myLines.size(),v[0],v[1]);
+	discreteEdge* internalE = new discreteEdge (this->model(),model()->getMaxElementaryNumber(1) + 1,v[0],v[1]);
 	setupDiscreteEdge(internalE,myLines,&todelete);
-	partition[i]->my_GEdges.push_back(internalE);
-	partition[ii]->my_GEdges.push_back(internalE);
+	gGEdges.insert(internalE);
 
 	first.erase(itf);// next first vertex of a nonloop GEdge
       }//end while first.empty()
@@ -654,17 +585,16 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
 	  v02edg.erase(cv0);// update the container
 	  cv0 = my_MLines.back()->getVertex(1);// next MLine of the loop
 	}
-	v = new discreteVertex (this->model(),NEWPOINT());
+	v = new discreteVertex (this->model(),model()->getMaxElementaryNumber(0) + 1);
 	setupDiscreteVertex(v,cv0,&todelete);
-	discreteEdge* gloop = new discreteEdge (this->model(),NEWLINE(),v,v);
+	discreteEdge* gloop = new discreteEdge (this->model(),model()->getMaxElementaryNumber(1) + 1,v,v);	
 	setupDiscreteEdge(gloop,my_MLines,&todelete);
-	partition[i]->my_GEdges.push_back(gloop);
-	partition[ii]->my_GEdges.push_back(gloop);
+	gGEdges.insert(gloop);
       }// end while v02edg.empty()
     }//end for ii
   }// end for i
-
-
+  
+  
   // adding old-updated bounding GEdge's to the corresponding partitions
   for(std::set<GEdge*>::iterator le=gGEdges.begin(); le!=gGEdges.end(); ++le){
     GEdge* ile = *le;
@@ -673,7 +603,7 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
       std::set<MEdge,Less_Edge> bordi = partition[i]->borderEdg;
       if(bordi.find(edTest)!=bordi.end()){
 	partition[i]->my_GEdges.push_back(ile);
-	break;
+	//break;
       }
     }
   }
@@ -691,7 +621,7 @@ void discreteFace::updateTopology(std::vector<triangulation*>&partition)
 }
 
 void discreteFace::fillHoles(triangulation* trian)
-{
+{// #improveme moving the center
 #if defined(HAVE_SOLVER) && defined(HAVE_ANN)
   std::map<double,std::vector<MVertex*> > bords = trian->bord;
   std::map<double,std::vector<MVertex*> >::reverse_iterator it = bords.rbegin();
@@ -749,311 +679,6 @@ void discreteFace::fillHoles(triangulation* trian)
 #endif
 }
 
-void discreteFace::bisectionEdg(triangulation* trian)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  std::map<MEdge,double,Less_Edge> ed2angle;
-  std::map<double,std::vector<MEdge> > ed2refine;
-  /*
-    checkEdges
-    for each ed in ed2refine
-    ...while ed exists
-    ......terminal from lepp(ed)
-    ......refine terminal
-    ......update ed2refine
-  */
-  int count = 1;
-  checkEdgesBis(trian,ed2refine,ed2angle);
-  while(!ed2refine.empty()){
-    //for(it = ed2refine.rbegin(); it != ed2refine.rend(); ++it){
-    std::map<double,std::vector<MEdge> >::reverse_iterator it = ed2refine.rbegin();
-    double key = it->first;
-    std::vector<MEdge> & ved = it->second;
-    while(!ved.empty()){
-      //for(unsigned int i=0; i<ved.size(); i++){
-      MEdge ed = ved[0];
-      while(ed2angle.find(ed) != ed2angle.end()){
-	MEdge terminal = lepp(trian,ed);
-	ed2angle.erase(terminal);
-	std::vector<MEdge> ed2update;
-	refineTriangles(trian,terminal,ed2update);
-	updateEd2refineBis(trian,ed2angle,ed2update,ed2refine);
-	printAtlasMesh(trian->tri,-count++);
-      }// end while exists
-      ed2refine[key].erase(ved.begin());
-      ved = ed2refine[key];
-    }// end for unsigned
-    ed2refine.erase(key);
-  }// end for it
-#endif
-}
-
-bool discreteFace::checkEdges(triangulation* trian,
-                              std::map<double,std::vector<MEdge> >& ed2refine,
-                              std::map<MEdge,double,Less_Edge>& ed2angle)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  for(unsigned int i=0; i<trian->tri.size(); i++){
-    MElement* t = trian->tri[i];
-    std::vector<MEdge> eds;
-    eds.push_back(t->getEdge(0));eds.push_back(t->getEdge(1));eds.push_back(t->getEdge(2));
-    for(int j=0; j<3; j++){
-      if(trian->ed2tri[eds[j]].size()>1){
-      MEdge ed1 = eds[j+1>2?j-2:j+1];
-      MEdge ed2 = eds[j+2>2?j-1:j+2];
-      SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
-		  ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
-		  ed1.getVertex(0)->z()-ed1.getVertex(1)->z());
-      SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
-		  ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
-		  ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
-      double dotp = dot(v1,v2);
-      double lp = ed1.length()*ed2.length();
-      std::map<MEdge,double,Less_Edge>::iterator check = ed2angle.find(eds[j]);
-      if(check!=ed2angle.end()){
-	ed2angle[eds[j]] += std::acos(dotp/lp);
-	if(ed2angle[eds[j]]>M_PI)
-	  ed2refine[eds[j].length()].push_back(eds[j]);
-	else
-	  ed2angle.erase(eds[j]);
-      }
-      else
-	  ed2angle[eds[j]] = std::acos(dotp/lp);
-      }//end if size()>1
-    }// end for j
-  }//end for tri
-  return !(ed2refine.empty());
-#else
-  return false;
-#endif
-}
-
-
-bool discreteFace::checkEdgesBis(triangulation* trian,
-                                 std::map<double,std::vector<MEdge> >& ed2refine,
-                                 std::map<MEdge,double,Less_Edge>& ed2angle)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  for(unsigned int i=0; i<trian->tri.size(); i++){
-    MElement* t = trian->tri[i];
-    std::vector<MEdge> eds;
-    eds.push_back(t->getEdge(0));eds.push_back(t->getEdge(1));eds.push_back(t->getEdge(2));
-    for(int j=0; j<3; j++){
-      MEdge ed1 = eds[j+1>2?j-2:j+1];
-      MEdge ed2 = eds[j+2>2?j-1:j+2];
-      SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
-		  ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
-		  ed1.getVertex(0)->z()-ed1.getVertex(1)->z());
-      SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
-		  ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
-		  ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
-      double dotp = dot(v1,v2);
-      double lp = ed1.length()*ed2.length();
-      std::map<MEdge,double,Less_Edge>::iterator check = ed2angle.find(eds[j]);
-      if(check==ed2angle.end()){
-	ed2angle[eds[j]] = std::acos(dotp/lp);
-	if(ed2angle[eds[j]]>M_PI/2.)
-	  ed2refine[eds[j].length()].push_back(eds[j]);
-	else
-	  ed2angle.erase(eds[j]);
-      }
-    }// end for j
-  }//end for tri
-  return !(ed2refine.empty());
-#else
-  return false;
-#endif
-}
-
-MEdge discreteFace::lepp(triangulation* trian,MEdge ed)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  std::vector<int> intri = trian->ed2tri[ed];
-  bool isTerminal = false;
-  while(intri.size()>1 && !isTerminal){
-    MEdge ed0 = maxEdge(trian->tri[intri[0]]);
-    MEdge ed1 = maxEdge(trian->tri[intri[1]]);
-    if(ed != ed0){
-      ed = ed0;
-      intri = trian->ed2tri[ed];
-    }
-    else if(ed != ed1){
-      ed = ed1;
-      intri = trian->ed2tri[ed];
-    }
-    else isTerminal = true;
-  }// end while
-  return ed;
-#else
-  return MEdge();
-#endif
-}
-
-void discreteFace::refineTriangles(triangulation* trian,MEdge ed,
-                                   std::vector<MEdge>&ed2update)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  SPoint3 mid = ed.barycenter();
-  MVertex* mv = new MVertex(mid.x(),mid.y(),mid.z());
-  trian->vert.insert(mv);
-
-  std::vector<int> t = trian->ed2tri[ed];
-
-  MTriangle *t00, *t01;
-  int ie;
-
-  ie = edgeLocalNum(trian->tri[t[0]],ed);
-  t00 = new MTriangle(trian->tri[t[0]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(0),trian->tri[t[0]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(1),mv);
-  t01 = new MTriangle(trian->tri[t[0]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(0),trian->tri[t[0]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(1),mv);
-
-  trian->tri[t[0]] = t00;
-  trian->ed2tri[t00->getEdge(2)] = trian->ed2tri[ed];
-  trian->ed2tri[t00->getEdge(1)].push_back(t[0]);
-  trian->ed2tri[t00->getEdge(1)].push_back(trian->tri.size());
-
-  std::vector<int> oldtri = trian->ed2tri[ed];
-  oldtri[0] == t[0] ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
-  trian->ed2tri[t01->getEdge(1)] = oldtri;
-  oldtri = trian->ed2tri[t01->getEdge(0)];
-  oldtri[0] == t[0]  ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
-  trian->ed2tri[t01->getEdge(0)] = oldtri;
-  trian->tri.push_back(t01);
-
-  ed2update.push_back(t00->getEdge(0));
-  ed2update.push_back(t01->getEdge(0));
-
-  if(t.size()>1){
-
-    ed2update.push_back(t01->getEdge(1));
-    ed2update.push_back(t00->getEdge(2));
-    MTriangle  *t10, *t11;
-
-    this->mesh_vertices.push_back(mv);
-    mv->setEntity(this);
-
-    ie = edgeLocalNum(trian->tri[t[1]],ed);
-    t11 = new MTriangle(trian->tri[t[1]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(0),trian->tri[t[1]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(1),mv);
-    t10 = new MTriangle(trian->tri[t[1]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(0),trian->tri[t[1]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(1),mv);
-
-    trian->tri[t[1]] = t10;
-    trian->ed2tri[t10->getEdge(1)] = trian->ed2tri[ed];
-    trian->ed2tri[t10->getEdge(2)].push_back(t[1]);
-    trian->ed2tri[t10->getEdge(2)].push_back(trian->tri.size());
-
-    oldtri = trian->ed2tri[t11->getEdge(2)];
-    oldtri[0] == t[1] ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
-    trian->ed2tri[t11->getEdge(2)] = oldtri;
-    oldtri = trian->ed2tri[t11->getEdge(0)];
-    oldtri[0] == t[1]  ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
-    trian->ed2tri[t11->getEdge(0)] = oldtri;
-    trian->tri.push_back(t11);
-
-    ed2update.push_back(t10->getEdge(0));
-    ed2update.push_back(t11->getEdge(0));
-
-  }
-  else{
-    std::list<GEdge*> gGEdges = trian->my_GEdges;
-    std::list<GEdge*>::iterator oe = gGEdges.begin();
-    while(oe != gGEdges.end() && ed.getVertex(0)->onWhat() != *oe && ed.getVertex(0)->onWhat() != (*oe)->getBeginVertex())
-	    ++oe;
-    GEdge* ged = *oe;
-    std::vector<MLine*> mlines = ged->lines;
-    std::vector<MLine*> conca;
-    for (unsigned int i=0; i<mlines.size(); i++){
-      if ((mlines[i]->getVertex(0)==ed.getVertex(0)&&mlines[i]->getVertex(1)==ed.getVertex(1))||
-	  (mlines[i]->getVertex(1)==ed.getVertex(0)&&mlines[i]->getVertex(0)==ed.getVertex(1))){
-	conca.push_back(new MLine(mlines[i]->getVertex(0),mv));
-	conca.push_back(new MLine(mv,mlines[i]->getVertex(1)));// delete MLine ?
-      }
-      else conca.push_back(mlines[i]);
-    }
-    discreteEdge* de = new discreteEdge(this->model(),NEWLINE(),ged->getBeginVertex(),ged->getEndVertex());
-    setupDiscreteEdge(de,conca,NULL);
-    trian->my_GEdges.remove(ged);
-    ged->lines.clear();
-    ged->mesh_vertices.clear();
-    trian->my_GEdges.push_back(de);
-    trian->borderEdg.erase(ed);
-    trian->borderEdg.insert(t00->getEdge(2));
-    trian->borderEdg.insert(t01->getEdge(1));
-  }
-#endif
-}
-
-void discreteFace::updateEd2refine(triangulation* trian,
-                                   std::map<MEdge,double,Less_Edge>&ed2angle,
-                                   std::vector<MEdge>&ed2update,
-                                   std::map<double,std::vector<MEdge> >&ed2refine)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  for(unsigned int i=0; i<ed2update.size(); i++){
-    MEdge current = ed2update[i];
-    std::vector<int> intri = trian->ed2tri[current];
-    if(intri.size()>1 && ed2angle.find(current) == ed2angle.end() ){
-      ed2angle[current] = 0.;
-      for(unsigned int j=0; j<intri.size(); j++){
-	MElement* tri = trian->tri[intri[j]];
-	int num = edgeLocalNum(tri,current);
-	MEdge ed1 = tri->getEdge(num+1>2?num-2:num+1);
-	MEdge ed2 = tri->getEdge(num+2>2?num-1:num+2);
-	SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
-		    ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
-		    ed1.getVertex(0)->z()-ed1.getVertex(1)->z());
-	SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
-		    ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
-		    ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
-	double dotp = dot(v1,v2);
-	double lp = ed1.length()*ed2.length();
-	if(ed2angle[current]==0.)
-	  ed2angle[current] = std::acos(dotp/lp);
-	else{
-	  ed2angle[current] += std::acos(dotp/lp);
-	  if(ed2angle[current] > M_PI)
-	    ed2refine[current.length()].push_back(current);
-	  else
-	    ed2angle.erase(current);
-	}
-      }//end for j
-    }
-  }// end for i
-#endif
-}
-
-void discreteFace::updateEd2refineBis(triangulation* trian,
-                                      std::map<MEdge,double,Less_Edge>&ed2angle,
-                                      std::vector<MEdge>&ed2update,
-                                      std::map<double,std::vector<MEdge> >&ed2refine)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  for(unsigned int i=0; i<ed2update.size(); i++){
-    MEdge current = ed2update[i];
-    std::vector<int> intri = trian->ed2tri[current];
-    for(unsigned int j=0; j<intri.size(); j++){
-      if(ed2angle.find(current) == ed2angle.end() ){
-	MElement* tri = trian->tri[intri[j]];
-	int num = edgeLocalNum(tri,current);
-	MEdge ed1 = tri->getEdge(num+1>2?num-2:num+1);
-	MEdge ed2 = tri->getEdge(num+2>2?num-1:num+2);
-	SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
-		    ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
-		    ed1.getVertex(0)->z()-ed1.getVertex(1)->z());
-	SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
-		    ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
-		    ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
-	double dotp = dot(v1,v2);
-	double lp = ed1.length()*ed2.length();
-	ed2angle[current] = std::acos(dotp/lp);
-	if (ed2angle[current]>M_PI/2.)
-	  ed2refine[current.length()].push_back(current);
-	else
-	  ed2angle.erase(current);
-      }//end for j
-    }
-  }// end for i
-#endif
-}
-
 void discreteFace::addTriangle(triangulation* trian, MTriangle* t)
 {
 #if defined(HAVE_SOLVER) && defined(HAVE_ANN)
diff --git a/Geo/discreteFace.h b/Geo/discreteFace.h
index 2515f1fbbc3ce9326852958597e8223d2a0f4d69..ee911f6e76eefedef6e7da68e3d5a7716c31996a 100644
--- a/Geo/discreteFace.h
+++ b/Geo/discreteFace.h
@@ -31,19 +31,13 @@ class discreteFace : public GFace {
   discreteFace(GModel *model, int num);
   virtual ~discreteFace() {}
   void checkAndFixOrientation();
+  void checkConnectivity(std::vector<std::vector<MElement*> >&);
   void setupDiscreteVertex(GVertex*,MVertex*,std::set<MVertex*>*);
   void setupDiscreteEdge(discreteEdge*,std::vector<MLine*>,std::set<MVertex*>*);
   void splitDiscreteEdge(GEdge*,GVertex*,discreteEdge*[2]);
   void updateTopology(std::vector<triangulation*>&);
   void split(triangulation*,std::vector<triangulation*>&,int);
   void fillHoles(triangulation*);
-  void bisectionEdg(triangulation*);
-  bool checkEdges(triangulation*,std::map<double,std::vector<MEdge> >&,std::map<MEdge,double,Less_Edge>&);
-  bool checkEdgesBis(triangulation*,std::map<double,std::vector<MEdge> >&,std::map<MEdge,double,Less_Edge>&);
-  MEdge lepp(triangulation*,MEdge);
-  void refineTriangles(triangulation*,MEdge,std::vector<MEdge>&);
-  void updateEd2refine(triangulation*,std::map<MEdge,double,Less_Edge>&,std::vector<MEdge>&,std::map<double,std::vector<MEdge> >&);
-   void updateEd2refineBis(triangulation*,std::map<MEdge,double,Less_Edge>&,std::vector<MEdge>&,std::map<double,std::vector<MEdge> >&);
   void addTriangle(triangulation*,MTriangle*);
   GPoint point(double par1, double par2) const;
   SPoint2 parFromPoint(const SPoint3 &p, bool onSurface=true) const;