diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp
index 8b9b4ab4e91440ba0f1257ede40f92fc709fafe5..203d8fca12d6d4fd5a365571f791cf9461a02015 100644
--- a/Geo/GFaceCompound.cpp
+++ b/Geo/GFaceCompound.cpp
@@ -44,6 +44,40 @@ static void fixEdgeToValue(GEdge *ed, double value, dofManager<double> &myAssemb
   }
 }
 
+//--------------------------------------------------------------
+static int intersection_segments (SPoint3 &p1, SPoint3 &p2,
+				  SPoint3 &q1, SPoint3 &q2, 
+				  double x[2]){
+  
+
+  double xp_max = std::max(p1.x(),p2.x()); 
+  double yp_max = std::max(p1.y(),p2.y()); 
+  double xq_max = std::max(q1.x(),q2.x()); 
+  double yq_max = std::max(q1.y(),q2.y()); 
+
+  double xp_min = std::min(p1.x(),p2.x()); 
+  double yp_min = std::min(p1.y(),p2.y()); 
+  double xq_min = std::min(q1.x(),q2.x()); 
+  double yq_min = std::min(q1.y(),q2.y()); 
+  if ( yq_min > yp_max || xq_min >  xp_max ||
+       yq_max < yp_min || xq_max <  xp_min){
+    return 0;
+  }
+  else{
+  double A[2][2];
+  A[0][0] = p2.x()-p1.x();
+  A[0][1] = q1.x()-q2.x();
+  A[1][0] = p2.y()-p1.y();
+  A[1][1] = q1.y()-q2.y();
+  double b[2] = {q1.x()-p1.x(),q1.y()-p1.y()};
+  sys2x2(A,b,x);
+
+  return (x[0] >= 0.0 && x[0] <= 1. &&
+	  x[1] >= 0.0 && x[1] <= 1.);
+  } 
+  
+}
+//--------------------------------------------------------------
 static void computeCGKernelPolygon(std::map<MVertex*,SPoint3> &coordinates, 
                                    std::vector<MVertex*> &cavV, double &ucg, double &vcg)
 {
@@ -242,6 +276,8 @@ void GFaceCompound::fillNeumannBCS() const
       double x=0.; 
       double y=0.; 
       double z=0.;
+      //EMI- TODO FIND KERNEL OF POLYGON AND PLACE AT CG KERNEL !
+      //IF NO KERNEL -> DO NOT FILL TRIS
       for (std::list<GEdge*>::iterator ite = loop.begin(); ite != loop.end(); ite++){
 	for (unsigned int k= 0; k< (*ite)->getNumMeshElements(); k++){
 	  MVertex *v0 = (*ite)->getMeshElement(k)->getVertex(0);
@@ -261,46 +297,45 @@ void GFaceCompound::fillNeumannBCS() const
 	  MVertex *v0 = (*ite)->getMeshElement(i)->getVertex(0);
 	  MVertex *v1 = (*ite)->getMeshElement(i)->getVertex(1);
   
-	  //fillTris.push_back(new MTriangle(v0,v1, c));
+//	  fillTris.push_back(new MTriangle(v0,v1, c));
 
-// 	  MVertex *v2 = new MVertex(.5*(v0->x()+c->x()), .5*(v0->y()+c->y()), .5*(v0->z()+c->z()));
-// 	  MVertex *v3 = new MVertex(.5*(v1->x()+c->x()), .5*(v1->y()+c->y()), .5*(v1->z()+c->z()));
-// 	  fillTris.push_back(new MTriangle(v0,v2,v3));
-// 	  fillTris.push_back(new MTriangle(v2,c, v3));
-// 	  fillTris.push_back(new MTriangle(v0,v3, v1);
-
-	  MVertex *v2 = new MVertex(.66*v0->x()+.33*c->x(), .66*v0->y()+.33*c->y(), .66*v0->z()+.33*c->z());
-	  MVertex *v3 = new MVertex(.66*v1->x()+.33*c->x(), .66*v1->y()+.33*c->y(), .66*v1->z()+.33*c->z());
-	  MVertex *v4 = new MVertex(.33*v0->x()+.66*c->x(), .33*v0->y()+.66*c->y(), .33*v0->z()+.66*c->z());
-	  MVertex *v5 = new MVertex(.33*v1->x()+.66*c->x(), .33*v1->y()+.66*c->y(), .33*v1->z()+.66*c->z()); 
+	  MVertex *v2 = new MVertex(.5*(v0->x()+c->x()), .5*(v0->y()+c->y()), .5*(v0->z()+c->z()));
+	  MVertex *v3 = new MVertex(.5*(v1->x()+c->x()), .5*(v1->y()+c->y()), .5*(v1->z()+c->z()));
 	  fillTris.push_back(new MTriangle(v0,v2,v3));
-	  fillTris.push_back(new MTriangle(v2,v5,v3));
-	  fillTris.push_back(new MTriangle(v2,v4,v5));
-	  fillTris.push_back(new MTriangle(v4,c,v5));
-	  fillTris.push_back(new MTriangle(v0,v3,v1));
+	  fillTris.push_back(new MTriangle(v2,c, v3));
+	  fillTris.push_back(new MTriangle(v0,v3, v1)) ;
+
+// 	  MVertex *v2 = new MVertex(.66*v0->x()+.33*c->x(), .66*v0->y()+.33*c->y(), .66*v0->z()+.33*c->z());
+// 	  MVertex *v3 = new MVertex(.66*v1->x()+.33*c->x(), .66*v1->y()+.33*c->y(), .66*v1->z()+.33*c->z());
+// 	  MVertex *v4 = new MVertex(.33*v0->x()+.66*c->x(), .33*v0->y()+.66*c->y(), .33*v0->z()+.66*c->z());
+// 	  MVertex *v5 = new MVertex(.33*v1->x()+.66*c->x(), .33*v1->y()+.66*c->y(), .33*v1->z()+.66*c->z()); 
+// 	  fillTris.push_back(new MTriangle(v0,v2,v3));
+// 	  fillTris.push_back(new MTriangle(v2,v5,v3));
+// 	  fillTris.push_back(new MTriangle(v2,v4,v5));
+// 	  fillTris.push_back(new MTriangle(v4,c,v5));
+// 	  fillTris.push_back(new MTriangle(v0,v3,v1));
 
 	}
       }
     }
   }
   
-  //if (fillTris.size() > 0)
-    //printf("**** Filling Neuman BCs with %d triangles \n", fillTris.size());
-  
-//    FILE * ftri = fopen("fillTris.pos","w");
-//    fprintf(ftri,"View \"\"{\n");
-//    for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 !=fillTris.end(); it2++ ){
-//      MTriangle *t = (*it2);
-//      fprintf(ftri,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
-//  	    t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(),
-//  	    t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(),
-//  	    t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(),
-//  	    1., 1., 1.);
-//    }
-//    fprintf(ftri,"};\n");
-//    fclose(ftri);
-   
-//    exit(1);
+
+  if (fillTris.size() > 0){
+    FILE * ftri = fopen("fillTris.pos","a");
+    fprintf(ftri,"View \"\"{\n");
+    for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 !=fillTris.end(); it2++ ){
+      MTriangle *t = (*it2);
+      fprintf(ftri,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
+	      t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(),
+	      t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(),
+	      t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(),
+	      1., 1., 1.);
+    }
+    fprintf(ftri,"};\n");
+    fclose(ftri);
+  }
+
 
 }
 
@@ -313,7 +348,31 @@ bool GFaceCompound::trivial() const
   }
   return false;
 }
+//For the conformal map the linear system cannot guarantee there is no folding 
+//of triangles
+bool GFaceCompound::checkFolding(std::vector<MVertex*> &ordered) const
+{
+ 
+  bool has_no_folding = true;
+
+  for(unsigned int i = 0; i < ordered.size()-1; ++i){
+    SPoint3 p1 = coordinates[ordered[i]];
+    SPoint3 p2 = coordinates[ordered[i+1]];
+    int maxSize = (i==0) ? ordered.size()-2: ordered.size()-1;
+    for(unsigned int k = i+2; k < maxSize; ++k){
+      SPoint3 q1 = coordinates[ordered[k]];
+      SPoint3 q2 = coordinates[ordered[k]];
+      double x[2];
+      int inters = intersection_segments (p1,p2,q1,q2,x);
+      if (inters > 0) has_no_folding = false;
+    }
+  }
+  
+  if ( !has_no_folding ) 
+    Msg::Warning("$$$ Folding for compound face %d", this->tag());
 
+  return has_no_folding;
+}
 
 //check if the discrete harmonic map is correct
 //by checking that all the mapped triangles have
@@ -419,52 +478,60 @@ bool GFaceCompound::parametrize() const
   
   if(allNodes.empty()) buildAllNodes();
   
-//   // TEST MULTISCALE LAPLACE ----------------------------------
-//   std::vector<MElement*> _elements;
-//   for( std::list<GFace*>::const_iterator itt = _compound.begin(); itt != _compound.end(); ++itt)
-//     for(unsigned int i = 0; i < (*itt)->triangles.size(); ++i)
-//       _elements.push_back((*itt)->triangles[i]);
-//   multiscaleLaplace multiLaplace(_elements); 
-//   printf("ended multiscale \n");
-//   exit(1);
-  // TEST MULTISCALE LAPLACE ----------------------------------
 
   //Laplace parametrization
   //-----------------
   if (_mapping == HARMONIC){
-    Msg::Debug("Parametrizing surface %d with 'harmonic map'", tag());
+    Msg::Debug("Parametrizing surface %d with 'harmonic map'", tag()); 
     fillNeumannBCS();
     parametrize(ITERU,HARMONIC); 
     parametrize(ITERV,HARMONIC);
   }
+  //Multiscale Laplace parametrization
+  //-----------------
+  else if (_mapping == MULTISCALE){
+    std::vector<MElement*> _elements;
+    for( std::list<GFace*>::const_iterator itt = _compound.begin(); itt != _compound.end(); ++itt)
+      for(unsigned int i = 0; i < (*itt)->triangles.size(); ++i)
+	_elements.push_back((*itt)->triangles[i]);
+    multiscaleLaplace multiLaplace(_elements, coordinates); 
+  }
   //Conformal map parametrization
   //----------------- 
   else if (_mapping == CONFORMAL){
     Msg::Debug("Parametrizing surface %d with 'conformal map'", tag());
     fillNeumannBCS();
-    parametrize_conformal();
+    bool withoutFolding = parametrize_conformal() ;
+    printStuff();
+    if ( withoutFolding == false ){
+      Msg::Warning("$$$ Parametrization switched to harmonic map");
+      parametrize(ITERU,HARMONIC); 
+      parametrize(ITERV,HARMONIC);
+    }
   }
   //Distance function
   //-----------------
   //compute_distance();
 
   buildOct();  
-  
+  printStuff();
+
   if (!checkOrientation(0)){
-    Msg::Info("Parametrization switched to convex combination map");
+    Msg::Info("*** Parametrization switched to convex combination map");
     coordinates.clear(); 
     Octree_Delete(oct);
     fillNeumannBCS();
     parametrize(ITERU,CONVEXCOMBINATION);
     parametrize(ITERV,CONVEXCOMBINATION);
+    checkOrientation(0);
     buildOct();
   }
 
-  printStuff();
+
 
   computeNormals();  
 
-  if (!checkAspectRatio()){
+  if (checkAspectRatio() > AR_MAX){
     printf("WARNING: geom aspect ratio too high \n");
     exit(1);
     paramOK = false;
@@ -534,30 +601,28 @@ double GFaceCompound::getSizeH() const
 {
 
   SBoundingBox3d bb;
-  SOrientedBoundingBox obbox ;
   std::vector<SPoint3> vertices;
   for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
     SPoint3 pt((*itv)->x(),(*itv)->y(), (*itv)->z());
     vertices.push_back(pt);
     bb +=pt;
   }
-   
-  //obbox =  SOrientedBoundingBox::buildOBB(vertices);
-  //double H = obbox.getMaxSize(); 
- 
   double H = norm(SVector3(bb.max(), bb.min()));
 
+  //SOrientedBoundingBox obbox =  SOrientedBoundingBox::buildOBB(vertices);
+  //double H = obbox.getMaxSize(); 
+ 
   return H;
 
 }
 double GFaceCompound::getSizeBB(const std::list<GEdge* > &elist) const
 {
    
-  SOrientedBoundingBox obboxD = obb_boundEdges(elist);
-  double D = obboxD.getMaxSize();
+  //SOrientedBoundingBox obboxD = obb_boundEdges(elist);
+  //double D = obboxD.getMaxSize();
 
-  //SOrientedBoundingBox bboxD = boundEdges(elist);
-  //double D = norm(SVector3(bboxD.max(), bboxD.min()));
+  SBoundingBox3d bboxD = boundEdges(elist);
+  double D = norm(SVector3(bboxD.max(), bboxD.min()));
 
   return D;
 
@@ -1035,7 +1100,7 @@ void GFaceCompound::parametrize(iterationStep step, typeOfMapping tom) const
 
 }
 
-void GFaceCompound::parametrize_conformal() const
+bool GFaceCompound::parametrize_conformal() const
 {
 
   dofManager<double> myAssembler(_lsys);
@@ -1045,20 +1110,22 @@ void GFaceCompound::parametrize_conformal() const
   bool success = orderVertices(_U0, ordered, coords);
   if(!success){
     Msg::Error("Could not order vertices on boundary");
-    return;
+    return false;
   }
 
-  MVertex *v1 = ordered[0];
-  MVertex *v2 ; 
-  double maxSize = 0.0;
-  for (int i=1; i< ordered.size(); i++){
-    MVertex *vi= ordered[i];
-    double dist = vi->distance(v1);
-    if (dist > maxSize){
-      v2 = vi;
-      maxSize = dist;
-    }
-  }
+   MVertex *v1 = ordered[0];
+   MVertex *v2  = ordered[(int)ceil(ordered.size()/2)];
+
+//   MVertex *v2 ;  
+//   double maxSize = 0.0;
+//   for (int i=1; i< ordered.size(); i++){
+//     MVertex *vi= ordered[i];
+//     double dist = vi->distance(v1);
+//     if (dist > maxSize){
+//       v2 = vi;
+//       maxSize = dist;
+//     }
+//   }
 
   myAssembler.fixVertex(v1, 0, 1, 0);//0
   myAssembler.fixVertex(v1, 0, 2, 0);//0
@@ -1127,6 +1194,9 @@ void GFaceCompound::parametrize_conformal() const
 
   _lsys->clear();
 
+  //check for folding
+  return checkFolding(ordered);
+
 }
 
 void GFaceCompound::compute_distance() const
@@ -1611,22 +1681,27 @@ bool GFaceCompound::checkTopology() const
 
   double H = getSizeH();
   double D = H; 
-  if (_interior_loops.size() > 0)    D =  getSizeBB(_U0);
-  int AR = (int) ceil(H/D);
-  
+  if (_interior_loops.size() > 0)    D =  getSizeBB(_U0); 
+  int AR = (int) checkAspectRatio();
+  //int AR = (int) ceil(H/D);
+
   if (G != 0 || Nb < 1){
     correctTopo = false;
-    nbSplit = 2; //std::max(G+2, 2);
+    nbSplit = std::max(G+2, 2);
     Msg::Info("-----------------------------------------------------------");
     Msg::Warning("Wrong topology: Genus=%d, Nb boundaries=%d, AR=%g", G, Nb, H/D);
     Msg::Info("*** Split surface %d in %d parts with Multilevel Mesh partitioner", tag(), nbSplit);
   }
-   else if (G == 0 && AR > 3){
+   else if (G == 0 && AR > AR_MAX){
      correctTopo = false;
      nbSplit = -2;
      Msg::Info("-----------------------------------------------------------");
      Msg::Warning("Wrong topology: Genus=%d, Nb boundaries=%d, AR=%d", G, Nb, AR);
      Msg::Info("*** Split surface %d in 2 parts with Laplacian Mesh partitioner", tag());
+
+//      correctTopo = true;
+//      _mapping = MULTISCALE;
+//      Msg::Warning("Aspect Ratio (AR=%d) is too high: using multiscale Laplace", AR);
    }
   else{
     Msg::Debug("Correct topology: Genus=%d and Nb boundaries=%d, AR=%g", G, Nb, H/D);
@@ -1636,17 +1711,17 @@ bool GFaceCompound::checkTopology() const
 
 }
 
-bool GFaceCompound::checkAspectRatio() const
+double GFaceCompound::checkAspectRatio() const
 {
 
   //if ((*(_compound.begin()))->geomType() != GEntity::DiscreteSurface)
   //  return true;
 
-  bool paramOK = true;
   if(allNodes.empty()) buildAllNodes();
   
   double limit =  1.e-15;
   double areaMin = 1.e15;
+  double area3D = 0.0;
   int nb = 0;
   std::list<GFace*>::const_iterator it = _compound.begin();
   for( ; it != _compound.end() ; ++it){
@@ -1663,6 +1738,7 @@ bool GFaceCompound::checkAspectRatio() const
       double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()};
       double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()};
       double a_3D = fabs(triangle_area(p0, p1, p2));
+      area3D += a_3D;
       double q0[3] = {it0->second.x(), it0->second.y(), 0.0}; 
       double q1[3] = {it1->second.x(), it1->second.y(), 0.0};
       double q2[3] = {it2->second.x(), it2->second.y(), 0.0};
@@ -1672,6 +1748,20 @@ bool GFaceCompound::checkAspectRatio() const
     }
   }
   
+  std::list<GEdge*>::const_iterator it0 = _U0.begin();
+  double tot_length = 0;
+  for( ; it0 != _U0.end(); ++it0 ){
+    for(unsigned int i = 0; i < (*it0)->lines.size(); i++ ){
+      MVertex *v0 = (*it0)->lines[i]->getVertex(0);
+      MVertex *v1 = (*it0)->lines[i]->getVertex(1);    
+      const double length = 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()));
+      tot_length += length;
+    }
+  }
+  double AR = 2*3.14*area3D/(tot_length*tot_length);
+  
   if (areaMin < limit && nb > 2) {
     Msg::Warning("Geometrical aspect ratio too high (a_2D=%g)", areaMin);
     SBoundingBox3d bboxH = bounds();
@@ -1679,14 +1769,12 @@ bool GFaceCompound::checkAspectRatio() const
     double D = getSizeBB(_U0);
     double eta = H/D;
     int nbSplit =  -2;
-    paramOK = true; //false;
   }
   else {
     Msg::Debug("Geometrical aspect ratio is OK  :-)");
-    paramOK = true;
   }
   
-  return paramOK;
+  return AR;
 
 }
 
@@ -1694,6 +1782,7 @@ void GFaceCompound::coherenceNormals()
 {
 
   Msg::Info("Coherence Normals ");
+
   std::map<MEdge, std::set<MTriangle*>, Less_Edge > edge2tris;
   for(unsigned int i = 0; i < triangles.size(); i++){
     MTriangle *t = triangles[i];
diff --git a/Geo/GFaceCompound.h b/Geo/GFaceCompound.h
index 64809a8e3e4b57cd0afbc0367b29e8cfea7b6e50..34928905745a286b7deb120e09f2c5fc09daca20 100644
--- a/Geo/GFaceCompound.h
+++ b/Geo/GFaceCompound.h
@@ -19,6 +19,8 @@
 #include "meshGFaceOptimize.h"
 #include "linearSystem.h"
 
+#define AR_MAX 5 //maximal geometrical spacte ratio
+
 /*
 A GFaceCompound is a model face that is the compound of model faces.
 
@@ -51,7 +53,7 @@ class Octree;
 class GFaceCompound : public GFace {
  public:
   typedef enum {ITERU=0,ITERV=1,ITERD=2} iterationStep;
-  typedef enum {HARMONIC=1,CONFORMAL=2, CONVEXCOMBINATION=3} typeOfMapping;
+  typedef enum {HARMONIC=1,CONFORMAL=2, CONVEXCOMBINATION=3, MULTISCALE=4} typeOfMapping;
   typedef enum {UNITCIRCLE, SQUARE} typeOfIsomorphism;
   void computeNormals(std::map<MVertex*, SVector3> &normals) const;
  protected:
@@ -71,11 +73,12 @@ class GFaceCompound : public GFace {
   void buildOct() const ;
   void buildAllNodes() const; 
   void parametrize(iterationStep, typeOfMapping) const;
-  void parametrize_conformal() const;
+  bool parametrize_conformal() const;
   void compute_distance() const;
   bool checkOrientation(int iter) const;
+  bool checkFolding(std::vector<MVertex*> &ordered) const;
   void one2OneMap() const;
-  bool checkAspectRatio() const;
+  double checkAspectRatio() const;
   void computeNormals () const;
   void getBoundingEdges();
   void getUniqueEdges(std::set<GEdge*> & _unique); 
@@ -118,7 +121,7 @@ class GFaceCompound : public GFace {
   mutable int nbSplit;
  private:
   typeOfIsomorphism _type;
-  typeOfMapping _mapping;
+  mutable typeOfMapping _mapping;
 };
 
 #else
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index e232b67521ba29c7398c46a211c66ea89016ae8d..a88d38b14c75d9f056d8e0c51f03118bfec70605 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1336,8 +1336,6 @@ void partitionAndRemesh(GFaceCompound *gf)
   //-----------------------------------------------------
   
   std::list<GFace*> cFaces = gf->getCompounds();
-  //PartitionMeshFace(cFaces, options);
-
   std::vector<MElement *> elements;
   for (std::list<GFace*>::iterator it = cFaces.begin(); it != cFaces.end(); it++)
     for(unsigned int j = 0; j < (*it)->getNumMeshElements(); j++)
diff --git a/Mesh/meshPartition.cpp b/Mesh/meshPartition.cpp
index d3ca6b75784a5ba44d84a356b9db25ebefd899a8..07bf7b47880ee7c999b25fefd4500aa94b7f3aeb 100644
--- a/Mesh/meshPartition.cpp
+++ b/Mesh/meshPartition.cpp
@@ -1080,9 +1080,6 @@ void assignPartitionBoundary(GModel *model,
     ppv = new  partitionVertex(model, -(int)pvertices.size()-1,v2);
     pvertices.insert (ppv);
     model->add(ppv);
-    printf("*** created partitionVertex %d (", ppv->tag());
-    for (unsigned int i = 0; i < v2.size(); ++i) printf("%d ", v2[i]);
-    printf(")\n");
   }
   else ppv = *it;
   ppv->points.push_back(new MPoint (ve));
@@ -1276,11 +1273,13 @@ void createPartitionFaces(GModel *model, GFaceCompound *gf, int N,
   std::list<GFace*>::iterator it = _compound.begin();
 
   for( ; it != _compound.end(); ++it){
+    //printf("tag compound =%d \n", (*it)->tag());
     for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
       MTriangle *e = (*it)->triangles[i];
       int part = e->getPartition();
       for(int j = 0; j < 3; j++){
 	MVertex *v0 = e->getVertex(j);
+	//printf("v0=%d part=%d\n", v0->getNum(), part); //returns part 0 ???
 	allNodes[part-1].insert(v0);
       }
       discreteFaces[part-1]->triangles.push_back(new MTriangle(e->getVertex(0),e->getVertex(1),e->getVertex(2)));     
diff --git a/Mesh/multiscalePartition.cpp b/Mesh/multiscalePartition.cpp
index 2df582db91741baeaaab2f05cbaa465a2e4234f7..e437a565eec59c34cf8b59f82d01511549a9b8de 100644
--- a/Mesh/multiscalePartition.cpp
+++ b/Mesh/multiscalePartition.cpp
@@ -134,54 +134,93 @@ static int getGenus (std::vector<MElement *> &elements,
 static int getAspectRatio(std::vector<MElement *> &elements, 
                           std::vector<std::vector<MEdge> > &boundaries)
 { 
-  std::set<MVertex*> vs;
-  for(unsigned int i = 0; i < elements.size(); i++){
-    MElement *e = elements[i];
-    for(int j = 0; j < e->getNumVertices(); j++){
-      vs.insert(e->getVertex(j));
-    }
-  }
-  SBoundingBox3d bb;
-  SOrientedBoundingBox obbox ;
-  std::vector<SPoint3> vertices;
-  for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){
-    SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
-    vertices.push_back(pt);
-    bb += pt;
+
+  double area3D = 0.0;
+  for(unsigned int i = 0; i <elements.size(); ++i){
+    MElement *t = elements[i];
+    std::vector<MVertex *> v(3);
+    for(int k = 0; k < 3; k++) v[k] = t->getVertex(k);
+    double p0[3] = {v[0]->x(), v[0]->y(), v[0]->z()}; 
+    double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()};
+    double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()};
+    double a_3D = fabs(triangle_area(p0, p1, p2));
+    area3D += a_3D;
   }
   
-  //obbox =  SOrientedBoundingBox::buildOBB(vertices);
-  //double H = obbox.getMaxSize(); 
-  double H = norm(SVector3(bb.max(), bb.min()));
-  
-  double D = H;
-  if (boundaries.size() > 0.0 ) D = 0.0;
-  for (unsigned int i = 0; i < boundaries.size(); i++){
-    std::set<MVertex*> vb;
+  double tot_length = 0.0;
+  for(unsigned int i = 0; i <boundaries.size(); ++i){
     std::vector<MEdge> iBound = boundaries[i];
-    for (unsigned int j = 0; j < iBound.size(); j++){
-      MEdge e = iBound[j];
-      vb.insert(e.getVertex(0));
-      vb.insert(e.getVertex(1));
-    }
-    std::vector<SPoint3> vBounds;
-    for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){
-      SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
-      vBounds.push_back(pt);
+    double iLength = 0.0;
+    for( unsigned int j = 0; j <iBound.size(); ++j){
+      MVertex *v0 = iBound[j].getVertex(0);
+      MVertex *v1 = iBound[j].getVertex(1);    
+      const double length = 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()));
+      iLength += length;
     }
-    SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds);
-    D = std::max(D, obboxD.getMaxSize());
+    tot_length += iLength;
   }
-  int AR = (int)ceil(H/D);
+  int AR = 1.0;
+  if (boundaries.size() > 0 ){
+    tot_length /= boundaries.size();
+    AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length));
+  }
+
+//   std::set<MVertex*> vs;
+//   for(unsigned int i = 0; i < elements.size(); i++){
+//     MElement *e = elements[i];
+//     for(int j = 0; j < e->getNumVertices(); j++){
+//       vs.insert(e->getVertex(j));
+//     }
+//   }
+//   SBoundingBox3d bb;
+//   std::vector<SPoint3> vertices;
+//   for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){
+//     SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
+//     vertices.push_back(pt);
+//     bb += pt;
+//   }
+//   double H = norm(SVector3(bb.max(), bb.min()));
+
+//   //SOrientedBoundingBox obbox =  SOrientedBoundingBox::buildOBB(vertices);
+//   //double H = obbox.getMaxSize(); 
+  
+//   double D = H;
+//   if (boundaries.size()  > 0 ) D = 0.0;
+//   for (unsigned int i = 0; i < boundaries.size(); i++){
+//     std::set<MVertex*> vb;
+//     std::vector<MEdge> iBound = boundaries[i];
+//     for (unsigned int j = 0; j < iBound.size(); j++){
+//       MEdge e = iBound[j];
+//       vb.insert(e.getVertex(0));
+//       vb.insert(e.getVertex(1));
+//     }
+//     std::vector<SPoint3> vBounds;
+//     SBoundingBox3d bb;
+//     for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){
+//       SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
+//       vBounds.push_back(pt);
+//       bb +=pt;
+//     }
+//     double iD = norm(SVector3(bb.max(), bb.min()));
+//     D = std::max(D, iD);
+    
+//     //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds); 
+//     //D = std::max(D, obboxD.getMaxSize());
+//   }
+//   int AR = (int)ceil(H/D);
   
   return AR;
 }
 
-static void getGenusAndRatio(std::vector<MElement *> &elements, int & genus, int &AR)
+static void getGenusAndRatio(std::vector<MElement *> &elements, int & genus, int &AR, int &NB)
 {
   std::vector<std::vector<MEdge> > boundaries;
   genus = getGenus(elements, boundaries);  
+  NB = boundaries.size();
   AR = getAspectRatio(elements, boundaries);
+
 }
 
 static void partitionRegions(std::vector<MElement*> &elements, 
@@ -281,7 +320,8 @@ void multiscalePartition::partition(partitionLevel & level, int nbParts, typeOfP
 #if defined(HAVE_METIS) || defined(HAVE_CHACO)
 
   if (method == LAPLACIAN){
-    multiscaleLaplace multiLaplace(level.elements, level.recur);
+    std::map<MVertex*, SPoint3> coordinates;
+    multiscaleLaplace multiLaplace(level.elements, coordinates);
   }
   else if (method == MULTILEVEL){
     setNumberOfPartitions(nbParts);
@@ -300,8 +340,8 @@ void multiscalePartition::partition(partitionLevel & level, int nbParts, typeOfP
     nextLevel->region = i;
 
     levels.push_back(nextLevel);
-    int genus, AR;
-    getGenusAndRatio(regions[i], genus, AR);
+    int genus, AR, NB;
+    getGenusAndRatio(regions[i], genus, AR, NB);
 
     printLevel (nextLevel->elements, nextLevel->recur,nextLevel->region);  
 
@@ -316,15 +356,15 @@ void multiscalePartition::partition(partitionLevel & level, int nbParts, typeOfP
 		nextLevel->recur,nextLevel->region, genus, AR, nbParts);  
       partition(*nextLevel, nbParts, MULTILEVEL);
     }
-     else if (genus == 0  &&  AR > 3 ){
-       int nbParts = 2;
-       Msg::Info("Mesh partition: level (%d-%d)  is ZERO-GENUS (AR=%d) ---> LAPLACIAN partition %d parts",
- 		nextLevel->recur,nextLevel->region, AR, nbParts);  
-       partition(*nextLevel, nbParts, LAPLACIAN);
-     }
+    else if (genus == 0  &&  AR > 4 || genus == 0  &&  NB > 1){
+      int nbParts = 2;
+      Msg::Info("Mesh partition: level (%d-%d)  is ZERO-GENUS (AR=%d NB=%d) ---> LAPLACIAN partition %d parts",
+ 		nextLevel->recur,nextLevel->region, AR, NB, nbParts);  
+      partition(*nextLevel, nbParts, LAPLACIAN);
+    }
     else {
-      Msg::Info("*** Mesh partition: level (%d-%d) is ZERO-GENUS (AR=%d)", 
-		 nextLevel->recur,nextLevel->region, AR);
+      Msg::Info("*** Mesh partition: level (%d-%d) is ZERO-GENUS (AR=%d, NB=%d)", 
+		nextLevel->recur,nextLevel->region, AR, NB);
     }
     
   }
diff --git a/Solver/multiscaleLaplace.cpp b/Solver/multiscaleLaplace.cpp
index b3ba1f1f7fde39a78d6fc9de98850efd83a43c34..9a53da220f0b71f81397447229252c574b8353a3 100644
--- a/Solver/multiscaleLaplace.cpp
+++ b/Solver/multiscaleLaplace.cpp
@@ -22,6 +22,15 @@
 #include "MTriangle.h"
 #include "robustPredicates.h"
 
+//--------------------------------------------------------------
+
+struct sort_pred {
+    bool operator()(const std::pair<SPoint2,multiscaleLaplaceLevel*> &left, const std::pair<SPoint2,multiscaleLaplaceLevel*> &right) {
+      return left.first.x() < right.first.x();
+    }
+};
+
+
 //--------------------------------------------------------------
 static int intersection_segments_b (SPoint2 &p1, SPoint2 &p2,
 				    SPoint2 &q1, SPoint2 &q2, 
@@ -230,12 +239,10 @@ static void recur_compute_centers_ (double R, double a1, double a2,
     }
   }
 
-  //compute interior_loops
-  std::vector<std::vector<MEdge> > boundaries;
-  connected_bounds(root->elements, boundaries);
-
   //add the center of real holes ... 
   if (root->children.size()==0 ){//|| boundaries.size()-1 != root->children.size()){
+    std::vector<std::vector<MEdge> > boundaries;
+    connected_bounds(root->elements, boundaries);
     for (int i = 0; i < boundaries.size(); i++){
       std::vector<MEdge> me = boundaries[i];
       SPoint2 c(0.0,0.0);
@@ -251,14 +258,14 @@ static void recur_compute_centers_ (double R, double a1, double a2,
 	rad = std::max(rad,sqrt ((c.x() - p.x())*(c.x() - p.x())+
 				 (c.y() - p.y())*(c.y() - p.y())));
       }
-      if (std::abs(rad/root->radius) < 0.8 && abs(rad) < 0.99){
+      if (std::abs(rad/root->radius) < 0.9 && abs(rad) < 0.99){
 	centers.push_back(std::make_pair(c,zero));  
       }
     }
   }
 
   //sort centers
-  std::sort(centers.begin(),centers.end());
+  std::sort(centers.begin(),centers.end(), sort_pred());
 
   for (int i=1;i<centers.size()-1;i++){
     multiscaleLaplaceLevel* m1 = centers[i-1].second;
@@ -271,7 +278,6 @@ static void recur_compute_centers_ (double R, double a1, double a2,
     }
   }
 
-
 }
 //--------------------------------------------------------------
 static void recur_cut_edges_ (multiscaleLaplaceLevel * root,
@@ -492,18 +498,18 @@ static void recur_cut_ (double R, double a1, double a2,
       double x[2];
       nbIntersect += intersection_segments (centers[j].first,centers[j+1].first,pp,farLeft,x); 
     }
-    if (root->recur != 0){
-      if (nbIntersect %2 == 0)
-	left.push_back(root->elements[i]);
-      else
-	right.push_back(root->elements[i]);
-    }
-    else{
+//     if (root->recur != 0){
+//       if (nbIntersect %2 == 0)
+// 	left.push_back(root->elements[i]);
+//       else
+// 	right.push_back(root->elements[i]);
+//     }
+//     else{
       if (nbIntersect %2 != 0)
 	left.push_back(root->elements[i]);
       else
 	right.push_back(root->elements[i]);
-    }
+ //    }
   }
   
   for (int i=1;i<centers.size()-1;i++){
@@ -511,9 +517,6 @@ static void recur_cut_ (double R, double a1, double a2,
     multiscaleLaplaceLevel* m2 = centers[i].second;
     multiscaleLaplaceLevel* m3 = centers[i+1].second;
     if (m2){
-      /*center of the local system is always 0,0
-	its relative position to its parent is center
-	only 2 angles have to be computed for in and out*/
       a1 = myatan2 (centers[i-1].first.y() - m2->center.y() , centers[i-1].first.x() - m2->center.x() ); 
       a2 = myatan2 (centers[i+1].first.y() - m2->center.y() , centers[i+1].first.x() - m2->center.x() );
       recur_cut_ (m2->radius, a1, a2, m2, left, right);
@@ -525,6 +528,7 @@ static void recur_cut_ (double R, double a1, double a2,
 static void connected_left_right (std::vector<MElement *> &left, 
 				 std::vector<MElement *> &right ){
 
+
   //connected left
   std::vector<std::vector<MElement*> >  subRegionsL;
   connectedRegions (left,subRegionsL);
@@ -588,11 +592,9 @@ static void printLevel ( const char* fn,
 
   
   std::set<MVertex*> vs;
-  for (int i=0;i<elements.size();i++){
-    for (int j=0;j<elements[i]->getNumVertices();j++){
+  for (int i=0;i<elements.size();i++)
+    for (int j=0;j<elements[i]->getNumVertices();j++)
       vs.insert(elements[i]->getVertex(j));
-    }
-  }
 
   bool binary = false;
   FILE *fp = fopen (fn, "w");
@@ -734,7 +736,8 @@ static bool checkOrientation(std::vector<MElement *> &elements,
 }
 //--------------------------------------------------------------
 
-multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements, int iPart) 
+multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements, 
+				      std::map<MVertex*, SPoint3> &allCoordinates) 
 {
 
   //To go through this execute gmsh with the option -optimize_hom
@@ -767,13 +770,19 @@ multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements, int iPa
   //Recursively parametrize
   root->recur = 0;
   root->region = 0;
+  root->scale = 1.0;
   parametrize(*root);
 
+  //fill the coordinates
+  std::vector<double> iScale; 
+  std::vector<SPoint2> iCenter;
+  fillCoordinates(*root, allCoordinates, iScale, iCenter);
+
   //Compute centers for the cut
   recur_compute_centers_ (1.0, M_PI, 0.0, root);
 
   //Partition the mesh in left and right
-  cut (elements, iPart); 
+  cut (elements); 
 
   //---- Testing other cut for partitionning  ----
   //---- cutEdges and connected_regions       ----
@@ -827,6 +836,35 @@ multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements, int iPa
 //     else left.push_back(_all[i]);
 //   }
 
+}
+
+void multiscaleLaplace::fillCoordinates (multiscaleLaplaceLevel & level, 
+					 std::map<MVertex*, SPoint3> &allCoordinates, 
+					 std::vector<double> &iScale, 
+					 std::vector<SPoint2> &iCenter){
+
+  iScale.push_back(level.scale);
+  iCenter.push_back(level.center);
+
+  for(unsigned int i = 0; i < level.elements.size(); ++i){
+    MElement *e = level.elements[i];
+    for(unsigned int j = 0; j<e->getNumVertices(); ++j){
+      MVertex *v = e->getVertex(j);
+      SPoint2 coord  = level.coordinates[v];
+      for (int k= iScale.size()-1; k > 0; k--){
+	coord = coord*iScale[k] + iCenter[k];
+      }
+      allCoordinates[v] = SPoint3(coord.x(), coord.y(), 0.0);
+    }
+  }
+
+  
+  for (int i=0;i<level.children.size();i++){
+    multiscaleLaplaceLevel* m = level.children[i]; 
+    fillCoordinates(*m, allCoordinates, iScale, iCenter);
+ }
+
+  
 }
 
 void multiscaleLaplace::parametrize (multiscaleLaplaceLevel & level){
@@ -864,7 +902,7 @@ void multiscaleLaplace::parametrize (multiscaleLaplaceLevel & level){
     MElement *e = level.elements[i];
     std::vector<SPoint2> localCoord;
     double local_size = localSize(e,solution);
-    if (local_size < 1.e-6 * global_size) 
+    if (local_size < 1.e-5 * global_size) 
       tooSmall.push_back(e);
     else  goodSize.push_back(e);
   }
@@ -872,61 +910,62 @@ void multiscaleLaplace::parametrize (multiscaleLaplaceLevel & level){
   //Only keep the connected elements vectors goodSize and tooSmall
   std::vector<std::vector<MElement*> >  regGoodSize;
   connectedRegions (goodSize,regGoodSize);
-  int index=0;
   if (regGoodSize.size()  > 0){
+    int index=0;
     int maxSize= regGoodSize[0].size(); 
     for (int i=1;i< regGoodSize.size() ; i++){   
       int size = regGoodSize[i].size();
       if(size > maxSize){
-	maxSize = size;
 	index = i;
+	maxSize = size;
       }
     }
+    goodSize.clear();
+    for (int i=0;i< regGoodSize.size() ; i++){   
+      if (i == index)  goodSize.insert(goodSize.begin(), regGoodSize[i].begin(),  regGoodSize[i].end());
+      else  tooSmall.insert(tooSmall.begin(), regGoodSize[i].begin(),  regGoodSize[i].end());
+    }
   }
-  goodSize.clear();
-  for (int i=0;i< regGoodSize.size() ; i++){   
-    if (i == index)  goodSize.insert(goodSize.begin(), regGoodSize[i].begin(),  regGoodSize[i].end());
-    else  tooSmall.insert(tooSmall.begin(), regGoodSize[i].begin(),  regGoodSize[i].end());
-  }
-
+  level.elements.clear();
   level.elements = goodSize;
 
   //Add the not too small regions to the level.elements 
   std::vector<std::vector<MElement*> >  regions_, regions ;
+  regions.clear(); regions_.clear();
   connectedRegions (tooSmall,regions_);
   for (int i=0;i< regions_.size() ; i++){    
     bool really_small_elements = false;
     for (int k=0; k<regions_[i].size() ; k++){
       MElement *e = regions_[i][k];
       double local_size = localSize(e,solution);
-      if (local_size < 1.e-8 * global_size) 
+      if (local_size < 1.e-7 * global_size) 
 	really_small_elements = true;
     }
-    if(really_small_elements && regions_[i].size() > 10) regions.push_back(regions_[i]);
+    if(really_small_elements ) regions.push_back(regions_[i]);
     else
       level.elements.insert(level.elements.begin(), regions_[i].begin(), regions_[i].end() );
   }  
 
- //Fill level.coordinates
+  //Fill level.coordinates
   std::set<MVertex*> goodSizev;
   for(unsigned int i = 0; i < level.elements.size(); ++i){
     MElement *e = level.elements[i];
     for(unsigned int j = 0; j<e->getNumVertices(); ++j){
-      goodSizev.insert(e->getVertex(j));
-      level.coordinates[e->getVertex(j)] = solution[e->getVertex(j)];
+      MVertex *v = e->getVertex(j);
+      goodSizev.insert(v);
+      level.coordinates[v] = solution[v];
     }
   }
 
   //Save multiscale meshes
   char name[245];
-  sprintf(name,"multiscale_level%d_region%d_real.msh",level.recur, level.region);
+  sprintf(name,"multiscale_%d_%d_real.msh",level.recur, level.region);
   printLevel (name,level.elements,0,2.0);
-  sprintf(name,"multiscale_level%d_region%d_param.msh",level.recur, level.region);
+  sprintf(name,"multiscale_%d_%d_param.msh",level.recur, level.region);
   printLevel (name,level.elements,&level.coordinates,2.0);
 
-
   //For every small region compute a new parametrization
-  Msg::Info("Level (%d-%d): %d connected small regions",level.recur,level.region, regions.size());
+  Msg::Info("Level (%d-%d): %d connected small regions",level.recur, level.region, regions.size());
   for (int i=0;i< regions.size() ; i++){    
     std::set<MVertex*> tooSmallv;
     tooSmallv.clear();
@@ -940,7 +979,7 @@ void multiscaleLaplace::parametrize (multiscaleLaplaceLevel & level){
     multiscaleLaplaceLevel *nextLevel = new multiscaleLaplaceLevel;
     nextLevel->elements = regions[i];
     nextLevel->recur = level.recur+1;
-    nextLevel->region = i;//Emi add something here
+    nextLevel->region = i;
     SBoundingBox3d smallB;
     for(std::set<MVertex *>::iterator itv = tooSmallv.begin(); itv !=tooSmallv.end() ; ++itv){
       SPoint2 p = solution[*itv];
@@ -1020,21 +1059,23 @@ void multiscaleLaplace::parametrize_method (multiscaleLaplaceLevel & level,
 
   }
 }
-void multiscaleLaplace::cut (std::vector<MElement *> &elements, int iPart)
+void multiscaleLaplace::cut (std::vector<MElement *> &elements)
 {
 
   std::vector<MElement*> left,right;
   recur_cut_ (1.0, M_PI, 0.0, root,left,right);
- 
   connected_left_right(left, right);
 
+  if ( elements.size() != left.size()+right.size()) 
+    Msg::Error("Cutting laplace wrong nb elements (%d) != left + right (%d)",  elements.size(), left.size()+right.size());
+
   elements.clear();
   elements.insert(elements.end(),left.begin(),left.end());
   elements.insert(elements.end(),right.begin(),right.end());
 
-  //char name[256];
-  //sprintf(name, "laplace_%d.msh", iPart);
-  //printLevel (name,elements,0,2.0);  
+  printLevel ("multiscale-all.msh",elements, 0,2.0);  
+  printLevel ("multiscale-left.msh",left,0,2.0);  
+  printLevel ("multiscale-right.msh",right,0,2.0);  
 
 }
 
diff --git a/Solver/multiscaleLaplace.h b/Solver/multiscaleLaplace.h
index 8b456290e2cef5c5732d68f38c5d256e574092cf..0bb5c6eec2fa484c9c2d7799f21593c673193564 100644
--- a/Solver/multiscaleLaplace.h
+++ b/Solver/multiscaleLaplace.h
@@ -5,6 +5,7 @@
 #include <map>
 #include <set>
 #include "SPoint2.h"
+#include "SPoint3.h"
 #include "linearSystem.h"
 
 class MElement;
@@ -23,12 +24,17 @@ struct multiscaleLaplaceLevel {
 
 class multiscaleLaplace{
 public:
-  multiscaleLaplace (std::vector<MElement *> &elements, int iPart=0); 
-  void cut (std::vector<MElement *> &elements,int iPart=0);  
+  multiscaleLaplace (std::vector<MElement *> &elements, 
+		     std::map<MVertex*, SPoint3> &allCoordinates); 
+  void cut (std::vector<MElement *> &elements);  
   typedef enum {HARMONIC=1,CONFORMAL=2, CONVEXCOMBINATION=3} typeOfMapping;
 
   linearSystem<double> *_lsys;
   multiscaleLaplaceLevel* root;
+  void fillCoordinates (multiscaleLaplaceLevel & level,
+			std::map<MVertex*, SPoint3> &allCoordinates,
+			std::vector<double> &iScale, 
+			std::vector<SPoint2> &iCenter);
   void parametrize (multiscaleLaplaceLevel &); 
   void parametrize_method (multiscaleLaplaceLevel & level, 
 			   std::set<MVertex*> &allNodes,