diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 39873e7f8948fbf66ae067d6505c9deb27962ef3..657db5ce90ef3398c7e21561c533e79f63772f76 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -1129,10 +1129,6 @@ void GetOptions(int argc, char *argv[])
         else
           Msg::Fatal("Missing argument");
       }
-      else if(!strcmp(argv[i] + 1, "showCompounds")) {
-        CTX::instance()->geom.hideCompounds = 0;
-        i++;
-      }
 #endif
 #if defined(__APPLE__)
       else if(!strncmp(argv[i] + 1, "psn", 3)) {
diff --git a/Common/Context.cpp b/Common/Context.cpp
index 2fbfe7d5b762d5e770c5791b295402134278acb7..3b149fb555a1c02b5388f08b8893c8e356044de8 100644
--- a/Common/Context.cpp
+++ b/Common/Context.cpp
@@ -79,7 +79,6 @@ CTX::CTX() : gamepad(0)
 
   // need to initialize these too, since the corresponding opt_XXX routines use
   // the current value to detect changes
-  geom.hideCompounds = 1;
   mesh.changed = 0;
   mesh.qualityInf = mesh.qualitySup = mesh.qualityType = 0;
   mesh.radiusInf = mesh.radiusSup = 0;
diff --git a/Common/Context.h b/Common/Context.h
index b34a23fb508980450620d25193ba7b2ae15b0f7b..c5c361aebb8d519c56f0eac3fa43161c1c74135b 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -80,7 +80,7 @@ struct contextGeometryOptions {
   double occScaling;
   int copyMeshingMethod, exactExtrusion;
   int matchGeomAndMesh;
-  int hideCompounds, orientedPhysicals, doubleClickedEntityTag;
+  int orientedPhysicals, doubleClickedEntityTag;
   int reparamOnFaceRobust;
   std::string doubleClickedPointCommand, doubleClickedLineCommand;
   std::string doubleClickedSurfaceCommand, doubleClickedVolumeCommand;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index b46b59db529f3aa31221a8e84b5ae2ea5eda32e3..ffe67a003ff4b06ed14ef47627538b7fd9ae7b29 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -836,8 +836,6 @@ StringXNumber GeometryOptions_Number[] = {
   { F|O, "ExtrudeSplinePoints" , opt_geometry_extrude_spline_points, 5. ,
     "Number of control points for splines created during extrusion" },
 
-  { F|O, "HideCompounds" , opt_geometry_hide_compounds, 1. ,
-    "Hide entities that make up compound entities?" },
   { F|O, "HighlightOrphans" , opt_geometry_highlight_orphans, 0. ,
     "Highlight orphan entities (lines connected to a single surface, etc.)?" },
 
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 3d27cbcc645ea550eef605924efaf45dbedd6d93..1be10f3bc3dc6967047b213f261770738a877d8a 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -745,7 +745,6 @@ void OpenProject(const std::string &fileName)
     FlGui::instance()->updateViews(true, false);
     FlGui::instance()->updateFields();
     GModel::current()->setSelection(0);
-    GModel::current()->setCompoundVisibility();
   }
 #endif
 }
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 0dad09c0637618c86705c0bf2311bc22563bddb0..a99ba9bdec715dec004cb7d33e4e380f4f8bbfcb 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -4399,28 +4399,6 @@ double opt_geometry_auto_coherence(OPT_ARGS_NUM)
   return CTX::instance()->geom.autoCoherence;
 }
 
-double opt_geometry_hide_compounds(OPT_ARGS_NUM)
-{
-  if(action & GMSH_SET){
-    int old = CTX::instance()->geom.hideCompounds;
-    CTX::instance()->geom.hideCompounds = (int)val;
-    if(old != (int)val){
-      GModel::current()->setCompoundVisibility();
-      CTX::instance()->mesh.changed = ENT_ALL;
-#if defined(HAVE_FLTK)
-      if(FlGui::available()) FlGui::instance()->resetVisibility();
-#endif
-    }
-  }
-#if defined(HAVE_FLTK)
-  if(FlGui::available() && (action & GMSH_GUI)){
-    FlGui::instance()->options->geo.butt[17]->value
-      (CTX::instance()->geom.hideCompounds);
-  }
-#endif
-  return CTX::instance()->geom.hideCompounds;
-}
-
 double opt_geometry_oriented_physicals(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 95436360dd5dc95b2be5e4345f81d84e16db041a..5cb13d5a000c53e076a3003fc84248fa5721898a 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -360,7 +360,6 @@ double opt_geometry_offset0(OPT_ARGS_NUM);
 double opt_geometry_offset1(OPT_ARGS_NUM);
 double opt_geometry_offset2(OPT_ARGS_NUM);
 double opt_geometry_auto_coherence(OPT_ARGS_NUM);
-double opt_geometry_hide_compounds(OPT_ARGS_NUM);
 double opt_geometry_oriented_physicals(OPT_ARGS_NUM);
 double opt_geometry_highlight_orphans(OPT_ARGS_NUM);
 double opt_geometry_tolerance(OPT_ARGS_NUM);
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index e2358c070dbbf896caa71cdb692e4f854238cacb..7c0d6e920567ad62e2adab546f0cd5caad74419a 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -429,7 +429,6 @@ static void geometry_options_ok_cb(Fl_Widget *w, void *data)
   opt_geometry_occ_scaling(0, GMSH_SET, o->geo.value[20]->value());
 
   opt_geometry_light_two_side(0, GMSH_SET, o->geo.butt[14]->value());
-  opt_geometry_hide_compounds(0, GMSH_SET, o->geo.butt[17]->value());
 
   opt_geometry_normals(0, GMSH_SET, o->geo.value[0]->value());
   opt_geometry_tangents(0, GMSH_SET, o->geo.value[1]->value());
diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt
index 2dff8ae7b53c33b1854a6afcbc1985e42f738224..98236c6c98f498b50dcae10ae7097320f39f9f17 100644
--- a/Geo/CMakeLists.txt
+++ b/Geo/CMakeLists.txt
@@ -9,8 +9,8 @@ set(SRC
   intersectCurveSurface.cpp
   GEntity.cpp STensor3.cpp
     GVertex.cpp GEdge.cpp GFace.cpp GRegion.cpp
-    GEdgeLoop.cpp GEdgeCompound.cpp GFaceCompound.cpp
-  GRegionCompound.cpp GRbf.cpp
+    GEdgeLoop.cpp
+  GRbf.cpp
     gmshVertex.cpp gmshEdge.cpp gmshFace.cpp gmshRegion.cpp
    gmshSurface.cpp
    OCCVertex.cpp OCCEdge.cpp OCCFace.cpp OCCRegion.cpp
@@ -46,7 +46,6 @@ set(SRC
     MHexahedron.cpp MPrism.cpp MPyramid.cpp MTrihedron.cpp MElementCut.cpp MSubElement.cpp
   MZone.cpp MZoneBoundary.cpp
   Cell.cpp CellComplex.cpp ChainComplex.cpp Homology.cpp Chain.cpp
-  Curvature.cpp
   MVertexBoundaryLayerData.cpp
 )
 
diff --git a/Geo/Curvature.cpp b/Geo/Curvature.cpp
deleted file mode 100644
index 3607cf1416908824f3cb14af3243358791a55a6a..0000000000000000000000000000000000000000
--- a/Geo/Curvature.cpp
+++ /dev/null
@@ -1,1987 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-
-#include "Curvature.h"
-#include "MElement.h"
-#include "MTriangle.h"
-#include "GEntity.h"
-#include "GFaceCompound.h"
-#include "MLine.h"
-#include "GRbf.h"
-#include "OS.h"
-#include "SBoundingBox3d.h"
-#include "discreteEdge.h"
-
-#include<iostream>
-#include<fstream>
-#include<cmath>
-
-#define NEXT(i) ((i)<2 ? (i)+1 : (i)-2)
-#define PREV(i) ((i)>0 ? (i)-1 : (i)+2)
-//========================================================================================================
-
-//Initialization of the static variables:
-Curvature* Curvature::_instance = 0;
-bool Curvature::_destroyed = false;
-bool Curvature::_alreadyComputedCurvature = false;
-
-//========================================================================================================
-
-//CONSTRUCTOR
-Curvature::Curvature() : _isMapInitialized(false)
-{
-}
-
-// Curvature::Curvature(std::list<GFace*> &myFaces){
-
-//   std::list<GFace*>::const_iterator it = myFaces.begin();
-//   for( ; it != myFaces.end() ; ++it){
-//          _ptFinalEntityList.push_back(*it);
-//   }
-
-// }
-
-//========================================================================================================
-
-Curvature::~Curvature()
-{
-   _instance = 0;
-  _destroyed = true;
-
-}
-//========================================================================================================
-void Curvature::onDeadReference()
-{
-  std::cout << "Dead reference of Curvature detected" << std::endl;
-}
-//========================================================================================================
-
-Curvature& Curvature::getInstance()
-{
-  if (!_instance)  {
-    if(_destroyed){
-      onDeadReference();
-    }
-    else{
-      create();
-    }
-  }
-  return *_instance;
-}
-//========================================================================================================
-  bool Curvature::valueAlreadyComputed()
-  {
-    return _alreadyComputedCurvature;
-  }
-
-//========================================================================================================
-
- void Curvature::create()
- {
-   static Curvature instance;
-   _instance = & instance;
- }
-
- //========================================================================================================
- void Curvature::retrieveCompounds()  {
-#if defined(HAVE_SOLVER)
-
-   /// -------------------------------------------------------------------------------------------
-   // Loop over all faces. Check if the face is a compound. If it is, store all of its discrete
-   // faces in _EntityArray
-   
-   std::list<GFace*> global_face_list;
-
-   for(GModel::fiter face_iter = _model->firstFace(); face_iter != _model->lastFace(); ++face_iter)
-   {
-     if ( (*face_iter)->geomType() != GEntity::CompoundSurface ){
-       if (!(*face_iter)->getCompound()){
-	 global_face_list.push_back(*face_iter);	 
-       }       
-     }
-     else if ( (*face_iter)->geomType() == GEntity::CompoundSurface )
-     {
-       GFaceCompound* compound = dynamic_cast<GFaceCompound*>(*face_iter);
-       std::list<GFace*> tempcompounds = compound->getCompounds();
-       std::list<GFace*>::iterator surfIterator;
-
-       for(surfIterator = tempcompounds.begin(); surfIterator != tempcompounds.end(); ++surfIterator)
-       {
-         if ((*surfIterator)->geomType() == GEntity::DiscreteSurface)
-         {
-           global_face_list.push_back(*surfIterator);
-         }
-       }
-     }
-
-   } // Loop over faces of the model
-
-   global_face_list.sort();
-   global_face_list.unique();
-   _EntityArray.resize(global_face_list.size());
-   std::copy(global_face_list.begin(),global_face_list.end(),_EntityArray.begin());
-#endif
- }
-
- //========================================================================================================
-
- // Method to detect boundary edges of the mesh. We want to find which edges are on the boundary in order
- // to correct the curvature field close to boundaries
-
- void Curvature::correctOnEdges()
- {
-#if defined(HAVE_SOLVER)
-
-   if (! _alreadyComputedCurvature )
-   {
-     Msg::Error("Cannot correct the curvature values at the edges because the curvatures weren't computed yet");
-     return;
-   }
-   // Remark: this can only be used after the call to initializeMap() !
-
-  buildEdgeList();
-
-  std::list<MeshEdgeInfo>::iterator VertToEdgeListIter;
-
-   _isOnBoundary.resize(_VertexToInt.size());
-   for (unsigned int i = 0; i < _VertexToInt.size(); ++i)
-   {
-     _isOnBoundary[i] = 0;
-   }
-
-   // To detect the nodes on the egdes of a geometry, we create a list of all edges on the mesh. The
-   // edges which are shared by only one mesh element are boundary edges. Their nodes are tagged by 1
-   for (unsigned int i = 0; i < _VertexToInt.size(); ++i)
-   {
-     for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end();
-                                                                                    ++VertToEdgeListIter)
-     {
-       if ((*VertToEdgeListIter).NbElemNeighbour == 1)
-       {
-         _isOnBoundary[(*VertToEdgeListIter).StartV] = 1;
-         _isOnBoundary[(*VertToEdgeListIter).EndV] = 1;
-       }
-     }
-
-   }
-
-   // We want to find the nodes that are the immediate neighbours of the boundary nodes. Those nodes are
-   // considered nodes with 'level 2'. The neighbours of neighbours have 'level 3' etc.
-   // We want to construct levels 1,2,3. Nodes with level 0 are internal nodes of the mesh
-   //Loop over the vector of edgelist
-   for (int level = 1; level < 3; ++level)
-   {
-     for (unsigned int i = 0; i < _VertexToEdgeList.size(); ++i)
-     {
-       for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end();
-                                                                                ++VertToEdgeListIter)
-       {
-         if (_isOnBoundary[(*VertToEdgeListIter).StartV] == level && _isOnBoundary[(*VertToEdgeListIter).EndV] == 0)
-         {
-          _isOnBoundary[(*VertToEdgeListIter).EndV] = level+1;
-         }
-         if (_isOnBoundary[(*VertToEdgeListIter).EndV] == level && _isOnBoundary[(*VertToEdgeListIter).StartV] == 0)
-         {
-           _isOnBoundary[(*VertToEdgeListIter).StartV] = level+1;
-         }
-       }
-     }
-   }//Loop over the level of the ring
-
-
-   // Check test to see the tag of the nodes on the boundary:
-//   for (int i = 0; i< _EntityArray.size(); ++i)
-//   {
-//     GFace* face = _EntityArray[i]; //List of all the discrete face on which we compute the curvature
-
-//     for (int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-//     {
-//       MElement *e = face->getMeshElement(iElem);
-
-//       // The NEW tag of the corresponding element
-//       const int E = _ElementToInt[e->getNum()];
-
-//       // Pointers to vertices of triangle
-//       MVertex* A = e->getVertex(0);
-//       MVertex* B = e->getVertex(1);
-//       MVertex* C = e->getVertex(2);
-
-//       V[0] = _VertexToInt[A->getNum()];  //The new number of the vertex
-//       V[1] = _VertexToInt[B->getNum()];
-//       V[2] = _VertexToInt[C->getNum()];
-
-//       if (_isOnBoundary[V[0]] == 3)
-//       {
-//         std::cout << "Vertex: " << A->getNum() << " -- " << A->x() << "; " << A->y() << "; " << A->z() << std::endl;
-//       }
-//       if (_isOnBoundary[V[1]] == 3)
-//       {
-//         std::cout << "Vertex: " << B->getNum() << " -- " << B->x() << "; " << B->y() << "; " << B->z() << std::endl;
-//       }
-//       if (_isOnBoundary[V[2]] == 3)
-//       {
-//         std::cout << "Vertex: " << C->getNum() << " -- " << C->x() << "; " << C->y() << "; " << C->z() << std::endl;
-//       }
-//     }
-//   }
-
-
-   // Now we'll propagate the cuvature values from inside nodes with level = 3 close to the boundary - first
-   // to nodes with level 2, then from nodes with level 2 to nodes with level 1 (on the boundary)
-   _NbNeighbour.resize(_VertexToInt.size());
-   for(unsigned int i = 0; i < _NbNeighbour.size(); ++i)
-   {
-     _NbNeighbour[i] = 0;
-   }
-
-   for (int level = 2; level > 0 ; --level)
-   {
-
-     for (unsigned int i = 0; i< _NbNeighbour.size(); ++i)
-     {
-       _NbNeighbour[i] = 0;
-       if (_isOnBoundary[i] == level)
-       {
-        _VertexCurve[i] = 0.0;
-       }
-     }
-
-
-     for (unsigned int i = 0; i < _VertexToEdgeList.size(); ++i)
-     {
-       for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end();
-                                                                                ++VertToEdgeListIter)
-       {
-
-         if (_isOnBoundary[(*VertToEdgeListIter).StartV] == level && _isOnBoundary[(*VertToEdgeListIter).EndV] == level+1)
-         {
-            _VertexCurve[(*VertToEdgeListIter).StartV] += _VertexCurve[(*VertToEdgeListIter).EndV];
-            _NbNeighbour[(*VertToEdgeListIter).StartV] ++;
-
-         }
-         if (_isOnBoundary[(*VertToEdgeListIter).EndV] == level && _isOnBoundary[(*VertToEdgeListIter).StartV] == level+1)
-         {
-            _VertexCurve[(*VertToEdgeListIter).EndV] += _VertexCurve[(*VertToEdgeListIter).StartV];
-            _NbNeighbour[(*VertToEdgeListIter).EndV] ++;
-         }
-
-       }
-     }
-
-     // Correction for a degenerate case when a node has neighbours with the same or lower level, but zero
-     // neighbours with level+1
-
-     for (unsigned int i = 0; i < _VertexToEdgeList.size(); ++i)
-     {
-       for (VertToEdgeListIter = _VertexToEdgeList[i].begin(); VertToEdgeListIter != _VertexToEdgeList[i].end();
-                                                                                ++VertToEdgeListIter)
-       {
-
-         if (_isOnBoundary[(*VertToEdgeListIter).StartV] == level
-             && _isOnBoundary[(*VertToEdgeListIter).EndV] == level
-             && _NbNeighbour[(*VertToEdgeListIter).StartV] == 0)
-         {
-           _VertexCurve[(*VertToEdgeListIter).StartV] += _VertexCurve[(*VertToEdgeListIter).EndV];
-           _NbNeighbour[(*VertToEdgeListIter).StartV] = _NbNeighbour[(*VertToEdgeListIter).EndV];
-         }
-         if (_isOnBoundary[(*VertToEdgeListIter).EndV] == level
-             && _isOnBoundary[(*VertToEdgeListIter).StartV] == level
-             && _NbNeighbour[(*VertToEdgeListIter).EndV] == 0)
-         {
-           _VertexCurve[(*VertToEdgeListIter).EndV] += _VertexCurve[(*VertToEdgeListIter).StartV];
-           _NbNeighbour[(*VertToEdgeListIter).EndV] = _NbNeighbour[(*VertToEdgeListIter).StartV];
-         }
-       }
-     }
-
-     for (unsigned int i = 0; i < _isOnBoundary.size(); ++i)
-     {
-       if (_isOnBoundary[i] == level)
-       {
-         if (_NbNeighbour[i] == 0)
-         {
-           std::cout << "ERROR: VERTEX " << i << " WITH LEVEL " << level << " HAS 0 NEIGHBOURS" << std::endl;
-         }
-         _VertexCurve[i] = _VertexCurve[i]/_NbNeighbour[i];
-       }
-     }
-
-   }//Loop over the levels of the ring
-
-//   for (int i = 0; i < _isOnBoundary.size(); ++i)
-//   {
-//     _VertexCurve[i] = _isOnBoundary[i];
-//   }
-
-#endif
- }
-
-//========================================================================================================
-
-//INITIALIZATION OF THE MAP  AND  RENUMBERING OF THE SELECTED ENTITIES:
-
-void Curvature::initializeMap()
-{
-  if (! _isMapInitialized)
-  {
-    for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-    {
-      GFace* face = _EntityArray[i];
-
-      for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-      {
-        MElement *e = face->getMeshElement(iElem);
-        const int E = e->getNum();
-        _ElementToInt[E] = 1;
-
-        const int A = e->getVertex(0)->getNum();   //Pointer to 1st vertex of the triangle
-        const int B = e->getVertex(1)->getNum();
-        const int C = e->getVertex(2)->getNum();
-
-        _VertexToInt[A] = 1;
-        _VertexToInt[B] = 1;
-        _VertexToInt[C] = 1;
-      }
-    }
-
-    /// Set up a new numbering of chosen vertices and triangles
-    int idx = 0;
-
-    // map between the pointer to vertex and the new numbering of the vertex
-    std::map<int,int>::iterator vertex_iterator;
-    // map between the pointer to element and the new numbering of the element
-    std::map<int,int>::iterator element_iterator;
-
-    for (vertex_iterator = _VertexToInt.begin() ; vertex_iterator !=_VertexToInt.end() ; ++ vertex_iterator, ++idx)
-      (*vertex_iterator).second = idx;
-
-    idx = 0;
-
-    for (element_iterator = _ElementToInt.begin() ; element_iterator !=_ElementToInt.end() ; ++ element_iterator, ++idx)
-      (*element_iterator).second = idx;
-
-   _isMapInitialized = true;
-
-  }
-
-}
-
-//========================================================================================================
-
-//COMPUTE THE NORMAL AT THE VERTEX AND THE AREA AROUND
-
-void Curvature::computeVertexNormals()
-{
-  SVector3 vector_AB;
-  SVector3 vector_AC;
-
-  _TriangleArea.resize(_ElementToInt.size() );
-  _VertexArea.resize(_ElementToInt.size() );
-  _VertexNormal.resize(_VertexToInt.size());
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    // face is a pointer to one surface of the group "FinalEntityList"
-    GFace* face = _EntityArray[i];
-
-    //Loop over the element all the element of the "myTag"-surface
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-    {
-      // Pointer to one element
-      MElement *e = face->getMeshElement(iElem);
-      // The NEW tag of the corresponding element
-      const int E = _ElementToInt[e->getNum()];
-      // std::cout << "We are now looking at element Nr: " << E << std::endl;
-
-      // Pointers to vertices of triangle
-      MVertex* A = e->getVertex(0);
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      const int V0 = _VertexToInt[A->getNum()];  //The new number of the vertex
-      const int V1 = _VertexToInt[B->getNum()];
-      const int V2 = _VertexToInt[C->getNum()];
-
-      vector_AB = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z() );
-      vector_AC = SVector3(C->x() - A->x(), C->y() - A->y(), C->z() - A->z() );
-
-      const SVector3 cross = crossprod(vector_AB, vector_AC);
-
-      // Area of the triangles:
-      _TriangleArea[E] = 0.5*cross.norm();
-      // std::cout << "The area of the triangle nr: " << e->getNum() << " is: "<< TriangleArea[E] << std::endl;
-
-      _VertexArea[V0] += _TriangleArea[E];
-      _VertexArea[V1] += _TriangleArea[E];
-      _VertexArea[V2] += _TriangleArea[E];
-
-      _VertexNormal[V0] += cross;  //here we are actually computing the unit normal vector per vertex
-      _VertexNormal[V1] += cross;
-      _VertexNormal[V2] += cross;
-
-    } // end of loop over elements of one face
-
-  } //Loop over _ptFinalEntityList
-
-    ///////Normalize the vertex-normals.
-    for (unsigned int n = 0; n < _VertexToInt.size(); ++ n)
-    {
-      _VertexNormal[n].normalize();
-    }
-}
-
-//========================================================================================================
-
-SVector3 Curvature::vertexNormal (MVertex* A)
-{
-  const int V0 = _VertexToInt[A->getNum()];  //The new number of the vertex
-  return _VertexNormal[V0];
-}
-
-//========================================================================================================
-
-void Curvature::curvatureTensor()
-{
-
-  STensor3 TempTensor;
-  STensor3 TijABTensorProduct;
-  SVector3 TijAB;
-  SVector3 vector_AB;
-
-  _CurveTensor.resize(_VertexToInt.size());
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList"
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface
-    {
-      MElement *e = face->getMeshElement(iElem);  //Pointer to one element
-      const int E = _ElementToInt[e->getNum()]; //The NEW tag of the corresponding element
-
-      for (unsigned int i = 0; i<3; ++i)  // Loop over the 3 edges of each element
-      {
-
-        MVertex* A = e->getVertex(i);                   //Pointer to 1st vertex of the edge A-to-B
-        MVertex* B = e->getVertex((i+1)%3);             //Pointer to 2nd vertex of the edge A-to-B
-
-        const int V0 = _VertexToInt[A->getNum()];       //Tag of the 1st vertex of the edge A-to-B
-        const int V1 = _VertexToInt[B->getNum()];       //Tag of the 2nd vertex of the edge A-to-B
-
-        //Weight for triangle-i-th's contribution to the shape tensor:
-        const double Wij0 = _TriangleArea[E] / (2 * _VertexArea[V0]);
-        const double Wij1 = _TriangleArea[E] / (2 * _VertexArea[V1]);
-
-        //Approximate Curvature "kappa" along some tangential vector T:
-        vector_AB = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z() );
-        const double k_nominator0 =  dot(_VertexNormal[V0], vector_AB); //Dot-product of the 2 vectors
-        const double k_nominator1 = -dot(_VertexNormal[V1], vector_AB);
-
-        const double coeff   = 2.0/vector_AB.normSq(); //normSq is the norm to the power 2
-        const double KijAB_0 = coeff*k_nominator0;
-        const double KijAB_1 = coeff*k_nominator1;
-
-        //Projection of the edge vector AB on the tangential plane:
-        //** For Vertex 0
-        tensprod(_VertexNormal[V0], _VertexNormal[V0], TempTensor);
-        TempTensor      *= -1.0; //-N*Nt
-        TempTensor(0,0) +=  1.0; //I-N*Nt
-        TempTensor(1,1) +=  1.0;
-        TempTensor(2,2) +=  1.0;
-
-        for (int m = 0; m<3; ++m)
-        {
-          TijAB(m) = 0.0;
-          for (int n = 0; n<3; ++n)
-          {
-            TijAB(m) += TempTensor(m,n) * vector_AB(n);
-          }
-        }
-
-        TijAB.normalize();
-        tensprod(TijAB, TijAB, TijABTensorProduct);
-        _CurveTensor[V0] += Wij0*KijAB_0*TijABTensorProduct;
-
-        //** For Vertex 1
-        tensprod(_VertexNormal[V1], _VertexNormal[V1], TempTensor);
-        TempTensor      *= -1.0; //-N*Nt
-        TempTensor(0,0) +=  1.0; //I-N*Nt
-        TempTensor(1,1) +=  1.0;
-        TempTensor(2,2) +=  1.0;
-
-         for (int m = 0; m<3; ++m)
-        {
-          TijAB(m) = 0.0;
-          for (int n = 0; n<3; ++n)
-          {
-            TijAB(m) += TempTensor(m,n) * vector_AB(n);
-          }
-        }
-
-        TijAB.normalize();
-        tensprod(TijAB, TijAB, TijABTensorProduct);
-        _CurveTensor[V1] += Wij1*KijAB_1*TijABTensorProduct;
-
-      }//end of loop over the edges
-
-    }//end of loop over all elements of one GFace
-
-  }//End of loop over ptFinalEntityList
-
-}//End of method
-
-//========================================================================================================
-
-void Curvature::computeCurvature_Simple()
-{
-  SVector3 vector_E;
-  SVector3 vector_A;
-  SVector3 vector_B;
-  SVector3 vector_Wvi;
-  STensor3 Qvi;
-  STensor3 QviT;
-  STensor3 Holder;
-
-  initializeMap();
-  computeVertexNormals();
-  curvatureTensor();
-
-  _VertexCurve.resize(_VertexToInt.size());
-
-  for (unsigned int n = 0; n < _VertexToInt.size(); ++ n) //Loop over the vertex
-  {
-    vector_E = SVector3(1,0,0);
-    vector_A = vector_E + _VertexNormal[n];
-    vector_B = vector_E - _VertexNormal[n];
-
-    const double MagA = vector_A.norm();
-    const double MagB = vector_B.norm();
-
-    if (MagB > MagA)
-    {
-      vector_Wvi = vector_B;
-    }
-    else
-    {
-      vector_Wvi = vector_A;
-    }
-
-    vector_Wvi.normalize();
-    //to obtain the Qvi = Id -2*Wvi*Wvi^t
-    tensprod(vector_Wvi, vector_Wvi, Qvi); //Qvi = Wvi*Wvi^t
-    Qvi      *= -2.0;                      //-2*Wvi*Wvi^t
-    Qvi(0,0) +=  1.0;                      //I - 2*Wvi*Wvi^t  ==> Householder transformation
-    Qvi(1,1) +=  1.0;
-    Qvi(2,2) +=  1.0;
-
-    //Transpose the matrix:
-    for (int i = 0; i<3; ++i)
-    {
-      for (int j = 0; j<3; ++j)
-      {
-        QviT(i,j) = Qvi(j,i);
-       }
-     }
-
-     QviT *= _CurveTensor[n];
-     QviT *=Qvi;
-     Holder = QviT;
-
-     //Eigenvalues of the 2*2 minor from the Householder matrix
-     const double A = 1.0;
-     const double B = -(Holder(1,1) + Holder(2,2));
-     const double C = Holder(1,1)*Holder(2,2) - Holder(1,2)*Holder(2,1);
-     const double Delta = std::sqrt(B*B-4*A*C);
-
-     if((B*B-4.*A*C) < 0.0)
-     {
-       std::cout << "WARNING: negative discriminant: " << B*B-4.*A*C << std::endl;
-     }
-
-     const double m11 = (-B + Delta)/(2*A);  //Eigenvalue of Householder submatrix
-     const double m22 = (-B - Delta)/(2*A);
-
-     //_VertexCurve[n] = (3*m11-m22)*(3*m22-m11);  //Gaussian Curvature
-     _VertexCurve[n] = ((3*m11-m22) + (3*m22-m11))*0.5; //Mean Curvature
-
-  }
-}
-
-//========================================================================================================
-
-//COMPUTE THE NORMAL AT THE VERTEX AND THE AREA AROUND
-
-void Curvature::computeRusinkiewiczNormals()
-{
-  SVector3 vector_AB;
-  SVector3 vector_AC;
-  SVector3 vector_BC;
-
-  _TriangleArea.resize(_ElementToInt.size() );
-  _VertexNormal.resize(_VertexToInt.size());
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    // face is a pointer to one surface of the group "FinalEntityList"
-    GFace* face = _EntityArray[i];
-
-    //Loop over the element all the element of the "myTag"-surface
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-    {
-      // Pointer to one element
-      MElement *e = face->getMeshElement(iElem);
-      const int E = _ElementToInt[e->getNum()];
-
-      // Pointers to vertices of triangle
-      MVertex* A = e->getVertex(0);
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      const int V0 = _VertexToInt[A->getNum()];  //The new number of the vertex
-      const int V1 = _VertexToInt[B->getNum()];
-      const int V2 = _VertexToInt[C->getNum()];
-
-      vector_AB = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z() );
-      vector_AC = SVector3(C->x() - A->x(), C->y() - A->y(), C->z() - A->z() );
-      vector_BC = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z() );
-
-      const SVector3 cross = crossprod(vector_AB, vector_AC);
-
-      // Area of the triangles:
-      _TriangleArea[E] = 0.5*cross.norm();
-
-      const double l_AB = vector_AB.normSq();
-      const double l_AC = vector_AC.normSq();
-      const double l_BC = vector_BC.normSq();
-
-      _VertexNormal[V0] += cross * (1.0/ (l_AB*l_AC));
-      _VertexNormal[V1] += cross * (1.0/ (l_AB*l_BC));
-      _VertexNormal[V2] += cross * (1.0/ (l_AC*l_BC));
-
-    } // end of loop over elements of one face
-
-  } //Loop over _ptFinalEntityList
-
-    ///////Normalize the vertex-normals.
-    for (unsigned int n = 0; n < _VertexToInt.size(); ++ n)
-    {
-      _VertexNormal[n].normalize();
-    }
-}
-
-//========================================================================================================
-// Compute per-vertex point areas
-void Curvature::computePointareas(){
-
-  SVector3 e[3];
-  SVector3 l2;
-  SVector3 ew;
-  double factor[3];
-
-  _pointareas.resize(_VertexToInt.size());
-  _cornerareas.resize(_ElementToInt.size());
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList"
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface
-    {
-      MElement *E = face->getMeshElement(iElem);  //Pointer to one element
-      // The NEW tag of the corresponding element
-      const int EIdx = _ElementToInt[E->getNum()];
-
-      MVertex* A = E->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = E->getVertex(1);
-      MVertex* C = E->getVertex(2);
-
-      const int V0 = _VertexToInt[A->getNum()];
-      const int V1 = _VertexToInt[B->getNum()];
-      const int V2 = _VertexToInt[C->getNum()];
-
-      factor[0] = 1.0;
-      factor[1] = 1.0;
-      factor[2] = 1.0;
-      // if (_isOnBoundary[V0])
-      // {
-      //     factor[0] = 1.0;
-      // }
-      // else {factor[0] = 1.0;}
-      // if (_isOnBoundary[V1])
-      // {
-      //     factor[1] = 1.0;
-      // }
-      // else {factor[1] = 1.0;}
-      // if (_isOnBoundary[V2])
-      // {
-      //     factor[2] = 1.0;
-      // }
-      // else {factor[2] = 1.0;}
-      
-//Edges
-      e[0] = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z()); //vector side of a triangular element
-      e[1] = SVector3(A->x() - C->x(), A->y() - C->y(), A->z() - C->z());
-      e[2] = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z());
-
-      // Compute corner weights
-      //SVector3 len = crossprod(e[0], e[1]);
-      //len = norm
-      //len2 = normSq
-      double area = 0.5 * norm(crossprod(e[0], e[1])); //area of a triangle
-      l2 = SVector3( normSq(e[0]), normSq(e[1]), normSq(e[2]) );
-      ew = SVector3( l2[0] * (l2[1] + l2[2] - l2[0]),
-                     l2[1] * (l2[2] + l2[0] - l2[1]),
-                     l2[2] * (l2[0] + l2[1] - l2[2]) );
-
-      if (ew[0] <= 0.0)
-      {
-        _cornerareas[EIdx][1] = -0.25 * l2[2] * area / dot(e[0], e[2]);
-        _cornerareas[EIdx][2] = -0.25 * l2[1] * area / dot(e[0], e[1]);
-        _cornerareas[EIdx][0] = area - _cornerareas[EIdx][1] - _cornerareas[EIdx][2];
-      }
-      else if (ew[1] <= 0.0)
-      {
-        _cornerareas[EIdx][2] = -0.25 * l2[0] * area / dot(e[1], e[0]);
-        _cornerareas[EIdx][0] = -0.25 * l2[2] * area / dot(e[1], e[2]);
-        _cornerareas[EIdx][1] = area - _cornerareas[EIdx][2] - _cornerareas[EIdx][0];
-      }
-      else if (ew[2] <= 0.0)
-      {
-        _cornerareas[EIdx][0] = -0.25 * l2[1] * area / dot(e[2], e[1]);
-        _cornerareas[EIdx][1] = -0.25 * l2[0] * area / dot(e[2], e[0]);
-        _cornerareas[EIdx][2] = area - _cornerareas[EIdx][0] - _cornerareas[EIdx][1];
-      }
-      else
-      {
-        float ewscale = 0.5 * area / (ew[0] + ew[1] + ew[2]);
-        for (int j = 0; j < 3; j++)
-          _cornerareas[EIdx][j] = ewscale * (ew[(j+1)%3] + ew[(j+2)%3]);
-      }
-
-      _pointareas[V0] += _cornerareas[EIdx][0];
-
-      _pointareas[V1] += _cornerareas[EIdx][1];
-
-      _pointareas[V2] += _cornerareas[EIdx][2];
-
-      for (int j = 0; j < 3; j++)
-      {
-          _cornerareas[EIdx][j] = factor[j]*_cornerareas[EIdx][j];
-      }
-
-
-    } //End of loop over iElem
-
-//      std::cout << "_pointareas.size = " << _pointareas.size() << std::endl;
-//      std::cout << "_cornerareas.size = " << _cornerareas.size() << std::endl;
-
-  } //End of loop over _ptFinalEntityList
-
-} //End of the method "computePointareas"
-
-
-//========================================================================================================
-//Rotate a coordinate system to be perpendicular to the given normal
-void Curvature::rot_coord_sys(const SVector3 &old_u, const SVector3 &old_v, const SVector3 &new_norm, SVector3 &new_u, SVector3 &new_v){
-
-  new_u = old_u;
-  new_v = old_v;
-  SVector3 old_norm = crossprod(old_u, old_v);
-  double ndot = dot(old_norm, new_norm);
-//  if (unlikely(ndot <= -1.0f))
-  if (ndot <= -1.0f)
-  {
-    new_u = -1.0*new_u;
-    new_v = -1.0*new_v;
-    return;
-  }
-
-  SVector3 perp_old = new_norm - ndot*old_norm;
-  SVector3 dperp = 1.0f/(1 + ndot) * (old_norm + new_norm);
-  new_u -= dperp*dot(new_u, perp_old);
-  new_v -= dperp*dot(new_v, perp_old);
-}
-
-//========================================================================================================
-
-//Project a curvature tensor from the basis spanned by old_u and old_v
-//(which are assumed to be unit-length and perpendicular) to the new_u
-//and new_v basis
-
-void Curvature::proj_curv( const SVector3 &old_u, const SVector3 &old_v,
-                          double old_ku, double old_kuv, double old_kv,
-                          const SVector3  &new_u, const SVector3 &new_v,
-                          double &new_ku, double &new_kuv, double &new_kv){
-  SVector3 r_new_u;
-  SVector3 r_new_v;
-  rot_coord_sys(new_u, new_v, crossprod(old_u,old_v), r_new_u, r_new_v);
-
-  const double u1 = dot(r_new_u, old_u);
-  const double v1 = dot(r_new_u, old_v);
-  const double u2 = dot(r_new_v, old_u);
-  const double v2 = dot(r_new_v, old_v);
-
-  new_ku  =   old_ku*u1*u1 + old_kuv*(2.0f * u1*v1)   + old_kv*v1*v1;
-  new_kuv  =  old_ku*u1*u2 + old_kuv*(u1*v2 * u2*v1)  + old_kv*v1*v2;
-  new_kv  =   old_ku*u2*u2 + old_kuv*(2.0f * u2*v2)   + old_kv*v2*v2;
-}
-
-
-//========================================================================================================
-
-//Given a curvature tensor, find principal directions and curvatures
-//Makes sure that pdir1 and pdir2 are perpendicular to normal
-
-void Curvature::diagonalize_curv(const SVector3 &old_u, const SVector3 &old_v,
-                      double ku, double kuv, double kv,
-                      const SVector3 &new_norm,
-                      SVector3 &pdir1, SVector3 &pdir2, double &k1, double &k2){
-  SVector3 r_old_u;
-  SVector3 r_old_v;
-
-  double c = 1.0;
-  double s = 0.0;
-  double tt = 0.0;
-
-  rot_coord_sys(old_u, old_v, new_norm, r_old_u, r_old_v);
-
-//  if(unlikely(kuv !=0.0f))
-  if(kuv !=0.0)  {
-    //Jacobi rotation to diagonalize
-    double h= 0.5*(kv -ku)/ kuv;
-    tt = (h<0.0) ?
-          1.0 / (h - std::sqrt(1.0 + h*h)):
-          1.0 / (h + std::sqrt(1.0 + h*h));
-    c = 1.0 / std::sqrt(1.0 + tt*tt);
-    s = tt*c;
-  }
-
-  k1 = ku - tt *kuv;
-  k2 = kv + tt *kuv;
-
-  if(std::abs(k1) >= std::abs(k2))  {
-    pdir1 = c*r_old_u - s*r_old_v;
-  }
-  else  {
-    std::swap(k1,k2);
-    pdir1 = s*r_old_u + c*r_old_v;
-  }
-  pdir2 = crossprod(new_norm, pdir1);
-}
-
-//========================================================================================================
-void Curvature::computeCurvature(GModel* model, typeOfCurvature typ)
-{
-
-  _model = model;
-
-  double t0 = Cpu();
-  Msg::StatusBar(true, "(C) Computing Curvature");
-  if (typ == RUSIN)
-    computeCurvature_Rusinkiewicz(0);
-  else if (typ == RBF)
-    computeCurvature_RBF();
-  else if (typ == SIMPLE)
-    computeCurvature_Simple();
-
-  double t1 = Cpu();
-  Msg::StatusBar(true, "(C) Done Computing Curvature (%g s)", t1-t0);
-
-  //writeToMshFile("curvature.msh");
-  //writeToPosFile("curvature.pos");
-  //writeToVtkFile("curvature.vtk");
-
-}
-
-//========================================================================================================
-
-void Curvature::buildEdgeList()
-{
-
-  int V[3];
-  bool edgefound;
-
-  _VertexToEdgeList.clear();
-
-  std::list<MeshEdgeInfo>::iterator VertToEdgeListIter;
-  MeshEdgeInfo TempEdge;
-
-  _VertexToEdgeList.resize(_VertexToInt.size());
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i]; //List of all the discrete face on which we compute the curvature
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-    {
-      MElement *e = face->getMeshElement(iElem);
-
-      // Pointers to vertices of triangle
-      MVertex* A = e->getVertex(0);
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      V[0] = _VertexToInt[A->getNum()];  //The new number of the vertex
-      V[1] = _VertexToInt[B->getNum()];
-      V[2] = _VertexToInt[C->getNum()];
-
-      // Try to add edge [V0,V1] to the global list
-      for (int j = 0; j < 3; ++j)
-      {
-          const int StartV = std::min(V[j], V[(j+1)%3]);
-          const int EndV = std::max(V[j], V[(j+1)%3]);
-
-          edgefound = false;
-          for (VertToEdgeListIter = _VertexToEdgeList[StartV].begin(); VertToEdgeListIter != _VertexToEdgeList[StartV].end();
-                                                                                   ++VertToEdgeListIter)
-          {
-            if(StartV == (*VertToEdgeListIter).StartV && EndV == (*VertToEdgeListIter).EndV)
-            {
-              (*VertToEdgeListIter).NbElemNeighbour ++;
-              edgefound = true;
-            }
-
-          }
-          if (false == edgefound)
-          {
-            TempEdge.StartV = StartV;
-            TempEdge.EndV = EndV;
-            TempEdge.NbElemNeighbour = 1;
-            _VertexToEdgeList[StartV].push_back(TempEdge);
-          }
-
-
-      } // Loop over j
-
-
-    } // Loop over the elements (triangles) of the face
-  }
-
-  int NbEdges = 0;
-  for(unsigned int i = 0; i < _VertexToEdgeList.size(); ++i)
-  {
-    NbEdges += _VertexToEdgeList[i].size();
-  }
-
-  //std::cout << "Euler formula:" << std::endl;
-  //std::cout << "Edges + 2 =        " << NbEdges + 2 << std::endl;
-  //std::cout << "Elements + Nodes = " << _VertexToInt.size() + _ElementToInt.size() << std::endl;
-
-}
-
-//========================================================================================================
-
-
-void Curvature::smoothCurvatureField(const int NbIter)
-{
-  if ( _VertexToEdgeList.size() == 0 ) { buildEdgeList(); }
-
-  std::vector<double> smoothedCurvature;
-  smoothedCurvature.resize( _VertexToInt.size() );
-
-
-  // Smoothed curvature directions
-  std::vector<SVector3> smoothedDir1;
-  std::vector<SVector3> smoothedDir2;
-  smoothedDir1.resize(_VertexToInt.size());
-  smoothedDir2.resize(_VertexToInt.size());
-
-  _NbNeighbour.resize(_VertexToInt.size());
-  for(unsigned int i = 0; i < _VertexToInt.size(); ++i)
-  {
-    _NbNeighbour[i] = 0;
-  }
-
-
-  // Smoothing iterations
-  for(int iter = 0; iter < NbIter; ++iter)
-  {
-
-    for(unsigned int i = 0; i < smoothedCurvature.size(); ++i)
-    {
-      smoothedCurvature[i] = 0.0;
-      smoothedDir1[i] = SVector3();
-      smoothedDir2[i] = SVector3();
-    }
-
-    std::list<MeshEdgeInfo>::const_iterator edgeIterator;
-
-
-    for(unsigned int i = 0; i < _VertexToEdgeList.size(); ++i)
-    {
-      for(edgeIterator = _VertexToEdgeList[i].begin(); edgeIterator != _VertexToEdgeList[i].end(); ++edgeIterator)
-      {
-
-        const int V0 = (*edgeIterator).StartV;
-        const int V1 = (*edgeIterator).EndV;
-
-        smoothedCurvature[V0] += _VertexCurve[V1];
-        smoothedCurvature[V1] += _VertexCurve[V0];
-
-        smoothedDir1[V0] += _pdir1[V1];
-        smoothedDir1[V1] += _pdir1[V0];
-
-        smoothedDir2[V0] += _pdir2[V1];
-        smoothedDir2[V1] += _pdir2[V0];
-
-        _NbNeighbour[V0]++;
-        _NbNeighbour[V1]++;
-      }
-    }
-
-
-
-    const double Lambda = 0.3;
-    for(unsigned int i = 0; i < _VertexCurve.size(); ++i)
-    {
-      _VertexCurve[i] = Lambda*_VertexCurve[i] + (1-Lambda)*smoothedCurvature[i] / _NbNeighbour[i];
-      _pdir1[i] = Lambda * _pdir1[i] + (1.-Lambda)/_NbNeighbour[i] * smoothedDir1[i];
-      _pdir2[i] = Lambda * _pdir2[i] + (1.-Lambda)/_NbNeighbour[i] * smoothedDir2[i];
-    }
-  }
-
-}
-
-
-//========================================================================================================
-
-
-
-void Curvature::computeCurvature_Rusinkiewicz(int isMax)
-{
-  
-  retrieveCompounds();
-  initializeMap();
-
-  computeRusinkiewiczNormals();
-  computePointareas();
-
-  SVector3 e[3];
-  STensor3 w;
-  SVector3 t;
-  SVector3 n;
-  SVector3 b;
-  SVector3 m;
-  SVector3 dn;
-
-  double u;
-  double v;
-  double dnu;
-  double dnv;
-  double c1;
-  double c2;
-  double c12;
-  double wt;
-
-  _pdir1.resize(_VertexToInt.size());
-  _pdir2.resize(_VertexToInt.size());
-
-  _curv1.resize(_VertexToInt.size());
-  _curv2.resize(_VertexToInt.size());
-  _curv12.resize(_VertexToInt.size());
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList"
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface
-    {
-      MElement *E = face->getMeshElement(iElem);  //Pointer to one element
-
-      MVertex* A = E->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = E->getVertex(1);
-      MVertex* C = E->getVertex(2);
-
-      const int V0 = _VertexToInt[A->getNum()];  //Tag of the 1st vertex of the triangle
-      const int V1 = _VertexToInt[B->getNum()];
-      const int V2 = _VertexToInt[C->getNum()];
-
-      ///Set up an initial coordinate system per vertex:
-      _pdir1[V0] = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z());
-      _pdir1[V1] = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z());
-      _pdir1[V2] = SVector3(A->x() - C->x(), A->y() - C->y(), A->z() - C->z());
-    }
-  }
-
-  for (unsigned int ivertex = 0; ivertex < _VertexToInt.size(); ++ivertex)
-  {
-    _pdir1[ivertex] = crossprod(_pdir1[ivertex], _VertexNormal[ivertex]);
-    _pdir1[ivertex].normalize();
-    _pdir2[ivertex] = crossprod(_VertexNormal[ivertex], _pdir1[ivertex]);
-  }
-
-  // Compute curvature per face:
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    //face is a pointer to one surface of the group "FinalEntityList"
-    GFace* face = _EntityArray[i];
-
-    //Loop over all elements of this face:
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-    {
-      MElement *E = face->getMeshElement(iElem);  //Pointer to one element
-      // The NEW tag of the corresponding element
-      const int EIdx = _ElementToInt[E->getNum()];
-
-      MVertex* A = E->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = E->getVertex(1);
-      MVertex* C = E->getVertex(2);
-
-      e[0] = SVector3(C->x() - B->x(), C->y() - B->y(), C->z() - B->z());
-      e[1] = SVector3(A->x() - C->x(), A->y() - C->y(), A->z() - C->z());
-      e[2] = SVector3(B->x() - A->x(), B->y() - A->y(), B->z() - A->z());
-
-      //N-T-B coordinate system per face
-      t = e[0];
-      t.normalize();
-      n = crossprod( e[0], e[1]);
-      b = crossprod(n, t);
-      b.normalize();
-
-      //Estimate curvature based on variations of normals along edges:
-      //intialization:
-      m = SVector3(0.0, 0.0, 0.0);
-       for (int i = 0; i< 3; ++i)
-	 for (int j = 0; j< 3; ++j)
-	   w(i,j) = 0.0;
-
-      //filling:
-      for (int j = 0; j< 3; ++j)
-      {
-        u = dot(e[j], t);
-        v = dot(e[j], b);
-
-        w(0,0) += u*u;
-        w(0,1) += u*v;
-        w(2,2) += v*v;
-
-        MVertex* U = E->getVertex(PREV(j));
-        MVertex* V = E->getVertex(NEXT(j));
-
-        const int UIdx = _VertexToInt[U->getNum()];
-        const int VIdx = _VertexToInt[V->getNum()];
-
-        dn = _VertexNormal[UIdx] - _VertexNormal[VIdx];
-
-        dnu = dot(dn, t);
-        dnv = dot(dn, b);
-
-        m[0] += dnu*u;
-        m[1] += dnu*v + dnv*u;
-        m[2] += dnv*v;
-      }
-
-      w(1,1) = w(0,0) + w(2,2);
-      w(1,2) = w(0,1);
-
-      //Least Squares Solution
-      double diag[3];
-      if (!ldltdc(w, diag))
-      {
-        std::cout << "ldltdc failed" << std::endl;
-        continue;
-      }
-      ldltsl(w, diag, m, m);
-
-      //Push it back out to the vertices
-      for (int j = 0; j< 3; ++j)
-      {
-        const int old_vj = E->getVertex(j)->getNum();
-        const int vj = _VertexToInt[old_vj];
-        proj_curv(t, b, m[0], m[1], m[2], _pdir1[vj], _pdir2[vj], c1, c12, c2);
-        wt = _cornerareas[EIdx][j]/_pointareas[vj];
-
-        _curv1[vj]  += wt*c1;
-        _curv12[vj] += wt*c12;
-        _curv2[vj]  += wt*c2;
-      }
-
-    } //End of loop over the element (iElem)
-
-  } //End of loop over "_EntityArray"
-
-
-  //Compute principal directions and curvatures at each vertex
-  for (unsigned int ivertex = 0; ivertex < _VertexToInt.size(); ++ivertex)  {
-    diagonalize_curv(_pdir1[ivertex], _pdir2[ivertex], _curv1[ivertex], _curv12[ivertex], _curv2[ivertex],
-                     _VertexNormal[ivertex], _pdir1[ivertex], _pdir2[ivertex], _curv1[ivertex], _curv2[ivertex]);
-  }
-
-
-  _VertexCurve.resize( _VertexToInt.size() );
-
-  for (unsigned int ivertex = 0; ivertex < _VertexToInt.size(); ++ivertex){
-
-    if (isMax){
-      _VertexCurve[ivertex] = std::max(fabs(_curv1[ivertex]), fabs(_curv2[ivertex]));
-    }
-    else{
-    //_VertexCurve[ivertex] = (_curv1[ivertex]+_curv2[ivertex])*0.5; //Mean curvature
-    //_VertexCurve[ivertex] = _curv1[ivertex]*_curv2[ivertex]; //Gaussian
-    _VertexCurve[ivertex] = _curv1[ivertex]; //Maximal Curvature
-    }
-
-  }
-
-//   smoothCurvatureField(1);
-  _alreadyComputedCurvature = true;
-
-// Propagate the value of curvature from nodes close the edges of the geometry onto the edges
-  correctOnEdges();
-  //  throw;
-
-} //End of the "computeCurvature_Rusinkiewicz" method
-
- //========================================================================================================
-
-void Curvature::computeCurvature_RBF()
-{
-  retrieveCompounds();
-  initializeMap();
-
-  //fill set of MVertex
-  std::set<MVertex*> allNodes;
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)  {
-    GFaceCompound* face = (GFaceCompound*)_EntityArray[i];
-    for (unsigned iElem = 0; iElem < face->getNumMeshElements(); iElem++) {
-      MElement *e = face->getMeshElement(iElem);
-      for(int j = 0; j < e->getNumVertices(); j++){
-        allNodes.insert(e->getVertex(j));
-      }
-    }
-  }
-
-  //bounding box
-  SBoundingBox3d bb;
-  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;
-  }
-  double sizeBox = norm(SVector3(bb.max(), bb.min()));
-
-  //compure curvature RBF
-  std::map<MVertex*, SVector3> _normals;
-  std::vector<MVertex*> _ordered;
-  std::map<MVertex*, double> curvRBF;
-  //GLOBAL
-  //GRbf *_rbf = new GRbf(sizeBox, 0, 1, _normals, allNodes, _ordered);
-  //_rbf->computeCurvature(_rbf->getXYZ(),curvRBF);
-  //LOCAL FD
-  GRbf *_rbf = new GRbf(sizeBox, 0, 1, _normals, allNodes, _ordered, true);
-  _rbf->computeLocalCurvature(_rbf->getXYZ(),curvRBF);
-
-  //fill vertex curve
-  _VertexCurve.resize( _VertexToInt.size() );
-  for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    std::map<int,int>::iterator vertexIterator;
-    int V0 = 0;
-    vertexIterator = _VertexToInt.find( v->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-    _VertexCurve[V0] = curvRBF[v];
-   }
-
- _alreadyComputedCurvature = true;
-
-} //End of the "computeCurvature_RBF" method
-
-
- //========================================================================================================
-
-void Curvature::triangleNodalValues(MTriangle* triangle, double& c0, double& c1, double& c2, int isAbs)
-  {
-    MVertex* A = triangle->getVertex(0);
-    MVertex* B = triangle->getVertex(1);
-    MVertex* C = triangle->getVertex(2);
-
-    int V0 = 0;
-    int V1 = 0;
-    int V2 = 0;
-
-    std::map<int,int>::iterator vertexIterator;
-    vertexIterator = _VertexToInt.find( A->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-    else
-      std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl;
-
-    vertexIterator = _VertexToInt.find( B->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )   V1 = (*vertexIterator).second;
-    else
-      std::cout << "Didn't find vertex with number " << B->getNum() << " in _VertextToInt !" << std::endl;
-
-    vertexIterator = _VertexToInt.find( C->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )  V2 = (*vertexIterator).second;
-    else
-      std::cout << "Didn't find vertex with number " << C->getNum() << " in _VertextToInt !" << std::endl;
-
-    if (isAbs){
-      c0 = std::abs(_VertexCurve[V0]); //Mean curvature in vertex 0
-      c1 = std::abs(_VertexCurve[V1]); //Mean curvature in vertex 1
-      c2 = std::abs(_VertexCurve[V2]); //Mean curvature in vertex 2
-    }
-    else{
-      c0 = _VertexCurve[V0]; //Mean curvature in vertex 0
-      c1 = _VertexCurve[V1]; //Mean curvature in vertex 1
-      c2 = _VertexCurve[V2]; //Mean curvature in vertex 2
-    }
-
-  }
-
-//========================================================================================================
-
-void Curvature::triangleNodalValuesAndDirections(MTriangle* triangle, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs)
-{
-  MVertex* A = triangle->getVertex(0);
-  MVertex* B = triangle->getVertex(1);
-  MVertex* C = triangle->getVertex(2);
-
-  int V0 = 0;
-  int V1 = 0;
-  int V2 = 0;
-
-  std::map<int,int>::iterator vertexIterator;
-  vertexIterator = _VertexToInt.find( A->getNum() );
-  if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-  else
-    std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl;
-
-  vertexIterator = _VertexToInt.find( B->getNum() );
-  if ( vertexIterator != _VertexToInt.end() )  V1 = (*vertexIterator).second;
-  else
-    std::cout << "Didn't find vertex with number " << B->getNum() << " in _VertextToInt !" << std::endl;
-
-  vertexIterator = _VertexToInt.find( C->getNum() );
-  if ( vertexIterator != _VertexToInt.end() )  V2 = (*vertexIterator).second;
-  else
-    std::cout << "Didn't find vertex with number " << C->getNum() << " in _VertextToInt !" << std::endl;
-
-  if (isAbs){
-    dMax[0] = _pdir1[V0];
-    dMax[1] = _pdir1[V1];
-    dMax[2] = _pdir1[V2];
-
-    dMin[0] = _pdir2[V0];
-    dMin[1] = _pdir2[V1];
-    dMin[2] = _pdir2[V2];
-
-    cMax[0]  = std::abs(_curv1[V0]);
-    cMax[1]  = std::abs(_curv1[V1]);
-    cMax[2]  = std::abs(_curv1[V2]);
-
-    cMin[0]  = std::abs(_curv2[V0]);
-    cMin[1]  = std::abs(_curv2[V1]);
-    cMin[2]  = std::abs(_curv2[V2]);
-
-  }
-  else{
-
-    dMax[0] = _pdir1[V0];
-    dMax[1] = _pdir1[V1];
-    dMax[2] = _pdir1[V2];
-
-    dMin[0] = _pdir2[V0];
-    dMin[1] = _pdir2[V1];
-    dMin[2] = _pdir2[V2];
-
-    cMax[0]  = _curv1[V0];
-    cMax[1]  = _curv1[V1];
-    cMax[2]  = _curv1[V2];
-
-    cMin[0]  = _curv2[V0];
-    cMin[1]  = _curv2[V1];
-    cMin[2]  = _curv2[V2];
-  }
-}
-
-  //========================================================================================================
-
-void Curvature::edgeNodalValues(MLine* edge, double& c0, double& c1, int isAbs)
-   {
-     MVertex* A = edge->getVertex(0);
-     MVertex* B = edge->getVertex(1);
-
-     int V0 = 0;
-     int V1 = 0;
-
-     std::map<int,int>::iterator vertexIterator;
-
-     vertexIterator = _VertexToInt.find( A->getNum() );
-     if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-     else  std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl;
-
-     vertexIterator = _VertexToInt.find( B->getNum() );
-     if ( vertexIterator != _VertexToInt.end() ) V1 = (*vertexIterator).second;
-     else std::cout << "Didn't find vertex with number " << B->getNum() << " in _VertextToInt !" << std::endl;
-
-     if (isAbs){
-       c0 = std::abs(_VertexCurve[V0]); //Mean curvature in vertex 0
-       c1 = std::abs(_VertexCurve[V1]); //Mean curvature in vertex 1
-     }
-     else{
-       c0 = _VertexCurve[V0]; //Mean curvature in vertex 0
-       c1 = _VertexCurve[V1]; //Mean curvature in vertex 1
-     }
-
-   }
-
-//========================================================================================================
-
-void Curvature::edgeNodalValuesAndDirections(MLine* edge, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs)
-{
-    std::vector<MVertex*> LineVertices;
-    //LineVertices.resize(2);
-    edge->getEdgeVertices(0,LineVertices);//triangle->getVertex(0);
-
-    int V0 = 0;
-    int V1 = 0;
-
-    std::map<int,int>::iterator vertexIterator;
-    vertexIterator = _VertexToInt.find( LineVertices[0]->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-    else
-      std::cout << "Didn't find vertex with number " << LineVertices[0]->getNum() << " in _VertextToInt !" << std::endl;
-
-    vertexIterator = _VertexToInt.find( LineVertices[1]->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )  V1 = (*vertexIterator).second;
-    else
-      std::cout << "Didn't find vertex with number " << LineVertices[1]->getNum() << " in _VertextToInt !" << std::endl;
-
-
-    if (isAbs){
-      dMax[0] = _pdir1[V0];
-      dMax[1] = _pdir1[V1];
-
-      dMin[0] = _pdir2[V0];
-      dMin[1] = _pdir2[V1];
-
-      cMax[0]  = std::abs(_curv1[V0]);
-      cMax[1]  = std::abs(_curv1[V1]);
-
-      cMin[0]  = std::abs(_curv2[V0]);
-      cMin[1]  = std::abs(_curv2[V1]);
-
-    }
-    else{
-
-      dMax[0] = _pdir1[V0];
-      dMax[1] = _pdir1[V1];
-
-      dMin[0] = _pdir2[V0];
-      dMin[1] = _pdir2[V1];
-
-      cMax[0]  = _curv1[V0];
-      cMax[1]  = _curv1[V1];
-
-      cMin[0]  = _curv2[V0];
-      cMin[1]  = _curv2[V1];
-    }
-}
-  //========================================================================================================
-
-void Curvature::vertexNodalValues(MVertex* A, double& c0, int isAbs)
-   {
-     int V0 = 0;
-
-     std::map<int,int>::iterator vertexIterator;
-
-     vertexIterator = _VertexToInt.find( A->getNum() );
-     if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-     else  std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl;
-
-
-     if (isAbs){
-       c0 = std::abs(_VertexCurve[V0]); //Mean curvature in vertex 0
-      }
-     else{
-       c0 = _VertexCurve[V0]; //Mean curvature in vertex 0
-      }
-
-   }
-
-void Curvature::vertexNodalValuesAndDirections(MVertex *A, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs)
-{
-
-    int V0 = 0;
-
-    std::map<int,int>::iterator vertexIterator;
-    vertexIterator = _VertexToInt.find( A->getNum() );
-    if ( vertexIterator != _VertexToInt.end() )  V0 = (*vertexIterator).second;
-    else
-      std::cout << "Didn't find vertex with number " << A->getNum() << " in _VertextToInt !" << std::endl;
-
-    if (isAbs){
-      dMax[0] = _pdir1[V0];
-      dMin[0] = _pdir2[V0];
-      cMax[0]  = std::abs(_curv1[V0]);
-      cMin[0]  = std::abs(_curv2[V0]);
-    }
-    else{
-      dMax[0] = _pdir1[V0];
-      dMin[0] = _pdir2[V0];
-      cMax[0]  = _curv1[V0];
-      cMin[0]  = _curv2[V0];
-    }
-}
-
-
-//========================================================================================================
-
-double Curvature::getAtVertex(const MVertex *v) const {
-  std::map<int,int>::const_iterator it = _VertexToInt.find(v->getNum());
-  if (it == _VertexToInt.end()) {
-    Msg::Error("curvature has not been computed for vertex %i (%i)", v->getNum(), _VertexToInt.size());
-    return 1;
-  }
-  return _VertexCurve[it->second];
-}
-
-//========================================================================================================
-
-void Curvature::writeToMshFile(const std::string &filename)
-{
-  std::ofstream outfile;
-  outfile.precision(18);
-  outfile.open(filename.c_str());
-
-  /// Write the values of curvature 1 (max)
-  outfile << "$MeshFormat"    << std::endl;
-  outfile << "2.1 0 8"        << std::endl;
-  outfile << "$EndMeshFormat" << std::endl;
-  outfile << "$NodeData" << std::endl;
-  outfile << "1" << std::endl;                 // One string tag
-  outfile << "\"Curvature 1 (max)\"" << std::endl;     // The name of the view
-  outfile << "1"             << std::endl;     // One real tag
-  outfile << "0.0"           << std::endl;     // The time value
-  outfile << "3"             << std::endl;     // Three integer tags
-  outfile << "0"             << std::endl;     // The time step (time steps always start at 0)
-  outfile << "1"             << std::endl;     // 1-component (scalar) field
-  outfile << _VertexToInt.size() << std::endl; // How many associated nodal values
-
-  std::map<int,int>::const_iterator vertex_iterator;
-  for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator)
-  {
-    outfile << vertex_iterator->first << " " << _curv1[vertex_iterator->second] << std::endl;
-  }
-
-  outfile << "$EndNodeData" << std::endl;
-
-
-  /// Write the values of curvature 2 (min)
-  outfile << "$MeshFormat"    << std::endl;
-  outfile << "2.1 0 8"        << std::endl;
-  outfile << "$EndMeshFormat" << std::endl;
-  outfile << "$NodeData" << std::endl;
-  outfile << "1" << std::endl;                 // One string tag
-  outfile << "\"Curvature 2 (min)\"" << std::endl;     // The name of the view
-  outfile << "1"             << std::endl;     // One real tag
-  outfile << "0.0"           << std::endl;     // The time value
-  outfile << "3"             << std::endl;     // Three integer tags
-  outfile << "0"             << std::endl;     // The time step (time steps always start at 0)
-  outfile << "1"             << std::endl;     // 1-component (scalar) field
-  outfile << _VertexToInt.size() << std::endl; // How many associated nodal values
-
-
-  for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator)
-  {
-    outfile << vertex_iterator->first << " " << _curv2[vertex_iterator->second] << std::endl;
-  }
-
-  outfile << "$EndNodeData" << std::endl;
-
-
-  /// Write the values of characteristic length
-
-  double lc;
-
-  outfile << "$MeshFormat"    << std::endl;
-  outfile << "2.1 0 8"        << std::endl;
-  outfile << "$EndMeshFormat" << std::endl;
-  outfile << "$NodeData" << std::endl;
-  outfile << "1" << std::endl;                 // One string tag
-  outfile << "\"Characteristic mesh length\"" << std::endl;     // The name of the view
-  outfile << "1"             << std::endl;     // One real tag
-  outfile << "0.0"           << std::endl;     // The time value
-  outfile << "3"             << std::endl;     // Three integer tags
-  outfile << "0"             << std::endl;     // The time step (time steps always start at 0)
-  outfile << "1"             << std::endl;     // 1-component (scalar) field
-  outfile << _VertexToInt.size() << std::endl; // How many associated nodal values
-
-  for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator)
-  {
-    lc = 2.0*M_PI/( fabs(_VertexCurve[vertex_iterator->second]) * CTX::instance()->mesh.minCircPoints );
-    lc = std::max(lc, CTX::instance()->mesh.lcMin);
-    lc = std::min(lc, CTX::instance()->mesh.lcMax);
-    //outfile << vertex_iterator->first << " " << 1.0/(lc*lc) << std::endl;
-    outfile << vertex_iterator->first << " " << lc << std::endl;
-  }
-
-  outfile << "$EndNodeData" << std::endl;
-
-  /// Write the values of curvature direction - principal direction 1
-  outfile << "$NodeData" << std::endl;
-  outfile << "1" << std::endl;                 // One string tag
-  outfile << "\"Principal curvature direction 1\"" << std::endl;     // The name of the view
-  outfile << "1"             << std::endl;     // One real tag
-  outfile << "0.0"           << std::endl;     // The time value
-  outfile << "3"             << std::endl;     // Three integer tags
-  outfile << "0"             << std::endl;     // The time step (time steps always start at 0)
-  outfile << "3"             << std::endl;     // 3-component (vector) field
-  outfile << _VertexToInt.size() << std::endl; // How many associated nodal values
-
-  for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator)
-  {
-    outfile << vertex_iterator->first << " " << _pdir1[vertex_iterator->second].x() << " "
-                                             << _pdir1[vertex_iterator->second].y() << " "
-                                             << _pdir1[vertex_iterator->second].z() << std::endl;
-  }
-
-  outfile << "$EndNodeData" << std::endl;
-
-
-  /// Write the values of curvature direction - principal direction 2
-  outfile << "$NodeData" << std::endl;
-  outfile << "1" << std::endl;                 // One string tag
-  outfile << "\"Principal curvature direction 2\"" << std::endl;     // The name of the view
-  outfile << "1"             << std::endl;     // One real tag
-  outfile << "0.0"           << std::endl;     // The time value
-  outfile << "3"             << std::endl;     // Three integer tags
-  outfile << "0"             << std::endl;     // The time step (time steps always start at 0)
-  outfile << "3"             << std::endl;     // 3-component (vector) field
-  outfile << _VertexToInt.size() << std::endl; // How many associated nodal values
-
-  for(vertex_iterator = _VertexToInt.begin(); vertex_iterator != _VertexToInt.end(); ++vertex_iterator)
-  {
-    outfile << vertex_iterator->first << " " << _pdir2[vertex_iterator->second].x() << " "
-                                             << _pdir2[vertex_iterator->second].y() << " "
-                                             << _pdir2[vertex_iterator->second].z() << std::endl;
-  }
-
-  outfile << "$EndNodeData" << std::endl;
-
-  outfile.close();
-
-
-}
-
-//========================================================================================================
-
-void Curvature::writeToPosFile( const std::string & filename)
-{
-  std::ofstream outfile;
-  outfile.precision(18);
-  outfile.open(filename.c_str());
-  outfile << "View \"Curvature \"{" << std::endl;
-
-  int idxelem = 0;
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i) {
-    GFace* face = _EntityArray[i];
-
-    for (unsigned iElem = 0; iElem < face->getNumMeshElements(); iElem++){
-      MElement *e = face->getMeshElement(iElem);
-      //const int E = _ElementToInt[e->getNum()];
-      //std::cout << "We are now looking at element Nr: " << E << std::endl;
-
-      MVertex* A = e->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      const int V1 = _VertexToInt[A->getNum()];                //Tag of the 1st vertex of the triangle
-      const int V2 = _VertexToInt[B->getNum()];                //Tag of the 2nd vertex of the triangle
-      const int V3 = _VertexToInt[C->getNum()];                //Tag of the 3rd vertex of the triangle
-
-      //Here is printing the triplet X-Y-Z of each vertex:
-      //*************************************************
-
-      outfile << "ST("; //VT = vector triangles   //ST = scalar triangle
-      outfile << A->x() << ","<< A->y() << "," << A->z()<< ",";
-      outfile << B->x() << ","<< B->y() << "," << B->z()<< ",";
-      outfile << C->x() << ","<< C->y() << "," << C->z();
-
-      outfile << ")";
-      outfile <<"{";
-
-      //Here is printing the 3 components of the normal vector for each vertex:
-      //**********************************************************************
-
-//      outfile << _VertexNormal[V1].x() << ","<< _VertexNormal[V1].y() << ","<< _VertexNormal[V1].z() << ",";
-//      outfile << _VertexNormal[V2].x() << ","<< _VertexNormal[V2].y() << ","<< _VertexNormal[V2].z() << ",";
-//      outfile << _VertexNormal[V3].x() << ","<< _VertexNormal[V3].y() << ","<< _VertexNormal[V3].z();
-
-      outfile << _VertexCurve[V1] << "," << _VertexCurve[V2] << "," << _VertexCurve[V3];
-
-      outfile << "};" << std::endl;
-
-      idxelem++;
-
-  } //Loop over elements
-
-} // Loop over ptFinalEntityList
-
-outfile << "};" << std::endl;
-
-outfile.close();
-}
-
-//========================================================================================================
-
-void Curvature::writeToVtkFile( const std::string & filename)
-{
-
-  std::ofstream outfile;
-  outfile.precision(18);
-  outfile.open(filename.c_str());
-  outfile << "# vtk DataFile Version 2.0" << std::endl;
-  outfile << "Surface curvature computed by Gmsh" << std::endl;
-  outfile << "ASCII" << std::endl;
-  outfile << "DATASET UNSTRUCTURED_GRID" << std::endl;
-
-  const int npoints = _VertexToInt.size();
-
-  outfile << "POINTS " << npoints << " double" << std::endl;
-
-  /// Build a table of coordinates
-  /// Loop over all elements and look at the 'old' (not necessarily continuous) numbers of vertices
-  /// Get the 'new' index of each vertex through _VertexToInt and the [x,y,z] coordinates of this vertex
-  /// Store them in coordx,coordy and coordz
-
-
-  std::vector<VtkPoint> coord;
-
-  coord.resize(npoints);
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i];
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-    {
-      MElement *e = face->getMeshElement(iElem);
-
-      MVertex* A = e->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      const int oldIdxA = A->getNum();
-      const int oldIdxB = B->getNum();
-      const int oldIdxC = C->getNum();
-
-      const int newIdxA = _VertexToInt[oldIdxA];
-      const int newIdxB = _VertexToInt[oldIdxB];
-      const int newIdxC = _VertexToInt[oldIdxC];
-
-      coord[newIdxA].x = A->x();
-      coord[newIdxA].y = A->y();
-      coord[newIdxA].z = A->z();
-
-      coord[newIdxB].x = B->x();
-      coord[newIdxB].y = B->y();
-      coord[newIdxB].z = B->z();
-
-      coord[newIdxC].x = C->x();
-      coord[newIdxC].y = C->y();
-      coord[newIdxC].z = C->z();
-    }
-  }
-
-  for (int v = 0; v < npoints; ++v)
-  {
-    outfile << coord[v].x << " " << coord[v].y << " " << coord[v].z << std::endl;
-  }
-
-  /// Empty the array 'coord' to free the memory
-  /// Point coordinates will not be needed anymore
-  coord.clear();
-
-  /// Write the cell connectivity
-
-  outfile << std::endl << "CELLS " << _ElementToInt.size() << " " << 4*_ElementToInt.size() << std::endl;
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i];
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++)
-    {
-      MElement *e = face->getMeshElement(iElem);
-
-      MVertex* A = e->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      const int oldIdxA = A->getNum();
-      const int oldIdxB = B->getNum();
-      const int oldIdxC = C->getNum();
-
-      const int newIdxA = _VertexToInt[oldIdxA];
-      const int newIdxB = _VertexToInt[oldIdxB];
-      const int newIdxC = _VertexToInt[oldIdxC];
-
-      outfile << "3 " << newIdxA << " " << newIdxB << " " << newIdxC << std::endl;
-    }
-  }
-
-  outfile << std::endl << "CELL_TYPES " << _ElementToInt.size() << std::endl;
-  for(unsigned int ie = 0; ie < _ElementToInt.size(); ++ie)
-  {
-    outfile << "5" << std::endl; //Triangle is element type 5 in vtk
-
-  }
-
-  /// Write the curvature values as vtk 'point data'
-
-  outfile << std::endl << "POINT_DATA " << npoints << std::endl;
-  outfile << "SCALARS Curvature float 1" << std::endl;
-  outfile << "LOOKUP_TABLE default" << std::endl;
-
-  for (int iv = 0; iv < npoints; ++iv)
-  {
-    outfile << _VertexCurve[iv] << std::endl;
-  }
-
-  outfile << "SCALARS CharacteristicMeshLength float 1" << std::endl;
-  outfile << "LOOKUP_TABLE default" << std::endl;
-
-  double lc;
-
-  for (int iv = 0; iv < npoints; ++iv)
-  {
-    lc = 2.0*M_PI / ( fabs(_VertexCurve[iv]) * CTX::instance()->mesh.minCircPoints );
-    lc = std::max(lc, CTX::instance()->mesh.lcMin);
-    lc = std::min(lc, CTX::instance()->mesh.lcMax);
-    //outfile << 1.0/(lc*lc) << std::endl;
-    outfile << lc << std::endl;
-  }
-
-  outfile << "VECTORS CurvatureDir1 float" << std::endl;
-  for (int iv = 0; iv < npoints; ++iv)
-  {
-    outfile << _pdir1[iv].x() << " " << _pdir1[iv].y() << " " << _pdir1[iv].z() << std::endl;
-  }
-
-  outfile << "VECTORS CurvatureDir2 float" << std::endl;
-  for (int iv = 0; iv < npoints; ++iv)
-  {
-    outfile << _pdir2[iv].x() << " " << _pdir2[iv].y() << " " << _pdir2[iv].z() << std::endl;
-  }
-
-  outfile.close();
-
-}
-
-//========================================================================================================
-
-void Curvature::writeDirectionsToPosFile( const std::string & filename)
-{
-  std::ofstream outfile;
-  outfile.precision(18);
-  outfile.open(filename.c_str());
-  outfile << "View \"Curvature_DirMax \"{" << std::endl;
-
-  for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-  {
-    GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList"
-
-    for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface
-    {
-      MElement *e = face->getMeshElement(iElem);  //Pointer to one element
-
-      //const int E = _ElementToInt[e->getNum()]; //The NEW tag of the corresponding element
-      //std::cout << "We are now looking at element Nr: " << E << std::endl;
-
-      MVertex* A = e->getVertex(0);  //Pointers to vertices of triangle
-      MVertex* B = e->getVertex(1);
-      MVertex* C = e->getVertex(2);
-
-      const int V1 = _VertexToInt[A->getNum()];                //Tag of the 1st vertex of the triangle
-      const int V2 = _VertexToInt[B->getNum()];                //Tag of the 2nd vertex of the triangle
-      const int V3 = _VertexToInt[C->getNum()];                //Tag of the 3rd vertex of the triangle
-
-      //Here is printing the triplet X-Y-Z of each vertex:
-      //*************************************************
-
-      outfile << "VT("; //VT = vector triangles   //ST = scalar triangle
-      outfile << A->x() << ","<< A->y() << "," << A->z()<< ",";
-      outfile << B->x() << ","<< B->y() << "," << B->z()<< ",";
-      outfile << C->x() << ","<< C->y() << "," << C->z();
-
-      outfile << ")";
-      outfile <<"{";
-
-      //Here is printing the 3 components of the curvature max direction for each vertex:
-      //*********************************************************************************
-
-         outfile << _pdir1[V1].x() << ","<< _pdir1[V1].y() << ","<< _pdir1[V1].z() << ",";
-         outfile << _pdir1[V2].x() << ","<< _pdir1[V2].y() << ","<< _pdir1[V2].z() << ",";
-         outfile << _pdir1[V3].x() << ","<< _pdir1[V3].y() << ","<< _pdir1[V3].z();
-
-
-      outfile << "};" << std::endl;
-
-  } //Loop over elements
-
-} // Loop over ptFinalEntityList
-
-outfile << "};" << std::endl;
-
-
-//----------------------------------------------------------------------------------------------
-
-outfile << "View \"Curvature_DirMin \"{" << std::endl;
-
-for (unsigned int i = 0; i< _EntityArray.size(); ++i)
-{
-  GFace* face = _EntityArray[i]; //face is a pointer to one surface of the group "FinalEntityList"
-
-  for (unsigned int iElem = 0; iElem < face->getNumMeshElements(); iElem++) //Loop over the element all the element of the "myTag"-surface
-  {
-    MElement *e = face->getMeshElement(iElem);  //Pointer to one element
-
-    //const int E = _ElementToInt[e->getNum()]; //The NEW tag of the corresponding element
-    //std::cout << "We are now looking at element Nr: " << E << std::endl;
-
-    MVertex* A = e->getVertex(0);  //Pointers to vertices of triangle
-    MVertex* B = e->getVertex(1);
-    MVertex* C = e->getVertex(2);
-
-    const int V1 = _VertexToInt[A->getNum()];                //Tag of the 1st vertex of the triangle
-    const int V2 = _VertexToInt[B->getNum()];                //Tag of the 2nd vertex of the triangle
-    const int V3 = _VertexToInt[C->getNum()];                //Tag of the 3rd vertex of the triangle
-
-    //Here is printing the triplet X-Y-Z of each vertex:
-    //*************************************************
-
-    outfile << "VT("; //VT = vector triangles   //ST = scalar triangle
-    outfile << A->x() << ","<< A->y() << "," << A->z()<< ",";
-    outfile << B->x() << ","<< B->y() << "," << B->z()<< ",";
-    outfile << C->x() << ","<< C->y() << "," << C->z();
-
-    outfile << ")";
-    outfile <<"{";
-
-    //Here is printing the 3 components of the curvature min direction for each vertex:
-    //*********************************************************************************
-
-       outfile << _pdir2[V1].x() << ","<< _pdir2[V1].y() << ","<< _pdir2[V1].z() << ",";
-       outfile << _pdir2[V2].x() << ","<< _pdir2[V2].y() << ","<< _pdir2[V2].z() << ",";
-       outfile << _pdir2[V3].x() << ","<< _pdir2[V3].y() << ","<< _pdir2[V3].z();
-
-
-    outfile << "};" << std::endl;
-
-} //Loop over elements
-
-} // Loop over ptFinalEntityList
-
-outfile << "};" << std::endl;
-
-outfile.close();
-}
-//========================================================================================================
-
-
-
diff --git a/Geo/Curvature.h b/Geo/Curvature.h
deleted file mode 100644
index 133a9090f9d93ce828f37db68a1564783d350b65..0000000000000000000000000000000000000000
--- a/Geo/Curvature.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-
-#ifndef _CURVATURE_H_
-#define _CURVATURE_H_
-
-#include "GModel.h"
-#include "STensor3.h"
-
-#include<map>
-#include<vector>
-#include<list>
-
-class Curvature {
-
-private:
-    //----------------------------------------
-    //TYPEDEFS:
-
-    typedef std::vector<GFace*> GFaceList;
-    //typedef std::map<int, GEntityList >::iterator GEntityIter;
-    typedef std::map<int, GFaceList >::iterator GFaceIter;
-
-    //-----------------------------------------
-    // HELPER TYPE FOR WRITING TO VTK FILES
-    struct VtkPoint
-    {
-      double x;
-      double y;
-      double z;
-    };
-
-    //-----------------------------------------
-    // HELPER TYPE FOR DETECTING BOUNDARY NODES
-    struct MeshEdgeInfo
-    {
-      int StartV;
-      int EndV;
-      int NbElemNeighbour;
-    };
-
-    //-----------------------------------------
-    // MEMBER VARIABLES
-
-    //Static member variable to implement the class curvature as a Singleton
-    static Curvature *_instance;
-    static bool _destroyed;
-
-    //Boolean to check if the curvature has already been computed
-    static bool _alreadyComputedCurvature;
-
-    //Map definition
-    std::map<int, int> _VertexToInt;
-    std::map<int, int> _ElementToInt;
-
-    bool _isMapInitialized;
-
-    //Model and list of selected entities with give physical tag:
-    GModel* _model;
-    GFaceList _EntityArray;
-
-    //Averaged vertex normals
-    std::vector<SVector3> _VertexNormal;
-
-    // Vector of principal directions
-    std::vector<SVector3> _pdir1;
-    std::vector<SVector3> _pdir2;
-
-    // Vector of principal curvature
-    std::vector<double> _curv1;
-    std::vector<double> _curv2;
-    std::vector<double> _curv12;
-
-    // Area around point
-    std::vector<double> _pointareas;
-    std::vector<SVector3> _cornerareas;
-
-    //Curvature Tensor per mesh vertex
-    std::vector<STensor3> _CurveTensor;
-
-    //Area of a triangle element:
-    std::vector<double> _TriangleArea;
-
-    //Area around a mesh vertex:
-    std::vector<double> _VertexArea;
-    std::vector<double> _VertexCurve;
-
-
-    //Number of neighbour for each vertices in the mesh:
-    std::vector<int> _NbNeighbour;
-
-    //Vector of 0/1 to check which nodes are on the boundary:
-    std::vector<int> _isOnBoundary;
-
-    std::vector<std::list<MeshEdgeInfo> > _VertexToEdgeList;
-    //-----------------------------------------
-    // PRIVATE METHODS
-
-    //Constructor and destructor
-    Curvature();
-    ~Curvature();
-
-    static void create();
-    static void onDeadReference();
-
-    void initializeMap();
-    void computeVertexNormals();
-    void curvatureTensor();
-    static void rot_coord_sys(const SVector3 &old_u, const SVector3 &old_v,
-                              const SVector3 &new_norm, SVector3 &new_u, SVector3 &new_v);
-    void proj_curv( const SVector3 &old_u, const SVector3 &old_v, double old_ku, double old_kuv,
-                              double old_kv, const SVector3  &new_u, const SVector3 &new_v,
-                              double &new_ku, double &new_kuv, double &new_kv);
-    void diagonalize_curv(const SVector3 &old_u, const SVector3 &old_v,
-                          double ku, double kuv, double kv,
-                          const SVector3 &new_norm,
-                          SVector3 &pdir1, SVector3 &pdir2, double &k1, double &k2);
-    void computePointareas();
-    void computeRusinkiewiczNormals();
-
-    // Perform LDL^T decomposition of a symmetric positive definite matrix.
-    // Like Cholesky, but no square roots.  Overwrites lower triangle of matrix.
-    static inline bool ldltdc(STensor3& A, double rdiag[3])
-    {
-      double v[2];
-      for (int i = 0; i < 3; i++)
-      {
-        for (int k = 0; k < i; k++)
-          v[k] = A(i,k) * rdiag[k];
-        for (int j = i; j < 3; j++)
-        {
-          double sum = A(i,j);
-          for (int k = 0; k < i; k++)
-            sum -= v[k] * A(j,k);
-          if (i == j)
-          {
-            //if (unlikely(sum <= T(0)))
-            if (sum <= 0.0)
-              return false;
-            rdiag[i] = 1.0 / sum;
-          }
-          else
-          {
-            A(j,i) = sum;
-          }
-        }
-      }
-
-      return true;
-    }
-    // Solve Ax=B after ldltdc
-    static inline void ldltsl(STensor3& A, double rdiag[3], double B[3], double x[3])
-    {
-      int i;
-      for (i = 0; i < 3; i++)
-      {
-        double sum = B[i];
-        for (int k = 0; k < i; k++)
-          sum -= A(i,k) * x[k];
-        x[i] = sum * rdiag[i];
-      }
-      for (i = 3 - 1; i >= 0; i--)
-      {
-        double sum = 0;
-        for (int k = i + 1; k < 3; k++)
-          sum += A(k,i) * x[k];
-        x[i] -= sum * rdiag[i];
-      }
-    }
-
-    //Build the list of all edges:
-    void buildEdgeList();
-
-    //Smooth the computed curvature field via Laplacian smoothing method:
-    void smoothCurvatureField(const int NbIter);
-
-public:
-
-  typedef enum {RUSIN=1,RBF=2, SIMPLE=3} typeOfCurvature;
-  static Curvature& getInstance();
-  static bool valueAlreadyComputed();
-
-  inline void setGModel(GModel* model)
-  {
-    _model = model;
-  }
-
-  void retrieveCompounds();
-  void correctOnEdges();
-  double getAtVertex(const MVertex *v) const;
-  //void retrievePhysicalSurfaces(const std::string & face_tag);
-
-  void computeCurvature(GModel* model, typeOfCurvature typ);
-
-  /// The following function implements algorithm from:
-  /// Implementation of an Algorithm for Approximating the Curvature Tensor
-  /// on a Triangular Surface Mesh in the Vish Environment
-  /// Edwin Matthews, Werner Benger, Marcel Ritter
-  void computeCurvature_Simple();
-
-  /// The following function implements algorithm from:
-  /// Estimating Curvatures and Their Derivatives on Triangle Meshes
-  /// Szymon Rusinkiewicz, Princeton University
-  /// Code taken from Rusinkiewicz' 'trimesh2' library
-  void computeCurvature_Rusinkiewicz(int isMax=0);
-
-  void computeCurvature_RBF();
-
-  void triangleNodalValues(MTriangle* triangle, double& c0, double& c1, double& c2, int isAbs=0);
-  void triangleNodalValuesAndDirections(MTriangle* triangle, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0);
-
-  void edgeNodalValues(MLine* edge, double& c0, double& c1, int isAbs=0);
-  void edgeNodalValuesAndDirections(MLine* edge, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0);
-
-  void vertexNodalValues(MVertex* A, double& c0, int isAbs=0);
-  void vertexNodalValuesAndDirections(MVertex *A, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0);
-  SVector3 vertexNormal (MVertex* A) ;
-
-  void writeToMshFile( const std::string & filename);
-
-  void writeToPosFile( const std::string & filename);
-
-  void writeToVtkFile( const std::string & filename);
-
-  void writeDirectionsToPosFile( const std::string & filename);
-};
-
-#endif
diff --git a/Geo/GEdge.cpp b/Geo/GEdge.cpp
index 13c8d5708b012f0b2778316db3b3028f497e83b2..66ca5b4660ae8dab3137a10e1528d52f4a1a221f 100644
--- a/Geo/GEdge.cpp
+++ b/Geo/GEdge.cpp
@@ -21,7 +21,7 @@
 
 GEdge::GEdge(GModel *model, int tag, GVertex *_v0, GVertex *_v1)
   : GEntity(model, tag), _length(0.), _tooSmall(false), _cp(0),
-    v0(_v0), v1(_v1), compound(0), masterOrientation(0)
+    v0(_v0), v1(_v1), masterOrientation(0)
 {
   if(v0) v0->addEdge(this);
   if(v1 && v1 != v0) v1->addEdge(this);
diff --git a/Geo/GEdge.h b/Geo/GEdge.h
index 4538a95d80af0914523a647c87a428ddee9e7eec..2b415079ee0c916327b2b64f4ae4dd4e7efe8252 100644
--- a/Geo/GEdge.h
+++ b/Geo/GEdge.h
@@ -21,7 +21,6 @@
 class MElement;
 class MLine;
 class ExtrudeParams;
-class GEdgeCompound;
 class closestPointFinder;
 
 // A model edge.
@@ -35,7 +34,6 @@ class GEdge : public GEntity {
   // FIXME: normals need to be mutable at the moment, because thay can
   // be created in const member functions
   mutable std::map<MVertex*, SVector3, std::less<MVertex*> > _normals;
-  GEdgeCompound *compound; // this model edge belongs to a compound
   std::list<GFace *> l_faces;
   // for specific solid modelers that need to re-do the internal curve
   // if a topological change ending points is done (glueing)
@@ -191,10 +189,6 @@ class GEdge : public GEntity {
   virtual bool XYZToU(const double X, const double Y, const double Z,
                       double &U, const double relax=1) const;
 
-  // compound
-  void setCompound(GEdgeCompound *gec) { compound = gec; }
-  GEdgeCompound *getCompound() const { return compound; }
-
   // gluing
   void replaceEndingPoints(GVertex *, GVertex *);
 
diff --git a/Geo/GEdgeCompound.cpp b/Geo/GEdgeCompound.cpp
deleted file mode 100644
index 58f93ad36f677047b66c8088f4095767642fe74f..0000000000000000000000000000000000000000
--- a/Geo/GEdgeCompound.cpp
+++ /dev/null
@@ -1,359 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-//
-// Contributor(s):
-//   Emilie Marchandise
-//
-
-#include <stdlib.h>
-#include "GmshConfig.h"
-#include "GEdgeCompound.h"
-#include "discreteEdge.h"
-#include "Numeric.h"
-#include "Curvature.h"
-
-static bool looksOk(int tag, std::vector<GEdge*> &compound)
-{
-  if(compound.empty()){
-    Msg::Error("Empty edge compound %d", tag);
-    return false;
-  }
-  for(unsigned int i = 0; i < compound.size(); i++){
-    if(!compound[i]->getBeginVertex() || !compound[i]->getEndVertex()){
-      Msg::Error("Edge compound %d with missing begin/end vertex", tag);
-      return false;
-    }
-    if(compound.size() > 1 && compound[i]->getBeginVertex() == compound[i]->getEndVertex()){
-      Msg::Warning("Edge compound %d with subloop", tag);
-      return true;
-    }
-  }
-  return true;
-}
-
-GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound,
-                             std::vector<int> &orientation)
-  : GEdge(m, tag, 0, 0), _compound(compound), _orientation(orientation)
-{
-  if(!looksOk(tag, compound)) return;
-
-  int N = _compound.size();
-  if(N == (int)_orientation.size()){
-    v0 = _orientation[0] ? _compound[0]->getBeginVertex() : _compound[0]->getEndVertex();
-    v1 = _orientation[N-1] ? _compound[N-1]->getEndVertex() : _compound[N-1]->getBeginVertex();
-    v0->addEdge(this);
-    v1->addEdge(this);
-  }
-  else{
-    Msg::Error("Wrong input data for compound edge %d", tag);
-    return;
-  }
-
-  for (unsigned int i = 0; i < _compound.size(); i++){
-    _compound[i]->setCompound(this);
-    discreteEdge *de = dynamic_cast<discreteEdge*> (_compound[i]);
-    if(de) de->createGeometry();
-  }
-
-  for(std::vector<GEdge*>::iterator it = _compound.begin(); it != _compound.end(); ++it){
-    if(!(*it)){
-      Msg::Error("Incorrect edge in compound edge %d", tag);
-      return;
-    }
-  }
-
-  parametrize();
-}
-
-GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound)
-  : GEdge(m, tag, 0 , 0), _compound(compound)
-{
-  if(!looksOk(tag, compound)) return;
-
-  orderEdges();
-  int N = _compound.size();
-  if(N == (int)_orientation.size()){
-    v0 = _orientation[0] ? _compound[0]->getBeginVertex() : _compound[0]->getEndVertex();
-    v1 = _orientation[N-1] ? _compound[N-1]->getEndVertex() : _compound[N-1]->getBeginVertex();
-    v0->addEdge(this);
-    v1->addEdge(this);
-  }
-  else{
-    Msg::Error("Wrong input data for compound edge %d", tag);
-    return;
-  }
-
-  for (unsigned int i = 0; i < _compound.size(); i++){
-    _compound[i]->setCompound(this);
-    discreteEdge *de = dynamic_cast<discreteEdge*> (_compound[i]);
-    if(de) de->createGeometry();
-  }
-  parametrize();
-}
-
-void GEdgeCompound::orderEdges()
-{
-  std::vector<GEdge*> _c ;
-  std::list<GEdge*> edges ;
-
-  for (unsigned int i = 0; i < _compound.size(); i++){
-    edges.push_back(_compound[i]);
-  }
-
-  // find a lonely edge
-  std::map<GVertex*, GEdge*> tempv;
-  for (std::list<GEdge*>::iterator it = edges.begin() ; it != edges.end() ; ++it){
-    GVertex *v1 = (*it)->getBeginVertex();
-    GVertex *v2 = (*it)->getEndVertex();
-    if(!v1 || !v2){
-      Msg::Error("Compounds don't support curves without two bounding vertices");
-      return;
-    }
-    std::map<GVertex*, GEdge*>::iterator it1 = tempv.find(v1);
-    if (it1 == tempv.end()) {
-      tempv.insert(std::make_pair(v1, *it));
-    }
-    else tempv.erase(it1);
-    std::map<GVertex*, GEdge*>::iterator it2 = tempv.find(v2);
-    if (it2 == tempv.end()){
-      tempv.insert(std::make_pair(v2, *it));
-    }
-    else tempv.erase(it2);
-  }
-
-  // find the first GEdge and erase it from the list edges
-  GEdge *firstEdge;
-  if (tempv.size() == 2){ // non periodic
-    firstEdge = (tempv.begin())->second;
-    for (std::list<GEdge*>::iterator it = edges.begin() ; it != edges.end() ; ++it){
-      if (*it == firstEdge){
-        edges.erase(it);
-        break;
-      }
-    }
-  }
-  else if (tempv.size() == 0){ // periodic
-    firstEdge = *(edges.begin());
-    edges.erase(edges.begin());
-  }
-  else{
-    Msg::Error("EdgeCompound %d is wrong (it has %d end points)", tag(), tempv.size());
-    return;
-  }
-
-  // loop over all segments to order segments and store it in the list _c
-  _c.push_back(firstEdge);
-  _orientation.push_back(1);
-  GVertex *first = _c[0]->getBeginVertex();
-  GVertex *last = _c[0]->getEndVertex();
-
-  while (first != last){
-    if (edges.empty())break;
-    bool found = false;
-    for (std::list<GEdge*>::iterator it = edges.begin() ; it != edges.end() ; ++it){
-      GEdge *e = *it;
-      std::list<GEdge*>::iterator itp;
-     if (e->getBeginVertex() == last){
-        _c.push_back(e);
-        itp = it;
-        it++;
-        edges.erase(itp);
-        _orientation.push_back(1);
-        last = e->getEndVertex();
-        found = true;
-        break;
-      }
-      else if (e->getEndVertex() == last){
-        _c.push_back(e);
-        itp = it;
-        it++;
-        edges.erase(itp);
-        _orientation.push_back(0);
-        last = e->getBeginVertex();
-        found = true;
-        break;
-      }
-    }
-    if (!found){
-      if (_c.size() == 1 && _orientation[0]){
-        GVertex *temp = first;
-        first = last;
-        last = temp;
-        _orientation[0] = 0;
-      }
-      else {
-        Msg::Error("Compound Edge %d is wrong", tag());
-        return;
-      }
-    }
-  }
-
-  //edges is now a list of ordered GEdges
-  _compound = _c;
-
-  // special case reverse orientation
-  if (_compound.size() < 2) return;
-  if (_orientation[0] && _compound[0]->getEndVertex() != _compound[1]->getEndVertex()
-      && _compound[0]->getEndVertex() != _compound[1]->getBeginVertex()){
-    for (unsigned int i = 0; i < _compound.size(); i++){
-      _orientation[i] = !_orientation[i] ;
-    }
-  }
-}
-
-int GEdgeCompound::minimumMeshSegments() const
-{
-  // int N = 0;
-  // for (unsigned int i = 0; i < _compound.size(); i++)
-  //   N += _compound[i]->minimumMeshSegments();
-  return 3;
-}
-
-int GEdgeCompound::minimumDrawSegments() const
-{
-  int N = 0;
-  for (unsigned int i = 0; i < _compound.size(); i++)
-    N += _compound[i]->minimumDrawSegments();
-  return N;
-}
-
-GEdgeCompound::~GEdgeCompound()
-{
-}
-
-Range<double> GEdgeCompound::parBounds(int i) const
-{
-  if(_pars.empty()){
-    Msg::Error("Edge compound has no parametrization");
-    return Range<double>(0, 1);
-  }
-  return Range<double>(0, _pars[_compound.size()]);
-}
-
-/*
-  +--------+-----------+----------- ... ----+
-  0      _pars[1]     _pars[2]              _pars[N-1]
-
-*/
-
-bool GEdgeCompound::getLocalParameter(const double &t,
-                                      int &iEdge,
-                                      double &tLoc) const
-{
-  if(_pars.empty()){
-    Msg::Error("Edge compound has no parametrization");
-    return false;
-  }
-  for (iEdge = 0; iEdge < (int)_compound.size(); iEdge++){
-    double tmin = _pars[iEdge];
-    double tmax = _pars[iEdge+1];
-    if (t >= tmin && t <= tmax){
-      Range<double> b = _compound[iEdge]->parBounds(0);
-      tLoc = _orientation[iEdge] ?
-        b.low()  + (t-tmin)/(tmax-tmin) * (b.high()-b.low()) :
-        b.high() - (t-tmin)/(tmax-tmin) * (b.high()-b.low()) ;
-      return true;
-    }
-  }
-  return false;
-}
-
-void GEdgeCompound::parametrize()
-{
-  _pars.clear();
-  _pars.push_back(0.0);
-  for (unsigned int i = 0; i < _compound.size(); i++){
-    Range<double> b = _compound[i]->parBounds(0);
-    _pars.push_back(_pars[_pars.size()-1] + (b.high() - b.low()));
-  }
-}
-
-double GEdgeCompound::curvature(double par) const
-{
-  double tLoc;
-  int iEdge;
-  if(!getLocalParameter(par, iEdge, tLoc))
-    return 0.;
-  return _compound[iEdge]->curvature(tLoc);
-}
-
-double GEdgeCompound::curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin,
-                                 double *curvMax, double *curvMin) const
-{
-  double tLoc = -1.0;
-  int iEdge;
-  if(!getLocalParameter(par, iEdge, tLoc))
-    return 0;
-
-  if( _compound[iEdge]->geomType() == GEntity::DiscreteCurve){
-    Curvature& curvature = Curvature::getInstance();
-    if( !Curvature::valueAlreadyComputed() ){
-      Msg::Info("Need to compute discrete curvature for anisotropic remesh (in GFace)");
-      Curvature::typeOfCurvature type = Curvature::RUSIN; //RBF
-      curvature.computeCurvature(model(), type);
-    }
-    double tLocMLine;
-    int iMLine;
-    discreteEdge* ptrEdge = dynamic_cast<discreteEdge*>(_compound[iEdge]);
-    ptrEdge->getLocalParameter(tLoc, iMLine, tLocMLine);
-
-    //vector of MLines
-    MLine* mline = ptrEdge->lines[iMLine];
-
-    double cMin[2];
-    double cMax[2];
-    SVector3 dMin[2];
-    SVector3 dMax[2];
-    curvature.edgeNodalValuesAndDirections(mline, dMax, dMin, cMax, cMin, 1);
-
-    *dirMax = (1-tLocMLine)*dMax[0] + tLocMLine*dMax[1];
-    *dirMin = (1-tLocMLine)*dMin[0] + tLocMLine*dMin[1];
-    *curvMax = (1-tLocMLine)*cMax[0] + tLocMLine*cMax[1];
-    *curvMin = (1-tLocMLine)*cMin[0] + tLocMLine*cMin[1];
-
-    return *curvMax;
-  }
-  else{
-    Msg::Error("Case of CAD Geometry, don't know what to do here...");
-  }
-  return 0.0;
-}
-
-GPoint GEdgeCompound::point(double par) const
-{
-  double tLoc;
-  int iEdge;
-  if(!getLocalParameter(par, iEdge, tLoc))
-    return GPoint();
-  return _compound[iEdge]->point(tLoc);
-}
-
-SVector3 GEdgeCompound::firstDer(double par) const
-{
-  double tLoc;
-  int iEdge;
-  if(!getLocalParameter(par, iEdge, tLoc))
-    return SVector3();
-  return _compound[iEdge]->firstDer(tLoc);
-}
-
-void replaceMeshCompound(GFace *gf, std::list<GEdge*> &edges)
-{
-  std::list<GEdge*> e = gf->edges();
-  // replace edges by their compounds
-  std::set<GEdge*> mySet;
-  std::list<GEdge*>::iterator it = e.begin();
-  while(it != e.end()){
-    if((*it)->getCompound()){
-      mySet.insert((*it)->getCompound());
-    }
-    else{
-      mySet.insert(*it);
-    }
-    ++it;
-  }
-  edges.clear();
-  edges.insert(edges.begin(), mySet.begin(), mySet.end());
-}
diff --git a/Geo/GEdgeCompound.h b/Geo/GEdgeCompound.h
deleted file mode 100644
index 036f021f20093233c119654ce01ef290df546714..0000000000000000000000000000000000000000
--- a/Geo/GEdgeCompound.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-
-#ifndef _GEDGE_COMPOUND_H_
-#define _GEDGE_COMPOUND_H_
-
-#include "GFace.h"
-#include "GEdge.h"
-
-// A GEdgeCompound is a model edge that is the compound of model edges.
-
-class GEdgeCompound : public GEdge {
- protected:
-  std::vector<GEdge*> _compound;
-  std::vector<int> _orientation;
-  std::vector<double> _pars;
-  void orderEdges();
- public:
-  void parametrize();
-  bool getLocalParameter(const double &t, int &iEdge, double & tLoc) const;
-  GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound);
-  GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound,
-                std::vector<int> &orientation); // confidence in the input
-  virtual ~GEdgeCompound();
-  Range<double> parBounds(int i) const;
-  virtual GPoint point(double par) const;
-  virtual SVector3 firstDer(double par) const;
-  virtual GEntity::GeomType geomType() const { return CompoundCurve;  }
-  ModelType getNativeType() const { return GmshModel; }
-  void * getNativePtr() const { return 0; }
-  virtual double curvature(double t) const;
-  virtual double curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin,
-   double *curvMax, double *curvMin) const;
-  virtual int minimumMeshSegments() const;
-  virtual int minimumDrawSegments() const;
-  std::vector<GEdge*>  getCompounds() const { return _compound; }
-};
-
-void replaceMeshCompound(GFace*, std::list<GEdge*>&);
-
-#endif
diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp
index 34349160a57790910e28de77b14ab496c6e6c758..42acb346926bc9de0e71da229bf6c7c7d6af319b 100644
--- a/Geo/GFace.cpp
+++ b/Geo/GFace.cpp
@@ -35,7 +35,7 @@
 #define SQU(a)      ((a)*(a))
 
 GFace::GFace(GModel *model, int tag)
-  : GEntity(model, tag), r1(0), r2(0), compound(0), va_geom_triangles(0)
+  : GEntity(model, tag), r1(0), r2(0), va_geom_triangles(0)
 {
   meshStatistics.status = GFace::PENDING;
   resetMeshAttributes();
@@ -1101,7 +1101,7 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[
 #endif
 }
 
-bool GFace::containsParam(const SPoint2 &pt) 
+bool GFace::containsParam(const SPoint2 &pt)
 {
   Range<double> uu = parBounds(0);
   Range<double> vv = parBounds(1);
diff --git a/Geo/GFace.h b/Geo/GFace.h
index b55a4b71382452b1c63bb7ce005c25c21d69685c..5e3cd5d1a753b5e15b718d0564c5da16bb20a2a4 100644
--- a/Geo/GFace.h
+++ b/Geo/GFace.h
@@ -24,7 +24,6 @@ class MTriangle;
 class MQuadrangle;
 class MPolygon;
 class ExtrudeParams;
-class GFaceCompound;
 
 class GRegion;
 
@@ -39,7 +38,6 @@ class GFace : public GEntity {
   mean_plane meanPlane;
   std::list<GEdge *> embedded_edges;
   std::list<GVertex *> embedded_vertices;
-  GFaceCompound *compound; // this model face belongs to a compound
 
   BoundaryLayerColumns _columns;
 
@@ -254,10 +252,6 @@ class GFace : public GEntity {
   void computeMeshSizeFieldAccuracy(double &avg,double &max_e, double &min_e,
 				    int &nE, int &GS);
 
-  // compound
-  void setCompound(GFaceCompound *gfc) { compound = gfc; }
-  GFaceCompound *getCompound() const { return compound; }
-
   // add points (and optionally normals) in vectors so that two
   // points are at most maxDist apart
   bool fillPointCloud(double maxDist,
diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp
deleted file mode 100644
index 46170ba73490387b30e98d6d97da57701dfdbae2..0000000000000000000000000000000000000000
--- a/Geo/GFaceCompound.cpp
+++ /dev/null
@@ -1,3083 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-//
-// Contributor(s):
-//   Emilie Marchandise
-//
-
-#include "GmshConfig.h"
-#include "GmshDefines.h"
-#include "GFaceCompound.h"
-#include "GEdgeCompound.h"
-#include "intersectCurveSurface.h"
-#include "OS.h"
-
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-
-#include "Options.h"
-#include "MLine.h"
-#include "MTriangle.h"
-#include "Numeric.h"
-#include "Octree.h"
-#include "SBoundingBox3d.h"
-#include "SPoint3.h"
-#include "polynomialBasis.h"
-#include "robustPredicates.h"
-#include "MElementCut.h"
-#include "dofManager.h"
-#include "laplaceTerm.h"
-#include "crossConfTerm.h"
-#include "convexCombinationTerm.h"
-#include "diagBCTerm.h"
-#include "linearSystemGMM.h"
-#include "linearSystemCSR.h"
-#include "linearSystemFull.h"
-#include "linearSystemPETSc.h"
-#include "CreateFile.h"
-#include "Context.h"
-#include "discreteFace.h"
-#include "eigenSolver.h"
-#include "multiscaleLaplace.h"
-#include "GRbf.h"
-#include "Curvature.h"
-#include "MPoint.h"
-#include "Numeric.h"
-#include "meshGFace.h"
-#include "ANN/ANN.h"
-
-static void fixEdgeToValue(GEdge *ed, double value, dofManager<double> &myAssembler)
-{
-  myAssembler.fixVertex(ed->getBeginVertex()->mesh_vertices[0], 0, 1, value);
-  myAssembler.fixVertex(ed->getEndVertex()->mesh_vertices[0], 0, 1, value);
-  for(unsigned int i = 0; i < ed->mesh_vertices.size(); i++){
-    myAssembler.fixVertex(ed->mesh_vertices[i], 0, 1, value);
-  }
-}
-
-static std::vector<MVertex*> getBlob(unsigned int minNbPt, v2t_cont::iterator it,
-                                     v2t_cont &adj)
-{
-  std::vector<MVertex*> vv(1,it->first), bvv = vv;
-  // Vector of vertices in blob and in boundary of blob
-  do {
-    std::set<MVertex*> nbvv;
-    // Set of vertices in new boundary
-    for (std::vector<MVertex*>::iterator itBV = bvv.begin(); itBV != bvv.end(); itBV++) {
-      // For each boundary vertex...
-      std::vector<MElement*> &adjBV = adj[*itBV];
-      for (std::vector<MElement*>::iterator itBVEl = adjBV.begin(); itBVEl != adjBV.end();
-           itBVEl++) {
-        for (int iV=0; iV<(*itBVEl)->getNumVertices(); iV++){
-          // ... look for adjacent vertices...
-          MVertex *v = (*itBVEl)->getVertex(iV);
-          if (find(vv.begin(),vv.end(),v) == vv.end()) nbvv.insert(v);
-          // ... and add them in the new boundary if they are not already in the blob
-        }
-      }
-    }
-    if (nbvv.empty()) bvv.clear();
-    else {
-      bvv.assign(nbvv.begin(),nbvv.end());
-      vv.insert(vv.end(),nbvv.begin(),nbvv.end());
-    }
-//  } while (!bvv.empty());
-  } while (vv.size() < minNbPt);
-  // Repeat until min. number of points is reached
-
-  return vv;
-}
-
-static bool orderVertices(const std::list<GEdge*> &e, std::vector<MVertex*> &l,
-                          std::vector<double> &coord)
-{
-  l.clear();
-  coord.clear();
-
-  std::list<GEdge*>::const_iterator it = e.begin();
-  std::list<MLine*> temp;
-  double tot_length = 0;
-  for( ; it != e.end(); ++it ){
-    for(unsigned int i = 0; i < (*it)->lines.size(); i++ ){
-      temp.push_back((*it)->lines[i]);
-      MVertex *v0 = (*it)->lines[i]->getVertex(0);
-      MVertex *v1 = (*it)->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;
-    }
-  }
-
-  MVertex *first_v = (*temp.begin())->getVertex(0);
-  MVertex *current_v = (*temp.begin())->getVertex(1);
-
-  l.push_back(first_v);
-  coord.push_back(0.0);
-  temp.erase(temp.begin());
-
-  while(temp.size()){
-    bool found = false;
-    for(std::list<MLine*>::iterator itl = temp.begin(); itl != temp.end(); ++itl){
-      MLine *ll = *itl;
-      MVertex *v0 = ll->getVertex(0);
-      MVertex *v1 = ll->getVertex(1);
-      if(v0 == current_v){
-        found = true;
-        l.push_back(current_v);
-        current_v = v1;
-        temp.erase(itl);
-        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()));
-        coord.push_back(coord[coord.size()-1] + length / tot_length);
-        break;
-      }
-      else if(v1 == current_v){
-        found = true;
-        l.push_back(current_v);
-        current_v = v0;
-        temp.erase(itl);
-        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()));
-        coord.push_back(coord[coord.size()-1] + length / tot_length);
-        break;
-      }
-    }
-    if(!found) return false;
-  }
-
-  return true;
-}
-
-static bool computeCGKernelPolygon(std::map<MVertex*,SPoint3> &coordinates,
-                                   std::vector<MVertex*> &cavV,
-                                   double &ucg, double &vcg)
-{
-  ucg = 0.0;
-  vcg = 0.0;
-
-  // place at CG KERNEL polygon
-
-  int nbPts = cavV.size();
-  fullMatrix<double> u(100,2);
-  int ipt = 0;
-  for(std::vector<MVertex*>::iterator it = cavV.begin(); it != cavV.end(); it++){
-    SPoint3 vsp = coordinates[*it];
-    u(ipt,0) = vsp[0];
-    u(ipt,1) = vsp[1];
-    ucg += u(ipt,0);
-    vcg += u(ipt,1);
-    ipt++;
-  }
-  ucg /= ipt;
-  vcg /= ipt;
-
-  double eps = -5.e-7;
-  int N = nbPts;
-
-  std::set<int> setP;
-  for(int k = 0; k < nbPts; k++) setP.insert(k);
-
-  if(nbPts > 3){
-    for(int i = 0; i < nbPts - 2; i++){
-      int next = i + 1;
-      double x1, x2, y1, y2;
-      x1 = u(i, 0); y1 = u(i, 1);
-      x2 = u(next, 0); y2 = u(next, 1);
-      for(int j = i + 2; j < nbPts; j++){
-        int jnext = j + 1;
-        if(j == nbPts - 1) jnext = 0;
-        double x3, x4, y3, y4, x,y;
-        double a, b, c, d;
-        x3 = u(j, 0); y3 = u(j, 1);
-        x4 = u(jnext, 0); y4 = u(jnext, 1);
-        a = (y2 - y1) / (x2 - x1);
-        c = (y4 - y3) / (x4 - x3);
-        b = y1 - a * x1;
-        d = y3 - c * x3;
-        if(fabs(a - c) > 1.e-5 && x2 !=x1 && x4 != x3 && jnext != i){
-          x = (d - b) / (a - c);
-          y = a * x + b;
-          bool exist= false;
-          for(unsigned int k = 1; k < setP.size(); k++){
-            if(x == u(k, 0) && y == u(k, 1)) exist = true;
-          }
-          if(!exist){
-            u(N, 0) = x; u(N, 1) = y;
-            setP.insert(N);
-            N++;
-          }
-        }
-      }
-    }
-
-    int nbAll = setP.size();
-    for(int i = 0; i <nbPts; i++){
-      int next = i + 1;
-      if(next == nbPts) next = 0;
-      double p1[2] = {u(next, 0) - u(i, 0), u(next, 1) - u(i, 1)};
-      for(int k = 0; k < nbAll; k++){
-        double p2[2] = {u(k, 0) - u(i, 0), u(k, 1) - u(i, 1)};
-        double crossProd = p1[0] * p2[1] - p2[0] * p1[1];
-        if(crossProd <  eps){
-          setP.erase(k);
-        }
-      }
-    }
-  }
-
-  int nbFinal = setP.size();
-  if(nbFinal > 0){
-    ucg = 0.0;
-    vcg = 0.0;
-    for(std::set<int>::iterator it =setP.begin(); it != setP.end(); it++){
-      ucg += u(*it,0);
-      vcg += u(*it,1);
-    }
-    ucg /= nbFinal;
-    vcg /= nbFinal;
-    return true;
-  }
-  else{
-    return false;
-  }
-}
-
-static void myPolygon(std::vector<MElement*> &vTri, std::vector<MVertex*> &vPoly)
-{
-  std::vector<MEdge> ePoly;
-  for(unsigned int i = 0; i  < vTri.size() ; i++) {
-    MTriangle *t = (MTriangle*) vTri[i];
-    for(int iEdge = 0; iEdge < 3; iEdge++) {
-      MEdge tmp_edge =  t->getEdge(iEdge);
-      if(std::find(ePoly.begin(), ePoly.end(), tmp_edge) == ePoly.end())
-        ePoly.push_back(tmp_edge);
-      else
-        ePoly.erase(std::find(ePoly.begin(), ePoly.end(),tmp_edge));
-    }
-  }
-
-  std::vector<MEdge>::iterator ite= ePoly.begin() ;
-  MVertex *vINIT = ite->getVertex(0);
-  vPoly.push_back(vINIT);
-  vPoly.push_back(ite->getVertex(1));
-  ePoly.erase(ite);
-
-  while(!ePoly.empty()){
-    ite = ePoly.begin() ;
-    while(ite != ePoly.end()){
-      MVertex *vB = ite->getVertex(0);
-      MVertex *vE = ite->getVertex(1);
-      if(vB == vPoly.back()){
-	if(vE != vINIT) vPoly.push_back(vE);
-	ePoly.erase(ite);
-      }
-      else if(vE == vPoly.back()){
-	if(vB != vINIT) vPoly.push_back(vB);
-	ePoly.erase(ite);
-      }
-      else ite++;
-    }
-  }
-}
-
-static double normalUV(MTriangle *t, std::map<MVertex*, SPoint3> &vCoord)
-{
-  SPoint3 v0 = vCoord[t->getVertex(0)];
-  SPoint3 v1 = vCoord[t->getVertex(1)];
-  SPoint3 v2 = vCoord[t->getVertex(2)];
-  double p0[2] = {v0[0], v0[1]};
-  double p1[2] = {v1[0], v1[1]};
-  double p2[2] = {v2[0], v2[1]};
-  double normal =  robustPredicates::orient2d(p0, p1, p2);
-
-  // SVector3 P0 (v0.x(),v0.y(), 0.0);
-  // SVector3 P1 (v1.x(),v1.y(), 0.0);
-  // SVector3 P2 (v2.x(),v2.y(), 0.0);
-  // double normal2 = crossprod(P1-P0,P2-P1).z();
-  // if (normal != 0.0) normal /= std::abs(normal);
-
-  return normal;
-}
-
-static bool checkCavity(std::vector<MElement*> &vTri, std::map<MVertex*, SPoint3> &vCoord)
-{
-  bool badCavity = false;
-
-  unsigned int nbV = vTri.size();
-  double a_old = 0.0, a_new;
-  for(unsigned int i = 0; i < nbV; ++i){
-    a_new = normalUV((MTriangle*) vTri[i], vCoord);
-    if(i == 0) a_old=a_new;
-    if(a_new*a_old < 0.0) badCavity = true;
-  }
-  return badCavity;
-}
-
-static bool closedCavity(MVertex *v, std::vector<MElement*> &vTri)
-{
-  std::set<MVertex *> vs;
-  for (unsigned int i = 0; i < vTri.size(); i++){
-    MElement *t = vTri[i];
-    for (int j = 0; j < t->getNumVertices(); j++){
-      MVertex *vv = t->getVertex(j);
-      if (vv != v){
-        if (vs.find(vv) == vs.end())vs.insert(vv);
-        else vs.erase(vv);
-      }
-    }
-  }
-  return vs.empty();
-}
-
-static MVertex* findVertexInTri(v2t_cont &adjv, MVertex *v0, MVertex *v1,
-				std::map<MVertex*, SPoint3> &vCoord, double nTot,
-				bool &inverted)
-{
-  MVertex *v2 = 0;
-  v2t_cont :: iterator it0 = adjv.find(v0);
-  std::vector<MElement*> vTri0 = it0->second;
-  MElement *myTri = 0;
-  for (unsigned int j = 0; j < vTri0.size(); j++){
-    MVertex *vt0  = vTri0[j]->getVertex(0);
-    MVertex *vt1  = vTri0[j]->getVertex(1);
-    MVertex *vt2  = vTri0[j]->getVertex(2);
-    bool found0 = (vt0==v0 || vt1 ==v0 || vt2 ==v0) ? true: false;
-    bool found1 = (vt0==v1 || vt1 ==v1 || vt2 ==v1) ? true: false;
-    if (found0 && found1) { myTri = vTri0[j]; break; }
-  }
-  if(!myTri) return 0;
-  for (unsigned int j = 0; j < 3; j++){
-    MVertex *vj = myTri->getVertex(j);
-    if (vj!=v0 && vj!=v1) { v2 = vj; break;}
-  }
-  double normTri = normalUV((MTriangle*)myTri, vCoord);
-  if (nTot*normTri < 0.0) inverted = true;
-  else inverted = false;
-
-  return v2;
-}
-
-static MTriangle* findInvertedTri(v2t_cont &adjv, MVertex*v0, MVertex*v1, MVertex*v2,
-                                  std::map<MVertex*, SPoint3> &vCoord, double nTot)
-{
-  v2t_cont::iterator it = adjv.find(v1);
-  std::vector<MElement*> vTri = it->second;
-  MTriangle *myTri=NULL;
-  for (unsigned int j = 0; j < vTri.size(); j++){
-    double normTri = normalUV((MTriangle*)vTri[j], vCoord);
-    if (nTot * normTri < 0.0) {
-      MVertex *vt0  = vTri[j]->getVertex(0);
-      MVertex *vt1  = vTri[j]->getVertex(1);
-      MVertex *vt2  = vTri[j]->getVertex(2);
-      bool found0 = (vt0==v0 || vt1 ==v0 || vt2 ==v0) ? true: false;
-      bool found2 = (vt0==v2 || vt1 ==v2 || vt2 ==v2) ? true: false;
-      if (!found0 && !found2) { myTri = (MTriangle*)vTri[j]; break; }
-    }
-  }
-
-  return myTri;
-}
-
-void GFaceCompound::orientFillTris(std::list<MTriangle*> loopfillTris) const
-{
-  // check normal orientations of loopfillTris
-  bool invertTris = false;
-  std::map<MEdge, std::set<MTriangle*>, Less_Edge > edge2tris;
-  for(std::list<MTriangle*>::iterator t = loopfillTris.begin();
-      t != loopfillTris.end(); t++){
-    for (int j = 0; j < 3; j++){
-      MEdge me = (*t)->getEdge(j);
-      std::map<MEdge, std::set<MTriangle*, std::less<MTriangle*> >,
-	       Less_Edge >::iterator it = edge2tris.find(me);
-      if (it == edge2tris.end()) {
-	std::set<MTriangle*, std::less<MTriangle*> > mySet;
-	mySet.insert(*t);
-	edge2tris.insert(std::make_pair(me, mySet));
-      }
-      else{
-	std::set<MTriangle*, std::less<MTriangle*> > mySet = it->second;
-	mySet.insert(*t);
-	it->second = mySet;
-      }
-    }
-  }
-
-  int iE, si, iE2, si2;
-  std::list<GFace*>::const_iterator itf = _compound.begin();
-  for( ; itf != _compound.end(); ++itf){
-    for(unsigned int i = 0; i < (*itf)->triangles.size(); ++i){
-      MTriangle *t = (*itf)->triangles[i];
-      for (int j = 0; j < 3; j++){
-	MEdge me = t->getEdge(j);
-	std::map<MEdge, std::set<MTriangle*>, Less_Edge >::iterator it =
-	  edge2tris.find(me);
-	if(it != edge2tris.end()){
-	  t->getEdgeInfo(me, iE,si);
-	  MTriangle* t2 = *((it->second).begin());
-	  t2->getEdgeInfo(me,iE2,si2);
-	  if(si == si2) {
-	    invertTris = true;
-	    break;
-	  }
-	}
-      }
-    }
-  }
-  if (invertTris){
-    for (std::list<MTriangle*>::iterator it = loopfillTris.begin();
-           it != loopfillTris.end(); it++ )
-	(*it)->reverse();
-  }
-
-  fillTris.insert(fillTris.begin(),loopfillTris.begin(),loopfillTris.end());
-}
-
-void GFaceCompound::printFillTris() const
-{
-  if(!CTX::instance()->mesh.saveAll) return;
-
-  if (fillTris.size() > 0){
-    char name[256];
-    //std::list<GFace*>::const_iterator itf = _compound.begin();
-    sprintf(name, "fillTris-%d.pos", tag());
-    FILE * ftri = Fopen(name,"w");
-    if(ftri){
-      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);
-    }
-  }
-}
-
-void GFaceCompound::fillNeumannBCS_Plane() const
-{
-#if 0
-//#if defined(HAVE_MESH)
-
-  Msg::Debug("Meshing %d interior holes with planes ", _interior_loops.size()-1);
-
-  fillTris.clear();
-  fillNodes.clear();
-
-  if (_interior_loops.size()==1 && _type != SQUARE) return;
-
-  GModel::current()->setFactory("Gmsh");
-  //GModel::current()->setFactory("OpenCASCADE");
-  std::vector<std::vector<GFace *> > myFaceLoops;
-  std::vector<GFace *> myFaces;
-  for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin();
-      iloop != _interior_loops.end(); iloop++){
-    std::list<MTriangle*> loopfillTris;
-    std::list<GEdge*> loop = *iloop;
-    if (loop != _U0 ){
-      std::vector<std::vector<GEdge *> > myEdgeLoops;
-      std::vector<GEdge*> myEdges;
-      myEdgeLoops.clear();
-      myEdges.clear();
-      for (std::list<GEdge*>::iterator itl = loop.begin(); itl != loop.end(); itl++){
-	myEdges.push_back(*itl);
-      }
-      myEdgeLoops.push_back(myEdges);
-      GFace *newFace =  GModel::current()->addPlanarFace(myEdgeLoops);
-      fillFaces.push_back(newFace);
-      int meshingAlgo = CTX::instance()->mesh.algo2d;
-      int recombine = CTX::instance()->mesh.recombineAll;
-      opt_mesh_algo2d(0, GMSH_SET, 1.0); //mesh adapt
-      opt_mesh_recombine_all(0, GMSH_SET, 0.0); //no recombination
-      meshGFace mgf;
-      mgf(newFace,false);
-      opt_mesh_algo2d(0, GMSH_SET, meshingAlgo);
-      opt_mesh_recombine_all(0, GMSH_SET, recombine);
-      for(unsigned int i = 0; i < newFace->triangles.size(); ++i){
-	loopfillTris.push_back(newFace->triangles[i]);
-	fillNodes.insert(newFace->triangles[i]->getVertex(0));
-	fillNodes.insert(newFace->triangles[i]->getVertex(1));
-	fillNodes.insert(newFace->triangles[i]->getVertex(2));
-      }
-      orientFillTris(loopfillTris);
-    }
-  }
-
-  printFillTris();
-#endif
-}
-
-void GFaceCompound::fillNeumannBCS() const
-{
-  fillTris.clear();
-  fillNodes.clear();
-
-  // closed interior loops
-  for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin();
-      iloop != _interior_loops.end(); iloop++){
-    std::list<MTriangle*> loopfillTris;
-    std::list<GEdge*> loop = *iloop;
-    if (loop != _U0 ){
-      std::vector<MVertex*> orderedLoop;
-      std::vector<double> coordsLoop;
-      orderVertices(*iloop, orderedLoop, coordsLoop);
-      int nbLoop = orderedLoop.size();
-
-      //--- center of Neumann interior loop
-      int nb = 0;
-      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(int i = 0; i < nbLoop; ++i){
-	MVertex *v0 = orderedLoop[i];
-	MVertex *v1 = (i==nbLoop-1) ? orderedLoop[0]: orderedLoop[i+1];
-	x += .5*(v0->x() + v1->x());
-	y += .5*(v0->y() + v1->y());
-	z += .5*(v0->z() + v1->z());
-	nb++;
-      }
-      x/=nb; y/=nb;  z/=nb;
-      MVertex *c = new MVertex(x, y, z);
-
-      //--- create new triangles
-      for(int i = 0; i < nbLoop; ++i){
-	MVertex *v0 = orderedLoop[i];
-	MVertex *v1 = (i==nbLoop-1) ? orderedLoop[0]: orderedLoop[i+1];
-
-	double k = 1. / 3.; double kk = 2. / 3.;
-	MVertex *v2 = new MVertex(kk * v0->x() + k * c->x(),
-                                  kk * v0->y() + k * c->y(),
-                                  kk * v0->z() + k * c->z());
-	MVertex *v3 = new MVertex(kk * v1->x() + k * c->x(),
-                                  kk * v1->y() + k * c->y(),
-                                  kk * v1->z() + k * c->z());
-	MVertex *v4 = new MVertex(k * v0->x() + kk * c->x(),
-                                  k * v0->y() + kk * c->y(),
-                                  k * v0->z() + kk * c->z());
-	MVertex *v5 = new MVertex(k * v1->x() + kk * c->x(),
-                                  k * v1->y() + kk * c->y(),
-                                  k * v1->z() + kk * c->z());
-	fillNodes.insert(c); fillNodes.insert(v2); fillNodes.insert(v3);
-	fillNodes.insert(v4); fillNodes.insert(v5);
-	loopfillTris.push_back(new MTriangle(v0, v2, v3));
-	loopfillTris.push_back(new MTriangle(v2, v5, v3));
-	loopfillTris.push_back(new MTriangle(v2, v4, v5));
-	loopfillTris.push_back(new MTriangle(v4, c, v5));
-	loopfillTris.push_back(new MTriangle(v0, v3, v1));
-      }
-    }
-    orientFillTris(loopfillTris);
-  }
-
-  printFillTris();
-}
-
-bool GFaceCompound::trivial() const
-{
-  return false;
-  if(_compound.size() == 1 &&
-     (*(_compound.begin()))->getNativeType() == GEntity::OpenCascadeModel &&
-     (*(_compound.begin()))->geomType() != GEntity::DiscreteSurface &&
-     _mapping != CONFORMAL){
-    if ((*(_compound.begin()))->periodic(0) ||
-	(*(_compound.begin()))->periodic(1) ) return false;
-    return true;
-  }
-  return false;
-}
-
-// For the conformal map the linear system cannot guarantee there is
-// no overlapping of triangles
-bool GFaceCompound::checkOverlap(std::vector<MVertex *> &vert) const
-{
-
-  vert.clear();
-  bool has_overlap = false;
-  double EPS = 1.e-2;
-  for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin();
-      iloop != _interior_loops.end(); iloop++){
-    std::list<GEdge*> loop = *iloop;
-    std::vector<MVertex*> orderedLoop;
-    if (loop != _U0 ){
-      std::vector<double> coordsLoop;
-      orderVertices(*iloop, orderedLoop, coordsLoop);
-    }
-    else orderedLoop = _ordered;
-    int nbLoop = orderedLoop.size();
-
-    for(int i = 0; i < nbLoop-1; ++i){
-      SPoint3 p1 = coordinates[orderedLoop[i]];
-      SPoint3 p2 = coordinates[orderedLoop[i+1]];
-      int maxSize = (i==0) ? nbLoop-2: nbLoop-1;
-      for(int k = i+2; k < maxSize; ++k){
-	SPoint3 q1 = coordinates[orderedLoop[k]];
-	SPoint3 q2 = coordinates[orderedLoop[k+1]];
-	double x[2];
-	int inters = intersection_segments (p1,p2,q1,q2,x);
-	if (inters && x[1] > EPS && x[1] < 1.-EPS){
-	  has_overlap = true;
-	  MVertex *v1 = orderedLoop[i];
-	  MVertex *v2 = orderedLoop[k];
-	  //std::set<MVertex *>::iterator it1 = ov.find(v1);
-	  //std::set<MVertex *>::iterator it2 = ov.find(v2);
-	  vert.push_back(v1);
-	  vert.push_back(v2);
-	  Msg::Info("=== Overlap");
-	  return has_overlap;
-	}
-      }
-    }
-
-  }
-
-  return has_overlap;
-}
-
-// check if the discrete harmonic map is correct by checking that all
-// the mapped triangles have the same normal orientation
-bool GFaceCompound::checkOrientation(int iter, bool moveBoundaries) const
-{
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  double a_old = 0.0, a_new=0.0;
-  bool oriented = true;
-  int count = 0;
-  double nTot = 0.0;
-  for( ; it != _compound.end(); ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      a_new = normalUV((*it)->triangles[i], coordinates);
-      if(count == 0) a_old=a_new;
-      nTot += a_new;
-      if(a_new*a_old < 0.0){
-        oriented = false;
-        break;
-      }
-      count++;
-    }
-  }
-
-  int iterMax = 15;
-  if(!oriented && iter < iterMax){
-    if (moveBoundaries){
-      if (iter ==0) Msg::Info("--- Flipping : moving boundaries.");
-      Msg::Debug("--- Moving Boundary - iter %d -",iter);
-      convexBoundary(nTot/fabs(nTot));
-      printStuff(iter);
-      return checkOrientation(iter+1, moveBoundaries);
-    }
-    else if (!moveBoundaries){
-      if (iter ==0) Msg::Info("--- Flipping : applying cavity checks.");
-      Msg::Debug("--- Cavity Check - iter %d -",iter);
-      oriented = one2OneMap();
-      printStuff(iter);
-      iter++;
-      if (!oriented) return checkOrientation(iter);
-    }
-  }
-
-  if (iter > 0 && iter < iterMax){
-    Msg::Info("--- Flipping : no more flips (%d iter)", iter);
-  }
-
-  return oriented;
-}
-
-void GFaceCompound::convexBoundary(double nTot) const
-{
-#if defined(HAVE_MESH)
-  if(adjv.size() == 0){
-    std::vector<MTriangle*> allTri;
-    std::list<GFace*>::const_iterator it = _compound.begin();
-    for( ; it != _compound.end(); ++it){
-      allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() );
-    }
-    buildVertexToTriangle(allTri, adjv);
-  }
-
-  for(std::list<std::list<GEdge*> >::const_iterator it = _interior_loops.begin();
-      it != _interior_loops.end(); it++){
-
-    double s = 1.0;
-    std::vector<MVertex*> oVert;
-    std::vector<double> coords;
-    if (*it == _U0){
-      oVert = _ordered;
-    }
-    else {
-      s = -1.0;
-      orderVertices(*it, oVert,coords);
-    }
-
-    // find normal of ordered loop
-    MVertex *v0 = oVert[0];
-    MVertex *v1 = oVert[1];
-    bool inverted;
-    MVertex *v2 = findVertexInTri(adjv, v0,v1,coordinates, nTot, inverted);
-    if (inverted) s *= -1.0 ;
-    SPoint3 uv0 = coordinates[v0];
-    SPoint3 uv1 = coordinates[v1];
-    SPoint3 uv2 = coordinates[v2];
-    SVector3 P0 (uv0.x(),uv0.y(), 0.0);
-    SVector3 P1 (uv1.x(),uv1.y(), 0.0);
-    SVector3 P2 (uv2.x(),uv2.y(), 0.0);
-    double myN = s*crossprod(P1-P0,P2-P1).z();
-    SVector3 N (0,0,myN/fabs(myN));
-
-    // start the loop
-    int nbInv = 0;
-    int nbInvTri = 0;
-    for(unsigned int i = 0; i < oVert.size(); i++){
-
-      MVertex *v0 = oVert[i];
-      MVertex *v1, *v2;
-      if (i == oVert.size()-2){
-	v1 = oVert[i+1];
-	v2 = oVert[0];
-      }
-      else if (i == oVert.size()-1){
-	v1= oVert[0];
-	v2= oVert[1];
-      }
-      else{
-	v1 = oVert[i+1];
-	v2 = oVert[i+2];
-      }
-
-      SPoint3 uv0 = coordinates[v0];
-      SPoint3 uv1 = coordinates[v1];
-      SPoint3 uv2 = coordinates[v2];
-      SVector3 P0 (uv0.x(),uv0.y(), uv0.z());
-      SVector3 P1 (uv1.x(),uv1.y(), uv1.z());
-      SVector3 P2 (uv2.x(),uv2.y(), uv2.z());
-
-      SVector3 dir1 = P1-P0;
-      SVector3 dir2 = P2-P1;
-      SVector3 dir3 = crossprod(dir1,dir2);
-      double rot = dot(N, (1./norm(dir3))*dir3);
-
-      bool inverted;
-      MVertex *v2t = findVertexInTri(adjv, v0,v1, coordinates, nTot, inverted);
-
-      if (rot < 0.0 && inverted){
-	SVector3 a = P1-P0;
-	SVector3 b = P2-P0;
-	double a_para = dot(a,b)/norm(b);
-	SVector3 P3,P1b;
-	P3= P0 + (a_para/norm(b))*b;
-	P1b = P1 + 1.2*(P3-P1);
-	SPoint3 uv1_new(P1b.x(),P1b.y(),P1b.z());
-	coordinates[v1] = uv1_new;
-      }
-      else if (rot > 0.0 && inverted){
-	nbInv++;
-	SPoint3 uv2t = coordinates[v2t];
-	SVector3 P2t (uv2t.x(),uv2t.y(), uv2t.z());
-	SVector3 a = P1-P0;
-	SVector3 b = P2t-P0;
-	double b_para = dot(a,b)/norm(a);
-	SVector3 P3,P2b;
-	P3= P0 + (b_para/norm(a))*a;
-	P2b = P2t + 1.3*(P3-P2t);
-	SPoint3 uv2_new(P2b.x(),P2b.y(),P2b.z());
-	coordinates[v2t] = uv2_new;
-      }
-
-      MTriangle *tinv = findInvertedTri(adjv, v0,v1,v2, coordinates, nTot);
-      if (tinv){
-	nbInvTri++;
-	MVertex *i0 = NULL;
-	MVertex *i1 = NULL;
-	for (unsigned int j = 0; j < 3; j++){
-	  MVertex *vj = tinv->getVertex(j);
-	  if (vj!=v1 && i0 == NULL) i0 = vj;
-	  else if (vj!=v1 && i1 ==NULL ) i1 = vj;
-	}
-	MVertex *i2 = v1;
-	SPoint3 uv0 = coordinates[i0];
-	SPoint3 uv1 = coordinates[i1];
-	SPoint3 uv2 = coordinates[i2];
-	SVector3 P0 (uv0.x(),uv0.y(), uv0.z());
-	SVector3 P1 (uv1.x(),uv1.y(), uv1.z());
-	SVector3 P2 (uv2.x(),uv2.y(), uv2.z());
-	SVector3 a = P1-P0;
-	SVector3 b = P2-P0;
-	double b_para = dot(a,b)/norm(a);
-	SVector3 P3,P2b;
-	P3= P0 + (b_para/norm(a))*a;
-	P2b = P2 + 1.2*(P3-P2);
-	SPoint3 uv2_new(P2b.x(),P2b.y(),P2b.z());
-	coordinates[i2] = uv2_new;
-      }
-
-    }
-  }
-#endif
-}
-
-bool GFaceCompound::one2OneMap() const
-{
-#if defined(HAVE_MESH)
-  if(adjv.size() == 0){
-    std::vector<MTriangle*> allTri;
-    std::list<GFace*>::const_iterator it = _compound.begin();
-    for( ; it != _compound.end(); ++it){
-      allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() );
-    }
-    buildVertexToTriangle(allTri, adjv);
-  }
-
-  int nbRepair = 0;
-  int nbCav = 0;
-  for(v2t_cont::iterator it = adjv.begin(); it!= adjv.end(); ++it){
-    MVertex *v = it->first;
-    SPoint2 p = getCoordinates(v);
-    std::vector<MElement*> vTri = it->second;
-    std::map<MVertex*,SPoint3> vCoord;
-    for (unsigned int j = 0; j < vTri.size(); j++){
-      for (int k = 0; k < vTri[j]->getNumVertices(); k++){
-        MVertex *vk = vTri[j]->getVertex(k);
-        SPoint2 pt2 =  getCoordinates(vk);
-	vCoord[vk] = SPoint3(pt2[0], pt2[1], 0.0);
-      }
-    }
-    bool badCavity = checkCavity(vTri, vCoord);
-    bool innerCavity = closedCavity(v,vTri);
-
-    if( badCavity && innerCavity ){
-      nbCav++;
-      double u_cg, v_cg;
-      std::vector<MVertex*> cavV;
-      myPolygon(vTri, cavV);
-      //bool success =
-         computeCGKernelPolygon(coordinates, cavV, u_cg, v_cg);
-      //if (success){ //if not succes compute with CG polygon
-	nbRepair++;
-	SPoint3 p_cg(u_cg,v_cg,0.0);
-	coordinates[v] = p_cg;
-      //}
-    }
-  }
-  if (nbRepair == 0) return false;
-  else return true;
-#endif
-}
-
-bool GFaceCompound::parametrize() const
-{
-  if (_compound.size() > 1) coherencePatches();
-
-  bool paramOK = true;
-  if(oct) return paramOK;
-  if(trivial()) return paramOK;
-
-  if (_mapping != RBF)
-    coordinates.clear();
-
-  computeNormals();
-
-  if(allNodes.empty()) buildAllNodes();
-
-  if (_type != SQUARE){
-    bool success = orderVertices(_U0, _ordered, _coords);
-    if(!success) {
-      Msg::Error("Could not order vertices on boundary");
-      return false;
-    }
-  }
-
-  //fillNeumannBCS_Plane();
-  fillNeumannBCS();
-
-  // Convex parametrization
-  if (_mapping == CONVEX){
-    Msg::Info("Parametrizing surface %d with 'convex map'", tag());
-    parametrize(ITERU,CONVEX);
-    parametrize(ITERV,CONVEX);
-    if (_type==MEANPLANE){
-      checkOrientation(0, true);
-    }
-  }
-  // Laplace parametrization
-  else if (_mapping == HARMONIC){
-    Msg::Info("Parametrizing surface %d with 'harmonic map'", tag());
-    parametrize(ITERU,HARMONIC);
-    parametrize(ITERV,HARMONIC);
-    if (_type == MEANPLANE) checkOrientation(0, true);
-  }
-  // Conformal map parametrization
-  else if (_mapping == CONFORMAL){
-    std::vector<MVertex *> vert;
-    bool oriented, overlap;
-    if (_type == SPECTRAL){
-      Msg::Info("Parametrizing surface %d with 'spectral conformal map'", tag());
-      overlap = parametrize_conformal_spectral();
-    }
-    else {
-      Msg::Info("Parametrizing surface %d with 'FE conformal map'", tag());
-      overlap = parametrize_conformal(0, NULL, NULL);
-    }
-    //printStuff(55);
-    oriented = checkOrientation(0);
-    //printStuff(77);
-    if (_type==SPECTRAL &&  (!oriented || overlap) ){
-      Msg::Warning("Parametrization switched to 'FE conformal' map");
-      overlap = parametrize_conformal(0, NULL, NULL);
-      oriented = checkOrientation(0);
-    }
-    if (!oriented || overlap){
-      Msg::Warning("Parametrization switched to 'convex' map");
-      _type  = UNITCIRCLE;
-      parametrize(ITERU,CONVEX);
-      parametrize(ITERV,CONVEX);
-    }
-  }
-  // Radial-Basis Function parametrization
-  else if (_mapping == RBF){
-    Msg::Debug("Parametrizing surface %d with 'RBF' ", tag());
-    int variableEps = 0;
-    int radFunInd = 1; // 1 MQ RBF , 0 GA
-    double sizeBox = getSizeH();
-    /*
-    fullMatrix<double> Oper(3*allNodes.size(),3*allNodes.size());
-    _rbf = new GRbf(sizeBox, variableEps, radFunInd, _normals, allNodes, _ordered);
-    _rbf->RbfLapSurface_local_CPM(false,_rbf->getXYZ(), _rbf->getN(), Oper);
-    _rbf->solveHarmonicMap(Oper, _ordered, _coords, coordinates);
-    */
-    fullMatrix<double> Oper(3*allNodes.size(),3*allNodes.size());
-
-    _rbf = new GRbf(sizeBox, variableEps, radFunInd, _normals, allNodes, _ordered);
-
-    linearSystemPETSc<double> sys;
-
-    #if 1
-    _rbf->RbfLapSurface_local_CPM_sparse(_ordered, false, _rbf->getXYZ(), _rbf->getN(), sys);
-    _rbf->solveHarmonicMap_sparse(sys, _rbf->getXYZ().size1()* 3,_ordered, _coords, coordinates);
-    #else
-    _rbf->RbfLapSurface_local_CPM(false, _rbf->getXYZ(), _rbf->getN(), Oper);
-    _rbf->solveHarmonicMap(Oper,_ordered, _coords, coordinates);
-    #endif
-  }
-
-  buildOct();
-
-  if (_mapping != RBF){
-    if (!checkOrientation(0)){
-      printStuff(22);
-      Msg::Info("### parametrization switched to 'convex map' onto circle");
-      printStuff(33);
-      _type = UNITCIRCLE;
-      coordinates.clear();
-      Octree_Delete(oct);
-      parametrize(ITERU, CONVEX);
-      parametrize(ITERV, CONVEX);
-      checkOrientation(0);
-      buildOct();
-    }
-  }
-
-  for (unsigned int i= 0; i< fillFaces.size(); i++){
-    GModel::current()->remove(fillFaces[i]);
-  }
-
-  return paramOK;
-}
-
-void GFaceCompound::getBoundingEdges()
-{
-  for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){
-    (*it)->setCompound(this);
-  }
-
-  std::set<GEdge*> _unique;
-  getUniqueEdges(_unique);
-
-  l_edges.clear();
-  l_dirs.clear();    // added by Trevor Strickler
-
-
-  if(_U0.size()){
-    // in case the bounding edges are explicitely given
-    std::list<GEdge*>::const_iterator it = _U0.begin();
-    for( ; it != _U0.end() ; ++it){
-      l_edges.push_back(*it);
-      (*it)->addFace(this);
-    }
-    if (_V0.size() && _U1.size() && _V1.size()){
-      it = _V0.begin();
-      for( ; it != _V0.end() ; ++it){
-	l_edges.push_back(*it);
-	(*it)->addFace(this);
-      }
-      it = _U1.begin();
-      for( ; it != _U1.end() ; ++it){
-	l_edges.push_back(*it);
-	(*it)->addFace(this);
-      }
-      it = _V1.begin();
-      for( ; it != _V1.end() ; ++it){
-	l_edges.push_back(*it);
-	(*it)->addFace(this);
-      }
-    }
-    std::list<GEdge*> loop;
-    computeALoop(_unique, loop);
-    while(!_unique.empty())  computeALoop(_unique,loop);
-  }
-  else{
-    // in case the bounding edges are NOT explicitely given
-    std::set<GEdge*>::iterator itf = _unique.begin();
-    for( ; itf != _unique.end(); ++itf){
-      l_edges.push_back(*itf);
-      (*itf)->addFace(this);
-    }
-
-    std::list<GEdge*> loop;
-    computeALoop(_unique,loop);
-    while(!_unique.empty())  computeALoop(_unique, loop);
-
-    // assign Derichlet BC (_U0) to boundary with largest size
-    double maxSize = 0.0;
-    for(std::list<std::list<GEdge*> >::iterator it = _interior_loops.begin();
-        it != _interior_loops.end(); it++){
-      double size = getSizeBB(*it);
-      if (size > maxSize) {
-	_U0 = *it;
-	maxSize = size;
-      }
-    }
-  }
-
-    // Added by Trevor Strickler (fill in the l_dirs)
-  std::list<GEdge*>::iterator it_loop;
-  std::list<std::list<GEdge*> >::iterator it_interior;
-  l_edges.clear();
-
-  for( it_interior = _interior_loops.begin(); it_interior != _interior_loops.end(); it_interior++ ){
-    for( it_loop = it_interior->begin(); it_loop != it_interior->end(); it_loop++ ){
-      l_edges.push_back( (*it_loop) );
-      std::list<GEdge*>::iterator it_loop_next = it_loop;
-      it_loop_next++;
-      if( it_loop_next == it_interior->end() )
-        it_loop_next = it_interior->begin();
-      GVertex *vB = (*it_loop)->getBeginVertex();
-      GVertex *vE = (*it_loop)->getEndVertex();
-      GVertex *vB_next = (*it_loop_next)->getBeginVertex();
-      GVertex *vE_next = (*it_loop_next)->getEndVertex();
-      if( vB == vB_next || vB == vE_next )
-        l_dirs.push_back(-1);
-      else if( vE == vB_next || vE == vE_next )
-        l_dirs.push_back(1);
-      else{
-       l_dirs.push_back(0);
-      }
-    }
-  }
-
-}
-
-
-double GFaceCompound::getSizeH() const
-{
-  SBoundingBox3d bb;
-  for(std::set<MVertex *>::iterator itv = allNodes.begin();
-      itv != allNodes.end() ; ++itv){
-    SPoint3 pt((*itv)->x(),(*itv)->y(), (*itv)->z());
-    bb +=pt;
-  }
-
-  double H = norm(SVector3(bb.max(), bb.min()));
-
-  return H;
-}
-
-double GFaceCompound::getSizeBB(const std::list<GEdge* > &elist) const
-{
-  SBoundingBox3d bboxD;
-  std::list<GEdge*>::const_iterator it = elist.begin();
-  for(; it != elist.end(); it++){
-    bboxD += (*it)->bounds();
-  }
-  double D = norm(SVector3(bboxD.max(), bboxD.min()));
-
-  return D;
-}
-
-void GFaceCompound::getUniqueEdges(std::set<GEdge*> &_unique)
-{
-  _unique.clear();
-
-  // in case the bounding edges are not given Boundary { {} };
-  std::multiset<GEdge*> _touched;
-  std::list<GFace*>::iterator it = _compound.begin();
-  for( ; it != _compound.end(); ++it){
-    std::list<GEdge*> ed = (*it)->edges();
-    std::list<GEdge*>::iterator ite = ed.begin();
-    for( ; ite != ed.end(); ++ite){
-      _touched.insert(*ite);
-    }
-  }
-  it = _compound.begin();
-  for( ; it != _compound.end(); ++it){
-    std::list<GEdge*> ed = (*it)->edges();
-    std::list<GEdge*>::iterator ite = ed.begin();
-    for( ; ite != ed.end() ; ++ite){
-      if(!(*ite)->degenerate(0) && _touched.count(*ite) == 1){
-        _unique.insert(*ite);
-      }
-    }
-  }
-}
-
-void GFaceCompound::computeALoop(std::set<GEdge*> &_unique, std::list<GEdge*> &loop)
-{
-  std::list<GEdge*> _loop;
-
-  if (_unique.empty()) return;
-
-  while(!_unique.empty()) {
-    std::set<GEdge*>::iterator it = _unique.begin();
-    GVertex *vB = (*it)->getBeginVertex();
-    GVertex *vE = (*it)->getEndVertex();
-    _loop.push_back(*it);
-    _unique.erase(it);
-
-    bool found = false;
-/* Mod by Trevor Strickler: In the old implementation, the iterator
-    itx was incremented twice per loop and _loops was not set up correctly.
-    The While Loop below replaces the old for loop.
-*/
-    for(int i = 0; i < 2; i++) {
-      std::set<GEdge*>::iterator itx = _unique.begin();
-      while (itx != _unique.end() ){
-        GVertex *v1 = (*itx)->getBeginVertex();
-        GVertex *v2 = (*itx)->getEndVertex();
-
-        std::set<GEdge*>::iterator itp = itx;
-        itx++;
-
-        if(v1 == vE ){
-          _loop.push_back(*itp);
-          vE = v2;
-          i = -1;
-          _unique.erase(itp);
-        }
-        else if(v2 == vE){
-          _loop.push_back(*itp);
-          vE = v1;
-          i=-1;
-          _unique.erase(itp);
-        }
-      }
-
-      if(vB == vE) {
-        found = true;
-        break;
-      }
-
-      if(_unique.empty())  break;
-
-      // Mod by Trevor Strickler: had to wrap this in an if
-      //  or else it was executed when i == -1, which is not good.
-      if( i != -1 ){
-        GVertex *temp = vB;
-        vB = vE;
-        vE = temp;
-      }
-    }
-    /* This is the old version of above nested loops before modified by Trevor Strickler
-    for(int i = 0; i < 2; i++) {
-      for(std::set<GEdge*>::iterator itx = _unique.begin();
-          itx != _unique.end(); ++itx){
-        GVertex *v1 = (*itx)->getBeginVertex();
-        GVertex *v2 = (*itx)->getEndVertex();
-
-        std::set<GEdge*>::iterator itp;
-        if(v1 == vE){
-          _loop.push_back(*itx);
-          itp = itx;
-          itx++;
-          _unique.erase(itp);
-          vE = v2;
-          i = -1;
-        }
-        else if(v2 == vE){
-          _loop.push_back(*itx);
-          itp = itx;
-          itx++;
-          _unique.erase(itp);
-          vE = v1;
-          i=-1;
-        }
-        if(itx == _unique.end()) break;
-      }
-
-      if(vB == vE) {
-        found = true;
-        break;
-      }
-
-      if(_unique.empty())  break;
-
-      GVertex *temp = vB;
-      vB = vE;
-      vE = temp;
-    }*/
-
-    if(found == true) break;
-
-    it++;
-  }
-
-  loop = _loop;
-  _interior_loops.push_back(loop);
-}
-
-GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
-			     std::list<GEdge*> &U0, typeOfCompound toc,
-                             int allowPartition)
-  : GFace(m, tag), _compound(compound), _U0(U0), oct(0), octNew(0),
-    _toc(toc), _allowPartition(allowPartition)
-{
-  ONE = new simpleFunction<double>(1.0);
-  MONE = new simpleFunction<double>(-1.0);
-
-  for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){
-    if(!(*it)){
-      Msg::Error("Incorrect face in compound surface %d\n", tag);
-      return;
-    }
-  }
-
-  getBoundingEdges();
-
-  _mapping = HARMONIC;
-  _type = UNITCIRCLE;
-  if(toc == RADIAL_BASIS)   _mapping = RBF;
-  else if (toc == HARMONIC_PLANE) _type = MEANPLANE;
-  else if (toc == CONVEX_CIRCLE)  _mapping = CONVEX;
-  else if (toc == CONVEX_PLANE){
-    _mapping = CONVEX;
-    _type = MEANPLANE;
-  }
-  else if(toc == CONFORMAL_SPECTRAL) {
-    _mapping = CONFORMAL;
-    _type = SPECTRAL;
-  }
-  else if(toc == CONFORMAL_FE) {
-    _mapping = CONFORMAL;
-    _type = FE;
-  }
-
-  nbSplit = 0;
-  fillTris.clear();
-
-  kdtree = NULL;
-  uv_kdtree = NULL;
-}
-
-GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
-			     std::list<GEdge*> &U0, std::list<GEdge*> &V0,
-			     std::list<GEdge*> &U1, std::list<GEdge*> &V1,
-			     typeOfCompound toc,
-			     int allowPartition)
-  : GFace(m, tag), _compound(compound), _U0(U0), _V0(V0), _U1(U1), _V1(V1),
-    oct(0), octNew(0), _toc(toc), _allowPartition(allowPartition)
-{
-  ONE = new simpleFunction<double>(1.0);
-  MONE = new simpleFunction<double>(-1.0);
-
-  for(std::list<GFace*>::iterator it = _compound.begin(); it != _compound.end(); ++it){
-    if(!(*it)){
-      Msg::Error("Incorrect face in compound surface %d\n", tag);
-      return;
-    }
-  }
-
-  getBoundingEdges();
-
-  _mapping = HARMONIC;
-  _type = UNITCIRCLE;
-  if(toc == RADIAL_BASIS)   _mapping = RBF;
-  else if (toc == HARMONIC_PLANE) _type = MEANPLANE;
-  else if (toc == CONVEX_CIRCLE)  _mapping = CONVEX;
-  else if (toc == CONVEX_PLANE){
-    _mapping = CONVEX;
-    _type = MEANPLANE;
-  }
-  if(toc == CONFORMAL_SPECTRAL) {
-    _mapping = CONFORMAL;
-    _type = SPECTRAL;
-  }
-  else if(toc == CONFORMAL_FE) {
-    _mapping = CONFORMAL;
-    _type = FE;
-  }
-  else if(toc == HARMONIC_SQUARE && _U0.size() && _V0.size() && _U1.size() && _V1.size()) {
-    _type = SQUARE;
-  }
-
-  nbSplit = 0;
-  fillTris.clear();
-
-  uv_kdtree = NULL;
-  kdtree = NULL;
-}
-
-GFaceCompound::~GFaceCompound()
-{
-  delete ONE;
-  delete MONE;
- _deleteInternals();
-}
-
-void GFaceCompound::deleteInternals(){
-  _deleteInternals();
-}
-
-void GFaceCompound::_deleteInternals()
-{
-  for (unsigned int i = 0; i < myParamVert.size(); i++)
-    delete myParamVert[i];
-  myParamVert.clear();
-  for (unsigned int i = 0; i < myParamElems.size(); i++)
-    delete myParamElems[i];
-  myParamElems.clear();
-  _3Dto2D.clear();
-  _2Dto3D.clear();
-  XYZoct.clear();
-  allNodes.clear();
-  adjv.clear();
-  coordinates.clear();
-  firstDerivatives.clear();
-  xuu.clear();
-  xvv.clear();
-  xuv.clear();
-  xu.clear();
-  xv.clear();
-  _coordPoints.clear();
-  _normals.clear();
-  fillTris.clear();
-  fillNodes.clear();
-  fillFaces.clear();
-  _ordered.clear();
-  _coords.clear();
-  _mapV.clear();
-
-  if(oct){
-    Octree_Delete(oct);
-    delete [] _gfct;
-    oct = 0;
-  }
-  if(octNew){
-    delete octNew;
-    octNew = 0;
-  }
-  if(uv_kdtree) {
-    ANNpointArray uv_nodes = uv_kdtree->thePoints();
-    if(uv_nodes) annDeallocPts(uv_nodes);
-    delete uv_kdtree;
-    uv_kdtree = 0;
-  }
-  if(kdtree){
-    ANNpointArray nodes = kdtree->thePoints();
-    if(nodes) annDeallocPts(nodes);
-    delete kdtree;
-    kdtree = 0;
-  }
-}
-
-
-void GFaceCompound::deleteMesh()
-{
-  _deleteInternals();
-  GFace::deleteMesh();
-}
-
-SPoint2 GFaceCompound::getCoordinates(MVertex *v) const
-{
-  if(trivial()){
-    SPoint2 param;
-    reparamMeshVertexOnFace(v, (*(_compound.begin())),param);
-    return param;
-  }
-
-  std::map<MVertex*,SPoint3>::iterator it = coordinates.find(v);
-
-  if(it != coordinates.end()){
-    return SPoint2(it->second.x(),it->second.y());
-  }
-  else{
-
-    //if(v->onWhat()->dim() == 1){
-      double tGlob, tLoc;
-      double tL, tR;
-      int iEdge;
-
-      // getParameter Point
-      v->getParameter(0, tGlob);
-
-      //find compound Edge
-      GEdgeCompound *gec = dynamic_cast<GEdgeCompound*>(v->onWhat());
-
-      if(gec){
-	// compute local parameter on Edge
-	gec->getLocalParameter(tGlob,iEdge,tLoc);
-	std::vector<GEdge*> gev = gec->getCompounds();
-	GEdge *ge = gev[iEdge];
-        std::map<MVertex*,SPoint3>::iterator itL;
-        std::map<MVertex*,SPoint3>::iterator itR;
-
-        if(ge->geomType() == GEntity::DiscreteCurve){
-          discreteEdge *de = dynamic_cast<discreteEdge*>(ge);
-          int i = (int)tLoc;
-          MLine *l = de->lines[i];
-          MVertex *vL = l->getVertex(0);
-          MVertex *vR = l->getVertex(1);
-          itL = coordinates.find(vL);
-          if(itL == coordinates.end()){
-            Msg::Error("Vertex %p (%g %g %g) not found", vL, vL->x(), vL->y(), vL->z());
-            return SPoint2(0, 0);
-          }
-          itR = coordinates.find(vR);
-          if(itR == coordinates.end()){
-            Msg::Error("Vertex %p (%g %g %g) not found", vR, vR->x(), vR->y(), vR->z());
-            return SPoint2(0, 0);
-          }
-          double xi, uloc, vloc;
-          xi = tLoc - i;
-          uloc = (1 - xi) * itL->second.x() + xi * itR->second.x();
-          vloc = (1 - xi) * itL->second.y() + xi * itR->second.y();
-          return SPoint2(uloc,vloc);
-        }
-        else{
-          // left and right vertex of the Edge
-          MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
-          MVertex *v1 = ge->getEndVertex()->mesh_vertices[0];
-          itL = coordinates.find(v0);
-          itR = coordinates.find(v1);
-          // for the Edge, find the left and right vertices of the initial
-          // 1D mesh and interpolate to find (u,v)
-          //MVertex *vL = v0;
-          MVertex *vR = v1;
-          double tB = ge->parBounds(0).low();
-          double tE = ge->parBounds(0).high();
-          int j = 0;
-          tL=tB;
-          bool found = false;
-          while(j < (int)ge->mesh_vertices.size()){
-            vR = ge->mesh_vertices[j];
-            if(vR->getPolynomialOrder() > 1){ j++; continue; }
-            vR->getParameter(0, tR);
-            if(!vR->getParameter(0, tR)) {
-              Msg::Error("Vertex vr %p not an MEdgeVertex", vR);
-              return SPoint2();
-            }
-            if(tLoc > tL && tLoc < tR){
-              found = true;
-              itR = coordinates.find(vR);
-              if(itR == coordinates.end()){
-                Msg::Error("Vertex %p (%g %g %g) not found", vR, vR->x(), vR->y(), vR->z());
-                return SPoint2(0, 0);
-              }
-              break;
-            }
-            else{
-              itL = coordinates.find(vR);
-              //vL = vR;
-              tL = tR;
-            }
-            j++;
-          }
-          if(!found) {
-            vR = v1;
-            tR = tE;
-          }
-          // linear interpolation between tL and tR
-          double uloc, vloc;
-          uloc = itL->second.x() + (tLoc-tL)/(tR-tL) * (itR->second.x()-itL->second.x());
-          vloc = itL->second.y() + (tLoc-tL)/(tR-tL) * (itR->second.y()-itL->second.y());
-          return SPoint2(uloc,vloc);
-        }
-      }
-
-  }
-
-  // never here
-  return SPoint2(0, 0);
-}
-
-void GFaceCompound::parametrize(iterationStep step, typeOfMapping tom) const
-{
-  linearSystem<double> *lsys;
-
-  if (tom==HARMONIC){
-#if defined(HAVE_TAUCS)
-    lsys = new linearSystemCSRTaucs<double>;
-#elif defined(HAVE_PETSC)
-    lsys = new linearSystemPETSc<double>;
-#elif defined(HAVE_GMM)
-    linearSystemGmm<double> *lsysb = new linearSystemGmm<double>;
-    lsysb->setGmres(1);
-    lsys = lsysb;
-#else
-    lsys = new linearSystemFull<double>;
-#endif
-  }
-  else{
-#if defined(HAVE_PETSC)
-    lsys = new linearSystemPETSc<double>;
-    lsys->setParameter("petscOptions",
-    "-pc_type ilu -ksp_rtol 1.e-12 -pc_factor_levels 10");
-
-    //    lsys->setParameter("petscOptions",
-    //    		       "-ksp_type preonly -pc_type lu -pc_factor_mat_solver_package umfpack");
-#elif defined(HAVE_GMM)
-    linearSystemGmm<double> *lsysb = new linearSystemGmm<double>;
-    lsysb->setGmres(1);
-    lsys = lsysb;
-#else
-    lsys = new linearSystemFull<double>;
-#endif
-  }
-
-  dofManager<double> myAssembler(lsys);
-
-  if(_type == UNITCIRCLE){
-    for(unsigned int i = 0; i < _ordered.size(); i++){
-      MVertex *v = _ordered[i];
-      const double theta = 2 * M_PI * _coords[i];
-      if(step == ITERU) myAssembler.fixVertex(v, 0, 1, cos(theta));
-      else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, sin(theta));
-    }
-  }
-  else if(_type == SQUARE){
-    if(step == ITERU){
-      std::list<GEdge*>::const_iterator it = _U0.begin();
-      for( ; it != _U0.end(); ++it){
-	fixEdgeToValue(*it, 0.0, myAssembler);
-      }
-      it = _U1.begin();
-      for( ; it != _U1.end(); ++it){
-	fixEdgeToValue(*it, 1.0, myAssembler);
-      }
-    }
-    else if(step == ITERV){
-      std::list<GEdge*>::const_iterator it = _V0.begin();
-      for( ; it != _V0.end(); ++it){
-	fixEdgeToValue(*it, 0.0, myAssembler);
-      }
-      it = _V1.begin();
-      for( ; it != _V1.end(); ++it){
-	fixEdgeToValue(*it, 1.0, myAssembler);
-      }
-    }
-  }
-  else if (_type == MEANPLANE){
-    std::vector<SPoint3> points, pointsProj, pointsUV;
-    SPoint3 ptCG(0.0, 0.0, 0.0);
-    for(unsigned int i = 0; i < _ordered.size(); i++){
-      MVertex *v = _ordered[i];
-      points.push_back(SPoint3(v->x(), v->y(), v->z()));
-      ptCG[0] += v->x();
-      ptCG[1] += v->y();
-      ptCG[2] += v->z();
-    }
-
-    ptCG /= points.size();
-    mean_plane meanPlane;
-    computeMeanPlaneSimple(points, meanPlane);
-    projectPointsToPlane(points, pointsProj, meanPlane);
-    transformPointsIntoOrthoBasis(pointsProj, pointsUV, ptCG, meanPlane);
-
-    for(unsigned int i = 0; i < pointsUV.size(); i++){
-      MVertex *v = _ordered[i];
-      if(step == ITERU) myAssembler.fixVertex(v, 0, 1, pointsUV[i][0]);
-      else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, pointsUV[i][1]);
-    }
-  }
-  else if (_type == ALREADYFIXED){
-    for(unsigned int i = 0; i < _ordered.size(); i++){
-      MVertex *v = _ordered[i];
-      SPoint3 uv = coordinates[v];
-      if(step == ITERU) myAssembler.fixVertex(v, 0, 1, uv[0]);
-      else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, uv[1]);
-    }
-  }
-  else{
-    Msg::Error("Unknown type of parametrization");
-    return;
-  }
-
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  for( ; it != _compound.end(); ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      myAssembler.numberVertex(t->getVertex(0), 0, 1);
-      myAssembler.numberVertex(t->getVertex(1), 0, 1);
-      myAssembler.numberVertex(t->getVertex(2), 0, 1);
-    }
-  }
-
-  for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 !=fillTris.end(); it2++ ){
-    MTriangle *t = (*it2);
-    myAssembler.numberVertex(t->getVertex(0), 0, 1);
-    myAssembler.numberVertex(t->getVertex(1), 0, 1);
-    myAssembler.numberVertex(t->getVertex(2), 0, 1);
-  }
-
-  Msg::Debug("Creating term %d dofs numbered %d fixed",
-             myAssembler.sizeOfR(), myAssembler.sizeOfF());
-
-  double t1 = Cpu();
-
-  femTerm<double> *mapping;
-  if (tom == HARMONIC)
-    mapping = new laplaceTerm(0, 1, ONE);
-  else
-    mapping = new convexCombinationTerm(0, 1, ONE);
-
-  it = _compound.begin();
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      SElement se((*it)->triangles[i]);
-      mapping->addToMatrix(myAssembler, &se);
-    }
-  }
-
-  for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 !=fillTris.end(); it2++ ){
-    SElement se((*it2));
-    mapping->addToMatrix(myAssembler, &se);
-  }
-
-  double t2 = Cpu();
-  Msg::Debug("Assembly done in %8.3f seconds", t2 - t1);
-  lsys->systemSolve();
-  Msg::Debug("System solved");
-
-  for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    double value;
-    myAssembler.getDofValue(v, 0, 1, value);
-    std::map<MVertex*,SPoint3>::iterator itf = coordinates.find(v);
-    if(itf == coordinates.end()){
-      SPoint3 p(0, 0, 0);
-      p[step] = value;
-      coordinates[v] = p;
-    }
-    else{
-      itf->second[step]= value;
-    }
-  }
-
-  delete mapping;
-  delete lsys;
-}
-
-bool GFaceCompound::parametrize_conformal_spectral() const
-{
-#if !defined(HAVE_PETSC) && !defined(HAVE_SLEPC)
-  Msg::Warning("Slepc not installed: parametrization switched to 'FE conformal' map");
-  return parametrize_conformal(0, NULL, NULL);
-#else
-
-  linearSystem <double> *lsysA = new linearSystemPETSc<double>;
-  linearSystem <double> *lsysB = new linearSystemPETSc<double>;
-  dofManager<double> myAssembler(lsysA, lsysB);
-
-  myAssembler.setCurrentMatrix("A");
-  for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    myAssembler.numberVertex(v, 0, 1);
-    myAssembler.numberVertex(v, 0, 2);
-  }
-
-  for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    myAssembler.numberVertex(v, 0, 1);
-    myAssembler.numberVertex(v, 0, 2);
-  }
-
-  laplaceTerm laplace1(model(), 1, ONE);
-  laplaceTerm laplace2(model(), 2, ONE);
-  crossConfTerm cross12(model(), 1, 2, ONE);
-  crossConfTerm cross21(model(), 2, 1, MONE);
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      SElement se((*it)->triangles[i]);
-      laplace1.addToMatrix(myAssembler, &se);
-      laplace2.addToMatrix(myAssembler, &se);
-      cross12.addToMatrix(myAssembler, &se);
-      cross21.addToMatrix(myAssembler, &se);
-    }
-  }
-
-  for (std::list<MTriangle*>::iterator it2 = fillTris.begin(); it2 != fillTris.end(); it2++){
-    SElement se((*it2));
-    laplace1.addToMatrix(myAssembler, &se);
-    laplace2.addToMatrix(myAssembler, &se);
-    cross12.addToMatrix(myAssembler, &se);
-    cross21.addToMatrix(myAssembler, &se);
-  }
-
-  double epsilon = 1.e-6;
-  for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    if (std::find(_ordered.begin(), _ordered.end(), v) == _ordered.end() ){
-      myAssembler.assemble(v, 0, 1, v, 0, 1,  epsilon);
-      myAssembler.assemble(v, 0, 2, v, 0, 2,  epsilon);
-    }
-  }
-  for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    if (std::find(_ordered.begin(), _ordered.end(), v) == _ordered.end() ){
-      myAssembler.assemble(v, 0, 1, v, 0, 1,  epsilon);
-      myAssembler.assemble(v, 0, 2, v, 0, 2,  epsilon);
-    }
-  }
-
-  myAssembler.setCurrentMatrix("B");
-
-  // mettre max NC contraintes par bord
-  int NB = _ordered.size();
-  int NC = std::min(30,NB);
-  int jump = (int) NB/NC;
-  int nbLoop = (int) NB/jump ;
-  for (int i = 0; i< nbLoop; i++){
-    MVertex *v1 = _ordered[i*jump];
-    myAssembler.assemble(v1, 0, 1, v1, 0, 1,  1.0);
-    myAssembler.assemble(v1, 0, 2, v1, 0, 2,  1.0);
-    for (int j = 0; j< nbLoop; j++){
-      MVertex *v2 = _ordered[j*jump];
-      myAssembler.assemble(v1, 0, 1, v2, 0, 1,  -1./NC);
-      myAssembler.assemble(v1, 0, 2, v2, 0, 2,  -1./NC);
-    }
-  }
-
-  // FIXME: force non-hermitian. For some reason (roundoff errors?)
-  // on some machines and for some meshes slepc complains about bad IP
-  // norm otherwise
-  eigenSolver eig(&myAssembler, "B" , "A", false);
-
-  bool converged = eig.solve(1, "largest");
-
-  if(converged) {
-    double Linfty = 0.0;
-    int k = 0;
-    std::vector<std::complex<double> > &ev = eig.getEigenVector(0);
-    for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-      double paramu = ev[k].real();
-      double paramv = ev[k+1].real();
-      Linfty=std::max(Linfty, sqrt(paramu*paramu+paramv*paramv));
-      k = k+2;
-    }
-    k = 0;
-    for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-      MVertex *v = *itv;
-      double paramu = ev[k].real()/Linfty;
-      double paramv = ev[k+1].real()/Linfty;
-      coordinates[v] = SPoint3(paramu,paramv,0.0);
-      k = k+2;
-    }
-    delete lsysA;
-    delete lsysB;
-  }
-  else{
-    Msg::Warning("Slepc not converged: parametrization switched to 'FE conformal' map");
-    return parametrize_conformal(0,NULL,NULL);
-  }
-
-  std::vector<MVertex *> vert;
-  return checkOverlap(vert);
-#endif
-}
-
-bool GFaceCompound::parametrize_conformal(int iter, MVertex *v1, MVertex *v2) const
-{
-  linearSystem<double> *lsys;
-#if defined(HAVE_TAUCS)
-  lsys = new linearSystemCSRTaucs<double>;
-#elif defined(HAVE_PETSC)
-  lsys = new linearSystemPETSc<double>;
-#elif defined(HAVE_GMM)
-  linearSystemGmm<double> *lsysb = new linearSystemGmm<double>;
-  lsysb->setGmres(1);
-  lsys = lsysb;
-#else
-  lsys = new linearSystemFull<double>;
-#endif
-
-  dofManager<double> myAssembler(lsys);
-
-  if(!v1) v1 = _ordered[0];
-  if(!v2) v2 = _ordered[(int)ceil((double)_ordered.size()/2.)];
-  myAssembler.fixVertex(v1, 0, 1, 1.);
-  myAssembler.fixVertex(v1, 0, 2, 0.);
-  myAssembler.fixVertex(v2, 0, 1, -1.);
-  myAssembler.fixVertex(v2, 0, 2, 0.);
-
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  for( ; it != _compound.end(); ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      myAssembler.numberVertex(t->getVertex(0), 0, 1);
-      myAssembler.numberVertex(t->getVertex(1), 0, 1);
-      myAssembler.numberVertex(t->getVertex(2), 0, 1);
-      myAssembler.numberVertex(t->getVertex(0), 0, 2);
-      myAssembler.numberVertex(t->getVertex(1), 0, 2);
-      myAssembler.numberVertex(t->getVertex(2), 0, 2);
-    }
-  }
-  for (std::list<MTriangle*>::iterator it2 = fillTris.begin();
-       it2 !=fillTris.end(); it2++){
-    MTriangle *t = (*it2);
-    myAssembler.numberVertex(t->getVertex(0), 0, 1);
-    myAssembler.numberVertex(t->getVertex(1), 0, 1);
-    myAssembler.numberVertex(t->getVertex(2), 0, 1);
-    myAssembler.numberVertex(t->getVertex(0), 0, 2);
-    myAssembler.numberVertex(t->getVertex(1), 0, 2);
-    myAssembler.numberVertex(t->getVertex(2), 0, 2);
-  }
-
-  laplaceTerm laplace1(model(), 1, ONE);
-  laplaceTerm laplace2(model(), 2, ONE);
-  crossConfTerm cross12(model(), 1, 2, ONE);
-  crossConfTerm cross21(model(), 2, 1, MONE);
-  it = _compound.begin();
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      SElement se((*it)->triangles[i]);
-      laplace1.addToMatrix(myAssembler, &se);
-      laplace2.addToMatrix(myAssembler, &se);
-      cross12.addToMatrix(myAssembler, &se);
-      cross21.addToMatrix(myAssembler, &se);
-    }
-  }
-  for (std::list<MTriangle*>::iterator it2 = fillTris.begin();
-       it2 != fillTris.end(); it2++ ){
-    SElement se((*it2));
-    laplace1.addToMatrix(myAssembler, &se);
-    laplace2.addToMatrix(myAssembler, &se);
-    cross12.addToMatrix(myAssembler, &se);
-    cross21.addToMatrix(myAssembler, &se);
-  }
-
-  Msg::Debug("Assembly done");
-  lsys->systemSolve();
-  Msg::Debug("System solved");
-
-  for(std::set<MVertex *>::iterator itv = allNodes.begin();
-      itv != allNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    double value1, value2;
-    myAssembler.getDofValue(v, 0, 1, value1);
-    myAssembler.getDofValue(v, 0, 2, value2);
-    coordinates[v] = SPoint3(value1,value2,0.0);
-  }
-
-  delete lsys;
-
-  // check for overlap and compute new mapping with new pinned
-  // vertices
-  std::vector<MVertex *> vert;
-  bool hasOverlap = checkOverlap(vert);
-  return hasOverlap;
-  // if ( hasOverlap && iter < 3){
-  //   Msg::Info("Loop FE conformal iter (%d) v1=%d v2=%d", iter,
-  //             vert[0]->getNum(), vert[1]->getNum());
-  //   printStuff(100+iter);
-  //   return hasOverlap = parametrize_conformal(iter+1, vert[0],vert[1]);
-  // }
-  // else{
-  //   return hasOverlap;
-  // }
-}
-
-void GFaceCompound::computeNormals(std::map<MVertex*,SVector3> &normals) const
-{
-  computeNormals ();
-  normals = _normals;
-}
-
-void GFaceCompound::computeNormals() const
-{
-  _normals.clear();
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  double J[3][3];
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      t->getJacobian(0, 0, 0, J);
-      SVector3 n (J[2][0], J[2][1], J[2][2]);
-      n.normalize();
-      for(int j = 0; j < 3; j++){
-        std::map<MVertex*, SVector3>::iterator itn = _normals.find(t->getVertex(j));
-        if(itn == _normals.end())_normals[t->getVertex(j)] = n;
-        else itn->second += n;
-      }
-    }
-  }
-  std::map<MVertex*,SVector3>::iterator itn = _normals.begin();
-  for( ; itn != _normals.end() ; ++itn) itn->second.normalize();
-}
-
-double GFaceCompound::curvatureMax(const SPoint2 &param) const
-{
-  if(!oct) parametrize();
-  if(trivial()) {
-    return (*(_compound.begin()))->curvatureMax(param);
-  }
-
-  double U, V;
-  GFaceCompoundTriangle *lt;
-  getTriangle(param.x(), param.y(), &lt, U,V);
-
-  if(!lt) return 0.0;
-
-  if(lt->gf && lt->gf->geomType() != GEntity::DiscreteSurface) {
-    SPoint2 pv = lt->gfp1*(1.-U-V) + lt->gfp2*U + lt->gfp3*V;
-    return lt->gf->curvatureMax(pv);
-  }
-  else if (lt->gf->geomType() == GEntity::DiscreteSurface) {
-    Curvature& curvature = Curvature::getInstance();
-    if( !Curvature::valueAlreadyComputed() ) {
-      Msg::Info("Need to compute discrete curvature for isotropic remesh (in GFace)");
-      Curvature::typeOfCurvature type = Curvature::RUSIN;
-      curvature.computeCurvature(model(), type);
-    }
-    double c0,c1,c2;
-    curvature.triangleNodalValues(lt->tri,c0, c1, c2, 1);
-    double cv = (1-U-V)*c0 + U*c1 + V*c2;
-    return cv;
-  }
-
-  return 0.;
-}
-
-double GFaceCompound::curvatures(const SPoint2 &param, SVector3 *dirMax, SVector3 *dirMin,
-                                 double *curvMax, double *curvMin) const
-{
-  if(!oct) parametrize();
-  if(trivial()) {
-    return (*(_compound.begin()))->curvatures(param, dirMax,dirMin, curvMax, curvMin);
-  }
-
-  double U, V;
-  GFaceCompoundTriangle *lt;
-  getTriangle(param.x(), param.y(), &lt, U,V);
-
-  if(!lt) return 0.0;
-
-  if(lt->gf && lt->gf->geomType() != GEntity::DiscreteSurface){
-    SPoint2 pv = lt->gfp1*(1.-U-V) + lt->gfp2*U + lt->gfp3*V;
-    return lt->gf->curvatures(pv, dirMax,dirMin, curvMax, curvMin);
-  }
-  else if (lt->gf->geomType() == GEntity::DiscreteSurface){
-    Curvature& curvature = Curvature::getInstance();
-    if( !Curvature::valueAlreadyComputed() ) {
-      Msg::Info("Need to compute discrete curvature for anisotropic remesh (in GFace)");
-      Curvature::typeOfCurvature type = Curvature::RUSIN; //RBF
-      curvature.computeCurvature(model(), type);
-    }
-
-    double cMin[3];
-    double cMax[3];
-    SVector3 dMin[3];
-    SVector3 dMax[3];
-    curvature.triangleNodalValuesAndDirections(lt->tri, dMax, dMin, cMax, cMin, 0);
-    //curvature.triangleNodalValuesAndDirections(lt->tri, dMax, dMin, cMax, cMin, 1);
-
-    *dirMax = (1-U-V)*dMax[0] + U*dMax[1] + V*dMax[2];
-    *dirMin = (1-U-V)*dMin[0] + U*dMin[1] + V*dMin[2];
-    *curvMax = (1-U-V)*cMax[0] + U*cMax[1] + V*cMax[2];
-    *curvMin = (1-U-V)*cMin[0] + U*cMin[1] + V*cMin[2];
-
-    return *curvMax;
-  }
-  return 0.;
-}
-
-double GFaceCompound::locCurvature(MTriangle *t, double u, double v) const
-{
-  SVector3 n1 = _normals[t->getVertex(0)];
-  SVector3 n2 = _normals[t->getVertex(1)];
-  SVector3 n3 = _normals[t->getVertex(2)];
-  double val[9] = {n1.x(), n2.x(), n3.x(),
-                   n1.y(), n2.y(), n3.y(),
-                   n1.z(), n2.z(), n3.z()};
-  return fabs(t->interpolateDiv(val, u, v, 3));
-}
-
-SPoint2 GFaceCompound::parFromVertex(MVertex *v) const
-{
-  double U=0.0,V=0.0;
-  if(v->onWhat()->dim()==2){
-    v->getParameter(0, U);
-    v->getParameter(1, V);
-  }
-  if (v->onWhat()->dim()==1 ||
-     (v->onWhat()->dim()==2 &&
-      U == -1 && V==-1)){ //if MFaceVertex created on edge in bunin
-    SPoint2 sp = getCoordinates(v);
-    U = sp.x();
-    V = sp.y();
-  }
-  if (v->onWhat()->dim()==0){
-    SPoint2 sp = parFromPoint(SPoint3(v->x(), v->y(), v->z()));
-    U = sp.x();
-    V = sp.y();
-  }
-  return SPoint2(U,V);
-
-}
-SPoint2 GFaceCompound::parFromPoint(const SPoint3 &p, bool onSurface) const
-{
-  if(!oct) parametrize();
-
-  std::map<SPoint3,SPoint3>::const_iterator it = _coordPoints.find(p);
-  SPoint3 sp = it->second;
-
-  return SPoint2(sp.x(), sp.y());
-}
-
-GPoint GFaceCompound::pointInRemeshedOctree(double par1, double par2) const
-{
-
-  //create new octree with new mesh elements
-  if(!octNew){
-    std::vector<MElement *> myElems;
-    for (unsigned int i = 0; i < triangles.size(); i++) myElems.push_back(triangles[i]);
-    for (unsigned int i = 0; i < quadrangles.size(); i++) myElems.push_back(quadrangles[i]);
-
-    std::set<SPoint2> myBCNodes;
-    for (unsigned int i = 0; i < myElems.size(); i++){
-      MElement *e = myElems[i];
-      MVertex *news[4];
-      for (int j = 0; j < e->getNumVertices(); j++){
-	MVertex *v = e->getVertex(j);
-	std::map<MVertex*,MVertex*>::iterator it = _3Dto2D.find(v);
-	MVertex *newv =0;
-	if (it == _3Dto2D.end()){
-	  SPoint2 p = parFromVertex(v);
-	  newv = new MVertex (p.x(), p.y(), 0.0);
-	  myParamVert.push_back(newv);
-	  _3Dto2D[v] = newv;
-	  _2Dto3D[newv] = v;
-	  if(v->onWhat()->dim()<2) myBCNodes.insert(p);
-	}
-	else newv = it->second;
-	news[j] = newv;
-      }
-
-      if(e->getType() == TYPE_TRI)
-  	myParamElems.push_back(new MTriangle(news[0],news[1],news[2],e->getNum()));
-      else if (e->getType() == TYPE_QUA) {
-  	myParamElems.push_back(new MQuadrangle(news[0],news[1],news[2],news[3],e->getNum()));
-      }
-    }
-
-    octNew = new MElementOctree(myParamElems);
-
-    //build kdtree boundary nodes in parametric space
-    int nbBCNodes  = myBCNodes.size();
-    ANNpointArray uv_nodes = annAllocPts(nbBCNodes, 3);
-    std::set<SPoint2>::iterator itp = myBCNodes.begin();
-    int ind = 0;
-    while (itp != myBCNodes.end()){
-      SPoint2 pt = *itp;
-      uv_nodes[ind][0] = pt.x();
-      uv_nodes[ind][1] = pt.y();
-      uv_nodes[ind][2] = 0.0;
-      itp++; ind++;
-    }
-    uv_kdtree = new ANNkd_tree(uv_nodes, nbBCNodes, 3);
-  }
-
-  //now use new octree to find point
-  double uvw[3]={par1,par2, 0.0};
-  double UV[3];
-  MElement *e = octNew->find(par1,par2, 0.0,-1,false);
-  if (e){
-    e->xyz2uvw(uvw,UV);
-    double valX[8], valY[8], valZ[8];
-    for (int i=0;i<e->getNumPrimaryVertices();i++){
-      MVertex *v = _2Dto3D[e->getVertex(i)];
-      valX[i] = v->x();
-      valY[i] = v->y();
-      valZ[i] = v->z();
-    }
-    GPoint gp;
-    gp.x() = e->interpolate(valX,UV[0],UV[1],UV[2]);
-    gp.y() = e->interpolate(valY,UV[0],UV[1],UV[2]);
-    gp.z() = e->interpolate(valZ,UV[0],UV[1],UV[2]);
-    return gp;
-  }
-  //if element not found in new octree find closest point
-  else{
-    GPoint gp(50,50,50);
-    double pt[3] = {par1,par2,0.0};
-    ANNidx index[2];
-    ANNdist dist[2];
-    uv_kdtree->annkSearch(pt, 2, index, dist);
-    ANNpointArray uv_nodes = uv_kdtree->thePoints();
-    SPoint3  p1(uv_nodes[index[0]][0], uv_nodes[index[0]][1], uv_nodes[index[0]][2]);
-    SPoint3  p2(uv_nodes[index[1]][0], uv_nodes[index[1]][1], uv_nodes[index[1]][2]);
-    SPoint3 pnew; double d;
-    signedDistancePointLine(p1,p2, SPoint3(par1,par2,0.0), d, pnew);
-
-    double uvw[3]={pnew.x(),pnew.y(), 0.0};
-    double UV[3];
-    MElement *e = octNew->find(pnew.x(), pnew.y(), 0.0,-1,true);
-    if(!e)    e = octNew->find(p1.x(), p1.y(), 0.0,-1,true);
-    if( e){
-      e->xyz2uvw(uvw,UV);
-      double valX[8], valY[8], valZ[8];
-      for (int i=0;i<e->getNumPrimaryVertices();i++){
-	MVertex *v = _2Dto3D[e->getVertex(i)];
-	valX[i] = v->x();
-	valY[i] = v->y();
-	valZ[i] = v->z();
-      }
-      gp.x() = e->interpolate(valX,UV[0],UV[1],UV[2]);
-      gp.y() = e->interpolate(valY,UV[0],UV[1],UV[2]);
-      gp.z() = e->interpolate(valZ,UV[0],UV[1],UV[2]);
-    }
-    else{
-      gp.setNoSuccess();
-    }
-
-    if (gp.succeeded()) return gp;
-    else{
-      Msg::Error("NOT found point with ANN %g %g", par1, par2);
-      GPoint gp (30,30,30,this);
-      gp.setNoSuccess();
-      return gp;
-    }
-  }
-}
-
-GPoint GFaceCompound::point(double par1, double par2) const
-{
-  if(trivial()){
-    return (*(_compound.begin()))->point(par1,par2);
-  }
-
-  if(!oct) parametrize();
-
-  double U,V;
-  double par[2] = {par1,par2};
-  GFaceCompoundTriangle *lt;
-  getTriangle(par1, par2, &lt, U,V);
-  if(!lt){
-    if (meshStatistics.status == GFace::DONE && triangles.size()+quadrangles.size() != 0) {
-      GPoint gp = pointInRemeshedOctree(par1,par2);
-      gp.setNoSuccess();
-      return gp;
-    }
-    else{
-      double pt[3] = {par1,par2, 0.0};
-      ANNidx index[2];
-      ANNdist dist[2];
-      kdtree->annkSearch(pt, 1, index, dist);
-      lt = &(_gfct[index[0]]);
-
-      SPoint3 pnew_a, pnew_b, pnew_c; double d_a, d_b, d_c;
-      signedDistancePointLine(lt->p1,lt->p2, SPoint3(par1,par2,0.0), d_a, pnew_a);
-      signedDistancePointLine(lt->p1,lt->p3, SPoint3(par1,par2,0.0), d_b, pnew_b);
-      signedDistancePointLine(lt->p2,lt->p3, SPoint3(par1,par2,0.0), d_c, pnew_c);
-      double u,v;
-      if (d_a <= d_b && d_a <= d_c)      {  u = pnew_a.x(); v= pnew_a.y();}
-      else if (d_b <= d_a && d_b <= d_c) {  u = pnew_b.x(); v= pnew_b.y();}
-      else                               {  u = pnew_c.x(); v= pnew_c.y();}
-      double M[2][2],X[2],R[2];
-      const SPoint3 p0 = (lt)->p1;
-      const SPoint3 p1 = (lt)->p2;
-      const SPoint3 p2 = (lt)->p3;
-      M[0][0] = p1.x() - p0.x();
-      M[0][1] = p2.x() - p0.x();
-      M[1][0] = p1.y() - p0.y();
-      M[1][1] = p2.y() - p0.y();
-      R[0] = (u - p0.x());
-      R[1] = (v - p0.y());
-      sys2x2(M, R, X);
-      U = X[0];
-      V = X[1];
-    }
-  }
-
-  if (lt->gf->geomType() != GEntity::DiscreteSurface){
-    SPoint2 pParam = lt->gfp1*(1.-U-V) + lt->gfp2*U + lt->gfp3*V;
-    GPoint pp = lt->gf->point(pParam);
-    return GPoint(pp.x(),pp.y(),pp.z(),this,par);
-  }
-
-  const bool LINEARMESH = true; //false
-  if(LINEARMESH){
-    // linear Lagrange mesh
-    SPoint3 p = lt->v1*(1.-U-V) + lt->v2*U + lt->v3*V;
-    return GPoint(p.x(),p.y(),p.z(),this,par);
-  }
-  else{
-    // curved PN triangle
-    const SVector3 n1 = _normals[lt->tri->getVertex(0)];
-    const SVector3 n2 = _normals[lt->tri->getVertex(1)];
-    const SVector3 n3 = _normals[lt->tri->getVertex(2)];
-
-    SVector3 b300, b030, b003;
-    SVector3 b210, b120, b021, b012, b102, b201, E, VV, b111;
-    b300 = lt->v1;
-    b030 = lt->v2;
-    b003 = lt->v3;
-
-    // tagged PN triangles (sigma=1)
-    double theta = 0.0;
-    SVector3 d1 = lt->v1+.33*(1-theta)*(lt->v2-lt->v1);
-    SVector3 d2 = lt->v2+.33*(1-theta)*(lt->v1-lt->v2);
-    SVector3 X1 = 1/norm(n1)*n1;
-    SVector3 X2 = 1/norm(n2)*n2;
-    b210 = d1 - dot(X1,d1-lt->v1)*X1;
-    b120 = d2 - dot(X2,d2-lt->v2)*X2;
-    SVector3 d3 = lt->v2+.33*(1-theta)*(lt->v3-lt->v2);
-    SVector3 d4 = lt->v3+.33*(1-theta)*(lt->v2-lt->v3);
-    SVector3 X3 = 1/norm(n2)*n2;
-    SVector3 X4 = 1/norm(n3)*n3;
-    b021 = d3 - dot(X3,d3-lt->v2)*X3;
-    b012 = d4 - dot(X4,d4-lt->v3)*X4;
-    SVector3 d5 = lt->v3+.33*(1-theta)*(lt->v1-lt->v3);
-    SVector3 d6 = lt->v1+.33*(1-theta)*(lt->v3-lt->v1);
-    SVector3 X5 = 1/norm(n3)*n3;
-    SVector3 X6 = 1/norm(n1)*n1;
-    b102 = d5 - dot(X5,d5-lt->v3)*X5;
-    b201 = d6 - dot(X6,d6-lt->v1)*X6;
-
-    E=(b210+b120+b021+b012+b102+b201)*0.16667;
-    VV=(lt->v1+lt->v2+lt->v3)*0.333;
-    b111=E+(E-VV)*0.5;
-
-    double W = 1-U-V;
-    SVector3 point = b300*W*W*W+b030*U*U*U+b003*V*V*V+
-      b210*3.*W*W*U+b120*3.*W*U*U+b201*3.*W*W*V+
-      b021*3.*U*U*V+b102*3.*W*V*V+b012*3.*U*V*V+
-      b111*6.*W*U*V;
-
-    SPoint3 PP(point.x(), point.y(), point.z());
-    return GPoint(PP.x(),PP.y(),PP.z(),this,par);
-  }
-}
-
-Pair<SVector3,SVector3> GFaceCompound::firstDer(const SPoint2 &param) const
-{
-
-  if(!oct) parametrize();
-
-  if(trivial())
-    return (*(_compound.begin()))->firstDer(param);
-
-  double U,V;
-  GFaceCompoundTriangle *lt;
-  getTriangle(param.x(), param.y(), &lt, U,V);
-  MTriangle *tri=NULL;
-  if (lt) tri = lt->tri;
-  else {
-    double pt[3] = {param.x(), param.y(), 0.0};
-    ANNidx index[2];
-    ANNdist dist[2];
-    kdtree->annkSearch(pt, 1, index, dist);
-    tri = (&_gfct[index[0]])->tri;
-  }
-
-  SVector3 dXdu1 = firstDerivatives[tri->getVertex(0)].first();
-  SVector3 dXdu2 = firstDerivatives[tri->getVertex(1)].first();
-  SVector3 dXdu3 = firstDerivatives[tri->getVertex(2)].first();
-  SVector3 dXdv1 = firstDerivatives[tri->getVertex(0)].second();
-  SVector3 dXdv2 = firstDerivatives[tri->getVertex(1)].second();
-  SVector3 dXdv3 = firstDerivatives[tri->getVertex(2)].second();
-  SVector3 dXdu = dXdu1*(1.-U-V) + dXdu2*U + dXdu3*V;
-  SVector3 dXdv = dXdv1*(1.-U-V) + dXdv2*U + dXdv3*V;
-  return Pair<SVector3, SVector3>(dXdu,dXdv);
-}
-
-void GFaceCompound::secondDer(const SPoint2 &param,
-                              SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const
-{
-#if defined(HAVE_MESH)
-
-  if(!oct) parametrize();
-
-  if(adjv.size() == 0){
-    std::vector<MTriangle*> allTri;
-    std::list<GFace*>::const_iterator it = _compound.begin();
-    for( ; it != _compound.end(); ++it){
-      allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() );
-    }
-    buildVertexToTriangle(allTri, adjv);
-  }
-
-  if (xuu.size() == 0) computeHessianMapping();
-
-  double U, V;
-  GFaceCompoundTriangle *lt;
-  getTriangle(param.x(), param.y(), &lt, U,V);
-  if(!lt) return;
-
-  MVertex* v0 = lt->tri->getVertex(0);
-  MVertex* v1 = lt->tri->getVertex(1);
-  MVertex* v2 = lt->tri->getVertex(2);
-
-  *dudu = (1-U-V)*xuu[v0] + U*xuu[v1] + V*xuu[v2];
-  *dvdv = (1-U-V)*xvv[v0] + U*xvv[v1] + V*xvv[v2];
-  *dudv = (1-U-V)*xuv[v0] + U*xuv[v1] + V*xuv[v2];
-
-#endif
-  //Msg::Debug("Computation of the second derivatives is not implemented for compound faces");
-}
-
-void GFaceCompound::computeHessianMapping() const
-{
-#if defined(HAVE_MESH)
-  unsigned int sysDim = 6; //for 2D
-  unsigned int minNbPtBlob = 3*sysDim;
-  for (v2t_cont::iterator it = adjv.begin(); it != adjv.end(); it++) {
-    MVertex *ver = it->first;
-    std::vector<MVertex*> vv = getBlob(minNbPtBlob, it, adjv);
-    fullMatrix<double> A(vv.size(),sysDim), ATAx(sysDim,sysDim);
-    fullMatrix<double> ATAy(sysDim,sysDim), ATAz(sysDim,sysDim);
-    fullVector<double> bx(vv.size()), ATbx(sysDim), coeffsx(sysDim);
-    fullVector<double> by(vv.size()), ATby(sysDim), coeffsy(sysDim);
-    fullVector<double> bz(vv.size()), ATbz(sysDim), coeffsz(sysDim);
-    for(unsigned int i=0; i<vv.size(); i++) {
-      SPoint3 uv = coordinates[vv[i]];
-      A(i,0) = uv.x()*uv.x(); A(i,1) = uv.x()*uv.y(); A(i,2) = uv.y()*uv.y();
-      A(i,3) = uv.x(); A(i,4) = uv.y(); A(i,5) = 1.;
-      bx(i) = vv[i]->x();
-      by(i) = vv[i]->y();
-      bz(i) = vv[i]->z();
-    }
-    ATAx.gemm(A,A,1.,0., true, false);
-    ATAy = ATAx; ATAz = ATAx;
-    A.multWithATranspose(bx,1.,0.,ATbx);
-    A.multWithATranspose(by,1.,0.,ATby);
-    A.multWithATranspose(bz,1.,0.,ATbz);
-    ATAx.luSolve(ATbx,coeffsx);
-    ATAy.luSolve(ATby,coeffsy);
-    ATAz.luSolve(ATbz,coeffsz);
-    SPoint3 uv = coordinates[ver];
-    xuu[ver] = SVector3(2.*coeffsx(0),2.*coeffsy(0),2.*coeffsz(0)) ;
-    xvv[ver] = SVector3(2.*coeffsx(2),2.*coeffsy(2),2.*coeffsz(2)) ;
-    xuv[ver] = SVector3(coeffsx(1), coeffsy(1),coeffsz(1));
-    xu[ver]  = SVector3(2.*coeffsx(0)*uv.x()+coeffsx(1)*uv.y()+coeffsx(3),
-			2.*coeffsy(0)*uv.x()+coeffsy(1)*uv.y()+coeffsy(3),
-			2.*coeffsz(0)*uv.x()+coeffsz(1)*uv.y()+coeffsz(3));
-    xv[ver] = SVector3(coeffsx(1)*uv.x()+2.*coeffsx(2)*uv.y()+coeffsx(4),
-		       coeffsy(1)*uv.x()+2.*coeffsy(2)*uv.y()+coeffsy(4),
-		       coeffsz(1)*uv.x()+2.*coeffsz(2)*uv.y()+coeffsz(4));
-  }
-
-#endif
-}
-
-static void GFaceCompoundBB(void *a, double*mmin, double*mmax)
-{
-  GFaceCompoundTriangle *t = (GFaceCompoundTriangle *)a;
-  mmin[0] = std::min(std::min(t->p1.x(), t->p2.x()), t->p3.x());
-  mmin[1] = std::min(std::min(t->p1.y(), t->p2.y()), t->p3.y());
-  mmax[0] = std::max(std::max(t->p1.x(), t->p2.x()), t->p3.x());
-  mmax[1] = std::max(std::max(t->p1.y(), t->p2.y()), t->p3.y());
-  mmin[2] = -1;
-  mmax[2] = 1;
-
-  const double dx = mmax[0] - mmin[0];
-  const double dy = mmax[1] - mmin[1];
-  const double eps = 0.0;//1.e-12;
-  mmin[0] -= eps*dx;
-  mmin[1] -= eps*dy;
-  mmax[0] += eps*dx;
-  mmax[1] += eps*dy;
-}
-
-static void GFaceCompoundCentroid(void *a, double*c)
-{
-  GFaceCompoundTriangle *t = (GFaceCompoundTriangle *)a;
-  c[0] = (t->p1.x() + t->p2.x() + t->p3.x()) / 3.0;
-  c[1] = (t->p1.y() + t->p2.y() + t->p3.y()) / 3.0;
-  c[2] = 0.0;
-}
-
-static int GFaceCompoundInEle(void *a, double*c)
-{
-  GFaceCompoundTriangle *t = (GFaceCompoundTriangle *)a;
-  double M[2][2], R[2], X[2];
-  const double eps = 1.e-8;
-  const SPoint3 p0 = t->p1;
-  const SPoint3 p1 = t->p2;
-  const SPoint3 p2 = t->p3;
-  M[0][0] = p1.x() - p0.x();
-  M[0][1] = p2.x() - p0.x();
-  M[1][0] = p1.y() - p0.y();
-  M[1][1] = p2.y() - p0.y();
-  R[0] = (c[0] - p0.x());
-  R[1] = (c[1] - p0.y());
-  sys2x2(M, R, X);
-  if(X[0] > -eps && X[1] > -eps && 1. - X[0] - X[1] > -eps){
-    return 1;
-  }
-  return 0;
-}
-
-void GFaceCompound::getTriangle(double u, double v,
-                                GFaceCompoundTriangle **lt,
-                                double &_u, double &_v) const
-{
-  double uv[3] = {u, v, 0};
-  *lt = (GFaceCompoundTriangle*)Octree_Search(uv, oct);
-
-  if(!(*lt)){
-    _u = 0.0; _v = 0.0;
-    return;
-  }
-
-  double M[2][2],X[2],R[2];
-  const SPoint3 p0 = (*lt)->p1;
-  const SPoint3 p1 = (*lt)->p2;
-  const SPoint3 p2 = (*lt)->p3;
-  M[0][0] = p1.x() - p0.x();
-  M[0][1] = p2.x() - p0.x();
-  M[1][0] = p1.y() - p0.y();
-  M[1][1] = p2.y() - p0.y();
-  R[0] = (u - p0.x());
-  R[1] = (v - p0.y());
-  sys2x2(M, R, X);
-  _u = X[0];
-  _v = X[1];
-}
-
-void GFaceCompound::buildOct() const
-{
-#if defined(HAVE_MESH)
-  SBoundingBox3d bb;
-  int count = 0;
-  std::list<GFace*>::const_iterator it = _compound.begin();
-
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      //create bounding box
-      for(int j = 0; j < 3; j++){
-        std::map<MVertex*,SPoint3>::const_iterator itj = coordinates.find(t->getVertex(j));
-        _coordPoints.insert(std::make_pair(t->getVertex(j)->point(), itj->second));
-        bb += SPoint3(itj->second.x(),itj->second.y(),0.0);
-      }
-      count++;
-    }
-  }
-
-  //ANN octree
-  std::set<MVertex*> allVS;
-  ANNpointArray nodes = annAllocPts(count, 3);
-
-  // make bounding box
-  SPoint3 bbmin = bb.min(), bbmax = bb.max();
-  double origin[3] = {bbmin.x(), bbmin.y(), bbmin.z()};
-  double ssize[3] = {bbmax.x() - bbmin.x(),
-                     bbmax.y() - bbmin.y(),
-                     bbmax.z() - bbmin.z()};
-
-  _gfct = new GFaceCompoundTriangle[count];
-  const int maxElePerBucket = 15;
-  oct = Octree_Create(maxElePerBucket, origin, ssize, GFaceCompoundBB,
-                      GFaceCompoundCentroid, GFaceCompoundInEle);
-  std::map<MElement*, Pair<SVector3,SVector3> > firstElemDerivatives;
-
-  it = _compound.begin();
-  count = 0;
-
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      std::map<MVertex*,SPoint3>::const_iterator it0 =
-        coordinates.find(t->getVertex(0));
-      std::map<MVertex*,SPoint3>::const_iterator it1 =
-        coordinates.find(t->getVertex(1));
-      std::map<MVertex*,SPoint3>::const_iterator it2 =
-        coordinates.find(t->getVertex(2));
-      _gfct[count].p1 = it0->second;
-      _gfct[count].p2 = it1->second;
-      _gfct[count].p3 = it2->second;
-       if((*it)->geomType() != GEntity::DiscreteSurface){
-	// take care of the seam !!!!
-	if (t->getVertex(0)->onWhat()->dim() == 2){
-	  reparamMeshEdgeOnFace(t->getVertex(0), t->getVertex(1), *it,
-                                _gfct[count].gfp1, _gfct[count].gfp2);
-	  reparamMeshEdgeOnFace(t->getVertex(0), t->getVertex(2), *it,
-                                _gfct[count].gfp1, _gfct[count].gfp3);
-	}
-	else if (t->getVertex(1)->onWhat()->dim() == 2){
-	  reparamMeshEdgeOnFace(t->getVertex(1), t->getVertex(0), *it,
-                                _gfct[count].gfp2, _gfct[count].gfp1);
-	  reparamMeshEdgeOnFace(t->getVertex(1), t->getVertex(2), *it,
-                                _gfct[count].gfp2, _gfct[count].gfp3);
-	}
-	else if (t->getVertex(2)->onWhat()->dim() == 2){
-	  reparamMeshEdgeOnFace(t->getVertex(2), t->getVertex(0), *it,
-                                _gfct[count].gfp3, _gfct[count].gfp1);
-	  reparamMeshEdgeOnFace(t->getVertex(2), t->getVertex(1), *it,
-                                _gfct[count].gfp3, _gfct[count].gfp2);
-	}
-	else {
-	  reparamMeshVertexOnFace(t->getVertex(0), *it, _gfct[count].gfp1);
-	  reparamMeshVertexOnFace(t->getVertex(1), *it, _gfct[count].gfp2);
-	  reparamMeshVertexOnFace(t->getVertex(2), *it, _gfct[count].gfp3);
-	}
-      }
-      _gfct[count].v1 = SPoint3(t->getVertex(0)->x(), t->getVertex(0)->y(),
-                                t->getVertex(0)->z());
-      _gfct[count].v2 = SPoint3(t->getVertex(1)->x(), t->getVertex(1)->y(),
-                                t->getVertex(1)->z());
-      _gfct[count].v3 = SPoint3(t->getVertex(2)->x(), t->getVertex(2)->y(),
-                                t->getVertex(2)->z());
-      _gfct[count].gf = *it;
-      _gfct[count].tri = t;
-
-      //compute first derivatives for every triangle
-      double mat[2][2] = {{_gfct[count].p2.x() - _gfct[count].p1.x(),
-			   _gfct[count].p3.x() - _gfct[count].p1.x()},
-			  {_gfct[count].p2.y() - _gfct[count].p1.y(),
-			   _gfct[count].p3.y() - _gfct[count].p1.y()}};
-      double inv[2][2];
-      inv2x2(mat, inv);
-      SVector3 dXdxi (_gfct[count].v2 - _gfct[count].v1);
-      SVector3 dXdeta(_gfct[count].v3 - _gfct[count].v1);
-      SVector3 dXdu(dXdxi * inv[0][0] + dXdeta * inv[1][0]);
-      SVector3 dXdv(dXdxi * inv[0][1] + dXdeta * inv[1][1]);
-      firstElemDerivatives[(MElement*)t] = Pair<SVector3,SVector3>(dXdu,dXdv);
-
-      // build ANN kdtree
-      nodes[count][0] = (it0->second.x() + it1->second.x() + it2->second.x())/3.0 ;
-      nodes[count][1] = (it0->second.y() + it1->second.y() + it2->second.y())/3.0 ;
-      nodes[count][2] = 0.0;
-
-      Octree_Insert(&_gfct[count], oct);
-      count++;
-    }
-  }
-  nbT = count;
-  Octree_Arrange(oct);
-
-  //smooth first derivatives at vertices
-  if(adjv.size() == 0){
-    std::vector<MTriangle*> allTri;
-    std::list<GFace*>::const_iterator it = _compound.begin();
-    for( ; it != _compound.end(); ++it){
-      allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() );
-    }
-    buildVertexToTriangle(allTri, adjv);
-  }
-  for(v2t_cont::iterator it = adjv.begin(); it!= adjv.end(); ++it){
-    MVertex *v = it->first;
-    std::vector<MElement*> vTri = it->second;
-    SVector3 dXdu(0.0), dXdv(0.0);
-    int nbTri = vTri.size();
-    for (int j = 0; j < nbTri; j++){
-      dXdu += firstElemDerivatives[vTri[j]].first();
-      dXdv += firstElemDerivatives[vTri[j]].second();
-    }
-    dXdu*= 1./nbTri;
-    dXdv*= 1./nbTri;
-    firstDerivatives[v] = Pair<SVector3, SVector3>(dXdu, dXdv);
-  }
-
-  //build ANN kdtree
-  kdtree = new ANNkd_tree(nodes, count, 3);
-
-  printStuff();
-#endif
-}
-
-bool GFaceCompound::checkTopology() const
-{
-  if (_mapping == RBF) return true;
-
-  bool correctTopo = true;
-  if(allNodes.empty()) buildAllNodes();
-
-  int Nb = _interior_loops.size();
-  int G  = genusGeom() ;
-
-  double H = getSizeH();
-  double D = H;
-  if (_interior_loops.size() > 0)    D =  getSizeBB(_U0);
-  int AR1 = (int) checkAspectRatio();
-  int AR2 = (int) floor(H/D+0.5);
-  int AR = std::max(AR1, AR2);
-
-  if (G != 0 || Nb < 1){
-    correctTopo = false;
-    nbSplit = std::max(G+2, 2);
-    Msg::Info("Wrong topology: Genus=%d, Nb boundaries=%d, AR=%g", G, Nb, H/D);
-    if (_allowPartition){
-      Msg::Info("-----------------------------------------------------------");
-      Msg::Info("--- Split surface %d in %d parts with Multilevel Mesh partitioner",
-                tag(), nbSplit);
-    }
-    else{
-      Msg::Fatal("For remeshing your geometry, you should enable the automatic "
-                 "remeshing algorithm. Add 'Mesh.RemeshAlgorithm=1;' in your "
-                 "geo file or through the Fltk window (Options > Mesh > General)");
-    }
-  }
-  else if (G == 0 && AR > AR_MAX){
-    correctTopo = false;
-    Msg::Info("Wrong topology: Aspect ratio is too high AR=%d (AR1=%d AR2=%d)",
-              AR, AR1, AR2);
-    if (_allowPartition == 1){
-      nbSplit = -2;
-      Msg::Info("-----------------------------------------------------------");
-      Msg::Info("--- Split surface %d in 2 parts with Laplacian Mesh partitioner",
-                tag());
-    }
-    else if (_allowPartition == 2){
-      nbSplit = 2;
-      Msg::Info("-----------------------------------------------------------");
-      Msg::Info("--- Split surface %d in %d parts with Multilevel Mesh partitioner",
-                tag(), nbSplit);
-    }
-    else if (_allowPartition == 0){
-      Msg::Debug("The geometrical aspect ratio of your geometry is quite high.\n "
-		 "You should enable partitioning of the mesh by activating the\n"
-		 "automatic remeshing algorithm. Add 'Mesh.RemeshAlgorithm=1;'\n "
-		 "in your geo file or through the Fltk window (Options > Mesh >\n "
-		 "General)");
-    }
-  }
-  else{
-    Msg::Debug("Correct topology: Genus=%d and Nb boundaries=%d, AR=%g", G, Nb, H/D);
-  }
-
-  return correctTopo;
-}
-
-double GFaceCompound::checkAspectRatio() const
-{
-  if(allNodes.empty()) buildAllNodes();
-
-  double limit =  1.e-20;
-  double areaMin = 1.e20;
-  double area3D = 0.0;
-  int nb = 0;
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[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;
-      std::map<MVertex*,SPoint3>::const_iterator it0 = coordinates.find(v[0]);
-      std::map<MVertex*,SPoint3>::const_iterator it1 = coordinates.find(v[1]);
-      std::map<MVertex*,SPoint3>::const_iterator it2 = coordinates.find(v[2]);
-      if(it0 != coordinates.end() &&
-         it1 != coordinates.end() &&
-         it2 != coordinates.end()){
-        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};
-        double a_2D = fabs(triangle_area(q0, q1, q2));
-        if (a_2D > limit) nb++;
-        areaMin = std::min(areaMin, a_2D);
-      }
-    }
-  }
-
-  std::list<GEdge*>::const_iterator it0 = _U0.begin();
-  double tot_length = 0.0;
-  for( ; it0 != _U0.end(); ++it0 )
-    for(unsigned int i = 0; i < (*it0)->lines.size(); i++ )
-      tot_length += (*it0)->lines[i]->getLength();
-
-  double AR = M_PI*area3D/(tot_length*tot_length);
-
-  if (nb > 3 && areaMin > 0 && areaMin < limit) {
-    Msg::Warning("Too small triangles in mapping (a_2D=%g)", areaMin);
-  }
-  else {
-    Msg::Debug("Geometrical aspect ratio is OK :-)");
-  }
-
-  return AR;
-}
-
-void GFaceCompound::coherencePatches() const
-{
-  if (_mapping == RBF) return;
-  Msg::Info("Re-orient all %d compound patches normals coherently",
-            _compound.size());
-
-  std::map<MEdge, std::set<MElement*>, Less_Edge > edge2elems;
-  std::vector<MElement*> allElems;
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->getNumMeshElements(); ++i){
-      MElement *t =  (*it)->getMeshElement(i);
-      allElems.push_back(t);
-      for (int j = 0; j <  t->getNumEdges(); j++){
-	MEdge me = t->getEdge(j);
-	std::map<MEdge, std::set<MElement*, std::less<MElement*> >,
-		 Less_Edge >::iterator it = edge2elems.find(me);
-	if (it == edge2elems.end()) {
-	  std::set<MElement*, std::less<MElement*> > mySet;
-	  mySet.insert(t);
-	  edge2elems.insert(std::make_pair(me, mySet));
-	}
-	else{
-	  std::set<MElement*, std::less<MElement*> > mySet = it->second;
-	  mySet.insert(t);
-	  it->second = mySet;
-	}
-      }
-    }
-  }
-
-  std::set<MElement* , std::less<MElement*> > touched;
-  int iE, si, iE2, si2;
-  touched.insert(allElems[0]);
-  while(touched.size() != allElems.size()){
-    for(unsigned int i = 0; i < allElems.size(); i++){
-      MElement *t = allElems[i];
-      std::set<MElement*, std::less<MElement*> >::iterator it2 = touched.find(t);
-      if(it2 != touched.end()){
-	for (int j = 0; j <  t->getNumEdges(); j++){
-	  MEdge me = t->getEdge(j);
-	  t->getEdgeInfo(me, iE,si);
-	  std::map<MEdge, std::set<MElement*>, Less_Edge >::iterator it =
-	    edge2elems.find(me);
-	  std::set<MElement*, std::less<MElement*> > mySet = it->second;
-	  for(std::set<MElement*, std::less<MElement*> >::iterator itt = mySet.begin();
-	      itt != mySet.end(); itt++){
-	    if (*itt != t){
-	      (*itt)->getEdgeInfo(me,iE2,si2);
-	      if(si == si2) { (*itt)->reverse();}
-	      touched.insert(*itt);
-	    }
-	  }
-	}
-      }
-    }
-  }
-}
-
-void GFaceCompound::coherenceNormals()
-{
-  if(!getNumMeshElements()) return;
-  Msg::Info("Re-orient all %d face normals coherently", getNumMeshElements());
-
-  std::map<MEdge, std::set<MElement*>, Less_Edge > edge2elems;
-  for(unsigned int i = 0; i <  getNumMeshElements(); i++){
-    MElement *t =  getMeshElement(i);
-    for (int j = 0; j <  t->getNumEdges(); j++){
-      MEdge me = t->getEdge(j);
-      std::map<MEdge, std::set<MElement*, std::less<MElement*> >,
-        Less_Edge >::iterator it = edge2elems.find(me);
-      if (it == edge2elems.end()) {
-        std::set<MElement*, std::less<MElement*> > mySet;
-        mySet.insert(t);
-        edge2elems.insert(std::make_pair(me, mySet));
-      }
-      else{
-        std::set<MElement*, std::less<MElement*> > mySet = it->second;
-        mySet.insert(t);
-        it->second = mySet;
-      }
-    }
-  }
-
-  std::set<MElement* , std::less<MElement*> > touched;
-  int iE, si, iE2, si2;
-  touched.insert(getMeshElement(0));
-  while(touched.size() != getNumMeshElements()){
-    for(unsigned int i = 0; i < getNumMeshElements(); i++){
-      MElement *t = getMeshElement(i);
-      std::set<MElement*, std::less<MElement*> >::iterator it2 = touched.find(t);
-      if(it2 != touched.end()){
-        for (int j = 0; j <  t->getNumEdges(); j++){
-          MEdge me = t->getEdge(j);
-          t->getEdgeInfo(me, iE,si);
-          std::map<MEdge, std::set<MElement*>, Less_Edge >::iterator it =
-            edge2elems.find(me);
-          std::set<MElement*, std::less<MElement*> > mySet = it->second;
-          for(std::set<MElement*, std::less<MElement*> >::iterator itt = mySet.begin();
-              itt != mySet.end(); itt++){
-            if (*itt != t){
-              (*itt)->getEdgeInfo(me,iE2,si2);
-              if(si == si2)  (*itt)->reverse();
-              touched.insert(*itt);
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-void GFaceCompound::buildAllNodes() const
-{
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      for(int j = 0; j < 3; j++){
-        allNodes.insert(t->getVertex(j));
-      }
-    }
-  }
-}
-
-int GFaceCompound::genusGeom() const
-{
-  std::list<GFace*>::const_iterator it = _compound.begin();
-  std::set<MEdge, Less_Edge> es;
-  std::set<MVertex*> vs;
-  int N = 0;
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      N++;
-      MTriangle *e = (*it)->triangles[i];
-      for(int j = 0; j < e->getNumVertices(); j++){
-	vs.insert(e->getVertex(j));
-      }
-      for(int j = 0; j < e->getNumEdges(); j++){
-	es.insert(e->getEdge(j));
-      }
-    }
-  }
-  int poincare = vs.size() - es.size() + N;
-
-  return (int)(-poincare + 2 - _interior_loops.size())/2;
-}
-
-void GFaceCompound::printStuff(int iNewton) const
-{
-  if(!CTX::instance()->mesh.saveAll) return;
-
-  std::list<GFace*>::const_iterator it = _compound.begin();
-
-  char name0[256], name1[256], name2[256], name3[256];
-  char name4[256], name5[256], name6[256];
-  char name7[256];
-  sprintf(name0, "UVAREA-%d.pos", tag()); //(*it)->tag()
-  sprintf(name1, "UVX-%d_%d.pos", tag(), iNewton);
-  sprintf(name2, "UVY-%d_%d.pos", tag(), iNewton);
-  sprintf(name3, "UVZ-%d_%d.pos", tag(), iNewton);
-  sprintf(name4, "XYZU-%d_%d.pos", tag(), iNewton);
-  sprintf(name5, "XYZV-%d_%d.pos", tag(), iNewton);
-  sprintf(name6, "XYZC-%d.pos", tag());
-
-  sprintf(name7, "UVM-%d.pos", (*it)->tag());
-
-  FILE * uvx = Fopen(name1,"w");
-  if(!uvx){
-    Msg::Error("Could not open file '%s'", name1);
-    return;
-  }
-  FILE * uvy = Fopen(name2,"w");
-  if(!uvy){
-    fclose(uvx);
-    Msg::Error("Could not open file '%s'", name2);
-    return;
-  }
-  FILE * uvz = Fopen(name3,"w");
-  if(!uvz){
-    fclose(uvx);
-    fclose(uvy);
-    Msg::Error("Could not open file '%s'", name3);
-    return;
-  }
-  FILE * xyzu = Fopen(name4,"w");
-  if(!xyzu){
-    fclose(uvx);
-    fclose(uvy);
-    fclose(uvz);
-    Msg::Error("Could not open file '%s'", name4);
-    return;
-  }
-  FILE * xyzv = Fopen(name5,"w");
-  if(!xyzv){
-    fclose(uvx);
-    fclose(uvy);
-    fclose(uvz);
-    fclose(xyzu);
-    Msg::Error("Could not open file '%s'", name5);
-    return;
-  }
-
-  fprintf(uvx, "View \"\"{\n");
-  fprintf(uvy, "View \"\"{\n");
-  fprintf(uvz, "View \"\"{\n");
-  fprintf(xyzu, "View \"\"{\n");
-  fprintf(xyzv, "View \"\"{\n");
-
-  for( ; it != _compound.end() ; ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
-      MTriangle *t = (*it)->triangles[i];
-      std::map<MVertex*,SPoint3>::const_iterator it0 =
-        coordinates.find(t->getVertex(0));
-      std::map<MVertex*,SPoint3>::const_iterator it1 =
-        coordinates.find(t->getVertex(1));
-      std::map<MVertex*,SPoint3>::const_iterator it2 =
-        coordinates.find(t->getVertex(2));
-      fprintf(xyzv, "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(),
-              it0->second.y(),it1->second.y(),it2->second.y());
-      fprintf(xyzu, "ST(%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,"
-              "%22.15E,%22.15E){%22.15E,%22.15E,%22.15E};\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(),
-              it0->second.x(),it1->second.x(),it2->second.x());
-      fprintf(uvx, "ST(%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,"
-              "%22.15E,%22.15E){%22.15E,%22.15E,%22.15E};\n",
-              it0->second.x(), it0->second.y(), 0.0,
-              it1->second.x(), it1->second.y(), 0.0,
-              it2->second.x(), it2->second.y(), 0.0,
-              t->getVertex(0)->x(), t->getVertex(1)->x(), t->getVertex(2)->x());
-      fprintf(uvy, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
-              it0->second.x(), it0->second.y(), 0.0,
-              it1->second.x(), it1->second.y(), 0.0,
-              it2->second.x(), it2->second.y(), 0.0,
-              t->getVertex(0)->y(), t->getVertex(1)->y(), t->getVertex(2)->y());
-      fprintf(uvz, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
-              it0->second.x(), it0->second.y(), 0.0,
-              it1->second.x(), it1->second.y(), 0.0,
-              it2->second.x(), it2->second.y(), 0.0,
-              t->getVertex(0)->z(), t->getVertex(1)->z(), t->getVertex(2)->z());
-    }
-  }
-  fprintf(uvx,"};\n");
-  fclose(uvx);
-  fprintf(uvy,"};\n");
-  fclose(uvy);
-  fprintf(uvz,"};\n");
-  fclose(uvz);
-  fprintf(xyzu,"};\n");
-  fclose(xyzu);
-  fprintf(xyzv,"};\n");
-  fclose(xyzv);
-}
-
-// useful for mesh generators ----------------------------------------
-// Intersection of a circle and a plane
-GPoint GFaceCompound::intersectionWithCircle(const SVector3 &n1, const SVector3 &n2,
-                                             const SVector3 &p, const double &d,
-                                             double uv[2]) const
-{
-  SVector3 n = crossprod(n1,n2);
-  n.normalize();
-  for (int i=-1;i<nbT;i++){
-    GFaceCompoundTriangle *ct;
-    double U,V;
-    if (i == -1) getTriangle(uv[0],uv[1], &ct, U,V);
-    else ct = &_gfct[i];
-    if (!ct) continue;
-    // we have two planes, defined with n1,n2 and t1,t2
-    // we have then a direction m = (n1 x n2) x (t1 x t2)
-    // and a point p that defines a straight line
-    // the point is situated in the half plane defined
-    // by direction n1 and point p (exclude the one on the
-    // other side)
-
-    SVector3 t1  = ct->v2 - ct->v1;
-    SVector3 t2  = ct->v3 - ct->v1;
-
-    // let us first compute point q to be the intersection
-    // of the plane of the triangle with the line L = p + t n1
-    // Compute w = t1 x t2 = (a,b,c) and write a point of the plabe as
-    // X(x,y,z) = ax + by + cz - (v1_x a + v1_y b + v1_z * c) = 0
-    // Then
-    // a (p_x + t n1_x) + a (p_y + t n1_y) + c (p_z + t n1_z) -
-    //    (v1_x a + v1_y b + v1_z * c) = 0
-    // gives t
-
-    SVector3 w = crossprod(t1,t2);
-    double t = dot(ct->v1-p,w)/dot(n1,w);
-    SVector3 q = p + n1*t;
-
-    // consider the line that intersects both planes in its
-    // parametric form
-    // X(x,y,z) = q + t m
-    // We have now to intersect that line with the sphere
-    // (x-p_x)^2 + (y-p_y)^2 + (z-p_z)^2 = d^2
-    // Inserting the parametric form of the line into the sphere gives
-    // (t m_x + q_x - p_x)^2 + (t m_y + q_y - p_y)^2  + (t m_z + q_z - p_z)^2  = d^2
-    //  t^2 (m_x^2 + m_y^2 + m_z^2) + 2 t (m_x (q_x - p_x) + m_y (q_y - p_z) +
-    //   m_z (q_z - p_z)) + ((q_x - p_x)^2 + (q_y - p_y)^2 + (q_z - p_z)^2 - d^2) = 0
-    // t^2 m^2 + 2 t (m . (q-p)) + ((q-p)^2 - d^2) = 0
-    // Let us call ta and tb the two roots
-    // they correspond to two points s_1 = q + ta m and s_2 = q + tb m
-    // we choose the one that corresponds to (s_i - p) . n1 > 0
-    SVector3 m = crossprod(w,n);
-    const double a = dot(m,m);
-    const double b = 2*dot(m,q-p);
-    const double c = dot(q-p,q-p) - d*d;
-    const double delta = b*b-4*a*c;
-
-    if (delta >= 0){
-      const double ta = (-b + sqrt(delta)) / (2.*a);
-      const double tb = (-b - sqrt(delta)) / (2.*a);
-      SVector3 s1 = q + m * ta;
-      SVector3 s2 = q + m * tb;
-      SVector3 s;
-      if (dot(s1-p,n1) > 0){
-	s = s1;
-      }
-      else if (dot(s2-p,n1) > 0){
-	s = s2;
-      }
-      else continue;
-
-      // we have now to look if the point is inside the triangle
-      // s = v1 + u t1 + v t2
-      // we know the system has a solution because s is in the plane
-      // defined by v1 and v2 we solve then
-      // (s - v1) . t1 = u t1^2    + v t2 . t1
-      // (s - v1) . t2 = u t1 . t2 + v t2^2
-
-      double mat[2][2], b[2],uv[2];
-      mat[0][0] = dot(t1,t1);
-      mat[1][1] = dot(t2,t2);
-      mat[0][1] = mat[1][0] = dot(t1,t2);
-      b[0] = dot(s-ct->v1,t1) ;
-      b[1] = dot(s-ct->v1,t2) ;
-      sys2x2(mat,b,uv);
-      // check now if the point is inside the triangle
-      if (uv[0] >= -1.e-6 && uv[1] >= -1.e-6 &&
-	  1.-uv[0]-uv[1] >= -1.e-6 ) {
-	SVector3 pp =
-	  ct->p1 * ( 1.-uv[0]-uv[1] ) +
-	  ct->p2 *uv[0] +
-	  ct->p3 *uv[1] ;
-	return GPoint(s.x(),s.y(),s.z(),this,pp);
-      }
-    }
-  }
-  GPoint pp(0);
-  pp.setNoSuccess();
-  Msg::Debug("ARGG no success intersection circle");
-  return pp;
-}
-
-#endif
diff --git a/Geo/GFaceCompound.h b/Geo/GFaceCompound.h
deleted file mode 100644
index 38f61dbd24735f660a34a61970a570b5dbeac392..0000000000000000000000000000000000000000
--- a/Geo/GFaceCompound.h
+++ /dev/null
@@ -1,240 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-
-#ifndef _GFACE_COMPOUND_H_
-#define _GFACE_COMPOUND_H_
-
-#include <list>
-#include <map>
-#include "GmshConfig.h"
-#include "GmshMessage.h"
-#include "GFace.h"
-template <class scalar> class simpleFunction;
-
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-
-#include "GEdge.h"
-#include "GEdgeCompound.h"
-#include "meshGFaceOptimize.h"
-#include "linearSystem.h"
-#include "GRbf.h"
-#include "MElementOctree.h"
-class ANNkd_tree;
-
-#define AR_MAX 5 //maximal geometrical aspect ratio
-
-/*
-  A GFaceCompound is a model face that is the compound of model faces.
-
-  It is assumed that all the faces of the compound have been meshed
-  first. We use this discretization to solve elliptic problems on the
-  compound. Those problems enable to compute the parametric
-  coordinates of the mesh points. The parametrization of the compound
-  consist in a triangulation in the (u,v) space with parameter values at
-  nodes.
-
-  The compound can therefore be (re)-meshed using any surface mesh
-  generator of gmsh!
-*/
-
-class  GFaceCompoundTriangle {
- public:
-  SPoint3 p1, p2, p3;
-  SPoint2 gfp1, gfp2, gfp3;
-  SPoint3 v1, v2, v3;
-  GFace *gf;
-  MTriangle *tri;
-  GFaceCompoundTriangle() : gf(0), tri(0) {}
-};
-
-class Octree;
-class GRbf;
-
-class GFaceCompound : public GFace {
- public:
-  typedef enum {ITERU=0,ITERV=1,ITERD=2} iterationStep;
-  typedef enum {HARMONIC_CIRCLE=0, CONFORMAL_SPECTRAL=1, RADIAL_BASIS=2, HARMONIC_PLANE=3,
-		CONVEX_CIRCLE=4,CONVEX_PLANE=5, HARMONIC_SQUARE=6, CONFORMAL_FE=7} typeOfCompound;
-  typedef enum {HARMONIC=0,CONFORMAL=1, RBF=2, CONVEX=3} typeOfMapping;
-  typedef enum {UNITCIRCLE, MEANPLANE, SQUARE, ALREADYFIXED,SPECTRAL, FE} typeOfIsomorphism;
-  mutable int nbSplit;
-
- protected:
-  mutable std::set<MVertex *> ov;
-  mutable GRbf *_rbf;
-  simpleFunction<double> *ONE;
-  simpleFunction<double> *MONE;
-  std::list<GFace*> _compound;
-  std::list<GEdge*> _U0, _V0, _U1, _V1;
-  std::list<std::list<GEdge*> > _interior_loops;
-  mutable int nbT;
-  mutable GFaceCompoundTriangle *_gfct;
-  mutable Octree *oct;
-  mutable MElementOctree *octNew;
-  mutable std::vector<MVertex*> myParamVert;
-  mutable std::vector<MElement*> myParamElems;
-  mutable std::map<MVertex*,MVertex*> _3Dto2D;
-  mutable std::map<MVertex*,MVertex*> _2Dto3D;
-  mutable std::map<int,SPoint3> XYZoct;
-  mutable std::set<MVertex*> allNodes;
-  mutable v2t_cont adjv;
-  mutable std::map<MVertex*, SPoint3> coordinates;
-  mutable std::map<MVertex*, Pair<SVector3,SVector3> > firstDerivatives;
-  mutable std::map<MVertex*, SVector3> xuu;
-  mutable std::map<MVertex*, SVector3> xvv;
-  mutable std::map<MVertex*, SVector3> xuv;
-  mutable std::map<MVertex*, SVector3> xu;
-  mutable std::map<MVertex*, SVector3> xv;
-  mutable std::map<SPoint3,SPoint3 > _coordPoints;
-  mutable std::map<MVertex*, SVector3> _normals;
-  mutable std::list<MTriangle*> fillTris;
-  mutable std::set<MVertex*> fillNodes;
-  mutable std::vector<GFace*> fillFaces;
-  mutable std::vector<MVertex*> _ordered;
-  mutable std::vector<double> _coords;
-  mutable std::map<MVertex*, int> _mapV;
-  mutable ANNkd_tree *uv_kdtree;
-  mutable ANNkd_tree *kdtree;
-  void buildOct() const ;
-  void buildAllNodes() const;
-
-  //different type of parametrizations
-  void parametrize(iterationStep, typeOfMapping) const;
-  bool parametrize_conformal(int iter, MVertex *v1, MVertex *v2) const;
-  bool parametrize_conformal_spectral() const;
-
-  //check for parametrizations
-  bool checkOrientation(int iter, bool moveBoundaries=false) const;
-  bool checkOverlap(std::vector<MVertex *> &vert) const;
-  bool one2OneMap() const;
-  void convexBoundary(double nTot) const;
-  double checkAspectRatio() const;
-
-  //tools for filling interior holes of surfaces
-  void fillNeumannBCS() const;
-  void fillNeumannBCS_Plane() const;
-  void orientFillTris(std::list<MTriangle*> loopfillTris)const;
-  void printFillTris()const;
-
-  void computeNormals () const;
-  void getBoundingEdges();
-  void getUniqueEdges(std::set<GEdge*> &_unique);
-  void computeALoop(std::set<GEdge*> &_unique, std::list<GEdge*> &);
-
-  virtual double locCurvature(MTriangle *t, double u, double v) const;
-
-  double getSizeH() const;
-  double getSizeBB(const std::list<GEdge* > &elist) const;
-  bool trivial() const;
-  void printStuff(int iNewton=0) const;
-  void computeHessianMapping() const;
-
- public:
-  GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
-		std::list<GEdge*> &U0, typeOfCompound typ = HARMONIC_CIRCLE,
-		int allowPartition=1);
-  GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
-                std::list<GEdge*> &U0, std::list<GEdge*> &V0,
-                std::list<GEdge*> &U1, std::list<GEdge*> &V1,
-                typeOfCompound typ = HARMONIC_CIRCLE,
-                int allowPartition=1);
- ~GFaceCompound();
-  virtual void deleteMesh();
-
-  Range<double> parBounds(int i) const
-  { return trivial() ? (*(_compound.begin()))->parBounds(i) : Range<double>(-1, 1); }
-
-  using GFace::point;
-  GPoint point(double par1, double par2) const;
-  GPoint pointInRemeshedOctree(double par1, double par2) const;
-  SPoint2 parFromPoint(const SPoint3 &p, bool onSurface=true) const;
-  SPoint2 parFromVertex(MVertex *v) const;
-  virtual Pair<SVector3,SVector3> firstDer(const SPoint2 &param) const;
-  virtual void secondDer(const SPoint2 &, SVector3 *, SVector3 *, SVector3 *) const;
-  virtual GEntity::GeomType geomType() const { return CompoundSurface; }
-  ModelType getNativeType() const { return GmshModel; }
-  void * getNativePtr() const { return 0; }
-  void getTriangle(double u, double v, GFaceCompoundTriangle **lt,
-                   double &_u, double &_v) const;
-  virtual SPoint2 getCoordinates(MVertex *v) const;
-  virtual double curvatureMax(const SPoint2 &param) const;
-  virtual double curvatures(const SPoint2 &param, SVector3 *dirMax, SVector3 *dirMin,
-			    double *curvMax, double *curvMin) const;
-  bool parametrize() const;
-  void computeNormals(std::map<MVertex*, SVector3> &normals) const;
-  void coherenceNormals();
-  void coherencePatches() const;
-  virtual int genusGeom () const;
-  virtual bool checkTopology() const;
-
-  virtual std::list<GFace*> getCompounds() const { return _compound; }
-  typeOfCompound getTypeOfCompound() { return _toc;}
-  int getNbSplit() const { return nbSplit; }
-  int allowPartition() const{ return _allowPartition; }
-  void setType(typeOfIsomorphism type){ _type=type;}
-
-  // useful for mesh generators
-  GPoint intersectionWithCircle (const SVector3 &n1, const SVector3 &n2, const SVector3 &p,
-				 const double &d, double uv[2]) const;
-
-  void deleteInternals();
-	
- private:
-  void _deleteInternals();
-  mutable typeOfCompound _toc;
-  mutable typeOfMapping _mapping;
-  mutable typeOfIsomorphism _type;
-  int _allowPartition;
-};
-
-#else
-
-template<class scalar> class linearSystem;
-class GFaceCompound : public GFace {
- public:
-  typedef enum {ITERU=0,ITERV=1,ITERD=2} iterationStep;
-  typedef enum {HARMONIC_CIRCLE=0, CONFORMAL_SPECTRAL=1, RADIAL_BASIS=2, HARMONIC_PLANE=3,
-		CONVEX_CIRCLE=4,CONVEX_PLANE=5, HARMONIC_SQUARE=6, CONFORMAL_FE=7} typeOfCompound;
-  typedef enum {HARMONIC=0,CONFORMAL=1, RBF=2, CONVEX=3} typeOfMapping;
-  typedef enum {UNITCIRCLE, MEANPLANE, SQUARE, ALREADYFIXED,SPECTRAL, FE} typeOfIsomorphism;
-  GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
-                std::list<GEdge*> &U0, typeOfCompound typ = HARMONIC_CIRCLE,
-                int allowPartition=1)
-    : GFace(m, tag)
-  {
-    Msg::Error("Gmsh has to be compiled with Solver and ANN support to use GFaceCompounds");
-  }
-  GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
-                std::list<GEdge*> &U0, std::list<GEdge*> &V0,
-                std::list<GEdge*> &U1, std::list<GEdge*> &V1,
-                typeOfCompound typ = HARMONIC_CIRCLE,
-                int allowPartition=1)
-    : GFace(m, tag)
-  {
-    Msg::Error("Gmsh has to be compiled with Solver and ANN support to use GFaceCompounds");
-  }
-  virtual ~GFaceCompound() {}
-  virtual void deleteMesh() {}
-  using GFace::point;
-  GPoint point(double par1, double par2) const { return GPoint(); }
-  Pair<SVector3, SVector3> firstDer(const SPoint2 &param) const
-  {
-    return Pair<SVector3, SVector3>(SVector3(0, 0, 0), SVector3(0, 0, 0));
-  }
-  SPoint2 parFromVertex(MVertex *v) const { return SPoint2(); }
-  void secondDer(const SPoint2 &param,
-                         SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const{}
-  virtual SPoint2 getCoordinates(MVertex *v) const { return SPoint2(); }
-  bool parametrize() const {return false;}
-  virtual std::list<GFace*> getCompounds() const { return std::list<GFace*>(); }
-  GPoint intersectionWithCircle (const SVector3 &n1, const SVector3 &n2, const SVector3 &p,
-				 const double &d, double uv[2]) const { return GPoint(); }
-  int allowPartition() const{ return 1; }
-  void deleteInternals(){}
-};
-
-#endif
-
-#endif
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index eaf83e780824c6d8935ff8f99897e3fcfb398cab..cfba89f26e8be3d91a3f24c5f0c8a9ebd9e8fddb 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -12,8 +12,6 @@
 #include "GModel.h"
 #include "GModelIO_GEO.h"
 #include "GModelIO_OCC.h"
-#include "GFaceCompound.h"
-#include "GEdgeCompound.h"
 #include "MPoint.h"
 #include "MLine.h"
 #include "MTriangle.h"
@@ -3222,36 +3220,6 @@ int GModel::readGEO(const std::string &name)
   return true;
 }
 
-GEdge* GModel::addCompoundEdge(std::vector<GEdge*> edges, int num)
-{
-  if (num < 0) num = getMaxElementaryNumber(1) + 1;
-  GEdgeCompound *gec = new GEdgeCompound(this, num, edges);
-  add(gec);
-  return gec;
-}
-
-GFace* GModel::addCompoundFace(std::vector<GFace*> faces, int param, int split, int num)
-{
-#if defined(HAVE_SOLVER)
-  if (num < 0) num = getMaxElementaryNumber(2) + 1;
-  std::list<GFace*> faces_comp(faces.begin(), faces.end());
-  std::list<GEdge*> U0;
-  GFaceCompound::typeOfCompound typ = GFaceCompound::HARMONIC_CIRCLE;
-  if (param == 1) typ =  GFaceCompound::CONFORMAL_SPECTRAL;
-  if (param == 2) typ =  GFaceCompound::RADIAL_BASIS;
-  if (param == 3) typ =  GFaceCompound::HARMONIC_PLANE;
-  if (param == 4) typ =  GFaceCompound::CONVEX_CIRCLE;
-  if (param == 5) typ =  GFaceCompound::CONVEX_PLANE;
-  if (param == 6) typ =  GFaceCompound::HARMONIC_SQUARE;
-  if (param == 7) typ =  GFaceCompound::CONFORMAL_FE;
-  GFaceCompound *gfc = new GFaceCompound(this, num, faces_comp, U0, typ, split);
-  add(gfc);
-  return gfc;
-#else
-  return 0;
-#endif
-}
-
 void GModel::setPhysicalNumToEntitiesInBox(int EntityDimension, int PhysicalNumber,
                                            SBoundingBox3d box)
 {
@@ -3701,47 +3669,3 @@ void GModel::computeHomology()
 #endif
 }
 
-void GModel::setCompoundVisibility()
-{
-  // force visibility status of compound entities
-
-  for(eiter eit = firstEdge(); eit != lastEdge(); eit++){
-    GEdge *ge = *eit;
-    if (ge->getCompound()){
-      if(CTX::instance()->geom.hideCompounds) {
-        // use visibility info of compound edge if this edge belongs to it
-        ge->setVisibility(0, true);
-        bool val2 = ge->getCompound()->getVisibility();
-        if(ge->getCompound()->getBeginVertex())
-          ge->getCompound()->getBeginVertex()->setVisibility(val2);
-        if(ge->getCompound()->getEndVertex())
-          ge->getCompound()->getEndVertex()->setVisibility(val2);
-      }
-      else {
-        ge->setVisibility(1, true);
-      }
-    }
-  }
-
-  for(fiter fit = firstFace(); fit != lastFace(); fit++){
-    GFace *gf = *fit;
-    if (gf->getCompound()){
-      if(CTX::instance()->geom.hideCompounds) {
-        gf->setVisibility(0, true);
-        std::list<GEdge*> edgesComp = gf->getCompound()->edges();
-        bool val2 = gf->getCompound()->getVisibility();
-        // show edges of the compound surface
-        for (std::list<GEdge*>::iterator it = edgesComp.begin(); it != edgesComp.end(); ++it) {
-          if((*it)->getCompound())
-            (*it)->getCompound()->setVisibility(val2, true);
-          else
-            (*it)->setVisibility(val2, true);
-        }
-      }
-      else {
-        gf->setVisibility(1, true);
-      }
-    }
-  }
-
-}
diff --git a/Geo/GModel.h b/Geo/GModel.h
index d14b5ea8fab51a9afd6aa67f8925bece978fc693..1d426c27a205d514711a25eb0530b7cfdeec567e 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -231,9 +231,6 @@ class GModel {
   char getVisibility(){ return _visible; }
   void setVisibility(char val){ _visible = val; }
 
-  // set the visibility of compound entities
-  void setCompoundVisibility();
-
   // get the number of entities in this model
   int getNumRegions() const { return regions.size(); }
   int getNumFaces() const { return faces.size(); }
@@ -279,9 +276,6 @@ class GModel {
   void remove(int dim, int tag, bool recursive=false);
   void remove(const std::vector<std::pair<int, int> > &dimTags, bool recursive=false);
 
-  GEdge *addCompoundEdge(std::vector<GEdge*> edges, int num=-1);
-  GFace *addCompoundFace(std::vector<GFace*> faces, int type, int split, int num=-1);
-
   // snap vertices on model edges by using geometry tolerance
   void snapVertices();
 
diff --git a/Geo/GModelIO_GEO.cpp b/Geo/GModelIO_GEO.cpp
index 003a2ef796a4356954087a70844ab1c38935af2c..be3e5cc6a3b698c19cc978aef5e6a6e2a3317053 100644
--- a/Geo/GModelIO_GEO.cpp
+++ b/Geo/GModelIO_GEO.cpp
@@ -16,9 +16,6 @@
 #include "ListUtils.h"
 #include "gmshVertex.h"
 #include "gmshFace.h"
-#include "GFaceCompound.h"
-#include "GEdgeCompound.h"
-#include "GRegionCompound.h"
 #include "gmshEdge.h"
 #include "gmshRegion.h"
 #include "Field.h"
@@ -308,22 +305,6 @@ bool GEO_Internals::addNurbs(int &tag, const std::vector<int> &vertexTags,
   return true;
 }
 
-bool GEO_Internals::addCompoundLine(int &tag, const std::vector<int> &edgeTags)
-{
-  if(tag >= 0 && FindCurve(tag)){
-    Msg::Error("GEO edge with tag %d already exists", tag);
-    return false;
-  }
-  if(tag < 0) tag = getMaxTag(1) + 1;
-  Curve *c = CreateCurve(tag, MSH_SEGM_COMPOUND, 1, NULL, NULL, -1, -1, 0., 1.);
-  c->compound = edgeTags;
-  EndCurve(c);
-  Tree_Add(Curves, &c);
-  CreateReversedCurve(c);
-  _changed = true;
-  return true;
-}
-
 bool GEO_Internals::addLineLoop(int &tag, const std::vector<int> &edgeTags)
 {
   if(tag >= 0 && FindEdgeLoop(tag)){
@@ -430,27 +411,6 @@ bool GEO_Internals::addSurfaceFilling(int &tag, const std::vector<int> &wireTags
   return true;
 }
 
-bool GEO_Internals::addCompoundSurface(int &tag, const std::vector<int> &faceTags,
-                                       std::vector<int> edgeTags[4])
-{
-  if(tag >= 0 && FindSurface(tag)){
-    Msg::Error("GEO face with tag %d already exists", tag);
-    return false;
-  }
-  if(tag < 0) tag = getMaxTag(2) + 1;
-
-  Surface *s = CreateSurface(tag, MSH_SURF_COMPOUND);
-  s->compound = faceTags;
-  if(edgeTags){
-    for(int i = 0; i < 4; i++)
-      s->compoundBoundary[i] = edgeTags[i];
-  }
-  SetSurfaceGeneratrices(s, 0);
-  Tree_Add(Surfaces, &s);
-  _changed = true;
-  return true;
-}
-
 bool GEO_Internals::addSurfaceLoop(int &tag, const std::vector<int> &faceTags)
 {
   if(tag >= 0 && FindSurfaceLoop(tag)){
@@ -492,21 +452,6 @@ bool GEO_Internals::addVolume(int &tag, const std::vector<int> &shellTags)
   return true;
 }
 
-bool GEO_Internals::addCompoundVolume(int &tag, const std::vector<int> &regionTags)
-{
-  if(tag >= 0 && FindVolume(tag)){
-    Msg::Error("GEO region with tag %d already exists", tag);
-    return false;
-  }
-  if(tag < 0) tag = getMaxTag(3) + 1;
-
-  Volume *v = CreateVolume(tag, MSH_VOLUME_COMPOUND);
-  v->compound = regionTags;
-  Tree_Add(Volumes, &v);
-  _changed = true;
-  return true;
-}
-
 bool GEO_Internals::_extrude(int mode,
                              const std::vector<std::pair<int, int> > &inDimTags,
                              double x, double y, double z,
@@ -1168,11 +1113,7 @@ void GEO_Internals::synchronize(GModel *model)
       List_Read(curves, i, &c);
       if(c->Num >= 0){
         GEdge *e = model->getEdgeByTag(c->Num);
-        if(!e && c->Typ == MSH_SEGM_COMPOUND){
-          Msg::Debug("Postpone creation of compound edge %d until all others "
-                     "have been created", c->Num);
-        }
-        else if(!e && c->beg && c->end){
+        if(!e && c->beg && c->end){
           e = new gmshEdge(model, c, model->getVertexByTag(c->beg->Num),
                            model->getVertexByTag(c->end->Num));
           model->add(e);
@@ -1182,8 +1123,7 @@ void GEO_Internals::synchronize(GModel *model)
           model->add(e);
         }
         else{
-          if(e->getNativeType() == GEntity::GmshModel &&
-             c->Typ != MSH_SEGM_COMPOUND){
+          if(e->getNativeType() == GEntity::GmshModel){
             if(c->beg && c->end)
               ((gmshEdge*)e)->resetNativePtr(c, model->getVertexByTag(c->beg->Num),
                                              model->getVertexByTag(c->end->Num));
@@ -1195,30 +1135,6 @@ void GEO_Internals::synchronize(GModel *model)
         if(c->degenerated) e->setTooSmall(true);
       }
     }
-    // now generate the compound curves
-    for(int i = 0; i < List_Nbr(curves); i++){
-      Curve *c;
-      List_Read(curves, i, &c);
-      if(c->Num >= 0){
-        GEdge *e = model->getEdgeByTag(c->Num);
-        if(!e && c->Typ == MSH_SEGM_COMPOUND){
-          std::vector<GEdge*> comp;
-          for(unsigned int j = 0; j < c->compound.size(); j++){
-            GEdge *ge = model->getEdgeByTag(c->compound[j]);
-            if(ge) comp.push_back(ge);
-          }
-          e = new GEdgeCompound(model, c->Num, comp);
-          e->meshAttributes.method = c->Method;
-          e->meshAttributes.nbPointsTransfinite = c->nbPointsTransfinite;
-          e->meshAttributes.typeTransfinite = c->typeTransfinite;
-          e->meshAttributes.coeffTransfinite = c->coeffTransfinite;
-          e->meshAttributes.extrude = c->Extrude;
-          e->meshAttributes.reverseMesh = c->ReverseMesh;
-          model->add(e);
-          if(c->degenerated) e->setTooSmall(true);
-        }
-      }
-    }
     List_Delete(curves);
   }
 
@@ -1228,55 +1144,12 @@ void GEO_Internals::synchronize(GModel *model)
       Surface *s;
       List_Read(surfaces, i, &s);
       GFace *f = model->getFaceByTag(s->Num);
-      if(!f && s->Typ == MSH_SURF_COMPOUND){
-        std::list<GFace*> comp;
-        for(unsigned int j = 0; j < s->compound.size(); j++){
-          GFace *gf = model->getFaceByTag(s->compound[j]);
-          if(gf)
-            comp.push_back(gf);
-        }
-        std::list<GEdge*> b[4];
-        for(int j = 0; j < 4; j++){
-          for(unsigned int k = 0; k < s->compoundBoundary[j].size(); k++){
-            GEdge *ge = model->getEdgeByTag(s->compoundBoundary[j][k]);
-            if(ge) b[j].push_back(ge);
-          }
-        }
-        int param = CTX::instance()->mesh.remeshParam;
-        GFaceCompound::typeOfCompound typ = GFaceCompound::HARMONIC_CIRCLE;
-        if (param == 1) typ = GFaceCompound::CONFORMAL_SPECTRAL;
-        if (param == 2) typ = GFaceCompound::RADIAL_BASIS;
-        if (param == 3) typ = GFaceCompound::HARMONIC_PLANE;
-        if (param == 4) typ = GFaceCompound::CONVEX_CIRCLE;
-        if (param == 5) typ = GFaceCompound::CONVEX_PLANE;
-        if (param == 6) typ = GFaceCompound::HARMONIC_SQUARE;
-        if (param == 7) typ = GFaceCompound::CONFORMAL_FE;
-        int algo = CTX::instance()->mesh.remeshAlgo;
-        f = new GFaceCompound(model, s->Num, comp, b[0], b[1], b[2], b[3], typ, algo);
-        f->meshAttributes.recombine = s->Recombine;
-        f->meshAttributes.recombineAngle = s->RecombineAngle;
-        f->meshAttributes.method = s->Method;
-        f->meshAttributes.extrude = s->Extrude;
-        f->meshAttributes.transfiniteArrangement = s->Recombine_Dir;
-        f->meshAttributes.corners.clear();
-        for(int j = 0; j < List_Nbr(s->TrsfPoints); j++){
-          Vertex *corn;
-          List_Read(s->TrsfPoints, j, &corn);
-          GVertex *gv = f->model()->getVertexByTag(corn->Num);
-          if(gv)
-            f->meshAttributes.corners.push_back(gv);
-          else
-            Msg::Error("Unknown vertex %d in transfinite attributes", corn->Num);
-        }
-        model->add(f);
-      }
-      else if(!f){
+      if(!f){
         f = new gmshFace(model, s);
         model->add(f);
       }
       else{
-        if(f->getNativeType() == GEntity::GmshModel &&
-           s->Typ != MSH_SURF_COMPOUND)
+        if(f->getNativeType() == GEntity::GmshModel)
           ((gmshFace*)f)->resetNativePtr(s);
         f->resetMeshAttributes();
       }
@@ -1290,22 +1163,12 @@ void GEO_Internals::synchronize(GModel *model)
       Volume *v;
       List_Read(volumes, i, &v);
       GRegion *r = model->getRegionByTag(v->Num);
-      if(!r && v->Typ == MSH_VOLUME_COMPOUND){
-        std::vector<GRegion*> comp;
-        for(unsigned int j = 0; j < v->compound.size(); j++){
-          GRegion *gr = model->getRegionByTag(v->compound[j]);
-          if(gr) comp.push_back(gr);
-        }
-        r = new GRegionCompound(model, v->Num, comp);
-        model->add(r);
-      }
-      else if(!r){
+      if(!r){
         r = new gmshRegion(model, v);
         model->add(r);
       }
       else{
-        if(r->getNativeType() == GEntity::GmshModel &&
-           v->Typ != MSH_VOLUME_COMPOUND)
+        if(r->getNativeType() == GEntity::GmshModel)
           ((gmshRegion*)r)->resetNativePtr(v);
         r->resetMeshAttributes();
       }
diff --git a/Geo/GRegion.cpp b/Geo/GRegion.cpp
index bca79da37c3d5c455e800b8e7f92b6af8d15784b..e6cd748a64e74e6ca419e7e6dc2b9b8be0420bfb 100644
--- a/Geo/GRegion.cpp
+++ b/Geo/GRegion.cpp
@@ -19,7 +19,7 @@
 #include "GmshDefines.h"
 
 GRegion::GRegion(GModel *model, int tag)
-  : GEntity (model, tag), compound(0)
+  : GEntity (model, tag)
 {
   resetMeshAttributes();
 }
@@ -309,13 +309,6 @@ std::list<GEdge*> GRegion::edges() const
     std::list<GEdge*>::const_iterator it2 = e2.begin();
     while (it2 != e2.end()){
       GEdge *edge = *it2;
-
-      // FIXME: we need to fix the compound design and decide what to do; same
-      // thing for faces() (either store or compute the entities, either use
-      // original or compound entities, etc.)
-      if(edge->getCompound())
-        edge = (GEdge*)edge->getCompound();
-
       if(std::find(e.begin(), e.end(), edge) == e.end())
         e.push_back(edge);
       ++it2;
diff --git a/Geo/GRegion.h b/Geo/GRegion.h
index b9810d558720652f4476d80fc1a2e6894f505cf3..4679ab1b521e92d7f632c8375bf1e0603c350c97 100644
--- a/Geo/GRegion.h
+++ b/Geo/GRegion.h
@@ -21,7 +21,6 @@ class MPyramid;
 class MPolyhedron;
 class MTrihedron;
 class ExtrudeParams;
-class GRegionCompound;
 class BoundaryLayerColumns;
 
 // A model region.
@@ -32,7 +31,6 @@ class GRegion : public GEntity {
   std::list<GFace *> embedded_faces;
   std::list<GEdge *> embedded_edges;
   std::list<int> l_dirs;
-  GRegionCompound *compound; // this model ede belongs to a compound
 
   // replace faces (for gluing) for specific modelers, we have to
   // re-create internal data ...
@@ -118,10 +116,6 @@ class GRegion : public GEntity {
   // reset the mesh attributes to default values
   virtual void resetMeshAttributes();
 
-  // compound
-  void setCompound(GRegionCompound *grc) { compound = grc; }
-  GRegionCompound *getCompound() const { return compound; }
-
   struct {
     // do we recombine the tetrahedra of the mesh into hex?
     int recombine3D;
diff --git a/Geo/GRegionCompound.cpp b/Geo/GRegionCompound.cpp
deleted file mode 100644
index 0a7d8dcd46578ad756d4719380b6a68410fd12f6..0000000000000000000000000000000000000000
--- a/Geo/GRegionCompound.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-//
-// Contributor(s):
-//   Emilie Marchandise
-//
-
-#include <stdlib.h>
-#include "GmshConfig.h"
-#include "GRegionCompound.h"
-#include "Numeric.h"
-
-GRegionCompound::GRegionCompound(GModel *m, int tag, std::vector<GRegion*> &compound)
-  : GRegion(m, tag), _compound(compound)
-{
-
-  for (unsigned int i = 0; i < _compound.size(); i++){
-    if(!_compound[i]){
-      Msg::Error("Incorrect region in compound region %d", tag);
-      return;
-    }
-  }
-  for (unsigned int i = 0; i < _compound.size(); i++)
-    _compound[i]->setCompound(this);
-  getBoundingFaces();
-}
-
-GRegionCompound::~GRegionCompound()
-{
-}
-
-void GRegionCompound::getBoundingFaces()
-{
-  std::set<GFace*> _unique;
-  std::multiset<GFace*> _touched;
-  std::vector<GRegion*>::iterator it = _compound.begin();
-  for ( ; it != _compound.end(); ++it){
-    std::list<GFace*> ed = (*it)->faces();
-    std::list<GFace*> :: iterator ite = ed.begin();
-    for ( ; ite != ed.end(); ++ite){
-      _touched.insert(*ite);
-    }
-  }
-  it = _compound.begin();
-  for ( ; it != _compound.end(); ++it){
-    std::list<GFace*> ed = (*it)->faces();
-    std::list<GFace*> :: iterator ite = ed.begin();
-    for ( ; ite != ed.end() ; ++ite){
-      if (!(*ite)->degenerate(0) && _touched.count(*ite) == 1) {
-        _unique.insert(*ite);
-      }
-    }
-  }
-
-  std::set<GFace*>::iterator itf = _unique.begin();
-  for ( ; itf != _unique.end(); ++itf){
-    printf("Compound Volume %d face %d \n", tag(), (*itf)->tag());
-    l_faces.push_back(*itf);
-    (*itf)->addRegion(this);
-  }
-}
-
-SBoundingBox3d  GRegionCompound::bounds() const
-{
-  Msg::Error("Cannot evaluate bounds on GRegion Compound");
-  return SBoundingBox3d(SPoint3());
-}
-
-double GRegionCompound::curvature(double par) const
-{
-  double k = 0.0;
-  Msg::Error("Cannot evaluate curvature on GRegionCompound");
-  return k;
-}
-
-GPoint GRegionCompound::point(double par) const
-{
-  Msg::Error("Cannot evaluate point on GRegionCompound");
-  return GPoint();
-}
-
-SVector3 GRegionCompound::firstDer(double par) const
-{
-  Msg::Error("Cannot evaluate firstDeriv on GRegionCompound");
-  return SVector3();
-}
diff --git a/Geo/GRegionCompound.h b/Geo/GRegionCompound.h
deleted file mode 100644
index bd7578c9f28e9367a159759431b89e6f69074db4..0000000000000000000000000000000000000000
--- a/Geo/GRegionCompound.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-
-#ifndef _GREGION_COMPOUND_H_
-#define _GREGION_COMPOUND_H_
-
-#include <list>
-#include <map>
-#include "GRegion.h"
-#include "GFace.h"
-#include "GFaceCompound.h"
-
-/*
-A GRegionCompound is a model region that is the compound of model regions.
-
-It is assumed that all the regions of the compound have been meshed
-first and that all the faces of the compound region are compound surfaces.
-
-The compound can therefore be re-meshed using any volume mesh
-generator of gmsh!
-*/
-
-class GRegionCompound : public GRegion {
- public:
-  GRegionCompound(GModel *m, int tag, std::vector<GRegion*> &compound);
-  virtual ~GRegionCompound();
-  virtual SBoundingBox3d bounds() const;
-  virtual double curvature(double t) const;
-  virtual GPoint point(double par) const; 
-  virtual SVector3 firstDer(double par) const; 
-  virtual GEntity::GeomType geomType() const { return CompoundVolume; }
-  ModelType getNativeType() const { return GmshModel; }
-  void * getNativePtr() const { return 0; }
-
- protected:
-  std::vector<GRegion*> _compound;
-  void getBoundingFaces();
-};
-
-#endif
-
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index cd1535f1d86152f204593e1963c6472f9c11bcb9..b7588f2bb0375d1aa0d3f53f279ffe12e88bd430 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -10,7 +10,6 @@
 #include "GVertex.h"
 #include "GEdge.h"
 #include "GFace.h"
-#include "GFaceCompound.h"
 #include "discreteDiskFace.h"
 #include "GmshMessage.h"
 #include "StringUtils.h"
@@ -399,12 +398,6 @@ static void getAllParameters(MVertex *v, GFace *gf, std::vector<SPoint2> &params
 {
   params.clear();
 
-  if (gf->geomType() == GEntity::CompoundSurface ){
-    GFaceCompound *gfc = (GFaceCompound*) gf;
-    params.push_back(gfc->parFromVertex(v));
-    return;
-  }
-
 #if defined(HAVE_ANN) && defined(HAVE_SOLVER)
   if (gf->geomType() == GEntity::DiscreteDiskSurface ){
     discreteDiskFace *gfc = (discreteDiskFace*) gf;
@@ -510,12 +503,6 @@ bool reparamMeshEdgeOnFace(MVertex *v1, MVertex *v2, GFace *gf,
 bool reparamMeshVertexOnFace(MVertex *v, const GFace *gf, SPoint2 &param,
                              bool onSurface)
 {
-  if(gf->geomType() == GEntity::CompoundSurface){
-    GFaceCompound *gfc = (GFaceCompound*) gf;
-    param = gfc->parFromVertex(v);
-    return true;
-  }
-
 #if defined(HAVE_ANN) && defined(HAVE_SOLVER)
   if (gf->geomType() == GEntity::DiscreteDiskSurface ){
     discreteDiskFace *gfc = (discreteDiskFace*) gf;
diff --git a/Geo/discreteEdge.cpp b/Geo/discreteEdge.cpp
index 29b53f1bab4ae0226e7bf5b6a91fb6b825f2ae90..81863528f0332d95650c443069aab2fc4c962e4b 100644
--- a/Geo/discreteEdge.cpp
+++ b/Geo/discreteEdge.cpp
@@ -20,8 +20,6 @@
 #include "GModelIO_GEO.h"
 #include "Geo.h"
 #include "OS.h"
-#include "Curvature.h"
-#include "GEdgeCompound.h"
 
 #if defined(HAVE_MESH)
 #include "meshGEdge.h"
@@ -489,34 +487,15 @@ SVector3 discreteEdge::firstDer(double par) const
 
 double discreteEdge::curvature(double par) const
 {
-  double tLoc;
-  int iEdge;
-  if(!getLocalParameter(par, iEdge, tLoc)) return MAX_LC;
-
-  double c0, c1;
-  Curvature& curvature  = Curvature::getInstance();
-  if( !Curvature::valueAlreadyComputed() ) {
-    Msg::Warning("Need to compute discrete curvature (in discreteEdge)");
-    Curvature::typeOfCurvature type = Curvature::RUSIN; //RUSIN; //RBF
-    curvature.computeCurvature(model(), type);
-  }
-
-  curvature.edgeNodalValues(lines[iEdge],c0, c1, 1);
-  double cv = (1-tLoc)*c0 + tLoc*c1;
-
-  return cv;
+  Msg::Error("Curvature for discrete edge not implemented yet");
+  return 0.;
 }
 
 double discreteEdge::curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin,
                                 double *curvMax, double *curvMin) const
 {
-  if (getCompound()){
-    return getCompound()->curvatures(par, dirMax, dirMin, curvMax, curvMin);
-  }
-  else{
-    Msg::Error("Cannot evaluate curvatures and curvature directions on discrete edge");
-    return false;
-  }
+  Msg::Error("Cannot evaluate curvatures and curvature directions on discrete edge");
+  return false;
 }
 
 Range<double> discreteEdge::parBounds(int i) const
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index dc82256177f5b1b1f8c4536945d5b7004176c0d3..6fea94e66918250135288565bf84ca4c176f6f1c 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -13,7 +13,6 @@
 #include "discreteDiskFace.h"
 #include "GModelIO_GEO.h"
 #include "Geo.h"
-#include "GFaceCompound.h"
 #include "Context.h"
 #include "OS.h"
 #include "meshPartitionObjects.h"
diff --git a/Geo/discreteFace.h b/Geo/discreteFace.h
index 71a83fec6a15b8317e9f07325f230065fa2e8039..5ba5eb554fb5ee93532aa69bf51bd66cc9e48b3e 100644
--- a/Geo/discreteFace.h
+++ b/Geo/discreteFace.h
@@ -40,7 +40,6 @@ class discreteFace : public GFace {
   double curvatureMax(const SPoint2 &param) const;
   double curvatures(const SPoint2 &param, SVector3 *dirMax, SVector3 *dirMin,
                                   double *curvMax, double *curvMin) const;
-  virtual bool haveParametrization() { return getCompound(); }
   GEntity::GeomType geomType() const { return DiscreteSurface; }
   virtual Pair<SVector3, SVector3> firstDer(const SPoint2 &param) const;
   virtual void secondDer(const SPoint2 &param,
diff --git a/Geo/gmshEdge.cpp b/Geo/gmshEdge.cpp
index 1283ce10c341a60cc4f96354103fe22d3722e265..0065e954a4bedcd0cccfe299ec070d844f348a51 100644
--- a/Geo/gmshEdge.cpp
+++ b/Geo/gmshEdge.cpp
@@ -6,7 +6,6 @@
 #include <sstream>
 #include "GModel.h"
 #include "GFace.h"
-#include "GFaceCompound.h"
 #include "gmshEdge.h"
 #include "Geo.h"
 #include "GeoInterpolation.h"
diff --git a/Graphics/drawGeom.cpp b/Graphics/drawGeom.cpp
index 67cf4f25f125e2a3497678e4a77c0637c466e453..59b1eef9c0ee4f8814ce4cbc0f28779ef3772d38 100644
--- a/Graphics/drawGeom.cpp
+++ b/Graphics/drawGeom.cpp
@@ -11,8 +11,6 @@
 #include "GModel.h"
 #include "SBoundingBox3d.h"
 #include "GmshMessage.h"
-#include "GEdgeCompound.h"
-#include "GFaceCompound.h"
 
 static void drawEntityLabel(drawContext *ctx, GEntity *e,
                             double x, double y, double z, double offset)
@@ -124,7 +122,6 @@ class drawGEdge {
     if(e->geomType() == GEntity::DiscreteCurve) return;
     if(e->geomType() == GEntity::PartitionCurve) return;
     if(e->geomType() == GEntity::BoundaryLayerCurve) return;
-    // if(e->geomType() == GEntity::CompoundCurve) return;
 
     bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
                    e->model() == GModel::current());
@@ -286,7 +283,7 @@ class drawGFace {
     if(CTX::instance()->geom.surfaces){
       if(CTX::instance()->geom.surfaceType > 0 && f->va_geom_triangles){
         bool selected = false;
-        if (f->getSelection() || (f->getCompound() && f->getCompound()->getSelection()))
+        if (f->getSelection())
           selected = true;
         _drawVertexArray
           (f->va_geom_triangles, CTX::instance()->geom.light,
@@ -365,8 +362,6 @@ class drawGFace {
 
     if(CTX::instance()->geom.surfaces) {
       //bool selected = false;
-      //if (f->getSelection() || (f->getCompound() && f->getCompound()->getSelection()))
-        //selected = true;
       if(CTX::instance()->geom.surfaceType > 0 && f->va_geom_triangles){
         _drawVertexArray(f->va_geom_triangles, CTX::instance()->geom.light,
                          f->getSelection(), CTX::instance()->color.geom.selection);
@@ -415,24 +410,6 @@ class drawGFace {
     }
   }
 
-  void _drawCompoundGFace(GFace *f, bool visible = false, bool selected = false)
-  {
-    GFaceCompound *fc = (GFaceCompound*) f;
-    std::list<GFace*> faces = fc->getCompounds();
-    for (std::list<GFace*>::iterator it = faces.begin(); it!=faces.end(); it++) {
-      if ((*it)->geomType() == GEntity::DiscreteSurface) continue;
-      if ((*it)->geomType() == GEntity::PartitionSurface) continue;
-      if ((*it)->geomType() == GEntity::BoundaryLayerSurface) continue;
-
-      if((*it)->geomType() == GEntity::CompoundSurface)
-        _drawCompoundGFace((*it));
-      else if ((*it)->geomType() == GEntity::Plane)
-        _drawPlaneGFace((*it));
-      else
-        _drawParametricGFace((*it));
-    }
-  }
-
  public :
   drawGFace(drawContext *ctx) : _ctx(ctx) {}
   void operator () (GFace *f)
@@ -467,9 +444,7 @@ class drawGFace {
     else
       glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
 
-    if(f->geomType() == GEntity::CompoundSurface)
-      _drawCompoundGFace(f);
-    else if(f->geomType() == GEntity::Plane)
+    if(f->geomType() == GEntity::Plane)
       _drawPlaneGFace(f);
     else
       _drawParametricGFace(f);
diff --git a/Graphics/drawMesh.cpp b/Graphics/drawMesh.cpp
index 1240f3117024343a61d6782aa4d4b91833ca0369..41d34f3dd3a2263e9c3c70936c1a61277d63ae58 100644
--- a/Graphics/drawMesh.cpp
+++ b/Graphics/drawMesh.cpp
@@ -8,8 +8,6 @@
 #include "GmshMessage.h"
 #include "GmshDefines.h"
 #include "GModel.h"
-#include "GFaceCompound.h"
-#include "GEdgeCompound.h"
 #include "MLine.h"
 #include "MTriangle.h"
 #include "MQuadrangle.h"
@@ -147,12 +145,6 @@ static void drawVertexLabel(drawContext *ctx, GEntity *e, MVertex *v,
 
 static void drawVerticesPerEntity(drawContext *ctx, GEntity *e)
 {
-  //if(e->dim() == 2) {
-  //  if(e->cast2Edge()->getCompound()) {
-  //    if(e->cast2Edge()->getCompound()
-  //
-   // }
-  //}
   if(CTX::instance()->mesh.points) {
     if(CTX::instance()->mesh.pointType) {
       for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){
@@ -442,11 +434,7 @@ class drawMeshGEdge {
   void operator () (GEdge *e)
   {
     if(!e->getVisibility()) {
-      if(e->getCompound()) {
-        if(!e->getCompound()->getVisibility()) return;
-      }
-      else
-        return;
+      return;
     }
 
     bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
@@ -491,11 +479,7 @@ class drawMeshGFace {
   void operator () (GFace *f)
   {
     if(!f->getVisibility()) {
-      if(f->getCompound()) {
-        if(!f->getCompound()->getVisibility()) return;
-      }
-      else
-        return;
+      return;
     }
 
     bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp
index b2cc9aa681a2e7274d63093523278bcac37e0d06..381b9d7f32ec589d0390162f77c9846226218efb 100644
--- a/Mesh/BackgroundMesh.cpp
+++ b/Mesh/BackgroundMesh.cpp
@@ -9,9 +9,7 @@
 #include "Context.h"
 #include "GVertex.h"
 #include "GEdge.h"
-#include "GEdgeCompound.h"
 #include "GFace.h"
-#include "GFaceCompound.h"
 #include "GModel.h"
 #include "OS.h"
 #include "Field.h"
@@ -227,7 +225,6 @@ static void propagateValuesOnFace(GFace *_gf,
 void backgroundMesh::propagate1dMesh(GFace *_gf)
 {
   std::list<GEdge*> e;// = _gf->edges();
-  replaceMeshCompound(_gf, e);
   std::list<GEdge*>::const_iterator it = e.begin();
   std::map<MVertex*,double> sizes;
 
@@ -282,7 +279,6 @@ crossField2d::crossField2d(MVertex* v, GEdge* ge)
 void backgroundMesh::propagateCrossFieldByDistance(GFace *_gf)
 {
   std::list<GEdge*> e;
-  replaceMeshCompound(_gf, e);
 
   std::list<GEdge*>::const_iterator it = e.begin();
   std::map<MVertex*,double> _cosines4,_sines4;
@@ -443,7 +439,6 @@ void backgroundMesh::propagateCrossField(GFace *_gf, simpleFunction<double> *ONE
   std::map<MVertex*,double> _cosines4,_sines4;
 
   std::list<GEdge*> e;
-  replaceMeshCompound(_gf, e);
 
   std::list<GEdge*>::const_iterator it = e.begin();
 
@@ -486,7 +481,7 @@ void backgroundMesh::propagateCrossField(GFace *_gf, simpleFunction<double> *ONE
 
   //    print("cos4.pos",0,_cosines4,0);
   //    print("sin4.pos",0,_sines4,0);
-  
+
   std::map<MVertex*,MVertex*>::iterator itv2 = _2Dto3D.begin();
   for ( ; itv2 != _2Dto3D.end(); ++itv2){
     MVertex *v_2D = itv2->first;
diff --git a/Mesh/BackgroundMesh2D.cpp b/Mesh/BackgroundMesh2D.cpp
index f3ff9e3c775fe0baeb79dc4ddd89564c4a8a57d2..f45c6707d1bfc32dddaaafad2fee00b44276993f 100644
--- a/Mesh/BackgroundMesh2D.cpp
+++ b/Mesh/BackgroundMesh2D.cpp
@@ -10,9 +10,7 @@
 #include "GModel.h"
 #include "GVertex.h"
 #include "GEdge.h"
-#include "GEdgeCompound.h"
 #include "GFace.h"
-#include "GFaceCompound.h"
 #include "MElement.h"
 #include "MElementOctree.h"
 #include "MTriangle.h"
@@ -291,7 +289,6 @@ void backgroundMesh2D::computeSizeField()
   }
 
   list<GEdge*> e;
-  replaceMeshCompound(face, e);
   list<GEdge*>::const_iterator it = e.begin();
   DoubleStorageType sizes;
 
@@ -483,8 +480,6 @@ void frameFieldBackgroundMesh2D::computeCrossField(simpleFunction<double> &eval_
     return;
   }
 
-  replaceMeshCompound(face, e);
-
   list<GEdge*>::const_iterator it = e.begin();
 
   for( ; it != e.end(); ++it ){
diff --git a/Mesh/BackgroundMeshTools.cpp b/Mesh/BackgroundMeshTools.cpp
index 85dc609596df67087f840ec513a90996e3c39a46..e882aa3fd9933e766c7cd86f6818147b8eb9e24a 100644
--- a/Mesh/BackgroundMeshTools.cpp
+++ b/Mesh/BackgroundMeshTools.cpp
@@ -7,7 +7,6 @@
 #include "GFace.h"
 #include "GVertex.h"
 #include "GEdge.h"
-#include "GEdgeCompound.h"
 #include "GEntity.h"
 #include "Context.h"
 #include "Field.h"
@@ -19,12 +18,9 @@ static double max_surf_curvature(const GEdge *ge, double u)
   std::list<GFace *> faces = ge->faces();
   std::list<GFace *>::iterator it = faces.begin();
   while(it != faces.end()){
-    if ((*it)->geomType() != GEntity::CompoundSurface &&
-        (*it)->geomType() != GEntity::DiscreteSurface){
-      SPoint2 par = ge->reparamOnFace((*it), u, 1);
-      double cc = (*it)->curvature(par);
-      val = std::max(cc, val);
-    }
+    SPoint2 par = ge->reparamOnFace((*it), u, 1);
+    double cc = (*it)->curvature(par);
+    val = std::max(cc, val);
     ++it;
   }
   return val;
@@ -93,71 +89,24 @@ SMetric3 max_edge_curvature_metric(const GEdge *ge, double u)
 
 static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u, bool iso_surf)
 {
-  const GEdgeCompound* ptrCompoundEdge = dynamic_cast<const GEdgeCompound*>(ge);
-  if (ptrCompoundEdge){
-    double cmax, cmin;
-    SVector3 dirMax,dirMin;
-    cmax = ptrCompoundEdge->curvatures(u,&dirMax, &dirMin, &cmax,&cmin);
-    if (cmin == 0)cmin =1.e-12;
-    if (cmax == 0)cmax =1.e-12;
-    double lambda2 =  ((2 * M_PI) /( fabs(cmax) *  CTX::instance()->mesh.minCircPoints ) );
-    double lambda1 =  ((2 * M_PI) /( fabs(cmin) *  CTX::instance()->mesh.minCircPoints ) );
-    SVector3 Z = crossprod(dirMax,dirMin);
-
-    lambda1 = std::max(lambda1, CTX::instance()->mesh.lcMin);
-    lambda2 = std::max(lambda2, CTX::instance()->mesh.lcMin);
-    lambda1 = std::min(lambda1, CTX::instance()->mesh.lcMax);
-    lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax);
-
-    SMetric3 curvMetric (1. / (lambda1 * lambda1), 1. / (lambda2 * lambda2),
-                         1.e-12, dirMin, dirMax, Z);
-    return curvMetric;
-  }
-  else{
-    SMetric3 mesh_size(1.e-12);
-    std::list<GFace *> faces = ge->faces();
-    std::list<GFace *>::iterator it = faces.begin();
-    // we choose the metric eigenvectors to be the ones
-    // related to the edge ...
-    SMetric3 curvMetric = max_edge_curvature_metric(ge, u);
-    while(it != faces.end()){
-      if (((*it)->geomType() != GEntity::CompoundSurface) &&
-          ((*it)->geomType() != GEntity::DiscreteSurface)){
-        SPoint2 par = ge->reparamOnFace((*it), u, 1);
-        SMetric3 m = metric_based_on_surface_curvature (*it, par.x(), par.y(), iso_surf);
-        curvMetric = intersection_conserveM1(curvMetric,m);
-      }
-      ++it;
-    }
-
-    return curvMetric;
+  SMetric3 mesh_size(1.e-12);
+  std::list<GFace *> faces = ge->faces();
+  std::list<GFace *>::iterator it = faces.begin();
+  // we choose the metric eigenvectors to be the ones
+  // related to the edge ...
+  SMetric3 curvMetric = max_edge_curvature_metric(ge, u);
+  while(it != faces.end()){
+    SPoint2 par = ge->reparamOnFace((*it), u, 1);
+    SMetric3 m = metric_based_on_surface_curvature (*it, par.x(), par.y(), iso_surf);
+    curvMetric = intersection_conserveM1(curvMetric,m);
+    ++it;
   }
+  return curvMetric;
 }
 
 static SMetric3 metric_based_on_surface_curvature(const GVertex *gv, bool iso_surf)
 {
   SMetric3 mesh_size(1.e-15);
-  std::list<GEdge*> l_edges = gv->edges();
-  for (std::list<GEdge*>::const_iterator ite = l_edges.begin();
-       ite != l_edges.end(); ++ite){
-    GEdge *_myGEdge = *ite;
-    Range<double> bounds = _myGEdge->parBounds(0);
-
-    // ES: Added extra if condition to use the code below only with compund curves
-    // This is because we want to call the function
-    // metric_based_on_surface_curvature(const GEdge *ge, double u) for the case when
-    // ge is a compound edge
-    if (_myGEdge->geomType() == GEntity::CompoundCurve){
-      if (gv == _myGEdge->getBeginVertex())
-        mesh_size = intersection
-          (mesh_size,
-           metric_based_on_surface_curvature(_myGEdge, bounds.low(), iso_surf));
-      else
-        mesh_size = intersection
-          (mesh_size,
-           metric_based_on_surface_curvature(_myGEdge, bounds.high(), iso_surf));
-    }
-  }
   return mesh_size;
 }
 
diff --git a/Mesh/BoundaryLayers.cpp b/Mesh/BoundaryLayers.cpp
index 41dc3860770106faafc73698b461743b27fed968..635e367440628e7a068413c8935503f892e5fef2 100644
--- a/Mesh/BoundaryLayers.cpp
+++ b/Mesh/BoundaryLayers.cpp
@@ -13,7 +13,6 @@
 #include "meshGFace.h"
 #include "GmshMessage.h"
 #include "Field.h"
-#include "GFaceCompound.h"
 
 #if defined(HAVE_POST)
 #include "PView.h"
@@ -250,20 +249,6 @@ static void checkDepends(GModel *m, GFace *f, std::set<GFace*> &dep)
     dep.insert(from);
     checkDepends(m, from, dep);
   }
-
-  if(f->geomType() == GEntity::CompoundSurface){
-    std::list<GFace*> compounds = ((GFaceCompound*)(f))->getCompounds();
-    std::list<GFace*>::iterator itgf = compounds.begin();
-    for( ; itgf != compounds.end(); itgf++ ){
-      if(!(*itgf)){
-        Msg::Error("Unknown compound face in boundary layer source face %d",
-                   f->tag());
-        return;
-      }
-      dep.insert(*itgf);
-      checkDepends(m, *itgf, dep);
-    }
-  }
 }
 
 static unsigned int FixErasedExtrScaleFlags(GModel *m,
diff --git a/Mesh/CMakeLists.txt b/Mesh/CMakeLists.txt
index a25131ee307a5c4e87540b3a8831a75180fddf36..2f5d07785a59ab0046a06ba1d994b2b8ff2576c8 100644
--- a/Mesh/CMakeLists.txt
+++ b/Mesh/CMakeLists.txt
@@ -35,7 +35,6 @@ set(SRC
     HighOrder.cpp 
     meshPartition.cpp
     meshRefine.cpp
-    multiscalePartition.cpp
     QuadTriUtils.cpp
       QuadTriExtruded2D.cpp QuadTriExtruded3D.cpp QuadTriTransfinite3D.cpp
     simple3D.cpp ThinLayer.cpp
diff --git a/Mesh/DivideAndConquer.cpp b/Mesh/DivideAndConquer.cpp
index 81c9d2874133e3ecf472413a5fdae4b421d0eb3a..274e643e436271affbf3233b00ad6c575d320f6a 100644
--- a/Mesh/DivideAndConquer.cpp
+++ b/Mesh/DivideAndConquer.cpp
@@ -23,7 +23,6 @@
 #include "OS.h"
 #include "GPoint.h"
 #include "GFace.h"
-#include "GEdgeCompound.h"
 #include "MLine.h"
 
 #define Pred(x) ((x)->prev)
@@ -1008,7 +1007,7 @@ void DocRecord::concave(double x,double y,GFace* gf)
   std::set<int>::iterator it2;
 
   list = gf->edges();
-  replaceMeshCompound(gf,list);
+
   for(it1 = list.begin(); it1 != list.end(); it1++){
     edge = *it1;
     for(unsigned int i = 0; i < edge->getNumMeshElements(); i++){
@@ -1142,7 +1141,7 @@ void DocRecord::clear_edges()
 bool DocRecord::delaunay_conformity(GFace* gf)
 {
   std::list<GEdge*> list = gf->edges();
-  replaceMeshCompound(gf,list);
+
   for(std::list<GEdge*>::iterator it = list.begin(); it!= list.end(); it++){
     GEdge *edge = *it;
     for(unsigned int i = 0; i < edge->getNumMeshElements(); i++){
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 5a774d171d72cba44dbb6ffb2574838688296492..3a939ad9f5459a002ae13f4723736ccf908d8c84 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -29,7 +29,6 @@
 #include "HighOrder.h"
 #include "Generator.h"
 #include "meshGFaceLloyd.h"
-#include "GFaceCompound.h"
 #include "Field.h"
 #include "Options.h"
 #include "simple3D.h"
@@ -449,10 +448,7 @@ static void Mesh2D(GModel *m)
   if(!Mesh2DWithBoundaryLayers(m)){
     std::set<GFace*, GEntityLessThan> cf, f;
     for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it)
-      if ((*it)->geomType() == GEntity::CompoundSurface)
-        cf.insert(*it);
-      else
-        f.insert(*it);
+      f.insert(*it);
 
     Msg::ResetProgressMeter();
 
@@ -471,8 +467,7 @@ static void Mesh2D(GModel *m)
           temp[K]->mesh(true);
 #if defined(HAVE_BFGS)
           if(CTX::instance()->mesh.optimizeLloyd){
-            if (temp[K]->geomType()==GEntity::CompoundSurface ||
-                temp[K]->geomType()==GEntity::Plane ||
+            if (temp[K]->geomType()==GEntity::Plane ||
                 temp[K]->geomType()==GEntity::RuledSurface) {
               if (temp[K]->meshAttributes.method != MESH_TRANSFINITE &&
                   !temp[K]->meshAttributes.extrude) {
@@ -509,8 +504,7 @@ static void Mesh2D(GModel *m)
           (*it)->mesh(true);
 #if defined(HAVE_BFGS)
           if(CTX::instance()->mesh.optimizeLloyd){
-            if ((*it)->geomType()==GEntity::CompoundSurface ||
-                (*it)->geomType()==GEntity::Plane ||
+            if ((*it)->geomType()==GEntity::Plane ||
                 (*it)->geomType()==GEntity::RuledSurface) {
               if ((*it)->meshAttributes.method != MESH_TRANSFINITE &&
                   !(*it)->meshAttributes.extrude) {
diff --git a/Mesh/directions3D.cpp b/Mesh/directions3D.cpp
index 7145f30e509971b5a7a4f78162f06eca2f1fef2d..ea27ca3179b8e6227f8a0e41006cd43ca9322082 100644
--- a/Mesh/directions3D.cpp
+++ b/Mesh/directions3D.cpp
@@ -13,7 +13,6 @@
 #include "MTetrahedron.h"
 #include "directions3D.h"
 #include "OS.h"
-#include "GFaceCompound.h"
 #include "cross3D.h"
 
 #if defined(HAVE_SOLVER)
@@ -509,21 +508,14 @@ void Frame_field::initFace(GFace* gf)
   // compute cumulative cross-data "vertices x elements" for the whole contour of gf
   std::list<GEdge*> edges = gf->edges();
   vertex_to_elements.clear();
-  //Replace edges by their compounds
-   std::set<GEdge*> mySet;
-   std::list<GEdge*>::iterator it = edges.begin();
-   while(it != edges.end()){
-    if((*it)->getCompound()){
-      GEdge *gec = (GEdge*)(*it)->getCompound();
-      mySet.insert(gec);
-    }
-    else{
-      mySet.insert(*it);
-    }
+  std::set<GEdge*> mySet;
+  std::list<GEdge*>::iterator it = edges.begin();
+  while(it != edges.end()){
+    mySet.insert(*it);
     ++it;
-   }
-   edges.clear();
-   edges.insert(edges.begin(), mySet.begin(), mySet.end());
+  }
+  edges.clear();
+  edges.insert(edges.begin(), mySet.begin(), mySet.end());
   for( std::list<GEdge*>::const_iterator it=edges.begin(); it!=edges.end(); it++){
     build_vertex_to_elements(*it,false);
   }
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 6508a69dea59f6bc99ff8e86ddc14ca47b230a0f..e1ea164d64f394e3d207d14c937aea30c77751d5 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -16,7 +16,6 @@
 #include "BackgroundMesh.h"
 #include "GVertex.h"
 #include "GEdge.h"
-#include "GEdgeCompound.h"
 #include "robustPredicates.h"
 #include "discreteFace.h"
 #include "GFace.h"
@@ -41,7 +40,6 @@
 #include "meshPartition.h"
 #include "CreateFile.h"
 #include "Context.h"
-#include "multiscalePartition.h"
 #include "meshGFaceLloyd.h"
 #include "boundaryLayersData.h"
 #include "filterElements.h"
@@ -958,16 +956,7 @@ static void directions_storage(GFace* gf)
   gf->storage4.clear();
 
   for(it=vertices.begin();it!=vertices.end();it++){
-    ok = 0;
-
-    if(!gf->getCompound()){
-      if(gf->geomType()==GEntity::CompoundSurface){
-        ok = translate(gf,octree,*it,SPoint2(0.0,0.0),v1,v2);
-      }
-      else{
-        ok = improved_translate(gf,*it,v1,v2);
-      }
-    }
+    ok = improved_translate(gf,*it,v1,v2);
 
     if(ok){
       gf->storage1.push_back(SPoint3((*it)->x(),(*it)->y(),(*it)->z()));
@@ -998,16 +987,6 @@ bool meshGenerator(GFace *gf, int RECUR_ITER,
   std::list<int> dir = gf->edgeOrientations();
   std::vector<MEdge> medgesToRecover;
 
-  // replace edges by their compounds
-  // if necessary split compound and remesh parts
-  bool isMeshed = false;
-  if(gf->geomType() == GEntity::CompoundSurface  && !onlyInitialMesh){
-    isMeshed = checkMeshCompound((GFaceCompound*) gf, edges);
-    if (isMeshed) return true;
-  }
-
-  //  if (gf->degenerate(0))return 0;
-
   // build a set with all points of the boundaries
   std::set<MVertex*, MVertexLessThanNum> all_vertices, boundary;
   std::list<GEdge*>::iterator ite = edges.begin();
@@ -1507,9 +1486,7 @@ bool meshGenerator(GFace *gf, int RECUR_ITER,
   //gf->triangles.clear();
   //gf->quadrangles.clear();
 
-  // only delete the mesh data stored in the base GFace class (calling
-  // gf->deleteMesh() would also destroy e.g. the data in a compound face, which
-  // we should not do)
+  // only delete the mesh data stored in the base GFace class
   gf->GFace::deleteMesh();
 
   Msg::Debug("Starting to add internal points");
@@ -2523,247 +2500,6 @@ void meshGFace::operator() (GFace *gf, bool print)
   }
 }
 
-bool checkMeshCompound(GFaceCompound *gf, std::list<GEdge*> &edges)
-{
-  bool isMeshed = false;
-#if defined(HAVE_SOLVER)
-  bool correctTopo = gf->checkTopology();
-  if (!correctTopo && gf->allowPartition()){
-    partitionAndRemesh((GFaceCompound*) gf);
-    isMeshed = true;
-    return isMeshed;
-  }
-
-  bool correctParam = gf->parametrize();
-
-  if (!correctParam &&  gf->allowPartition()){
-   partitionAndRemesh((GFaceCompound*) gf);
-   isMeshed = true;
-   return isMeshed;
-  }
-
-  //Replace edges by their compounds
-  std::set<GEdge*> mySet;
-  std::list<GEdge*>::iterator it = edges.begin();
-  while(it != edges.end()){
-    if((*it)->getCompound()){
-      mySet.insert((*it)->getCompound());
-    }
-    else{
-      mySet.insert(*it);
-    }
-    ++it;
-  }
-  edges.clear();
-  edges.insert(edges.begin(), mySet.begin(), mySet.end());
-#endif
-  return isMeshed;
-}
-
-void partitionAndRemesh(GFaceCompound *gf)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN) && (defined(HAVE_CHACO) || defined(HAVE_METIS))
-
-  // Partition the mesh and createTopology for new faces
-  double tbegin = Cpu();
-  std::list<GFace*> cFaces = gf->getCompounds();
-  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++)
-      elements.push_back((*it)->getMeshElement(j));
-
-  typeOfPartition method;
-  if(gf->nbSplit > 0) method = MULTILEVEL;
-  else method = LAPLACIAN;
-
-  int allowType = gf->allowPartition();
-  multiscalePartition *msp = new multiscalePartition(elements, abs(gf->nbSplit),
-                                                     method, allowType);
-
-  int NF = msp->getNumberOfParts();
-  int numv = gf->model()->getMaxElementaryNumber(0) + 1;
-  int nume = gf->model()->getMaxElementaryNumber(1) + 1;
-  int numf = gf->model()->getMaxElementaryNumber(2) + 1;
-  std::vector<discreteFace*> pFaces;
-  createPartitionFaces(gf->model(), elements, NF, pFaces);
-
-  gf->model()->createTopologyFromFaces(pFaces);
-
-  double tmult = Cpu();
-  Msg::Info("Multiscale Partition SUCCESSFULLY PERFORMED : %d parts (%g s)",
-            NF, tmult - tbegin);
-  gf->model()->writeMSH("multiscalePARTS.msh", 2.2, false, true);
-
-  // Remesh new faces (Compound Lines and Compound Surfaces)
-  Msg::Info("*** Starting parametrize compounds:");
-  double t0 = Cpu();
-
-  //Parametrize Compound Lines
-  int NE = gf->model()->getMaxElementaryNumber(1) - nume + 1;
-  for (int i=0; i < NE; i++){
-    std::vector<GEdge*>e_compound;
-    GEdge *pe = gf->model()->getEdgeByTag(nume+i);//partition edge
-    e_compound.push_back(pe);
-    int num_gec = nume + NE + i ;
-    Msg::Info("Parametrize Compound Line (%d) = %d discrete edge",
-              num_gec, pe->tag());
-    GEdgeCompound *gec = new GEdgeCompound(gf->model(), num_gec, e_compound);
-    gf->model()->add(gec);
-  }
-
-  // Parametrize Compound surfaces
-  std::set<MVertex*> allNod;
-  std::list<GEdge*> U0;
-  for (int i=0; i < NF; i++){
-    std::list<GFace*> f_compound;
-    GFace *pf =  gf->model()->getFaceByTag(numf+i);//partition face
-    int num_gfc = numf + NF + i ;
-    f_compound.push_back(pf);
-    Msg::Info("Parametrize Compound Surface (%d) = %d discrete face",
-              num_gfc, pf->tag());
-
-    GFaceCompound *gfc = new GFaceCompound(gf->model(), num_gfc, f_compound, U0,
-                                           gf->getTypeOfCompound());
-
-    gfc->meshAttributes.recombine = gf->meshAttributes.recombine;
-    gf->model()->add(gfc);
-
-    gfc->parametrize();
-  }
-
-  double t1 = Cpu();
-  Msg::Info("*** Parametrize compounds done (%g s)", t1-t0);
-  Msg::Info("*** Starting meshing 1D edges ...:");
-  for (int i = 0; i < NE; i++){
-    GEdge *gec = gf->model()->getEdgeByTag(nume + NE + i);
-    meshGEdge mge;
-    mge(gec);
-  }
-  double t2 = Cpu();
-  Msg::Info("*** Meshing 1D edges done (%gs)", t2-t1);
-
-  Msg::Info("*** Starting Mesh of surface %d ...", gf->tag());
-
-  for (int i=0; i < NF; i++){
-    GFace *gfc =  gf->model()->getFaceByTag(numf + NF + i );
-    meshGFace mgf;
-    mgf(gfc);
-
-    for(unsigned int j = 0; j < gfc->triangles.size(); ++j){
-      MTriangle *t = gfc->triangles[j];
-      std::vector<MVertex *> v(3);
-      for(int k = 0; k < 3; k++){
-        v[k] = t->getVertex(k);
-        allNod.insert(v[k]);
-      }
-      gf->triangles.push_back(new MTriangle(v[0], v[1], v[2]));
-    }
-    for(unsigned int j = 0; j < gfc->quadrangles.size(); ++j){
-      MQuadrangle *q = gfc->quadrangles[j];
-      std::vector<MVertex *> v(4);
-      for(int k = 0; k < 4; k++){
-        v[k] = q->getVertex(k);
-        allNod.insert(v[k]);
-      }
-      gf->quadrangles.push_back(new MQuadrangle(v[0], v[1], v[2], v[3]));
-    }
-
-    //update mesh statistics
-    gf->meshStatistics.efficiency_index += gfc->meshStatistics.efficiency_index;
-    gf->meshStatistics.longest_edge_length = std::max(gf->meshStatistics.longest_edge_length,
-                                                     gfc->meshStatistics.longest_edge_length);
-    gf->meshStatistics.smallest_edge_length= std::min(gf->meshStatistics.smallest_edge_length,
-                                                      gfc->meshStatistics.smallest_edge_length);
-    gf->meshStatistics.nbGoodLength  += gfc->meshStatistics.nbGoodLength;
-    gf->meshStatistics.nbGoodQuality += gfc->meshStatistics.nbGoodQuality;
-    gf->meshStatistics.nbEdge += gfc->meshStatistics.nbEdge;
-
-  }
-
-  // Removing discrete Vertices - Edges - Faces
-  int NV = gf->model()->getMaxElementaryNumber(0) - numv + 1;
-  for (int i=0; i < NV; i++){
-    GVertex *pv = gf->model()->getVertexByTag(numv+i);
-    gf->model()->remove(pv);
-  }
-  for (int i=0; i < NE; i++){
-    GEdge *gec = gf->model()->getEdgeByTag(nume+NE+i);
-    GEdge *pe = gf->model()->getEdgeByTag(nume+i);
-    gf->model()->remove(pe);
-    gf->model()->remove(gec);
-  }
-  for (int i=0; i < NF; i++){
-    GFace *gfc = gf->model()->getFaceByTag(numf+NF+i);
-    GFace *pf  = gf->model()->getFaceByTag(numf+i);
-    gf->model()->remove(pf);
-    gf->model()->remove(gfc);
-  }
-
-  // Put new mesh in a new discreteFace
-  for(std::set<MVertex*>::iterator it = allNod.begin(); it != allNod.end(); ++it){
-    gf->mesh_vertices.push_back(*it);
-  }
-
-  // FIXME: This horrible hack is necessary to remove vertices that might belong
-  // to a GVertex.  The true fix is rewrite this part of the code: it's far too
-  // complex and error prone.
-  for(GModel::viter it = gf->model()->firstVertex(); it != gf->model()->lastVertex(); it++){
-    std::vector<MVertex*>::iterator itve = std::find
-      (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), (*it)->mesh_vertices[0]);
-    if(itve != gf->mesh_vertices.end())
-      gf->mesh_vertices.erase(itve);
-  }
-
-  // Remove mesh_vertices that belong to l_edges
-  std::list<GEdge*> l_edges = gf->edges();
-  for(std::list<GEdge*>::iterator it = l_edges.begin(); it != l_edges.end(); it++){
-    std::vector<MVertex*> edge_vertices = (*it)->mesh_vertices;
-    std::vector<MVertex*>::const_iterator itv = edge_vertices.begin();
-    for(; itv != edge_vertices.end(); itv++){
-      std::vector<MVertex*>::iterator itve = std::find
-        (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), *itv);
-      if (itve != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itve);
-    }
-    MVertex *vB = (*it)->getBeginVertex()->mesh_vertices[0];
-    std::vector<MVertex*>::iterator itvB = std::find
-      (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vB);
-    if (itvB != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvB);
-    MVertex *vE = (*it)->getEndVertex()->mesh_vertices[0];
-    std::vector<MVertex*>::iterator itvE = std::find
-      (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vE);
-    if (itvE != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvE);
-
-    //if l_edge is a compond
-    if((*it)->getCompound()){
-      GEdgeCompound *gec = (*it)->getCompound();
-      std::vector<MVertex*> edge_vertices = gec->mesh_vertices;
-      std::vector<MVertex*>::const_iterator itv = edge_vertices.begin();
-      for(; itv != edge_vertices.end(); itv++){
-        std::vector<MVertex*>::iterator itve = std::find
-          (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), *itv);
-        if (itve != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itve);
-      }
-      MVertex *vB = (*it)->getBeginVertex()->mesh_vertices[0];
-      std::vector<MVertex*>::iterator itvB = std::find
-        (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vB);
-      if (itvB != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvB);
-      MVertex *vE = (*it)->getEndVertex()->mesh_vertices[0];
-      std::vector<MVertex*>::iterator itvE = std::find
-        (gf->mesh_vertices.begin(), gf->mesh_vertices.end(), vE);
-      if (itvE != gf->mesh_vertices.end()) gf->mesh_vertices.erase(itvE);
-    }
-  }
-
-  double t3 = Cpu();
-  Msg::Info("*** Mesh of surface %d done by assembly %d remeshed faces (%g s)",
-            gf->tag(), NF, t3-t2);
-  Msg::Info("-----------------------------------------------------------");
-
-  gf->coherenceNormals();
-  gf->meshStatistics.status = GFace::DONE;
-#endif
-}
-
 static bool getGFaceNormalFromVert(GFace *gf, MElement *el, SVector3 &nf)
 {
   bool found = false;
@@ -2832,8 +2568,7 @@ void orientMeshGFace::operator()(GFace *gf)
   gf->model()->setCurrentMeshEntity(gf);
 
   if(gf->geomType() == GEntity::DiscreteSurface ||
-     gf->geomType() == GEntity::BoundaryLayerSurface ||
-     gf->geomType() == GEntity::CompoundSurface){
+     gf->geomType() == GEntity::BoundaryLayerSurface){
     // don't do anything
   }
   else {
diff --git a/Mesh/meshGFaceBamg.cpp b/Mesh/meshGFaceBamg.cpp
index 7cf9ae6b0778ca3f3696f5b5ff086f2182aacf03..250a0a53e08c528bd659dd396a080c93e29b2b11 100644
--- a/Mesh/meshGFaceBamg.cpp
+++ b/Mesh/meshGFaceBamg.cpp
@@ -20,7 +20,6 @@
 #include "meshGFaceDelaunayInsertion.h"
 #include "Options.h"
 #include "meshGFace.h"
-#include "GFaceCompound.h"
 #include "MElementOctree.h"
 
 #if defined(HAVE_BAMG)
@@ -74,21 +73,13 @@ static void computeMeshMetricsForBamg(GFace *gf, int numV,
 void meshGFaceBamg(GFace *gf){
 
    std::list<GEdge*> edges = gf->edges();
-   bool hasCompounds  = false;
 
   //Replace edges by their compounds
    std::set<GEdge*> mySet;
    std::list<GEdge*>::iterator it = edges.begin();
    while(it != edges.end()){
-    if((*it)->getCompound()){
-      hasCompounds = true;
-      GEdge *gec = (GEdge*)(*it)->getCompound();
-      mySet.insert(gec);
-    }
-    else{
-      mySet.insert(*it);
-    }
-    ++it;
+     mySet.insert(*it);
+     ++it;
    }
    edges.clear();
    edges.insert(edges.begin(), mySet.begin(), mySet.end());
@@ -149,16 +140,6 @@ void meshGFaceBamg(GFace *gf){
     double v1(bamgVertices[nodes[0]][1]);
     double v2(bamgVertices[nodes[1]][1]);
     double v3(bamgVertices[nodes[2]][1]);
-    if (hasCompounds){
-      MVertex *vv1 = new MVertex(u1,v1,0.0);
-      MVertex *vv2 = new MVertex(u2,v2,0.0);
-      MVertex *vv3 = new MVertex(u3,v3,0.0);
-      newVert.push_back(vv1);
-      newVert.push_back(vv2);
-      newVert.push_back(vv3);
-      MTriangle *tri = new MTriangle(vv1,vv2,vv3, i);
-      myParamElems.push_back(tri);
-    }
     double sign = (u2-u1)*(v3-v1) - (u3-u1)*(v2-v1);
     if (sign < 0){
       int temp = nodes[0];
@@ -189,9 +170,6 @@ void meshGFaceBamg(GFace *gf){
 			       bamgVertices, bamgTriangles, bamgBoundary);
 
   MElementOctree *_octree = NULL;
-  if (hasCompounds){
-    _octree = new MElementOctree(myParamElems);
-  }
 
   Mesh2 *refinedBamgMesh = 0;
   int iterMax = 41;
@@ -239,27 +217,6 @@ void meshGFaceBamg(GFace *gf){
       // }
       //If point not found because compound edges have been remeshed and boundary triangles have changed
       //then we call our new octree
-      if ( !gp.succeeded() && hasCompounds){
-	double uvw[3] = {v[0],v[1], 0.0};
-	double UV[3];
-	double initialTol = MElement::getTolerance();
-	MElement::setTolerance(1.e-2);
-	MElement *e = _octree->find(v[0],v[1], 0.0, -1);
-	MElement::setTolerance(initialTol);
-	if (e){
-	  e->xyz2uvw(uvw,UV);
-	  double valX[8], valY[8], valZ[8];
-	  for (int i=0;i<e->getNumPrimaryVertices();i++){
-	    int numTri = e->getNum();
-	    valX[i] = gf->triangles[numTri]->getVertex(i)->x();
-	    valY[i] = gf->triangles[numTri]->getVertex(i)->y();
-	    valZ[i] = gf->triangles[numTri]->getVertex(i)->z();
-	  }
-	  gp.x() = e->interpolate(valX,UV[0],UV[1],UV[2]);
-	  gp.y() = e->interpolate(valY,UV[0],UV[1],UV[2]);
-	  gp.z() = e->interpolate(valZ,UV[0],UV[1],UV[2]);
-	}
-      }
       MFaceVertex *x = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, v[0], v[1]);
       yetAnother[i] = x;
       gf->mesh_vertices.push_back(x);
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index 37b7e568916088dadc7dd90b9ee8ef052cac24ec..5e5afb43d6993079fa072ae18313ba19718333ac 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -23,7 +23,6 @@
 #include "MQuadrangle.h"
 #include "Field.h"
 #include "GModel.h"
-#include "GFaceCompound.h"
 #include "discreteDiskFace.h"
 #include "intersectCurveSurface.h"
 #include "HilbertCurve.h"
@@ -1327,18 +1326,6 @@ bool optimalPointFrontalB (GFace *gf,
   }
 #endif
 
-  if (gf->geomType() == GEntity::CompoundSurface){
-    GFaceCompound *gfc = dynamic_cast<GFaceCompound*> (gf);
-    if (gfc){
-      GPoint gp = gfc->intersectionWithCircle(n2,n1,middle,d,newPoint);
-      if (gp.succeeded()){
-	newPoint[0] = gp.u();
-	newPoint[1] = gp.v();
-	return true;
-      }
-    }
-  }
-
   double uvt[3] = {newPoint[0],newPoint[1],0.0};
   curveFunctorCircle cc (n2,n1,middle,d);
   surfaceFunctorGFace ss (gf);
diff --git a/Mesh/meshGFaceLloyd.cpp b/Mesh/meshGFaceLloyd.cpp
index eb265729fddc3a2ad3844996c922ea3c9c4d4fef..a29c83aa6f293993537d6696e0af0087778273f0 100644
--- a/Mesh/meshGFaceLloyd.cpp
+++ b/Mesh/meshGFaceLloyd.cpp
@@ -413,8 +413,9 @@ smoothing::smoothing(int param1,int param2){
   NORM = param2;
 }
 
-void smoothing::optimize_face(GFace* gf){
-  if(gf->getNumMeshElements()==0 || gf->getCompound()) return;
+void smoothing::optimize_face(GFace* gf)
+{
+  if(gf->getNumMeshElements()==0) return;
 
   std::set<MVertex*> all;
 
@@ -600,10 +601,10 @@ void smoothing::optimize_model(){
   for(it=model->firstFace();it!=model->lastFace();it++)
   {
     gf = *it;
-	if(gf->getNumMeshElements()>0 && !gf->getCompound() /*&& gf->geomType()==GEntity::CompoundSurface*/){
-	  optimize_face(gf);
-	  //recombineIntoQuads(gf,1,1);
-	}
+    if(gf->getNumMeshElements()>0){
+      optimize_face(gf);
+      //recombineIntoQuads(gf,1,1);
+    }
   }
 }
 
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index bb9715703edcb45713c594e240fdb8a681d588ea..5a9b0dadc032c65e731fdac442a9d74be33f2a0c 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -1173,7 +1173,6 @@ int edgeSwapPass2(GFace *gf, std::set<MTri3*, compareTri3Ptr> &allTris,
 static int _recombineIntoQuads(GFace *gf, double minqual, bool cubicGraph = 1)
 {
   // never recombine a face that is part of a compound!
-  if(gf->getCompound()) return 0;
   if(gf->triangles.size() == 0) return 1;
 
   int success = 1;
@@ -1444,7 +1443,7 @@ void recombineIntoQuads(GFace *gf,
 
   bool haveParam = true;
   bool saveAll = CTX::instance()->mesh.saveAll;
-  if(gf->geomType() == GEntity::DiscreteSurface && !gf->getCompound())
+  if(gf->geomType() == GEntity::DiscreteSurface)
     haveParam = false;
 
   if (saveAll) gf->model()->writeMSH("before.msh");
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index 7f2864c378d9de09b329a61794d50846f6b8acb1..c30c609351679ac0443ff173b00ed9deeb6a6dae 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -30,7 +30,6 @@
 #include "BDS.h"
 #include "OS.h"
 #include "Context.h"
-#include "GFaceCompound.h"
 #include "meshGRegionMMG3D.h"
 #include "simple3D.h"
 #include "directions3D.h"
@@ -1076,22 +1075,6 @@ void meshGRegion::operator() (GRegion *gr)
     }
   }
 
-  // replace discreteFaces by their compounds
-  {
-    std::set<GFace*, GEntityLessThan> mySet;
-    std::list<GFace*>::iterator it = faces.begin();
-    while(it != faces.end()){
-      if((*it)->getCompound())
-        mySet.insert((*it)->getCompound());
-      else
-        mySet.insert(*it);
-      ++it;
-    }
-    faces.clear();
-    faces.insert(faces.begin(), mySet.begin(), mySet.end());
-    gr->set(faces);
-  }
-
   if(CTX::instance()->mesh.algo3d != ALGO_3D_FRONTAL){
     delaunay.push_back(gr);
   }
diff --git a/Mesh/meshPartition.cpp b/Mesh/meshPartition.cpp
index 62ed7f260bdf6e6b53d37bc1ef0acca251f6e7bf..951852d94496783527285c90cc3897043d05878e 100644
--- a/Mesh/meshPartition.cpp
+++ b/Mesh/meshPartition.cpp
@@ -28,7 +28,6 @@
 #include "discreteEdge.h"
 #include "discreteFace.h"
 #include "discreteRegion.h"
-#include "GFaceCompound.h"
 
 //--Prototype for Chaco interface
 
diff --git a/Mesh/meshPartition.h b/Mesh/meshPartition.h
index fcc593b492b16e4c7a991fd9211dfce8aa89f25e..6da2a9a9b1ee567e452719e7b303b0bb4333c4df 100644
--- a/Mesh/meshPartition.h
+++ b/Mesh/meshPartition.h
@@ -8,7 +8,6 @@
 
 #include <vector>
 #include "partitionEdge.h"
-#include "GFaceCompound.h"
 #include "GFace.h"
 
 class GModel;
@@ -27,7 +26,7 @@ int RenumberGraph(Graph &graph, meshPartitionOptions &options);
 int PartitionMesh(GModel *const model, meshPartitionOptions &options);
 int RenumberMesh(GModel *const model, meshPartitionOptions &options);
 int PartitionMeshFace(std::list<GFace*> &cFaces, meshPartitionOptions &options);
-int PartitionMeshElements(std::vector<MElement*> &elements, 
+int PartitionMeshElements(std::vector<MElement*> &elements,
                           meshPartitionOptions &options);
 int CreatePartitionBoundaries(GModel *model, bool createGhostCells, bool createAllDims = false);
 
diff --git a/Mesh/multiscalePartition.cpp b/Mesh/multiscalePartition.cpp
deleted file mode 100644
index 0bd30710b28ccda54ecf74fe47defb4ba4202be6..0000000000000000000000000000000000000000
--- a/Mesh/multiscalePartition.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-//
-// Contributor(s):
-//   Emilie Marchandise
-
-#include "multiscalePartition.h"
-#include "GmshConfig.h"
-#include "GmshDefines.h"
-#include "meshPartition.h"
-#include "MEdge.h"
-#include "MElement.h"
-#include "multiscaleLaplace.h"
-#include "GFaceCompound.h"
-#include "Numeric.h"
-#include "Context.h"
-#include "OS.h"
-
-static void recur_connect(MVertex *v,
-                          std::multimap<MVertex*,MEdge> &v2e,
-                          std::set<MEdge,Less_Edge> &group,
-                          std::set<MVertex*> &touched)
-{
-  if (touched.find(v) != touched.end())return;
-
-  touched.insert(v);
-  for (std::multimap <MVertex*,MEdge>::iterator it = v2e.lower_bound(v);
-       it != v2e.upper_bound(v) ; ++it){
-    group.insert(it->second);
-    for (int i=0;i<it->second.getNumVertices();++i){
-      recur_connect (it->second.getVertex(i),v2e,group,touched);
-    }
-  }
-
-}
-
-
-// starting form a list of elements, returns
-// lists of lists that are all simply connected
-static void recur_connect_e (const MEdge &e,
-                             std::multimap<MEdge,MElement*,Less_Edge> &e2e,
-                             std::set<MElement*> &group,
-                             std::set<MEdge,Less_Edge> &touched){
-  if (touched.find(e) != touched.end())return;
-  touched.insert(e);
-  for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(e);
-         it != e2e.upper_bound(e) ; ++it){
-    group.insert(it->second);
-    for (int i=0;i<it->second->getNumEdges();++i){
-      recur_connect_e (it->second->getEdge(i),e2e,group,touched);
-    }
-  }
-}
-
-
-static int connected_bounds (std::vector<MEdge> &edges,  std::vector<std::vector<MEdge> > &boundaries)
-{
-  std::multimap<MVertex*,MEdge> v2e;
-  for (unsigned i = 0; i < edges.size(); ++i){
-    for (int j=0;j<edges[i].getNumVertices();j++){
-      v2e.insert(std::make_pair(edges[i].getVertex(j),edges[i]));
-    }
-  }
-  while (!v2e.empty()){
-    std::set<MEdge, Less_Edge> group;
-    std::set<MVertex*> touched;
-    recur_connect (v2e.begin()->first,v2e,group,touched);
-    std::vector<MEdge> temp;
-    temp.insert(temp.begin(), group.begin(), group.end());
-    boundaries.push_back(temp);
-    for (std::set<MVertex*>::iterator it = touched.begin() ; it != touched.end();++it)
-      v2e.erase(*it);
-  }
-
-  return boundaries.size();
-}
-
-//--------------------------------------------------------------
-static void connectedRegions (std::vector<MElement*> &elements,
-                              std::vector<std::vector<MElement*> > &regions)
-{
-  std::multimap<MEdge,MElement*,Less_Edge> e2e;
-  for (unsigned int i = 0; i < elements.size(); ++i){
-    for (int j = 0; j < elements[i]->getNumEdges(); j++){
-      e2e.insert(std::make_pair(elements[i]->getEdge(j),elements[i]));
-    }
-  }
-  while (!e2e.empty()){
-    std::set<MElement*> group;
-    std::set<MEdge,Less_Edge> touched;
-    recur_connect_e (e2e.begin()->first,e2e,group,touched);
-    std::vector<MElement*> temp;
-    temp.insert(temp.begin(), group.begin(), group.end());
-    regions.push_back(temp);
-    for ( std::set<MEdge,Less_Edge>::iterator it = touched.begin() ; it != touched.end();++it)
-      e2e.erase(*it);
-  }
-}
-
-static int getGenus (std::vector<MElement *> &elements,
-                     std::vector<std::vector<MEdge> > &boundaries)
-{
-
-  //We suppose MElements are simply connected
-
-  std::set<MEdge, Less_Edge> es;
-  std::set<MVertex*> vs;
-  int N = 0;
-  for(unsigned int i = 0; i < elements.size(); i++){
-    N++;
-    MElement *e = elements[i];
-    for(int j = 0; j < e->getNumVertices(); j++){
-      vs.insert(e->getVertex(j));
-    }
-    for(int j = 0; j < e->getNumEdges(); j++){
-      es.insert(e->getEdge(j));
-    }
-  }
-
-  int poincare = vs.size() - es.size() + N;
-
-  //compute connected boundaries
-  int nbBounds = 0;
-  std::vector<MEdge> bEdges;
-  for(unsigned int i = 0; i < elements.size(); i++){
-    for(int j = 0; j < elements[i]->getNumEdges(); j++){
-      MEdge me =  elements[i]->getEdge(j);
-      if(std::find(bEdges.begin(), bEdges.end(), me) == bEdges.end())
-         bEdges.push_back(me);
-      else
-         bEdges.erase(std::find(bEdges.begin(), bEdges.end(),me));
-    }
-  }
-  nbBounds = connected_bounds(bEdges, boundaries);
-  int genus = (int)(-poincare + 2 - nbBounds)/2;
-
-  //printf("************** partition has %d boundaries and genus =%d \n", nbBounds, genus);
-
-  return genus;
-
-}
-
-static int getAspectRatio(std::vector<MElement *> &elements,
-                          std::vector<std::vector<MEdge> > &boundaries)
-{
-
-  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;
-  }
-
-  double tot_length = 0.0;
-  for(unsigned int i = 0; i <boundaries.size(); ++i){
-    std::vector<MEdge> iBound = boundaries[i];
-    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;
-    }
-    tot_length += iLength;
-  }
-  int AR = 1;
-  if (boundaries.size() > 0){
-    tot_length /= boundaries.size();
-    AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length));
-  }
-
-  //compute AR also with Bounding box
-  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 = 10e4;
-  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::min(D, iD);
-
-    //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds);
-    //D = std::max(D, obboxD.getMaxSize());
-  }
-  int AR2 = (int)ceil(H/D);
-
-  return std::max(AR, AR2);
-}
-
-static void getGenusAndRatio(std::vector<MElement *> &elements, int & genus, int &AR, int &NB)
-{
-  std::vector<std::vector<MEdge> > boundaries;
-  boundaries.clear();
-  genus = getGenus(elements, boundaries);
-  NB = boundaries.size();
-  AR = getAspectRatio(elements, boundaries);
-
-}
-static void partitionRegions(std::vector<MElement*> &elements,
-                             std::vector<std::vector<MElement*> > &regions)
-{
-
-  for (unsigned int i = 0; i < elements.size(); ++i){
-    MElement *e = elements[i];
-    int part = e->getPartition();
-    regions[part-1].push_back(e);
-  }
-
-  std::vector<std::vector<MElement*> > allRegions;
-  for (unsigned int k = 0; k < regions.size(); ++k){
-    std::vector<std::vector<MElement*> >  conRegions;
-    conRegions.clear();
-    connectedRegions (regions[k], conRegions);
-    for (unsigned int j = 0; j < conRegions.size(); j++)
-      allRegions.push_back(conRegions[j]);
-  }
-  regions.clear();
-  regions.resize(allRegions.size());
-  regions = allRegions;
-
-}
-
-/*
-static void printLevel(std::vector<MElement *> &elements, int recur, int region)
-{
-  char fn[256];
-  sprintf(fn, "part_%d_%d.msh", recur, region);
-  double version = 2.2;
-
-  std::set<MVertex*> vs;
-  for (unsigned 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");
-  if(fp){
-    fprintf(fp, "$MeshFormat\n");
-    fprintf(fp, "%g %d %d\n", version, binary ? 1 : 0, (int)sizeof(double));
-    fprintf(fp, "$EndMeshFormat\n");
-
-    fprintf(fp,"$Nodes\n%d\n", (int)vs.size());
-    std::set<MVertex*> :: iterator it = vs.begin();
-    int index = 1;
-    for (; it != vs.end() ; ++it){
-      (*it)->setIndex(index++);
-      fprintf(fp,"%d %g %g %g\n",(*it)->getIndex(),
-              (*it)->x(),(*it)->y(),(*it)->z());
-    }
-    fprintf(fp,"$EndNodes\n");
-
-    fprintf(fp,"$Elements\n%d\n", (int)elements.size());
-    for (unsigned int i = 0; i < elements.size(); i++){
-      elements[i]->writeMSH(fp, version);
-    }
-    fprintf(fp,"$EndElements\n%d\n", (int)elements.size());
-
-    fclose(fp);
-  }
-}
-*/
-
-multiscalePartition::multiscalePartition(std::vector<MElement *> &elements,
-                                         int nbParts, typeOfPartition method,
-					 int allowPartition)
-{
-  options = CTX::instance()->partitionOptions;
-  options.num_partitions = nbParts;
-  options.partitioner = 1; //1 CHACO, 2 METIS
-  if (options.partitioner == 1){
-    options.global_method = 1;// 1 Multilevel-KL, 2 Spectral
-    options.mesh_dims[0] = nbParts;
-  }
-  else if (options.partitioner == 2){
-    options.algorithm = 2;//1 recursive, 2=kway, 3=nodal weights
-    options.refine_algorithm=2;
-    options.edge_matching = 3;
-  }
-
-  partitionLevel *level = new partitionLevel;
-  level->elements.insert(level->elements.begin(),elements.begin(),elements.end());
-  level->recur = 0;
-  level->region = 0;
-
-  levels.push_back(level);
-  onlyMultilevel = false;
-  if (allowPartition == 2)  onlyMultilevel = true;
-
-  partition(*level, nbParts, method);
-
-  totalParts = assembleAllPartitions(elements);
-
-}
-
-void multiscalePartition::setNumberOfPartitions(int &nbParts)
-{
-  options.num_partitions = nbParts;
-   if (options.partitioner == 1){
-     options.mesh_dims[0] = nbParts;
-   }
-}
-
-void multiscalePartition::partition(partitionLevel & level, int nbParts,
-                                    typeOfPartition method)
-{
-#if defined(HAVE_SOLVER) && defined(HAVE_ANN) && (defined(HAVE_METIS) || defined(HAVE_CHACO))
-
-  if (method == LAPLACIAN){
-    std::map<MVertex*, SPoint3> coordinates;
-    multiscaleLaplace multiLaplace(level.elements, coordinates);
-  }
-  else if (method == MULTILEVEL){
-    setNumberOfPartitions(nbParts);
-    PartitionMeshElements(level.elements, options);
-  }
-
-  std::vector<std::vector<MElement*> > regions(nbParts);
-  partitionRegions(level.elements, regions);
-  level.elements.clear();
-
-  for (unsigned i=0;i< regions.size() ; i++){
-
-    partitionLevel *nextLevel = new partitionLevel;
-    nextLevel->elements = regions[i];
-    nextLevel->recur = level.recur+1;
-    nextLevel->region = i;
-
-    levels.push_back(nextLevel);
-    int genus, AR, NB;
-    getGenusAndRatio(regions[i], genus, AR, NB);
-
-    if (genus < 0) {
-      Msg::Error("Genus partition is negative G=%d!", genus);
-      return;
-    }
-
-    if (genus != 0 ){
-      int nbParts = std::max(genus+2,2);
-      Msg::Info("Mesh partition: level (%d-%d)  is %d-GENUS (AR=%d) "
-                "---> MULTILEVEL partition %d parts",
-                nextLevel->recur,nextLevel->region, genus, AR, nbParts);
-      partition(*nextLevel, nbParts, MULTILEVEL);
-    }
-    else if ((genus == 0  &&  AR > AR_MAX) || (genus == 0  &&  NB > 1)){
-      int nbParts = 2;
-      if(!onlyMultilevel){
-	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 NB=%d) "
-                  "---> MULTILEVEL partition %d parts",
-                  nextLevel->recur,nextLevel->region, AR, NB, nbParts);
-        partition(*nextLevel, nbParts, MULTILEVEL);
-      }
-    }
-    else {
-      Msg::Info("*** Mesh partition: level (%d-%d) is ZERO-GENUS (AR=%d, NB=%d)",
-                nextLevel->recur,nextLevel->region, AR, NB);
-    }
-
-  }
-
-#endif
-}
-
-int multiscalePartition::assembleAllPartitions(std::vector<MElement*> & elements)
-{
-  int iPart =  1;
-
-  elements.clear();
-  for (unsigned i = 0; i< levels.size(); i++){
-    partitionLevel *iLevel = levels[i];
-    if(iLevel->elements.size() > 0){
-      for (unsigned j = 0; j < iLevel->elements.size(); j++){
-        MElement *e = iLevel->elements[j];
-	elements.push_back(e);
-        e->setPartition(iPart);
-      }
-      iPart++;
-    }
-  }
-
-  return iPart - 1;
-}
diff --git a/Mesh/multiscalePartition.h b/Mesh/multiscalePartition.h
deleted file mode 100644
index 3f44ad525db693e8a6ea3e7b0d35c03f5f7f54cb..0000000000000000000000000000000000000000
--- a/Mesh/multiscalePartition.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-//
-// Contributor(s):
-//   Emilie Marchandise
-
-#ifndef _MULTI_PARTITION_H_
-#define _MULTI_PARTITION_H_
-
-#include <vector>
-#include <map>
-#include "linearSystemGMM.h"
-#include "meshPartitionOptions.h"
-#include "meshPartition.h"
-
-class MElement;
-class meshPartitionOptions;
-
-struct partitionLevel {
-  int recur;
-  int region;
-  std::vector<MElement *> elements;
-};
-
-typedef enum {LAPLACIAN= 0, MULTILEVEL=1} typeOfPartition;
-
-class multiscalePartition{
-
- private:
-  std::vector<partitionLevel*> levels;
-  void partition(partitionLevel &level, int nbParts,  typeOfPartition method);
-  int totalParts;
-  bool onlyMultilevel;
-  meshPartitionOptions options;
-
- public:
-  multiscalePartition(std::vector<MElement *> &elements, int nbParts, 
-		      typeOfPartition method, int allowPartition);
-  int assembleAllPartitions(std::vector<MElement*> & elements);
-  void setNumberOfPartitions(int &nbParts);
-  int getNumberOfParts(){return totalParts;}
-};
-
-#endif
diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp
index 833158f6e5a05d59d49f6bafe7b32ef60515875a..c6ae1b0ffeb1adde9f5c9833eea4cb0e2372ee9a 100644
--- a/Parser/Gmsh.tab.cpp
+++ b/Parser/Gmsh.tab.cpp
@@ -1440,48 +1440,48 @@ static const yytype_uint16 yyrline[] =
     1540,  1549,  1552,  1559,  1562,  1569,  1593,  1609,  1625,  1662,
     1702,  1718,  1734,  1756,  1772,  1791,  1807,  1828,  1839,  1845,
     1851,  1858,  1889,  1904,  1926,  1949,  1972,  1995,  2019,  2043,
-    2067,  2093,  2110,  2126,  2144,  2162,  2192,  2222,  2221,  2251,
-    2253,  2255,  2257,  2259,  2267,  2269,  2271,  2273,  2281,  2283,
-    2285,  2293,  2295,  2297,  2299,  2309,  2325,  2341,  2357,  2373,
-    2389,  2426,  2448,  2472,  2473,  2478,  2481,  2485,  2501,  2519,
-    2537,  2562,  2581,  2602,  2617,  2633,  2651,  2702,  2723,  2745,
-    2768,  2873,  2889,  2924,  2946,  2968,  2974,  2989,  3017,  3029,
-    3038,  3045,  3057,  3076,  3080,  3085,  3089,  3094,  3101,  3108,
-    3115,  3127,  3200,  3218,  3235,  3250,  3283,  3295,  3319,  3323,
-    3328,  3335,  3340,  3350,  3355,  3361,  3369,  3373,  3377,  3386,
-    3450,  3466,  3483,  3500,  3522,  3544,  3579,  3587,  3595,  3601,
-    3608,  3615,  3635,  3661,  3673,  3684,  3702,  3720,  3739,  3738,
-    3763,  3762,  3789,  3788,  3813,  3812,  3835,  3851,  3868,  3885,
-    3908,  3911,  3917,  3929,  3949,  3953,  3957,  3961,  3965,  3969,
-    3973,  3977,  3986,  3999,  4000,  4001,  4002,  4003,  4007,  4008,
-    4009,  4010,  4011,  4014,  4038,  4057,  4080,  4083,  4099,  4102,
-    4119,  4122,  4128,  4131,  4138,  4141,  4148,  4170,  4211,  4255,
-    4294,  4319,  4328,  4358,  4384,  4410,  4442,  4469,  4495,  4521,
-    4547,  4573,  4595,  4606,  4654,  4703,  4715,  4726,  4733,  4748,
-    4762,  4763,  4764,  4768,  4774,  4786,  4804,  4832,  4833,  4834,
-    4835,  4836,  4837,  4838,  4839,  4840,  4847,  4848,  4849,  4850,
-    4851,  4852,  4853,  4854,  4855,  4856,  4857,  4858,  4859,  4860,
-    4861,  4862,  4863,  4864,  4865,  4866,  4867,  4868,  4869,  4870,
-    4871,  4872,  4873,  4874,  4875,  4876,  4877,  4878,  4879,  4880,
-    4881,  4882,  4883,  4884,  4893,  4894,  4895,  4896,  4897,  4898,
-    4899,  4900,  4901,  4902,  4903,  4908,  4907,  4915,  4917,  4922,
-    4927,  4931,  4936,  4941,  4945,  4949,  4953,  4957,  4961,  4965,
-    4971,  4987,  4992,  4998,  5004,  5023,  5044,  5077,  5081,  5086,
-    5090,  5094,  5098,  5103,  5108,  5118,  5128,  5133,  5144,  5153,
-    5158,  5163,  5191,  5192,  5198,  5199,  5205,  5204,  5227,  5229,
-    5234,  5243,  5245,  5251,  5252,  5257,  5261,  5265,  5269,  5273,
-    5280,  5284,  5288,  5292,  5299,  5304,  5311,  5316,  5320,  5325,
-    5329,  5337,  5348,  5352,  5356,  5370,  5378,  5386,  5393,  5403,
-    5426,  5431,  5437,  5442,  5448,  5459,  5465,  5470,  5480,  5490,
-    5500,  5512,  5516,  5521,  5533,  5537,  5541,  5545,  5563,  5571,
-    5579,  5608,  5618,  5634,  5645,  5650,  5654,  5658,  5670,  5674,
-    5686,  5703,  5713,  5717,  5732,  5737,  5744,  5748,  5753,  5767,
-    5783,  5787,  5791,  5795,  5799,  5807,  5813,  5819,  5825,  5834,
-    5838,  5842,  5850,  5856,  5862,  5866,  5874,  5882,  5889,  5898,
-    5902,  5906,  5921,  5935,  5949,  5961,  5977,  5986,  5995,  6005,
-    6016,  6024,  6032,  6036,  6055,  6062,  6068,  6075,  6083,  6082,
-    6092,  6116,  6118,  6124,  6129,  6131,  6136,  6141,  6146,  6148,
-    6152,  6164,  6178,  6182,  6189,  6197,  6205,  6216,  6218,  6221
+    2067,  2093,  2110,  2126,  2144,  2162,  2168,  2176,  2175,  2205,
+    2207,  2209,  2211,  2213,  2221,  2223,  2225,  2227,  2235,  2237,
+    2239,  2247,  2249,  2251,  2253,  2263,  2279,  2295,  2311,  2327,
+    2343,  2380,  2402,  2426,  2427,  2432,  2435,  2439,  2455,  2473,
+    2491,  2516,  2535,  2556,  2571,  2587,  2605,  2656,  2677,  2699,
+    2722,  2827,  2843,  2878,  2900,  2922,  2928,  2943,  2971,  2983,
+    2992,  2999,  3011,  3030,  3034,  3039,  3043,  3048,  3055,  3062,
+    3069,  3081,  3154,  3172,  3189,  3204,  3237,  3249,  3273,  3277,
+    3282,  3289,  3294,  3304,  3309,  3315,  3323,  3327,  3331,  3340,
+    3404,  3420,  3437,  3454,  3476,  3498,  3533,  3541,  3549,  3555,
+    3562,  3569,  3589,  3615,  3627,  3638,  3656,  3674,  3693,  3692,
+    3717,  3716,  3743,  3742,  3767,  3766,  3789,  3805,  3822,  3839,
+    3862,  3865,  3871,  3883,  3903,  3907,  3911,  3915,  3919,  3923,
+    3927,  3931,  3940,  3953,  3954,  3955,  3956,  3957,  3961,  3962,
+    3963,  3964,  3965,  3968,  3992,  4011,  4034,  4037,  4053,  4056,
+    4073,  4076,  4082,  4085,  4092,  4095,  4102,  4124,  4165,  4209,
+    4248,  4273,  4282,  4312,  4338,  4364,  4396,  4423,  4449,  4475,
+    4501,  4527,  4549,  4560,  4608,  4657,  4669,  4680,  4687,  4702,
+    4716,  4717,  4718,  4722,  4728,  4740,  4758,  4786,  4787,  4788,
+    4789,  4790,  4791,  4792,  4793,  4794,  4801,  4802,  4803,  4804,
+    4805,  4806,  4807,  4808,  4809,  4810,  4811,  4812,  4813,  4814,
+    4815,  4816,  4817,  4818,  4819,  4820,  4821,  4822,  4823,  4824,
+    4825,  4826,  4827,  4828,  4829,  4830,  4831,  4832,  4833,  4834,
+    4835,  4836,  4837,  4838,  4847,  4848,  4849,  4850,  4851,  4852,
+    4853,  4854,  4855,  4856,  4857,  4862,  4861,  4869,  4871,  4876,
+    4881,  4885,  4890,  4895,  4899,  4903,  4907,  4911,  4915,  4919,
+    4925,  4941,  4946,  4952,  4958,  4977,  4998,  5031,  5035,  5040,
+    5044,  5048,  5052,  5057,  5062,  5072,  5082,  5087,  5098,  5107,
+    5112,  5117,  5145,  5146,  5152,  5153,  5159,  5158,  5181,  5183,
+    5188,  5197,  5199,  5205,  5206,  5211,  5215,  5219,  5223,  5227,
+    5234,  5238,  5242,  5246,  5253,  5258,  5265,  5270,  5274,  5279,
+    5283,  5291,  5302,  5306,  5310,  5324,  5332,  5340,  5347,  5357,
+    5380,  5385,  5391,  5396,  5402,  5413,  5419,  5424,  5434,  5444,
+    5454,  5466,  5470,  5475,  5487,  5491,  5495,  5499,  5517,  5525,
+    5533,  5562,  5572,  5588,  5599,  5604,  5608,  5612,  5624,  5628,
+    5640,  5657,  5667,  5671,  5686,  5691,  5698,  5702,  5707,  5721,
+    5737,  5741,  5745,  5749,  5753,  5761,  5767,  5773,  5779,  5788,
+    5792,  5796,  5804,  5810,  5816,  5820,  5828,  5836,  5843,  5852,
+    5856,  5860,  5875,  5889,  5903,  5915,  5931,  5940,  5949,  5959,
+    5970,  5978,  5986,  5990,  6009,  6016,  6022,  6029,  6037,  6036,
+    6046,  6070,  6072,  6078,  6083,  6085,  6090,  6095,  6100,  6102,
+    6106,  6118,  6132,  6136,  6143,  6151,  6159,  6170,  6172,  6175
 };
 #endif
 
@@ -8615,76 +8615,30 @@ yyreduce:
   case 185:
 #line 2163 "Gmsh.y"
     {
-      int num = (int)(yyvsp[(4) - (8)].d);
-      std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (8)].l), tags);
-      switch ((yyvsp[(2) - (8)].i)) {
-      case 1:
-        {
-          bool r = GModel::current()->getGEOInternals()->addCompoundLine(num, tags);
-          if(!r) yymsg(0, "Could not add compound line");
-        }
-        (yyval.s).Type = MSH_SEGM_COMPOUND;
-        break;
-      case 2:
-        {
-          bool r = GModel::current()->getGEOInternals()->addCompoundSurface(num, tags);
-          if(!r) yymsg(0, "Could not add compound surface");
-        }
-        (yyval.s).Type = MSH_SURF_COMPOUND;
-        break;
-      case 3:
-        {
-          bool r = GModel::current()->getGEOInternals()->addCompoundVolume(num, tags);
-          if(!r) yymsg(0, "Could not add compound volume");
-        }
-        (yyval.s).Type = MSH_VOLUME_COMPOUND;
-        break;
-      }
-      List_Delete((yyvsp[(7) - (8)].l));
-      (yyval.s).Num = num;
+      yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead");
+      (yyval.s).Type = 0;
+      (yyval.s).Num = 0;
     ;}
     break;
 
   case 186:
-#line 2194 "Gmsh.y"
-    {
-      // Particular case only for dim 2 (Surface)
-      if ((yyvsp[(2) - (12)].i) == 2) {
-        int num = (int)(yyvsp[(4) - (12)].d);
-        std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (12)].l), tags);
-        std::vector<int> bndTags[4];
-        for(int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++){
-          if(i < 4)
-            ListOfDouble2Vector(*(List_T**)List_Pointer((yyvsp[(10) - (12)].l), i), bndTags[i]);
-          else
-            break;
-        }
-        bool r = GModel::current()->getGEOInternals()->addCompoundSurface
-          (num, tags, bndTags);
-        if(!r) yymsg(0, "Could not add compound surface");
-        List_Delete((yyvsp[(7) - (12)].l));
-        Free((yyvsp[(8) - (12)].c));
-        for (int i = 0; i < List_Nbr((yyvsp[(10) - (12)].l)); i++)
-          List_Delete(*(List_T**)List_Pointer((yyvsp[(10) - (12)].l), i));
-        List_Delete((yyvsp[(10) - (12)].l));
-        (yyval.s).Type = MSH_SURF_COMPOUND;
-        (yyval.s).Num = num;
-      }
-      else {
-        yymsg(0, "GeoEntity dim out of range [2,2]");
-      }
+#line 2170 "Gmsh.y"
+    {
+      yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead");
+      (yyval.s).Type = 0;
+      (yyval.s).Num = 0;
     ;}
     break;
 
   case 187:
-#line 2222 "Gmsh.y"
+#line 2176 "Gmsh.y"
     {
       dim_entity = (yyvsp[(2) - (2)].i);
     ;}
     break;
 
   case 188:
-#line 2226 "Gmsh.y"
+#line 2180 "Gmsh.y"
     {
       int num = (int)(yyvsp[(5) - (9)].i);
       int op = (yyvsp[(7) - (9)].i);
@@ -8710,27 +8664,27 @@ yyreduce:
     break;
 
   case 189:
-#line 2252 "Gmsh.y"
+#line 2206 "Gmsh.y"
     { (yyval.i) = 0; ;}
     break;
 
   case 190:
-#line 2254 "Gmsh.y"
+#line 2208 "Gmsh.y"
     { (yyval.i) = 1; ;}
     break;
 
   case 191:
-#line 2256 "Gmsh.y"
+#line 2210 "Gmsh.y"
     { (yyval.i) = 2; ;}
     break;
 
   case 192:
-#line 2258 "Gmsh.y"
+#line 2212 "Gmsh.y"
     { (yyval.i) = 3; ;}
     break;
 
   case 193:
-#line 2260 "Gmsh.y"
+#line 2214 "Gmsh.y"
     {
       (yyval.i) = (int)(yyvsp[(3) - (4)].d);
       if ((yyval.i)<0 || (yyval.i)>3) yymsg(0, "GeoEntity dim out of range [0,3]");
@@ -8738,22 +8692,22 @@ yyreduce:
     break;
 
   case 194:
-#line 2268 "Gmsh.y"
+#line 2222 "Gmsh.y"
     { (yyval.i) = 1; ;}
     break;
 
   case 195:
-#line 2270 "Gmsh.y"
+#line 2224 "Gmsh.y"
     { (yyval.i) = 2; ;}
     break;
 
   case 196:
-#line 2272 "Gmsh.y"
+#line 2226 "Gmsh.y"
     { (yyval.i) = 3; ;}
     break;
 
   case 197:
-#line 2274 "Gmsh.y"
+#line 2228 "Gmsh.y"
     {
       (yyval.i) = (int)(yyvsp[(3) - (4)].d);
       if ((yyval.i)<1 || (yyval.i)>3) yymsg(0, "GeoEntity dim out of range [1,3]");
@@ -8761,17 +8715,17 @@ yyreduce:
     break;
 
   case 198:
-#line 2282 "Gmsh.y"
+#line 2236 "Gmsh.y"
     { (yyval.i) = 1; ;}
     break;
 
   case 199:
-#line 2284 "Gmsh.y"
+#line 2238 "Gmsh.y"
     { (yyval.i) = 2; ;}
     break;
 
   case 200:
-#line 2286 "Gmsh.y"
+#line 2240 "Gmsh.y"
     {
       (yyval.i) = (int)(yyvsp[(3) - (4)].d);
       if ((yyval.i)<1 || (yyval.i)>2) yymsg(0, "GeoEntity dim out of range [1,2]");
@@ -8779,22 +8733,22 @@ yyreduce:
     break;
 
   case 201:
-#line 2294 "Gmsh.y"
+#line 2248 "Gmsh.y"
     { (yyval.i) = 0; ;}
     break;
 
   case 202:
-#line 2296 "Gmsh.y"
+#line 2250 "Gmsh.y"
     { (yyval.i) = 1; ;}
     break;
 
   case 203:
-#line 2298 "Gmsh.y"
+#line 2252 "Gmsh.y"
     { (yyval.i) = 2; ;}
     break;
 
   case 204:
-#line 2300 "Gmsh.y"
+#line 2254 "Gmsh.y"
     {
       (yyval.i) = (int)(yyvsp[(3) - (4)].d);
       if ((yyval.i)<0 || (yyval.i)>2) yymsg(0, "GeoEntity dim out of range [0,2]");
@@ -8802,7 +8756,7 @@ yyreduce:
     break;
 
   case 205:
-#line 2310 "Gmsh.y"
+#line 2264 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -8821,7 +8775,7 @@ yyreduce:
     break;
 
   case 206:
-#line 2326 "Gmsh.y"
+#line 2280 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(10) - (11)].l), dimTags);
@@ -8840,7 +8794,7 @@ yyreduce:
     break;
 
   case 207:
-#line 2342 "Gmsh.y"
+#line 2296 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -8859,7 +8813,7 @@ yyreduce:
     break;
 
   case 208:
-#line 2358 "Gmsh.y"
+#line 2312 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(8) - (9)].l), dimTags);
@@ -8878,7 +8832,7 @@ yyreduce:
     break;
 
   case 209:
-#line 2374 "Gmsh.y"
+#line 2328 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(8) - (9)].l), dimTags);
@@ -8897,7 +8851,7 @@ yyreduce:
     break;
 
   case 210:
-#line 2390 "Gmsh.y"
+#line 2344 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), inDimTags);
@@ -8937,7 +8891,7 @@ yyreduce:
     break;
 
   case 211:
-#line 2427 "Gmsh.y"
+#line 2381 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -8961,7 +8915,7 @@ yyreduce:
     break;
 
   case 212:
-#line 2449 "Gmsh.y"
+#line 2403 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -8985,31 +8939,31 @@ yyreduce:
     break;
 
   case 213:
-#line 2472 "Gmsh.y"
+#line 2426 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 214:
-#line 2473 "Gmsh.y"
+#line 2427 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 215:
-#line 2478 "Gmsh.y"
+#line 2432 "Gmsh.y"
     {
       (yyval.l) = List_Create(3, 3, sizeof(Shape));
     ;}
     break;
 
   case 216:
-#line 2482 "Gmsh.y"
+#line 2436 "Gmsh.y"
     {
       List_Add((yyval.l), &(yyvsp[(2) - (2)].s));
     ;}
     break;
 
   case 217:
-#line 2486 "Gmsh.y"
+#line 2440 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (6)].l)); i++){
 	double d;
@@ -9028,7 +8982,7 @@ yyreduce:
     break;
 
   case 218:
-#line 2502 "Gmsh.y"
+#line 2456 "Gmsh.y"
     {
       List_T *tmp = List_Create(10, 10, sizeof(double));
       getElementaryTagsForPhysicalGroups((yyvsp[(3) - (7)].i), (yyvsp[(5) - (7)].l), tmp);
@@ -9049,7 +9003,7 @@ yyreduce:
     break;
 
   case 219:
-#line 2520 "Gmsh.y"
+#line 2474 "Gmsh.y"
     {
       List_T *tmp = List_Create(10, 10, sizeof(double));
       getAllElementaryTags((yyvsp[(2) - (6)].i), tmp);
@@ -9070,7 +9024,7 @@ yyreduce:
     break;
 
   case 220:
-#line 2538 "Gmsh.y"
+#line 2492 "Gmsh.y"
     {
       List_T *tmp = List_Create(10, 10, sizeof(double));
       List_T *tmp2 = List_Create(10, 10, sizeof(double));
@@ -9093,7 +9047,7 @@ yyreduce:
     break;
 
   case 221:
-#line 2563 "Gmsh.y"
+#line 2517 "Gmsh.y"
     {
       if(List_Nbr((yyvsp[(7) - (8)].l)) == 4){
         int t = (int)(yyvsp[(4) - (8)].d);
@@ -9115,7 +9069,7 @@ yyreduce:
     break;
 
   case 222:
-#line 2582 "Gmsh.y"
+#line 2536 "Gmsh.y"
     {
       int t = (int)(yyvsp[(4) - (10)].d);
       if(gLevelset::find(t)){
@@ -9139,7 +9093,7 @@ yyreduce:
     break;
 
   case 223:
-#line 2604 "Gmsh.y"
+#line 2558 "Gmsh.y"
     {
       int t = (int)(yyvsp[(4) - (14)].d);
       if(gLevelset::find(t)){
@@ -9156,7 +9110,7 @@ yyreduce:
     break;
 
   case 224:
-#line 2619 "Gmsh.y"
+#line 2573 "Gmsh.y"
     {
       int t = (int)(yyvsp[(4) - (16)].d);
       if(gLevelset::find(t)){
@@ -9174,7 +9128,7 @@ yyreduce:
     break;
 
   case 225:
-#line 2634 "Gmsh.y"
+#line 2588 "Gmsh.y"
     {
       if(List_Nbr((yyvsp[(10) - (12)].l)) == 1){
         int t = (int)(yyvsp[(4) - (12)].d);
@@ -9195,7 +9149,7 @@ yyreduce:
     break;
 
   case 226:
-#line 2653 "Gmsh.y"
+#line 2607 "Gmsh.y"
     {
       if(List_Nbr((yyvsp[(12) - (14)].l)) == 1){
         int t = (int)(yyvsp[(4) - (14)].d);
@@ -9248,7 +9202,7 @@ yyreduce:
     break;
 
   case 227:
-#line 2704 "Gmsh.y"
+#line 2658 "Gmsh.y"
     {
       if(List_Nbr((yyvsp[(12) - (14)].l)) == 1){
         int t = (int)(yyvsp[(4) - (14)].d);
@@ -9271,7 +9225,7 @@ yyreduce:
     break;
 
   case 228:
-#line 2725 "Gmsh.y"
+#line 2679 "Gmsh.y"
     {
       if(List_Nbr((yyvsp[(12) - (14)].l)) == 3){
         int t = (int)(yyvsp[(4) - (14)].d);
@@ -9295,7 +9249,7 @@ yyreduce:
     break;
 
   case 229:
-#line 2747 "Gmsh.y"
+#line 2701 "Gmsh.y"
     {
       if(List_Nbr((yyvsp[(12) - (14)].l)) == 5){
         int t = (int)(yyvsp[(4) - (14)].d);
@@ -9320,7 +9274,7 @@ yyreduce:
     break;
 
   case 230:
-#line 2769 "Gmsh.y"
+#line 2723 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (8)].c), "Union")){
         int t = (int)(yyvsp[(4) - (8)].d);
@@ -9428,7 +9382,7 @@ yyreduce:
     break;
 
   case 231:
-#line 2874 "Gmsh.y"
+#line 2828 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (8)].c), "MathEval")){
         int t = (int)(yyvsp[(4) - (8)].d);
@@ -9447,7 +9401,7 @@ yyreduce:
     break;
 
   case 232:
-#line 2890 "Gmsh.y"
+#line 2844 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (6)].c), "CutMesh")){
         int t = (int)(yyvsp[(4) - (6)].d);
@@ -9480,7 +9434,7 @@ yyreduce:
     break;
 
   case 233:
-#line 2925 "Gmsh.y"
+#line 2879 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags);
@@ -9505,7 +9459,7 @@ yyreduce:
     break;
 
   case 234:
-#line 2947 "Gmsh.y"
+#line 2901 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -9530,7 +9484,7 @@ yyreduce:
     break;
 
   case 235:
-#line 2969 "Gmsh.y"
+#line 2923 "Gmsh.y"
     {
 #if defined(HAVE_MESH)
       GModel::current()->getFields()->deleteField((int)(yyvsp[(4) - (6)].d));
@@ -9539,7 +9493,7 @@ yyreduce:
     break;
 
   case 236:
-#line 2975 "Gmsh.y"
+#line 2929 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(2) - (6)].c), "View")){
@@ -9557,7 +9511,7 @@ yyreduce:
     break;
 
   case 237:
-#line 2990 "Gmsh.y"
+#line 2944 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (3)].c), "Meshes") || !strcmp((yyvsp[(2) - (3)].c), "All")){
         ClearProject();
@@ -9588,7 +9542,7 @@ yyreduce:
     break;
 
   case 238:
-#line 3018 "Gmsh.y"
+#line 2972 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(2) - (4)].c), "Empty") && !strcmp((yyvsp[(3) - (4)].c), "Views")){
@@ -9603,14 +9557,14 @@ yyreduce:
     break;
 
   case 239:
-#line 3030 "Gmsh.y"
+#line 2984 "Gmsh.y"
     {
       gmsh_yynamespaces.clear();
     ;}
     break;
 
   case 240:
-#line 3039 "Gmsh.y"
+#line 2993 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -9620,7 +9574,7 @@ yyreduce:
     break;
 
   case 241:
-#line 3046 "Gmsh.y"
+#line 3000 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(5) - (6)].l), dimTags);
@@ -9630,7 +9584,7 @@ yyreduce:
     break;
 
   case 242:
-#line 3058 "Gmsh.y"
+#line 3012 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -9647,14 +9601,14 @@ yyreduce:
     break;
 
   case 243:
-#line 3077 "Gmsh.y"
+#line 3031 "Gmsh.y"
     {
       setVisibility(-1, 1, false);
     ;}
     break;
 
   case 244:
-#line 3081 "Gmsh.y"
+#line 3035 "Gmsh.y"
     {
       setVisibility(-1, 1, false);
       Free((yyvsp[(2) - (3)].c));
@@ -9662,14 +9616,14 @@ yyreduce:
     break;
 
   case 245:
-#line 3086 "Gmsh.y"
+#line 3040 "Gmsh.y"
     {
       setVisibility(-1, 0, false);
     ;}
     break;
 
   case 246:
-#line 3090 "Gmsh.y"
+#line 3044 "Gmsh.y"
     {
       setVisibility(-1, 0, false);
       Free((yyvsp[(2) - (3)].c));
@@ -9677,7 +9631,7 @@ yyreduce:
     break;
 
   case 247:
-#line 3095 "Gmsh.y"
+#line 3049 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags);
@@ -9687,7 +9641,7 @@ yyreduce:
     break;
 
   case 248:
-#line 3102 "Gmsh.y"
+#line 3056 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -9697,7 +9651,7 @@ yyreduce:
     break;
 
   case 249:
-#line 3109 "Gmsh.y"
+#line 3063 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags);
@@ -9707,7 +9661,7 @@ yyreduce:
     break;
 
   case 250:
-#line 3116 "Gmsh.y"
+#line 3070 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
@@ -9717,7 +9671,7 @@ yyreduce:
     break;
 
   case 251:
-#line 3128 "Gmsh.y"
+#line 3082 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (3)].c), "Include")){
         std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(2) - (3)].c));
@@ -9793,7 +9747,7 @@ yyreduce:
     break;
 
   case 252:
-#line 3201 "Gmsh.y"
+#line 3155 "Gmsh.y"
     {
       int n = List_Nbr((yyvsp[(3) - (5)].l));
       if(n == 1){
@@ -9814,7 +9768,7 @@ yyreduce:
     break;
 
   case 253:
-#line 3219 "Gmsh.y"
+#line 3173 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(1) - (7)].c), "Save") && !strcmp((yyvsp[(2) - (7)].c), "View")){
@@ -9834,7 +9788,7 @@ yyreduce:
     break;
 
   case 254:
-#line 3236 "Gmsh.y"
+#line 3190 "Gmsh.y"
     {
 #if defined(HAVE_POST) && defined(HAVE_MESH)
       if(!strcmp((yyvsp[(1) - (7)].c), "Background") && !strcmp((yyvsp[(2) - (7)].c), "Mesh")  && !strcmp((yyvsp[(3) - (7)].c), "View")){
@@ -9852,7 +9806,7 @@ yyreduce:
     break;
 
   case 255:
-#line 3251 "Gmsh.y"
+#line 3205 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (3)].c), "Sleep")){
 	SleepInSeconds((yyvsp[(2) - (3)].d));
@@ -9888,7 +9842,7 @@ yyreduce:
     break;
 
   case 256:
-#line 3284 "Gmsh.y"
+#line 3238 "Gmsh.y"
     {
 #if defined(HAVE_PLUGINS)
        try {
@@ -9903,7 +9857,7 @@ yyreduce:
     break;
 
   case 257:
-#line 3296 "Gmsh.y"
+#line 3250 "Gmsh.y"
     {
 #if defined(HAVE_POST)
       if(!strcmp((yyvsp[(2) - (3)].c), "ElementsFromAllViews"))
@@ -9930,14 +9884,14 @@ yyreduce:
     break;
 
   case 258:
-#line 3320 "Gmsh.y"
+#line 3274 "Gmsh.y"
     {
       Msg::Exit(0);
     ;}
     break;
 
   case 259:
-#line 3324 "Gmsh.y"
+#line 3278 "Gmsh.y"
     {
       gmsh_yyerrorstate = 999; // this will be checked when yyparse returns
       YYABORT;
@@ -9945,7 +9899,7 @@ yyreduce:
     break;
 
   case 260:
-#line 3329 "Gmsh.y"
+#line 3283 "Gmsh.y"
     {
       // force sync
       if(GModel::current()->getOCCInternals())
@@ -9955,7 +9909,7 @@ yyreduce:
     break;
 
   case 261:
-#line 3336 "Gmsh.y"
+#line 3290 "Gmsh.y"
     {
       new GModel();
       GModel::current(GModel::list.size() - 1);
@@ -9963,7 +9917,7 @@ yyreduce:
     break;
 
   case 262:
-#line 3341 "Gmsh.y"
+#line 3295 "Gmsh.y"
     {
       CTX::instance()->forcedBBox = 0;
       if(GModel::current()->getOCCInternals() &&
@@ -9976,7 +9930,7 @@ yyreduce:
     break;
 
   case 263:
-#line 3351 "Gmsh.y"
+#line 3305 "Gmsh.y"
     {
       CTX::instance()->forcedBBox = 1;
       SetBoundingBox((yyvsp[(3) - (15)].d), (yyvsp[(5) - (15)].d), (yyvsp[(7) - (15)].d), (yyvsp[(9) - (15)].d), (yyvsp[(11) - (15)].d), (yyvsp[(13) - (15)].d));
@@ -9984,7 +9938,7 @@ yyreduce:
     break;
 
   case 264:
-#line 3356 "Gmsh.y"
+#line 3310 "Gmsh.y"
     {
 #if defined(HAVE_OPENGL)
       drawContext::global()->draw();
@@ -9993,7 +9947,7 @@ yyreduce:
     break;
 
   case 265:
-#line 3362 "Gmsh.y"
+#line 3316 "Gmsh.y"
     {
 #if defined(HAVE_OPENGL)
      CTX::instance()->mesh.changed = ENT_ALL;
@@ -10004,21 +9958,21 @@ yyreduce:
     break;
 
   case 266:
-#line 3370 "Gmsh.y"
+#line 3324 "Gmsh.y"
     {
       GModel::current()->createTopologyFromMesh();
     ;}
     break;
 
   case 267:
-#line 3374 "Gmsh.y"
+#line 3328 "Gmsh.y"
     {
       GModel::current()->createTopologyFromMesh(1);
     ;}
     break;
 
   case 268:
-#line 3378 "Gmsh.y"
+#line 3332 "Gmsh.y"
     {
       if(GModel::current()->getOCCInternals() &&
          GModel::current()->getOCCInternals()->getChanged())
@@ -10030,7 +9984,7 @@ yyreduce:
     break;
 
   case 269:
-#line 3388 "Gmsh.y"
+#line 3342 "Gmsh.y"
     {
       int lock = CTX::instance()->lock;
       CTX::instance()->lock = 0;
@@ -10091,7 +10045,7 @@ yyreduce:
     break;
 
   case 270:
-#line 3451 "Gmsh.y"
+#line 3405 "Gmsh.y"
     {
 #if defined(HAVE_POPPLER)
        std::vector<int> is;
@@ -10106,7 +10060,7 @@ yyreduce:
     break;
 
   case 271:
-#line 3467 "Gmsh.y"
+#line 3421 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(3) - (6)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(5) - (6)].d);
@@ -10126,7 +10080,7 @@ yyreduce:
     break;
 
   case 272:
-#line 3484 "Gmsh.y"
+#line 3438 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(3) - (8)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(5) - (8)].d);
@@ -10146,7 +10100,7 @@ yyreduce:
     break;
 
   case 273:
-#line 3501 "Gmsh.y"
+#line 3455 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(5) - (8)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(7) - (8)].d);
@@ -10171,7 +10125,7 @@ yyreduce:
     break;
 
   case 274:
-#line 3523 "Gmsh.y"
+#line 3477 "Gmsh.y"
     {
       LoopControlVariablesTab[ImbricatedLoop][0] = (yyvsp[(5) - (10)].d);
       LoopControlVariablesTab[ImbricatedLoop][1] = (yyvsp[(7) - (10)].d);
@@ -10196,7 +10150,7 @@ yyreduce:
     break;
 
   case 275:
-#line 3545 "Gmsh.y"
+#line 3499 "Gmsh.y"
     {
       if(ImbricatedLoop <= 0){
 	yymsg(0, "Invalid For/EndFor loop");
@@ -10234,7 +10188,7 @@ yyreduce:
     break;
 
   case 276:
-#line 3580 "Gmsh.y"
+#line 3534 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->createFunction
          (std::string((yyvsp[(2) - (2)].c)), gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -10245,7 +10199,7 @@ yyreduce:
     break;
 
   case 277:
-#line 3588 "Gmsh.y"
+#line 3542 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->createFunction
          (std::string((yyvsp[(2) - (2)].c)), gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -10256,7 +10210,7 @@ yyreduce:
     break;
 
   case 278:
-#line 3596 "Gmsh.y"
+#line 3550 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->leaveFunction
          (&gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -10265,7 +10219,7 @@ yyreduce:
     break;
 
   case 279:
-#line 3602 "Gmsh.y"
+#line 3556 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->enterFunction
          (std::string((yyvsp[(2) - (3)].c)), &gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -10275,7 +10229,7 @@ yyreduce:
     break;
 
   case 280:
-#line 3609 "Gmsh.y"
+#line 3563 "Gmsh.y"
     {
       if(!FunctionManager::Instance()->enterFunction
          (std::string((yyvsp[(2) - (3)].c)), &gmsh_yyin, gmsh_yyname, gmsh_yylineno))
@@ -10285,7 +10239,7 @@ yyreduce:
     break;
 
   case 281:
-#line 3616 "Gmsh.y"
+#line 3570 "Gmsh.y"
     {
       ImbricatedTest++;
       if(ImbricatedTest > MAX_RECUR_TESTS-1){
@@ -10308,7 +10262,7 @@ yyreduce:
     break;
 
   case 282:
-#line 3636 "Gmsh.y"
+#line 3590 "Gmsh.y"
     {
       if(ImbricatedTest > 0){
         if (statusImbricatedTests[ImbricatedTest]){
@@ -10337,7 +10291,7 @@ yyreduce:
     break;
 
   case 283:
-#line 3662 "Gmsh.y"
+#line 3616 "Gmsh.y"
     {
       if(ImbricatedTest > 0){
         if(statusImbricatedTests[ImbricatedTest]){
@@ -10352,7 +10306,7 @@ yyreduce:
     break;
 
   case 284:
-#line 3674 "Gmsh.y"
+#line 3628 "Gmsh.y"
     {
       ImbricatedTest--;
       if(ImbricatedTest < 0)
@@ -10361,7 +10315,7 @@ yyreduce:
     break;
 
   case 285:
-#line 3685 "Gmsh.y"
+#line 3639 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), inDimTags);
@@ -10382,7 +10336,7 @@ yyreduce:
     break;
 
   case 286:
-#line 3703 "Gmsh.y"
+#line 3657 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(10) - (11)].l), inDimTags);
@@ -10403,7 +10357,7 @@ yyreduce:
     break;
 
   case 287:
-#line 3721 "Gmsh.y"
+#line 3675 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(12) - (13)].l), inDimTags);
@@ -10424,7 +10378,7 @@ yyreduce:
     break;
 
   case 288:
-#line 3739 "Gmsh.y"
+#line 3693 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
       extr.mesh.QuadToTri = NO_QUADTRI;
@@ -10433,7 +10387,7 @@ yyreduce:
     break;
 
   case 289:
-#line 3745 "Gmsh.y"
+#line 3699 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (7)].l), inDimTags);
@@ -10454,7 +10408,7 @@ yyreduce:
     break;
 
   case 290:
-#line 3763 "Gmsh.y"
+#line 3717 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
       extr.mesh.QuadToTri = NO_QUADTRI;
@@ -10463,7 +10417,7 @@ yyreduce:
     break;
 
   case 291:
-#line 3769 "Gmsh.y"
+#line 3723 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(10) - (13)].l), inDimTags);
@@ -10486,7 +10440,7 @@ yyreduce:
     break;
 
   case 292:
-#line 3789 "Gmsh.y"
+#line 3743 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
       extr.mesh.QuadToTri = NO_QUADTRI;
@@ -10495,7 +10449,7 @@ yyreduce:
     break;
 
   case 293:
-#line 3795 "Gmsh.y"
+#line 3749 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(12) - (15)].l), inDimTags);
@@ -10516,7 +10470,7 @@ yyreduce:
     break;
 
   case 294:
-#line 3813 "Gmsh.y"
+#line 3767 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = extr.mesh.Recombine = false;
       extr.mesh.QuadToTri = NO_QUADTRI;
@@ -10525,7 +10479,7 @@ yyreduce:
     break;
 
   case 295:
-#line 3819 "Gmsh.y"
+#line 3773 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (6)].l), inDimTags);
@@ -10545,7 +10499,7 @@ yyreduce:
     break;
 
   case 296:
-#line 3836 "Gmsh.y"
+#line 3790 "Gmsh.y"
     {
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (9)].l), inDimTags);
@@ -10564,7 +10518,7 @@ yyreduce:
     break;
 
   case 297:
-#line 3852 "Gmsh.y"
+#line 3806 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -10584,7 +10538,7 @@ yyreduce:
     break;
 
   case 298:
-#line 3869 "Gmsh.y"
+#line 3823 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -10604,7 +10558,7 @@ yyreduce:
     break;
 
   case 299:
-#line 3886 "Gmsh.y"
+#line 3840 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -10627,19 +10581,19 @@ yyreduce:
     break;
 
   case 300:
-#line 3909 "Gmsh.y"
+#line 3863 "Gmsh.y"
     {
     ;}
     break;
 
   case 301:
-#line 3912 "Gmsh.y"
+#line 3866 "Gmsh.y"
     {
     ;}
     break;
 
   case 302:
-#line 3918 "Gmsh.y"
+#line 3872 "Gmsh.y"
     {
       int n = (int)fabs((yyvsp[(3) - (5)].d));
       if(n){ // we accept n==0 to easily disable layers
@@ -10654,7 +10608,7 @@ yyreduce:
     break;
 
   case 303:
-#line 3930 "Gmsh.y"
+#line 3884 "Gmsh.y"
     {
       extr.mesh.ExtrudeMesh = true;
       extr.mesh.NbLayer = List_Nbr((yyvsp[(3) - (7)].l));
@@ -10677,56 +10631,56 @@ yyreduce:
     break;
 
   case 304:
-#line 3950 "Gmsh.y"
+#line 3904 "Gmsh.y"
     {
       extr.mesh.ScaleLast = true;
     ;}
     break;
 
   case 305:
-#line 3954 "Gmsh.y"
+#line 3908 "Gmsh.y"
     {
       extr.mesh.Recombine = true;
     ;}
     break;
 
   case 306:
-#line 3958 "Gmsh.y"
+#line 3912 "Gmsh.y"
     {
       extr.mesh.Recombine = (yyvsp[(2) - (3)].d) ? true : false;
     ;}
     break;
 
   case 307:
-#line 3962 "Gmsh.y"
+#line 3916 "Gmsh.y"
     {
       extr.mesh.QuadToTri = QUADTRI_ADDVERTS_1;
     ;}
     break;
 
   case 308:
-#line 3966 "Gmsh.y"
+#line 3920 "Gmsh.y"
     {
       extr.mesh.QuadToTri = QUADTRI_ADDVERTS_1_RECOMB;
     ;}
     break;
 
   case 309:
-#line 3970 "Gmsh.y"
+#line 3924 "Gmsh.y"
     {
       extr.mesh.QuadToTri = QUADTRI_NOVERTS_1;
     ;}
     break;
 
   case 310:
-#line 3974 "Gmsh.y"
+#line 3928 "Gmsh.y"
     {
       extr.mesh.QuadToTri = QUADTRI_NOVERTS_1_RECOMB;
     ;}
     break;
 
   case 311:
-#line 3978 "Gmsh.y"
+#line 3932 "Gmsh.y"
     {
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (9)].l), tags);
       int num = (int)(yyvsp[(3) - (9)].d);
@@ -10738,7 +10692,7 @@ yyreduce:
     break;
 
   case 312:
-#line 3987 "Gmsh.y"
+#line 3941 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (6)].c), "Index"))
         extr.mesh.BoundaryLayerIndex = (yyvsp[(4) - (6)].d);
@@ -10749,57 +10703,57 @@ yyreduce:
     break;
 
   case 313:
-#line 3999 "Gmsh.y"
+#line 3953 "Gmsh.y"
     { (yyval.i) = OCC_Internals::Union; ;}
     break;
 
   case 314:
-#line 4000 "Gmsh.y"
+#line 3954 "Gmsh.y"
     { (yyval.i) = OCC_Internals::Intersection; ;}
     break;
 
   case 315:
-#line 4001 "Gmsh.y"
+#line 3955 "Gmsh.y"
     { (yyval.i) = OCC_Internals::Difference; ;}
     break;
 
   case 316:
-#line 4002 "Gmsh.y"
+#line 3956 "Gmsh.y"
     { (yyval.i) = OCC_Internals::Section; ;}
     break;
 
   case 317:
-#line 4003 "Gmsh.y"
+#line 3957 "Gmsh.y"
     { (yyval.i) = OCC_Internals::Fragments; ;}
     break;
 
   case 318:
-#line 4007 "Gmsh.y"
+#line 3961 "Gmsh.y"
     { (yyval.i) = 0; ;}
     break;
 
   case 319:
-#line 4008 "Gmsh.y"
+#line 3962 "Gmsh.y"
     { (yyval.i) = 1; ;}
     break;
 
   case 320:
-#line 4009 "Gmsh.y"
+#line 3963 "Gmsh.y"
     { (yyval.i) = 2; ;}
     break;
 
   case 321:
-#line 4010 "Gmsh.y"
+#line 3964 "Gmsh.y"
     { (yyval.i) = (yyvsp[(2) - (3)].d) ? 1 : 0; ;}
     break;
 
   case 322:
-#line 4011 "Gmsh.y"
+#line 3965 "Gmsh.y"
     { (yyval.i) = (yyvsp[(3) - (4)].d) ? 2 : 0; ;}
     break;
 
   case 323:
-#line 4016 "Gmsh.y"
+#line 3970 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -10825,7 +10779,7 @@ yyreduce:
     break;
 
   case 324:
-#line 4039 "Gmsh.y"
+#line 3993 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
@@ -10844,7 +10798,7 @@ yyreduce:
     break;
 
   case 325:
-#line 4059 "Gmsh.y"
+#line 4013 "Gmsh.y"
     {
       bool r = true;
       if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
@@ -10865,14 +10819,14 @@ yyreduce:
     break;
 
   case 326:
-#line 4080 "Gmsh.y"
+#line 4034 "Gmsh.y"
     {
       (yyval.v)[0] = (yyval.v)[1] = 1.;
     ;}
     break;
 
   case 327:
-#line 4084 "Gmsh.y"
+#line 4038 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (3)].c), "Progression") || !strcmp((yyvsp[(2) - (3)].c), "Power"))
         (yyval.v)[0] = 1.;
@@ -10888,14 +10842,14 @@ yyreduce:
     break;
 
   case 328:
-#line 4099 "Gmsh.y"
+#line 4053 "Gmsh.y"
     {
       (yyval.i) = -1; // left
     ;}
     break;
 
   case 329:
-#line 4103 "Gmsh.y"
+#line 4057 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (1)].c), "Right"))
         (yyval.i) = 1;
@@ -10912,49 +10866,49 @@ yyreduce:
     break;
 
   case 330:
-#line 4119 "Gmsh.y"
+#line 4073 "Gmsh.y"
     {
      (yyval.l) = List_Create(1, 1, sizeof(double));
    ;}
     break;
 
   case 331:
-#line 4123 "Gmsh.y"
+#line 4077 "Gmsh.y"
     {
      (yyval.l) = (yyvsp[(2) - (2)].l);
    ;}
     break;
 
   case 332:
-#line 4128 "Gmsh.y"
+#line 4082 "Gmsh.y"
     {
       (yyval.i) = 45;
     ;}
     break;
 
   case 333:
-#line 4132 "Gmsh.y"
+#line 4086 "Gmsh.y"
     {
       (yyval.i) = (int)(yyvsp[(2) - (2)].d);
     ;}
     break;
 
   case 334:
-#line 4138 "Gmsh.y"
+#line 4092 "Gmsh.y"
     {
       (yyval.l) = List_Create(1, 1, sizeof(double));
     ;}
     break;
 
   case 335:
-#line 4142 "Gmsh.y"
+#line 4096 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (2)].l);
     ;}
     break;
 
   case 336:
-#line 4149 "Gmsh.y"
+#line 4103 "Gmsh.y"
     {
       // mesh sizes at vertices are stored in internal CAD data, as they can be
       // specified during vertex creation and copied around during CAD
@@ -10979,7 +10933,7 @@ yyreduce:
     break;
 
   case 337:
-#line 4171 "Gmsh.y"
+#line 4125 "Gmsh.y"
     {
       // transfinite constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11023,7 +10977,7 @@ yyreduce:
     break;
 
   case 338:
-#line 4212 "Gmsh.y"
+#line 4166 "Gmsh.y"
     {
       // transfinite constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11070,7 +11024,7 @@ yyreduce:
     break;
 
   case 339:
-#line 4256 "Gmsh.y"
+#line 4210 "Gmsh.y"
     {
       // transfinite constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11112,7 +11066,7 @@ yyreduce:
     break;
 
   case 340:
-#line 4295 "Gmsh.y"
+#line 4249 "Gmsh.y"
     {
       // transfinite constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11140,7 +11094,7 @@ yyreduce:
     break;
 
   case 341:
-#line 4320 "Gmsh.y"
+#line 4274 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(4) - (8)].l)); i++){
 	double d;
@@ -11152,7 +11106,7 @@ yyreduce:
     break;
 
   case 342:
-#line 4329 "Gmsh.y"
+#line 4283 "Gmsh.y"
     {
       // recombine constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11185,7 +11139,7 @@ yyreduce:
     break;
 
   case 343:
-#line 4359 "Gmsh.y"
+#line 4313 "Gmsh.y"
     {
       // recombine constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11214,7 +11168,7 @@ yyreduce:
     break;
 
   case 344:
-#line 4385 "Gmsh.y"
+#line 4339 "Gmsh.y"
     {
       // smoothing constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11243,7 +11197,7 @@ yyreduce:
     break;
 
   case 345:
-#line 4412 "Gmsh.y"
+#line 4366 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(4) - (11)].l)) != List_Nbr((yyvsp[(8) - (11)].l))){
         yymsg(0, "Number of master lines (%d) different from number of "
@@ -11277,7 +11231,7 @@ yyreduce:
     break;
 
   case 346:
-#line 4444 "Gmsh.y"
+#line 4398 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(4) - (11)].l)) != List_Nbr((yyvsp[(8) - (11)].l))){
         yymsg(0, "Number of master faces (%d) different from number of "
@@ -11306,7 +11260,7 @@ yyreduce:
     break;
 
   case 347:
-#line 4471 "Gmsh.y"
+#line 4425 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(4) - (18)].l)) != List_Nbr((yyvsp[(8) - (18)].l))){
         yymsg(0, "Number of master edges (%d) different from number of "
@@ -11334,7 +11288,7 @@ yyreduce:
     break;
 
   case 348:
-#line 4497 "Gmsh.y"
+#line 4451 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(4) - (18)].l)) != List_Nbr((yyvsp[(8) - (18)].l))){
         yymsg(0, "Number of master faces (%d) different from number of "
@@ -11362,7 +11316,7 @@ yyreduce:
     break;
 
   case 349:
-#line 4523 "Gmsh.y"
+#line 4477 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(4) - (12)].l)) != List_Nbr((yyvsp[(8) - (12)].l))){
         yymsg(0, "Number of master edges (%d) different from number of "
@@ -11390,7 +11344,7 @@ yyreduce:
     break;
 
   case 350:
-#line 4549 "Gmsh.y"
+#line 4503 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(4) - (12)].l)) != List_Nbr((yyvsp[(8) - (12)].l))){
         yymsg(0, "Number of master faces (%d) different from number of "
@@ -11418,7 +11372,7 @@ yyreduce:
     break;
 
   case 351:
-#line 4575 "Gmsh.y"
+#line 4529 "Gmsh.y"
     {
       if (List_Nbr((yyvsp[(5) - (12)].l)) != List_Nbr((yyvsp[(10) - (12)].l))){
         yymsg(0, "Number of master surface edges (%d) different from number of "
@@ -11442,7 +11396,7 @@ yyreduce:
     break;
 
   case 352:
-#line 4596 "Gmsh.y"
+#line 4550 "Gmsh.y"
     {
       if (((yyvsp[(6) - (10)].i)==2 || (yyvsp[(6) - (10)].i)==3) && (yyvsp[(1) - (10)].i)<(yyvsp[(6) - (10)].i) ) {
         std::vector<int> tags; ListOfDouble2Vector((yyvsp[(3) - (10)].l), tags);
@@ -11456,7 +11410,7 @@ yyreduce:
     break;
 
   case 353:
-#line 4607 "Gmsh.y"
+#line 4561 "Gmsh.y"
     {
       // reverse mesh constraints are stored in GEO internals in addition to
       // GModel, as they can be copied around during GEO operations
@@ -11507,7 +11461,7 @@ yyreduce:
     break;
 
   case 354:
-#line 4655 "Gmsh.y"
+#line 4609 "Gmsh.y"
     {
       if(!(yyvsp[(3) - (4)].l)){
         switch ((yyvsp[(2) - (4)].i)) {
@@ -11559,7 +11513,7 @@ yyreduce:
     break;
 
   case 355:
-#line 4704 "Gmsh.y"
+#line 4658 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){
 	double dnum;
@@ -11574,7 +11528,7 @@ yyreduce:
     break;
 
   case 356:
-#line 4716 "Gmsh.y"
+#line 4670 "Gmsh.y"
     {
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(3) - (4)].l), tags);
       GModel::current()->getGEOInternals()->setCompoundMesh((yyvsp[(2) - (4)].i), tags);
@@ -11583,7 +11537,7 @@ yyreduce:
     break;
 
   case 357:
-#line 4727 "Gmsh.y"
+#line 4681 "Gmsh.y"
     {
       if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals())
         GModel::current()->getOCCInternals()->removeAllDuplicates();
@@ -11593,7 +11547,7 @@ yyreduce:
     break;
 
   case 358:
-#line 4734 "Gmsh.y"
+#line 4688 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(2) - (3)].c), "Geometry")){
         if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals())
@@ -11611,7 +11565,7 @@ yyreduce:
     break;
 
   case 359:
-#line 4749 "Gmsh.y"
+#line 4703 "Gmsh.y"
     {
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(4) - (6)].l), tags);
       if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals())
@@ -11623,22 +11577,22 @@ yyreduce:
     break;
 
   case 360:
-#line 4762 "Gmsh.y"
+#line 4716 "Gmsh.y"
     { (yyval.c) = (char*)"Homology"; ;}
     break;
 
   case 361:
-#line 4763 "Gmsh.y"
+#line 4717 "Gmsh.y"
     { (yyval.c) = (char*)"Cohomology"; ;}
     break;
 
   case 362:
-#line 4764 "Gmsh.y"
+#line 4718 "Gmsh.y"
     { (yyval.c) = (char*)"Betti"; ;}
     break;
 
   case 363:
-#line 4769 "Gmsh.y"
+#line 4723 "Gmsh.y"
     {
       std::vector<int> domain, subdomain, dim;
       for(int i = 0; i < 4; i++) dim.push_back(i);
@@ -11647,7 +11601,7 @@ yyreduce:
     break;
 
   case 364:
-#line 4775 "Gmsh.y"
+#line 4729 "Gmsh.y"
     {
       std::vector<int> domain, subdomain, dim;
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (5)].l)); i++){
@@ -11662,7 +11616,7 @@ yyreduce:
     break;
 
   case 365:
-#line 4787 "Gmsh.y"
+#line 4741 "Gmsh.y"
     {
       std::vector<int> domain, subdomain, dim;
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (7)].l)); i++){
@@ -11683,7 +11637,7 @@ yyreduce:
     break;
 
   case 366:
-#line 4805 "Gmsh.y"
+#line 4759 "Gmsh.y"
     {
       std::vector<int> domain, subdomain, dim;
       for(int i = 0; i < List_Nbr((yyvsp[(6) - (10)].l)); i++){
@@ -11709,47 +11663,47 @@ yyreduce:
     break;
 
   case 367:
-#line 4832 "Gmsh.y"
+#line 4786 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (1)].d);           ;}
     break;
 
   case 368:
-#line 4833 "Gmsh.y"
+#line 4787 "Gmsh.y"
     { (yyval.d) = (yyvsp[(2) - (3)].d);           ;}
     break;
 
   case 369:
-#line 4834 "Gmsh.y"
+#line 4788 "Gmsh.y"
     { (yyval.d) = -(yyvsp[(2) - (2)].d);          ;}
     break;
 
   case 370:
-#line 4835 "Gmsh.y"
+#line 4789 "Gmsh.y"
     { (yyval.d) = (yyvsp[(2) - (2)].d);           ;}
     break;
 
   case 371:
-#line 4836 "Gmsh.y"
+#line 4790 "Gmsh.y"
     { (yyval.d) = !(yyvsp[(2) - (2)].d);          ;}
     break;
 
   case 372:
-#line 4837 "Gmsh.y"
+#line 4791 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) - (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 373:
-#line 4838 "Gmsh.y"
+#line 4792 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) + (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 374:
-#line 4839 "Gmsh.y"
+#line 4793 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) * (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 375:
-#line 4841 "Gmsh.y"
+#line 4795 "Gmsh.y"
     {
       if(!(yyvsp[(3) - (3)].d))
 	yymsg(0, "Division by zero in '%g / %g'", (yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d));
@@ -11759,257 +11713,257 @@ yyreduce:
     break;
 
   case 376:
-#line 4847 "Gmsh.y"
+#line 4801 "Gmsh.y"
     { (yyval.d) = (int)(yyvsp[(1) - (3)].d) | (int)(yyvsp[(3) - (3)].d); ;}
     break;
 
   case 377:
-#line 4848 "Gmsh.y"
+#line 4802 "Gmsh.y"
     { (yyval.d) = (int)(yyvsp[(1) - (3)].d) & (int)(yyvsp[(3) - (3)].d); ;}
     break;
 
   case 378:
-#line 4849 "Gmsh.y"
+#line 4803 "Gmsh.y"
     { (yyval.d) = (int)(yyvsp[(1) - (3)].d) % (int)(yyvsp[(3) - (3)].d); ;}
     break;
 
   case 379:
-#line 4850 "Gmsh.y"
+#line 4804 "Gmsh.y"
     { (yyval.d) = pow((yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d));  ;}
     break;
 
   case 380:
-#line 4851 "Gmsh.y"
+#line 4805 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 381:
-#line 4852 "Gmsh.y"
+#line 4806 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) > (yyvsp[(3) - (3)].d);      ;}
     break;
 
   case 382:
-#line 4853 "Gmsh.y"
+#line 4807 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) <= (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 383:
-#line 4854 "Gmsh.y"
+#line 4808 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) >= (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 384:
-#line 4855 "Gmsh.y"
+#line 4809 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) == (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 385:
-#line 4856 "Gmsh.y"
+#line 4810 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) != (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 386:
-#line 4857 "Gmsh.y"
+#line 4811 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) && (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 387:
-#line 4858 "Gmsh.y"
+#line 4812 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (3)].d) || (yyvsp[(3) - (3)].d);     ;}
     break;
 
   case 388:
-#line 4859 "Gmsh.y"
+#line 4813 "Gmsh.y"
     { (yyval.d) = ((int)(yyvsp[(1) - (3)].d) >> (int)(yyvsp[(3) - (3)].d)); ;}
     break;
 
   case 389:
-#line 4860 "Gmsh.y"
+#line 4814 "Gmsh.y"
     { (yyval.d) = ((int)(yyvsp[(1) - (3)].d) << (int)(yyvsp[(3) - (3)].d)); ;}
     break;
 
   case 390:
-#line 4861 "Gmsh.y"
+#line 4815 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (5)].d) ? (yyvsp[(3) - (5)].d) : (yyvsp[(5) - (5)].d); ;}
     break;
 
   case 391:
-#line 4862 "Gmsh.y"
+#line 4816 "Gmsh.y"
     { (yyval.d) = exp((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 392:
-#line 4863 "Gmsh.y"
+#line 4817 "Gmsh.y"
     { (yyval.d) = log((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 393:
-#line 4864 "Gmsh.y"
+#line 4818 "Gmsh.y"
     { (yyval.d) = log10((yyvsp[(3) - (4)].d));    ;}
     break;
 
   case 394:
-#line 4865 "Gmsh.y"
+#line 4819 "Gmsh.y"
     { (yyval.d) = sqrt((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 395:
-#line 4866 "Gmsh.y"
+#line 4820 "Gmsh.y"
     { (yyval.d) = sin((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 396:
-#line 4867 "Gmsh.y"
+#line 4821 "Gmsh.y"
     { (yyval.d) = asin((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 397:
-#line 4868 "Gmsh.y"
+#line 4822 "Gmsh.y"
     { (yyval.d) = cos((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 398:
-#line 4869 "Gmsh.y"
+#line 4823 "Gmsh.y"
     { (yyval.d) = acos((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 399:
-#line 4870 "Gmsh.y"
+#line 4824 "Gmsh.y"
     { (yyval.d) = tan((yyvsp[(3) - (4)].d));      ;}
     break;
 
   case 400:
-#line 4871 "Gmsh.y"
+#line 4825 "Gmsh.y"
     { (yyval.d) = atan((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 401:
-#line 4872 "Gmsh.y"
+#line 4826 "Gmsh.y"
     { (yyval.d) = atan2((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d));;}
     break;
 
   case 402:
-#line 4873 "Gmsh.y"
+#line 4827 "Gmsh.y"
     { (yyval.d) = sinh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 403:
-#line 4874 "Gmsh.y"
+#line 4828 "Gmsh.y"
     { (yyval.d) = cosh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 404:
-#line 4875 "Gmsh.y"
+#line 4829 "Gmsh.y"
     { (yyval.d) = tanh((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 405:
-#line 4876 "Gmsh.y"
+#line 4830 "Gmsh.y"
     { (yyval.d) = fabs((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 406:
-#line 4877 "Gmsh.y"
+#line 4831 "Gmsh.y"
     { (yyval.d) = std::abs((yyvsp[(3) - (4)].d)); ;}
     break;
 
   case 407:
-#line 4878 "Gmsh.y"
+#line 4832 "Gmsh.y"
     { (yyval.d) = floor((yyvsp[(3) - (4)].d));    ;}
     break;
 
   case 408:
-#line 4879 "Gmsh.y"
+#line 4833 "Gmsh.y"
     { (yyval.d) = ceil((yyvsp[(3) - (4)].d));     ;}
     break;
 
   case 409:
-#line 4880 "Gmsh.y"
+#line 4834 "Gmsh.y"
     { (yyval.d) = floor((yyvsp[(3) - (4)].d) + 0.5); ;}
     break;
 
   case 410:
-#line 4881 "Gmsh.y"
+#line 4835 "Gmsh.y"
     { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 411:
-#line 4882 "Gmsh.y"
+#line 4836 "Gmsh.y"
     { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 412:
-#line 4883 "Gmsh.y"
+#line 4837 "Gmsh.y"
     { (yyval.d) = sqrt((yyvsp[(3) - (6)].d) * (yyvsp[(3) - (6)].d) + (yyvsp[(5) - (6)].d) * (yyvsp[(5) - (6)].d)); ;}
     break;
 
   case 413:
-#line 4884 "Gmsh.y"
+#line 4838 "Gmsh.y"
     { (yyval.d) = (yyvsp[(3) - (4)].d) * (double)rand() / (double)RAND_MAX; ;}
     break;
 
   case 414:
-#line 4893 "Gmsh.y"
+#line 4847 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (1)].d); ;}
     break;
 
   case 415:
-#line 4894 "Gmsh.y"
+#line 4848 "Gmsh.y"
     { (yyval.d) = 3.141592653589793; ;}
     break;
 
   case 416:
-#line 4895 "Gmsh.y"
+#line 4849 "Gmsh.y"
     { (yyval.d) = (double)ImbricatedTest; ;}
     break;
 
   case 417:
-#line 4896 "Gmsh.y"
+#line 4850 "Gmsh.y"
     { (yyval.d) = Msg::GetCommRank(); ;}
     break;
 
   case 418:
-#line 4897 "Gmsh.y"
+#line 4851 "Gmsh.y"
     { (yyval.d) = Msg::GetCommSize(); ;}
     break;
 
   case 419:
-#line 4898 "Gmsh.y"
+#line 4852 "Gmsh.y"
     { (yyval.d) = GetGmshMajorVersion(); ;}
     break;
 
   case 420:
-#line 4899 "Gmsh.y"
+#line 4853 "Gmsh.y"
     { (yyval.d) = GetGmshMinorVersion(); ;}
     break;
 
   case 421:
-#line 4900 "Gmsh.y"
+#line 4854 "Gmsh.y"
     { (yyval.d) = GetGmshPatchVersion(); ;}
     break;
 
   case 422:
-#line 4901 "Gmsh.y"
+#line 4855 "Gmsh.y"
     { (yyval.d) = Cpu(); ;}
     break;
 
   case 423:
-#line 4902 "Gmsh.y"
+#line 4856 "Gmsh.y"
     { (yyval.d) = GetMemoryUsage()/1024./1024.; ;}
     break;
 
   case 424:
-#line 4903 "Gmsh.y"
+#line 4857 "Gmsh.y"
     { (yyval.d) = TotalRam(); ;}
     break;
 
   case 425:
-#line 4908 "Gmsh.y"
+#line 4862 "Gmsh.y"
     { init_options(); ;}
     break;
 
   case 426:
-#line 4910 "Gmsh.y"
+#line 4864 "Gmsh.y"
     {
       std::vector<double> val(1, (yyvsp[(3) - (6)].d));
       Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions);
@@ -12018,12 +11972,12 @@ yyreduce:
     break;
 
   case 427:
-#line 4916 "Gmsh.y"
+#line 4870 "Gmsh.y"
     { (yyval.d) = (yyvsp[(1) - (1)].d); ;}
     break;
 
   case 428:
-#line 4918 "Gmsh.y"
+#line 4872 "Gmsh.y"
     {
       (yyval.d) = Msg::GetOnelabNumber((yyvsp[(3) - (4)].c));
       Free((yyvsp[(3) - (4)].c));
@@ -12031,7 +11985,7 @@ yyreduce:
     break;
 
   case 429:
-#line 4923 "Gmsh.y"
+#line 4877 "Gmsh.y"
     {
       (yyval.d) = Msg::GetOnelabNumber((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d));
       Free((yyvsp[(3) - (6)].c));
@@ -12039,70 +11993,70 @@ yyreduce:
     break;
 
   case 430:
-#line 4928 "Gmsh.y"
+#line 4882 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_Float((yyvsp[(1) - (1)].c2).char1, (yyvsp[(1) - (1)].c2).char2);
     ;}
     break;
 
   case 431:
-#line 4933 "Gmsh.y"
+#line 4887 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_Float(NULL, (yyvsp[(1) - (4)].c), 2, (int)(yyvsp[(3) - (4)].d));
     ;}
     break;
 
   case 432:
-#line 4938 "Gmsh.y"
+#line 4892 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_Float(NULL, (yyvsp[(1) - (4)].c), 2, (int)(yyvsp[(3) - (4)].d));
     ;}
     break;
 
   case 433:
-#line 4942 "Gmsh.y"
+#line 4896 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (4)].c2).char1, (yyvsp[(3) - (4)].c2).char2, 1, 0, 0., 1);
     ;}
     break;
 
   case 434:
-#line 4946 "Gmsh.y"
+#line 4900 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (6)].c2).char1, (yyvsp[(3) - (6)].c2).char2, (yyvsp[(5) - (6)].c), 0, 0., 1);
     ;}
     break;
 
   case 435:
-#line 4950 "Gmsh.y"
+#line 4904 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (5)].c2).char1, (yyvsp[(3) - (5)].c2).char2, 1, 0, (yyvsp[(4) - (5)].d), 2);
     ;}
     break;
 
   case 436:
-#line 4954 "Gmsh.y"
+#line 4908 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (7)].c2).char1, (yyvsp[(3) - (7)].c2).char2, (yyvsp[(5) - (7)].c), 0, (yyvsp[(6) - (7)].d), 2);
     ;}
     break;
 
   case 437:
-#line 4958 "Gmsh.y"
+#line 4912 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (8)].c2).char1, (yyvsp[(3) - (8)].c2).char2, 2, (int)(yyvsp[(5) - (8)].d), (yyvsp[(7) - (8)].d), 2);
     ;}
     break;
 
   case 438:
-#line 4962 "Gmsh.y"
+#line 4916 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (10)].c2).char1, (yyvsp[(3) - (10)].c2).char2, (yyvsp[(5) - (10)].c), (int)(yyvsp[(7) - (10)].d), (yyvsp[(9) - (10)].d), 2);
     ;}
     break;
 
   case 439:
-#line 4966 "Gmsh.y"
+#line 4920 "Gmsh.y"
     {
       std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c));
       (yyval.d) = !StatFile(tmp);
@@ -12111,7 +12065,7 @@ yyreduce:
     break;
 
   case 440:
-#line 4972 "Gmsh.y"
+#line 4926 "Gmsh.y"
     {
       if(gmsh_yysymbols.count((yyvsp[(2) - (4)].c))){
         gmsh_yysymbol &s(gmsh_yysymbols[(yyvsp[(2) - (4)].c)]);
@@ -12129,14 +12083,14 @@ yyreduce:
     break;
 
   case 441:
-#line 4988 "Gmsh.y"
+#line 4942 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float_getDim((yyvsp[(2) - (6)].c2).char1, (yyvsp[(2) - (6)].c2).char2, (yyvsp[(4) - (6)].c));
     ;}
     break;
 
   case 442:
-#line 4993 "Gmsh.y"
+#line 4947 "Gmsh.y"
     {
       std::string struct_namespace((yyvsp[(3) - (4)].c));
       (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size();
@@ -12145,7 +12099,7 @@ yyreduce:
     break;
 
   case 443:
-#line 4999 "Gmsh.y"
+#line 4953 "Gmsh.y"
     {
       std::string struct_namespace(std::string(""));
       (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size();
@@ -12153,7 +12107,7 @@ yyreduce:
     break;
 
   case 444:
-#line 5005 "Gmsh.y"
+#line 4959 "Gmsh.y"
     {
       if(!gmsh_yysymbols.count((yyvsp[(1) - (2)].c))){
 	yymsg(0, "Unknown variable '%s'", (yyvsp[(1) - (2)].c));
@@ -12175,7 +12129,7 @@ yyreduce:
     break;
 
   case 445:
-#line 5024 "Gmsh.y"
+#line 4978 "Gmsh.y"
     {
       int index = (int)(yyvsp[(3) - (5)].d);
       if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){
@@ -12198,7 +12152,7 @@ yyreduce:
     break;
 
   case 446:
-#line 5045 "Gmsh.y"
+#line 4999 "Gmsh.y"
     {
       int index = (int)(yyvsp[(3) - (5)].d);
       if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){
@@ -12221,49 +12175,49 @@ yyreduce:
     break;
 
   case 447:
-#line 5078 "Gmsh.y"
+#line 5032 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (3)].c), (yyvsp[(3) - (3)].c));
     ;}
     break;
 
   case 448:
-#line 5082 "Gmsh.y"
+#line 5036 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c), (yyvsp[(5) - (5)].c));
     ;}
     break;
 
   case 449:
-#line 5087 "Gmsh.y"
+#line 5041 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d));
     ;}
     break;
 
   case 450:
-#line 5091 "Gmsh.y"
+#line 5045 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d));
     ;}
     break;
 
   case 451:
-#line 5095 "Gmsh.y"
+#line 5049 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d));
     ;}
     break;
 
   case 452:
-#line 5099 "Gmsh.y"
+#line 5053 "Gmsh.y"
     {
       (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d));
     ;}
     break;
 
   case 453:
-#line 5104 "Gmsh.y"
+#line 5058 "Gmsh.y"
     {
       NumberOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), (yyval.d));
       Free((yyvsp[(1) - (6)].c)); Free((yyvsp[(6) - (6)].c));
@@ -12271,7 +12225,7 @@ yyreduce:
     break;
 
   case 454:
-#line 5109 "Gmsh.y"
+#line 5063 "Gmsh.y"
     {
       double d = 0.;
       if(NumberOption(GMSH_GET, (yyvsp[(1) - (4)].c), 0, (yyvsp[(3) - (4)].c), d)){
@@ -12284,7 +12238,7 @@ yyreduce:
     break;
 
   case 455:
-#line 5119 "Gmsh.y"
+#line 5073 "Gmsh.y"
     {
       double d = 0.;
       if(NumberOption(GMSH_GET, (yyvsp[(1) - (7)].c), (int)(yyvsp[(3) - (7)].d), (yyvsp[(6) - (7)].c), d)){
@@ -12297,7 +12251,7 @@ yyreduce:
     break;
 
   case 456:
-#line 5129 "Gmsh.y"
+#line 5083 "Gmsh.y"
     {
       (yyval.d) = Msg::GetValue((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d));
       Free((yyvsp[(3) - (6)].c));
@@ -12305,7 +12259,7 @@ yyreduce:
     break;
 
   case 457:
-#line 5134 "Gmsh.y"
+#line 5088 "Gmsh.y"
     {
       int matches = 0;
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (6)].l)); i++){
@@ -12319,7 +12273,7 @@ yyreduce:
     break;
 
   case 458:
-#line 5145 "Gmsh.y"
+#line 5099 "Gmsh.y"
     {
       std::string s((yyvsp[(3) - (6)].c)), substr((yyvsp[(5) - (6)].c));
       if(s.find(substr) != std::string::npos)
@@ -12331,7 +12285,7 @@ yyreduce:
     break;
 
   case 459:
-#line 5154 "Gmsh.y"
+#line 5108 "Gmsh.y"
     {
       (yyval.d) = strlen((yyvsp[(3) - (4)].c));
       Free((yyvsp[(3) - (4)].c));
@@ -12339,7 +12293,7 @@ yyreduce:
     break;
 
   case 460:
-#line 5159 "Gmsh.y"
+#line 5113 "Gmsh.y"
     {
       (yyval.d) = strcmp((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c));
       Free((yyvsp[(3) - (6)].c)); Free((yyvsp[(5) - (6)].c));
@@ -12347,7 +12301,7 @@ yyreduce:
     break;
 
   case 461:
-#line 5164 "Gmsh.y"
+#line 5118 "Gmsh.y"
     {
       int align = 0, font = 0, fontsize = CTX::instance()->glFontSize;
       if(List_Nbr((yyvsp[(3) - (4)].l)) % 2){
@@ -12374,27 +12328,27 @@ yyreduce:
     break;
 
   case 462:
-#line 5191 "Gmsh.y"
+#line 5145 "Gmsh.y"
     { (yyval.d) = 0.; ;}
     break;
 
   case 463:
-#line 5193 "Gmsh.y"
+#line 5147 "Gmsh.y"
     { (yyval.d) = (yyvsp[(2) - (2)].d);;}
     break;
 
   case 464:
-#line 5198 "Gmsh.y"
+#line 5152 "Gmsh.y"
     { (yyval.c) = NULL; ;}
     break;
 
   case 465:
-#line 5200 "Gmsh.y"
+#line 5154 "Gmsh.y"
     { (yyval.c) = (yyvsp[(2) - (2)].c);;}
     break;
 
   case 466:
-#line 5205 "Gmsh.y"
+#line 5159 "Gmsh.y"
     {
       std::string struct_namespace((yyvsp[(2) - (3)].c2).char1? (yyvsp[(2) - (3)].c2).char1 : std::string("")),
         struct_name((yyvsp[(2) - (3)].c2).char2);
@@ -12404,7 +12358,7 @@ yyreduce:
     break;
 
   case 467:
-#line 5212 "Gmsh.y"
+#line 5166 "Gmsh.y"
     {
       std::string struct_namespace((yyvsp[(2) - (7)].c2).char1? (yyvsp[(2) - (7)].c2).char1 : std::string("")),
         struct_name((yyvsp[(2) - (7)].c2).char2);
@@ -12420,105 +12374,105 @@ yyreduce:
     break;
 
   case 468:
-#line 5228 "Gmsh.y"
+#line 5182 "Gmsh.y"
     { (yyval.c2).char1 = NULL; (yyval.c2).char2 = (yyvsp[(1) - (1)].c); ;}
     break;
 
   case 469:
-#line 5230 "Gmsh.y"
+#line 5184 "Gmsh.y"
     { (yyval.c2).char1 = (yyvsp[(1) - (3)].c); (yyval.c2).char2 = (yyvsp[(3) - (3)].c); ;}
     break;
 
   case 470:
-#line 5235 "Gmsh.y"
+#line 5189 "Gmsh.y"
     { (yyval.c) = (yyvsp[(1) - (1)].c); flag_tSTRING_alloc = 1; ;}
     break;
 
   case 471:
-#line 5244 "Gmsh.y"
+#line 5198 "Gmsh.y"
     { (yyval.i) = 99; ;}
     break;
 
   case 472:
-#line 5246 "Gmsh.y"
+#line 5200 "Gmsh.y"
     { (yyval.i) = (int)(yyvsp[(2) - (2)].d); ;}
     break;
 
   case 473:
-#line 5251 "Gmsh.y"
+#line 5205 "Gmsh.y"
     { (yyval.i) = 0; ;}
     break;
 
   case 474:
-#line 5253 "Gmsh.y"
+#line 5207 "Gmsh.y"
     { (yyval.i) = (yyvsp[(2) - (3)].i); ;}
     break;
 
   case 475:
-#line 5258 "Gmsh.y"
+#line 5212 "Gmsh.y"
     {
       memcpy((yyval.v), (yyvsp[(1) - (1)].v), 5*sizeof(double));
     ;}
     break;
 
   case 476:
-#line 5262 "Gmsh.y"
+#line 5216 "Gmsh.y"
     {
       for(int i = 0; i < 5; i++) (yyval.v)[i] = -(yyvsp[(2) - (2)].v)[i];
     ;}
     break;
 
   case 477:
-#line 5266 "Gmsh.y"
+#line 5220 "Gmsh.y"
     {
       for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(2) - (2)].v)[i];
     ;}
     break;
 
   case 478:
-#line 5270 "Gmsh.y"
+#line 5224 "Gmsh.y"
     {
       for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] - (yyvsp[(3) - (3)].v)[i];
     ;}
     break;
 
   case 479:
-#line 5274 "Gmsh.y"
+#line 5228 "Gmsh.y"
     {
       for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] + (yyvsp[(3) - (3)].v)[i];
     ;}
     break;
 
   case 480:
-#line 5281 "Gmsh.y"
+#line 5235 "Gmsh.y"
     {
       (yyval.v)[0] = (yyvsp[(2) - (11)].d);  (yyval.v)[1] = (yyvsp[(4) - (11)].d);  (yyval.v)[2] = (yyvsp[(6) - (11)].d);  (yyval.v)[3] = (yyvsp[(8) - (11)].d); (yyval.v)[4] = (yyvsp[(10) - (11)].d);
     ;}
     break;
 
   case 481:
-#line 5285 "Gmsh.y"
+#line 5239 "Gmsh.y"
     {
       (yyval.v)[0] = (yyvsp[(2) - (9)].d);  (yyval.v)[1] = (yyvsp[(4) - (9)].d);  (yyval.v)[2] = (yyvsp[(6) - (9)].d);  (yyval.v)[3] = (yyvsp[(8) - (9)].d); (yyval.v)[4] = 1.0;
     ;}
     break;
 
   case 482:
-#line 5289 "Gmsh.y"
+#line 5243 "Gmsh.y"
     {
       (yyval.v)[0] = (yyvsp[(2) - (7)].d);  (yyval.v)[1] = (yyvsp[(4) - (7)].d);  (yyval.v)[2] = (yyvsp[(6) - (7)].d);  (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0;
     ;}
     break;
 
   case 483:
-#line 5293 "Gmsh.y"
+#line 5247 "Gmsh.y"
     {
       (yyval.v)[0] = (yyvsp[(2) - (7)].d);  (yyval.v)[1] = (yyvsp[(4) - (7)].d);  (yyval.v)[2] = (yyvsp[(6) - (7)].d);  (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0;
     ;}
     break;
 
   case 484:
-#line 5300 "Gmsh.y"
+#line 5254 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(List_T*));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].l)));
@@ -12526,14 +12480,14 @@ yyreduce:
     break;
 
   case 485:
-#line 5305 "Gmsh.y"
+#line 5259 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].l)));
     ;}
     break;
 
   case 486:
-#line 5312 "Gmsh.y"
+#line 5266 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].d)));
@@ -12541,14 +12495,14 @@ yyreduce:
     break;
 
   case 487:
-#line 5317 "Gmsh.y"
+#line 5271 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(1) - (1)].l);
     ;}
     break;
 
   case 488:
-#line 5321 "Gmsh.y"
+#line 5275 "Gmsh.y"
     {
       // creates an empty list
       (yyval.l) = List_Create(2, 1, sizeof(double));
@@ -12556,14 +12510,14 @@ yyreduce:
     break;
 
   case 489:
-#line 5326 "Gmsh.y"
+#line 5280 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (3)].l);
     ;}
     break;
 
   case 490:
-#line 5330 "Gmsh.y"
+#line 5284 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(3) - (4)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -12574,7 +12528,7 @@ yyreduce:
     break;
 
   case 491:
-#line 5338 "Gmsh.y"
+#line 5292 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(4) - (5)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -12585,21 +12539,21 @@ yyreduce:
     break;
 
   case 492:
-#line 5349 "Gmsh.y"
+#line 5303 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(1) - (1)].l);
     ;}
     break;
 
   case 493:
-#line 5353 "Gmsh.y"
+#line 5307 "Gmsh.y"
     {
       (yyval.l) = 0;
     ;}
     break;
 
   case 494:
-#line 5357 "Gmsh.y"
+#line 5311 "Gmsh.y"
     {
       if(!strcmp((yyvsp[(1) - (1)].c), "*") || !strcmp((yyvsp[(1) - (1)].c), "all")){
         (yyval.l) = 0;
@@ -12613,7 +12567,7 @@ yyreduce:
     break;
 
   case 495:
-#line 5371 "Gmsh.y"
+#line 5325 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (2)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -12624,7 +12578,7 @@ yyreduce:
     break;
 
   case 496:
-#line 5379 "Gmsh.y"
+#line 5333 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(3) - (3)].l);
       for(int i = 0; i < List_Nbr((yyval.l)); i++){
@@ -12635,7 +12589,7 @@ yyreduce:
     break;
 
   case 497:
-#line 5387 "Gmsh.y"
+#line 5341 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       for(double d = (yyvsp[(1) - (3)].d); ((yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d)) ? (d <= (yyvsp[(3) - (3)].d)) : (d >= (yyvsp[(3) - (3)].d));
@@ -12645,7 +12599,7 @@ yyreduce:
     break;
 
   case 498:
-#line 5394 "Gmsh.y"
+#line 5348 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       if(!(yyvsp[(5) - (5)].d)){  //|| ($1 < $3 && $5 < 0) || ($1 > $3 && $5 > 0)
@@ -12658,7 +12612,7 @@ yyreduce:
     break;
 
   case 499:
-#line 5404 "Gmsh.y"
+#line 5358 "Gmsh.y"
     {
       (yyval.l) = List_Create(3, 1, sizeof(double));
       int tag = (int)(yyvsp[(3) - (4)].d);
@@ -12684,7 +12638,7 @@ yyreduce:
     break;
 
   case 500:
-#line 5427 "Gmsh.y"
+#line 5381 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       getAllElementaryTags(0, (yyval.l));
@@ -12692,7 +12646,7 @@ yyreduce:
     break;
 
   case 501:
-#line 5432 "Gmsh.y"
+#line 5386 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       getAllElementaryTags(0, (yyval.l));
@@ -12701,7 +12655,7 @@ yyreduce:
     break;
 
   case 502:
-#line 5438 "Gmsh.y"
+#line 5392 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       getAllElementaryTags((yyvsp[(1) - (4)].i), (yyval.l));
@@ -12709,7 +12663,7 @@ yyreduce:
     break;
 
   case 503:
-#line 5443 "Gmsh.y"
+#line 5397 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       getAllElementaryTags((yyvsp[(1) - (2)].i), (yyval.l));
@@ -12718,7 +12672,7 @@ yyreduce:
     break;
 
   case 504:
-#line 5449 "Gmsh.y"
+#line 5403 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       if(!(yyvsp[(3) - (3)].l)){
@@ -12732,7 +12686,7 @@ yyreduce:
     break;
 
   case 505:
-#line 5461 "Gmsh.y"
+#line 5415 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       getElementaryTagsInBoundingBox((yyvsp[(1) - (16)].i), (yyvsp[(5) - (16)].d), (yyvsp[(7) - (16)].d), (yyvsp[(9) - (16)].d), (yyvsp[(11) - (16)].d), (yyvsp[(13) - (16)].d), (yyvsp[(15) - (16)].d), (yyval.l));
@@ -12740,7 +12694,7 @@ yyreduce:
     break;
 
   case 506:
-#line 5466 "Gmsh.y"
+#line 5420 "Gmsh.y"
     {
       (yyval.l) = List_Create(10, 10, sizeof(double));
       getBoundingBox((yyvsp[(2) - (5)].i), (int)(yyvsp[(4) - (5)].d), (yyval.l));
@@ -12748,7 +12702,7 @@ yyreduce:
     break;
 
   case 507:
-#line 5471 "Gmsh.y"
+#line 5425 "Gmsh.y"
     {
       (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double));
       for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){
@@ -12761,7 +12715,7 @@ yyreduce:
     break;
 
   case 508:
-#line 5481 "Gmsh.y"
+#line 5435 "Gmsh.y"
     {
       (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double));
       for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){
@@ -12774,7 +12728,7 @@ yyreduce:
     break;
 
   case 509:
-#line 5491 "Gmsh.y"
+#line 5445 "Gmsh.y"
     {
       (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double));
       for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){
@@ -12787,7 +12741,7 @@ yyreduce:
     break;
 
   case 510:
-#line 5501 "Gmsh.y"
+#line 5455 "Gmsh.y"
     {
       (yyval.l) = List_Create(20, 20, sizeof(double));
       if(!gmsh_yysymbols.count((yyvsp[(1) - (3)].c)))
@@ -12802,21 +12756,21 @@ yyreduce:
     break;
 
   case 511:
-#line 5513 "Gmsh.y"
+#line 5467 "Gmsh.y"
     {
       (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfFloat(NULL, (yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c));
     ;}
     break;
 
   case 512:
-#line 5517 "Gmsh.y"
+#line 5471 "Gmsh.y"
     {
       (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfFloat((yyvsp[(1) - (7)].c), (yyvsp[(3) - (7)].c), (yyvsp[(5) - (7)].c));
     ;}
     break;
 
   case 513:
-#line 5522 "Gmsh.y"
+#line 5476 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       if(!gmsh_yysymbols.count((yyvsp[(3) - (4)].c)))
@@ -12831,28 +12785,28 @@ yyreduce:
     break;
 
   case 514:
-#line 5534 "Gmsh.y"
+#line 5488 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(3) - (4)].l);
     ;}
     break;
 
   case 515:
-#line 5538 "Gmsh.y"
+#line 5492 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(3) - (4)].l);
     ;}
     break;
 
   case 516:
-#line 5542 "Gmsh.y"
+#line 5496 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(4) - (6)].l);
     ;}
     break;
 
   case 517:
-#line 5546 "Gmsh.y"
+#line 5500 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       if(!gmsh_yysymbols.count((yyvsp[(1) - (6)].c)))
@@ -12873,7 +12827,7 @@ yyreduce:
     break;
 
   case 518:
-#line 5564 "Gmsh.y"
+#line 5518 "Gmsh.y"
     {
       (yyval.l) = List_Create(20,20,sizeof(double));
       for(int i = 0; i < (int)(yyvsp[(7) - (8)].d); i++) {
@@ -12884,7 +12838,7 @@ yyreduce:
     break;
 
   case 519:
-#line 5572 "Gmsh.y"
+#line 5526 "Gmsh.y"
     {
       (yyval.l) = List_Create(20,20,sizeof(double));
       for(int i = 0; i < (int)(yyvsp[(7) - (8)].d); i++) {
@@ -12895,7 +12849,7 @@ yyreduce:
     break;
 
   case 520:
-#line 5580 "Gmsh.y"
+#line 5534 "Gmsh.y"
     {
       Msg::Barrier();
       FILE *File;
@@ -12927,7 +12881,7 @@ yyreduce:
     break;
 
   case 521:
-#line 5609 "Gmsh.y"
+#line 5563 "Gmsh.y"
     {
       double x0 = (yyvsp[(3) - (14)].d), x1 = (yyvsp[(5) - (14)].d), y0 = (yyvsp[(7) - (14)].d), y1 = (yyvsp[(9) - (14)].d), ys = (yyvsp[(11) - (14)].d);
       int N = (int)(yyvsp[(13) - (14)].d);
@@ -12940,7 +12894,7 @@ yyreduce:
     break;
 
   case 522:
-#line 5619 "Gmsh.y"
+#line 5573 "Gmsh.y"
     {
       std::vector<double> tmp;
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){
@@ -12959,7 +12913,7 @@ yyreduce:
     break;
 
   case 523:
-#line 5635 "Gmsh.y"
+#line 5589 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){
         double *d = (double*)List_Pointer((yyvsp[(3) - (4)].l), i);
@@ -12970,7 +12924,7 @@ yyreduce:
     break;
 
   case 524:
-#line 5646 "Gmsh.y"
+#line 5600 "Gmsh.y"
     {
       (yyval.l) = List_Create(2, 1, sizeof(double));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].d)));
@@ -12978,21 +12932,21 @@ yyreduce:
     break;
 
   case 525:
-#line 5651 "Gmsh.y"
+#line 5605 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(1) - (1)].l);
     ;}
     break;
 
   case 526:
-#line 5655 "Gmsh.y"
+#line 5609 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].d)));
     ;}
     break;
 
   case 527:
-#line 5659 "Gmsh.y"
+#line 5613 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){
 	double d;
@@ -13004,21 +12958,21 @@ yyreduce:
     break;
 
   case 528:
-#line 5671 "Gmsh.y"
+#line 5625 "Gmsh.y"
     {
       (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (9)].d), (int)(yyvsp[(4) - (9)].d), (int)(yyvsp[(6) - (9)].d), (int)(yyvsp[(8) - (9)].d));
     ;}
     break;
 
   case 529:
-#line 5675 "Gmsh.y"
+#line 5629 "Gmsh.y"
     {
       (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (7)].d), (int)(yyvsp[(4) - (7)].d), (int)(yyvsp[(6) - (7)].d), 255);
     ;}
     break;
 
   case 530:
-#line 5687 "Gmsh.y"
+#line 5641 "Gmsh.y"
     {
       int flag = 0;
       if(gmsh_yystringsymbols.count((yyvsp[(1) - (1)].c))){
@@ -13038,7 +12992,7 @@ yyreduce:
     break;
 
   case 531:
-#line 5704 "Gmsh.y"
+#line 5658 "Gmsh.y"
     {
       unsigned int val = 0;
       ColorOption(GMSH_GET, (yyvsp[(1) - (5)].c), 0, (yyvsp[(5) - (5)].c), val);
@@ -13048,14 +13002,14 @@ yyreduce:
     break;
 
   case 532:
-#line 5714 "Gmsh.y"
+#line 5668 "Gmsh.y"
     {
       (yyval.l) = (yyvsp[(2) - (3)].l);
     ;}
     break;
 
   case 533:
-#line 5718 "Gmsh.y"
+#line 5672 "Gmsh.y"
     {
       (yyval.l) = List_Create(256, 10, sizeof(unsigned int));
       GmshColorTable *ct = GetColorTable((int)(yyvsp[(3) - (6)].d));
@@ -13070,7 +13024,7 @@ yyreduce:
     break;
 
   case 534:
-#line 5733 "Gmsh.y"
+#line 5687 "Gmsh.y"
     {
       (yyval.l) = List_Create(256, 10, sizeof(unsigned int));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].u)));
@@ -13078,21 +13032,21 @@ yyreduce:
     break;
 
   case 535:
-#line 5738 "Gmsh.y"
+#line 5692 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].u)));
     ;}
     break;
 
   case 536:
-#line 5745 "Gmsh.y"
+#line 5699 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(1) - (1)].c);
     ;}
     break;
 
   case 537:
-#line 5749 "Gmsh.y"
+#line 5703 "Gmsh.y"
     {
       // No need to extend to Struct_FullName (a Tag is not a String)
       (yyval.c) = treat_Struct_FullName_String(NULL, (yyvsp[(1) - (1)].c));
@@ -13100,7 +13054,7 @@ yyreduce:
     break;
 
   case 538:
-#line 5754 "Gmsh.y"
+#line 5708 "Gmsh.y"
     {
       std::string val;
       int j = (int)(yyvsp[(3) - (4)].d);
@@ -13117,7 +13071,7 @@ yyreduce:
     break;
 
   case 539:
-#line 5768 "Gmsh.y"
+#line 5722 "Gmsh.y"
     {
       std::string val;
       int j = (int)(yyvsp[(3) - (4)].d);
@@ -13134,35 +13088,35 @@ yyreduce:
     break;
 
   case 540:
-#line 5784 "Gmsh.y"
+#line 5738 "Gmsh.y"
     {
       (yyval.c) = treat_Struct_FullName_dot_tSTRING_String(NULL, (yyvsp[(1) - (3)].c), (yyvsp[(3) - (3)].c));
     ;}
     break;
 
   case 541:
-#line 5788 "Gmsh.y"
+#line 5742 "Gmsh.y"
     {
       (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c), (yyvsp[(5) - (5)].c));
     ;}
     break;
 
   case 542:
-#line 5792 "Gmsh.y"
+#line 5746 "Gmsh.y"
     {
       (yyval.c) = treat_Struct_FullName_dot_tSTRING_String(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d));
     ;}
     break;
 
   case 543:
-#line 5796 "Gmsh.y"
+#line 5750 "Gmsh.y"
     {
       (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d));
     ;}
     break;
 
   case 544:
-#line 5800 "Gmsh.y"
+#line 5754 "Gmsh.y"
     {
       std::string out;
       StringOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), out);
@@ -13173,7 +13127,7 @@ yyreduce:
     break;
 
   case 545:
-#line 5808 "Gmsh.y"
+#line 5762 "Gmsh.y"
     {
       std::string name = GModel::current()->getPhysicalName(0, (int)(yyvsp[(4) - (5)].d));
       (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char));
@@ -13182,7 +13136,7 @@ yyreduce:
     break;
 
   case 546:
-#line 5814 "Gmsh.y"
+#line 5768 "Gmsh.y"
     {
       std::string name = GModel::current()->getPhysicalName(1, (int)(yyvsp[(4) - (5)].d));
       (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char));
@@ -13191,7 +13145,7 @@ yyreduce:
     break;
 
   case 547:
-#line 5820 "Gmsh.y"
+#line 5774 "Gmsh.y"
     {
       std::string name = GModel::current()->getPhysicalName(2, (int)(yyvsp[(4) - (5)].d));
       (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char));
@@ -13200,7 +13154,7 @@ yyreduce:
     break;
 
   case 548:
-#line 5826 "Gmsh.y"
+#line 5780 "Gmsh.y"
     {
       std::string name = GModel::current()->getPhysicalName(3, (int)(yyvsp[(4) - (5)].d));
       (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char));
@@ -13209,21 +13163,21 @@ yyreduce:
     break;
 
   case 549:
-#line 5835 "Gmsh.y"
+#line 5789 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(1) - (1)].c);
     ;}
     break;
 
   case 550:
-#line 5839 "Gmsh.y"
+#line 5793 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(3) - (4)].c);
     ;}
     break;
 
   case 551:
-#line 5843 "Gmsh.y"
+#line 5797 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc(32 * sizeof(char));
       time_t now;
@@ -13234,7 +13188,7 @@ yyreduce:
     break;
 
   case 552:
-#line 5851 "Gmsh.y"
+#line 5805 "Gmsh.y"
     {
       std::string exe = Msg::GetExecutableName();
       (yyval.c) = (char *)Malloc(exe.size() + 1);
@@ -13243,7 +13197,7 @@ yyreduce:
     break;
 
   case 553:
-#line 5857 "Gmsh.y"
+#line 5811 "Gmsh.y"
     {
       std::string action = Msg::GetOnelabAction();
       (yyval.c) = (char *)Malloc(action.size() + 1);
@@ -13252,14 +13206,14 @@ yyreduce:
     break;
 
   case 554:
-#line 5863 "Gmsh.y"
+#line 5817 "Gmsh.y"
     {
       (yyval.c) = strsave((char*)"Gmsh");
     ;}
     break;
 
   case 555:
-#line 5867 "Gmsh.y"
+#line 5821 "Gmsh.y"
     {
       const char *env = GetEnvironmentVar((yyvsp[(3) - (4)].c));
       if(!env) env = "";
@@ -13270,7 +13224,7 @@ yyreduce:
     break;
 
   case 556:
-#line 5875 "Gmsh.y"
+#line 5829 "Gmsh.y"
     {
       std::string s = Msg::GetString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c));
       (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char));
@@ -13281,7 +13235,7 @@ yyreduce:
     break;
 
   case 557:
-#line 5883 "Gmsh.y"
+#line 5837 "Gmsh.y"
     {
       std::string s = Msg::GetOnelabString((yyvsp[(3) - (4)].c));
       (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char));
@@ -13291,7 +13245,7 @@ yyreduce:
     break;
 
   case 558:
-#line 5890 "Gmsh.y"
+#line 5844 "Gmsh.y"
     {
       std::string s = Msg::GetOnelabString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c));
       (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char));
@@ -13302,21 +13256,21 @@ yyreduce:
     break;
 
   case 559:
-#line 5899 "Gmsh.y"
+#line 5853 "Gmsh.y"
     {
       (yyval.c) = treat_Struct_FullName_String(NULL, (yyvsp[(3) - (5)].c2).char2, 1, 0, (yyvsp[(4) - (5)].c), 2);
     ;}
     break;
 
   case 560:
-#line 5903 "Gmsh.y"
+#line 5857 "Gmsh.y"
     {
       (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(3) - (7)].c2).char1, (yyvsp[(3) - (7)].c2).char2, (yyvsp[(5) - (7)].c), 0, (yyvsp[(6) - (7)].c), 2);
     ;}
     break;
 
   case 561:
-#line 5907 "Gmsh.y"
+#line 5861 "Gmsh.y"
     {
       int size = 1;
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++)
@@ -13334,7 +13288,7 @@ yyreduce:
     break;
 
   case 562:
-#line 5922 "Gmsh.y"
+#line 5876 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char));
       int i;
@@ -13351,7 +13305,7 @@ yyreduce:
     break;
 
   case 563:
-#line 5936 "Gmsh.y"
+#line 5890 "Gmsh.y"
     {
       (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char));
       int i;
@@ -13368,7 +13322,7 @@ yyreduce:
     break;
 
   case 564:
-#line 5950 "Gmsh.y"
+#line 5904 "Gmsh.y"
     {
       std::string input = (yyvsp[(3) - (8)].c);
       std::string substr_old = (yyvsp[(5) - (8)].c);
@@ -13383,7 +13337,7 @@ yyreduce:
     break;
 
   case 565:
-#line 5962 "Gmsh.y"
+#line 5916 "Gmsh.y"
     {
       int size = 1;
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++)
@@ -13402,7 +13356,7 @@ yyreduce:
     break;
 
   case 566:
-#line 5978 "Gmsh.y"
+#line 5932 "Gmsh.y"
     {
       int i = 0;
       while ((yyvsp[(3) - (4)].c)[i]) {
@@ -13414,7 +13368,7 @@ yyreduce:
     break;
 
   case 567:
-#line 5987 "Gmsh.y"
+#line 5941 "Gmsh.y"
     {
       int i = 0;
       while ((yyvsp[(3) - (4)].c)[i]) {
@@ -13426,7 +13380,7 @@ yyreduce:
     break;
 
   case 568:
-#line 5996 "Gmsh.y"
+#line 5950 "Gmsh.y"
     {
       int i = 0;
       while ((yyvsp[(3) - (4)].c)[i]) {
@@ -13439,7 +13393,7 @@ yyreduce:
     break;
 
   case 569:
-#line 6006 "Gmsh.y"
+#line 5960 "Gmsh.y"
     {
       if((yyvsp[(3) - (8)].d)){
         (yyval.c) = (yyvsp[(5) - (8)].c);
@@ -13453,7 +13407,7 @@ yyreduce:
     break;
 
   case 570:
-#line 6017 "Gmsh.y"
+#line 5971 "Gmsh.y"
     {
       std::string in = (yyvsp[(3) - (8)].c);
       std::string out = in.substr((int)(yyvsp[(5) - (8)].d), (int)(yyvsp[(7) - (8)].d));
@@ -13464,7 +13418,7 @@ yyreduce:
     break;
 
   case 571:
-#line 6025 "Gmsh.y"
+#line 5979 "Gmsh.y"
     {
       std::string in = (yyvsp[(3) - (6)].c);
       std::string out = in.substr((int)(yyvsp[(5) - (6)].d), std::string::npos);
@@ -13475,14 +13429,14 @@ yyreduce:
     break;
 
   case 572:
-#line 6033 "Gmsh.y"
+#line 5987 "Gmsh.y"
     {
       (yyval.c) = (yyvsp[(3) - (4)].c);
     ;}
     break;
 
   case 573:
-#line 6037 "Gmsh.y"
+#line 5991 "Gmsh.y"
     {
       char tmpstring[5000];
       int i = printListOfDouble((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].l), tmpstring);
@@ -13504,7 +13458,7 @@ yyreduce:
     break;
 
   case 574:
-#line 6056 "Gmsh.y"
+#line 6010 "Gmsh.y"
     {
       std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c));
       (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char));
@@ -13514,7 +13468,7 @@ yyreduce:
     break;
 
   case 575:
-#line 6063 "Gmsh.y"
+#line 6017 "Gmsh.y"
     {
       std::string tmp = SplitFileName(GetAbsolutePath(gmsh_yyname))[0];
       (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char));
@@ -13523,7 +13477,7 @@ yyreduce:
     break;
 
   case 576:
-#line 6069 "Gmsh.y"
+#line 6023 "Gmsh.y"
     {
       std::string tmp = SplitFileName((yyvsp[(3) - (4)].c))[0];
       (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char));
@@ -13533,7 +13487,7 @@ yyreduce:
     break;
 
   case 577:
-#line 6076 "Gmsh.y"
+#line 6030 "Gmsh.y"
     {
       std::string tmp = GetAbsolutePath((yyvsp[(3) - (4)].c));
       (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char));
@@ -13543,12 +13497,12 @@ yyreduce:
     break;
 
   case 578:
-#line 6083 "Gmsh.y"
+#line 6037 "Gmsh.y"
     { init_options(); ;}
     break;
 
   case 579:
-#line 6085 "Gmsh.y"
+#line 6039 "Gmsh.y"
     {
       std::string val((yyvsp[(3) - (6)].c));
       Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions);
@@ -13559,7 +13513,7 @@ yyreduce:
     break;
 
   case 580:
-#line 6093 "Gmsh.y"
+#line 6047 "Gmsh.y"
     {
       std::string out;
       const std::string * key_struct = NULL;
@@ -13583,37 +13537,37 @@ yyreduce:
     break;
 
   case 581:
-#line 6117 "Gmsh.y"
+#line 6071 "Gmsh.y"
     { struct_namespace = std::string(""); (yyval.d) = (yyvsp[(2) - (2)].d); ;}
     break;
 
   case 582:
-#line 6119 "Gmsh.y"
+#line 6073 "Gmsh.y"
     { struct_namespace = (yyvsp[(1) - (4)].c); Free((yyvsp[(1) - (4)].c)); (yyval.d) = (yyvsp[(4) - (4)].d); ;}
     break;
 
   case 583:
-#line 6125 "Gmsh.y"
+#line 6079 "Gmsh.y"
     { (yyval.l) = (yyvsp[(3) - (4)].l); ;}
     break;
 
   case 584:
-#line 6130 "Gmsh.y"
+#line 6084 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 585:
-#line 6132 "Gmsh.y"
+#line 6086 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 586:
-#line 6137 "Gmsh.y"
+#line 6091 "Gmsh.y"
     { (yyval.l) = (yyvsp[(2) - (3)].l); ;}
     break;
 
   case 587:
-#line 6142 "Gmsh.y"
+#line 6096 "Gmsh.y"
     {
       (yyval.l) = List_Create(20,20,sizeof(char*));
       List_Add((yyval.l), &((yyvsp[(1) - (1)].c)));
@@ -13621,19 +13575,19 @@ yyreduce:
     break;
 
   case 588:
-#line 6147 "Gmsh.y"
+#line 6101 "Gmsh.y"
     { (yyval.l) = (yyvsp[(1) - (1)].l); ;}
     break;
 
   case 589:
-#line 6149 "Gmsh.y"
+#line 6103 "Gmsh.y"
     {
       List_Add((yyval.l), &((yyvsp[(3) - (3)].c)));
     ;}
     break;
 
   case 590:
-#line 6153 "Gmsh.y"
+#line 6107 "Gmsh.y"
     {
       for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){
 	char* c;
@@ -13645,7 +13599,7 @@ yyreduce:
     break;
 
   case 591:
-#line 6165 "Gmsh.y"
+#line 6119 "Gmsh.y"
     {
       (yyval.l) = List_Create(20, 20, sizeof(char *));
       if(!gmsh_yystringsymbols.count((yyvsp[(1) - (3)].c)))
@@ -13662,21 +13616,21 @@ yyreduce:
     break;
 
   case 592:
-#line 6179 "Gmsh.y"
+#line 6133 "Gmsh.y"
     {
       (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfString(NULL, (yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c));
     ;}
     break;
 
   case 593:
-#line 6183 "Gmsh.y"
+#line 6137 "Gmsh.y"
     {
       (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfString((yyvsp[(1) - (7)].c), (yyvsp[(3) - (7)].c), (yyvsp[(5) - (7)].c));
     ;}
     break;
 
   case 594:
-#line 6190 "Gmsh.y"
+#line 6144 "Gmsh.y"
     {
       char tmpstr[256];
       sprintf(tmpstr, "_%d", (int)(yyvsp[(4) - (5)].d));
@@ -13687,7 +13641,7 @@ yyreduce:
     break;
 
   case 595:
-#line 6198 "Gmsh.y"
+#line 6152 "Gmsh.y"
     {
       char tmpstr[256];
       sprintf(tmpstr, "_%d", (int)(yyvsp[(4) - (5)].d));
@@ -13698,7 +13652,7 @@ yyreduce:
     break;
 
   case 596:
-#line 6206 "Gmsh.y"
+#line 6160 "Gmsh.y"
     {
       char tmpstr[256];
       sprintf(tmpstr, "_%d", (int)(yyvsp[(7) - (8)].d));
@@ -13709,23 +13663,23 @@ yyreduce:
     break;
 
   case 597:
-#line 6217 "Gmsh.y"
+#line 6171 "Gmsh.y"
     { (yyval.c) = (yyvsp[(1) - (1)].c); ;}
     break;
 
   case 598:
-#line 6219 "Gmsh.y"
+#line 6173 "Gmsh.y"
     { (yyval.c) = (yyvsp[(1) - (1)].c); ;}
     break;
 
   case 599:
-#line 6222 "Gmsh.y"
+#line 6176 "Gmsh.y"
     { (yyval.c) = (yyvsp[(3) - (4)].c); ;}
     break;
 
 
 /* Line 1267 of yacc.c.  */
-#line 13729 "Gmsh.tab.cpp"
+#line 13683 "Gmsh.tab.cpp"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -13939,7 +13893,7 @@ yyreturn:
 }
 
 
-#line 6225 "Gmsh.y"
+#line 6179 "Gmsh.y"
 
 
 void assignVariable(const std::string &name, int index, int assignType,
diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y
index 4200917b0193120c90fcc9c1764e3eadd99c437d..5667f813e79058d973b5a62655c78571171f8c51 100644
--- a/Parser/Gmsh.y
+++ b/Parser/Gmsh.y
@@ -2161,62 +2161,16 @@ Shape :
     }
   | tCompound GeoEntity123 '(' FExpr ')' tAFFECT ListOfDouble tEND
     {
-      int num = (int)$4;
-      std::vector<int> tags; ListOfDouble2Vector($7, tags);
-      switch ($2) {
-      case 1:
-        {
-          bool r = GModel::current()->getGEOInternals()->addCompoundLine(num, tags);
-          if(!r) yymsg(0, "Could not add compound line");
-        }
-        $$.Type = MSH_SEGM_COMPOUND;
-        break;
-      case 2:
-        {
-          bool r = GModel::current()->getGEOInternals()->addCompoundSurface(num, tags);
-          if(!r) yymsg(0, "Could not add compound surface");
-        }
-        $$.Type = MSH_SURF_COMPOUND;
-        break;
-      case 3:
-        {
-          bool r = GModel::current()->getGEOInternals()->addCompoundVolume(num, tags);
-          if(!r) yymsg(0, "Could not add compound volume");
-        }
-        $$.Type = MSH_VOLUME_COMPOUND;
-        break;
-      }
-      List_Delete($7);
-      $$.Num = num;
+      yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead");
+      $$.Type = 0;
+      $$.Num = 0;
     }
   | tCompound GeoEntity123 '(' FExpr ')' tAFFECT ListOfDouble tSTRING
       '{' RecursiveListOfListOfDouble '}' tEND
     {
-      // Particular case only for dim 2 (Surface)
-      if ($2 == 2) {
-        int num = (int)$4;
-        std::vector<int> tags; ListOfDouble2Vector($7, tags);
-        std::vector<int> bndTags[4];
-        for(int i = 0; i < List_Nbr($10); i++){
-          if(i < 4)
-            ListOfDouble2Vector(*(List_T**)List_Pointer($10, i), bndTags[i]);
-          else
-            break;
-        }
-        bool r = GModel::current()->getGEOInternals()->addCompoundSurface
-          (num, tags, bndTags);
-        if(!r) yymsg(0, "Could not add compound surface");
-        List_Delete($7);
-        Free($8);
-        for (int i = 0; i < List_Nbr($10); i++)
-          List_Delete(*(List_T**)List_Pointer($10, i));
-        List_Delete($10);
-        $$.Type = MSH_SURF_COMPOUND;
-        $$.Num = num;
-      }
-      else {
-        yymsg(0, "GeoEntity dim out of range [2,2]");
-      }
+      yymsg(0, "Compounds entities are deprecated: use Compound meshing constraints instead");
+      $$.Type = 0;
+      $$.Num = 0;
     }
   | tPhysical GeoEntity
     {
diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt
index d9f5de36614eb4848556ccdc3dad4f09925f3a74..9254e2aa6d368096dcbb97c0dd5d80da9332ea8f 100644
--- a/Solver/CMakeLists.txt
+++ b/Solver/CMakeLists.txt
@@ -15,7 +15,6 @@ elasticitySolver.cpp
   thermicSolver.cpp
   SElement.cpp
   eigenSolver.cpp
-  multiscaleLaplace.cpp
 functionSpace.cpp
   filters.cpp
   frameSolver.cpp
diff --git a/Solver/multiscaleLaplace.cpp b/Solver/multiscaleLaplace.cpp
deleted file mode 100644
index ca2d11eaae226ec908d1dd3350f94e0498aeeb0d..0000000000000000000000000000000000000000
--- a/Solver/multiscaleLaplace.cpp
+++ /dev/null
@@ -1,1138 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-//
-// Contributor(s):
-//   Emilie Marchandise
-//
-
-#include "Context.h"
-#include "multiscaleLaplace.h"
-#include "GmshConfig.h"
-#include "GmshDefines.h"
-#include "Numeric.h"
-#include "OS.h"
-#include "SBoundingBox3d.h"
-#include "SPoint3.h"
-#include "dofManager.h"
-#include "laplaceTerm.h"
-#include "convexCombinationTerm.h"
-#include "linearSystemCSR.h"
-#include "linearSystemPETSc.h"
-#include "robustPredicates.h"
-#include "meshGFaceOptimize.h"
-#include "GFaceCompound.h"
-
-#ifdef HAVE_GMM
-#include "linearSystemGMM.h"
-#endif
-
-#include "linearSystemFull.h"
-#include "MTriangle.h"
-#include "robustPredicates.h"
-
-struct compareRotatedPoints {
-  double angle;
-  const SPoint2 &left;
-  compareRotatedPoints (const SPoint2& l,const SPoint2& r) : left(l){
-    angle = atan2(r.y()-l.y(),r.x()-l.x());
-  }
-  bool operator  ( ) (const SPoint2 &p1, const SPoint2 &p2) const {
-    //sort from left (x=-1) to right (sin=0), cos(=1)
-    double x1 = (p1.x()-left.x())*cos(angle) + (p1.y()-left.y())*sin(angle);
-    double x2 = (p2.x()-left.x())*cos(angle) + (p2.y()-left.y())*sin(angle);
-    if (x1<x2)return true;
-    if (x1>x2)return false;
-    double y1 =-(p1.x()-left.x())*sin(angle) + (p1.y()-left.y())*cos(angle);
-    double y2 =-(p2.x()-left.x())*sin(angle) + (p2.y()-left.y())*cos(angle);
-    if (y1<y2)return true;
-    return false;
-  }
-};
-
-struct sort_pred {
-  compareRotatedPoints  comparator;
-  sort_pred (const SPoint2 &left, const SPoint2 &right)
-    : comparator(left,right) {}
-  bool operator()(const std::pair<SPoint2,multiscaleLaplaceLevel*> &left,
-                  const std::pair<SPoint2,multiscaleLaplaceLevel*> &right)
-  {
-    return comparator(left.first,right.first);
-  }
-};
-
-static void recur_connect (MVertex *v,
-                           std::multimap<MVertex*,MEdge> &v2e,
-                           std::set<MEdge,Less_Edge> &group,
-                           std::set<MVertex*> &touched)
-{
-  if (touched.find(v) != touched.end()) return;
-
-  touched.insert(v);
-  for (std::multimap <MVertex*,MEdge>::iterator it = v2e.lower_bound(v);
-       it != v2e.upper_bound(v) ; ++it){
-    group.insert(it->second);
-    for (int i=0;i<it->second.getNumVertices();++i){
-      recur_connect (it->second.getVertex(i),v2e,group,touched);
-    }
-  }
-
-}
-
-static void connected_bounds (std::vector<MElement*> &elements,
-                              std::vector<std::vector<MEdge> > &boundaries)
-{
-  std::vector<MEdge> bEdges;
-  for(unsigned int i = 0; i < elements.size(); i++){
-    for(int j = 0; j < elements[i]->getNumEdges(); j++){
-      MEdge me =  elements[i]->getEdge(j);
-      if(std::find(bEdges.begin(), bEdges.end(), me) == bEdges.end())
-        bEdges.push_back(me);
-      else
-        bEdges.erase(std::find(bEdges.begin(), bEdges.end(),me));
-    }
-  }
-
-  std::multimap<MVertex*,MEdge> v2e;
-  for (unsigned int i = 0; i < bEdges.size(); ++i){
-    for (int j=0;j<bEdges[i].getNumVertices();j++){
-      v2e.insert(std::make_pair(bEdges[i].getVertex(j),bEdges[i]));
-    }
-  }
-  while (!v2e.empty()){
-    std::set<MEdge, Less_Edge> group;
-    std::set<MVertex*> touched;
-    recur_connect (v2e.begin()->first,v2e,group,touched);
-    std::vector<MEdge> temp;
-    temp.insert(temp.begin(), group.begin(), group.end());
-    boundaries.push_back(temp);
-    for ( std::set<MVertex*>::iterator it = touched.begin() ; it != touched.end();++it)
-      v2e.erase(*it);
-  }
-
-  return;
-}
-
-static double getSizeBB(std::vector<MEdge> &me)
-{
-  SBoundingBox3d bb ;
-  SOrientedBoundingBox obbox ;
-
-  std::vector<SPoint3> vertices;
-  for (unsigned int i=0; i< me.size(); i++){
-    MVertex *v0 = me[i].getVertex(0);
-    MVertex *v1 = me[i].getVertex(1);
-    SPoint3 pt1(v0->x(),v0->y(), v0->z());
-    vertices.push_back(pt1);
-    SPoint3 pt2(v1->x(),v1->y(), v1->z());
-    vertices.push_back(pt2);
-    bb+=pt1;
-    bb+=pt2;
-  }
-
-  //double H = norm(SVector3(bb.max(), bb.min()));
-  //printf("H=%g \n", H);
-
-  obbox =  SOrientedBoundingBox::buildOBB(vertices);
-  double H =  obbox.getMaxSize();
-
-  return H;
-}
-
-static void  ordering_dirichlet(std::vector<MElement*> &elements,
-                                std::vector<std::pair<MVertex*,double> > &dirichletNodes)
-{
-  //finding all boundaries
-  std::vector<std::vector<MEdge> > boundaries;
-  connected_bounds(elements,boundaries);
-
-  //largest boundary is dirichlet boundary
-  std::vector<MEdge> dirichletEdges;
-  double maxSize = 0.0;
-  for(unsigned int i = 0; i < boundaries.size(); i++){
-    std::vector<MEdge> iBound = boundaries[i];
-    double size = getSizeBB(iBound);
-    if (size > maxSize) {
-      dirichletEdges = iBound;
-      maxSize = size;
-    }
-  }
-
-  //ordering dirichletNodes
-  dirichletNodes.clear();
-  std::list<MEdge> temp;
-  double tot_length = 0.0;
-  for(unsigned int i = 0; i < dirichletEdges.size(); i++ ){
-      MVertex *v0 =  dirichletEdges[i].getVertex(0);
-      MVertex *v1 =  dirichletEdges[i].getVertex(1);
-      double len = 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 += len;
-      temp.push_back(dirichletEdges[i]);
-  }
-
-  dirichletNodes.push_back(std::make_pair(dirichletEdges[0].getVertex(0),0.0));
-  MVertex *current_v =  dirichletEdges[0].getVertex(1);
-  temp.erase(temp.begin());
-
-  while(temp.size()){
-    bool found = false;
-    for(std::list<MEdge>::iterator itl = temp.begin(); itl != temp.end(); ++itl){
-      MVertex *v0 =  itl->getVertex(0);
-      MVertex *v1 =  itl->getVertex(1);
-      if(v0 == current_v){
-        found = true;
-        current_v = v1;
-        temp.erase(itl);
-        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()));
-        double iLength = dirichletNodes[dirichletNodes.size()-1].second +
-          (length / tot_length);
-        dirichletNodes.push_back(std::make_pair(v0,iLength));
-        break;
-      }
-      else if(v1 == current_v){
-        found = true;
-        current_v = v0;
-        temp.erase(itl);
-        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()));
-        double iLength = dirichletNodes[dirichletNodes.size()-1].second +
-          (length  / tot_length);
-        dirichletNodes.push_back(std::make_pair(v1,iLength));
-        break;
-      }
-    }
-    if(!found) return ;
-  }
-
-  return;
-}
-
-static int intersection_segments (SPoint2 &p1, SPoint2 &p2,
-                                  SPoint2 &q1, SPoint2 &q2,
-                                  double x[2])
-{
-  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 recur_compute_centers_ (double R, double a1, double a2,
-                                    multiscaleLaplaceLevel * root, int &nbElems)
-{
-  nbElems += root->elements.size();
-
-  root->radius = R;
-  std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > &centers = root->cut;
-  centers.clear();
-  multiscaleLaplaceLevel* zero = 0;
-
-  double fact = 2.5;
-  SPoint2 PL (fact*R*cos(a1),fact*R*sin(a1));
-  SPoint2 PR (fact*R*cos(a2),fact*R*sin(a2));
-
-  std::vector<SPoint2> centersChild;
-  centersChild.clear();
-  for (unsigned int i=0;i<root->children.size();i++){
-    multiscaleLaplaceLevel* m = root->children[i];
-    centers.push_back(std::make_pair(m->center,m));
-    m->radius = 0.0;
-    for (std::map<MVertex*,SPoint2>::iterator it = m->coordinates.begin();
-         it !=  m->coordinates.end() ; ++it){
-      SPoint2 p = it->second;
-      m->radius = std::max(m->radius,sqrt ((m->center.x() - p.x())*(m->center.x() - p.x())+
-                                           (m->center.y() - p.y())*(m->center.y() - p.y())));
-    }
-    centersChild.push_back(m->center);
-  }
-
-  //add the center of real holes ...
-  std::vector<std::vector<MEdge> > boundaries;
-  connected_bounds(root->elements, boundaries);
-  int added = 0;
-  int toadd = boundaries.size()-1 - root->children.size();
-  if (root->children.size()==0  || (root->children.size()> 0 && toadd > 0) ){
-    for (unsigned int i = 0; i < boundaries.size(); i++){
-      std::vector<MEdge> me = boundaries[i];
-      SPoint2 c(0.0,0.0);
-      double rad = 0.0;
-      for(unsigned int j= 0; j< me.size(); j++){
-        MVertex *v = me[j].getVertex(0);
-        std::map<MVertex *, SPoint2>::iterator it0 = root->coordinates.find(v);
-        c += it0->second;
-      }
-      c *= 1./((double)me.size());
-      for(unsigned int j= 0; j< me.size(); j++){
-        SPoint2 p =  root->coordinates[me[j].getVertex(0)];
-        rad = std::max(rad,sqrt ((c.x() - p.x())*(c.x() - p.x())+
-                                 (c.y() - p.y())*(c.y() - p.y())));
-      }
-
-      //check if the center has not been added
-      bool newCenter = true;
-      for (std::vector<SPoint2>::iterator it2 = centersChild.begin();
-           it2 != centersChild.end(); it2++){
-        SPoint2 p = *it2;
-        double dist = sqrt ((c.x() - p.x())*(c.x() - p.x())+
-                            (c.y() - p.y())*(c.y() - p.y()));
-        if (dist < 0.5*rad)  newCenter = false;//0.6
-      }
-
-      if (std::abs(rad/root->radius) < 0.65 && std::abs(rad) < 0.95 && newCenter){//0.6
-        added++;
-        centers.push_back(std::make_pair(c,zero));
-      }
-    }
-  }
-  if (added !=  toadd && root->children.size()> 0)  {
-    printf("!!!!!!!! ARG added = %d != %d (bounds=%d, child=%d)\n",  added,
-           (int)(boundaries.size() - 1 - root->children.size()), (int)boundaries.size(),
-           (int)root->children.size());
-  }
-
-  //sort centers from left to right
-  std::sort(centers.begin(),centers.end(), sort_pred(PL,PR));
-
-  //sort from distances
-  //sort_centers_dist(centers, PL);
-
-  centers.insert(centers.begin(), std::make_pair(PL,zero));
-  centers.push_back(std::make_pair(PR,zero));
-
-  for (unsigned int i = 1; i < centers.size() - 1; i++){
-    multiscaleLaplaceLevel* m2 = centers[i].second;
-    if (m2){
-      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_compute_centers_ (m2->radius, a1, a2, m2, nbElems);
-    }
-  }
-
-}
-
-static void recur_cut_edges_ (multiscaleLaplaceLevel *root,
-                              std::map<MEdge,MVertex*,Less_Edge> &cutEdges,
-                              std::set<MVertex*> &cutVertices)
-{
-  const double EPS = 0.001;
-
-  std::multimap<MEdge,MElement*,Less_Edge> e2e;
-  std::set<MEdge,Less_Edge> allEdges;
-  for (unsigned int i = 0; i < root->elements.size(); ++i){
-    for (int j = 0; j < root->elements[i]->getNumEdges(); j++){
-      e2e.insert(std::make_pair(root->elements[i]->getEdge(j),root->elements[i]));
-      allEdges.insert(root->elements[i]->getEdge(j));
-     }
-   }
-
-  std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > &centers = root->cut;
-  for (unsigned int i = 0; i < centers.size() - 1; i++){
-    SPoint2 p1 = centers[i].first;
-    SPoint2 p2 = centers[i+1].first;
-    //printf("*************** line p1p2 (%g %g) -- (%g %g) \n",p1.x(),p1.y(),p2.x(),p2.y());
-    for (std::set <MEdge,Less_Edge>::iterator it = allEdges.begin();
-         it != allEdges.end() ; ++it){
-      if(cutEdges.find(*it) == cutEdges.end()){//e2e.count(*it) == 2 &&
-        std::map<MVertex *, SPoint2>::iterator it0 = root->coordinates.find(it->getVertex(0));
-        std::map<MVertex *, SPoint2>::iterator it1 = root->coordinates.find(it->getVertex(1));
-        if (it0 != root->coordinates.end() && it1 != root->coordinates.end()){
-          SPoint2 q1 = root->coordinates[it->getVertex(0)];
-          SPoint2 q2 = root->coordinates[it->getVertex(1)];
-          double x[2];
-          int inters = intersection_segments (p1,p2,q1,q2,x);
-          if (inters && x[1] > EPS && x[1] < 1.-EPS){
-	    MVertex *newv = new MVertex
-              ((1.-x[1])*it->getVertex(0)->x() + x[1]*it->getVertex(1)->x(),
-               (1.-x[1])*it->getVertex(0)->y() + x[1]*it->getVertex(1)->y(),
-               (1.-x[1])*it->getVertex(0)->z() + x[1]*it->getVertex(1)->z());
-            cutEdges[*it] = newv;
-            root->coordinates[newv] = q1*(1.-x[1]) + q2*x[1] ;
-          }
-          else if (inters && x[1] <= EPS) cutVertices.insert(it->getVertex(0));
-          else if (inters && x[1] >= 1.-EPS) cutVertices.insert(it->getVertex(1));
-        }
-      }
-    }
-  }
-  for (unsigned int i = 0; i < centers.size(); i++){
-    multiscaleLaplaceLevel* m2 = centers[i].second;
-    if (m2){
-      recur_cut_edges_ (m2,cutEdges,cutVertices);
-    }
-  }
-}
-
-static void recur_cut_elements_ (multiscaleLaplaceLevel * root,
-                                 std::map<MEdge,MVertex*,Less_Edge> &cutEdges,
-                                 std::set<MVertex*> &cutVertices,
-                                 std::set<MEdge,Less_Edge> &theCut,
-                                 std::vector<MElement*> &_all)
-{
-  std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > &centers = root->cut;
-  std::vector<MElement*> newElements;
-  for (unsigned int i = 0; i < root->elements.size(); i++){
-    MVertex *c[3] = {0,0,0};
-    for (int j=0;j<3;j++){
-      MEdge ed = root->elements[i]->getEdge(j);
-      std::map<MEdge,MVertex*,Less_Edge> :: iterator it = cutEdges.find(ed);
-      if (it != cutEdges.end()){
-        c[j] = it->second;
-      }
-    }
-    if (c[0] && c[1]){
-      newElements.push_back(new MTriangle (c[0],root->elements[i]->getVertex(1),c[1]));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[0],
-                                           root->elements[i]->getVertex(2)));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[0],c[1]));
-      theCut.insert(MEdge(c[0],c[1]));
-    }
-    else if (c[0] && c[2]){
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[0],c[2]));
-      newElements.push_back(new MTriangle (c[0],root->elements[i]->getVertex(1),
-                                           root->elements[i]->getVertex(2)));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[2],c[0]));
-      theCut.insert(MEdge(c[0],c[2]));
-    }
-    else if (c[1] && c[2]){
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[2],c[1]));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),
-                                           root->elements[i]->getVertex(1),c[2]));
-      newElements.push_back(new MTriangle (c[2],root->elements[i]->getVertex(1),c[1]));
-      theCut.insert(MEdge(c[1],c[2]));
-    }
-    else if (c[0]){
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[0],
-                                           root->elements[i]->getVertex(2)));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(2),c[0],
-                                           root->elements[i]->getVertex(1)));
-      if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end()){
-        theCut.insert(MEdge(c[0],root->elements[i]->getVertex(0)));
-      }
-      else if (cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) {
-        theCut.insert(MEdge(c[0],root->elements[i]->getVertex(1)));
-      }
-      else{
-        theCut.insert(MEdge(c[0],root->elements[i]->getVertex(2)));
-      }
-    }
-    else if (c[1]){
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(1),c[1],
-                                           root->elements[i]->getVertex(0)));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),c[1],
-                                           root->elements[i]->getVertex(2)));
-     if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end()){
-        theCut.insert(MEdge(c[1],root->elements[i]->getVertex(0)));
-      }
-      else if (cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) {
-        theCut.insert(MEdge(c[1],root->elements[i]->getVertex(1)));
-      }
-      else{
-        theCut.insert(MEdge(c[1],root->elements[i]->getVertex(2)));
-      }
-    }
-    else if (c[2]){
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(0),
-                                           root->elements[i]->getVertex(1), c[2]));
-      newElements.push_back(new MTriangle (root->elements[i]->getVertex(1),
-                                           root->elements[i]->getVertex(2), c[2]));
-     if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end()){
-        theCut.insert(MEdge(c[2],root->elements[i]->getVertex(0)));
-      }
-      else if (cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end()) {
-        theCut.insert(MEdge(c[2],root->elements[i]->getVertex(1)));
-      }
-      else{
-        theCut.insert(MEdge(c[2],root->elements[i]->getVertex(2)));
-      }
-    }
-    else {
-      newElements.push_back(root->elements[i]);
-      if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end() &&
-	  cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end())
-        theCut.insert(MEdge(root->elements[i]->getVertex(0),root->elements[i]->getVertex(1)));
-      if (cutVertices.find (root->elements[i]->getVertex(0)) != cutVertices.end() &&
-	  cutVertices.find (root->elements[i]->getVertex(2)) != cutVertices.end())
-        theCut.insert(MEdge(root->elements[i]->getVertex(0),root->elements[i]->getVertex(2)));
-      if (cutVertices.find (root->elements[i]->getVertex(2)) != cutVertices.end() &&
-	  cutVertices.find (root->elements[i]->getVertex(1)) != cutVertices.end())
-        theCut.insert(MEdge(root->elements[i]->getVertex(2),root->elements[i]->getVertex(1)));
-    }
-  }
-
-  root->elements.clear();
-  root->elements = newElements;
-  _all.insert(_all.end(),newElements.begin(),newElements.end());
-  for (unsigned int i = 0; i < centers.size(); i++){
-    multiscaleLaplaceLevel* m2 = centers[i].second;
-    if (m2){
-      recur_cut_elements_ (m2,cutEdges,cutVertices,theCut,_all);
-    }
-  }
-}
-
-static void recur_leftCut_ (MElement *e,
-			    std::multimap<MEdge,MElement*,Less_Edge> &e2e,
-			    std::set<MEdge,Less_Edge> &theCut,
-			    std::set<MElement*> &leftSet)
-{
-  if (leftSet.find(e) != leftSet.end())return;
-  leftSet.insert(e);
-  //printf("insert in left %d \n", e->getNum());
-  for (int i=0;i<e->getNumEdges();i++){
-    MEdge ed = e->getEdge(i);
-    if (theCut.find(ed) == theCut.end()){
-      for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(ed);
-         it != e2e.upper_bound(ed) ; ++it){
-        if (it->second != e) recur_leftCut_ (it->second,e2e,theCut, leftSet);
-      }
-    }
-  }
-
-}
-
-// starting form a list of elements, returns
-// lists of lists that are all simply connected
-static void recur_connect (const MEdge &e,
-                           std::multimap<MEdge,MElement*,Less_Edge> &e2e,
-                           std::set<MElement*> &group,
-                           std::set<MEdge,Less_Edge> &touched)
-{
-  if (touched.find(e) != touched.end())return;
-  touched.insert(e);
-  for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(e);
-         it != e2e.upper_bound(e) ; ++it){
-    group.insert(it->second);
-    for (int i=0;i<it->second->getNumEdges();++i){
-      recur_connect (it->second->getEdge(i),e2e,group,touched);
-    }
-  }
-}
-
-static void connectedRegions (const std::vector<MElement*> &elements,
-                              std::vector<std::vector<MElement*> > &regions)
-{
-  std::multimap<MEdge,MElement*,Less_Edge> e2e;
-  for (unsigned int i = 0; i < elements.size(); ++i){
-    for (int j = 0; j < elements[i]->getNumEdges(); j++){
-      e2e.insert(std::make_pair(elements[i]->getEdge(j),elements[i]));
-    }
-  }
-  while (!e2e.empty()){
-    std::set<MElement*> group;
-    std::set<MEdge,Less_Edge> touched;
-    recur_connect (e2e.begin()->first,e2e,group,touched);
-    std::vector<MElement*> temp;
-    temp.insert(temp.begin(), group.begin(), group.end());
-    regions.push_back(temp);
-    for ( std::set<MEdge,Less_Edge>::iterator it = touched.begin() ; it != touched.end();++it)
-      e2e.erase(*it);
-  }
-}
-
-static void keepConnected(std::vector<MElement*> &goodSize, std::vector<MElement*> &tooSmall)
-{
-  std::vector<std::vector<MElement*> >  regGoodSize;
-  connectedRegions (goodSize,regGoodSize);
-  if (regGoodSize.size()  > 0){
-    int index=0;
-    int maxSize= regGoodSize[0].size();
-    for (unsigned int i=1;i< regGoodSize.size() ; i++){
-      int size = regGoodSize[i].size();
-      if(size > maxSize){
-        index = i;
-        maxSize = size;
-      }
-    }
-    goodSize.clear();
-    for (unsigned int i = 0; i < regGoodSize.size(); i++){
-      if ((int)i == index)
-        goodSize.insert(goodSize.begin(), regGoodSize[i].begin(),
-                        regGoodSize[i].end());
-      else
-        tooSmall.insert(tooSmall.begin(), regGoodSize[i].begin(),
-                        regGoodSize[i].end());
-    }
-  }
-}
-
-static void recur_cut_ (double R, double a1, double a2,
-                        multiscaleLaplaceLevel * root,
-                        std::vector<MElement *> &left,
-                        std::vector<MElement *> &right)
-{
-  SPoint2 PL (R*cos(a1),R*sin(a1));
-  SPoint2 PR (R*cos(a2),R*sin(a2));
-  std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > centers = root->cut;
-
-  double d = sqrt((PL.x()-PR.x())*(PL.x()-PR.x())+
-                  (PL.y()-PR.y())*(PL.y()-PR.y()));
-  SPoint2 farLeft (0.5*(PL.x()+PR.x()) - (PR.y()-PL.y())/d ,
-                   0.5*(PL.y()+PR.y()) + (PR.x()-PL.x())/d );
-
-  for (unsigned int i = 0; i < root->elements.size(); i++){
-    SPoint2 pp (0,0);
-    for (int j=0; j<root->elements[i]->getNumVertices(); j++){
-      pp += root->coordinates[root->elements[i]->getVertex(j)];
-    }
-    pp *= 1./(double)root->elements[i]->getNumVertices();
-    int nbIntersect = 0;
-    for (unsigned int j = 0; j < centers.size() - 1; j++){
-      double x[2];
-      nbIntersect += intersection_segments (centers[j].first,centers[j+1].first,pp,farLeft,x);
-    }
-    if (nbIntersect %2 != 0)
-      left.push_back(root->elements[i]);
-    else
-      right.push_back(root->elements[i]);
-  }
-
-  for (unsigned int i = 1; i < centers.size() - 1; i++){
-    multiscaleLaplaceLevel* m2 = centers[i].second;
-    if (m2){
-      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);
-    }
-  }
-}
-
-static void connected_left_right (std::vector<MElement *> &left,
-                                 std::vector<MElement *> &right)
-{
-  //connected left
-  keepConnected(left, right);
-
-  //assign partitions
-  for (unsigned int i= 0; i< left.size(); i++)
-    left[i]->setPartition(1);
-  for (unsigned int i= 0; i< right.size(); i++)
-    right[i]->setPartition(2);
-}
-
-static void printCut(std::map<MEdge,MVertex*,Less_Edge> &cutEdges,
-                     std::set<MEdge,Less_Edge> &theCut, std::set<MVertex*> cutVertices)
-{
-   printf("Writing points.pos \n");
-   std::map<MEdge,MVertex*,Less_Edge>::iterator ite = cutEdges.begin();
-   FILE *f1 = Fopen("points.pos","w");
-   if(f1){
-     fprintf(f1,"View\"\"{\n");
-     for ( ; ite != cutEdges.end();++ite){
-       fprintf(f1,"SP(%g,%g,%g){1.0};\n",ite->second->x(),ite->second->y(),ite->second->z());
-     }
-     std::set<MVertex*>::iterator itv = cutVertices.begin();
-     for ( ; itv != cutVertices.end();++itv){
-       fprintf(f1,"SP(%g,%g,%g){3.0};\n",(*itv)->x(),(*itv)->y(),(*itv)->z());
-     }
-     fprintf(f1,"};\n");
-     fclose(f1);
-   }
-
-   printf("Writing edges.pos \n");
-   std::set<MEdge,Less_Edge>::iterator itc = theCut.begin();
-   FILE *f2 = Fopen("edges.pos","w");
-   if(f2){
-     fprintf(f2,"View\"\"{\n");
-     for ( ; itc != theCut.end();++itc){
-       fprintf(f2,"SL(%g,%g,%g,%g,%g,%g){1.0,1.0};\n",itc->getVertex(0)->x(),
-               itc->getVertex(0)->y(),itc->getVertex(0)->z(),
-               itc->getVertex(1)->x(),itc->getVertex(1)->y(),itc->getVertex(1)->z());
-     }
-     fprintf(f2,"};\n");
-     fclose(f2);
-   }
-}
-
-static void printLevel(const char* fn,
-                       std::vector<MElement *> &elements,
-                       std::map<MVertex*,SPoint2> *coordinates,
-                       double version,
-		       double *dx = 0)
-{
-  if(!CTX::instance()->mesh.saveAll) return;
-
-  std::set<MVertex*> vs;
-  for (unsigned 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");
-  if(!fp){
-    Msg::Error("Could not open file '%s'", fn);
-    return;
-  }
-  fprintf(fp, "$MeshFormat\n");
-  fprintf(fp, "%g %d %d\n", version, binary ? 1 : 0, (int)sizeof(double));
-  fprintf(fp, "$EndMeshFormat\n");
-
-  fprintf(fp, "$Nodes\n%d\n", (int)vs.size());
-  std::set<MVertex*> :: iterator it = vs.begin();
-  int index = 1;
-  for (; it != vs.end() ; ++it){
-    (*it)->setIndex(index++);
-    SPoint2 p = (coordinates) ? (*coordinates)[*it] : SPoint2(0,0);
-    if (coordinates) {
-      if (dx)fprintf(fp, "%d %22.15E %22.15E 0\n", (*it)->getIndex(),
-                     dx[2]*(p.x()-dx[0]), dx[2]*(p.y()-dx[1]));
-      else   fprintf(fp, "%d %22.15E %22.15E 0\n", (*it)->getIndex(), p.x(), p.y());
-    }
-    else fprintf(fp, "%d %g %g %g\n", (*it)->getIndex(),(*it)->x(), (*it)->y(), (*it)->z());
-  }
-  fprintf(fp, "$EndNodes\n");
-
-  fprintf(fp, "$Elements\n%d\n", (int)elements.size());
-  for (unsigned int i = 0; i < elements.size(); i++){
-    elements[i]->writeMSH(fp, version);
-  }
-  fprintf(fp, "$EndElements\n");
-
-  fclose(fp);
-}
-
-static double localSize(MElement *e,  std::map<MVertex*,SPoint2> &solution)
-{
-  SBoundingBox3d local;
-  for(int j = 0; j<e->getNumVertices(); ++j){
-    SPoint2 p = solution[e->getVertex(j)];
-    local += SPoint3(p.x(),p.y(),0.0);
-  }
-  return local.max().distance(local.min());
-
-//   MVertex* v0 = e->getVertex(0);
-//   MVertex* v1 = e->getVertex(1);
-//   MVertex* v2 = e->getVertex(2);
-//   double p0[3] = {v0->x(), v0->y(), v0->z()};
-//   double p1[3] = {v1->x(), v1->y(), v1->z()};
-//   double p2[3] = {v2->x(), v2->y(), v2->z()};
-//   double a_3D = fabs(triangle_area(p0, p1, p2));
-//   SPoint2 s1 = solution[v0];
-//   SPoint2 s2 = solution[v1];
-//   SPoint2 s3 = solution[v2];
-//   double q0[3] = {s1.x(), s1.y(), 0.0};
-//   double q1[3] = {s2.x(), s2.y(), 0.0};
-//   double q2[3] = {s3.x(), s3.y(), 0.0};
-//   double a_2D = fabs(triangle_area(q0, q1, q2));
-
-//   return a_2D;  //a_2D / a_3D;
-}
-
-static void printLevel_onlysmall(const char* fn,
-				 std::vector<MElement *> &elements,
-				 std::map<MVertex*,SPoint2> *coordinates,
-				 double version,
-				 double tolerance)
-{
-  std::vector<MElement *> small;
-  double dx[3] = {0,0,0};
-  int COUNT = 0;
-  for (unsigned i=0;i<elements.size();i++){
-    double local_size = localSize(elements[i],*coordinates);
-    if (local_size < tolerance){
-      small.push_back(elements[i]);
-      for (int j=0;j<3;j++){
-	SPoint2 p = (*coordinates)[elements[i]->getVertex(j)];
-	dx[0] += p.x();
-	dx[1] += p.y();
-	COUNT++;
-      }
-    }
-  }
-  dx[0] /= COUNT;
-  dx[1] /= COUNT;
-  dx[2] = 1./tolerance;
-  printLevel(fn,small,coordinates,version,dx);
-}
-
-multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements,
-                                      std::map<MVertex*, SPoint3> &allCoordinates)
-{
-  //Find the boundary loops
-  //The loop with the largest equivalent radius is the Dirichlet boundary
-  std::vector<std::pair<MVertex*,double> > boundaryNodes;
-  ordering_dirichlet(elements,boundaryNodes);
-
-  //Assign Dirichlet BCs
-  // FIXME: this is never deleted
-  root = new multiscaleLaplaceLevel;
-  root->elements = elements;
-  for(unsigned int i = 0; i < boundaryNodes.size(); i++){
-     MVertex *v = boundaryNodes[i].first;
-     const double theta = 2 * M_PI * boundaryNodes[i].second;
-     root->coordinates[v] = SPoint2(cos(theta),sin(theta));
-  }
-
-  //Recursively parametrize
-  root->recur = 0;
-  root->region = 0;
-  root->scale = 1.0;
-  root->_name = "Root";
-
-  parametrize(*root);
-
-  //fill the coordinates
-  std::vector<double> iScale;
-  std::vector<SPoint2> iCenter;
-  fillCoordinates(*root, allCoordinates, iScale, iCenter);
-
-  //Compute centers for the cut
-  int nbElems = 0;
-  recur_compute_centers_ (1.0, M_PI, 0.0, root, nbElems);
-
-  //Split the mesh in left and right
-  //or Cut the mesh in left and right (of bamg)
-  if ( CTX::instance()->mesh.algo2d ==  ALGO_2D_BAMG){
-    printf("-------------> EXACT CUTTING \n");
-    cutElems(elements);
-  }
-  else {
-    splitElems(elements);
-  }
-
-}
-
-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(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 (unsigned int i=0;i<level.children.size();i++){
-    multiscaleLaplaceLevel* m = level.children[i];
-    fillCoordinates(*m, allCoordinates, iScale, iCenter);
-  }
-}
-
-void multiscaleLaplace::parametrize(multiscaleLaplaceLevel & level)
-{
-  //Compute all nodes for the level
-  std::set<MVertex*> allNodes;
-  for(unsigned int i = 0; i < level.elements.size(); ++i){
-    MElement *e = level.elements[i];
-    for(int j = 0; j<e->getNumVertices(); ++j){
-      allNodes.insert(e->getVertex(j));
-    }
-  }
-
-  //Parametrize level
-  std::map<MVertex*,SPoint2> solution;
-  parametrize_method(level, allNodes, solution);
-
-  //Compute the bbox of the parametric space
-  SBoundingBox3d bbox;
-  for(std::set<MVertex *>::iterator itv = allNodes.begin(); itv !=allNodes.end() ; ++itv){
-    MVertex *v = *itv;
-    SPoint2 p = solution[v];
-    bbox += SPoint3(p.x(),p.y(),0.0);
-  }
-  double global_size = bbox.max().distance(bbox.min());
-
-  //Check elements that are too small
-  std::vector<MElement*> tooSmall, goodSize;
-  for(unsigned int i = 0; i < level.elements.size(); ++i){
-    MElement *e = level.elements[i];
-    std::vector<SPoint2> localCoord;
-    double local_size = localSize(e,solution);
-    if (local_size < 1.e-6*global_size)
-      tooSmall.push_back(e);
-    else  goodSize.push_back(e);
-  }
-
-  //Only keep the connected elements vectors goodSize (the rest goes into tooSmall)
-  keepConnected(goodSize, tooSmall);
-
-  //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 (unsigned int i=0;i< regions_.size() ; i++){
-    bool really_small_elements = false;
-    for (unsigned 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) //1.e-7
-        really_small_elements = true;
-    }
-    if(really_small_elements ){
-      regions.push_back(regions_[i]);
-    }
-    else
-      goodSize.insert(goodSize.begin(), regions_[i].begin(), regions_[i].end() );
-  }
-
-  //check for convex small regions patches
-  for (unsigned int i = 0; i < regions.size(); i++){
-    std::vector<MElement*> &elemR = regions[i];
-    v2t_cont adj;
-    buildVertexToElement (elemR,adj);
-    for (std::vector<MElement*>::iterator it = elemR.begin(); it != elemR.end(); ++it){
-      int nbNeigh = 0;
-      MElement *e = *it;
-      v2t_cont::iterator it0 = adj.find(e->getVertex(0));
-      if(it0 != adj.end()) nbNeigh += it0->second.size();
-      v2t_cont::iterator it1 = adj.find(e->getVertex(1));
-      if(it1 != adj.end()) nbNeigh += it1->second.size();
-      v2t_cont::iterator it2 = adj.find(e->getVertex(2));
-      if(it2 != adj.end()) nbNeigh += it2->second.size();
-      std::vector<MElement*>::iterator itp;
-      if (nbNeigh < 12) {
-  	goodSize.push_back(e);
-  	itp = it;
-  	it++;
-  	elemR.erase(itp);
-      }
-    }
-    keepConnected(elemR, goodSize);
-  }
-  tooSmall.clear();
-  for (unsigned int i = 0; i < regions.size(); i++)
-    tooSmall.insert(tooSmall.begin(), regions[i].begin(), regions[i].end());
-
-  keepConnected(goodSize, tooSmall);
-  regions.clear();
-  connectedRegions (tooSmall,regions);
-
-  level.elements.clear();
-  level.elements = goodSize;
-
-  //Fill level.coordinates
-  std::set<MVertex*> goodSizev;
-  for(unsigned int i = 0; i < level.elements.size(); ++i){
-    MElement *e = level.elements[i];
-    for(int j = 0; j<e->getNumVertices(); ++j){
-      MVertex *v = e->getVertex(j);
-      goodSizev.insert(v);
-      level.coordinates[v] = solution[v];
-    }
-  }
-
-  //Save multiscale meshes
-   std::string name1(level._name+"real.msh");
-   std::string name2(level._name+"param.msh");
-   std::string name3(level._name+"param_small.msh");
-   printLevel (name1.c_str(),level.elements,0,2.2);
-   printLevel (name2.c_str(),level.elements,&level.coordinates,2.2);
-   printLevel_onlysmall (name3.c_str(),level.elements,&level.coordinates,2.2,1.e-15);
-
-  //For every small region compute a new parametrization
-  Msg::Info("Level (%d-%d): %d connected small regions",
-            level.recur, level.region, regions.size());
-  for (unsigned int i = 0; i < regions.size(); i++){
-    std::set<MVertex*> tooSmallv;
-    tooSmallv.clear();
-    for (unsigned int k=0; k<regions[i].size() ; k++){
-      MElement *e = regions[i][k];
-      for(int j = 0; j<e->getNumVertices(); ++j){
-        tooSmallv.insert(e->getVertex(j));
-      }
-    }
-
-    // FIXME: this is never deleted
-    multiscaleLaplaceLevel *nextLevel = new multiscaleLaplaceLevel;
-    nextLevel->elements = regions[i];
-    nextLevel->recur = level.recur+1;
-    nextLevel->region = i;
-    std::stringstream s1 ; s1 << nextLevel->recur;
-    std::stringstream s2 ; s2 << nextLevel->region;
-    nextLevel->_name = level._name+"-"+s1.str()+"-"+s2.str();
-    SBoundingBox3d smallB;
-    for(std::set<MVertex *>::iterator itv = tooSmallv.begin();
-        itv !=tooSmallv.end(); ++itv){
-      SPoint2 p = solution[*itv];
-      nextLevel->center += p;
-      smallB += SPoint3(p.x(),p.y(),0.0);
-    }
-    nextLevel->center *= (1./(double)tooSmallv.size());
-    nextLevel->scale = smallB.max().distance(smallB.min());
-
-    for(std::set<MVertex *>::iterator itv = tooSmallv.begin();
-        itv !=tooSmallv.end() ; ++itv){
-      MVertex *v = *itv;
-      if (goodSizev.find(v) != goodSizev.end()){
-        nextLevel->coordinates[v] =  (solution[v]-nextLevel->center) *
-          (1./nextLevel->scale);
-      }
-    }
-    // recursively continue if tooSmall is not empty
-    if (!tooSmallv.empty()){
-      Msg::Info("Level (%d-%d) Multiscale Laplace (reg[%d] =  %d too small)",
-                level.recur,level.region, i, tooSmallv.size());
-      level.children.push_back(nextLevel);
-      parametrize(*nextLevel);
-    }
-  }
-}
-
-void multiscaleLaplace::parametrize_method (multiscaleLaplaceLevel & level,
-                                            std::set<MVertex*> &allNodes,
-                                            std::map<MVertex*,SPoint2> &solution)
-{
-  linearSystem<double> *_lsys;
-#if defined(HAVE_PETSC)
-  _lsys =  new linearSystemPETSc<double>;
-#elif defined(HAVE_GMM)
-  linearSystemGmm<double> *_lsysb = new linearSystemGmm<double>;
-  _lsysb->setGmres(1);
-  _lsys = _lsysb;
-#else
-  _lsys = new linearSystemFull<double>;
-#endif
-
-  solution.clear();
-  simpleFunction<double> ONE(1.0);
-
-  for (int step =0 ; step<2 ; step++){
-
-    dofManager<double> myAssembler(_lsys);
-    for(std::map<MVertex*,SPoint2>::iterator it = level.coordinates.begin();
-        it != level.coordinates.end(); ++it){
-      MVertex *v = it->first;
-      myAssembler.fixVertex(v, 0, 1, it->second[step]);
-    }
-
-    // do the numbering
-    for(std::set<MVertex *>::iterator itv = allNodes.begin();
-        itv != allNodes.end(); ++itv){
-      MVertex *v = *itv;
-      myAssembler.numberVertex(v, 0, 1);
-    }
-
-    // assemble
-    femTerm<double> *mapping;
-    mapping = new convexCombinationTerm(0, 1, &ONE);
-
-    for(unsigned int i = 0; i < level.elements.size(); ++i){
-      MElement *e = level.elements[i];
-      SElement se(e);
-      mapping->addToMatrix(myAssembler, &se);
-    }
-
-    delete mapping;
-
-    // solve
-    if (myAssembler.sizeOfR() != 0) _lsys->systemSolve();
-
-    // get the values
-    for(std::set<MVertex *>::iterator itv = allNodes.begin();
-        itv != allNodes.end(); ++itv){
-      MVertex *v = *itv;
-      double value;
-      myAssembler.getDofValue(v, 0, 1, value);
-      if (step == 0)solution[v] = SPoint2(value,0);
-      else solution[v] = SPoint2(solution[v][0],value);
-    }
-    _lsys->clear();
-
-  }
-
-  delete _lsys;
-}
-
-void multiscaleLaplace::cutElems(std::vector<MElement *> &elements)
-{
-   std::map<MEdge,MVertex*,Less_Edge> cutEdges;
-   std::set<MEdge,Less_Edge> theCut;
-   std::set<MVertex*> cutVertices;
-   elements.clear();
-
-   recur_cut_edges_ (root, cutEdges,cutVertices);
-   recur_cut_elements_ (root,cutEdges,cutVertices,theCut, elements);
-   printCut(cutEdges, theCut, cutVertices);
-
-   std::multimap<MEdge,MElement*,Less_Edge> e2e;
-   for (unsigned int i = 0; i < elements.size(); ++i){
-     for (int j = 0; j < elements[i]->getNumEdges(); j++){
-       e2e.insert(std::make_pair(elements[i]->getEdge(j),elements[i]));
-     }
-   }
-   std::set<MElement*> leftS;
-   leftS.clear();
-   std::vector<MElement*> left,right;
-   recur_leftCut_ (elements[0], e2e, theCut, leftS);
-
-   for (unsigned int i = 0; i < elements.size(); i++){
-     MElement *e = elements[i];
-     if (leftS.find(e) != leftS.end()) left.push_back(e);
-     else right.push_back(e);
-   }
-
-   connected_left_right(left, right);
-   if (left.size() == 0 || right.size() == 0) {
-     Msg::Error("KO size left=%d, right=%d  not good (zero elems)",
-                (int) left.size(), (int) right.size() );
-     return;
-   }
-
-   elements.clear();
-   elements.insert(elements.end(),left.begin(),left.end());
-   elements.insert(elements.end(),right.begin(),right.end());
-
-   printLevel ("Rootcut-left.msh",left,0,2.2);
-   printLevel ("Rootcut-right.msh",right,0,2.2);
-   printLevel ("Rootcut-all.msh",elements, 0,2.2);
-}
-
-void multiscaleLaplace::splitElems(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);
-
-  printLevel ("Rootsplit-left.msh",left,0,2.2);
-  printLevel ("Rootsplit-right.msh",right,0,2.2);
-  printLevel ("Rootsplit-all.msh",elements, 0,2.2);
-
-  printLevel ("Rootsplit-left-param.msh",left,&root->coordinates,2.2);
-  // printLevel_onlysmall ("Rootsplit-left-param10.msh",left,&root->coordinates,2.2,1.e-10);
-  // printLevel_onlysmall ("Rootsplit-left-param12.msh",left,&root->coordinates,2.2,1.e-12);
-  // printLevel_onlysmall ("Rootsplit-left-param15.msh",left,&root->coordinates,2.2,1.e-15);
-
-  printLevel ("Rootsplit-right-param.msh",right,&root->coordinates,2.2);
-  // printLevel_onlysmall ("Rootsplit-right-param10.msh",right,&root->coordinates,2.2,1.e-10);
-  // printLevel_onlysmall ("Rootsplit-right-param12.msh",right,&root->coordinates,2.2,1.e-12);
-  // printLevel_onlysmall ("Rootsplit-right-param15.msh",right,&root->coordinates,2.2,1.e-15);
-
-  // printLevel_onlysmall ("Rootsplit-all-param12.msh",elements,&root->coordinates,2.2,1.e-12);
-  // printLevel_onlysmall ("Rootsplit-all-param15.msh",elements,&root->coordinates,2.2,1.e-15);
-
-  if ( elements.size() != left.size()+right.size()) {
-    Msg::Error("Cutting laplace wrong nb elements (%d) != left + right (%d)",
-               elements.size(), left.size()+right.size());
-    return;
-  }
-
-  elements.clear();
-  elements.insert(elements.end(),left.begin(),left.end());
-  elements.insert(elements.end(),right.begin(),right.end());
-}
diff --git a/Solver/multiscaleLaplace.h b/Solver/multiscaleLaplace.h
deleted file mode 100644
index b5411284fb98a7168387c44d0f2575d72ee8f853..0000000000000000000000000000000000000000
--- a/Solver/multiscaleLaplace.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Gmsh - Copyright (C) 1997-2017 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to the public mailing list <gmsh@onelab.info>.
-
-#ifndef _MULTISCALE_LAPLACE_H_
-#define _MULTISCALE_LAPLACE_H_
-
-#include <vector>
-#include <map>
-#include <set>
-#include "SPoint2.h"
-#include "SPoint3.h"
-#include "linearSystem.h"
-
-class MElement;
-class MVertex;
-
-struct multiscaleLaplaceLevel {
-  SPoint2 center;
-  double  scale;
-  double radius;
-  int recur,region;
-  std::vector<multiscaleLaplaceLevel*> children;
-  std::vector<MElement *> elements;
-  std::map<MVertex*,SPoint2> coordinates;
-  std::vector<std::pair<SPoint2,multiscaleLaplaceLevel*> > cut;
-  std::string _name;
-};
-
-class multiscaleLaplace{
-public:
-  multiscaleLaplace (std::vector<MElement *> &elements,
-                     std::map<MVertex*, SPoint3> &allCoordinates);
-  void cutElems   (std::vector<MElement *> &elements);
-  void splitElems (std::vector<MElement *> &elements);
- 
-  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,
-                           std::map<MVertex*,SPoint2> &solution);
-
-
-};
-#endif
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index 2378519e840ace89e832c4c59fbb6065ad6d4f8c..f645649b3bb3455828860c32ce8e6df91e2fa633 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -1963,16 +1963,6 @@ Creates a path made of lines. Wires are only available with the
 OpenCASCADE kernel. They are used to create @code{ThruSections} and
 extrusions along paths.
 
-@item Compound Line ( @var{expression} ) = @{ @var{expression-list} @};
-Creates a compound line from several elementary lines.  When meshed, a
-compound line will be reparametrized as a single line, whose mesh can
-thus cross internal boundaries. The @var{expression} inside the
-parentheses is the compound line's identification number; the
-@var{expression-list} on the right hand side contains the identification
-number of the elementary lines that should be reparametrized as a single
-line. See @code{Compound Surface} for additional information on compound
-entities.
-
 @item Physical Line ( @var{expression} | @var{char-expression} <, @var{expression}> ) <+|->= @{ @var{expression-list} @};
 Creates a physical line. The @var{expression} inside the parentheses is
 the physical line's identification number; the @var{expression-list} on
@@ -2043,19 +2033,6 @@ elementary surfaces should be oriented consistently (using negative
 identification numbers to specify reverse orientation). (Surface loops are
 used to create volumes: see @ref{Volumes}.)
 
-@item Compound Surface ( @var{expression} ) = @{ @var{expression-list} @} < Boundary @{ @{ @var{expression-list} @}, @{ @var{expression-list} @}, @{ @var{expression-list} @}, @{ @var{expression-list} @} @} > ;
-Creates a compound surface from several elementary surfaces.  When
-meshed, a compound surface will be reparametrized as a single surface,
-whose mesh can thus cross internal boundaries. Compound surfaces are
-mostly useful for remeshing discrete models; see ``J.-F. Remacle,
-C. Geuzaine, G. Compere and E. Marchandise, @emph{High Quality Surface
-Remeshing Using Harmonic Maps}, International Journal for Numerical
-Methods in Engineering, 2009'' for details as well as the wiki for more
-examples.  The @var{expression} inside the parentheses is the compound
-surface's identification number; the mandatory @var{expression-list} on
-the right hand side contains the identification number of the elementary
-surfaces that should be reparametrized as a single surface.
-
 @item Physical Surface ( @var{expression} | @var{char-expression} <, @var{expression}> ) <+|->= @{ @var{expression-list} @};
 Creates a physical surface. The @var{expression} inside the parentheses
 is the physical surface's identification number; the
@@ -2143,16 +2120,6 @@ the OpenCASCADE kernel.
 @c @item ThickSolid ( @var{expression} ) = @{ @var{expression-list} @};
 @c todo: @code{ThickSolid} is only available with the OpenCASCADE kernel.
 
-@item Compound Volume ( @var{expression} ) = @{ @var{expression-list} @};
-Creates a compound volume from several elementary volumes.  When meshed,
-a compound volume will be reparametrized as a single volume, whose mesh
-can thus cross internal boundaries. The @var{expression} inside the
-parentheses is the compound volume's identification number; the
-@var{expression-list} on the right hand side contains the identification
-number of the elementary volumes that should be reparametrized as a
-single volume. See @code{Compound Surface} for additional information on
-compound entities.
-
 @item Physical Volume ( @var{expression} | @var{char-expression} <, @var{expression}> ) <+|->= @{ @var{expression-list} @};
 Creates a physical volume. The @var{expression} inside the parentheses
 is the physical volume's identification number; the