diff --git a/Geo/discreteDiskFace.cpp b/Geo/discreteDiskFace.cpp
index 4c28872ce9fa63aa9668d7dabbd8d4730cd0235e..b06f5660f59eab26f047973f4d493cd7b13aebc1 100644
--- a/Geo/discreteDiskFace.cpp
+++ b/Geo/discreteDiskFace.cpp
@@ -26,6 +26,8 @@
 #include "convexCombinationTerm.h"  // #FIXME
 
 #include "qualityMeasuresJacobian.h" // #temporary?
+#include "OptHomRun.h"
+#include "MeshQualityOptimizer.h"
 
 static inline void functionShapes(int p, double Xi[2], double* phi)
 {
@@ -286,13 +288,17 @@ discreteDiskFace::discreteDiskFace(int id, GFace *gf, triangulation* diskTriangu
   if (!checkOrientationUV()){
     Msg::Info("discreteDiskFace:: parametrization is not one-to-one; fixing "
               "the discrete system.");
-    parametrize(true);
+
+    //parametrize(true);
+    //buildOct(CAD); 
+    optimize();
     buildOct(CAD);    
-  }
-  
+    
+    }
   putOnView(true,false);
   printParamMesh();
   if(!checkOrientationUV()) Msg::Fatal("discreteDiskFace:: failing to fix the discrete system");
+  else Msg::Info("Parameterization done :-)");
 }
 /*end BUILDER*/
 
@@ -497,6 +503,87 @@ bool discreteDiskFace::checkOrientationUV()
   }
 }
 
+
+void discreteDiskFace::optimize(){
+
+  // parameters for mesh optimization
+  // -- high order
+  OptHomParameters optParams;
+  optParams.dim = 2;
+  optParams.optPassMax = 10;
+  optParams.TMAX = 300;
+  optParams.fixBndNodes = true;
+  optParams.strategy = 1;
+  // -- linear
+  MeshQualOptParameters opt;
+  opt.dim = 2;
+  opt.fixBndNodes = true;
+
+  //creating the "geometry" of the parametrization, and its corresponding mesh
+  // -- generation of parametric nodes
+  std::map<SPoint3,MVertex*> sp2mv;
+  std::vector<MElement*> paramTriangles;
+  for(std::map<MVertex*,SPoint3>::iterator it=coordinates.begin(); it!= coordinates.end(); ++it)
+    sp2mv[it->second] = new MVertex(it->second.x(),it->second.y(),0.);
+  // -- generation of parametric triangles    
+  paramTriangles.resize(discrete_triangles.size() - geoTriangulation->fillingHoles.size());
+  for(unsigned int i=0; i<discrete_triangles.size() -geoTriangulation->fillingHoles.size(); i++){
+    discreteDiskFaceTriangle* ct = &_ddft[i];
+    std::vector<MVertex*> mv;
+    mv.resize(ct->tri->getNumVertices());
+    for (int j=0; j<ct->tri->getNumVertices(); j++)
+      mv[j] = sp2mv[ct->p[j]];    
+    if(_order==1)
+      paramTriangles[i] = new MTriangle(mv);
+    else
+      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;
+  e2e[0] = paramTriangles;
+  std::vector<int> v;
+  v.push_back(0);
+  std::map<int,std::vector<int> > e2p;
+  e2p[0] = v;
+  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);
+  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]]]));
+  }
+  de.createGeometry();
+
+  
+  // 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++){
+    discreteDiskFaceTriangle* ct = &_ddft[i];
+    MElement* tri = paramTriangles[i];
+    for(int j=0; j<ct->tri->getNumVertices(); j++){
+      MVertex* mv = tri->getVertex(j);
+      SPoint3 p(mv->x(), mv->y(), 0);
+      coordinates[ct->tri->getVertex(j)] = p;
+      ct->p[j] = p;
+    }
+  }
+
+  // cleaning
+  delete paramDisk;
+  
+}
+
 // (u;v) |-> < (x;y;z); GFace; (u;v) >
 GPoint discreteDiskFace::point(const double par1, const double par2) const
 {
@@ -1010,7 +1097,7 @@ double triangulation::geodesicDistance () {
     addTo (v2t, tri[i]->getVertex(2),tri[i]);
   }
 
-  //  printf("computing geodesic distance with %d triangles and %d vertcie\n",
+  //  printf("computing geodesic distance with %d triangles and %d vertices\n",
   //	 tri.size(),v2t.size());
   
   std::map<MVertex*,double> Fixed;
diff --git a/Geo/discreteDiskFace.h b/Geo/discreteDiskFace.h
index d5e394904502fceadcf6bf2921b9e559d6bff6f0..aa4908def9a7f21d9966566c2a754b5f9ca4a6f2 100644
--- a/Geo/discreteDiskFace.h
+++ b/Geo/discreteDiskFace.h
@@ -22,20 +22,7 @@
 #include "meshGFaceOptimize.h"
 #include "PView.h"
 #include "robustPredicates.h"
-
-inline double tri3Darea(MVertex* mv0, MVertex* mv1, MVertex* mv2)
-{
-
-  SVector3 v1(mv1->x()-mv0->x(),mv1->y()-mv0->y(),mv1->z()-mv0->z());
-  SVector3 v2(mv2->x()-mv0->x(),mv2->y()-mv0->y(),mv2->z()-mv0->z());
-  
-  SVector3 n(v1.y()*v2.z()-v2.y()*v1.z(),v2.x()*v1.z()-v1.x()*v2.z(),v1.x()*v2.y()-v2.x()*v1.y());
-
-  
-  return .5*n.norm();
-
-}
-
+#include "MLine.h"
 
 inline int nodeLocalNum(MElement* e, MVertex* v)
 {
@@ -231,6 +218,7 @@ class discreteDiskFace : public GFace {
   bool parametrize(bool one2one = false) const;
   void putOnView(bool,bool);
   bool checkOrientationUV();
+  void optimize();
   void printParamMesh();
 
  public:
@@ -274,6 +262,7 @@ class discreteDiskFace : public GFace {
   mutable discreteDiskFaceTriangle *_ddft;
   mutable Octree *oct;
   mutable std::vector<double> _coords;
+  
 };
 
 #endif
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 776a0a8dddece283f6d778ef2c2ce85afcc97d56..1e5f01ae02b2ebc2cae5be547d051bbda510f939 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -111,7 +111,7 @@ void discreteFace::secondDer(const SPoint2 &param,
 void discreteFace::createGeometry()
 {
   checkAndFixOrientation();
-  int order = 1;
+  int order = 2;
   int nPart = 2;
   double eta = 2*3.14/7;
 
@@ -154,12 +154,12 @@ void discreteFace::createGeometry()
 
   for(unsigned int i=0; i<toParam.size(); i++){
     //printf("MAP(%d) : aspect ratio = %12.5E\n",i,toParam[i]->aspectRatio());
-    char name[256];
+    //char name[256];
     //sprintf(name,"map%d.pos",i);
-    toParam[i]->print(name,i);
+    //toParam[i]->print(name,i);
     fillHoles(toParam[i]);
     //sprintf(name,"mapFilled%d.pos",i);
-    toParam[i]->print(name,i);
+    //toParam[i]->print(name,i);
   }
   for(unsigned int i=0; i<toParam.size(); i++){
     std::vector<MElement*> mytri = toParam[i]->tri;
@@ -167,6 +167,7 @@ void discreteFace::createGeometry()
     df->replaceEdges(toParam[i]->my_GEdges);
     _atlas.push_back(df);
   }
+
 #endif
 }
 
@@ -215,7 +216,6 @@ void discreteFace::gatherMeshes()
 
 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++){