diff --git a/Fltk/Makefile b/Fltk/Makefile
index 92efaa7c77ca69dbfdbf5c5a4eac88a88e070a54..12b8c8d53083dfd3df1c65bba19218f8d940b2a7 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -336,8 +336,9 @@ classificationEditor${OBJEXT}: classificationEditor.cpp GUI.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
   ../Post/ColorTable.h paletteWindow.h ../Numeric/Numeric.h \
   ../Numeric/GmshMatrix.h Draw.h ../Common/Options.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
-  ../Mesh/meshGFaceDelaunayInsertion.h ../Mesh/meshGFaceOptimize.h \
+  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h ../Geo/MLine.h \
+  ../Geo/MElement.h ../Mesh/meshGFaceDelaunayInsertion.h \
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Mesh/meshGFaceOptimize.h \
   ../Mesh/meshGFaceDelaunayInsertion.h ../Geo/discreteEdge.h \
   ../Geo/GModel.h ../Geo/GEdge.h ../Geo/discreteFace.h ../Geo/GModel.h \
   ../Geo/GFace.h
diff --git a/Fltk/classificationEditor.cpp b/Fltk/classificationEditor.cpp
index 29f220b6eb5e428c3cff71f781109c51bad80d2b..baaeea2795508e9d3b7550551c07da69265132ef 100644
--- a/Fltk/classificationEditor.cpp
+++ b/Fltk/classificationEditor.cpp
@@ -13,6 +13,7 @@
 #include "Options.h"
 #include "Context.h"
 #include "GmshMessage.h"
+#include "MLine.h"
 #include "meshGFaceDelaunayInsertion.h"
 #include "meshGFaceOptimize.h"
 #include "discreteEdge.h"
diff --git a/Fltk/visibilityWindow.cpp b/Fltk/visibilityWindow.cpp
index da78a6c18873ddcfeadfda246fe54d776a059a61..3237de1c9c7843b8046dc66673dba33672914f58 100644
--- a/Fltk/visibilityWindow.cpp
+++ b/Fltk/visibilityWindow.cpp
@@ -752,53 +752,24 @@ static void _set_visibility_by_number(int what, int num, char val, bool recursiv
   bool all = (num < 0) ? true : false;
 
   GModel *m = GModel::current();
+  std::vector<GEntity*> entities;
+  m->getEntities(entities);
 
   switch(what){
   case 0: // nodes
-    for(GModel::viter it = m->firstVertex(); it != m->lastVertex(); it++)
-      for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++)
-        if(all || (*it)->mesh_vertices[i]->getNum() == num) 
-          (*it)->mesh_vertices[i]->setVisibility(val);
-    for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++)
-      for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++)
-        if(all || (*it)->mesh_vertices[i]->getNum() == num) 
-          (*it)->mesh_vertices[i]->setVisibility(val);
-    for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++)
-      for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++)
-        if(all || (*it)->mesh_vertices[i]->getNum() == num) 
-          (*it)->mesh_vertices[i]->setVisibility(val);
-    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++)
-      for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++)
-        if(all || (*it)->mesh_vertices[i]->getNum() == num) 
-          (*it)->mesh_vertices[i]->setVisibility(val);
+    for(unsigned int i = 0; i < entities.size(); i++){
+      for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){
+        MVertex *v = entities[i]->mesh_vertices[j];
+        if(all || v->getNum() == num) v->setVisibility(val);
+      }
+    }
     break;
   case 1: // elements
-    for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++){
-      for(unsigned int i = 0; i < (*it)->lines.size(); i++)
-        if(all || (*it)->lines[i]->getNum() == num) 
-          (*it)->lines[i]->setVisibility(val);
-    }
-    for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
-      for(unsigned int i = 0; i < (*it)->triangles.size(); i++)
-        if(all || (*it)->triangles[i]->getNum() == num) 
-          (*it)->triangles[i]->setVisibility(val);
-      for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++)
-        if(all || (*it)->quadrangles[i]->getNum() == num) 
-          (*it)->quadrangles[i]->setVisibility(val);
-    }
-    for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
-      for(unsigned int i = 0; i < (*it)->tetrahedra.size(); i++)
-        if(all || (*it)->tetrahedra[i]->getNum() == num) 
-          (*it)->tetrahedra[i]->setVisibility(val);
-      for(unsigned int i = 0; i < (*it)->hexahedra.size(); i++)
-        if(all || (*it)->hexahedra[i]->getNum() == num) 
-          (*it)->hexahedra[i]->setVisibility(val);
-      for(unsigned int i = 0; i < (*it)->prisms.size(); i++)
-        if(all || (*it)->prisms[i]->getNum() == num) 
-          (*it)->prisms[i]->setVisibility(val);
-      for(unsigned int i = 0; i < (*it)->pyramids.size(); i++)
-        if(all || (*it)->pyramids[i]->getNum() == num) 
-          (*it)->pyramids[i]->setVisibility(val);
+    for(unsigned int i = 0; i < entities.size(); i++){
+      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
+        MElement *e = entities[i]->getMeshElement(j);
+        if(all || e->getNum() == num) e->setVisibility(val);
+      }
     }
     break;
   case 2: // point
@@ -820,22 +791,26 @@ static void _set_visibility_by_number(int what, int num, char val, bool recursiv
   case 6: // physical point
     for(GModel::viter it = m->firstVertex(); it != m->lastVertex(); it++)
       for(unsigned int i = 0; i < (*it)->physicals.size(); i++)
-        if (all || std::abs((*it)->physicals[i]) == num) (*it)->setVisibility(val, recursive);
+        if (all || std::abs((*it)->physicals[i]) == num)
+          (*it)->setVisibility(val, recursive);
     break;
   case 7: // physical line
     for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++)
       for(unsigned int i = 0; i < (*it)->physicals.size(); i++)
-        if (all || std::abs((*it)->physicals[i]) == num) (*it)->setVisibility(val, recursive);
+        if (all || std::abs((*it)->physicals[i]) == num) 
+          (*it)->setVisibility(val, recursive);
     break;
   case 8: // physical surface
     for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++)
       for(unsigned int i = 0; i < (*it)->physicals.size(); i++)
-        if (all || std::abs((*it)->physicals[i]) == num) (*it)->setVisibility(val, recursive);
+        if (all || std::abs((*it)->physicals[i]) == num) 
+          (*it)->setVisibility(val, recursive);
     break;
   case 9: // physical volume
     for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++)
       for(unsigned int i = 0; i < (*it)->physicals.size(); i++)
-        if (all || std::abs((*it)->physicals[i]) == num) (*it)->setVisibility(val, recursive);
+        if (all || std::abs((*it)->physicals[i]) == num) 
+          (*it)->setVisibility(val, recursive);
     break;
   }
 }
diff --git a/Geo/GEdge.cpp b/Geo/GEdge.cpp
index 8c37aa8f9d6706cdc1bf5b0d3545415e94633705..2d9c0c60250e5f6eea0b3c7e5060f3617b61b590 100644
--- a/Geo/GEdge.cpp
+++ b/Geo/GEdge.cpp
@@ -12,7 +12,7 @@
 #include "GModel.h"
 #include "GEdge.h"
 #include "GFace.h"
-#include "MElement.h"
+#include "MLine.h"
 #include "Context.h"
 
 #if !defined(HAVE_GMSH_EMBEDDED)
diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp
index 0bb307b78ae93ac55a3f445177bf9cd9eb969464..2d9772dd049f5ab376ad579751768c35eef41560 100644
--- a/Geo/GFace.cpp
+++ b/Geo/GFace.cpp
@@ -9,7 +9,8 @@
 #include "GModel.h"
 #include "GFace.h"
 #include "GEdge.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
 #include "VertexArray.h"
 #include "GmshMatrix.h"
 #include "Numeric.h"
diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp
index 5869bd998d2eba4e9857ca140c4bf892d64dc601..1a0542bb1f59541aec2d3ec514136a1f7d89515b 100644
--- a/Geo/GFaceCompound.cpp
+++ b/Geo/GFaceCompound.cpp
@@ -5,10 +5,12 @@
 
 #include "GmshConfig.h"
 #include "GFaceCompound.h"
-#include "gmshAssembler.h"
-#include "gmshLaplace.h"
+#include "MLine.h"
+#include "MTriangle.h"
 #include "Numeric.h"
 #include "Octree.h"
+#include "gmshAssembler.h"
+#include "gmshLaplace.h"
 #include "gmshLinearSystemGmm.h"
 #include "gmshLinearSystemFull.h"
 
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index ec2349c55feb0e4572d051c9893ab8a745a9e720..c7039168d25cd170b5cdeae6b539c54d57070a68 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -7,7 +7,14 @@
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "GModel.h"
-#include "MElement.h"
+#include "MPoint.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "discreteRegion.h"
 #include "discreteFace.h"
 #include "discreteEdge.h"
diff --git a/Geo/GModelIO_Mesh.cpp b/Geo/GModelIO_Mesh.cpp
index be2f54ed72042ca4e3c6d48480e3fa88adc35508..457a24b22fd3efa22c232d03270dd1ff0a23050e 100644
--- a/Geo/GModelIO_Mesh.cpp
+++ b/Geo/GModelIO_Mesh.cpp
@@ -9,7 +9,14 @@
 #include <string>
 #include "GModel.h"
 #include "GmshDefines.h"
-#include "MElement.h"
+#include "MPoint.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "SBoundingBox3d.h"
 #include "discreteRegion.h"
 #include "discreteFace.h"
diff --git a/Geo/GRegion.cpp b/Geo/GRegion.cpp
index dcb195040617b5e97bffd91763db393ae9d2c910..bbc2bf533ef140806f2bf8e7b35d75456553a0df 100644
--- a/Geo/GRegion.cpp
+++ b/Geo/GRegion.cpp
@@ -7,7 +7,10 @@
 #include "GModel.h"
 #include "GRegion.h"
 #include "GFace.h"
-#include "MElement.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "GmshMessage.h"
 
 GRegion::GRegion(GModel *model, int tag) : GEntity (model, tag)
diff --git a/Geo/GVertex.cpp b/Geo/GVertex.cpp
index 821a95404fff0befc3765d7c4473ed3f56c4f446..3bf0d3fa2944045360a06e2f7caf27053b10afef 100644
--- a/Geo/GVertex.cpp
+++ b/Geo/GVertex.cpp
@@ -7,7 +7,7 @@
 #include <algorithm>
 #include "GVertex.h"
 #include "GFace.h"
-#include "MElement.h"
+#include "MPoint.h"
 #include "GmshMessage.h"
 
 GVertex::GVertex(GModel *m, int tag, double ms) : GEntity(m, tag), meshSize(ms) 
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index d1c673727979984b3ecab2feeed9025c79ec924e..d5689b65d9ecec298200b496d92241e7973159e9 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -8,6 +8,14 @@
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "MElement.h"
+#include "MPoint.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "GEntity.h"
 #include "GFace.h"
 #include "StringUtils.h"
@@ -16,11 +24,7 @@
 #if defined(HAVE_GMSH_EMBEDDED)
 #include "GmshEmbedded.h"
 #else
-#include "GaussLegendre1D.h"
 #include "Context.h"
-#include "qualityMeasures.h"
-#include "meshGFaceDelaunayInsertion.h"
-#include "meshGRegionDelaunayInsertion.h"
 #endif
 
 #define SQU(a)      ((a)*(a))
@@ -720,533 +724,3 @@ MElement *MElementFactory::create(int type, std::vector<MVertex*> &v,
   default:         return 0;
   }
 }
-
-const gmshFunctionSpace* MLine::getFunctionSpace(int o) const
-{
-  int order = (o == -1) ? getPolynomialOrder() : o;
-  
-  switch (order) {
-  case 1: return &gmshFunctionSpaces::find(MSH_LIN_2);
-  case 2: return &gmshFunctionSpaces::find(MSH_LIN_3);
-  case 3: return &gmshFunctionSpaces::find(MSH_LIN_4);
-  case 4: return &gmshFunctionSpaces::find(MSH_LIN_5);
-  case 5: return &gmshFunctionSpaces::find(MSH_LIN_6);
-  default: Msg::Error("Order %d line function space not implemented", order);
-  }
-  return 0;
-}
-
-void MLine::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
-{
-#if !defined(HAVE_GMSH_EMBEDDED)
-  static IntPt GQL[100]; 
-  double *t, *w;
-  int nbP = pOrder / 2 + 1;
-  gmshGaussLegendre1D(nbP, &t, &w);
-  for (int i = 0; i < nbP; i++){
-    GQL[i].pt[0] = t[i];
-    GQL[i].pt[1] = 0;
-    GQL[i].pt[2] = 0;
-    GQL[i].weight = w[i];
-  }
-  *npts = nbP;
-  *pts = GQL;
-#endif
-}
-
-SPoint3 MTriangle::circumcenter()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return SPoint3();
-#else
-  double p1[3] = {_v[0]->x(), _v[0]->y(), _v[0]->z()};
-  double p2[3] = {_v[1]->x(), _v[1]->y(), _v[1]->z()};
-  double p3[3] = {_v[2]->x(), _v[2]->y(), _v[2]->z()};
-  double res[3];
-  circumCenterXYZ(p1, p2, p3, res);
-  return SPoint3(res[0], res[1], res[2]);
-#endif
-}
-
-double MTriangle::distoShapeMeasure()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return 1.;
-#else
-  return qmDistorsionOfMapping(this);
-#endif
-}
-
-double MTriangle::gammaShapeMeasure()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return 0.;
-#else
-  return qmTriangle(this, QMTRI_RHO);
-#endif
-}
-
-const gmshFunctionSpace* MTriangle::getFunctionSpace(int o) const
-{
-  int order = (o == -1) ? getPolynomialOrder() : o;
-
-  int nf = getNumFaceVertices();  
-
-  if ((nf == 0) && (o == -1)) {
-    switch (order) {
-    case 1: return &gmshFunctionSpaces::find(MSH_TRI_3);
-    case 2: return &gmshFunctionSpaces::find(MSH_TRI_6);
-    case 3: return &gmshFunctionSpaces::find(MSH_TRI_9);
-    case 4: return &gmshFunctionSpaces::find(MSH_TRI_12);
-    case 5: return &gmshFunctionSpaces::find(MSH_TRI_15I);
-    default: Msg::Error("Order %d triangle function space not implemented", order);
-    }
-  }
-  else { 
-    switch (order) {
-    case 1: return &gmshFunctionSpaces::find(MSH_TRI_3);
-    case 2: return &gmshFunctionSpaces::find(MSH_TRI_6);
-    case 3: return &gmshFunctionSpaces::find(MSH_TRI_10);
-    case 4: return &gmshFunctionSpaces::find(MSH_TRI_15);
-    case 5: return &gmshFunctionSpaces::find(MSH_TRI_21);
-    default: Msg::Error("Order %d triangle function space not implemented", order);
-    }
-  }
-  return 0;
-}
-
-int MTriangleN::getNumEdgesRep(){ return 3 * CTX::instance()->mesh.numSubEdges; }
-int MTriangle6::getNumEdgesRep(){ return 3 * CTX::instance()->mesh.numSubEdges; }
-
-static void _myGetEdgeRep(MTriangle *t, int num, double *x, double *y, double *z,
-                          SVector3 *n, int numSubEdges)
-{
-  n[0] = n[1] = n[2] = t->getFace(0).normal();
-
-  if (num < numSubEdges){
-    SPoint3 pnt1, pnt2;
-    t->pnt((double)num / numSubEdges, 0., 0.,pnt1);
-    t->pnt((double)(num + 1) / numSubEdges, 0., 0, pnt2);
-    x[0] = pnt1.x(); x[1] = pnt2.x();
-    y[0] = pnt1.y(); y[1] = pnt2.y();
-    z[0] = pnt1.z(); z[1] = pnt2.z();
-    return;
-  }  
-  if (num < 2 * numSubEdges){
-    SPoint3 pnt1, pnt2;
-    num -= numSubEdges;
-    t->pnt(1. - (double)num / numSubEdges, (double)num / numSubEdges, 0, pnt1);
-    t->pnt(1. - (double)(num + 1) / numSubEdges, (double)(num + 1) / numSubEdges, 0, pnt2);
-    x[0] = pnt1.x(); x[1] = pnt2.x();
-    y[0] = pnt1.y(); y[1] = pnt2.y();
-    z[0] = pnt1.z(); z[1] = pnt2.z();
-    return ;
-  }  
-  {
-    SPoint3 pnt1, pnt2;
-    num -= 2 * numSubEdges;
-    t->pnt(0, (double)num / numSubEdges, 0,pnt1);
-    t->pnt(0, (double)(num + 1) / numSubEdges, 0,pnt2);
-    x[0] = pnt1.x(); x[1] = pnt2.x();
-    y[0] = pnt1.y(); y[1] = pnt2.y();
-    z[0] = pnt1.z(); z[1] = pnt2.z();
-  }
-}
-
-void MTriangleN::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-void MTriangle6::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-int MTriangle6::getNumFacesRep(){ return SQU(CTX::instance()->mesh.numSubEdges); }
-int MTriangleN::getNumFacesRep(){ return SQU(CTX::instance()->mesh.numSubEdges); }
-
-static void _myGetFaceRep(MTriangle *t, int num, double *x, double *y, double *z,
-                          SVector3 *n, int numSubEdges)
-{
-
-  // on the first layer, we have (numSubEdges-1) * 2 + 1 triangles
-  // on the second layer, we have (numSubEdges-2) * 2 + 1 triangles
-  // on the ith layer, we have (numSubEdges-1-i) * 2 + 1 triangles
-  int ix = 0, iy = 0;
-  int nbt = 0;
-  for (int i = 0; i < numSubEdges; i++){
-    int nbl = (numSubEdges - i - 1) * 2 + 1;
-    nbt += nbl;
-    if (nbt > num){
-      iy = i;
-      ix = nbl - (nbt - num);
-      break;
-    }
-  }
-
-  const double d = 1. / numSubEdges;
-
-  SPoint3 pnt1, pnt2, pnt3;
-  double J1[3][3], J2[3][3], J3[3][3];
-  if (ix % 2 == 0){
-    t->pnt(ix / 2 * d, iy * d, 0, pnt1);
-    t->pnt((ix / 2 + 1) * d, iy * d, 0, pnt2);
-    t->pnt(ix / 2 * d, (iy + 1) * d, 0, pnt3);
-    t->getJacobian(ix / 2 * d, iy * d, 0, J1);
-    t->getJacobian((ix / 2 + 1) * d, iy * d, 0, J2);
-    t->getJacobian(ix / 2 * d, (iy + 1) * d, 0, J3);
-  }
-  else{
-    t->pnt((ix / 2 + 1) * d, iy * d, 0, pnt1);
-    t->pnt((ix / 2 + 1) * d, (iy + 1) * d, 0, pnt2);
-    t->pnt(ix / 2 * d, (iy + 1) * d, 0, pnt3);
-    t->getJacobian((ix / 2 + 1) * d, iy * d, 0, J1);
-    t->getJacobian((ix / 2 + 1) * d, (iy + 1) * d, 0, J2);
-    t->getJacobian(ix / 2 * d, (iy + 1) * d, 0, J3);
-  }
-  {
-    SVector3 d1(J1[0][0], J1[0][1], J1[0][2]);
-    SVector3 d2(J1[1][0], J1[1][1], J1[1][2]);
-    n[0] = crossprod(d1, d2);
-    n[0].normalize();
-  }
-  {
-    SVector3 d1(J2[0][0], J2[0][1], J2[0][2]);
-    SVector3 d2(J2[1][0], J2[1][1], J2[1][2]);
-    n[1] = crossprod(d1, d2);
-    n[1].normalize();
-  }
-  {
-    SVector3 d1(J3[0][0], J3[0][1], J3[0][2]);
-    SVector3 d2(J3[1][0], J3[1][1], J3[1][2]);
-    n[2] = crossprod(d1, d2);
-    n[2].normalize();
-  }
-
-  x[0] = pnt1.x(); x[1] = pnt2.x(); x[2] = pnt3.x();
-  y[0] = pnt1.y(); y[1] = pnt2.y(); y[2] = pnt3.y();
-  z[0] = pnt1.z(); z[1] = pnt2.z(); z[2] = pnt3.z();
-}
-
-void MTriangleN::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-void MTriangle6::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-void MTriangle::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
-{
-#if !defined(HAVE_GMSH_EMBEDDED)
-  *npts = getNGQTPts(pOrder);
-  *pts = getGQTPts(pOrder);
-#endif
-}
-
-void MQuadrangle::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
-{
-#if !defined(HAVE_GMSH_EMBEDDED)
-  *npts = getNGQQPts(pOrder);
-  *pts = getGQQPts(pOrder);
-#endif
-}
-
-SPoint3 MTetrahedron::circumcenter()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return SPoint3();
-#else
-  MTet4 t(this,0);
-  double res[3];
-  t.circumcenter(res);
-  return SPoint3(res[0],res[1],res[2]);
-#endif
-}
-
-double MTetrahedron::distoShapeMeasure()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return 1.;
-#else
-  return qmDistorsionOfMapping(this);
-#endif
-}
-
-double MTetrahedronN::distoShapeMeasure()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return 1.;
-#else
-  // if (_disto < -1.e21)
-  _disto = qmDistorsionOfMapping(this);
-  return _disto;
-#endif
-}
-
-double MTetrahedron::gammaShapeMeasure()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return 0.;
-#else
-  double vol;
-  return qmTet(this, QMTET_2, &vol);
-#endif
-}
-
-double MTetrahedron::etaShapeMeasure()
-{
-#if defined(HAVE_GMSH_EMBEDDED)
-  return 0.;
-#else
-  double vol;
-  return qmTet(this, QMTET_3, &vol);
-#endif
-}
-
-double MTetrahedron::getVolume()
-{
-  double mat[3][3];
-  getMat(mat);
-  return det3x3(mat) / 6.;
-}
-
-void MTetrahedron::xyz2uvw(double xyz[3], double uvw[3])
-{
-  double mat[3][3], b[3], det;
-  getMat(mat);
-  b[0] = xyz[0] - getVertex(0)->x();
-  b[1] = xyz[1] - getVertex(0)->y();
-  b[2] = xyz[2] - getVertex(0)->z();
-  sys3x3(mat, b, uvw, &det);
-}
-
-const gmshFunctionSpace* MTetrahedron::getFunctionSpace(int o) const
-{
-  int order = (o == -1) ? getPolynomialOrder() : o;
-
-  int nv = getNumVolumeVertices();
-  
-  if ((nv == 0) && (o == -1)) {
-    switch (order) {
-    case 1: return &gmshFunctionSpaces::find(MSH_TET_4);
-    case 2: return &gmshFunctionSpaces::find(MSH_TET_10);
-    case 3: return &gmshFunctionSpaces::find(MSH_TET_20);
-    case 4: return &gmshFunctionSpaces::find(MSH_TET_34);
-    case 5: return &gmshFunctionSpaces::find(MSH_TET_52);
-    default: Msg::Error("Order %d tetrahedron function space not implemented", order);
-    }
-  }
-  else { 
-    switch (order) {
-    case 1: return &gmshFunctionSpaces::find(MSH_TET_4);
-    case 2: return &gmshFunctionSpaces::find(MSH_TET_10);
-    case 3: return &gmshFunctionSpaces::find(MSH_TET_20);
-    case 4: return &gmshFunctionSpaces::find(MSH_TET_35);
-    case 5: return &gmshFunctionSpaces::find(MSH_TET_56);
-    default: Msg::Error("Order %d tetrahedron function space not implemented", order);
-    }
-  }
-  return 0;
-}
-
-int MTetrahedron10::getNumEdgesRep(){ return 6 * CTX::instance()->mesh.numSubEdges; }
-int MTetrahedronN::getNumEdgesRep(){ return 6 * CTX::instance()->mesh.numSubEdges; }
-
-static void _myGetEdgeRep(MTetrahedron *tet, int num, double *x, double *y, double *z,
-                          SVector3 *n, int numSubEdges)
-{
-  static double pp[4][3] = {{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
-  static int ed [6][2] = {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}};
-  int iEdge = num / numSubEdges;
-  int iSubEdge = num % numSubEdges;  
-
-  int iVertex1 = ed [iEdge][0];
-  int iVertex2 = ed [iEdge][1];
-  double t1 = (double) iSubEdge / (double) numSubEdges;
-  double u1 = pp[iVertex1][0] * (1.-t1) + pp[iVertex2][0] * t1;
-  double v1 = pp[iVertex1][1] * (1.-t1) + pp[iVertex2][1] * t1;
-  double w1 = pp[iVertex1][2] * (1.-t1) + pp[iVertex2][2] * t1;
-
-  double t2 = (double) (iSubEdge+1) / (double) numSubEdges;
-  double u2 = pp[iVertex1][0] * (1.-t2) + pp[iVertex2][0] * t2;
-  double v2 = pp[iVertex1][1] * (1.-t2) + pp[iVertex2][1] * t2;
-  double w2 = pp[iVertex1][2] * (1.-t2) + pp[iVertex2][2] * t2;
-
-  SPoint3 pnt1, pnt2;
-  tet->pnt(u1,v1,w1,pnt1);
-  tet->pnt(u2,v2,w2,pnt2);
-  x[0] = pnt1.x(); x[1] = pnt2.x(); 
-  y[0] = pnt1.y(); y[1] = pnt2.y();
-  z[0] = pnt1.z(); z[1] = pnt2.z();
-
-  // not great, but better than nothing
-  static const int f[6] = {0, 0, 0, 1, 2, 3};
-  n[0] = n[1] = tet->getFace(f[iEdge]).normal();
-}
-
-void MTetrahedron10::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-void MTetrahedronN::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-int MTetrahedronN::getNumFacesRep(){ return 4 * SQU(CTX::instance()->mesh.numSubEdges); }
-int MTetrahedron10::getNumFacesRep(){ return 4 * SQU(CTX::instance()->mesh.numSubEdges); }
-
-static void _myGetFaceRep(MTetrahedron *tet, int num, double *x, double *y, double *z, 
-                          SVector3 *n, int numSubEdges)
-{
-  static double pp[4][3] = {{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
-  static int fak [4][3] = {{0,1,2},{0,1,3},{0,2,3},{1,2,3}};
-  int iFace    = num / (numSubEdges * numSubEdges);
-  int iSubFace = num % (numSubEdges * numSubEdges);  
-  
-  int iVertex1 = fak[iFace][0];
-  int iVertex2 = fak[iFace][1];
-  int iVertex3 = fak[iFace][2];
-
-  /*
-    0
-    0 1
-    0 1 2
-    0 1 2 3
-    0 1 2 3 4
-    0 1 2 3 4 5
-  */
-
-  // on the first layer, we have (numSubEdges-1) * 2 + 1 triangles
-  // on the second layer, we have (numSubEdges-2) * 2 + 1 triangles
-  // on the ith layer, we have (numSubEdges-1-i) * 2 + 1 triangles
-  int ix = 0, iy = 0;
-  int nbt = 0;
-  for (int i = 0; i < numSubEdges; i++){
-    int nbl = (numSubEdges - i - 1) * 2 + 1;
-    nbt += nbl;
-    if (nbt > iSubFace){
-      iy = i;
-      ix = nbl - (nbt - iSubFace);
-      break;
-    }
-  }
-
-  const double d = 1. / numSubEdges;
-
-  SPoint3 pnt1, pnt2, pnt3;
-  double J1[2][3], J2[2][3], J3[2][3];
-  double u1,v1,u2,v2,u3,v3;
-  if (ix % 2 == 0){
-    u1 = ix / 2 * d; v1= iy*d;
-    u2 = (ix / 2 + 1) * d ; v2 =  iy * d;
-    u3 = ix / 2 * d ; v3 =  (iy+1) * d;
-  }
-  else{
-    u1 = (ix / 2 + 1) * d; v1= iy * d;
-    u2 = (ix / 2 + 1) * d; v2= (iy + 1) * d;
-    u3 = ix / 2 * d ; v3 =  (iy + 1) * d;
-  }
-
-  double U1 = pp[iVertex1][0] * (1.-u1-v1) + pp[iVertex2][0] * u1 + pp[iVertex3][0] * v1;
-  double U2 = pp[iVertex1][0] * (1.-u2-v2) + pp[iVertex2][0] * u2 + pp[iVertex3][0] * v2;
-  double U3 = pp[iVertex1][0] * (1.-u3-v3) + pp[iVertex2][0] * u3 + pp[iVertex3][0] * v3;
-
-  double V1 = pp[iVertex1][1] * (1.-u1-v1) + pp[iVertex2][1] * u1 + pp[iVertex3][1] * v1;
-  double V2 = pp[iVertex1][1] * (1.-u2-v2) + pp[iVertex2][1] * u2 + pp[iVertex3][1] * v2;
-  double V3 = pp[iVertex1][1] * (1.-u3-v3) + pp[iVertex2][1] * u3 + pp[iVertex3][1] * v3;
-
-  double W1 = pp[iVertex1][2] * (1.-u1-v1) + pp[iVertex2][2] * u1 + pp[iVertex3][2] * v1;
-  double W2 = pp[iVertex1][2] * (1.-u2-v2) + pp[iVertex2][2] * u2 + pp[iVertex3][2] * v2;
-  double W3 = pp[iVertex1][2] * (1.-u3-v3) + pp[iVertex2][2] * u3 + pp[iVertex3][2] * v3;
-
-  tet->pnt(U1,V1,W1,pnt1);
-  tet->pnt(U2,V2,W2,pnt2);
-  tet->pnt(U3,V3,W3,pnt3);
-
-  x[0] = pnt1.x(); x[1] = pnt2.x(); x[2] = pnt3.x();
-  y[0] = pnt1.y(); y[1] = pnt2.y(); y[2] = pnt3.y();
-  z[0] = pnt1.z(); z[1] = pnt2.z(); z[2] = pnt3.z();
-
-  SVector3 d1(x[1]-x[0],y[1]-y[0],z[1]-z[0]);
-  SVector3 d2(x[2]-x[0],y[2]-y[0],z[2]-z[0]);
-  n[0] = crossprod(d1, d2);
-  n[0].normalize();
-  n[1] = n[0];
-  n[2] = n[0];
-}
-
-void MTetrahedronN::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-void MTetrahedron10::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-{
-  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
-}
-
-void MTetrahedron::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
-{
-#if !defined(HAVE_GMSH_EMBEDDED)
-  *npts = getNGQTetPts(pOrder);
-  *pts = getGQTetPts(pOrder);
-#endif
-}
-
-int MHexahedron::getVolumeSign()
-{ 
-  double mat[3][3];
-  mat[0][0] = _v[1]->x() - _v[0]->x();
-  mat[0][1] = _v[3]->x() - _v[0]->x();
-  mat[0][2] = _v[4]->x() - _v[0]->x();
-  mat[1][0] = _v[1]->y() - _v[0]->y();
-  mat[1][1] = _v[3]->y() - _v[0]->y();
-  mat[1][2] = _v[4]->y() - _v[0]->y();
-  mat[2][0] = _v[1]->z() - _v[0]->z();
-  mat[2][1] = _v[3]->z() - _v[0]->z();
-  mat[2][2] = _v[4]->z() - _v[0]->z();
-  return sign(det3x3(mat));
-}
-
-void MHexahedron::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
-{
-#if !defined(HAVE_GMSH_EMBEDDED)
-  *npts = getNGQHPts(pOrder);
-  *pts = getGQHPts(pOrder);
-#endif
-}
-
-int MPrism::getVolumeSign()
-{ 
-  double mat[3][3];
-  mat[0][0] = _v[1]->x() - _v[0]->x();
-  mat[0][1] = _v[2]->x() - _v[0]->x();
-  mat[0][2] = _v[3]->x() - _v[0]->x();
-  mat[1][0] = _v[1]->y() - _v[0]->y();
-  mat[1][1] = _v[2]->y() - _v[0]->y();
-  mat[1][2] = _v[3]->y() - _v[0]->y();
-  mat[2][0] = _v[1]->z() - _v[0]->z();
-  mat[2][1] = _v[2]->z() - _v[0]->z();
-  mat[2][2] = _v[3]->z() - _v[0]->z();
-  return sign(det3x3(mat));
-}
-
-int MPyramid::getVolumeSign()
-{ 
-  double mat[3][3];
-  mat[0][0] = _v[1]->x() - _v[0]->x();
-  mat[0][1] = _v[3]->x() - _v[0]->x();
-  mat[0][2] = _v[4]->x() - _v[0]->x();
-  mat[1][0] = _v[1]->y() - _v[0]->y();
-  mat[1][1] = _v[3]->y() - _v[0]->y();
-  mat[1][2] = _v[4]->y() - _v[0]->y();
-  mat[2][0] = _v[1]->z() - _v[0]->z();
-  mat[2][1] = _v[3]->z() - _v[0]->z();
-  mat[2][2] = _v[4]->z() - _v[0]->z();
-  return sign(det3x3(mat));
-}
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 876fe70b899e5b9bee5fa5168bd2800aa3cb4572..8a381843550e798bcecb3f597ee8ff536ea9c04d 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -262,2641 +262,6 @@ class MElementFactory{
   MElement *create(int type, std::vector<MVertex*> &v, int num=0, int part=0);
 };
 
-/*
- * MPoint
- *
- */
-class MPoint : public MElement {
- protected:
-  MVertex *_v[1];
- public :
-  MPoint(MVertex *v0, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0;
-  }
-  MPoint(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v[0];
-  }
-  ~MPoint(){}
-  virtual int getDim(){ return 0; }
-  virtual int getNumVertices() const { return 1; }
-  virtual MVertex *getVertex(int num){ return _v[0]; }
-  virtual int getNumEdges(){ return 0; }
-  virtual MEdge getEdge(int num){ return MEdge(); }
-  virtual int getNumEdgesRep(){ return 0; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n){}
-  virtual int getNumFaces(){ return 0; }
-  virtual MFace getFace(int num){ return MFace(); }
-  virtual int getNumFacesRep(){ return 0; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n){}
-  virtual int getTypeForMSH() const { return MSH_PNT; }
-  virtual int getTypeForVTK() const { return 1; }
-  virtual const char *getStringForPOS() const { return "SP"; }
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
-  {
-    s[0] = 1.;
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
-  {
-    s[0][0] = s[0][1] = s[0][2] = 0.;
-  }
-  virtual bool isInside(double u, double v, double w)
-  {
-    return true;
-  }
-};
-
-/*
- * MLine
- *
- *   0----------1 --> u
- *
- */
-class MLine : public MElement {
- protected:
-  MVertex *_v[2];
-  void _getEdgeVertices(std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[0];
-    v[1] = _v[1];
-  }
- public :
-  MLine(MVertex *v0, MVertex *v1, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1;
-  }
-  MLine(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 2; i++) _v[i] = v[i];
-  }
-  ~MLine(){}
-  virtual int getDim(){ return 1; }
-  virtual int getNumVertices() const { return 2; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual int getNumEdges(){ return 1; }
-  virtual MEdge getEdge(int num){ return MEdge(_v[0], _v[1]); }
-  virtual int getNumEdgesRep(){ return 1; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    _getEdgeRep(_v[0], _v[1], x, y, z, n);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(v);
-  }
-  virtual int getNumFaces(){ return 0; }
-  virtual MFace getFace(int num){ return MFace(); }
-  virtual int getNumFacesRep(){ return 0; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n){}
-  virtual int getTypeForMSH() const { return MSH_LIN_2; }
-  virtual int getTypeForUNV() const { return 21; } // linear beam
-  virtual int getTypeForVTK() const { return 3; }
-  virtual const char *getStringForPOS() const { return "SL"; }
-  virtual const char *getStringForBDF() const { return "CBAR"; }
-  virtual void revert() 
-  {
-    MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
-  }
-  virtual const gmshFunctionSpace* getFunctionSpace(int o=-1) const;
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(u < -(1. + tol) || u > (1. + tol))
-      return false;
-    return true;
-  }
-  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
-};
-
-/*
- * MLine3
- *
- *   0-----2----1
- *
- */
-class MLine3 : public MLine {
- protected:
-  MVertex *_vs[1];
- public :
-  MLine3(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
-    : MLine(v0, v1, num, part)
-  {
-    _vs[0] = v2;
-    _vs[0]->setPolynomialOrder(2);
-  }
-  MLine3(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MLine(v, num, part)
-  {
-    _vs[0] = v[2];
-    _vs[0]->setPolynomialOrder(2);
-  }
-  ~MLine3(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 3; }
-  virtual MVertex *getVertex(int num){ return num < 2 ? _v[num] : _vs[num - 2]; }
-  virtual MVertex *getVertexUNV(int num)
-  {
-    static const int map[3] = {0, 2, 1};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 1; }
-  virtual int getNumEdgesRep(){ return 2; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[2][2] = {
-      {0, 2}, {2, 1}
-    };
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MLine::_getEdgeVertices(v);
-    v[2] = _vs[0];
-  }
-  virtual int getTypeForMSH() const { return MSH_LIN_3; }
-  virtual int getTypeForUNV() const { return 24; } // parabolic beam
-  //virtual int getTypeForVTK() const { return 21; }
-  virtual const char *getStringForPOS() const { return "SL2"; }
-};
-
-/*
- * MLineN
- *
- *   0---2---...-(N-1)-1
- *
- */
-class MLineN : public MLine {
- protected:
-  std::vector<MVertex *> _vs;
- public :
-  MLineN(MVertex *v0, MVertex *v1, const std::vector<MVertex*> &vs, int num=0, int part=0) 
-    : MLine(v0, v1, num, part), _vs(vs)
-  {
-    for(unsigned int i = 0; i < _vs.size(); i++)
-      _vs[i]->setPolynomialOrder(_vs.size() + 1);
-  }
-  MLineN(const std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MLine(v[0] , v[1], num, part)
-  {
-    for(unsigned int i = 2; i < v.size(); i++)
-      _vs.push_back(v[i]);
-    for(unsigned int i = 0; i < _vs.size(); i++)
-      _vs[i]->setPolynomialOrder(_vs.size() + 1);
-  }
-  ~MLineN(){}
-  virtual int getPolynomialOrder() const { return _vs.size() + 1; }
-  virtual int getNumVertices() const { return _vs.size() + 2; }
-  virtual MVertex *getVertex(int num){ return num < 2 ? _v[num] : _vs[num - 2]; }
-  virtual int getNumEdgeVertices() const { return _vs.size(); }
-  virtual int getNumEdgesRep(){ return _vs.size() + 1; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    _getEdgeRep(getVertex((num == 0) ? 0 : num + 1), 
-                getVertex((num == getNumEdgesRep() - 1) ? 1 : num + 2),
-                x, y, z, n);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2 + _vs.size());
-    MLine::_getEdgeVertices(v);
-    for(unsigned int i = 0; i != _vs.size(); ++i) v[i+2] = _vs[i];
-  }
-  virtual int getTypeForMSH() const 
-  { 
-    if(_vs.size() == 2) return MSH_LIN_4; 
-    if(_vs.size() == 3) return MSH_LIN_5; 
-    if(_vs.size() == 4) return MSH_LIN_6; 
-    return 0;
-  }
-};
-
-/* 
- * MTriangle
- *
- *   v
- *   ^
- *   |
- *   2
- *   |`\
- *   |  `\
- *   |    `\
- *   |      `\
- *   |        `\
- *   0----------1 --> u
- *
- */
-class MTriangle : public MElement {
- protected:
-  MVertex *_v[3];
-  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[edges_tri(num, 0)];
-    v[1] = _v[edges_tri(num, 1)];
-  }
-  void _getFaceVertices(std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[0];
-    v[1] = _v[1];
-    v[2] = _v[2];
-  }
- public :
-  MTriangle(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1; _v[2] = v2;
-  }
-  MTriangle(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 3; i++) _v[i] = v[i];
-  }
-  ~MTriangle(){}
-  virtual int getDim(){ return 2; }
-  virtual double gammaShapeMeasure();
-  virtual double distoShapeMeasure();
-  virtual int getNumVertices() const { return 3; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[3] = {0, 2, 1};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getOtherVertex(MVertex *v1, MVertex *v2)
-  { 
-    if(_v[0] != v1 && _v[0] != v2) return _v[0];
-    if(_v[1] != v1 && _v[1] != v2) return _v[1];
-    if(_v[2] != v1 && _v[2] != v2) return _v[2];
-    return 0;
-  }
-  virtual int getNumEdges(){ return 3; }
-  virtual MEdge getEdge(int num)
-  {
-    return MEdge(_v[edges_tri(num, 0)], _v[edges_tri(num, 1)]);
-  }
-  virtual int getNumEdgesRep(){ return 3; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    MEdge e(getEdge(num));
-    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, 0);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(num, v);
-  }
-  virtual int getNumFaces(){ return 1; }
-  virtual MFace getFace(int num)
-  { 
-    return MFace(_v[0], _v[1], _v[2]); 
-  }
-  virtual int getNumFacesRep(){ return 1; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    _getFaceRep(_v[0], _v[1], _v[2], x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    _getFaceVertices(v);
-  }
-  virtual int getTypeForMSH() const { return MSH_TRI_3; }
-  virtual int getTypeForUNV() const { return 91; } // thin shell linear triangle
-  virtual int getTypeForVTK() const { return 5; }
-  virtual const char *getStringForPOS() const { return "ST"; }
-  virtual const char *getStringForBDF() const { return "CTRIA3"; }
-  virtual const char *getStringForDIFF() const { return "ElmT3n2D"; }
-  virtual void revert() 
-  {
-    MVertex *tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
-  }
-  virtual const gmshFunctionSpace* getFunctionSpace(int o=-1) const;
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(u < (-tol) || v < (-tol) || u > ((1. + tol) - v))
-      return false; 
-    return true;
-  }
-  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
-  virtual SPoint3 circumcenter();
- private:
-  int edges_tri(const int edge, const int vert) const
-  {
-    static const int e[3][2] = {
-      {0, 1},
-      {1, 2},
-      {2, 0}
-    };
-    return e[edge][vert];
-  }
-};
-
-/*
- * MTriangle6
- *
- *   2
- *   |`\
- *   |  `\
- *   5    `4
- *   |      `\
- *   |        `\
- *   0-----3----1
- *
- */
-class MTriangle6 : public MTriangle {
- protected:
-  MVertex *_vs[3];
- public :
-  MTriangle6(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4,
-             MVertex *v5, int num=0, int part=0) 
-    : MTriangle(v0, v1, v2, num, part)
-  {
-    _vs[0] = v3; _vs[1] = v4; _vs[2] = v5;
-    for(int i = 0; i < 3; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MTriangle6(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MTriangle(v, num, part)
-  {
-    for(int i = 0; i < 3; i++) _vs[i] = v[3 + i];
-    for(int i = 0; i < 3; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MTriangle6(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 6; }
-  virtual MVertex *getVertex(int num){ return num < 3 ? _v[num] : _vs[num - 3]; }
-  virtual MVertex *getVertexUNV(int num)
-  {
-    static const int map[6] = {0, 3, 1, 4, 2, 5};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[6] = {0, 2, 1, 5, 4, 3};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 3; }
-  virtual int getNumEdgesRep();
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MTriangle::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep();
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(6);
-    MTriangle::_getFaceVertices(v);
-    v[3] = _vs[0];
-    v[4] = _vs[1];
-    v[5] = _vs[2];
-  }
-  virtual int getTypeForMSH() const { return MSH_TRI_6; }
-  virtual int getTypeForUNV() const { return 92; } // thin shell parabolic triangle
-  //virtual int getTypeForVTK() const { return 22; }
-  virtual const char *getStringForPOS() const { return "ST2"; }
-  virtual const char *getStringForBDF() const { return "CTRIA6"; }
-  virtual const char *getStringForDIFF() const { return "ElmT6n2D"; }
-  virtual void revert() 
-  {
-    MVertex *tmp;
-    tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
-    tmp = _vs[0]; _vs[0] = _vs[2]; _vs[2] = tmp;
-  }
-};
-
-/*
- * MTriangleN  FIXME: check the plot
- *
- *   2
- *   |`\                E = order - 1;
- *   |  `\              N = total number of vertices
- * 3+2E   2+2E
- *   |      `\          Interior vertex numbers
- *  ...       ...         for edge 0 <= i <= 2: 3+i*E to 2+(i+1)*E
- *   |          `\        in volume           : 3+3*E to N-1
- * 2+3E           3+E
- *   |  3+3E to N-1 `\
- *   |                `\
- *   0---3--...---2+E---1
- *
- */
-class MTriangleN : public MTriangle {
- protected:
-  std::vector<MVertex *> _vs;
-  const char _order;
- public:
-  MTriangleN(MVertex *v0, MVertex *v1, MVertex *v2, 
-             std::vector<MVertex*> &v, char order, int num=0, int part=0) 
-    : MTriangle(v0, v1, v2, num, part), _vs(v), _order(order)
-  {
-    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
-  }
-  MTriangleN(std::vector<MVertex*> &v, char order, int num=0, int part=0) 
-    : MTriangle(v[0], v[1], v[2], num, part), _order(order)
-  {
-    for(unsigned int i = 3; i < v.size(); i++) _vs.push_back(v[i]);
-    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
-  }
-  ~MTriangleN(){}
-  virtual int getPolynomialOrder() const { return _order; }
-  virtual int getNumVertices() const { return 3 + _vs.size(); }
-  virtual MVertex *getVertex(int num){ return num < 3 ? _v[num] : _vs[num - 3]; }
-  virtual int getNumFaceVertices() const 
-  {
-    if(_order == 3 && _vs.size() == 6) return 0;
-    if(_order == 3 && _vs.size() == 7) return 1;
-    if(_order == 4 && _vs.size() == 9) return 0;
-    if(_order == 4 && _vs.size() == 12) return 3;
-    if(_order == 5 && _vs.size() == 12) return 0;
-    if(_order == 5 && _vs.size() == 18) return 6;
-    return 0;
-  }
-  virtual int getNumEdgeVertices() const { return 3 * (_order - 1); }
-  virtual int getNumEdgesRep();
-  virtual int getNumFacesRep();
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(_order + 1);
-    MTriangle::_getEdgeVertices(num, v);
-    int j = 2;
-    const int ie = (num + 1) * (_order - 1);
-    for(int i = num * (_order-1); i != ie; ++i) v[j++] = _vs[i];
-  }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3 + _vs.size());
-    MTriangle::_getFaceVertices(v);
-    for(unsigned int i = 0; i != _vs.size(); ++i) v[i + 3] = _vs[i];
-  }
-  virtual int getTypeForMSH() const
-  {
-    if(_order == 2 && _vs.size() == 3) return MSH_TRI_6; 
-    if(_order == 3 && _vs.size() == 6) return MSH_TRI_9; 
-    if(_order == 3 && _vs.size() == 7) return MSH_TRI_10; 
-    if(_order == 4 && _vs.size() == 9) return MSH_TRI_12; 
-    if(_order == 4 && _vs.size() == 12) return MSH_TRI_15; 
-    if(_order == 5 && _vs.size() == 12) return MSH_TRI_15I; 
-    if(_order == 5 && _vs.size() == 18) return MSH_TRI_21;
-    return 0;
-  }
-  virtual void revert() 
-  {
-    MVertex *tmp;
-    tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
-    std::vector<MVertex*> inv;
-    inv.insert(inv.begin(), _vs.rbegin(), _vs.rend());
-    _vs = inv;
-  }
-};
-
-/*
- * MQuadrangle
- *
- *         v
- *         ^
- *         |
- *   3-----------2
- *   |     |     |
- *   |     |     |
- *   |     +---- | --> u
- *   |           |
- *   |           |
- *   0-----------1 
- *
- */
-class MQuadrangle : public MElement {
- protected:
-  MVertex *_v[4];
-  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[edges_quad(num, 0)];
-    v[1] = _v[edges_quad(num, 1)];
-  }
-  void _getFaceVertices(std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[0];
-    v[1] = _v[1];
-    v[2] = _v[2];
-    v[3] = _v[3];
-  }
- public :
-  MQuadrangle(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
-  }
-  MQuadrangle(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 4; i++) _v[i] = v[i];
-  }
-  ~MQuadrangle(){}
-  virtual int getDim(){ return 2; }
-  virtual int getNumVertices() const { return 4; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[4] = {0, 3, 2, 1};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[4] = {0, 1, 3, 2};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdges(){ return 4; }
-  virtual MEdge getEdge(int num)
-  {
-    return MEdge(_v[edges_quad(num, 0)], _v[edges_quad(num, 1)]);
-  }
-  virtual int getNumEdgesRep(){ return 4; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    MEdge e(getEdge(num));
-    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, 0);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(num, v);
-  }
-  virtual int getNumFaces(){ return 1; }
-  virtual MFace getFace(int num){ return MFace(_v[0], _v[1], _v[2], _v[3]); }
-  virtual int getNumFacesRep(){ return 2; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[2][3] = {
-      {0, 1, 2}, {0, 2, 3}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(4);
-    _getFaceVertices(v);
-  }
-  virtual int getTypeForMSH() const { return MSH_QUA_4; }
-  virtual int getTypeForUNV() const { return 94; } // thin shell linear quadrilateral
-  virtual int getTypeForVTK() const { return 9; }
-  virtual const char *getStringForPOS() const { return "SQ"; }
-  virtual const char *getStringForBDF() const { return "CQUAD4"; }
-  virtual const char *getStringForDIFF() const { return "ElmB4n2D"; }
-  virtual void revert() 
-  {
-    MVertex *tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
-  }
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
-  {
-    s[0] = (1. - u) * (1. - v) * 0.25;
-    s[1] = (1. + u) * (1. - v) * 0.25;
-    s[2] = (1. + u) * (1. + v) * 0.25;
-    s[3] = (1. - u) * (1. + v) * 0.25;
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
-  {
-    s[0][0] = -0.25 * (1. - v); s[0][1] = -0.25 * (1. - u); s[0][2] = 0.;
-    s[1][0] =  0.25 * (1. - v); s[1][1] = -0.25 * (1. + u); s[1][2] = 0.;
-    s[2][0] =  0.25 * (1. + v); s[2][1] =  0.25 * (1. + u); s[2][2] = 0.;
-    s[3][0] = -0.25 * (1. + v); s[3][1] =  0.25 * (1. - u); s[3][2] = 0.;
-  }
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(u < -(1. + tol) || v < -(1. + tol) || u > (1. + tol) || v > (1. + tol))
-      return false;
-    return true;
-  }
-  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
- private:
-  int edges_quad(const int edge, const int vert) const
-  {
-    static const int e[4][2] = {
-      {0, 1},
-      {1, 2},
-      {2, 3},
-      {3, 0}
-    };
-    return e[edge][vert];
-  }
-};
-
-/*
- * MQuadrangle8
- *
- *   3-----6-----2
- *   |           |
- *   |           |
- *   7           5
- *   |           |
- *   |           |
- *   0-----4-----1 
- *
- */
-class MQuadrangle8 : public MQuadrangle {
- protected:
-  MVertex *_vs[4];
- public :
-  MQuadrangle8(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-               MVertex *v5, MVertex *v6, MVertex *v7, int num=0, int part=0) 
-    : MQuadrangle(v0, v1, v2, v3, num, part)
-  {
-    _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7;
-    for(int i = 0; i < 4; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MQuadrangle8(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MQuadrangle(v, num, part)
-  {
-    for(int i = 0; i < 4; i++) _vs[i] = v[4 + i];
-    for(int i = 0; i < 4; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MQuadrangle8(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 8; }
-  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
-  virtual MVertex *getVertexUNV(int num)
-  {
-    static const int map[8] = {0, 4, 1, 5, 2, 6, 3, 7};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[8] = {0, 3, 2, 1, 7, 6, 5, 4};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[8] = {0, 1, 3, 2, 4, 7, 5, 6};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 4; }
-  virtual int getNumEdgesRep(){ return 8; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[8][2] = {
-      {0, 4}, {4, 1},
-      {1, 5}, {5, 2},
-      {2, 6}, {6, 3},
-      {3, 7}, {7, 0}
-    };
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, 0);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MQuadrangle::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 6; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[6][3] = {
-      {0, 4, 7}, {1, 5, 4}, {2, 6, 5}, {3, 7, 6}, {4, 5, 6}, {4, 6, 7}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(8);
-    MQuadrangle::_getFaceVertices(v);
-    v[4] = _vs[0];
-    v[5] = _vs[1];
-    v[6] = _vs[2];
-    v[7] = _vs[3];
-  }
-  virtual int getTypeForMSH() const { return MSH_QUA_8; }
-  virtual int getTypeForUNV() const { return 95; } // shell parabolic quadrilateral
-  //virtual int getTypeForVTK() const { return 23; }
-  virtual const char *getStringForBDF() const { return "CQUAD8"; }
-  virtual const char *getStringForDIFF() const { return "ElmB8n2D"; }
-  virtual void revert() 
-  {
-    MVertex *tmp;
-    tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
-    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
-    tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
-  }
-};
-
-/*
- * MQuadrangle9
- *
- *   3-----6-----2
- *   |           |
- *   |           |
- *   7     8     5
- *   |           |
- *   |           |
- *   0-----4-----1 
- *
- */
-class MQuadrangle9 : public MQuadrangle {
- protected:
-  MVertex *_vs[5];
- public :
-  MQuadrangle9(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-               MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, int num=0, int part=0) 
-    : MQuadrangle(v0, v1, v2, v3, num, part)
-  {
-    _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7; _vs[4] = v8;
-    for(int i = 0; i < 5; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MQuadrangle9(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MQuadrangle(v, num, part)
-  {
-    for(int i = 0; i < 5; i++) _vs[i] = v[4 + i];
-    for(int i = 0; i < 5; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MQuadrangle9(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 9; }
-  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[9] = {0, 2, 8, 6, 1, 5, 7, 3, 4};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 4; }
-  virtual int getNumFaceVertices() const { return 1; }
-  virtual int getNumEdgesRep(){ return 8; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[8][2] = {
-      {0, 4}, {4, 1},
-      {1, 5}, {5, 2},
-      {2, 6}, {6, 3},
-      {3, 7}, {7, 0}
-    };
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, 0);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MQuadrangle::getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 8; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[8][4] = {
-      {0, 4, 8}, {0, 8, 7}, {1, 5, 8}, {1, 8, 4}, 
-      {2, 6, 8}, {2, 8, 5}, {3, 7, 8}, {3, 8, 6}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(9);
-    MQuadrangle::_getFaceVertices(v);
-    v[4] = _vs[0];
-    v[5] = _vs[1];
-    v[6] = _vs[2];
-    v[7] = _vs[3];
-    v[8] = _vs[4];
-  }
-  virtual int getTypeForMSH() const { return MSH_QUA_9; }
-  virtual const char *getStringForPOS() const { return "SQ2"; }
-  virtual const char *getStringForDIFF() const { return "ElmB9n2D"; }
-  virtual void revert() 
-  {
-    MVertex *tmp;
-    tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
-    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
-    tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
-  }
-};
-
-/*
- * MTetrahedron
- *
- *                      v
- *                    .
- *                  ,/
- *                 /
- *              2
- *            ,/|`\
- *          ,/  |  `\
- *        ,/    '.   `\
- *      ,/       |     `\
- *    ,/         |       `\
- *   0-----------'.--------1 --> u
- *    `\.         |      ,/
- *       `\.      |    ,/
- *          `\.   '. ,/
- *             `\. |/
- *                `3
- *                   `\.
- *                      ` w
- *
- */
-class MTetrahedron : public MElement {
- protected:
-  MVertex *_v[4];
-  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[edges_tetra(num, 0)];
-    v[1] = _v[edges_tetra(num, 1)];
-  }
-  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[faces_tetra(num, 0)];
-    v[1] = _v[faces_tetra(num, 1)];
-    v[2] = _v[faces_tetra(num, 2)];
-  }
- public :
-  MTetrahedron(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
-  }
-  MTetrahedron(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 4; i++) _v[i] = v[i];
-  }
-  ~MTetrahedron(){}
-  virtual int getDim(){ return 3; }
-  virtual int getNumVertices() const { return 4; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[4] = {0, 2, 1, 3};
-    return getVertex(map[num]);
-  }
-  virtual int getNumEdges(){ return 6; }
-  virtual MEdge getEdge(int num)
-  {
-    return MEdge(_v[edges_tetra(num, 0)], _v[edges_tetra(num, 1)]);
-  }
-  virtual int getNumEdgesRep(){ return 6; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  {
-    static const int f[6] = {0, 0, 0, 1, 2, 3};
-    MEdge e(getEdge(num));
-    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(num, v);
-  }
-  virtual int getNumFaces(){ return 4; }
-  virtual MFace getFace(int num)
-  {
-    return MFace(_v[faces_tetra(num, 0)],
-		 _v[faces_tetra(num, 1)],
-		 _v[faces_tetra(num, 2)]);
-  }
-  virtual int getNumFacesRep(){ return 4; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    MFace f(getFace(num));
-    _getFaceRep(f.getVertex(0), f.getVertex(1), f.getVertex(2), x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    _getFaceVertices(num, v);
-  }
-  virtual int getTypeForMSH() const { return MSH_TET_4; }
-  virtual int getTypeForUNV() const { return 111; } // solid linear tetrahedron
-  virtual int getTypeForVTK() const { return 10; }
-  virtual const char *getStringForPOS() const { return "SS"; }
-  virtual const char *getStringForBDF() const { return "CTETRA"; }
-  virtual const char *getStringForDIFF() const { return "ElmT4n3D"; }
-  virtual void revert()
-  {
-    MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
-  }
-  void getMat(double mat[3][3])
-  {
-    mat[0][0] = _v[1]->x() - _v[0]->x();
-    mat[0][1] = _v[2]->x() - _v[0]->x();
-    mat[0][2] = _v[3]->x() - _v[0]->x();
-    mat[1][0] = _v[1]->y() - _v[0]->y();
-    mat[1][1] = _v[2]->y() - _v[0]->y();
-    mat[1][2] = _v[3]->y() - _v[0]->y();
-    mat[2][0] = _v[1]->z() - _v[0]->z();
-    mat[2][1] = _v[2]->z() - _v[0]->z();
-    mat[2][2] = _v[3]->z() - _v[0]->z();
-  }
-  virtual double getVolume();
-  virtual int getVolumeSign(){ return (getVolume() >= 0) ? 1 : -1; }
-  virtual double gammaShapeMeasure();
-  virtual double distoShapeMeasure();
-  virtual double etaShapeMeasure();
-  void xyz2uvw(double xyz[3], double uvw[3]);
-  virtual const gmshFunctionSpace* getFunctionSpace(int o=-1) const;
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(u < (-tol) || v < (-tol) || w < (-tol) || u > ((1. + tol) - v - w))
-      return false;
-    return true;
-  }
-  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
-  virtual SPoint3 circumcenter();
- private:
-  int edges_tetra(const int edge, const int vert) const
-  {
-    static const int e[6][2] = {
-      {0, 1},
-      {1, 2},
-      {2, 0},
-      {3, 0},
-      {3, 2},
-      {3, 1}
-    };
-    return e[edge][vert];
-  }
-  int faces_tetra(const int face, const int vert) const
-  {
-    static const int f[4][3] = {
-      {0, 2, 1},
-      {0, 1, 3},
-      {0, 3, 2},
-      {3, 1, 2}
-    };
-    return f[face][vert];
-  }
-};
-
-/*
- * MTetrahedron10
- *
- *              2 
- *            ,/|`\
- *          ,/  |  `\
- *        ,6    '.   `5
- *      ,/       8     `\
- *    ,/         |       `\
- *   0--------4--'.--------1
- *    `\.         |      ,/
- *       `\.      |    ,9
- *          `7.   '. ,/
- *             `\. |/
- *                `3
- *
- */
-class MTetrahedron10 : public MTetrahedron {
- protected:
-  MVertex *_vs[6];
- public :
-  MTetrahedron10(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-                 MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-                 int num=0, int part=0) 
-    : MTetrahedron(v0, v1, v2, v3, num, part)
-  {
-    _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7; _vs[4] = v8; _vs[5] = v9;
-    for(int i = 0; i < 6; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MTetrahedron10(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MTetrahedron(v, num, part)
-  {
-    for(int i = 0; i < 6; i++) _vs[i] = v[4 + i];
-    for(int i = 0; i < 6; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MTetrahedron10(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 10; }
-  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
-  virtual MVertex *getVertexUNV(int num)
-  {
-    static const int map[10] = {0, 4, 1, 5, 2, 6, 8, 9, 7, 3};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexBDF(int num)
-  {
-    static const int map[10] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 8};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[10] = {0, 2, 1, 3, 6, 5, 4, 7, 8, 9};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[10] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 8};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 6; }
-
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual int getNumEdgesRep();
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual int getNumFacesRep();
-
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MTetrahedron::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(6);
-    MTetrahedron::_getFaceVertices(num, v);
-    static const int f[4][3] = {
-      {4, 5, 6},
-      {4, 7, 9},
-      {6, 7, 8},
-      {5, 8, 9}
-    };
-    v[3] = _vs[f[num][0]];
-    v[4] = _vs[f[num][1]];
-    v[5] = _vs[f[num][2]];
-  }
-  virtual int getTypeForMSH() const { return MSH_TET_10; }
-  virtual int getTypeForUNV() const { return 118; } // solid parabolic tetrahedron
-  //virtual int getTypeForVTK() const { return 24; }
-  virtual const char *getStringForPOS() const { return "SS2"; }
-  virtual const char *getStringForBDF() const { return "CTETRA"; }
-  virtual const char *getStringForDIFF() const { return "ElmT10n3D"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0] ; _v[0]  = _v[1]; _v[1] = tmp;
-    tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
-    tmp = _vs[5]; _vs[5] = _vs[3]; _vs[3] = tmp;
-  }
-};
-
-/*
- * MTetrahedronN  FIXME: check the plot
- *
- *              2
- *            ,/|`\ 
- *          ,/  |  `\              E = order - 1
- *        ,/    '.   `\            C = 4 + 6*E 
- *      ,/       |     `\          F = ((order - 1)*(order - 2))/2
- *    ,/         |       `\	   N = total number of vertices
- *   0-----------'.--------1
- *    `\.         |      ,/        Interior vertex numbers  
- *       `\.      |    ,/            for edge 0 <= i <= 5: 4+i*E to 3+(i+1)*E
- *          `\.   '. ,/		     for face 0 <= j <= 3: C+j*F to C-1+(j+1)*F
- *             `\. |/		     in volume           : C+4*F to N-1
- *                `3
- *
- */
-
-
-
-/* tet order 3
-   
- *              2
- *            ,/|`\ 
- *          ,5  |  `6              E = order - 1
- *        ,/    12   `\            C = 4 + 6*E 
- *      ,4       |     `7          F = ((order - 1)*(order - 2))/2
- *    ,/         |       `\	   N = total number of vertices
- *   0-----9-----'.--8-----1
- *    `\.         |      ,/        Interior vertex numbers
- *       10.     13    ,14           for edge 0 <= i <= 5: 4+i*E to 3+(i+1)*E
- *          `\.   '. 15		     for face 0 <= j <= 3: C+j*F to C-1+(j+1)*F
- *             11\.|/ 	     in volume           : C+4*F to N-1
- *                `3
- *
- */
-
-static int reverseTet20[20] = {0,2,1,3,  // principal vertices
-                               9,8,      // E0 switches with E2
-                               7,6,      // E1 inverts direction
-                               5,4,      // E2 switches with E0
-                               10,11,    // E3 pure w edge > remains the same
-                               14,15,    // E4 uw edge swithes with v/w edge E5
-                               12,13,    // E5 switches with E4
-                               16,       // F0 is uv plane, reverts normal
-                               18,       // F1 is uw plane, switches with F2
-                               17,       // F2 is vw plane, switches with F1
-                               19};      // F3 is uvw plane, reverts normal
-
-static int reverseTet35[35] = {0,2,1,3,  // principal vertices
-                               
-                               12,11,10, // E0 switches with E2
-                               9,8,7,    // E1 inverts direction
-                               6,5,4,    // E2 switches with E0
-                               13,14,15, // E3 pure w edge > remains the same
-                               19,20,21, // E4 uw edge swithes with v/w edge E5
-                               16,17,18, // E5 switches with E4
-                               22,24,23, // F0 is uv plane, reverts normal
-                               28,30,29, // F1 is uw plane, switches with F2, orientation is different
-                               25,27,26, // F2 is vw plane, switches with F1
-                               31,33,32, // F3 is uvw plane, reverts normal
-                               34};      // central node remains 
-  
-static int reverseTet34[34] = {0,2,1,3,  // principal vertices
-                               12,11,10, // E0 switches with E2
-                               9,8,7,    // E1 inverts direction
-                               6,5,4,    // E2 switches with E0
-                               13,14,15, // E3 pure w edge > remains the same
-                               19,20,21, // E4 uw edge swithes with v/w edge E5
-                               16,17,18, // E5 switches with E4
-                               22,24,23, // F0 is uv plane, reverts normal
-                               28,29,30, // F1 is uw plane, switches with F2
-                               25,26,27, // F2 is vw plane, switches with F1
-                               31,33,32};// F3 is uvw plane, reverts normal
-
-class MTetrahedronN : public MTetrahedron {
- protected:
-  std::vector<MVertex *> _vs;
-  const char _order;
-  double _disto;
- public:
-  MTetrahedronN(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, 
-		std::vector<MVertex*> &v, char order, int num=0, int part=0) 
-    : MTetrahedron(v0, v1, v2, v3, num, part) , _vs (v), _order(order),_disto(-1.e22)
-  {
-    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
-  }
-  MTetrahedronN(std::vector<MVertex*> &v, char order, int num=0, int part=0) 
-    : MTetrahedron(v[0], v[1], v[2], v[3], num, part) , _order(order),_disto(-1.e22)
-  {
-    for(unsigned int i = 4; i < v.size(); i++) _vs.push_back(v[i]);
-    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
-  }
-  ~MTetrahedronN(){}
-  virtual double distoShapeMeasure();
-  virtual int getPolynomialOrder() const { return _order; }
-  virtual int getNumVertices() const { return 4 + _vs.size(); }
-  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
-  virtual int getNumEdgeVertices() const { return 6 * (_order - 1); }
-  virtual int getNumFaceVertices() const
-  {
-    return 4 * ((_order - 1) * (_order - 2)) / 2;
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(_order + 1);
-    MTetrahedron::_getEdgeVertices(num, v);
-    int j = 2;
-    const int ie = (num + 1) * (_order -1);
-    for(int i = num * (_order -1); i != ie; ++i) v[j++] = _vs[i];
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3 + 3 * (_order - 1) + (_order-1) * (_order - 2) /2);
-    MTetrahedron::_getFaceVertices(num, v);
-    int j = 3;
-    int nbV = (_order - 1) * (_order - 2) / 2;
-    const int ie = (num+1)*nbV;
-    for(int i = num*nbV; i != ie; ++i) v[j++] = _vs[i];
-  }
-  virtual int getNumVolumeVertices() const 
-  {
-    switch(getTypeForMSH()){
-    case MSH_TET_35 : return 1;
-    case MSH_TET_56 : return 4;
-    default : return 0;
-    }    
-  }
-  virtual int getTypeForMSH() const 
-  {
-    // (p+1)*(p+2)*(p+3)/6
-    if(_order == 3 && _vs.size() + 4 == 20) return MSH_TET_20; 
-    if(_order == 4 && _vs.size() + 4 == 34) return MSH_TET_34; 
-    if(_order == 4 && _vs.size() + 4 == 35) return MSH_TET_35; 
-    if(_order == 5 && _vs.size() + 4 == 56) return MSH_TET_56; 
-    if(_order == 5 && _vs.size() + 4 == 52) return MSH_TET_52; 
-    return 0;
-  }
-  virtual void revert() 
-  {    
-    MVertex *tmp;
-    tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;    
-    switch (getTypeForMSH()) {
-    case MSH_TET_20:
-      {
-        std::vector<MVertex*> inv(16);
-        for (int i=0;i<16;i++) inv[i] = _vs[reverseTet20[i+4]-4];
-        _vs = inv;
-        break;
-      }
-    case MSH_TET_35:
-      {
-        std::vector<MVertex*> inv(31);
-        for (int i=0;i<31;i++) inv[i] = _vs[reverseTet35[i+4]-4];
-        _vs = inv;
-        break;
-      }
-    case MSH_TET_34:
-      {
-        std::vector<MVertex*> inv(30);
-        for (int i=0;i<30;i++) inv[i] = _vs[reverseTet34[i+4]-4];
-        _vs = inv;
-        break;
-      }
-    default:
-      {
-        Msg::Error("Reversion of %d order tetrahedron (type %d) not implemented\n",
-                   _order, getTypeForMSH());
-        break;
-      }
-    }
-  }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual int getNumEdgesRep();
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
-  virtual int getNumFacesRep();
-};
-
-/*
- * MHexahedron
- *
- *          v
- *   3----------2
- *   |\     ^   |\
- *   | \    |   | \
- *   |  \   |   |  \
- *   |   7------+---6
- *   |   |  +-- |-- | -> u
- *   0---+---\--1   | 
- *    \  |    \  \  |
- *     \ |     \  \ |
- *      \|      w  \|
- *       4----------5
- *
- */
-class MHexahedron : public MElement {
- protected:
-  MVertex *_v[8];
-  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[edges_hexa(num, 0)];
-    v[1] = _v[edges_hexa(num, 1)];
-  }
-  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[faces_hexa(num, 0)];
-    v[1] = _v[faces_hexa(num, 1)];
-    v[2] = _v[faces_hexa(num, 2)];
-    v[3] = _v[faces_hexa(num, 3)];
-  }
- public :
-  MHexahedron(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-              MVertex *v5, MVertex *v6, MVertex *v7, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
-    _v[4] = v4; _v[5] = v5; _v[6] = v6; _v[7] = v7;
-  }
-  MHexahedron(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 8; i++) _v[i] = v[i];
-  }
-  ~MHexahedron(){}
-  virtual int getDim(){ return 3; }
-  virtual int getNumVertices() const { return 8; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[8] = {0, 3, 2, 1, 4, 7, 6, 5};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[8] = {2, 3, 7, 6, 0, 1, 5, 4};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdges(){ return 12; }
-  virtual MEdge getEdge(int num)
-  {
-    return MEdge(_v[edges_hexa(num, 0)], _v[edges_hexa(num, 1)]);
-  }
-  virtual int getNumEdgesRep(){ return 12; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  {
-    static const int f[12] = {0, 0, 1, 0, 1, 0, 3, 2, 1, 2, 3, 4};
-    MEdge e(getEdge(num));
-    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(num, v);
-  }
-  virtual int getNumFaces(){ return 6; }
-  virtual MFace getFace(int num)
-  {
-    return MFace(_v[faces_hexa(num, 0)],
-		 _v[faces_hexa(num, 1)],
-		 _v[faces_hexa(num, 2)],
-		 _v[faces_hexa(num, 3)]);
-  }
-  virtual int getNumFacesRep(){ return 12; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[12][3] = {
-      {0, 3, 2}, {0, 2, 1},
-      {0, 1, 5}, {0, 5, 4},
-      {0, 4, 7}, {0, 7, 3},
-      {1, 2, 6}, {1, 6, 5},
-      {2, 3, 7}, {2, 7, 6},
-      {4, 5, 6}, {4, 6, 7}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(4);
-    _getFaceVertices(num, v);
-  }
-  virtual int getTypeForMSH() const { return MSH_HEX_8; }
-  virtual int getTypeForUNV() const { return 115; } // solid linear brick
-  virtual int getTypeForVTK() const { return 12; }
-  virtual const char *getStringForPOS() const { return "SH"; }
-  virtual const char *getStringForBDF() const { return "CHEXA"; }
-  virtual const char *getStringForDIFF() const { return "ElmB8n3D"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
-    tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
-  }
-  virtual int getVolumeSign();
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
-  {
-    s[0] = (1. - u) * (1. - v) * (1. - w) * 0.125;
-    s[1] = (1. + u) * (1. - v) * (1. - w) * 0.125;
-    s[2] = (1. + u) * (1. + v) * (1. - w) * 0.125;
-    s[3] = (1. - u) * (1. + v) * (1. - w) * 0.125;
-    s[4] = (1. - u) * (1. - v) * (1. + w) * 0.125;
-    s[5] = (1. + u) * (1. - v) * (1. + w) * 0.125;
-    s[6] = (1. + u) * (1. + v) * (1. + w) * 0.125;
-    s[7] = (1. - u) * (1. + v) * (1. + w) * 0.125;
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
-  {
-    s[0][0] = -0.125 * (1. - v) * (1. - w);
-    s[0][1] = -0.125 * (1. - u) * (1. - w);
-    s[0][2] = -0.125 * (1. - u) * (1. - v);
-    s[1][0] =  0.125 * (1. - v) * (1. - w);
-    s[1][1] = -0.125 * (1. + u) * (1. - w);
-    s[1][2] = -0.125 * (1. + u) * (1. - v);
-    s[2][0] =  0.125 * (1. + v) * (1. - w);
-    s[2][1] =  0.125 * (1. + u) * (1. - w);
-    s[2][2] = -0.125 * (1. + u) * (1. + v);
-    s[3][0] = -0.125 * (1. + v) * (1. - w);
-    s[3][1] =  0.125 * (1. - u) * (1. - w);
-    s[3][2] = -0.125 * (1. - u) * (1. + v);
-    s[4][0] = -0.125 * (1. - v) * (1. + w);
-    s[4][1] = -0.125 * (1. - u) * (1. + w);
-    s[4][2] =  0.125 * (1. - u) * (1. - v);
-    s[5][0] =  0.125 * (1. - v) * (1. + w);
-    s[5][1] = -0.125 * (1. + u) * (1. + w);
-    s[5][2] =  0.125 * (1. + u) * (1. - v);
-    s[6][0] =  0.125 * (1. + v) * (1. + w);
-    s[6][1] =  0.125 * (1. + u) * (1. + w);
-    s[6][2] =  0.125 * (1. + u) * (1. + v);
-    s[7][0] = -0.125 * (1. + v) * (1. + w);
-    s[7][1] =  0.125 * (1. - u) * (1. + w);
-    s[7][2] =  0.125 * (1. - u) * (1. + v);
-  }
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(u < -(1. + tol) || v < -(1. + tol) || w < -(1. + tol) || 
-       u > (1. + tol) || v > (1. + tol) || w > (1. + tol))
-      return false;
-    return true;
-  }
-  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
- private:
-  int edges_hexa(const int edge, const int vert) const
-  {
-    static const int e[12][2] = {
-      {0, 1},
-      {0, 3},
-      {0, 4},
-      {1, 2},
-      {1, 5},
-      {2, 3},
-      {2, 6},
-      {3, 7},
-      {4, 5},
-      {4, 7},
-      {5, 6},
-      {6, 7}
-    };
-    return e[edge][vert];
-  }
-  int faces_hexa(const int face, const int vert) const
-  {
-    static const int f[6][4] = {
-      {0, 3, 2, 1},
-      {0, 1, 5, 4},
-      {0, 4, 7, 3},
-      {1, 2, 6, 5},
-      {2, 3, 7, 6},
-      {4, 5, 6, 7}
-    };
-    return f[face][vert];
-  }
-};
-
-/*
- * MHexahedron20
- *
- *   3----13----2
- *   |\         |\
- *   | 15       | 14
- *   9  \       11 \
- *   |   7----19+---6
- *   |   |      |   |
- *   0---+-8----1   | 
- *    \  17      \  18
- *    10 |        12|
- *      \|         \|
- *       4----16----5
- *
- */
-class MHexahedron20 : public MHexahedron {
- protected:
-  MVertex *_vs[12];
- public :
-  MHexahedron20(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-                MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-                MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
-                MVertex *v15, MVertex *v16, MVertex *v17, MVertex *v18, MVertex *v19,
-                int num=0, int part=0) 
-    : MHexahedron(v0, v1, v2, v3, v4, v5, v6, v7, num, part)
-  {
-    _vs[0] = v8; _vs[1] = v9; _vs[2] = v10; _vs[3] = v11; _vs[4] = v12; 
-    _vs[5] = v13; _vs[6] = v14; _vs[7] = v15; _vs[8] = v16; _vs[9] = v17; 
-    _vs[10] = v18; _vs[11] = v19; 
-    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MHexahedron20(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MHexahedron(v, num, part)
-  {
-    for(int i = 0; i < 12; i++) _vs[i] = v[8 + i];
-    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MHexahedron20(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 20; }
-  virtual MVertex *getVertex(int num){ return num < 8 ? _v[num] : _vs[num - 8]; }
-  virtual MVertex *getVertexUNV(int num)
-  {
-    static const int map[20] = {0, 8, 1, 11, 2, 13, 3, 9, 10, 12, 
-                                14, 15, 4, 16, 5, 18, 6, 19, 7, 17};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexBDF(int num)
-  {
-    static const int map[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 13, 
-                                9, 10, 12, 14, 15, 16, 18, 19, 17};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[20] = {0, 3, 2, 1, 4, 7, 6, 5, 9, 13, 11, 
-				8, 17, 19, 18, 16, 10, 15, 14, 12};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[20] = {2, 3, 7, 6, 0, 1, 5, 4, 9, 18, 12, 
-				19, 14, 11, 15, 13, 8, 16, 17, 10};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 12; }
-  virtual int getNumEdgesRep(){ return 24; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[24][2] = {
-      {0, 8}, {8, 1},
-      {0, 9}, {9, 3},
-      {0, 10}, {10, 4},
-      {1, 11}, {11, 2},
-      {1, 12}, {12, 5},
-      {2, 13}, {13, 3},
-      {2, 14}, {14, 6},
-      {3, 15}, {15, 7},
-      {4, 16}, {16, 5},
-      {4, 17}, {17, 7},
-      {5, 18}, {18, 6},
-      {6, 19}, {19, 7}
-    };
-    static const int f[12] = {0, 0, 1, 0, 1, 0, 3, 2, 1, 2, 3, 4};
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MHexahedron::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 36; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[36][3] = {
-      {0, 9, 8}, {3, 13, 9}, {2, 11, 13}, {1, 8, 11}, {8, 9, 13}, {8, 13, 11},
-      {0, 8, 10}, {1, 12, 8}, {5, 16, 12}, {4, 10, 16}, {8, 12, 16}, {8, 16, 10},
-      {0, 10, 9}, {4, 17, 10}, {7, 15, 17}, {3, 9, 7}, {9, 10, 17}, {9, 17, 15},
-      {1, 11, 12}, {2, 14, 11}, {6, 18, 14}, {5, 12, 18}, {11, 14, 18}, {11, 18, 12},
-      {2, 13, 14}, {3, 15, 13}, {7, 19, 15}, {6, 14, 19}, {13, 15, 19}, {13, 19, 14},
-      {4, 16, 17}, {5, 18, 16}, {6, 19, 18}, {7, 17, 19}, {16, 18, 19}, {16, 19, 17}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(8);
-    MHexahedron::_getFaceVertices(num, v);
-    static const int f[6][4] = {
-      {1,  5,  3, 0},
-      {0,  4,  8, 2},
-      {2,  9,  7, 1},
-      {3,  6, 10, 4},
-      {5,  7, 11, 6},
-      {8, 10, 11, 9}
-    };
-    v[4] = _vs[f[num][0]];
-    v[5] = _vs[f[num][1]];
-    v[6] = _vs[f[num][2]];
-    v[7] = _vs[f[num][3]];
-  }
-  virtual int getTypeForMSH() const { return MSH_HEX_20; }
-  virtual int getTypeForUNV() const { return 116; } // solid parabolic brick
-  //virtual int getTypeForVTK() const { return 25; }
-  virtual const char *getStringForBDF() const { return "CHEXA"; }
-  virtual const char *getStringForDIFF() const { return "ElmB20n3D"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
-    tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
-    MVertex *old[12];
-    for(int i = 0; i < 12; i++) old[i] = _vs[i];
-    _vs[0] = old[3]; _vs[3] = old[0];
-    _vs[1] = old[5]; _vs[5] = old[1];
-    _vs[2] = old[6]; _vs[6] = old[2];
-    _vs[8] = old[10]; _vs[10] = old[8];
-    _vs[9] = old[11]; _vs[11] = old[9];
-  }
-};
-
-/*
- * MHexahedron27
- *
- *   3----13----2
- *   |\         |\
- *   |15    24  | 14
- *   9  \ 20    11 \
- *   |   7----19+---6
- *   |22 |  26  | 23|
- *   0---+-8----1   |
- *    \ 17    25 \  18
- *    10 |  21    12|
- *      \|         \|
- *       4----16----5
- *
- */
-class MHexahedron27 : public MHexahedron {
- protected:
-  MVertex *_vs[19];
- public :
-  MHexahedron27(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-                MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-                MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
-                MVertex *v15, MVertex *v16, MVertex *v17, MVertex *v18, MVertex *v19,
-                MVertex *v20, MVertex *v21, MVertex *v22, MVertex *v23, MVertex *v24,
-                MVertex *v25, MVertex *v26, int num=0, int part=0) 
-    : MHexahedron(v0, v1, v2, v3, v4, v5, v6, v7, num, part)
-  {
-    _vs[0] = v8; _vs[1] = v9; _vs[2] = v10; _vs[3] = v11; _vs[4] = v12; 
-    _vs[5] = v13; _vs[6] = v14; _vs[7] = v15; _vs[8] = v16; _vs[9] = v17; 
-    _vs[10] = v18; _vs[11] = v19; _vs[12] = v20; _vs[13] = v21; _vs[14] = v22;
-    _vs[15] = v23; _vs[16] = v24; _vs[17] = v25; _vs[18] = v26;
-    for(int i = 0; i < 19; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MHexahedron27(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MHexahedron(v, num, part)
-  {
-    for(int i = 0; i < 19; i++) _vs[i] = v[8 + i];
-    for(int i = 0; i < 19; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MHexahedron27(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 27; }
-  virtual MVertex *getVertex(int num){ return num < 8 ? _v[num] : _vs[num - 8]; }
-  virtual MVertex *getVertexDIFF(int num)
-  {
-    static const int map[27] = {6, 8, 26, 24, 0, 2, 20, 18, 7, 15, 3, 17, 5, 25, 
-                                23, 21, 1, 9, 11, 19, 16, 4, 12, 14, 22, 10, 13};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 12; }
-  virtual int getNumFaceVertices() const { return 6; }
-  virtual int getNumVolumeVertices() const { return 1; }
-  virtual int getNumEdgesRep(){ return 24; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[24][2] = {
-      {0, 8}, {8, 1},
-      {0, 9}, {9, 3},
-      {0, 10}, {10, 4},
-      {1, 11}, {11, 2},
-      {1, 12}, {12, 5},
-      {2, 13}, {13, 3},
-      {2, 14}, {14, 6},
-      {3, 15}, {15, 7},
-      {4, 16}, {16, 5},
-      {4, 17}, {17, 7},
-      {5, 18}, {18, 6},
-      {6, 19}, {19, 7}
-    };
-    static const int f[12] = {0, 0, 1, 0, 1, 0, 3, 2, 1, 2, 3, 4};
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MHexahedron::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 48; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[48][3] = {
-      {0, 9, 20}, {0, 20, 8}, {3, 13, 20}, {3, 20, 9}, 
-      {2, 11, 20}, {2, 20, 13}, {1, 8, 20}, {1, 20, 11},
-      {0, 8, 21}, {0, 21, 10}, {1, 12, 21}, {1, 21, 8}, 
-      {5, 16, 21}, {5, 21, 12}, {4, 10, 21}, {4, 21, 16}, 
-      {0, 10, 22}, {0, 22, 9}, {4, 17, 22}, {4, 22, 10}, 
-      {7, 15, 22}, {7, 22, 17}, {3, 9, 22}, {3, 22, 15},  
-      {1, 11, 23}, {1, 23, 12}, {2, 14, 23}, {2, 23, 11}, 
-      {6, 18, 23}, {6, 23, 14}, {5, 12, 23}, {5, 23, 18}, 
-      {2, 13, 24}, {2, 24, 14}, {3, 15, 24}, {3, 24, 13}, 
-      {7, 19, 24}, {7, 24, 15}, {6, 14, 24}, {6, 24, 19}, 
-      {4, 16, 25}, {4, 25, 17}, {5, 18, 25}, {5, 25, 16}, 
-      {6, 19, 25}, {6, 25, 18}, {7, 17, 25}, {7, 25, 19}  
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(9);
-    MHexahedron::_getFaceVertices(num, v);
-    static const int f[6][4] = {
-      {1,  5,  3, 0},
-      {0,  4,  8, 2},
-      {2,  9,  7, 1},
-      {3,  6, 10, 4},
-      {5,  7, 11, 6},
-      {8, 10, 11, 9}
-    };
-    v[4] = _vs[f[num][0]];
-    v[5] = _vs[f[num][1]];
-    v[6] = _vs[f[num][2]];
-    v[7] = _vs[f[num][3]];
-    v[8] = _vs[12+num];
-  }
-  virtual int getTypeForMSH() const { return MSH_HEX_27; }
-  virtual const char *getStringForPOS() const { return "SH2"; }
-  virtual const char *getStringForDIFF() const { return "ElmB27n3D"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
-    tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
-    MVertex *old[19];
-    for(int i = 0; i < 19; i++) old[i] = _vs[i];
-    // edge vertices
-    _vs[0] = old[3]; _vs[3] = old[0];
-    _vs[1] = old[5]; _vs[5] = old[1];
-    _vs[2] = old[6]; _vs[6] = old[2];
-    _vs[8] = old[10]; _vs[10] = old[8];
-    _vs[9] = old[11]; _vs[11] = old[9];
-    // face vertices
-    _vs[13] = old[15]; _vs[15] = old[13];
-    _vs[14] = old[16]; _vs[16] = old[14];
-  }
-};
-
-/*
- * MPrism
- *
- *               w
- *               ^
- *               |
- *               3
- *             ,/|`\
- *           ,/  |  `\
- *         ,/    |    `\
- *        4------+------5
- *        |      |      |
- *        |    ,/|`\    |
- *        |  ,/  |  `\  |
- *        |,/    |    `\|
- *       ,|      |      `\
- *     ,/ |      0      | `\
- *    u   |    ,/ `\    |    v
- *        |  ,/     `\  |
- *        |,/         `\|
- *        1-------------2
- *
- */
-class MPrism : public MElement {
- protected:
-  MVertex *_v[6];
-  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[edges_prism(num, 0)];
-    v[1] = _v[edges_prism(num, 1)];
-  }
-  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[faces_prism(num, 0)];
-    v[1] = _v[faces_prism(num, 1)];
-    v[2] = _v[faces_prism(num, 2)];
-    if(num >= 2) v[3] = _v[faces_prism(num, 3)];
-  }
- public :
-  MPrism(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-         MVertex *v5, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
-    _v[4] = v4; _v[5] = v5; 
-  }
-  MPrism(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 6; i++) _v[i] = v[i];
-  }
-  ~MPrism(){}
-  virtual int getDim(){ return 3; }
-  virtual int getNumVertices() const { return 6; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[6] = {0, 2, 1, 3, 5, 4};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdges(){ return 9; }
-  virtual MEdge getEdge(int num)
-  {
-    return MEdge(_v[edges_prism(num, 0)], _v[edges_prism(num, 1)]);
-  }
-  virtual int getNumEdgesRep(){ return 9; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  {
-    static const int f[9] = {0, 1, 2, 0, 2, 3, 1, 1, 1};
-    MEdge e(getEdge(num));
-    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(num, v);
-  }
-  virtual int getNumFaces(){ return 5; }
-  virtual MFace getFace(int num)
-  {
-    if(num < 2)
-      return MFace(_v[faces_prism(num, 0)],
-                   _v[faces_prism(num, 1)],
-                   _v[faces_prism(num, 2)]);
-    else
-      return MFace(_v[faces_prism(num, 0)],
-                   _v[faces_prism(num, 1)],
-                   _v[faces_prism(num, 2)],
-                   _v[faces_prism(num, 3)]);
-  }
-  virtual int getNumFacesRep(){ return 8; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[8][3] = {
-      {0, 2, 1},
-      {3, 4, 5},
-      {0, 1, 4}, {0, 4, 3},
-      {0, 3, 5}, {0, 5, 2},
-      {1, 2, 5}, {1, 5, 4}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize((num < 2) ? 3 : 4);
-    _getFaceVertices(num, v);
-  }
-  virtual int getTypeForMSH() const { return MSH_PRI_6; }
-  virtual int getTypeForUNV() const { return 112; } // solid linear wedge
-  virtual int getTypeForVTK() const { return 13; }
-  virtual const char *getStringForPOS() const { return "SI"; }
-  virtual const char *getStringForBDF() const { return "CPENTA"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
-    tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
-  }
-  virtual int getVolumeSign();
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
-  {
-    s[0] = (1. - u - v) * (1. - w) * 0.5;
-    s[1] =       u      * (1. - w) * 0.5;
-    s[2] =           v  * (1. - w) * 0.5;
-    s[3] = (1. - u - v) * (1. + w) * 0.5;
-    s[4] =       u      * (1. + w) * 0.5;
-    s[5] =           v  * (1. + w) * 0.5;
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
-  {
-    s[0][0] = -0.5 * (1. - w)    ;
-    s[0][1] = -0.5 * (1. - w)    ;
-    s[0][2] = -0.5 * (1. - u - v);
-    s[1][0] =  0.5 * (1. - w)    ;
-    s[1][1] =  0.                ;
-    s[1][2] = -0.5 * u           ;
-    s[2][0] =  0.                ;
-    s[2][1] =  0.5 * (1. - w)    ;
-    s[2][2] = -0.5 * v           ;
-    s[3][0] = -0.5 * (1. + w)    ;
-    s[3][1] = -0.5 * (1. + w)    ;
-    s[3][2] =  0.5 * (1. - u - v);
-    s[4][0] =  0.5 * (1. + w)    ;
-    s[4][1] =  0.                ;
-    s[4][2] =  0.5 * u           ;
-    s[5][0] =  0.                ;
-    s[5][1] =  0.5 * (1. + w)    ;
-    s[5][2] =  0.5 * v           ;
-  }
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(w > (1. + tol) || w < -(1. + tol) || u < (1. + tol)
-       || v < (1. + tol) || u > ((1. + tol) - v))
-      return false;
-    return true;
-  }
- private:
-  int edges_prism(const int edge, const int vert) const
-  {
-    static const int e[9][2] = {
-      {0, 1},
-      {0, 2},
-      {0, 3},
-      {1, 2},
-      {1, 4},
-      {2, 5},
-      {3, 4},
-      {3, 5},
-      {4, 5}
-    };
-    return e[edge][vert];
-  }
-  int faces_prism(const int face, const int vert) const
-  {
-    static const int f[5][4] = {
-      {0, 2, 1, -1},
-      {3, 4, 5, -1},
-      {0, 1, 4,  3},
-      {0, 3, 5,  2},
-      {1, 2, 5,  4}
-    };
-    return f[face][vert];
-  }
-};
-
-/*
- * MPrism15
- *
- *               3
- *             ,/|`\
- *           12  |  13
- *         ,/    |    `\
- *        4------14-----5
- *        |      8      |
- *        |      |      |
- *        |      |      |
- *        |      |      |
- *        10     |      11
- *        |      0      |
- *        |    ,/ `\    |
- *        |  ,6     `7  |
- *        |,/         `\|
- *        1------9------2
- *
- */
-class MPrism15 : public MPrism {
- protected:
-  MVertex *_vs[9];
- public :
-  MPrism15(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-           MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-           MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
-           int num=0, int part=0) 
-    : MPrism(v0, v1, v2, v3, v4, v5, num, part)
-  {
-    _vs[0] = v6; _vs[1] = v7; _vs[2] = v8; _vs[3] = v9; _vs[4] = v10; 
-    _vs[5] = v11; _vs[6] = v12; _vs[7] = v13; _vs[8] = v14;
-    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MPrism15(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MPrism(v, num, part)
-  {
-    for(int i = 0; i < 9; i++) _vs[i] = v[6 + i];
-    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MPrism15(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 15; }
-  virtual MVertex *getVertex(int num){ return num < 6 ? _v[num] : _vs[num - 6]; }
-  virtual MVertex *getVertexUNV(int num)
-  {
-    static const int map[15] = {0, 6, 1, 9, 2, 7, 8, 10, 11, 3, 12, 4, 14, 5, 13};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexBDF(int num)
-  {
-    static const int map[15] = {0, 1, 2, 3, 4, 5, 6, 9, 7, 8, 10, 11, 12, 14, 13};
-    return getVertex(map[num]); 
-  }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[15] = {0, 2, 1, 3, 5, 4, 7, 9, 6, 13, 14, 12, 8, 11, 10};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 9; }
-  virtual int getNumEdgesRep(){ return 18; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[18][2] = {
-      {0, 6}, {6, 1},
-      {0, 7}, {7, 2},
-      {0, 8}, {8, 3},
-      {1, 9}, {9, 2},
-      {1, 10}, {10, 4},
-      {2, 11}, {11, 5},
-      {3, 12}, {12, 4},
-      {3, 13}, {13, 5},
-      {4, 14}, {14, 5}
-    };
-    static const int f[9] = {0, 1, 2, 0, 2, 3, 1, 1, 1};
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MPrism::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 26; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[26][3] = {
-      {0, 7, 6}, {2, 9, 7}, {1, 6, 9}, {6, 7, 9},
-      {3, 12, 13}, {4, 14, 12}, {5, 13, 14}, {12, 14, 13},
-      {0, 6, 8}, {1, 10, 6}, {4, 12, 10}, {3, 8, 12}, {6, 10, 12}, {6, 12, 8},
-      {0, 8, 7}, {3, 13, 8}, {5, 11, 13}, {2, 7, 11}, {7, 8, 13}, {7, 13, 11},
-      {1, 9, 10}, {2, 11, 9}, {5, 14, 11}, {4, 10, 14}, {9, 11, 14}, {9, 14, 10}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize((num < 2) ? 6 : 8);
-    MPrism::_getFaceVertices(num, v);
-    static const int f[5][4] = {
-      {1, 3, 0, -1},
-      {6, 8, 7, -1},
-      {0, 4, 6,  2},
-      {2, 7, 5,  1},
-      {3, 5, 8,  4}
-    };
-    const int i = (num < 2) ? 3 : 4;
-    v[i  ] = _vs[f[num][0]];
-    v[i+1] = _vs[f[num][1]];
-    v[i+2] = _vs[f[num][2]];
-    if (num >= 2) v[7] = _vs[f[num][3]];
-  }
-  virtual int getTypeForMSH() const { return MSH_PRI_15; }
-  virtual int getTypeForUNV() const { return 113; } // solid parabolic wedge
-  virtual const char *getStringForBDF() const { return "CPENTA"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
-    tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
-    tmp = _vs[1]; _vs[1] = _vs[3]; _vs[3] = tmp;
-    tmp = _vs[2]; _vs[2] = _vs[4]; _vs[4] = tmp;
-    tmp = _vs[7]; _vs[7] = _vs[8]; _vs[8] = tmp;
-  }
-};
-
-/*
- * MPrism18
- *
- *               3
- *             ,/|`\
- *           12  |  13
- *         ,/    |    `\
- *        4------14-----5
- *        |      8      |
- *        |    ,/|`\    |
- *        |  15  |  16  |
- *        |,/    |    `\|
- *        10-----17-----11
- *        |      0      |
- *        |    ,/ `\    |
- *        |  ,6     `7  |
- *        |,/         `\|
- *        1------9------2
- *
- */
-class MPrism18 : public MPrism {
- protected:
-  MVertex *_vs[12];
- public :
-  MPrism18(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-           MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-           MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
-           MVertex *v15, MVertex *v16, MVertex *v17, int num=0, int part=0) 
-    : MPrism(v0, v1, v2, v3, v4, v5, num, part)
-  {
-    _vs[0] = v6; _vs[1] = v7; _vs[2] = v8; _vs[3] = v9; _vs[4] = v10; 
-    _vs[5] = v11; _vs[6] = v12; _vs[7] = v13; _vs[8] = v14; _vs[9] = v15; 
-    _vs[10] = v16; _vs[11] = v17; 
-    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MPrism18(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MPrism(v, num, part)
-  {
-    for(int i = 0; i < 12; i++) _vs[i] = v[6 + i];
-    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MPrism18(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 18; }
-  virtual MVertex *getVertex(int num){ return num < 6 ? _v[num] : _vs[num - 6]; }
-  virtual int getNumEdgeVertices() const { return 9; }
-  virtual int getNumFaceVertices() const { return 3; }
-  virtual int getNumEdgesRep(){ return 18; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[18][2] = {
-      {0, 6}, {6, 1},
-      {0, 7}, {7, 2},
-      {0, 8}, {8, 3},
-      {1, 9}, {9, 2},
-      {1, 10}, {10, 4},
-      {2, 11}, {11, 5},
-      {3, 12}, {12, 4},
-      {3, 13}, {13, 5},
-      {4, 14}, {14, 5}
-    };
-    static const int f[9] = {0, 1, 2, 0, 2, 3, 1, 1, 1};
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MPrism::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 32; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[32][3] = {
-      {0, 7, 6}, {2, 9, 7}, {1, 6, 9}, {6, 7, 9},
-      {3, 12, 13}, {4, 14, 12}, {5, 13, 14}, {12, 14, 13},
-      {0, 6, 15}, {0, 15, 8}, {1, 10, 15}, {1, 15, 6},  
-      {4, 12, 15}, {4, 15, 10}, {3, 8, 15}, {3, 15, 12},  
-      {0, 8, 16}, {0, 16, 7}, {3, 13, 16}, {3, 16, 8},  
-      {5, 11, 16}, {5, 16, 13}, {2, 7, 16}, {2, 16, 11},  
-      {1, 9, 17}, {1, 17, 10}, {2, 11, 17}, {2, 17, 9},  
-      {5, 14, 17}, {5, 17, 11}, {4, 10, 17}, {4, 17, 14}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize((num < 2) ? 6 : 9);
-    MPrism::_getFaceVertices(num, v);
-    static const int f[5][4] = {
-      {1, 3, 0, -1},
-      {6, 8, 7, -1},
-      {0, 4, 6,  2},
-      {2, 7, 5,  1},
-      {3, 5, 8,  4}
-    };
-    const int i = (num < 2) ? 3 : 4;
-    v[i  ] = _vs[f[num][0]];
-    v[i+1] = _vs[f[num][1]];
-    v[i+2] = _vs[f[num][2]];
-    if (num >= 2) {
-      v[7] = _vs[f[num][3]];
-      v[8] = _vs[7+num];
-    }
-  }
-  virtual int getTypeForMSH() const { return MSH_PRI_18; }
-  virtual const char *getStringForPOS() const { return "SI2"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
-    tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
-    // edge vertices
-    tmp = _vs[1]; _vs[1] = _vs[3]; _vs[3] = tmp;
-    tmp = _vs[2]; _vs[2] = _vs[4]; _vs[4] = tmp;
-    tmp = _vs[7]; _vs[7] = _vs[8]; _vs[8] = tmp;
-    // quad face vertices
-    tmp = _vs[10]; _vs[10] = _vs[11]; _vs[11] = tmp;
-  }
-};
-
-/*
- * MPyramid
- *
- *                 4
- *               ,/|\
- *             ,/ .'|\
- *           ,/   | | \
- *         ,/    .' | `.
- *       ,/      |  '.  \
- *     ,/       .' w |   \
- *   ,/         |  ^ |    \
- *  0----------.'--|-3    `. 
- *   `\        |   |  `\    \
- *     `\     .'   +----`\ - \ -> v
- *       `\   |    `\     `\  \
- *         `\.'      `\     `\`
- *            1----------------2
- *                      `\
- *                         u
- *
- */
-class MPyramid : public MElement {
- protected:
-  MVertex *_v[5];
-  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v[0] = _v[edges_pyramid(num, 0)];
-    v[1] = _v[edges_pyramid(num, 1)];
-  }
-  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    if(num < 4) {
-      v[0] = _v[faces_pyramid(num, 0)];
-      v[1] = _v[faces_pyramid(num, 1)];
-      v[2] = _v[faces_pyramid(num, 2)];
-    }
-    else {
-      v[0] = _v[0];
-      v[1] = _v[3];
-      v[2] = _v[2];
-      v[3] = _v[1];
-    }
-  }
- public :
-  MPyramid(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-           int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3; _v[4] = v4;
-  }
-  MPyramid(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MElement(num, part)
-  {
-    for(int i = 0; i < 5; i++) _v[i] = v[i];
-  }
-  ~MPyramid(){}
-  virtual int getDim(){ return 3; }
-  virtual int getNumVertices() const { return 5; }
-  virtual MVertex *getVertex(int num){ return _v[num]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[5] = {0, 3, 2, 1, 4};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdges(){ return 8; }
-  virtual MEdge getEdge(int num)
-  {
-    return MEdge(_v[edges_pyramid(num, 0)], _v[edges_pyramid(num, 1)]);
-  }
-  virtual int getNumEdgesRep(){ return 8; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  {
-    static const int f[8] = {0, 1, 1, 2, 0, 3, 2, 3};
-    MEdge e(getEdge(num));
-    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(2);
-    _getEdgeVertices(num, v);
-  }
-  virtual int getNumFaces(){ return 5; }
-  virtual MFace getFace(int num)
-  {
-    if(num < 4)
-      return MFace(_v[faces_pyramid(num, 0)],
-                   _v[faces_pyramid(num, 1)],
-                   _v[faces_pyramid(num, 2)]);
-    else
-      return MFace(_v[0], _v[3], _v[2], _v[1]);
-  }
-  virtual int getNumFacesRep(){ return 6; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[6][3] = {
-      {0, 1, 4},
-      {3, 0, 4},
-      {1, 2, 4},
-      {2, 3, 4},
-      {0, 3, 2}, {0, 2, 1}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize((num < 4) ? 3 : 4);
-    _getFaceVertices(num, v);
-  }
-  virtual int getTypeForMSH() const { return MSH_PYR_5; }
-  virtual int getTypeForVTK() const { return 14; }
-  virtual const char *getStringForPOS() const { return "SY"; }
-  virtual const char *getStringForBDF() const { return "CPYRAM"; }
-  virtual void revert()
-  {
-    MVertex *tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
-  }
-  virtual int getVolumeSign();
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
-  {
-    double r = (w != 1.) ? (u * v * w / (1. - w)) : 0.;
-    s[0] = 0.25 * ((1. - u) * (1. - v) - w + r);
-    s[1] = 0.25 * ((1. + u) * (1. - v) - w - r);
-    s[2] = 0.25 * ((1. + u) * (1. + v) - w + r);
-    s[3] = 0.25 * ((1. - u) * (1. + v) - w - r);
-    s[4] = w;
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
-  {
-    if(w == 1.) {
-      s[0][0] = -0.25 ; 
-      s[0][1] = -0.25 ;
-      s[0][2] = -0.25 ; 
-      s[1][0] =  0.25 ; 
-      s[1][1] = -0.25 ;
-      s[1][2] = -0.25 ; 
-      s[2][0] =  0.25 ; 
-      s[2][1] =  0.25 ;
-      s[2][2] = -0.25 ; 
-      s[3][0] = -0.25 ; 
-      s[3][1] =  0.25 ;
-      s[3][2] = -0.25 ; 
-    }
-    else{
-      s[0][0] = 0.25 * ( -(1. - v) + v * w / (1. - w)) ;
-      s[0][1] = 0.25 * ( -(1. - u) + u * w / (1. - w)) ;
-      s[0][2] = 0.25 * ( -1.     + u * v / (1. - w) + u * v * w / (1. - w) / (1. - w)) ; 
-      s[1][0] = 0.25 * (  (1. - v) - v * w / (1. - w)) ;
-      s[1][1] = 0.25 * ( -(1. + u) - u * w / (1. - w)) ;
-      s[1][2] = 0.25 * ( -1.     - u * v / (1. - w) - u * v * w / (1. - w) / (1. - w)) ; 
-      s[2][0] = 0.25 * (  (1. + v) + v * w / (1. - w)) ;
-      s[2][1] = 0.25 * (  (1. + u) + u * w / (1. - w)) ;
-      s[2][2] = 0.25 * ( -1.     + u * v / (1. - w) + u * v * w / (1. - w) / (1. - w)) ; 
-      s[3][0] = 0.25 * ( -(1. + v) - v * w / (1. - w)) ;
-      s[3][1] = 0.25 * (  (1. - u) - u * w / (1. - w)) ;
-      s[3][2] = 0.25 * ( -1.     - u * v / (1. - w) - u * v * w / (1. - w) / (1. - w)) ; 
-    }
-    s[4][0] = 0.; 
-    s[4][1] = 0.;
-    s[4][2] = 1.;
-  }
-  virtual bool isInside(double u, double v, double w)
-  {
-    double tol = _isInsideTolerance;
-    if(u < (w - (1. + tol)) || u > ((1. + tol) - w) || v < (w - (1. + tol)) ||
-       v > ((1. + tol) - w) || w < (-tol) || w > (1. + tol))
-      return false;
-    return true;
-  }
- private:
-  int edges_pyramid(const int edge, const int vert) const
-  {
-    static const int e[8][2] = {
-      {0, 1},
-      {0, 3},
-      {0, 4},
-      {1, 2},
-      {1, 4},
-      {2, 3},
-      {2, 4},
-      {3, 4}
-    };
-    return e[edge][vert];
-  }
-  int faces_pyramid(const int face, const int vert) const
-  {
-    // only triangular faces
-    static const int f[4][3] = {
-      {0, 1, 4},
-      {3, 0, 4},
-      {1, 2, 4},
-      {2, 3, 4}
-    };
-    return f[face][vert];
-  }
-};
-
-/*
- * MPyramid13
- *
- *                 4
- *               ,/|\
- *             ,/ .'|\
- *           ,/   | | \
- *         ,/    .' | `.
- *       ,7      |  12  \
- *     ,/       .'   |   \
- *   ,/         9    |    11
- *  0--------6-.'----3    `. 
- *   `\        |      `\    \
- *     `5     .'        10   \ 
- *       `\   |           `\  \
- *         `\.'             `\`
- *            1--------8-------2
- *                        
- */
-class MPyramid13 : public MPyramid {
- protected:
-  MVertex *_vs[8];
- public :
-  MPyramid13(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-             MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-             MVertex *v10, MVertex *v11, MVertex *v12, int num=0, int part=0) 
-    : MPyramid(v0, v1, v2, v3, v4, num, part)
-  {
-    _vs[0] = v5; _vs[1] = v6; _vs[2] = v7; _vs[3] = v8; _vs[4] = v9; 
-    _vs[5] = v10; _vs[6] = v11; _vs[7] = v12;
-    for(int i = 0; i < 8; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  MPyramid13(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MPyramid(v, num, part)
-  {
-    for(int i = 0; i < 8; i++) _vs[i] = v[5 + i];
-    for(int i = 0; i < 8; i++) _vs[i]->setPolynomialOrder(2);
-  }
-  ~MPyramid13(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 13; }
-  virtual MVertex *getVertex(int num){ return num < 5 ? _v[num] : _vs[num - 5]; }
-  virtual MVertex *getVertexMED(int num)
-  {
-    static const int map[13] = {0, 3, 2, 1, 4, 6, 10, 8, 5, 7, 12, 11, 9};
-    return getVertex(map[num]); 
-  }
-  virtual int getNumEdgeVertices() const { return 8; }
-  virtual int getNumEdgesRep(){ return 16; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[16][2] = {
-      {0, 5}, {5, 1},
-      {0, 6}, {6, 3},
-      {0, 7}, {7, 4},
-      {1, 8}, {8, 2},
-      {1, 9}, {9, 4},
-      {2, 10}, {10, 3},
-      {2, 11}, {11, 4},
-      {3, 12}, {12, 4}
-    };
-    static const int f[8] = {0, 1, 1, 2, 0, 3, 2, 3};
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MPyramid::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 22; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[22][3] = {
-      {0, 5, 7}, {1, 9, 5}, {4, 7, 9}, {5, 9, 7},
-      {3, 6, 12}, {0, 7, 6}, {4, 12, 7}, {6, 7, 12},
-      {1, 8, 9}, {2, 11, 8}, {4, 9, 11}, {8, 11, 9},
-      {2, 10, 11}, {3, 12, 10}, {4, 11, 12}, {10, 12, 11},
-      {0, 6, 5}, {3, 10, 6}, {2, 8, 10}, {1, 5, 8}, {5, 6, 10}, {5, 10, 8}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize((num < 4) ? 6 : 8);
-    MPyramid::_getFaceVertices(num, v);
-    static const int f[4][3] = {
-      {0, 4, 2},
-      {1, 2, 7},
-      {3, 6, 4},
-      {5, 7, 6}
-    };
-    if(num < 4) {
-      v[3] = _vs[f[num][0]];
-      v[4] = _vs[f[num][1]];
-      v[5] = _vs[f[num][2]];
-    }
-    else {
-      v[4] = _vs[1];
-      v[5] = _vs[5];
-      v[6] = _vs[3];
-      v[7] = _vs[0];
-    }
-  }
-  virtual int getTypeForMSH() const { return MSH_PYR_13; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
-    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
-    tmp = _vs[1]; _vs[1] = _vs[5]; _vs[5] = tmp;
-    tmp = _vs[2]; _vs[2] = _vs[6]; _vs[6] = tmp;
-  }
-};
-
-/*
- * MPyramid14
- *
- *                 4
- *               ,/|\
- *             ,/ .'|\
- *           ,/   | | \
- *         ,/    .' | `.
- *       ,7      |  12  \
- *     ,/       .'   |   \
- *   ,/         9    |    11
- *  0--------6-.'----3    `. 
- *   `\        |      `\    \
- *     `5     .' 13     10   \ 
- *       `\   |           `\  \
- *         `\.'             `\`
- *            1--------8-------2
- *
- */
-class MPyramid14 : public MPyramid {
- protected:
-  MVertex *_vs[9];
- public :
-  MPyramid14(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
-             MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
-             MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, 
-             int num=0, int part=0) 
-    : MPyramid(v0, v1, v2, v3, v4, num, part)
-  {
-    _vs[0] = v5; _vs[1] = v6; _vs[2] = v7; _vs[3] = v8; _vs[4] = v9; 
-    _vs[5] = v10; _vs[6] = v11; _vs[7] = v12; _vs[8] = v13; 
-    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);   
-  }
-  MPyramid14(std::vector<MVertex*> &v, int num=0, int part=0) 
-    : MPyramid(v, num, part)
-  {
-    for(int i = 0; i < 9; i++) _vs[i] = v[5 + i];
-    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);   
-  }
-  ~MPyramid14(){}
-  virtual int getPolynomialOrder() const { return 2; }
-  virtual int getNumVertices() const { return 14; }
-  virtual MVertex *getVertex(int num){ return num < 5 ? _v[num] : _vs[num - 5]; }
-  virtual int getNumEdgeVertices() const { return 8; }
-  virtual int getNumFaceVertices() const { return 1; }
-  virtual int getNumEdgesRep(){ return 16; }
-  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int e[16][2] = {
-      {0, 5}, {5, 1},
-      {0, 6}, {6, 3},
-      {0, 7}, {7, 4},
-      {1, 8}, {8, 2},
-      {1, 9}, {9, 4},
-      {2, 10}, {10, 3},
-      {2, 11}, {11, 4},
-      {3, 12}, {12, 4}
-    };
-    static const int f[8] = {0, 1, 1, 2, 0, 3, 2, 3};
-    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
-  }
-  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize(3);
-    MPyramid::_getEdgeVertices(num, v);
-    v[2] = _vs[num];
-  }
-  virtual int getNumFacesRep(){ return 24; }
-  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
-  { 
-    static const int f[24][3] = {
-      {0, 5, 7}, {1, 9, 5}, {4, 7, 9}, {5, 9, 7},
-      {3, 6, 12}, {0, 7, 6}, {4, 12, 7}, {6, 7, 12},
-      {1, 8, 9}, {2, 11, 8}, {4, 9, 11}, {8, 11, 9},
-      {2, 10, 11}, {3, 12, 10}, {4, 11, 12}, {10, 12, 11},
-      {0, 6, 13}, {0, 13, 5}, {3, 10, 13}, {3, 13, 6}, 
-      {2, 8, 13}, {2, 13, 10}, {1, 5, 13}, {1, 13, 8}
-    };
-    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
-                x, y, z, n);
-  }
-  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
-  {
-    v.resize((num < 4) ? 6 : 9);
-    MPyramid::_getFaceVertices(num, v);
-    static const int f[4][3] = {
-      {0, 4, 2},
-      {1, 2, 7},
-      {3, 6, 4},
-      {5, 7, 6}
-    };
-    if(num < 4) {
-      v[3] = _vs[f[num][0]];
-      v[4] = _vs[f[num][1]];
-      v[5] = _vs[f[num][2]];
-    }
-    else {
-      v[4] = _vs[1];
-      v[5] = _vs[5];
-      v[6] = _vs[3];
-      v[7] = _vs[0];
-      v[8] = _vs[8];
-    }
-  }
-  virtual int getTypeForMSH() const { return MSH_PYR_14; }
-  virtual const char *getStringForPOS() const { return "SY2"; }
-  virtual void revert()
-  {
-    MVertex *tmp;
-    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
-    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
-    tmp = _vs[1]; _vs[1] = _vs[5]; _vs[5] = tmp;
-    tmp = _vs[2]; _vs[2] = _vs[6]; _vs[6] = tmp;
-  }
-};
-
-template <class T> 
-void sort3(T *t[3])
-{
-  T *temp;
-  if(t[0] > t[1]){
-    temp = t[1];
-    t[1] = t[0];
-    t[0] = temp;
-  }
-  if(t[1] > t[2]){
-    temp = t[2];
-    t[2] = t[1];
-    t[1] = temp;
-  }
-  if(t[0] > t[1]){
-    temp = t[1];
-    t[1] = t[0];
-    t[0] = temp;
-  }
-}
-
-struct compareMTriangleLexicographic
-{
-  bool operator () (MTriangle *t1, MTriangle *t2) const
-  {
-    MVertex *_v1[3] = {t1->getVertex(0), t1->getVertex(1), t1->getVertex(2)};
-    MVertex *_v2[3] = {t2->getVertex(0), t2->getVertex(1), t2->getVertex(2)};
-    sort3(_v1);
-    sort3(_v2);
-    if(_v1[0] < _v2[0]) return true;
-    if(_v1[0] > _v2[0]) return false;
-    if(_v1[1] < _v2[1]) return true;
-    if(_v1[1] > _v2[1]) return false;
-    if(_v1[2] < _v2[2]) return true;
-    return false;
-  }
-};
-
 // Traits of various elements based on the dimension.  These generally define
 // the faces of 2-D elements as MEdge and 3-D elements as MFace.
 
diff --git a/Geo/MHexahedron.cpp b/Geo/MHexahedron.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..20ccc3916213888e046c9769f87dbe51b9c9a63e
--- /dev/null
+++ b/Geo/MHexahedron.cpp
@@ -0,0 +1,30 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MHexahedron.h"
+#include "Numeric.h"
+
+int MHexahedron::getVolumeSign()
+{ 
+  double mat[3][3];
+  mat[0][0] = _v[1]->x() - _v[0]->x();
+  mat[0][1] = _v[3]->x() - _v[0]->x();
+  mat[0][2] = _v[4]->x() - _v[0]->x();
+  mat[1][0] = _v[1]->y() - _v[0]->y();
+  mat[1][1] = _v[3]->y() - _v[0]->y();
+  mat[1][2] = _v[4]->y() - _v[0]->y();
+  mat[2][0] = _v[1]->z() - _v[0]->z();
+  mat[2][1] = _v[3]->z() - _v[0]->z();
+  mat[2][2] = _v[4]->z() - _v[0]->z();
+  return sign(det3x3(mat));
+}
+
+void MHexahedron::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
+{
+#if !defined(HAVE_GMSH_EMBEDDED)
+  *npts = getNGQHPts(pOrder);
+  *pts = getGQHPts(pOrder);
+#endif
+}
diff --git a/Geo/MHexahedron.h b/Geo/MHexahedron.h
new file mode 100644
index 0000000000000000000000000000000000000000..e614f6d3c066ee402e53fa15650b66bbe410ca4c
--- /dev/null
+++ b/Geo/MHexahedron.h
@@ -0,0 +1,490 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MHEXAHEDRON_H_
+#define _MHEXAHEDRON_H_
+
+#include "MElement.h"
+
+/*
+ * MHexahedron
+ *
+ *          v
+ *   3----------2
+ *   |\     ^   |\
+ *   | \    |   | \
+ *   |  \   |   |  \
+ *   |   7------+---6
+ *   |   |  +-- |-- | -> u
+ *   0---+---\--1   | 
+ *    \  |    \  \  |
+ *     \ |     \  \ |
+ *      \|      w  \|
+ *       4----------5
+ *
+ */
+class MHexahedron : public MElement {
+ protected:
+  MVertex *_v[8];
+  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[edges_hexa(num, 0)];
+    v[1] = _v[edges_hexa(num, 1)];
+  }
+  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[faces_hexa(num, 0)];
+    v[1] = _v[faces_hexa(num, 1)];
+    v[2] = _v[faces_hexa(num, 2)];
+    v[3] = _v[faces_hexa(num, 3)];
+  }
+ public :
+  MHexahedron(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+              MVertex *v5, MVertex *v6, MVertex *v7, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
+    _v[4] = v4; _v[5] = v5; _v[6] = v6; _v[7] = v7;
+  }
+  MHexahedron(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 8; i++) _v[i] = v[i];
+  }
+  ~MHexahedron(){}
+  virtual int getDim(){ return 3; }
+  virtual int getNumVertices() const { return 8; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[8] = {0, 3, 2, 1, 4, 7, 6, 5};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[8] = {2, 3, 7, 6, 0, 1, 5, 4};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdges(){ return 12; }
+  virtual MEdge getEdge(int num)
+  {
+    return MEdge(_v[edges_hexa(num, 0)], _v[edges_hexa(num, 1)]);
+  }
+  virtual int getNumEdgesRep(){ return 12; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  {
+    static const int f[12] = {0, 0, 1, 0, 1, 0, 3, 2, 1, 2, 3, 4};
+    MEdge e(getEdge(num));
+    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(num, v);
+  }
+  virtual int getNumFaces(){ return 6; }
+  virtual MFace getFace(int num)
+  {
+    return MFace(_v[faces_hexa(num, 0)],
+		 _v[faces_hexa(num, 1)],
+		 _v[faces_hexa(num, 2)],
+		 _v[faces_hexa(num, 3)]);
+  }
+  virtual int getNumFacesRep(){ return 12; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[12][3] = {
+      {0, 3, 2}, {0, 2, 1},
+      {0, 1, 5}, {0, 5, 4},
+      {0, 4, 7}, {0, 7, 3},
+      {1, 2, 6}, {1, 6, 5},
+      {2, 3, 7}, {2, 7, 6},
+      {4, 5, 6}, {4, 6, 7}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(4);
+    _getFaceVertices(num, v);
+  }
+  virtual int getTypeForMSH() const { return MSH_HEX_8; }
+  virtual int getTypeForUNV() const { return 115; } // solid linear brick
+  virtual int getTypeForVTK() const { return 12; }
+  virtual const char *getStringForPOS() const { return "SH"; }
+  virtual const char *getStringForBDF() const { return "CHEXA"; }
+  virtual const char *getStringForDIFF() const { return "ElmB8n3D"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
+    tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
+  }
+  virtual int getVolumeSign();
+  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
+  {
+    s[0] = (1. - u) * (1. - v) * (1. - w) * 0.125;
+    s[1] = (1. + u) * (1. - v) * (1. - w) * 0.125;
+    s[2] = (1. + u) * (1. + v) * (1. - w) * 0.125;
+    s[3] = (1. - u) * (1. + v) * (1. - w) * 0.125;
+    s[4] = (1. - u) * (1. - v) * (1. + w) * 0.125;
+    s[5] = (1. + u) * (1. - v) * (1. + w) * 0.125;
+    s[6] = (1. + u) * (1. + v) * (1. + w) * 0.125;
+    s[7] = (1. - u) * (1. + v) * (1. + w) * 0.125;
+  }
+  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
+  {
+    s[0][0] = -0.125 * (1. - v) * (1. - w);
+    s[0][1] = -0.125 * (1. - u) * (1. - w);
+    s[0][2] = -0.125 * (1. - u) * (1. - v);
+    s[1][0] =  0.125 * (1. - v) * (1. - w);
+    s[1][1] = -0.125 * (1. + u) * (1. - w);
+    s[1][2] = -0.125 * (1. + u) * (1. - v);
+    s[2][0] =  0.125 * (1. + v) * (1. - w);
+    s[2][1] =  0.125 * (1. + u) * (1. - w);
+    s[2][2] = -0.125 * (1. + u) * (1. + v);
+    s[3][0] = -0.125 * (1. + v) * (1. - w);
+    s[3][1] =  0.125 * (1. - u) * (1. - w);
+    s[3][2] = -0.125 * (1. - u) * (1. + v);
+    s[4][0] = -0.125 * (1. - v) * (1. + w);
+    s[4][1] = -0.125 * (1. - u) * (1. + w);
+    s[4][2] =  0.125 * (1. - u) * (1. - v);
+    s[5][0] =  0.125 * (1. - v) * (1. + w);
+    s[5][1] = -0.125 * (1. + u) * (1. + w);
+    s[5][2] =  0.125 * (1. + u) * (1. - v);
+    s[6][0] =  0.125 * (1. + v) * (1. + w);
+    s[6][1] =  0.125 * (1. + u) * (1. + w);
+    s[6][2] =  0.125 * (1. + u) * (1. + v);
+    s[7][0] = -0.125 * (1. + v) * (1. + w);
+    s[7][1] =  0.125 * (1. - u) * (1. + w);
+    s[7][2] =  0.125 * (1. - u) * (1. + v);
+  }
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(u < -(1. + tol) || v < -(1. + tol) || w < -(1. + tol) || 
+       u > (1. + tol) || v > (1. + tol) || w > (1. + tol))
+      return false;
+    return true;
+  }
+  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
+ private:
+  int edges_hexa(const int edge, const int vert) const
+  {
+    static const int e[12][2] = {
+      {0, 1},
+      {0, 3},
+      {0, 4},
+      {1, 2},
+      {1, 5},
+      {2, 3},
+      {2, 6},
+      {3, 7},
+      {4, 5},
+      {4, 7},
+      {5, 6},
+      {6, 7}
+    };
+    return e[edge][vert];
+  }
+  int faces_hexa(const int face, const int vert) const
+  {
+    static const int f[6][4] = {
+      {0, 3, 2, 1},
+      {0, 1, 5, 4},
+      {0, 4, 7, 3},
+      {1, 2, 6, 5},
+      {2, 3, 7, 6},
+      {4, 5, 6, 7}
+    };
+    return f[face][vert];
+  }
+};
+
+/*
+ * MHexahedron20
+ *
+ *   3----13----2
+ *   |\         |\
+ *   | 15       | 14
+ *   9  \       11 \
+ *   |   7----19+---6
+ *   |   |      |   |
+ *   0---+-8----1   | 
+ *    \  17      \  18
+ *    10 |        12|
+ *      \|         \|
+ *       4----16----5
+ *
+ */
+class MHexahedron20 : public MHexahedron {
+ protected:
+  MVertex *_vs[12];
+ public :
+  MHexahedron20(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+                MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+                MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
+                MVertex *v15, MVertex *v16, MVertex *v17, MVertex *v18, MVertex *v19,
+                int num=0, int part=0) 
+    : MHexahedron(v0, v1, v2, v3, v4, v5, v6, v7, num, part)
+  {
+    _vs[0] = v8; _vs[1] = v9; _vs[2] = v10; _vs[3] = v11; _vs[4] = v12; 
+    _vs[5] = v13; _vs[6] = v14; _vs[7] = v15; _vs[8] = v16; _vs[9] = v17; 
+    _vs[10] = v18; _vs[11] = v19; 
+    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MHexahedron20(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MHexahedron(v, num, part)
+  {
+    for(int i = 0; i < 12; i++) _vs[i] = v[8 + i];
+    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MHexahedron20(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 20; }
+  virtual MVertex *getVertex(int num){ return num < 8 ? _v[num] : _vs[num - 8]; }
+  virtual MVertex *getVertexUNV(int num)
+  {
+    static const int map[20] = {0, 8, 1, 11, 2, 13, 3, 9, 10, 12, 
+                                14, 15, 4, 16, 5, 18, 6, 19, 7, 17};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexBDF(int num)
+  {
+    static const int map[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 13, 
+                                9, 10, 12, 14, 15, 16, 18, 19, 17};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[20] = {0, 3, 2, 1, 4, 7, 6, 5, 9, 13, 11, 
+				8, 17, 19, 18, 16, 10, 15, 14, 12};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[20] = {2, 3, 7, 6, 0, 1, 5, 4, 9, 18, 12, 
+				19, 14, 11, 15, 13, 8, 16, 17, 10};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 12; }
+  virtual int getNumEdgesRep(){ return 24; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[24][2] = {
+      {0, 8}, {8, 1},
+      {0, 9}, {9, 3},
+      {0, 10}, {10, 4},
+      {1, 11}, {11, 2},
+      {1, 12}, {12, 5},
+      {2, 13}, {13, 3},
+      {2, 14}, {14, 6},
+      {3, 15}, {15, 7},
+      {4, 16}, {16, 5},
+      {4, 17}, {17, 7},
+      {5, 18}, {18, 6},
+      {6, 19}, {19, 7}
+    };
+    static const int f[12] = {0, 0, 1, 0, 1, 0, 3, 2, 1, 2, 3, 4};
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MHexahedron::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 36; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[36][3] = {
+      {0, 9, 8}, {3, 13, 9}, {2, 11, 13}, {1, 8, 11}, {8, 9, 13}, {8, 13, 11},
+      {0, 8, 10}, {1, 12, 8}, {5, 16, 12}, {4, 10, 16}, {8, 12, 16}, {8, 16, 10},
+      {0, 10, 9}, {4, 17, 10}, {7, 15, 17}, {3, 9, 7}, {9, 10, 17}, {9, 17, 15},
+      {1, 11, 12}, {2, 14, 11}, {6, 18, 14}, {5, 12, 18}, {11, 14, 18}, {11, 18, 12},
+      {2, 13, 14}, {3, 15, 13}, {7, 19, 15}, {6, 14, 19}, {13, 15, 19}, {13, 19, 14},
+      {4, 16, 17}, {5, 18, 16}, {6, 19, 18}, {7, 17, 19}, {16, 18, 19}, {16, 19, 17}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(8);
+    MHexahedron::_getFaceVertices(num, v);
+    static const int f[6][4] = {
+      {1,  5,  3, 0},
+      {0,  4,  8, 2},
+      {2,  9,  7, 1},
+      {3,  6, 10, 4},
+      {5,  7, 11, 6},
+      {8, 10, 11, 9}
+    };
+    v[4] = _vs[f[num][0]];
+    v[5] = _vs[f[num][1]];
+    v[6] = _vs[f[num][2]];
+    v[7] = _vs[f[num][3]];
+  }
+  virtual int getTypeForMSH() const { return MSH_HEX_20; }
+  virtual int getTypeForUNV() const { return 116; } // solid parabolic brick
+  //virtual int getTypeForVTK() const { return 25; }
+  virtual const char *getStringForBDF() const { return "CHEXA"; }
+  virtual const char *getStringForDIFF() const { return "ElmB20n3D"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
+    tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
+    MVertex *old[12];
+    for(int i = 0; i < 12; i++) old[i] = _vs[i];
+    _vs[0] = old[3]; _vs[3] = old[0];
+    _vs[1] = old[5]; _vs[5] = old[1];
+    _vs[2] = old[6]; _vs[6] = old[2];
+    _vs[8] = old[10]; _vs[10] = old[8];
+    _vs[9] = old[11]; _vs[11] = old[9];
+  }
+};
+
+/*
+ * MHexahedron27
+ *
+ *   3----13----2
+ *   |\         |\
+ *   |15    24  | 14
+ *   9  \ 20    11 \
+ *   |   7----19+---6
+ *   |22 |  26  | 23|
+ *   0---+-8----1   |
+ *    \ 17    25 \  18
+ *    10 |  21    12|
+ *      \|         \|
+ *       4----16----5
+ *
+ */
+class MHexahedron27 : public MHexahedron {
+ protected:
+  MVertex *_vs[19];
+ public :
+  MHexahedron27(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+                MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+                MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
+                MVertex *v15, MVertex *v16, MVertex *v17, MVertex *v18, MVertex *v19,
+                MVertex *v20, MVertex *v21, MVertex *v22, MVertex *v23, MVertex *v24,
+                MVertex *v25, MVertex *v26, int num=0, int part=0) 
+    : MHexahedron(v0, v1, v2, v3, v4, v5, v6, v7, num, part)
+  {
+    _vs[0] = v8; _vs[1] = v9; _vs[2] = v10; _vs[3] = v11; _vs[4] = v12; 
+    _vs[5] = v13; _vs[6] = v14; _vs[7] = v15; _vs[8] = v16; _vs[9] = v17; 
+    _vs[10] = v18; _vs[11] = v19; _vs[12] = v20; _vs[13] = v21; _vs[14] = v22;
+    _vs[15] = v23; _vs[16] = v24; _vs[17] = v25; _vs[18] = v26;
+    for(int i = 0; i < 19; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MHexahedron27(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MHexahedron(v, num, part)
+  {
+    for(int i = 0; i < 19; i++) _vs[i] = v[8 + i];
+    for(int i = 0; i < 19; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MHexahedron27(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 27; }
+  virtual MVertex *getVertex(int num){ return num < 8 ? _v[num] : _vs[num - 8]; }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[27] = {6, 8, 26, 24, 0, 2, 20, 18, 7, 15, 3, 17, 5, 25, 
+                                23, 21, 1, 9, 11, 19, 16, 4, 12, 14, 22, 10, 13};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 12; }
+  virtual int getNumFaceVertices() const { return 6; }
+  virtual int getNumVolumeVertices() const { return 1; }
+  virtual int getNumEdgesRep(){ return 24; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[24][2] = {
+      {0, 8}, {8, 1},
+      {0, 9}, {9, 3},
+      {0, 10}, {10, 4},
+      {1, 11}, {11, 2},
+      {1, 12}, {12, 5},
+      {2, 13}, {13, 3},
+      {2, 14}, {14, 6},
+      {3, 15}, {15, 7},
+      {4, 16}, {16, 5},
+      {4, 17}, {17, 7},
+      {5, 18}, {18, 6},
+      {6, 19}, {19, 7}
+    };
+    static const int f[12] = {0, 0, 1, 0, 1, 0, 3, 2, 1, 2, 3, 4};
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MHexahedron::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 48; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[48][3] = {
+      {0, 9, 20}, {0, 20, 8}, {3, 13, 20}, {3, 20, 9}, 
+      {2, 11, 20}, {2, 20, 13}, {1, 8, 20}, {1, 20, 11},
+      {0, 8, 21}, {0, 21, 10}, {1, 12, 21}, {1, 21, 8}, 
+      {5, 16, 21}, {5, 21, 12}, {4, 10, 21}, {4, 21, 16}, 
+      {0, 10, 22}, {0, 22, 9}, {4, 17, 22}, {4, 22, 10}, 
+      {7, 15, 22}, {7, 22, 17}, {3, 9, 22}, {3, 22, 15},  
+      {1, 11, 23}, {1, 23, 12}, {2, 14, 23}, {2, 23, 11}, 
+      {6, 18, 23}, {6, 23, 14}, {5, 12, 23}, {5, 23, 18}, 
+      {2, 13, 24}, {2, 24, 14}, {3, 15, 24}, {3, 24, 13}, 
+      {7, 19, 24}, {7, 24, 15}, {6, 14, 24}, {6, 24, 19}, 
+      {4, 16, 25}, {4, 25, 17}, {5, 18, 25}, {5, 25, 16}, 
+      {6, 19, 25}, {6, 25, 18}, {7, 17, 25}, {7, 25, 19}  
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(9);
+    MHexahedron::_getFaceVertices(num, v);
+    static const int f[6][4] = {
+      {1,  5,  3, 0},
+      {0,  4,  8, 2},
+      {2,  9,  7, 1},
+      {3,  6, 10, 4},
+      {5,  7, 11, 6},
+      {8, 10, 11, 9}
+    };
+    v[4] = _vs[f[num][0]];
+    v[5] = _vs[f[num][1]];
+    v[6] = _vs[f[num][2]];
+    v[7] = _vs[f[num][3]];
+    v[8] = _vs[12+num];
+  }
+  virtual int getTypeForMSH() const { return MSH_HEX_27; }
+  virtual const char *getStringForPOS() const { return "SH2"; }
+  virtual const char *getStringForDIFF() const { return "ElmB27n3D"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
+    tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
+    MVertex *old[19];
+    for(int i = 0; i < 19; i++) old[i] = _vs[i];
+    // edge vertices
+    _vs[0] = old[3]; _vs[3] = old[0];
+    _vs[1] = old[5]; _vs[5] = old[1];
+    _vs[2] = old[6]; _vs[6] = old[2];
+    _vs[8] = old[10]; _vs[10] = old[8];
+    _vs[9] = old[11]; _vs[11] = old[9];
+    // face vertices
+    _vs[13] = old[15]; _vs[15] = old[13];
+    _vs[14] = old[16]; _vs[16] = old[14];
+  }
+};
+
+#endif
diff --git a/Geo/MLine.cpp b/Geo/MLine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5205a683889313c4da160ecc268f7740e59e20a
--- /dev/null
+++ b/Geo/MLine.cpp
@@ -0,0 +1,47 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MLine.h"
+
+#if defined(HAVE_GMSH_EMBEDDED)
+#include "GmshEmbedded.h"
+#else
+#include "GaussLegendre1D.h"
+#include "Context.h"
+#include "qualityMeasures.h"
+#endif
+
+const gmshFunctionSpace* MLine::getFunctionSpace(int o) const
+{
+  int order = (o == -1) ? getPolynomialOrder() : o;
+  
+  switch (order) {
+  case 1: return &gmshFunctionSpaces::find(MSH_LIN_2);
+  case 2: return &gmshFunctionSpaces::find(MSH_LIN_3);
+  case 3: return &gmshFunctionSpaces::find(MSH_LIN_4);
+  case 4: return &gmshFunctionSpaces::find(MSH_LIN_5);
+  case 5: return &gmshFunctionSpaces::find(MSH_LIN_6);
+  default: Msg::Error("Order %d line function space not implemented", order);
+  }
+  return 0;
+}
+
+void MLine::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
+{
+#if !defined(HAVE_GMSH_EMBEDDED)
+  static IntPt GQL[100]; 
+  double *t, *w;
+  int nbP = pOrder / 2 + 1;
+  gmshGaussLegendre1D(nbP, &t, &w);
+  for (int i = 0; i < nbP; i++){
+    GQL[i].pt[0] = t[i];
+    GQL[i].pt[1] = 0;
+    GQL[i].pt[2] = 0;
+    GQL[i].weight = w[i];
+  }
+  *npts = nbP;
+  *pts = GQL;
+#endif
+}
diff --git a/Geo/MLine.h b/Geo/MLine.h
new file mode 100644
index 0000000000000000000000000000000000000000..15e53a4578b089bf694539a3a011b96cb5b93b2a
--- /dev/null
+++ b/Geo/MLine.h
@@ -0,0 +1,179 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MLINE_H_
+#define _MLINE_H_
+
+#include "MElement.h"
+
+/*
+ * MLine
+ *
+ *   0----------1 --> u
+ *
+ */
+class MLine : public MElement {
+ protected:
+  MVertex *_v[2];
+  void _getEdgeVertices(std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[0];
+    v[1] = _v[1];
+  }
+ public :
+  MLine(MVertex *v0, MVertex *v1, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1;
+  }
+  MLine(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 2; i++) _v[i] = v[i];
+  }
+  ~MLine(){}
+  virtual int getDim(){ return 1; }
+  virtual int getNumVertices() const { return 2; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual int getNumEdges(){ return 1; }
+  virtual MEdge getEdge(int num){ return MEdge(_v[0], _v[1]); }
+  virtual int getNumEdgesRep(){ return 1; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    _getEdgeRep(_v[0], _v[1], x, y, z, n);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(v);
+  }
+  virtual int getNumFaces(){ return 0; }
+  virtual MFace getFace(int num){ return MFace(); }
+  virtual int getNumFacesRep(){ return 0; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n){}
+  virtual int getTypeForMSH() const { return MSH_LIN_2; }
+  virtual int getTypeForUNV() const { return 21; } // linear beam
+  virtual int getTypeForVTK() const { return 3; }
+  virtual const char *getStringForPOS() const { return "SL"; }
+  virtual const char *getStringForBDF() const { return "CBAR"; }
+  virtual void revert() 
+  {
+    MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
+  }
+  virtual const gmshFunctionSpace* getFunctionSpace(int o=-1) const;
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(u < -(1. + tol) || u > (1. + tol))
+      return false;
+    return true;
+  }
+  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
+};
+
+/*
+ * MLine3
+ *
+ *   0-----2----1
+ *
+ */
+class MLine3 : public MLine {
+ protected:
+  MVertex *_vs[1];
+ public :
+  MLine3(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
+    : MLine(v0, v1, num, part)
+  {
+    _vs[0] = v2;
+    _vs[0]->setPolynomialOrder(2);
+  }
+  MLine3(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MLine(v, num, part)
+  {
+    _vs[0] = v[2];
+    _vs[0]->setPolynomialOrder(2);
+  }
+  ~MLine3(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 3; }
+  virtual MVertex *getVertex(int num){ return num < 2 ? _v[num] : _vs[num - 2]; }
+  virtual MVertex *getVertexUNV(int num)
+  {
+    static const int map[3] = {0, 2, 1};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 1; }
+  virtual int getNumEdgesRep(){ return 2; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[2][2] = {
+      {0, 2}, {2, 1}
+    };
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MLine::_getEdgeVertices(v);
+    v[2] = _vs[0];
+  }
+  virtual int getTypeForMSH() const { return MSH_LIN_3; }
+  virtual int getTypeForUNV() const { return 24; } // parabolic beam
+  //virtual int getTypeForVTK() const { return 21; }
+  virtual const char *getStringForPOS() const { return "SL2"; }
+};
+
+/*
+ * MLineN
+ *
+ *   0---2---...-(N-1)-1
+ *
+ */
+class MLineN : public MLine {
+ protected:
+  std::vector<MVertex *> _vs;
+ public :
+  MLineN(MVertex *v0, MVertex *v1, const std::vector<MVertex*> &vs, int num=0, int part=0) 
+    : MLine(v0, v1, num, part), _vs(vs)
+  {
+    for(unsigned int i = 0; i < _vs.size(); i++)
+      _vs[i]->setPolynomialOrder(_vs.size() + 1);
+  }
+  MLineN(const std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MLine(v[0] , v[1], num, part)
+  {
+    for(unsigned int i = 2; i < v.size(); i++)
+      _vs.push_back(v[i]);
+    for(unsigned int i = 0; i < _vs.size(); i++)
+      _vs[i]->setPolynomialOrder(_vs.size() + 1);
+  }
+  ~MLineN(){}
+  virtual int getPolynomialOrder() const { return _vs.size() + 1; }
+  virtual int getNumVertices() const { return _vs.size() + 2; }
+  virtual MVertex *getVertex(int num){ return num < 2 ? _v[num] : _vs[num - 2]; }
+  virtual int getNumEdgeVertices() const { return _vs.size(); }
+  virtual int getNumEdgesRep(){ return _vs.size() + 1; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    _getEdgeRep(getVertex((num == 0) ? 0 : num + 1), 
+                getVertex((num == getNumEdgesRep() - 1) ? 1 : num + 2),
+                x, y, z, n);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2 + _vs.size());
+    MLine::_getEdgeVertices(v);
+    for(unsigned int i = 0; i != _vs.size(); ++i) v[i+2] = _vs[i];
+  }
+  virtual int getTypeForMSH() const 
+  { 
+    if(_vs.size() == 2) return MSH_LIN_4; 
+    if(_vs.size() == 3) return MSH_LIN_5; 
+    if(_vs.size() == 4) return MSH_LIN_6; 
+    return 0;
+  }
+};
+
+#endif
diff --git a/Geo/MPoint.h b/Geo/MPoint.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9d7b403098f70ac0b6a4ffd5fbc697cec448e51
--- /dev/null
+++ b/Geo/MPoint.h
@@ -0,0 +1,58 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MPOINT_H_
+#define _MPOINT_H_
+
+#include "MElement.h"
+
+/*
+ * MPoint
+ *
+ */
+class MPoint : public MElement {
+ protected:
+  MVertex *_v[1];
+ public :
+  MPoint(MVertex *v0, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0;
+  }
+  MPoint(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v[0];
+  }
+  ~MPoint(){}
+  virtual int getDim(){ return 0; }
+  virtual int getNumVertices() const { return 1; }
+  virtual MVertex *getVertex(int num){ return _v[0]; }
+  virtual int getNumEdges(){ return 0; }
+  virtual MEdge getEdge(int num){ return MEdge(); }
+  virtual int getNumEdgesRep(){ return 0; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n){}
+  virtual int getNumFaces(){ return 0; }
+  virtual MFace getFace(int num){ return MFace(); }
+  virtual int getNumFacesRep(){ return 0; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n){}
+  virtual int getTypeForMSH() const { return MSH_PNT; }
+  virtual int getTypeForVTK() const { return 1; }
+  virtual const char *getStringForPOS() const { return "SP"; }
+  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
+  {
+    s[0] = 1.;
+  }
+  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
+  {
+    s[0][0] = s[0][1] = s[0][2] = 0.;
+  }
+  virtual bool isInside(double u, double v, double w)
+  {
+    return true;
+  }
+};
+
+#endif
diff --git a/Geo/MPrism.cpp b/Geo/MPrism.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..02e62883168c23283681c5c9eaa823df001865db
--- /dev/null
+++ b/Geo/MPrism.cpp
@@ -0,0 +1,22 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MPrism.h"
+#include "Numeric.h"
+
+int MPrism::getVolumeSign()
+{ 
+  double mat[3][3];
+  mat[0][0] = _v[1]->x() - _v[0]->x();
+  mat[0][1] = _v[2]->x() - _v[0]->x();
+  mat[0][2] = _v[3]->x() - _v[0]->x();
+  mat[1][0] = _v[1]->y() - _v[0]->y();
+  mat[1][1] = _v[2]->y() - _v[0]->y();
+  mat[1][2] = _v[3]->y() - _v[0]->y();
+  mat[2][0] = _v[1]->z() - _v[0]->z();
+  mat[2][1] = _v[2]->z() - _v[0]->z();
+  mat[2][2] = _v[3]->z() - _v[0]->z();
+  return sign(det3x3(mat));
+}
diff --git a/Geo/MPrism.h b/Geo/MPrism.h
new file mode 100644
index 0000000000000000000000000000000000000000..07807e8b71cfa8086ab6ce39cd5a2006370699df
--- /dev/null
+++ b/Geo/MPrism.h
@@ -0,0 +1,447 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MPRISM_H_
+#define _MPRISM_H_
+
+#include "MElement.h"
+
+/*
+ * MPrism
+ *
+ *               w
+ *               ^
+ *               |
+ *               3
+ *             ,/|`\
+ *           ,/  |  `\
+ *         ,/    |    `\
+ *        4------+------5
+ *        |      |      |
+ *        |    ,/|`\    |
+ *        |  ,/  |  `\  |
+ *        |,/    |    `\|
+ *       ,|      |      `\
+ *     ,/ |      0      | `\
+ *    u   |    ,/ `\    |    v
+ *        |  ,/     `\  |
+ *        |,/         `\|
+ *        1-------------2
+ *
+ */
+class MPrism : public MElement {
+ protected:
+  MVertex *_v[6];
+  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[edges_prism(num, 0)];
+    v[1] = _v[edges_prism(num, 1)];
+  }
+  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[faces_prism(num, 0)];
+    v[1] = _v[faces_prism(num, 1)];
+    v[2] = _v[faces_prism(num, 2)];
+    if(num >= 2) v[3] = _v[faces_prism(num, 3)];
+  }
+ public :
+  MPrism(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+         MVertex *v5, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
+    _v[4] = v4; _v[5] = v5; 
+  }
+  MPrism(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 6; i++) _v[i] = v[i];
+  }
+  ~MPrism(){}
+  virtual int getDim(){ return 3; }
+  virtual int getNumVertices() const { return 6; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[6] = {0, 2, 1, 3, 5, 4};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdges(){ return 9; }
+  virtual MEdge getEdge(int num)
+  {
+    return MEdge(_v[edges_prism(num, 0)], _v[edges_prism(num, 1)]);
+  }
+  virtual int getNumEdgesRep(){ return 9; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  {
+    static const int f[9] = {0, 1, 2, 0, 2, 3, 1, 1, 1};
+    MEdge e(getEdge(num));
+    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(num, v);
+  }
+  virtual int getNumFaces(){ return 5; }
+  virtual MFace getFace(int num)
+  {
+    if(num < 2)
+      return MFace(_v[faces_prism(num, 0)],
+                   _v[faces_prism(num, 1)],
+                   _v[faces_prism(num, 2)]);
+    else
+      return MFace(_v[faces_prism(num, 0)],
+                   _v[faces_prism(num, 1)],
+                   _v[faces_prism(num, 2)],
+                   _v[faces_prism(num, 3)]);
+  }
+  virtual int getNumFacesRep(){ return 8; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[8][3] = {
+      {0, 2, 1},
+      {3, 4, 5},
+      {0, 1, 4}, {0, 4, 3},
+      {0, 3, 5}, {0, 5, 2},
+      {1, 2, 5}, {1, 5, 4}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((num < 2) ? 3 : 4);
+    _getFaceVertices(num, v);
+  }
+  virtual int getTypeForMSH() const { return MSH_PRI_6; }
+  virtual int getTypeForUNV() const { return 112; } // solid linear wedge
+  virtual int getTypeForVTK() const { return 13; }
+  virtual const char *getStringForPOS() const { return "SI"; }
+  virtual const char *getStringForBDF() const { return "CPENTA"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
+    tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
+  }
+  virtual int getVolumeSign();
+  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
+  {
+    s[0] = (1. - u - v) * (1. - w) * 0.5;
+    s[1] =       u      * (1. - w) * 0.5;
+    s[2] =           v  * (1. - w) * 0.5;
+    s[3] = (1. - u - v) * (1. + w) * 0.5;
+    s[4] =       u      * (1. + w) * 0.5;
+    s[5] =           v  * (1. + w) * 0.5;
+  }
+  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
+  {
+    s[0][0] = -0.5 * (1. - w)    ;
+    s[0][1] = -0.5 * (1. - w)    ;
+    s[0][2] = -0.5 * (1. - u - v);
+    s[1][0] =  0.5 * (1. - w)    ;
+    s[1][1] =  0.                ;
+    s[1][2] = -0.5 * u           ;
+    s[2][0] =  0.                ;
+    s[2][1] =  0.5 * (1. - w)    ;
+    s[2][2] = -0.5 * v           ;
+    s[3][0] = -0.5 * (1. + w)    ;
+    s[3][1] = -0.5 * (1. + w)    ;
+    s[3][2] =  0.5 * (1. - u - v);
+    s[4][0] =  0.5 * (1. + w)    ;
+    s[4][1] =  0.                ;
+    s[4][2] =  0.5 * u           ;
+    s[5][0] =  0.                ;
+    s[5][1] =  0.5 * (1. + w)    ;
+    s[5][2] =  0.5 * v           ;
+  }
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(w > (1. + tol) || w < -(1. + tol) || u < (1. + tol)
+       || v < (1. + tol) || u > ((1. + tol) - v))
+      return false;
+    return true;
+  }
+ private:
+  int edges_prism(const int edge, const int vert) const
+  {
+    static const int e[9][2] = {
+      {0, 1},
+      {0, 2},
+      {0, 3},
+      {1, 2},
+      {1, 4},
+      {2, 5},
+      {3, 4},
+      {3, 5},
+      {4, 5}
+    };
+    return e[edge][vert];
+  }
+  int faces_prism(const int face, const int vert) const
+  {
+    static const int f[5][4] = {
+      {0, 2, 1, -1},
+      {3, 4, 5, -1},
+      {0, 1, 4,  3},
+      {0, 3, 5,  2},
+      {1, 2, 5,  4}
+    };
+    return f[face][vert];
+  }
+};
+
+/*
+ * MPrism15
+ *
+ *               3
+ *             ,/|`\
+ *           12  |  13
+ *         ,/    |    `\
+ *        4------14-----5
+ *        |      8      |
+ *        |      |      |
+ *        |      |      |
+ *        |      |      |
+ *        10     |      11
+ *        |      0      |
+ *        |    ,/ `\    |
+ *        |  ,6     `7  |
+ *        |,/         `\|
+ *        1------9------2
+ *
+ */
+class MPrism15 : public MPrism {
+ protected:
+  MVertex *_vs[9];
+ public :
+  MPrism15(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+           MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+           MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
+           int num=0, int part=0) 
+    : MPrism(v0, v1, v2, v3, v4, v5, num, part)
+  {
+    _vs[0] = v6; _vs[1] = v7; _vs[2] = v8; _vs[3] = v9; _vs[4] = v10; 
+    _vs[5] = v11; _vs[6] = v12; _vs[7] = v13; _vs[8] = v14;
+    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MPrism15(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MPrism(v, num, part)
+  {
+    for(int i = 0; i < 9; i++) _vs[i] = v[6 + i];
+    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MPrism15(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 15; }
+  virtual MVertex *getVertex(int num){ return num < 6 ? _v[num] : _vs[num - 6]; }
+  virtual MVertex *getVertexUNV(int num)
+  {
+    static const int map[15] = {0, 6, 1, 9, 2, 7, 8, 10, 11, 3, 12, 4, 14, 5, 13};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexBDF(int num)
+  {
+    static const int map[15] = {0, 1, 2, 3, 4, 5, 6, 9, 7, 8, 10, 11, 12, 14, 13};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[15] = {0, 2, 1, 3, 5, 4, 7, 9, 6, 13, 14, 12, 8, 11, 10};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 9; }
+  virtual int getNumEdgesRep(){ return 18; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[18][2] = {
+      {0, 6}, {6, 1},
+      {0, 7}, {7, 2},
+      {0, 8}, {8, 3},
+      {1, 9}, {9, 2},
+      {1, 10}, {10, 4},
+      {2, 11}, {11, 5},
+      {3, 12}, {12, 4},
+      {3, 13}, {13, 5},
+      {4, 14}, {14, 5}
+    };
+    static const int f[9] = {0, 1, 2, 0, 2, 3, 1, 1, 1};
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MPrism::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 26; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[26][3] = {
+      {0, 7, 6}, {2, 9, 7}, {1, 6, 9}, {6, 7, 9},
+      {3, 12, 13}, {4, 14, 12}, {5, 13, 14}, {12, 14, 13},
+      {0, 6, 8}, {1, 10, 6}, {4, 12, 10}, {3, 8, 12}, {6, 10, 12}, {6, 12, 8},
+      {0, 8, 7}, {3, 13, 8}, {5, 11, 13}, {2, 7, 11}, {7, 8, 13}, {7, 13, 11},
+      {1, 9, 10}, {2, 11, 9}, {5, 14, 11}, {4, 10, 14}, {9, 11, 14}, {9, 14, 10}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((num < 2) ? 6 : 8);
+    MPrism::_getFaceVertices(num, v);
+    static const int f[5][4] = {
+      {1, 3, 0, -1},
+      {6, 8, 7, -1},
+      {0, 4, 6,  2},
+      {2, 7, 5,  1},
+      {3, 5, 8,  4}
+    };
+    const int i = (num < 2) ? 3 : 4;
+    v[i  ] = _vs[f[num][0]];
+    v[i+1] = _vs[f[num][1]];
+    v[i+2] = _vs[f[num][2]];
+    if (num >= 2) v[7] = _vs[f[num][3]];
+  }
+  virtual int getTypeForMSH() const { return MSH_PRI_15; }
+  virtual int getTypeForUNV() const { return 113; } // solid parabolic wedge
+  virtual const char *getStringForBDF() const { return "CPENTA"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
+    tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
+    tmp = _vs[1]; _vs[1] = _vs[3]; _vs[3] = tmp;
+    tmp = _vs[2]; _vs[2] = _vs[4]; _vs[4] = tmp;
+    tmp = _vs[7]; _vs[7] = _vs[8]; _vs[8] = tmp;
+  }
+};
+
+/*
+ * MPrism18
+ *
+ *               3
+ *             ,/|`\
+ *           12  |  13
+ *         ,/    |    `\
+ *        4------14-----5
+ *        |      8      |
+ *        |    ,/|`\    |
+ *        |  15  |  16  |
+ *        |,/    |    `\|
+ *        10-----17-----11
+ *        |      0      |
+ *        |    ,/ `\    |
+ *        |  ,6     `7  |
+ *        |,/         `\|
+ *        1------9------2
+ *
+ */
+class MPrism18 : public MPrism {
+ protected:
+  MVertex *_vs[12];
+ public :
+  MPrism18(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+           MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+           MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, MVertex *v14,
+           MVertex *v15, MVertex *v16, MVertex *v17, int num=0, int part=0) 
+    : MPrism(v0, v1, v2, v3, v4, v5, num, part)
+  {
+    _vs[0] = v6; _vs[1] = v7; _vs[2] = v8; _vs[3] = v9; _vs[4] = v10; 
+    _vs[5] = v11; _vs[6] = v12; _vs[7] = v13; _vs[8] = v14; _vs[9] = v15; 
+    _vs[10] = v16; _vs[11] = v17; 
+    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MPrism18(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MPrism(v, num, part)
+  {
+    for(int i = 0; i < 12; i++) _vs[i] = v[6 + i];
+    for(int i = 0; i < 12; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MPrism18(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 18; }
+  virtual MVertex *getVertex(int num){ return num < 6 ? _v[num] : _vs[num - 6]; }
+  virtual int getNumEdgeVertices() const { return 9; }
+  virtual int getNumFaceVertices() const { return 3; }
+  virtual int getNumEdgesRep(){ return 18; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[18][2] = {
+      {0, 6}, {6, 1},
+      {0, 7}, {7, 2},
+      {0, 8}, {8, 3},
+      {1, 9}, {9, 2},
+      {1, 10}, {10, 4},
+      {2, 11}, {11, 5},
+      {3, 12}, {12, 4},
+      {3, 13}, {13, 5},
+      {4, 14}, {14, 5}
+    };
+    static const int f[9] = {0, 1, 2, 0, 2, 3, 1, 1, 1};
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MPrism::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 32; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[32][3] = {
+      {0, 7, 6}, {2, 9, 7}, {1, 6, 9}, {6, 7, 9},
+      {3, 12, 13}, {4, 14, 12}, {5, 13, 14}, {12, 14, 13},
+      {0, 6, 15}, {0, 15, 8}, {1, 10, 15}, {1, 15, 6},  
+      {4, 12, 15}, {4, 15, 10}, {3, 8, 15}, {3, 15, 12},  
+      {0, 8, 16}, {0, 16, 7}, {3, 13, 16}, {3, 16, 8},  
+      {5, 11, 16}, {5, 16, 13}, {2, 7, 16}, {2, 16, 11},  
+      {1, 9, 17}, {1, 17, 10}, {2, 11, 17}, {2, 17, 9},  
+      {5, 14, 17}, {5, 17, 11}, {4, 10, 17}, {4, 17, 14}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((num < 2) ? 6 : 9);
+    MPrism::_getFaceVertices(num, v);
+    static const int f[5][4] = {
+      {1, 3, 0, -1},
+      {6, 8, 7, -1},
+      {0, 4, 6,  2},
+      {2, 7, 5,  1},
+      {3, 5, 8,  4}
+    };
+    const int i = (num < 2) ? 3 : 4;
+    v[i  ] = _vs[f[num][0]];
+    v[i+1] = _vs[f[num][1]];
+    v[i+2] = _vs[f[num][2]];
+    if (num >= 2) {
+      v[7] = _vs[f[num][3]];
+      v[8] = _vs[7+num];
+    }
+  }
+  virtual int getTypeForMSH() const { return MSH_PRI_18; }
+  virtual const char *getStringForPOS() const { return "SI2"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
+    tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
+    // edge vertices
+    tmp = _vs[1]; _vs[1] = _vs[3]; _vs[3] = tmp;
+    tmp = _vs[2]; _vs[2] = _vs[4]; _vs[4] = tmp;
+    tmp = _vs[7]; _vs[7] = _vs[8]; _vs[8] = tmp;
+    // quad face vertices
+    tmp = _vs[10]; _vs[10] = _vs[11]; _vs[11] = tmp;
+  }
+};
+
+#endif
diff --git a/Geo/MPyramid.cpp b/Geo/MPyramid.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b95a80dfccc4506f0bfa499322fcde872610c238
--- /dev/null
+++ b/Geo/MPyramid.cpp
@@ -0,0 +1,22 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MPyramid.h"
+#include "Numeric.h"
+
+int MPyramid::getVolumeSign()
+{ 
+  double mat[3][3];
+  mat[0][0] = _v[1]->x() - _v[0]->x();
+  mat[0][1] = _v[3]->x() - _v[0]->x();
+  mat[0][2] = _v[4]->x() - _v[0]->x();
+  mat[1][0] = _v[1]->y() - _v[0]->y();
+  mat[1][1] = _v[3]->y() - _v[0]->y();
+  mat[1][2] = _v[4]->y() - _v[0]->y();
+  mat[2][0] = _v[1]->z() - _v[0]->z();
+  mat[2][1] = _v[3]->z() - _v[0]->z();
+  mat[2][2] = _v[4]->z() - _v[0]->z();
+  return sign(det3x3(mat));
+}
diff --git a/Geo/MPyramid.h b/Geo/MPyramid.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c91efe97ed3c070e9e6432e294db9b9a19b3974
--- /dev/null
+++ b/Geo/MPyramid.h
@@ -0,0 +1,440 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MPYRAMID_H_
+#define _MPYRAMID_H_
+
+#include "MElement.h"
+
+/*
+ * MPyramid
+ *
+ *                 4
+ *               ,/|\
+ *             ,/ .'|\
+ *           ,/   | | \
+ *         ,/    .' | `.
+ *       ,/      |  '.  \
+ *     ,/       .' w |   \
+ *   ,/         |  ^ |    \
+ *  0----------.'--|-3    `. 
+ *   `\        |   |  `\    \
+ *     `\     .'   +----`\ - \ -> v
+ *       `\   |    `\     `\  \
+ *         `\.'      `\     `\`
+ *            1----------------2
+ *                      `\
+ *                         u
+ *
+ */
+class MPyramid : public MElement {
+ protected:
+  MVertex *_v[5];
+  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[edges_pyramid(num, 0)];
+    v[1] = _v[edges_pyramid(num, 1)];
+  }
+  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    if(num < 4) {
+      v[0] = _v[faces_pyramid(num, 0)];
+      v[1] = _v[faces_pyramid(num, 1)];
+      v[2] = _v[faces_pyramid(num, 2)];
+    }
+    else {
+      v[0] = _v[0];
+      v[1] = _v[3];
+      v[2] = _v[2];
+      v[3] = _v[1];
+    }
+  }
+ public :
+  MPyramid(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+           int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3; _v[4] = v4;
+  }
+  MPyramid(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 5; i++) _v[i] = v[i];
+  }
+  ~MPyramid(){}
+  virtual int getDim(){ return 3; }
+  virtual int getNumVertices() const { return 5; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[5] = {0, 3, 2, 1, 4};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdges(){ return 8; }
+  virtual MEdge getEdge(int num)
+  {
+    return MEdge(_v[edges_pyramid(num, 0)], _v[edges_pyramid(num, 1)]);
+  }
+  virtual int getNumEdgesRep(){ return 8; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  {
+    static const int f[8] = {0, 1, 1, 2, 0, 3, 2, 3};
+    MEdge e(getEdge(num));
+    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(num, v);
+  }
+  virtual int getNumFaces(){ return 5; }
+  virtual MFace getFace(int num)
+  {
+    if(num < 4)
+      return MFace(_v[faces_pyramid(num, 0)],
+                   _v[faces_pyramid(num, 1)],
+                   _v[faces_pyramid(num, 2)]);
+    else
+      return MFace(_v[0], _v[3], _v[2], _v[1]);
+  }
+  virtual int getNumFacesRep(){ return 6; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[6][3] = {
+      {0, 1, 4},
+      {3, 0, 4},
+      {1, 2, 4},
+      {2, 3, 4},
+      {0, 3, 2}, {0, 2, 1}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((num < 4) ? 3 : 4);
+    _getFaceVertices(num, v);
+  }
+  virtual int getTypeForMSH() const { return MSH_PYR_5; }
+  virtual int getTypeForVTK() const { return 14; }
+  virtual const char *getStringForPOS() const { return "SY"; }
+  virtual const char *getStringForBDF() const { return "CPYRAM"; }
+  virtual void revert()
+  {
+    MVertex *tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
+  }
+  virtual int getVolumeSign();
+  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
+  {
+    double r = (w != 1.) ? (u * v * w / (1. - w)) : 0.;
+    s[0] = 0.25 * ((1. - u) * (1. - v) - w + r);
+    s[1] = 0.25 * ((1. + u) * (1. - v) - w - r);
+    s[2] = 0.25 * ((1. + u) * (1. + v) - w + r);
+    s[3] = 0.25 * ((1. - u) * (1. + v) - w - r);
+    s[4] = w;
+  }
+  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
+  {
+    if(w == 1.) {
+      s[0][0] = -0.25 ; 
+      s[0][1] = -0.25 ;
+      s[0][2] = -0.25 ; 
+      s[1][0] =  0.25 ; 
+      s[1][1] = -0.25 ;
+      s[1][2] = -0.25 ; 
+      s[2][0] =  0.25 ; 
+      s[2][1] =  0.25 ;
+      s[2][2] = -0.25 ; 
+      s[3][0] = -0.25 ; 
+      s[3][1] =  0.25 ;
+      s[3][2] = -0.25 ; 
+    }
+    else{
+      s[0][0] = 0.25 * ( -(1. - v) + v * w / (1. - w)) ;
+      s[0][1] = 0.25 * ( -(1. - u) + u * w / (1. - w)) ;
+      s[0][2] = 0.25 * ( -1.     + u * v / (1. - w) + u * v * w / (1. - w) / (1. - w)) ; 
+      s[1][0] = 0.25 * (  (1. - v) - v * w / (1. - w)) ;
+      s[1][1] = 0.25 * ( -(1. + u) - u * w / (1. - w)) ;
+      s[1][2] = 0.25 * ( -1.     - u * v / (1. - w) - u * v * w / (1. - w) / (1. - w)) ; 
+      s[2][0] = 0.25 * (  (1. + v) + v * w / (1. - w)) ;
+      s[2][1] = 0.25 * (  (1. + u) + u * w / (1. - w)) ;
+      s[2][2] = 0.25 * ( -1.     + u * v / (1. - w) + u * v * w / (1. - w) / (1. - w)) ; 
+      s[3][0] = 0.25 * ( -(1. + v) - v * w / (1. - w)) ;
+      s[3][1] = 0.25 * (  (1. - u) - u * w / (1. - w)) ;
+      s[3][2] = 0.25 * ( -1.     - u * v / (1. - w) - u * v * w / (1. - w) / (1. - w)) ; 
+    }
+    s[4][0] = 0.; 
+    s[4][1] = 0.;
+    s[4][2] = 1.;
+  }
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(u < (w - (1. + tol)) || u > ((1. + tol) - w) || v < (w - (1. + tol)) ||
+       v > ((1. + tol) - w) || w < (-tol) || w > (1. + tol))
+      return false;
+    return true;
+  }
+ private:
+  int edges_pyramid(const int edge, const int vert) const
+  {
+    static const int e[8][2] = {
+      {0, 1},
+      {0, 3},
+      {0, 4},
+      {1, 2},
+      {1, 4},
+      {2, 3},
+      {2, 4},
+      {3, 4}
+    };
+    return e[edge][vert];
+  }
+  int faces_pyramid(const int face, const int vert) const
+  {
+    // only triangular faces
+    static const int f[4][3] = {
+      {0, 1, 4},
+      {3, 0, 4},
+      {1, 2, 4},
+      {2, 3, 4}
+    };
+    return f[face][vert];
+  }
+};
+
+/*
+ * MPyramid13
+ *
+ *                 4
+ *               ,/|\
+ *             ,/ .'|\
+ *           ,/   | | \
+ *         ,/    .' | `.
+ *       ,7      |  12  \
+ *     ,/       .'   |   \
+ *   ,/         9    |    11
+ *  0--------6-.'----3    `. 
+ *   `\        |      `\    \
+ *     `5     .'        10   \ 
+ *       `\   |           `\  \
+ *         `\.'             `\`
+ *            1--------8-------2
+ *                        
+ */
+class MPyramid13 : public MPyramid {
+ protected:
+  MVertex *_vs[8];
+ public :
+  MPyramid13(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+             MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+             MVertex *v10, MVertex *v11, MVertex *v12, int num=0, int part=0) 
+    : MPyramid(v0, v1, v2, v3, v4, num, part)
+  {
+    _vs[0] = v5; _vs[1] = v6; _vs[2] = v7; _vs[3] = v8; _vs[4] = v9; 
+    _vs[5] = v10; _vs[6] = v11; _vs[7] = v12;
+    for(int i = 0; i < 8; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MPyramid13(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MPyramid(v, num, part)
+  {
+    for(int i = 0; i < 8; i++) _vs[i] = v[5 + i];
+    for(int i = 0; i < 8; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MPyramid13(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 13; }
+  virtual MVertex *getVertex(int num){ return num < 5 ? _v[num] : _vs[num - 5]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[13] = {0, 3, 2, 1, 4, 6, 10, 8, 5, 7, 12, 11, 9};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 8; }
+  virtual int getNumEdgesRep(){ return 16; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[16][2] = {
+      {0, 5}, {5, 1},
+      {0, 6}, {6, 3},
+      {0, 7}, {7, 4},
+      {1, 8}, {8, 2},
+      {1, 9}, {9, 4},
+      {2, 10}, {10, 3},
+      {2, 11}, {11, 4},
+      {3, 12}, {12, 4}
+    };
+    static const int f[8] = {0, 1, 1, 2, 0, 3, 2, 3};
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MPyramid::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 22; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[22][3] = {
+      {0, 5, 7}, {1, 9, 5}, {4, 7, 9}, {5, 9, 7},
+      {3, 6, 12}, {0, 7, 6}, {4, 12, 7}, {6, 7, 12},
+      {1, 8, 9}, {2, 11, 8}, {4, 9, 11}, {8, 11, 9},
+      {2, 10, 11}, {3, 12, 10}, {4, 11, 12}, {10, 12, 11},
+      {0, 6, 5}, {3, 10, 6}, {2, 8, 10}, {1, 5, 8}, {5, 6, 10}, {5, 10, 8}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((num < 4) ? 6 : 8);
+    MPyramid::_getFaceVertices(num, v);
+    static const int f[4][3] = {
+      {0, 4, 2},
+      {1, 2, 7},
+      {3, 6, 4},
+      {5, 7, 6}
+    };
+    if(num < 4) {
+      v[3] = _vs[f[num][0]];
+      v[4] = _vs[f[num][1]];
+      v[5] = _vs[f[num][2]];
+    }
+    else {
+      v[4] = _vs[1];
+      v[5] = _vs[5];
+      v[6] = _vs[3];
+      v[7] = _vs[0];
+    }
+  }
+  virtual int getTypeForMSH() const { return MSH_PYR_13; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
+    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
+    tmp = _vs[1]; _vs[1] = _vs[5]; _vs[5] = tmp;
+    tmp = _vs[2]; _vs[2] = _vs[6]; _vs[6] = tmp;
+  }
+};
+
+/*
+ * MPyramid14
+ *
+ *                 4
+ *               ,/|\
+ *             ,/ .'|\
+ *           ,/   | | \
+ *         ,/    .' | `.
+ *       ,7      |  12  \
+ *     ,/       .'   |   \
+ *   ,/         9    |    11
+ *  0--------6-.'----3    `. 
+ *   `\        |      `\    \
+ *     `5     .' 13     10   \ 
+ *       `\   |           `\  \
+ *         `\.'             `\`
+ *            1--------8-------2
+ *
+ */
+class MPyramid14 : public MPyramid {
+ protected:
+  MVertex *_vs[9];
+ public :
+  MPyramid14(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+             MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+             MVertex *v10, MVertex *v11, MVertex *v12, MVertex *v13, 
+             int num=0, int part=0) 
+    : MPyramid(v0, v1, v2, v3, v4, num, part)
+  {
+    _vs[0] = v5; _vs[1] = v6; _vs[2] = v7; _vs[3] = v8; _vs[4] = v9; 
+    _vs[5] = v10; _vs[6] = v11; _vs[7] = v12; _vs[8] = v13; 
+    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);   
+  }
+  MPyramid14(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MPyramid(v, num, part)
+  {
+    for(int i = 0; i < 9; i++) _vs[i] = v[5 + i];
+    for(int i = 0; i < 9; i++) _vs[i]->setPolynomialOrder(2);   
+  }
+  ~MPyramid14(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 14; }
+  virtual MVertex *getVertex(int num){ return num < 5 ? _v[num] : _vs[num - 5]; }
+  virtual int getNumEdgeVertices() const { return 8; }
+  virtual int getNumFaceVertices() const { return 1; }
+  virtual int getNumEdgesRep(){ return 16; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[16][2] = {
+      {0, 5}, {5, 1},
+      {0, 6}, {6, 3},
+      {0, 7}, {7, 4},
+      {1, 8}, {8, 2},
+      {1, 9}, {9, 4},
+      {2, 10}, {10, 3},
+      {2, 11}, {11, 4},
+      {3, 12}, {12, 4}
+    };
+    static const int f[8] = {0, 1, 1, 2, 0, 3, 2, 3};
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, f[num / 2]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MPyramid::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 24; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[24][3] = {
+      {0, 5, 7}, {1, 9, 5}, {4, 7, 9}, {5, 9, 7},
+      {3, 6, 12}, {0, 7, 6}, {4, 12, 7}, {6, 7, 12},
+      {1, 8, 9}, {2, 11, 8}, {4, 9, 11}, {8, 11, 9},
+      {2, 10, 11}, {3, 12, 10}, {4, 11, 12}, {10, 12, 11},
+      {0, 6, 13}, {0, 13, 5}, {3, 10, 13}, {3, 13, 6}, 
+      {2, 8, 13}, {2, 13, 10}, {1, 5, 13}, {1, 13, 8}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((num < 4) ? 6 : 9);
+    MPyramid::_getFaceVertices(num, v);
+    static const int f[4][3] = {
+      {0, 4, 2},
+      {1, 2, 7},
+      {3, 6, 4},
+      {5, 7, 6}
+    };
+    if(num < 4) {
+      v[3] = _vs[f[num][0]];
+      v[4] = _vs[f[num][1]];
+      v[5] = _vs[f[num][2]];
+    }
+    else {
+      v[4] = _vs[1];
+      v[5] = _vs[5];
+      v[6] = _vs[3];
+      v[7] = _vs[0];
+      v[8] = _vs[8];
+    }
+  }
+  virtual int getTypeForMSH() const { return MSH_PYR_14; }
+  virtual const char *getStringForPOS() const { return "SY2"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
+    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
+    tmp = _vs[1]; _vs[1] = _vs[5]; _vs[5] = tmp;
+    tmp = _vs[2]; _vs[2] = _vs[6]; _vs[6] = tmp;
+  }
+};
+
+#endif
diff --git a/Geo/MQuadrangle.cpp b/Geo/MQuadrangle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f99a8c547fe63593a172abb80e0c16758c4e8a1
--- /dev/null
+++ b/Geo/MQuadrangle.cpp
@@ -0,0 +1,23 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MQuadrangle.h"
+
+#if defined(HAVE_GMSH_EMBEDDED)
+#include "GmshEmbedded.h"
+#else
+#include "GaussLegendre1D.h"
+#include "Context.h"
+#include "qualityMeasures.h"
+#endif
+
+void MQuadrangle::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
+{
+#if !defined(HAVE_GMSH_EMBEDDED)
+  *npts = getNGQQPts(pOrder);
+  *pts = getGQQPts(pOrder);
+#endif
+}
+
diff --git a/Geo/MQuadrangle.h b/Geo/MQuadrangle.h
new file mode 100644
index 0000000000000000000000000000000000000000..2eb10507144aacd56fc59fde3fa8f60849b1bf16
--- /dev/null
+++ b/Geo/MQuadrangle.h
@@ -0,0 +1,330 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MQUADRANGLE_H_
+#define _MQUADRANGLE_H_
+
+#include "MElement.h"
+
+/*
+ * MQuadrangle
+ *
+ *         v
+ *         ^
+ *         |
+ *   3-----------2
+ *   |     |     |
+ *   |     |     |
+ *   |     +---- | --> u
+ *   |           |
+ *   |           |
+ *   0-----------1 
+ *
+ */
+class MQuadrangle : public MElement {
+ protected:
+  MVertex *_v[4];
+  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[edges_quad(num, 0)];
+    v[1] = _v[edges_quad(num, 1)];
+  }
+  void _getFaceVertices(std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[0];
+    v[1] = _v[1];
+    v[2] = _v[2];
+    v[3] = _v[3];
+  }
+ public :
+  MQuadrangle(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
+  }
+  MQuadrangle(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 4; i++) _v[i] = v[i];
+  }
+  ~MQuadrangle(){}
+  virtual int getDim(){ return 2; }
+  virtual int getNumVertices() const { return 4; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[4] = {0, 3, 2, 1};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[4] = {0, 1, 3, 2};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdges(){ return 4; }
+  virtual MEdge getEdge(int num)
+  {
+    return MEdge(_v[edges_quad(num, 0)], _v[edges_quad(num, 1)]);
+  }
+  virtual int getNumEdgesRep(){ return 4; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    MEdge e(getEdge(num));
+    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, 0);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(num, v);
+  }
+  virtual int getNumFaces(){ return 1; }
+  virtual MFace getFace(int num){ return MFace(_v[0], _v[1], _v[2], _v[3]); }
+  virtual int getNumFacesRep(){ return 2; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[2][3] = {
+      {0, 1, 2}, {0, 2, 3}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(4);
+    _getFaceVertices(v);
+  }
+  virtual int getTypeForMSH() const { return MSH_QUA_4; }
+  virtual int getTypeForUNV() const { return 94; } // thin shell linear quadrilateral
+  virtual int getTypeForVTK() const { return 9; }
+  virtual const char *getStringForPOS() const { return "SQ"; }
+  virtual const char *getStringForBDF() const { return "CQUAD4"; }
+  virtual const char *getStringForDIFF() const { return "ElmB4n2D"; }
+  virtual void revert() 
+  {
+    MVertex *tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
+  }
+  virtual void getShapeFunctions(double u, double v, double w, double s[], int o) 
+  {
+    s[0] = (1. - u) * (1. - v) * 0.25;
+    s[1] = (1. + u) * (1. - v) * 0.25;
+    s[2] = (1. + u) * (1. + v) * 0.25;
+    s[3] = (1. - u) * (1. + v) * 0.25;
+  }
+  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) 
+  {
+    s[0][0] = -0.25 * (1. - v); s[0][1] = -0.25 * (1. - u); s[0][2] = 0.;
+    s[1][0] =  0.25 * (1. - v); s[1][1] = -0.25 * (1. + u); s[1][2] = 0.;
+    s[2][0] =  0.25 * (1. + v); s[2][1] =  0.25 * (1. + u); s[2][2] = 0.;
+    s[3][0] = -0.25 * (1. + v); s[3][1] =  0.25 * (1. - u); s[3][2] = 0.;
+  }
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(u < -(1. + tol) || v < -(1. + tol) || u > (1. + tol) || v > (1. + tol))
+      return false;
+    return true;
+  }
+  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
+ private:
+  int edges_quad(const int edge, const int vert) const
+  {
+    static const int e[4][2] = {
+      {0, 1},
+      {1, 2},
+      {2, 3},
+      {3, 0}
+    };
+    return e[edge][vert];
+  }
+};
+
+/*
+ * MQuadrangle8
+ *
+ *   3-----6-----2
+ *   |           |
+ *   |           |
+ *   7           5
+ *   |           |
+ *   |           |
+ *   0-----4-----1 
+ *
+ */
+class MQuadrangle8 : public MQuadrangle {
+ protected:
+  MVertex *_vs[4];
+ public :
+  MQuadrangle8(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+               MVertex *v5, MVertex *v6, MVertex *v7, int num=0, int part=0) 
+    : MQuadrangle(v0, v1, v2, v3, num, part)
+  {
+    _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7;
+    for(int i = 0; i < 4; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MQuadrangle8(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MQuadrangle(v, num, part)
+  {
+    for(int i = 0; i < 4; i++) _vs[i] = v[4 + i];
+    for(int i = 0; i < 4; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MQuadrangle8(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 8; }
+  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
+  virtual MVertex *getVertexUNV(int num)
+  {
+    static const int map[8] = {0, 4, 1, 5, 2, 6, 3, 7};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[8] = {0, 3, 2, 1, 7, 6, 5, 4};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[8] = {0, 1, 3, 2, 4, 7, 5, 6};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 4; }
+  virtual int getNumEdgesRep(){ return 8; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[8][2] = {
+      {0, 4}, {4, 1},
+      {1, 5}, {5, 2},
+      {2, 6}, {6, 3},
+      {3, 7}, {7, 0}
+    };
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, 0);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MQuadrangle::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 6; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[6][3] = {
+      {0, 4, 7}, {1, 5, 4}, {2, 6, 5}, {3, 7, 6}, {4, 5, 6}, {4, 6, 7}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(8);
+    MQuadrangle::_getFaceVertices(v);
+    v[4] = _vs[0];
+    v[5] = _vs[1];
+    v[6] = _vs[2];
+    v[7] = _vs[3];
+  }
+  virtual int getTypeForMSH() const { return MSH_QUA_8; }
+  virtual int getTypeForUNV() const { return 95; } // shell parabolic quadrilateral
+  //virtual int getTypeForVTK() const { return 23; }
+  virtual const char *getStringForBDF() const { return "CQUAD8"; }
+  virtual const char *getStringForDIFF() const { return "ElmB8n2D"; }
+  virtual void revert() 
+  {
+    MVertex *tmp;
+    tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
+    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
+    tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
+  }
+};
+
+/*
+ * MQuadrangle9
+ *
+ *   3-----6-----2
+ *   |           |
+ *   |           |
+ *   7     8     5
+ *   |           |
+ *   |           |
+ *   0-----4-----1 
+ *
+ */
+class MQuadrangle9 : public MQuadrangle {
+ protected:
+  MVertex *_vs[5];
+ public :
+  MQuadrangle9(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+               MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, int num=0, int part=0) 
+    : MQuadrangle(v0, v1, v2, v3, num, part)
+  {
+    _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7; _vs[4] = v8;
+    for(int i = 0; i < 5; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MQuadrangle9(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MQuadrangle(v, num, part)
+  {
+    for(int i = 0; i < 5; i++) _vs[i] = v[4 + i];
+    for(int i = 0; i < 5; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MQuadrangle9(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 9; }
+  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[9] = {0, 2, 8, 6, 1, 5, 7, 3, 4};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 4; }
+  virtual int getNumFaceVertices() const { return 1; }
+  virtual int getNumEdgesRep(){ return 8; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int e[8][2] = {
+      {0, 4}, {4, 1},
+      {1, 5}, {5, 2},
+      {2, 6}, {6, 3},
+      {3, 7}, {7, 0}
+    };
+    _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n, 0);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MQuadrangle::getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep(){ return 8; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    static const int f[8][4] = {
+      {0, 4, 8}, {0, 8, 7}, {1, 5, 8}, {1, 8, 4}, 
+      {2, 6, 8}, {2, 8, 5}, {3, 7, 8}, {3, 8, 6}
+    };
+    _getFaceRep(getVertex(f[num][0]), getVertex(f[num][1]), getVertex(f[num][2]),
+                x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(9);
+    MQuadrangle::_getFaceVertices(v);
+    v[4] = _vs[0];
+    v[5] = _vs[1];
+    v[6] = _vs[2];
+    v[7] = _vs[3];
+    v[8] = _vs[4];
+  }
+  virtual int getTypeForMSH() const { return MSH_QUA_9; }
+  virtual const char *getStringForPOS() const { return "SQ2"; }
+  virtual const char *getStringForDIFF() const { return "ElmB9n2D"; }
+  virtual void revert() 
+  {
+    MVertex *tmp;
+    tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
+    tmp = _vs[0]; _vs[0] = _vs[3]; _vs[3] = tmp;
+    tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
+  }
+};
+
+#endif
diff --git a/Geo/MTetrahedron.cpp b/Geo/MTetrahedron.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d2272e7e16c9aa193932c8a7089db92685a406f
--- /dev/null
+++ b/Geo/MTetrahedron.cpp
@@ -0,0 +1,261 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MTetrahedron.h"
+
+#if defined(HAVE_GMSH_EMBEDDED)
+#include "GmshEmbedded.h"
+#else
+#include "Context.h"
+#include "qualityMeasures.h"
+#include "meshGFaceDelaunayInsertion.h"
+#include "meshGRegionDelaunayInsertion.h"
+#endif
+
+#define SQU(a)      ((a)*(a))
+
+SPoint3 MTetrahedron::circumcenter()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return SPoint3();
+#else
+  MTet4 t(this,0);
+  double res[3];
+  t.circumcenter(res);
+  return SPoint3(res[0],res[1],res[2]);
+#endif
+}
+
+double MTetrahedron::distoShapeMeasure()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return 1.;
+#else
+  return qmDistorsionOfMapping(this);
+#endif
+}
+
+double MTetrahedronN::distoShapeMeasure()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return 1.;
+#else
+  // if (_disto < -1.e21)
+  _disto = qmDistorsionOfMapping(this);
+  return _disto;
+#endif
+}
+
+double MTetrahedron::gammaShapeMeasure()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return 0.;
+#else
+  double vol;
+  return qmTet(this, QMTET_2, &vol);
+#endif
+}
+
+double MTetrahedron::etaShapeMeasure()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return 0.;
+#else
+  double vol;
+  return qmTet(this, QMTET_3, &vol);
+#endif
+}
+
+double MTetrahedron::getVolume()
+{
+  double mat[3][3];
+  getMat(mat);
+  return det3x3(mat) / 6.;
+}
+
+void MTetrahedron::xyz2uvw(double xyz[3], double uvw[3])
+{
+  double mat[3][3], b[3], det;
+  getMat(mat);
+  b[0] = xyz[0] - getVertex(0)->x();
+  b[1] = xyz[1] - getVertex(0)->y();
+  b[2] = xyz[2] - getVertex(0)->z();
+  sys3x3(mat, b, uvw, &det);
+}
+
+const gmshFunctionSpace* MTetrahedron::getFunctionSpace(int o) const
+{
+  int order = (o == -1) ? getPolynomialOrder() : o;
+
+  int nv = getNumVolumeVertices();
+  
+  if ((nv == 0) && (o == -1)) {
+    switch (order) {
+    case 1: return &gmshFunctionSpaces::find(MSH_TET_4);
+    case 2: return &gmshFunctionSpaces::find(MSH_TET_10);
+    case 3: return &gmshFunctionSpaces::find(MSH_TET_20);
+    case 4: return &gmshFunctionSpaces::find(MSH_TET_34);
+    case 5: return &gmshFunctionSpaces::find(MSH_TET_52);
+    default: Msg::Error("Order %d tetrahedron function space not implemented", order);
+    }
+  }
+  else { 
+    switch (order) {
+    case 1: return &gmshFunctionSpaces::find(MSH_TET_4);
+    case 2: return &gmshFunctionSpaces::find(MSH_TET_10);
+    case 3: return &gmshFunctionSpaces::find(MSH_TET_20);
+    case 4: return &gmshFunctionSpaces::find(MSH_TET_35);
+    case 5: return &gmshFunctionSpaces::find(MSH_TET_56);
+    default: Msg::Error("Order %d tetrahedron function space not implemented", order);
+    }
+  }
+  return 0;
+}
+
+int MTetrahedron10::getNumEdgesRep(){ return 6 * CTX::instance()->mesh.numSubEdges; }
+int MTetrahedronN::getNumEdgesRep(){ return 6 * CTX::instance()->mesh.numSubEdges; }
+
+static void _myGetEdgeRep(MTetrahedron *tet, int num, double *x, double *y, double *z,
+                          SVector3 *n, int numSubEdges)
+{
+  static double pp[4][3] = {{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
+  static int ed [6][2] = {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}};
+  int iEdge = num / numSubEdges;
+  int iSubEdge = num % numSubEdges;  
+
+  int iVertex1 = ed [iEdge][0];
+  int iVertex2 = ed [iEdge][1];
+  double t1 = (double) iSubEdge / (double) numSubEdges;
+  double u1 = pp[iVertex1][0] * (1.-t1) + pp[iVertex2][0] * t1;
+  double v1 = pp[iVertex1][1] * (1.-t1) + pp[iVertex2][1] * t1;
+  double w1 = pp[iVertex1][2] * (1.-t1) + pp[iVertex2][2] * t1;
+
+  double t2 = (double) (iSubEdge+1) / (double) numSubEdges;
+  double u2 = pp[iVertex1][0] * (1.-t2) + pp[iVertex2][0] * t2;
+  double v2 = pp[iVertex1][1] * (1.-t2) + pp[iVertex2][1] * t2;
+  double w2 = pp[iVertex1][2] * (1.-t2) + pp[iVertex2][2] * t2;
+
+  SPoint3 pnt1, pnt2;
+  tet->pnt(u1,v1,w1,pnt1);
+  tet->pnt(u2,v2,w2,pnt2);
+  x[0] = pnt1.x(); x[1] = pnt2.x(); 
+  y[0] = pnt1.y(); y[1] = pnt2.y();
+  z[0] = pnt1.z(); z[1] = pnt2.z();
+
+  // not great, but better than nothing
+  static const int f[6] = {0, 0, 0, 1, 2, 3};
+  n[0] = n[1] = tet->getFace(f[iEdge]).normal();
+}
+
+void MTetrahedron10::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+void MTetrahedronN::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+int MTetrahedronN::getNumFacesRep(){ return 4 * SQU(CTX::instance()->mesh.numSubEdges); }
+int MTetrahedron10::getNumFacesRep(){ return 4 * SQU(CTX::instance()->mesh.numSubEdges); }
+
+static void _myGetFaceRep(MTetrahedron *tet, int num, double *x, double *y, double *z, 
+                          SVector3 *n, int numSubEdges)
+{
+  static double pp[4][3] = {{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
+  static int fak [4][3] = {{0,1,2},{0,1,3},{0,2,3},{1,2,3}};
+  int iFace    = num / (numSubEdges * numSubEdges);
+  int iSubFace = num % (numSubEdges * numSubEdges);  
+  
+  int iVertex1 = fak[iFace][0];
+  int iVertex2 = fak[iFace][1];
+  int iVertex3 = fak[iFace][2];
+
+  /*
+    0
+    0 1
+    0 1 2
+    0 1 2 3
+    0 1 2 3 4
+    0 1 2 3 4 5
+  */
+
+  // on the first layer, we have (numSubEdges-1) * 2 + 1 triangles
+  // on the second layer, we have (numSubEdges-2) * 2 + 1 triangles
+  // on the ith layer, we have (numSubEdges-1-i) * 2 + 1 triangles
+  int ix = 0, iy = 0;
+  int nbt = 0;
+  for (int i = 0; i < numSubEdges; i++){
+    int nbl = (numSubEdges - i - 1) * 2 + 1;
+    nbt += nbl;
+    if (nbt > iSubFace){
+      iy = i;
+      ix = nbl - (nbt - iSubFace);
+      break;
+    }
+  }
+
+  const double d = 1. / numSubEdges;
+
+  SPoint3 pnt1, pnt2, pnt3;
+  double J1[2][3], J2[2][3], J3[2][3];
+  double u1,v1,u2,v2,u3,v3;
+  if (ix % 2 == 0){
+    u1 = ix / 2 * d; v1= iy*d;
+    u2 = (ix / 2 + 1) * d ; v2 =  iy * d;
+    u3 = ix / 2 * d ; v3 =  (iy+1) * d;
+  }
+  else{
+    u1 = (ix / 2 + 1) * d; v1= iy * d;
+    u2 = (ix / 2 + 1) * d; v2= (iy + 1) * d;
+    u3 = ix / 2 * d ; v3 =  (iy + 1) * d;
+  }
+
+  double U1 = pp[iVertex1][0] * (1.-u1-v1) + pp[iVertex2][0] * u1 + pp[iVertex3][0] * v1;
+  double U2 = pp[iVertex1][0] * (1.-u2-v2) + pp[iVertex2][0] * u2 + pp[iVertex3][0] * v2;
+  double U3 = pp[iVertex1][0] * (1.-u3-v3) + pp[iVertex2][0] * u3 + pp[iVertex3][0] * v3;
+
+  double V1 = pp[iVertex1][1] * (1.-u1-v1) + pp[iVertex2][1] * u1 + pp[iVertex3][1] * v1;
+  double V2 = pp[iVertex1][1] * (1.-u2-v2) + pp[iVertex2][1] * u2 + pp[iVertex3][1] * v2;
+  double V3 = pp[iVertex1][1] * (1.-u3-v3) + pp[iVertex2][1] * u3 + pp[iVertex3][1] * v3;
+
+  double W1 = pp[iVertex1][2] * (1.-u1-v1) + pp[iVertex2][2] * u1 + pp[iVertex3][2] * v1;
+  double W2 = pp[iVertex1][2] * (1.-u2-v2) + pp[iVertex2][2] * u2 + pp[iVertex3][2] * v2;
+  double W3 = pp[iVertex1][2] * (1.-u3-v3) + pp[iVertex2][2] * u3 + pp[iVertex3][2] * v3;
+
+  tet->pnt(U1,V1,W1,pnt1);
+  tet->pnt(U2,V2,W2,pnt2);
+  tet->pnt(U3,V3,W3,pnt3);
+
+  x[0] = pnt1.x(); x[1] = pnt2.x(); x[2] = pnt3.x();
+  y[0] = pnt1.y(); y[1] = pnt2.y(); y[2] = pnt3.y();
+  z[0] = pnt1.z(); z[1] = pnt2.z(); z[2] = pnt3.z();
+
+  SVector3 d1(x[1]-x[0],y[1]-y[0],z[1]-z[0]);
+  SVector3 d2(x[2]-x[0],y[2]-y[0],z[2]-z[0]);
+  n[0] = crossprod(d1, d2);
+  n[0].normalize();
+  n[1] = n[0];
+  n[2] = n[0];
+}
+
+void MTetrahedronN::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+void MTetrahedron10::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+void MTetrahedron::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
+{
+#if !defined(HAVE_GMSH_EMBEDDED)
+  *npts = getNGQTetPts(pOrder);
+  *pts = getGQTetPts(pOrder);
+#endif
+}
diff --git a/Geo/MTetrahedron.h b/Geo/MTetrahedron.h
new file mode 100644
index 0000000000000000000000000000000000000000..21c723185aa58c5cc30a781eca15dc2fdbdfa34a
--- /dev/null
+++ b/Geo/MTetrahedron.h
@@ -0,0 +1,446 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MTETRAHEDRON_H_
+#define _MTETRAHEDRON_H_
+
+#include "MElement.h"
+
+/*
+ * MTetrahedron
+ *
+ *                      v
+ *                    .
+ *                  ,/
+ *                 /
+ *              2
+ *            ,/|`\
+ *          ,/  |  `\
+ *        ,/    '.   `\
+ *      ,/       |     `\
+ *    ,/         |       `\
+ *   0-----------'.--------1 --> u
+ *    `\.         |      ,/
+ *       `\.      |    ,/
+ *          `\.   '. ,/
+ *             `\. |/
+ *                `3
+ *                   `\.
+ *                      ` w
+ *
+ */
+class MTetrahedron : public MElement {
+ protected:
+  MVertex *_v[4];
+  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[edges_tetra(num, 0)];
+    v[1] = _v[edges_tetra(num, 1)];
+  }
+  void _getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[faces_tetra(num, 0)];
+    v[1] = _v[faces_tetra(num, 1)];
+    v[2] = _v[faces_tetra(num, 2)];
+  }
+ public :
+  MTetrahedron(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1; _v[2] = v2; _v[3] = v3;
+  }
+  MTetrahedron(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 4; i++) _v[i] = v[i];
+  }
+  ~MTetrahedron(){}
+  virtual int getDim(){ return 3; }
+  virtual int getNumVertices() const { return 4; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[4] = {0, 2, 1, 3};
+    return getVertex(map[num]);
+  }
+  virtual int getNumEdges(){ return 6; }
+  virtual MEdge getEdge(int num)
+  {
+    return MEdge(_v[edges_tetra(num, 0)], _v[edges_tetra(num, 1)]);
+  }
+  virtual int getNumEdgesRep(){ return 6; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  {
+    static const int f[6] = {0, 0, 0, 1, 2, 3};
+    MEdge e(getEdge(num));
+    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, f[num]);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(num, v);
+  }
+  virtual int getNumFaces(){ return 4; }
+  virtual MFace getFace(int num)
+  {
+    return MFace(_v[faces_tetra(num, 0)],
+		 _v[faces_tetra(num, 1)],
+		 _v[faces_tetra(num, 2)]);
+  }
+  virtual int getNumFacesRep(){ return 4; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    MFace f(getFace(num));
+    _getFaceRep(f.getVertex(0), f.getVertex(1), f.getVertex(2), x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    _getFaceVertices(num, v);
+  }
+  virtual int getTypeForMSH() const { return MSH_TET_4; }
+  virtual int getTypeForUNV() const { return 111; } // solid linear tetrahedron
+  virtual int getTypeForVTK() const { return 10; }
+  virtual const char *getStringForPOS() const { return "SS"; }
+  virtual const char *getStringForBDF() const { return "CTETRA"; }
+  virtual const char *getStringForDIFF() const { return "ElmT4n3D"; }
+  virtual void revert()
+  {
+    MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
+  }
+  void getMat(double mat[3][3])
+  {
+    mat[0][0] = _v[1]->x() - _v[0]->x();
+    mat[0][1] = _v[2]->x() - _v[0]->x();
+    mat[0][2] = _v[3]->x() - _v[0]->x();
+    mat[1][0] = _v[1]->y() - _v[0]->y();
+    mat[1][1] = _v[2]->y() - _v[0]->y();
+    mat[1][2] = _v[3]->y() - _v[0]->y();
+    mat[2][0] = _v[1]->z() - _v[0]->z();
+    mat[2][1] = _v[2]->z() - _v[0]->z();
+    mat[2][2] = _v[3]->z() - _v[0]->z();
+  }
+  virtual double getVolume();
+  virtual int getVolumeSign(){ return (getVolume() >= 0) ? 1 : -1; }
+  virtual double gammaShapeMeasure();
+  virtual double distoShapeMeasure();
+  virtual double etaShapeMeasure();
+  void xyz2uvw(double xyz[3], double uvw[3]);
+  virtual const gmshFunctionSpace* getFunctionSpace(int o=-1) const;
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(u < (-tol) || v < (-tol) || w < (-tol) || u > ((1. + tol) - v - w))
+      return false;
+    return true;
+  }
+  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
+  virtual SPoint3 circumcenter();
+ private:
+  int edges_tetra(const int edge, const int vert) const
+  {
+    static const int e[6][2] = {
+      {0, 1},
+      {1, 2},
+      {2, 0},
+      {3, 0},
+      {3, 2},
+      {3, 1}
+    };
+    return e[edge][vert];
+  }
+  int faces_tetra(const int face, const int vert) const
+  {
+    static const int f[4][3] = {
+      {0, 2, 1},
+      {0, 1, 3},
+      {0, 3, 2},
+      {3, 1, 2}
+    };
+    return f[face][vert];
+  }
+};
+
+/*
+ * MTetrahedron10
+ *
+ *              2 
+ *            ,/|`\
+ *          ,/  |  `\
+ *        ,6    '.   `5
+ *      ,/       8     `\
+ *    ,/         |       `\
+ *   0--------4--'.--------1
+ *    `\.         |      ,/
+ *       `\.      |    ,9
+ *          `7.   '. ,/
+ *             `\. |/
+ *                `3
+ *
+ */
+class MTetrahedron10 : public MTetrahedron {
+ protected:
+  MVertex *_vs[6];
+ public :
+  MTetrahedron10(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, 
+                 MVertex *v5, MVertex *v6, MVertex *v7, MVertex *v8, MVertex *v9,
+                 int num=0, int part=0) 
+    : MTetrahedron(v0, v1, v2, v3, num, part)
+  {
+    _vs[0] = v4; _vs[1] = v5; _vs[2] = v6; _vs[3] = v7; _vs[4] = v8; _vs[5] = v9;
+    for(int i = 0; i < 6; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MTetrahedron10(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MTetrahedron(v, num, part)
+  {
+    for(int i = 0; i < 6; i++) _vs[i] = v[4 + i];
+    for(int i = 0; i < 6; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MTetrahedron10(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 10; }
+  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
+  virtual MVertex *getVertexUNV(int num)
+  {
+    static const int map[10] = {0, 4, 1, 5, 2, 6, 8, 9, 7, 3};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexBDF(int num)
+  {
+    static const int map[10] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 8};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[10] = {0, 2, 1, 3, 6, 5, 4, 7, 8, 9};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    static const int map[10] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 8};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 6; }
+
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual int getNumEdgesRep();
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual int getNumFacesRep();
+
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MTetrahedron::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(6);
+    MTetrahedron::_getFaceVertices(num, v);
+    static const int f[4][3] = {
+      {4, 5, 6},
+      {4, 7, 9},
+      {6, 7, 8},
+      {5, 8, 9}
+    };
+    v[3] = _vs[f[num][0]];
+    v[4] = _vs[f[num][1]];
+    v[5] = _vs[f[num][2]];
+  }
+  virtual int getTypeForMSH() const { return MSH_TET_10; }
+  virtual int getTypeForUNV() const { return 118; } // solid parabolic tetrahedron
+  //virtual int getTypeForVTK() const { return 24; }
+  virtual const char *getStringForPOS() const { return "SS2"; }
+  virtual const char *getStringForBDF() const { return "CTETRA"; }
+  virtual const char *getStringForDIFF() const { return "ElmT10n3D"; }
+  virtual void revert()
+  {
+    MVertex *tmp;
+    tmp = _v[0] ; _v[0]  = _v[1]; _v[1] = tmp;
+    tmp = _vs[1]; _vs[1] = _vs[2]; _vs[2] = tmp;
+    tmp = _vs[5]; _vs[5] = _vs[3]; _vs[3] = tmp;
+  }
+};
+
+/*
+ * MTetrahedronN  FIXME: check the plot
+ *
+ *              2
+ *            ,/|`\ 
+ *          ,/  |  `\              E = order - 1
+ *        ,/    '.   `\            C = 4 + 6*E 
+ *      ,/       |     `\          F = ((order - 1)*(order - 2))/2
+ *    ,/         |       `\	   N = total number of vertices
+ *   0-----------'.--------1
+ *    `\.         |      ,/        Interior vertex numbers  
+ *       `\.      |    ,/            for edge 0 <= i <= 5: 4+i*E to 3+(i+1)*E
+ *          `\.   '. ,/		     for face 0 <= j <= 3: C+j*F to C-1+(j+1)*F
+ *             `\. |/		     in volume           : C+4*F to N-1
+ *                `3
+ *
+ */
+
+
+
+/* tet order 3
+   
+ *              2
+ *            ,/|`\ 
+ *          ,5  |  `6              E = order - 1
+ *        ,/    12   `\            C = 4 + 6*E 
+ *      ,4       |     `7          F = ((order - 1)*(order - 2))/2
+ *    ,/         |       `\	   N = total number of vertices
+ *   0-----9-----'.--8-----1
+ *    `\.         |      ,/        Interior vertex numbers
+ *       10.     13    ,14           for edge 0 <= i <= 5: 4+i*E to 3+(i+1)*E
+ *          `\.   '. 15		     for face 0 <= j <= 3: C+j*F to C-1+(j+1)*F
+ *             11\.|/ 	     in volume           : C+4*F to N-1
+ *                `3
+ *
+ */
+
+static int reverseTet20[20] = {0,2,1,3,  // principal vertices
+                               9,8,      // E0 switches with E2
+                               7,6,      // E1 inverts direction
+                               5,4,      // E2 switches with E0
+                               10,11,    // E3 pure w edge > remains the same
+                               14,15,    // E4 uw edge swithes with v/w edge E5
+                               12,13,    // E5 switches with E4
+                               16,       // F0 is uv plane, reverts normal
+                               18,       // F1 is uw plane, switches with F2
+                               17,       // F2 is vw plane, switches with F1
+                               19};      // F3 is uvw plane, reverts normal
+
+static int reverseTet35[35] = {0,2,1,3,  // principal vertices
+                               
+                               12,11,10, // E0 switches with E2
+                               9,8,7,    // E1 inverts direction
+                               6,5,4,    // E2 switches with E0
+                               13,14,15, // E3 pure w edge > remains the same
+                               19,20,21, // E4 uw edge swithes with v/w edge E5
+                               16,17,18, // E5 switches with E4
+                               22,24,23, // F0 is uv plane, reverts normal
+                               28,30,29, // F1 is uw plane, switches with F2, orientation is different
+                               25,27,26, // F2 is vw plane, switches with F1
+                               31,33,32, // F3 is uvw plane, reverts normal
+                               34};      // central node remains 
+  
+static int reverseTet34[34] = {0,2,1,3,  // principal vertices
+                               12,11,10, // E0 switches with E2
+                               9,8,7,    // E1 inverts direction
+                               6,5,4,    // E2 switches with E0
+                               13,14,15, // E3 pure w edge > remains the same
+                               19,20,21, // E4 uw edge swithes with v/w edge E5
+                               16,17,18, // E5 switches with E4
+                               22,24,23, // F0 is uv plane, reverts normal
+                               28,29,30, // F1 is uw plane, switches with F2
+                               25,26,27, // F2 is vw plane, switches with F1
+                               31,33,32};// F3 is uvw plane, reverts normal
+
+class MTetrahedronN : public MTetrahedron {
+ protected:
+  std::vector<MVertex *> _vs;
+  const char _order;
+  double _disto;
+ public:
+  MTetrahedronN(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, 
+		std::vector<MVertex*> &v, char order, int num=0, int part=0) 
+    : MTetrahedron(v0, v1, v2, v3, num, part) , _vs (v), _order(order),_disto(-1.e22)
+  {
+    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
+  }
+  MTetrahedronN(std::vector<MVertex*> &v, char order, int num=0, int part=0) 
+    : MTetrahedron(v[0], v[1], v[2], v[3], num, part) , _order(order),_disto(-1.e22)
+  {
+    for(unsigned int i = 4; i < v.size(); i++) _vs.push_back(v[i]);
+    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
+  }
+  ~MTetrahedronN(){}
+  virtual double distoShapeMeasure();
+  virtual int getPolynomialOrder() const { return _order; }
+  virtual int getNumVertices() const { return 4 + _vs.size(); }
+  virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
+  virtual int getNumEdgeVertices() const { return 6 * (_order - 1); }
+  virtual int getNumFaceVertices() const
+  {
+    return 4 * ((_order - 1) * (_order - 2)) / 2;
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(_order + 1);
+    MTetrahedron::_getEdgeVertices(num, v);
+    int j = 2;
+    const int ie = (num + 1) * (_order -1);
+    for(int i = num * (_order -1); i != ie; ++i) v[j++] = _vs[i];
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3 + 3 * (_order - 1) + (_order-1) * (_order - 2) /2);
+    MTetrahedron::_getFaceVertices(num, v);
+    int j = 3;
+    int nbV = (_order - 1) * (_order - 2) / 2;
+    const int ie = (num+1)*nbV;
+    for(int i = num*nbV; i != ie; ++i) v[j++] = _vs[i];
+  }
+  virtual int getNumVolumeVertices() const 
+  {
+    switch(getTypeForMSH()){
+    case MSH_TET_35 : return 1;
+    case MSH_TET_56 : return 4;
+    default : return 0;
+    }    
+  }
+  virtual int getTypeForMSH() const 
+  {
+    // (p+1)*(p+2)*(p+3)/6
+    if(_order == 3 && _vs.size() + 4 == 20) return MSH_TET_20; 
+    if(_order == 4 && _vs.size() + 4 == 34) return MSH_TET_34; 
+    if(_order == 4 && _vs.size() + 4 == 35) return MSH_TET_35; 
+    if(_order == 5 && _vs.size() + 4 == 56) return MSH_TET_56; 
+    if(_order == 5 && _vs.size() + 4 == 52) return MSH_TET_52; 
+    return 0;
+  }
+  virtual void revert() 
+  {    
+    MVertex *tmp;
+    tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;    
+    switch (getTypeForMSH()) {
+    case MSH_TET_20:
+      {
+        std::vector<MVertex*> inv(16);
+        for (int i=0;i<16;i++) inv[i] = _vs[reverseTet20[i+4]-4];
+        _vs = inv;
+        break;
+      }
+    case MSH_TET_35:
+      {
+        std::vector<MVertex*> inv(31);
+        for (int i=0;i<31;i++) inv[i] = _vs[reverseTet35[i+4]-4];
+        _vs = inv;
+        break;
+      }
+    case MSH_TET_34:
+      {
+        std::vector<MVertex*> inv(30);
+        for (int i=0;i<30;i++) inv[i] = _vs[reverseTet34[i+4]-4];
+        _vs = inv;
+        break;
+      }
+    default:
+      {
+        Msg::Error("Reversion of %d order tetrahedron (type %d) not implemented\n",
+                   _order, getTypeForMSH());
+        break;
+      }
+    }
+  }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual int getNumEdgesRep();
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual int getNumFacesRep();
+};
+
+#endif
diff --git a/Geo/MTriangle.cpp b/Geo/MTriangle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c334469365c3790e86ba2635004d49ddad5993aa
--- /dev/null
+++ b/Geo/MTriangle.cpp
@@ -0,0 +1,209 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "MTriangle.h"
+#include "Numeric.h"
+
+#if defined(HAVE_GMSH_EMBEDDED)
+#include "GmshEmbedded.h"
+#else
+#include "Context.h"
+#include "qualityMeasures.h"
+#endif
+
+#define SQU(a)      ((a)*(a))
+
+SPoint3 MTriangle::circumcenter()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return SPoint3();
+#else
+  double p1[3] = {_v[0]->x(), _v[0]->y(), _v[0]->z()};
+  double p2[3] = {_v[1]->x(), _v[1]->y(), _v[1]->z()};
+  double p3[3] = {_v[2]->x(), _v[2]->y(), _v[2]->z()};
+  double res[3];
+  circumCenterXYZ(p1, p2, p3, res);
+  return SPoint3(res[0], res[1], res[2]);
+#endif
+}
+
+double MTriangle::distoShapeMeasure()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return 1.;
+#else
+  return qmDistorsionOfMapping(this);
+#endif
+}
+
+double MTriangle::gammaShapeMeasure()
+{
+#if defined(HAVE_GMSH_EMBEDDED)
+  return 0.;
+#else
+  return qmTriangle(this, QMTRI_RHO);
+#endif
+}
+
+const gmshFunctionSpace* MTriangle::getFunctionSpace(int o) const
+{
+  int order = (o == -1) ? getPolynomialOrder() : o;
+
+  int nf = getNumFaceVertices();  
+
+  if ((nf == 0) && (o == -1)) {
+    switch (order) {
+    case 1: return &gmshFunctionSpaces::find(MSH_TRI_3);
+    case 2: return &gmshFunctionSpaces::find(MSH_TRI_6);
+    case 3: return &gmshFunctionSpaces::find(MSH_TRI_9);
+    case 4: return &gmshFunctionSpaces::find(MSH_TRI_12);
+    case 5: return &gmshFunctionSpaces::find(MSH_TRI_15I);
+    default: Msg::Error("Order %d triangle function space not implemented", order);
+    }
+  }
+  else { 
+    switch (order) {
+    case 1: return &gmshFunctionSpaces::find(MSH_TRI_3);
+    case 2: return &gmshFunctionSpaces::find(MSH_TRI_6);
+    case 3: return &gmshFunctionSpaces::find(MSH_TRI_10);
+    case 4: return &gmshFunctionSpaces::find(MSH_TRI_15);
+    case 5: return &gmshFunctionSpaces::find(MSH_TRI_21);
+    default: Msg::Error("Order %d triangle function space not implemented", order);
+    }
+  }
+  return 0;
+}
+
+int MTriangleN::getNumEdgesRep(){ return 3 * CTX::instance()->mesh.numSubEdges; }
+int MTriangle6::getNumEdgesRep(){ return 3 * CTX::instance()->mesh.numSubEdges; }
+
+static void _myGetEdgeRep(MTriangle *t, int num, double *x, double *y, double *z,
+                          SVector3 *n, int numSubEdges)
+{
+  n[0] = n[1] = n[2] = t->getFace(0).normal();
+
+  if (num < numSubEdges){
+    SPoint3 pnt1, pnt2;
+    t->pnt((double)num / numSubEdges, 0., 0.,pnt1);
+    t->pnt((double)(num + 1) / numSubEdges, 0., 0, pnt2);
+    x[0] = pnt1.x(); x[1] = pnt2.x();
+    y[0] = pnt1.y(); y[1] = pnt2.y();
+    z[0] = pnt1.z(); z[1] = pnt2.z();
+    return;
+  }  
+  if (num < 2 * numSubEdges){
+    SPoint3 pnt1, pnt2;
+    num -= numSubEdges;
+    t->pnt(1. - (double)num / numSubEdges, (double)num / numSubEdges, 0, pnt1);
+    t->pnt(1. - (double)(num + 1) / numSubEdges, (double)(num + 1) / numSubEdges, 0, pnt2);
+    x[0] = pnt1.x(); x[1] = pnt2.x();
+    y[0] = pnt1.y(); y[1] = pnt2.y();
+    z[0] = pnt1.z(); z[1] = pnt2.z();
+    return ;
+  }  
+  {
+    SPoint3 pnt1, pnt2;
+    num -= 2 * numSubEdges;
+    t->pnt(0, (double)num / numSubEdges, 0,pnt1);
+    t->pnt(0, (double)(num + 1) / numSubEdges, 0,pnt2);
+    x[0] = pnt1.x(); x[1] = pnt2.x();
+    y[0] = pnt1.y(); y[1] = pnt2.y();
+    z[0] = pnt1.z(); z[1] = pnt2.z();
+  }
+}
+
+void MTriangleN::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+void MTriangle6::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetEdgeRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+int MTriangle6::getNumFacesRep(){ return SQU(CTX::instance()->mesh.numSubEdges); }
+int MTriangleN::getNumFacesRep(){ return SQU(CTX::instance()->mesh.numSubEdges); }
+
+static void _myGetFaceRep(MTriangle *t, int num, double *x, double *y, double *z,
+                          SVector3 *n, int numSubEdges)
+{
+
+  // on the first layer, we have (numSubEdges-1) * 2 + 1 triangles
+  // on the second layer, we have (numSubEdges-2) * 2 + 1 triangles
+  // on the ith layer, we have (numSubEdges-1-i) * 2 + 1 triangles
+  int ix = 0, iy = 0;
+  int nbt = 0;
+  for (int i = 0; i < numSubEdges; i++){
+    int nbl = (numSubEdges - i - 1) * 2 + 1;
+    nbt += nbl;
+    if (nbt > num){
+      iy = i;
+      ix = nbl - (nbt - num);
+      break;
+    }
+  }
+
+  const double d = 1. / numSubEdges;
+
+  SPoint3 pnt1, pnt2, pnt3;
+  double J1[3][3], J2[3][3], J3[3][3];
+  if (ix % 2 == 0){
+    t->pnt(ix / 2 * d, iy * d, 0, pnt1);
+    t->pnt((ix / 2 + 1) * d, iy * d, 0, pnt2);
+    t->pnt(ix / 2 * d, (iy + 1) * d, 0, pnt3);
+    t->getJacobian(ix / 2 * d, iy * d, 0, J1);
+    t->getJacobian((ix / 2 + 1) * d, iy * d, 0, J2);
+    t->getJacobian(ix / 2 * d, (iy + 1) * d, 0, J3);
+  }
+  else{
+    t->pnt((ix / 2 + 1) * d, iy * d, 0, pnt1);
+    t->pnt((ix / 2 + 1) * d, (iy + 1) * d, 0, pnt2);
+    t->pnt(ix / 2 * d, (iy + 1) * d, 0, pnt3);
+    t->getJacobian((ix / 2 + 1) * d, iy * d, 0, J1);
+    t->getJacobian((ix / 2 + 1) * d, (iy + 1) * d, 0, J2);
+    t->getJacobian(ix / 2 * d, (iy + 1) * d, 0, J3);
+  }
+  {
+    SVector3 d1(J1[0][0], J1[0][1], J1[0][2]);
+    SVector3 d2(J1[1][0], J1[1][1], J1[1][2]);
+    n[0] = crossprod(d1, d2);
+    n[0].normalize();
+  }
+  {
+    SVector3 d1(J2[0][0], J2[0][1], J2[0][2]);
+    SVector3 d2(J2[1][0], J2[1][1], J2[1][2]);
+    n[1] = crossprod(d1, d2);
+    n[1].normalize();
+  }
+  {
+    SVector3 d1(J3[0][0], J3[0][1], J3[0][2]);
+    SVector3 d2(J3[1][0], J3[1][1], J3[1][2]);
+    n[2] = crossprod(d1, d2);
+    n[2].normalize();
+  }
+
+  x[0] = pnt1.x(); x[1] = pnt2.x(); x[2] = pnt3.x();
+  y[0] = pnt1.y(); y[1] = pnt2.y(); y[2] = pnt3.y();
+  z[0] = pnt1.z(); z[1] = pnt2.z(); z[2] = pnt3.z();
+}
+
+void MTriangleN::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+void MTriangle6::getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  _myGetFaceRep(this, num, x, y, z, n, CTX::instance()->mesh.numSubEdges);
+}
+
+void MTriangle::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
+{
+#if !defined(HAVE_GMSH_EMBEDDED)
+  *npts = getNGQTPts(pOrder);
+  *pts = getGQTPts(pOrder);
+#endif
+}
+
diff --git a/Geo/MTriangle.h b/Geo/MTriangle.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d52e2bb913642d478507a265486c3dc4ba99796
--- /dev/null
+++ b/Geo/MTriangle.h
@@ -0,0 +1,333 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _MTRIANGLE_H_
+#define _MTRIANGLE_H_
+
+#include "MElement.h"
+
+/* 
+ * MTriangle
+ *
+ *   v
+ *   ^
+ *   |
+ *   2
+ *   |`\
+ *   |  `\
+ *   |    `\
+ *   |      `\
+ *   |        `\
+ *   0----------1 --> u
+ *
+ */
+class MTriangle : public MElement {
+ protected:
+  MVertex *_v[3];
+  void _getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[edges_tri(num, 0)];
+    v[1] = _v[edges_tri(num, 1)];
+  }
+  void _getFaceVertices(std::vector<MVertex*> &v) const
+  {
+    v[0] = _v[0];
+    v[1] = _v[1];
+    v[2] = _v[2];
+  }
+ public :
+  MTriangle(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    _v[0] = v0; _v[1] = v1; _v[2] = v2;
+  }
+  MTriangle(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MElement(num, part)
+  {
+    for(int i = 0; i < 3; i++) _v[i] = v[i];
+  }
+  ~MTriangle(){}
+  virtual int getDim(){ return 2; }
+  virtual double gammaShapeMeasure();
+  virtual double distoShapeMeasure();
+  virtual int getNumVertices() const { return 3; }
+  virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[3] = {0, 2, 1};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getOtherVertex(MVertex *v1, MVertex *v2)
+  { 
+    if(_v[0] != v1 && _v[0] != v2) return _v[0];
+    if(_v[1] != v1 && _v[1] != v2) return _v[1];
+    if(_v[2] != v1 && _v[2] != v2) return _v[2];
+    return 0;
+  }
+  virtual int getNumEdges(){ return 3; }
+  virtual MEdge getEdge(int num)
+  {
+    return MEdge(_v[edges_tri(num, 0)], _v[edges_tri(num, 1)]);
+  }
+  virtual int getNumEdgesRep(){ return 3; }
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    MEdge e(getEdge(num));
+    _getEdgeRep(e.getVertex(0), e.getVertex(1), x, y, z, n, 0);
+  }
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(2);
+    _getEdgeVertices(num, v);
+  }
+  virtual int getNumFaces(){ return 1; }
+  virtual MFace getFace(int num)
+  { 
+    return MFace(_v[0], _v[1], _v[2]); 
+  }
+  virtual int getNumFacesRep(){ return 1; }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n)
+  { 
+    _getFaceRep(_v[0], _v[1], _v[2], x, y, z, n);
+  }
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    _getFaceVertices(v);
+  }
+  virtual int getTypeForMSH() const { return MSH_TRI_3; }
+  virtual int getTypeForUNV() const { return 91; } // thin shell linear triangle
+  virtual int getTypeForVTK() const { return 5; }
+  virtual const char *getStringForPOS() const { return "ST"; }
+  virtual const char *getStringForBDF() const { return "CTRIA3"; }
+  virtual const char *getStringForDIFF() const { return "ElmT3n2D"; }
+  virtual void revert() 
+  {
+    MVertex *tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
+  }
+  virtual const gmshFunctionSpace* getFunctionSpace(int o=-1) const;
+  virtual bool isInside(double u, double v, double w)
+  {
+    double tol = _isInsideTolerance;
+    if(u < (-tol) || v < (-tol) || u > ((1. + tol) - v))
+      return false; 
+    return true;
+  }
+  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const;
+  virtual SPoint3 circumcenter();
+ private:
+  int edges_tri(const int edge, const int vert) const
+  {
+    static const int e[3][2] = {
+      {0, 1},
+      {1, 2},
+      {2, 0}
+    };
+    return e[edge][vert];
+  }
+};
+
+/*
+ * MTriangle6
+ *
+ *   2
+ *   |`\
+ *   |  `\
+ *   5    `4
+ *   |      `\
+ *   |        `\
+ *   0-----3----1
+ *
+ */
+class MTriangle6 : public MTriangle {
+ protected:
+  MVertex *_vs[3];
+ public :
+  MTriangle6(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4,
+             MVertex *v5, int num=0, int part=0) 
+    : MTriangle(v0, v1, v2, num, part)
+  {
+    _vs[0] = v3; _vs[1] = v4; _vs[2] = v5;
+    for(int i = 0; i < 3; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  MTriangle6(std::vector<MVertex*> &v, int num=0, int part=0) 
+    : MTriangle(v, num, part)
+  {
+    for(int i = 0; i < 3; i++) _vs[i] = v[3 + i];
+    for(int i = 0; i < 3; i++) _vs[i]->setPolynomialOrder(2);
+  }
+  ~MTriangle6(){}
+  virtual int getPolynomialOrder() const { return 2; }
+  virtual int getNumVertices() const { return 6; }
+  virtual MVertex *getVertex(int num){ return num < 3 ? _v[num] : _vs[num - 3]; }
+  virtual MVertex *getVertexUNV(int num)
+  {
+    static const int map[6] = {0, 3, 1, 4, 2, 5};
+    return getVertex(map[num]); 
+  }
+  virtual MVertex *getVertexMED(int num)
+  {
+    static const int map[6] = {0, 2, 1, 5, 4, 3};
+    return getVertex(map[num]); 
+  }
+  virtual int getNumEdgeVertices() const { return 3; }
+  virtual int getNumEdgesRep();
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3);
+    MTriangle::_getEdgeVertices(num, v);
+    v[2] = _vs[num];
+  }
+  virtual int getNumFacesRep();
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(6);
+    MTriangle::_getFaceVertices(v);
+    v[3] = _vs[0];
+    v[4] = _vs[1];
+    v[5] = _vs[2];
+  }
+  virtual int getTypeForMSH() const { return MSH_TRI_6; }
+  virtual int getTypeForUNV() const { return 92; } // thin shell parabolic triangle
+  //virtual int getTypeForVTK() const { return 22; }
+  virtual const char *getStringForPOS() const { return "ST2"; }
+  virtual const char *getStringForBDF() const { return "CTRIA6"; }
+  virtual const char *getStringForDIFF() const { return "ElmT6n2D"; }
+  virtual void revert() 
+  {
+    MVertex *tmp;
+    tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
+    tmp = _vs[0]; _vs[0] = _vs[2]; _vs[2] = tmp;
+  }
+};
+
+/*
+ * MTriangleN  FIXME: check the plot
+ *
+ *   2
+ *   |`\                E = order - 1;
+ *   |  `\              N = total number of vertices
+ * 3+2E   2+2E
+ *   |      `\          Interior vertex numbers
+ *  ...       ...         for edge 0 <= i <= 2: 3+i*E to 2+(i+1)*E
+ *   |          `\        in volume           : 3+3*E to N-1
+ * 2+3E           3+E
+ *   |  3+3E to N-1 `\
+ *   |                `\
+ *   0---3--...---2+E---1
+ *
+ */
+class MTriangleN : public MTriangle {
+ protected:
+  std::vector<MVertex *> _vs;
+  const char _order;
+ public:
+  MTriangleN(MVertex *v0, MVertex *v1, MVertex *v2, 
+             std::vector<MVertex*> &v, char order, int num=0, int part=0) 
+    : MTriangle(v0, v1, v2, num, part), _vs(v), _order(order)
+  {
+    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
+  }
+  MTriangleN(std::vector<MVertex*> &v, char order, int num=0, int part=0) 
+    : MTriangle(v[0], v[1], v[2], num, part), _order(order)
+  {
+    for(unsigned int i = 3; i < v.size(); i++) _vs.push_back(v[i]);
+    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
+  }
+  ~MTriangleN(){}
+  virtual int getPolynomialOrder() const { return _order; }
+  virtual int getNumVertices() const { return 3 + _vs.size(); }
+  virtual MVertex *getVertex(int num){ return num < 3 ? _v[num] : _vs[num - 3]; }
+  virtual int getNumFaceVertices() const 
+  {
+    if(_order == 3 && _vs.size() == 6) return 0;
+    if(_order == 3 && _vs.size() == 7) return 1;
+    if(_order == 4 && _vs.size() == 9) return 0;
+    if(_order == 4 && _vs.size() == 12) return 3;
+    if(_order == 5 && _vs.size() == 12) return 0;
+    if(_order == 5 && _vs.size() == 18) return 6;
+    return 0;
+  }
+  virtual int getNumEdgeVertices() const { return 3 * (_order - 1); }
+  virtual int getNumEdgesRep();
+  virtual int getNumFacesRep();
+  virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(_order + 1);
+    MTriangle::_getEdgeVertices(num, v);
+    int j = 2;
+    const int ie = (num + 1) * (_order - 1);
+    for(int i = num * (_order-1); i != ie; ++i) v[j++] = _vs[i];
+  }
+  virtual void getFaceRep(int num, double *x, double *y, double *z, SVector3 *n);
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize(3 + _vs.size());
+    MTriangle::_getFaceVertices(v);
+    for(unsigned int i = 0; i != _vs.size(); ++i) v[i + 3] = _vs[i];
+  }
+  virtual int getTypeForMSH() const
+  {
+    if(_order == 2 && _vs.size() == 3) return MSH_TRI_6; 
+    if(_order == 3 && _vs.size() == 6) return MSH_TRI_9; 
+    if(_order == 3 && _vs.size() == 7) return MSH_TRI_10; 
+    if(_order == 4 && _vs.size() == 9) return MSH_TRI_12; 
+    if(_order == 4 && _vs.size() == 12) return MSH_TRI_15; 
+    if(_order == 5 && _vs.size() == 12) return MSH_TRI_15I; 
+    if(_order == 5 && _vs.size() == 18) return MSH_TRI_21;
+    return 0;
+  }
+  virtual void revert() 
+  {
+    MVertex *tmp;
+    tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
+    std::vector<MVertex*> inv;
+    inv.insert(inv.begin(), _vs.rbegin(), _vs.rend());
+    _vs = inv;
+  }
+};
+
+template <class T> 
+void sort3(T *t[3])
+{
+  T *temp;
+  if(t[0] > t[1]){
+    temp = t[1];
+    t[1] = t[0];
+    t[0] = temp;
+  }
+  if(t[1] > t[2]){
+    temp = t[2];
+    t[2] = t[1];
+    t[1] = temp;
+  }
+  if(t[0] > t[1]){
+    temp = t[1];
+    t[1] = t[0];
+    t[0] = temp;
+  }
+}
+
+struct compareMTriangleLexicographic
+{
+  bool operator () (MTriangle *t1, MTriangle *t2) const
+  {
+    MVertex *_v1[3] = {t1->getVertex(0), t1->getVertex(1), t1->getVertex(2)};
+    MVertex *_v2[3] = {t2->getVertex(0), t2->getVertex(1), t2->getVertex(2)};
+    sort3(_v1);
+    sort3(_v2);
+    if(_v1[0] < _v2[0]) return true;
+    if(_v1[0] > _v2[0]) return false;
+    if(_v1[1] < _v2[1]) return true;
+    if(_v1[1] > _v2[1]) return false;
+    if(_v1[2] < _v2[2]) return true;
+    return false;
+  }
+};
+
+#endif
diff --git a/Geo/Makefile b/Geo/Makefile
index 9e99d4363732b3d116a49cfcf43f9f7a4442d53c..4d350d101f1f1348bcbbd72ee517ee369b1e0349 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -15,25 +15,28 @@ INC = ${DASH}I../Common ${DASH}I../Geo ${DASH}I../Mesh\
 CFLAGS = ${OPTIM} ${FLAGS} ${INC} ${SYSINCLUDE}
 
 SRC = GEntity.cpp\
-      GVertex.cpp GEdge.cpp GEdgeLoop.cpp GFace.cpp GEdgeCompound.cpp GFaceCompound.cpp GRegion.cpp\
-      gmshVertex.cpp gmshEdge.cpp gmshFace.cpp gmshRegion.cpp gmshSurface.cpp\
-      OCCVertex.cpp OCCEdge.cpp OCCFace.cpp OCCRegion.cpp\
-      discreteEdge.cpp discreteFace.cpp discreteRegion.cpp\
-      fourierEdge.cpp fourierFace.cpp fourierProjectionFace.cpp\
+        GVertex.cpp GEdge.cpp GFace.cpp GRegion.cpp\
+        GEdgeLoop.cpp GEdgeCompound.cpp GFaceCompound.cpp\
+        gmshVertex.cpp gmshEdge.cpp gmshFace.cpp gmshRegion.cpp gmshSurface.cpp\
+        OCCVertex.cpp OCCEdge.cpp OCCFace.cpp OCCRegion.cpp\
+        discreteEdge.cpp discreteFace.cpp discreteRegion.cpp\
+        fourierEdge.cpp fourierFace.cpp fourierProjectionFace.cpp\
       GModel.cpp\
-      GModelIO_Geo.cpp\
-      GModelIO_Mesh.cpp\
-      GModelIO_OCC.cpp\
-      GModelIO_Fourier.cpp\
-      GModelIO_CGNS.cpp\
-      GModelIO_MED.cpp\
-      ExtrudeParams.cpp \
-      Geo.cpp \
+        GModelIO_Geo.cpp\
+        GModelIO_Mesh.cpp\
+        GModelIO_OCC.cpp\
+        GModelIO_Fourier.cpp\
+        GModelIO_CGNS.cpp\
+        GModelIO_MED.cpp\
+      ExtrudeParams.cpp\
+      Geo.cpp\
       GeoStringInterface.cpp GeoInterpolation.cpp\
       findLinks.cpp\
       MVertex.cpp\
       MFace.cpp\
       MElement.cpp\
+        MLine.cpp MTriangle.cpp MQuadrangle.cpp MTetrahedron.cpp\
+        MHexahedron.cpp MPrism.cpp MPyramid.cpp\
       MZone.cpp MZoneBoundary.cpp
 
 OBJ = ${SRC:.cpp=${OBJEXT}}
@@ -72,56 +75,57 @@ GEntity${OBJEXT}: GEntity.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
   ../Mesh/meshPartitionOptions.h
 GVertex${OBJEXT}: GVertex.cpp GVertex.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h GPoint.h SPoint2.h GFace.h GEdgeLoop.h GEdge.h \
-  SVector3.h Pair.h MElement.h ../Common/GmshDefines.h MVertex.h MEdge.h \
-  MFace.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  SVector3.h Pair.h MPoint.h MElement.h ../Common/GmshDefines.h MVertex.h \
+  MEdge.h MFace.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h
 GEdge${OBJEXT}: GEdge.cpp ../Common/GmshConfig.h ../Common/GmshDefines.h \
   ../Common/GmshMessage.h GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h \
-  GEdgeLoop.h Pair.h GRegion.h MElement.h MVertex.h MEdge.h MFace.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
-  ../Numeric/GaussLegendre1D.h
-GEdgeLoop${OBJEXT}: GEdgeLoop.cpp GEdgeLoop.h GEdge.h GEntity.h Range.h \
-  SPoint3.h SBoundingBox3d.h GVertex.h GPoint.h SPoint2.h SVector3.h \
-  ../Common/GmshMessage.h
+  GEdgeLoop.h Pair.h GRegion.h MLine.h MElement.h MVertex.h MEdge.h \
+  MFace.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Numeric/Gauss.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h ../Numeric/GaussLegendre1D.h
 GFace${OBJEXT}: GFace.cpp ../Common/GmshConfig.h ../Common/GmshMessage.h \
   GModel.h GVertex.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h \
   GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h GEdgeLoop.h Pair.h \
-  GRegion.h MElement.h ../Common/GmshDefines.h MVertex.h MEdge.h MFace.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  ../Common/VertexArray.h ../Geo/SVector3.h ../Numeric/Numeric.h \
-  ../Numeric/GmshMatrix.h ../Numeric/GaussLegendre1D.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
+  GRegion.h MTriangle.h MElement.h ../Common/GmshDefines.h MVertex.h \
+  MEdge.h MFace.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Numeric/Gauss.h MQuadrangle.h ../Common/VertexArray.h \
+  ../Geo/SVector3.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
+  ../Numeric/GaussLegendre1D.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h
+GRegion${OBJEXT}: GRegion.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
+  SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h \
+  GEdgeLoop.h Pair.h GRegion.h MTetrahedron.h MElement.h \
+  ../Common/GmshDefines.h MVertex.h MEdge.h MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  MHexahedron.h MPrism.h MPyramid.h
+GEdgeLoop${OBJEXT}: GEdgeLoop.cpp GEdgeLoop.h GEdge.h GEntity.h Range.h \
+  SPoint3.h SBoundingBox3d.h GVertex.h GPoint.h SPoint2.h SVector3.h \
+  ../Common/GmshMessage.h
 GEdgeCompound${OBJEXT}: GEdgeCompound.cpp ../Common/GmshConfig.h GEdgeCompound.h \
   GFace.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h GPoint.h \
   GEdgeLoop.h GEdge.h GVertex.h SPoint2.h SVector3.h Pair.h \
   ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/GmshMessage.h
 GFaceCompound${OBJEXT}: GFaceCompound.cpp ../Common/GmshConfig.h GFaceCompound.h \
   GFace.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h GPoint.h \
-  GEdgeLoop.h GEdge.h GVertex.h SPoint2.h SVector3.h Pair.h \
-  ../Numeric/gmshAssembler.h ../Numeric/gmshLinearSystem.h \
-  ../Numeric/gmshLaplace.h ../Numeric/gmshTermOfFormulation.h \
-  ../Numeric/GmshMatrix.h ../Common/GmshMessage.h \
+  GEdgeLoop.h GEdge.h GVertex.h SPoint2.h SVector3.h Pair.h MLine.h \
+  MElement.h ../Common/GmshDefines.h MVertex.h MEdge.h MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Numeric/Gauss.h MTriangle.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/Octree.h \
+  ../Common/OctreeInternals.h ../Numeric/gmshAssembler.h \
+  ../Numeric/gmshLinearSystem.h ../Numeric/gmshLaplace.h \
+  ../Numeric/gmshTermOfFormulation.h ../Numeric/GmshMatrix.h \
   ../Numeric/gmshFunction.h ../Numeric/gmshAssembler.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h ../Geo/GRegion.h \
   ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
-  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  ../Numeric/gmshFunction.h ../Common/Gmsh.h ../Common/GmshMessage.h \
-  ../Numeric/GmshMatrix.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
-  ../Common/Octree.h ../Common/OctreeInternals.h \
+  ../Geo/MElement.h ../Numeric/gmshFunction.h ../Common/Gmsh.h \
+  ../Common/GmshMessage.h ../Numeric/GmshMatrix.h \
   ../Numeric/gmshLinearSystemGmm.h ../Numeric/gmshLinearSystem.h \
   ../Numeric/gmshLinearSystemFull.h ../Numeric/gmshLinearSystem.h \
   ../Numeric/GmshMatrix.h
-GRegion${OBJEXT}: GRegion.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
-  SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h \
-  GEdgeLoop.h Pair.h GRegion.h MElement.h ../Common/GmshDefines.h \
-  MVertex.h MEdge.h MFace.h ../Common/GmshMessage.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Common/GmshConfig.h ../Numeric/Gauss.h
 gmshVertex${OBJEXT}: gmshVertex.cpp GFace.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h GPoint.h GEdgeLoop.h GEdge.h GVertex.h SPoint2.h \
   SVector3.h Pair.h gmshVertex.h Geo.h ../Common/GmshDefines.h \
@@ -129,7 +133,7 @@ gmshVertex${OBJEXT}: gmshVertex.cpp GFace.h GEntity.h Range.h SPoint3.h \
   ../Common/GmshConfig.h ../Common/GmshMessage.h ../Common/ListUtils.h \
   ../Common/TreeUtils.h ../Common/avl.h ../Common/ListUtils.h \
   ExtrudeParams.h ../Common/SmoothData.h GeoInterpolation.h MVertex.h \
-  MElement.h MEdge.h MFace.h ../Numeric/FunctionSpace.h \
+  MPoint.h MElement.h MEdge.h MFace.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Numeric/Gauss.h
 gmshEdge${OBJEXT}: gmshEdge.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h \
@@ -161,10 +165,11 @@ gmshSurface${OBJEXT}: gmshSurface.cpp ../Common/GmshConfig.h \
   ../Numeric/GmshMatrix.h
 OCCVertex${OBJEXT}: OCCVertex.cpp ../Common/GmshConfig.h GModel.h GVertex.h \
   GEntity.h Range.h SPoint3.h SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h \
-  SVector3.h GFace.h GEdgeLoop.h Pair.h GRegion.h MVertex.h MElement.h \
-  ../Common/GmshDefines.h MEdge.h MFace.h ../Common/GmshMessage.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  OCCVertex.h OCCIncludes.h OCCEdge.h OCCFace.h
+  SVector3.h GFace.h GEdgeLoop.h Pair.h GRegion.h MVertex.h MPoint.h \
+  MElement.h ../Common/GmshDefines.h MEdge.h MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Numeric/Gauss.h OCCVertex.h OCCIncludes.h \
+  OCCEdge.h OCCFace.h
 OCCEdge${OBJEXT}: OCCEdge.cpp ../Common/GmshConfig.h ../Common/GmshMessage.h \
   GModel.h GVertex.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h \
   GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h GEdgeLoop.h Pair.h \
@@ -222,13 +227,15 @@ fourierProjectionFace${OBJEXT}: fourierProjectionFace.cpp ../Common/GmshConfig.h
 GModel${OBJEXT}: GModel.cpp ../Common/GmshConfig.h ../Common/GmshMessage.h \
   GModel.h GVertex.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h \
   GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h GEdgeLoop.h Pair.h \
-  GRegion.h MElement.h ../Common/GmshDefines.h MVertex.h MEdge.h MFace.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  discreteRegion.h discreteFace.h discreteEdge.h discreteVertex.h \
-  gmshSurface.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
-  ../Common/Octree.h ../Common/OctreeInternals.h ../Common/SmoothData.h \
-  ../Mesh/Field.h ../Post/PView.h ../Geo/SPoint3.h ../Mesh/Generator.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
+  GRegion.h MPoint.h MElement.h ../Common/GmshDefines.h MVertex.h MEdge.h \
+  MFace.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Numeric/Gauss.h MLine.h MTriangle.h MQuadrangle.h MTetrahedron.h \
+  MHexahedron.h MPrism.h MPyramid.h discreteRegion.h discreteFace.h \
+  discreteEdge.h discreteVertex.h gmshSurface.h ../Numeric/Numeric.h \
+  ../Numeric/GmshMatrix.h ../Common/Octree.h ../Common/OctreeInternals.h \
+  ../Common/SmoothData.h ../Mesh/Field.h ../Post/PView.h ../Geo/SPoint3.h \
+  ../Mesh/Generator.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h
 GModelIO_Geo${OBJEXT}: GModelIO_Geo.cpp ../Common/GmshConfig.h \
   ../Common/GmshMessage.h GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h SVector3.h GFace.h \
@@ -241,11 +248,12 @@ GModelIO_Geo${OBJEXT}: GModelIO_Geo.cpp ../Common/GmshConfig.h \
   ../Geo/SPoint3.h ../Parser/Parser.h
 GModelIO_Mesh${OBJEXT}: GModelIO_Mesh.cpp GModel.h GVertex.h GEntity.h Range.h \
   SPoint3.h SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h SVector3.h \
-  GFace.h GEdgeLoop.h Pair.h GRegion.h ../Common/GmshDefines.h MElement.h \
-  MVertex.h MEdge.h MFace.h ../Common/GmshMessage.h \
+  GFace.h GEdgeLoop.h Pair.h GRegion.h ../Common/GmshDefines.h MPoint.h \
+  MElement.h MVertex.h MEdge.h MFace.h ../Common/GmshMessage.h \
   ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Common/GmshConfig.h ../Numeric/Gauss.h discreteRegion.h \
-  discreteFace.h ../Common/StringUtils.h
+  ../Common/GmshConfig.h ../Numeric/Gauss.h MLine.h MTriangle.h \
+  MQuadrangle.h MTetrahedron.h MHexahedron.h MPrism.h MPyramid.h \
+  discreteRegion.h discreteFace.h ../Common/StringUtils.h
 GModelIO_OCC${OBJEXT}: GModelIO_OCC.cpp ../Common/GmshConfig.h \
   ../Common/GmshMessage.h GModelIO_OCC.h GModel.h GVertex.h GEntity.h \
   Range.h SPoint3.h SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h \
@@ -315,13 +323,55 @@ MFace${OBJEXT}: MFace.cpp ../Common/GmshConfig.h MFace.h MVertex.h SPoint2.h \
 MElement${OBJEXT}: MElement.cpp ../Common/GmshConfig.h ../Common/GmshMessage.h \
   MElement.h ../Common/GmshDefines.h MVertex.h SPoint2.h SPoint3.h \
   MEdge.h SVector3.h MFace.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h ../Numeric/Gauss.h GEntity.h Range.h \
-  SBoundingBox3d.h GFace.h GPoint.h GEdgeLoop.h GEdge.h GVertex.h Pair.h \
-  ../Common/StringUtils.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
+  ../Numeric/GmshMatrix.h ../Numeric/Gauss.h MPoint.h MLine.h MTriangle.h \
+  MQuadrangle.h MTetrahedron.h MHexahedron.h MPrism.h MPyramid.h \
+  GEntity.h Range.h SBoundingBox3d.h GFace.h GPoint.h GEdgeLoop.h GEdge.h \
+  GVertex.h Pair.h ../Common/StringUtils.h ../Numeric/Numeric.h \
+  ../Numeric/GmshMatrix.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h
+MLine${OBJEXT}: MLine.cpp MLine.h MElement.h ../Common/GmshDefines.h MVertex.h \
+  SPoint2.h SPoint3.h MEdge.h SVector3.h MFace.h ../Common/GmshMessage.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Common/GmshConfig.h ../Numeric/Gauss.h ../Numeric/GaussLegendre1D.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
+  ../Mesh/qualityMeasures.h
+MTriangle${OBJEXT}: MTriangle.cpp MTriangle.h MElement.h ../Common/GmshDefines.h \
+  MVertex.h SPoint2.h SPoint3.h MEdge.h SVector3.h MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
+  ../Mesh/qualityMeasures.h
+MQuadrangle${OBJEXT}: MQuadrangle.cpp MQuadrangle.h MElement.h \
+  ../Common/GmshDefines.h MVertex.h SPoint2.h SPoint3.h MEdge.h \
+  SVector3.h MFace.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
   ../Numeric/GaussLegendre1D.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/meshPartitionOptions.h ../Mesh/qualityMeasures.h \
-  ../Mesh/meshGFaceDelaunayInsertion.h ../Geo/MElement.h \
-  ../Mesh/meshGRegionDelaunayInsertion.h ../Mesh/BackgroundMesh.h \
+  ../Mesh/meshPartitionOptions.h ../Mesh/qualityMeasures.h
+MTetrahedron${OBJEXT}: MTetrahedron.cpp MTetrahedron.h MElement.h \
+  ../Common/GmshDefines.h MVertex.h SPoint2.h SPoint3.h MEdge.h \
+  SVector3.h MFace.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
+  ../Mesh/qualityMeasures.h ../Mesh/meshGFaceDelaunayInsertion.h \
+  ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Mesh/meshGRegionDelaunayInsertion.h ../Geo/MTetrahedron.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Mesh/BackgroundMesh.h \
   ../Mesh/qualityMeasures.h
+MHexahedron${OBJEXT}: MHexahedron.cpp MHexahedron.h MElement.h \
+  ../Common/GmshDefines.h MVertex.h SPoint2.h SPoint3.h MEdge.h \
+  SVector3.h MFace.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h
+MPrism${OBJEXT}: MPrism.cpp MPrism.h MElement.h ../Common/GmshDefines.h \
+  MVertex.h SPoint2.h SPoint3.h MEdge.h SVector3.h MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h
+MPyramid${OBJEXT}: MPyramid.cpp MPyramid.h MElement.h ../Common/GmshDefines.h \
+  MVertex.h SPoint2.h SPoint3.h MEdge.h SVector3.h MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h
 MZone${OBJEXT}: MZone.cpp ../Common/GmshConfig.h
 MZoneBoundary${OBJEXT}: MZoneBoundary.cpp ../Common/GmshConfig.h
diff --git a/Geo/OCCVertex.cpp b/Geo/OCCVertex.cpp
index 825bd0f18587b6ac3e5cfb19b8f038c6c9385e4b..16f52706f3158962a17bb4386fb67e9b263667fd 100644
--- a/Geo/OCCVertex.cpp
+++ b/Geo/OCCVertex.cpp
@@ -6,7 +6,7 @@
 #include "GmshConfig.h"
 #include "GModel.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MPoint.h"
 #include "OCCVertex.h"
 #include "OCCEdge.h"
 #include "OCCFace.h"
diff --git a/Geo/gmshVertex.cpp b/Geo/gmshVertex.cpp
index 7a324e33d1641cb7b41ac346c70bc602d2d98b1e..c2c911dfd6aab935c777dfbc57cbfb001db0cfc6 100644
--- a/Geo/gmshVertex.cpp
+++ b/Geo/gmshVertex.cpp
@@ -10,7 +10,7 @@
 #include "GeoInterpolation.h"
 #include "GmshMessage.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MPoint.h"
 
 gmshVertex::gmshVertex(GModel *m, Vertex *_v)
   : GVertex(m, _v->Num, _v->lc), v(_v)
diff --git a/Graphics/Makefile b/Graphics/Makefile
index 8a0dbdd61291e2c547af90bd3c43c996994b39c1..8b76b62685aa87b1bd26751abc64783e27232133 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -87,13 +87,17 @@ drawMesh${OBJEXT}: drawMesh.cpp drawContext.h ../Geo/SBoundingBox3d.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Common/GmshConfig.h ../Numeric/Gauss.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h ../Common/OS.h \
-  gl2ps.h ../Common/VertexArray.h ../Common/SmoothData.h ../Post/PView.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MLine.h ../Geo/MElement.h \
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Common/GmshConfig.h ../Numeric/Gauss.h ../Geo/MTriangle.h \
+  ../Geo/MElement.h ../Geo/MQuadrangle.h ../Geo/MElement.h \
+  ../Geo/MTetrahedron.h ../Geo/MElement.h ../Geo/MHexahedron.h \
+  ../Geo/MElement.h ../Geo/MPrism.h ../Geo/MElement.h ../Geo/MPyramid.h \
+  ../Geo/MElement.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h ../Common/OS.h gl2ps.h \
+  ../Common/VertexArray.h ../Common/SmoothData.h ../Post/PView.h \
   ../Post/PViewData.h
 drawGeom${OBJEXT}: drawGeom.cpp drawContext.h ../Geo/SBoundingBox3d.h \
   ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
diff --git a/Graphics/drawMesh.cpp b/Graphics/drawMesh.cpp
index 8b5fdba6115706b47b11ffa0471d4430abb5a36e..9c2640d70d2eeef871326229a725b15c6666caf7 100644
--- a/Graphics/drawMesh.cpp
+++ b/Graphics/drawMesh.cpp
@@ -9,7 +9,13 @@
 #include "GmshMessage.h"
 #include "GmshDefines.h"
 #include "GModel.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "Context.h"
 #include "OS.h"
 #include "gl2ps.h"
diff --git a/Mesh/BoundaryLayers.cpp b/Mesh/BoundaryLayers.cpp
index 4095d75a37c5c1da0b84af885d2216692e4c2e66..0d77d5a0879f517b7c9647dd235325c3a6a50310 100644
--- a/Mesh/BoundaryLayers.cpp
+++ b/Mesh/BoundaryLayers.cpp
@@ -4,7 +4,8 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include "GModel.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
 #include "BoundaryLayers.h"
 #include "ExtrudeParams.h"
 #include "meshGEdge.h"
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index d3ea91950c46dba3a704c06c9ed60f7e0a4204d3..faa147102c880e90f139905efca18f20270eacbe 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -10,7 +10,13 @@
 #include "Context.h"
 #include "OS.h"
 #include "GModel.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "meshGEdge.h"
 #include "meshGFace.h"
 #include "meshGFaceBDS.h"
diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp
index e96bce83d9213ab490dbc0c1a0a2848befb0fe91..954b6b0c4ff34b54cb98b7c7097712c5a02de4aa 100644
--- a/Mesh/HighOrder.cpp
+++ b/Mesh/HighOrder.cpp
@@ -9,7 +9,13 @@
 
 #include "HighOrder.h"
 #include "gmshSmoothHighOrder.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "GmshMessage.h"
 #include "OS.h"
 #include "Numeric.h"
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 3bc0c63136936cd990d7f3112353a4a1b21625b0..7710cc1c92522efbcb0b02f0bce3d8a1ee1f9c8c 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -85,13 +85,18 @@ Generator${OBJEXT}: Generator.cpp ../Common/GmshConfig.h ../Common/GmshMessage.h
   ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h \
   ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Numeric/Gauss.h meshGEdge.h meshGFace.h meshGFaceBDS.h meshGRegion.h \
-  BackgroundMesh.h BoundaryLayers.h HighOrder.h Generator.h \
-  ../Post/PView.h ../Post/PViewData.h
+  ../Geo/SBoundingBox3d.h ../Geo/MLine.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Geo/MTetrahedron.h ../Geo/MElement.h \
+  ../Geo/MHexahedron.h ../Geo/MElement.h ../Geo/MPrism.h \
+  ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h meshGEdge.h \
+  meshGFace.h meshGFaceBDS.h meshGRegion.h BackgroundMesh.h \
+  BoundaryLayers.h HighOrder.h Generator.h ../Post/PView.h \
+  ../Post/PViewData.h
 Field${OBJEXT}: Field.cpp ../Common/GmshConfig.h \
   ../contrib/ANN/include/ANN/ANN.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h Field.h \
@@ -112,20 +117,24 @@ Field${OBJEXT}: Field.cpp ../Common/GmshConfig.h \
   ../Geo/SBoundingBox3d.h ../Post/OctreePost.h ../Common/Octree.h \
   ../Common/OctreeInternals.h ../Post/PViewDataList.h ../Post/PViewData.h \
   ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h
-gmshSmoothHighOrder${OBJEXT}: gmshSmoothHighOrder.cpp HighOrder.h \
+gmshSmoothHighOrder${OBJEXT}: gmshSmoothHighOrder.cpp ../Geo/MLine.h \
+  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
+  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Geo/MTetrahedron.h ../Geo/MElement.h \
+  ../Geo/MHexahedron.h ../Geo/MElement.h ../Geo/MPrism.h \
+  ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h HighOrder.h \
   ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
   ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
   ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h \
-  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
-  ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h \
-  ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/SVector3.h meshGFaceOptimize.h \
-  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
-  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
+  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
+  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h meshGFaceOptimize.h \
   meshGFaceDelaunayInsertion.h gmshSmoothHighOrder.h \
   ../Numeric/gmshAssembler.h ../Numeric/gmshLinearSystem.h \
   ../Numeric/gmshLaplace.h ../Numeric/gmshTermOfFormulation.h \
@@ -145,7 +154,7 @@ meshGEdge${OBJEXT}: meshGEdge.cpp ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h meshGEdge.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.h meshGEdge.h ../Geo/MLine.h ../Geo/MElement.h \
   ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
   ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
@@ -161,29 +170,32 @@ meshGEdgeExtruded${OBJEXT}: meshGEdgeExtruded.cpp ../Geo/GModel.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MLine.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
   ../Geo/ExtrudeParams.h ../Common/SmoothData.h
 meshGFace${OBJEXT}: meshGFace.cpp meshGFace.h meshGFaceBDS.h \
-  meshGFaceDelaunayInsertion.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Common/GmshMessage.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Common/GmshConfig.h ../Numeric/Gauss.h meshGFaceQuadrilateralize.h \
-  meshGFaceOptimize.h DivideAndConquer.h BackgroundMesh.h \
-  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
-  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h \
-  ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GModel.h \
-  ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
+  meshGFaceDelaunayInsertion.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  meshGFaceQuadrilateralize.h meshGFaceOptimize.h DivideAndConquer.h \
+  BackgroundMesh.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+  ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h \
+  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
+  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
+  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MLine.h ../Geo/MElement.h \
+  ../Geo/MQuadrangle.h ../Geo/MElement.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
   ../Numeric/Numeric.h ../Numeric/GmshMatrix.h BDS.h qualityMeasures.h \
   Field.h ../Post/PView.h ../Common/OS.h HighOrder.h
 meshGFaceTransfinite${OBJEXT}: meshGFaceTransfinite.cpp meshGFace.h \
@@ -193,13 +205,15 @@ meshGFaceTransfinite${OBJEXT}: meshGFaceTransfinite.cpp meshGFace.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MElement.h \
-  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
-  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MTriangle.h \
+  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
+  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Common/GmshMessage.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Common/GmshConfig.h ../Numeric/Gauss.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h ../Numeric/Numeric.h \
+  ../Numeric/GmshMatrix.h
 meshGFaceExtruded${OBJEXT}: meshGFaceExtruded.cpp ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
@@ -208,13 +222,15 @@ meshGFaceExtruded${OBJEXT}: meshGFaceExtruded.cpp ../Geo/GModel.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MLine.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  ../Geo/ExtrudeParams.h ../Common/SmoothData.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Geo/ExtrudeParams.h ../Common/SmoothData.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
 meshGFaceBDS${OBJEXT}: meshGFaceBDS.cpp ../Common/GmshMessage.h \
   ../Numeric/GmshPredicates.h meshGFace.h meshGFaceOptimize.h \
   ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
@@ -222,30 +238,32 @@ meshGFaceBDS${OBJEXT}: meshGFaceBDS.cpp ../Common/GmshMessage.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
   ../Common/GmshConfig.h ../Numeric/Gauss.h meshGFaceDelaunayInsertion.h \
-  BackgroundMesh.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
-  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
-  ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h \
-  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
-  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
-  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h \
-  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h \
-  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
-  BDS.h qualityMeasures.h Field.h ../Post/PView.h ../Common/OS.h
+  ../Geo/MTriangle.h ../Geo/MElement.h BackgroundMesh.h ../Geo/GVertex.h \
+  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
+  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
+  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h \
+  ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
+  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h ../Geo/GModel.h \
+  ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h ../Geo/GRegion.h \
+  ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h BDS.h qualityMeasures.h \
+  Field.h ../Post/PView.h ../Common/OS.h
 meshGFaceDelaunayInsertion${OBJEXT}: meshGFaceDelaunayInsertion.cpp \
   ../Common/GmshMessage.h ../Numeric/GmshPredicates.h BackgroundMesh.h \
-  meshGFaceDelaunayInsertion.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  meshGFaceOptimize.h meshGFace.h ../Geo/GFace.h ../Geo/GEntity.h \
-  ../Geo/Range.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
-  ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/GPoint.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Numeric/Numeric.h \
+  meshGFaceDelaunayInsertion.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Common/GmshConfig.h ../Numeric/Gauss.h meshGFaceOptimize.h \
+  meshGFace.h ../Geo/GFace.h ../Geo/GEntity.h ../Geo/Range.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+  ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/GEntity.h \
+  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Numeric/Numeric.h \
   ../Numeric/GmshMatrix.h
 meshGFaceOptimize${OBJEXT}: meshGFaceOptimize.cpp meshGFaceOptimize.h \
   ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
@@ -253,14 +271,15 @@ meshGFaceOptimize${OBJEXT}: meshGFaceOptimize.cpp meshGFaceOptimize.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  meshGFaceDelaunayInsertion.h qualityMeasures.h ../Geo/GFace.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
-  ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h BackgroundMesh.h ../Numeric/Numeric.h \
-  ../Numeric/GmshMatrix.h Generator.h
+  meshGFaceDelaunayInsertion.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  qualityMeasures.h ../Geo/GFace.h ../Geo/GEntity.h ../Geo/Range.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+  ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/GEntity.h \
+  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/MQuadrangle.h ../Geo/MElement.h \
+  BackgroundMesh.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
+  Generator.h
 meshGFaceQuadrilateralize${OBJEXT}: meshGFaceQuadrilateralize.cpp \
   meshGFaceQuadrilateralize.h ../Common/GmshMessage.h \
   ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/GmshConfig.h \
@@ -270,36 +289,39 @@ meshGFaceQuadrilateralize${OBJEXT}: meshGFaceQuadrilateralize.cpp \
   ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h meshGFaceDelaunayInsertion.h \
-  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  meshGFaceOptimize.h meshGFaceBDS.h BDS.h
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Numeric/Gauss.h meshGFaceOptimize.h meshGFaceBDS.h BDS.h
 meshGRegion${OBJEXT}: meshGRegion.cpp ../Common/GmshConfig.h \
   ../Common/GmshMessage.h meshGRegion.h meshGRegionDelaunayInsertion.h \
-  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Numeric/Gauss.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
-  BackgroundMesh.h qualityMeasures.h ../Geo/GModel.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
-  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h \
-  ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
-  ../Geo/gmshRegion.h ../Geo/Geo.h ../Geo/gmshSurface.h ../Geo/Pair.h \
-  ../Geo/Range.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/SVector3.h \
-  ../Geo/SBoundingBox3d.h ../Common/ListUtils.h ../Common/TreeUtils.h \
-  ../Common/avl.h ../Common/ListUtils.h ../Geo/SPoint2.h \
-  ../Geo/ExtrudeParams.h ../Common/SmoothData.h ../Geo/GRegion.h BDS.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
+  ../Geo/MTetrahedron.h ../Geo/MElement.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Numeric/Gauss.h ../Numeric/Numeric.h \
+  ../Numeric/GmshMatrix.h BackgroundMesh.h qualityMeasures.h \
+  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+  ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h \
+  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
+  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
+  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/gmshRegion.h ../Geo/Geo.h \
+  ../Geo/gmshSurface.h ../Geo/Pair.h ../Geo/Range.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/SVector3.h ../Geo/SBoundingBox3d.h \
+  ../Common/ListUtils.h ../Common/TreeUtils.h ../Common/avl.h \
+  ../Common/ListUtils.h ../Geo/SPoint2.h ../Geo/ExtrudeParams.h \
+  ../Common/SmoothData.h ../Geo/GRegion.h ../Geo/MLine.h \
+  ../Geo/MElement.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Geo/MQuadrangle.h ../Geo/MElement.h BDS.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
 meshGRegionDelaunayInsertion${OBJEXT}: meshGRegionDelaunayInsertion.cpp \
   ../Common/GmshMessage.h ../Numeric/GmshPredicates.h ../Common/OS.h \
   BackgroundMesh.h meshGRegion.h meshGRegionLocalMeshMod.h \
-  meshGRegionDelaunayInsertion.h ../Geo/MElement.h \
+  meshGRegionDelaunayInsertion.h ../Geo/MTetrahedron.h ../Geo/MElement.h \
   ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
   ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
@@ -312,7 +334,8 @@ meshGRegionDelaunayInsertion${OBJEXT}: meshGRegionDelaunayInsertion.cpp \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h \
   ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
   ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h
+  ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
+  ../Geo/MTriangle.h ../Geo/MElement.h
 meshGRegionTransfinite${OBJEXT}: meshGRegionTransfinite.cpp meshGFace.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
@@ -320,12 +343,15 @@ meshGRegionTransfinite${OBJEXT}: meshGRegionTransfinite.cpp meshGFace.h \
   ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MElement.h \
-  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h \
+  ../Geo/MTetrahedron.h ../Geo/MElement.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
+  ../Geo/MHexahedron.h ../Geo/MElement.h ../Geo/MPrism.h \
+  ../Geo/MElement.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h
 meshGRegionExtruded${OBJEXT}: meshGRegionExtruded.cpp ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
@@ -334,11 +360,15 @@ meshGRegionExtruded${OBJEXT}: meshGRegionExtruded.cpp ../Geo/GModel.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Geo/MQuadrangle.h ../Geo/MElement.h ../Geo/MTetrahedron.h \
+  ../Geo/MElement.h ../Geo/MHexahedron.h ../Geo/MElement.h \
+  ../Geo/MPrism.h ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h \
   ../Geo/ExtrudeParams.h ../Common/SmoothData.h meshGFace.h meshGRegion.h \
   ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
 meshGRegionCarveHole${OBJEXT}: meshGRegionCarveHole.cpp ../Common/GmshConfig.h \
@@ -350,20 +380,25 @@ meshGRegionCarveHole${OBJEXT}: meshGRegionCarveHole.cpp ../Common/GmshConfig.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Numeric/Gauss.h ../contrib/ANN/include/ANN/ANN.h
+  ../Geo/SBoundingBox3d.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
+  ../Geo/MQuadrangle.h ../Geo/MElement.h ../Geo/MTetrahedron.h \
+  ../Geo/MElement.h ../Geo/MHexahedron.h ../Geo/MElement.h \
+  ../Geo/MPrism.h ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h \
+  ../contrib/ANN/include/ANN/ANN.h
 meshGRegionLocalMeshMod${OBJEXT}: meshGRegionLocalMeshMod.cpp \
   meshGRegionLocalMeshMod.h meshGRegionDelaunayInsertion.h \
-  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h BackgroundMesh.h \
-  qualityMeasures.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/MTetrahedron.h ../Geo/MElement.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Common/GmshMessage.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Common/GmshConfig.h ../Numeric/Gauss.h ../Numeric/Numeric.h \
+  ../Numeric/GmshMatrix.h BackgroundMesh.h qualityMeasures.h \
+  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GRegion.h \
   ../Geo/GEntity.h
 DivideAndConquer${OBJEXT}: DivideAndConquer.cpp ../Common/GmshMessage.h \
@@ -384,11 +419,12 @@ BackgroundMesh${OBJEXT}: BackgroundMesh.cpp ../Common/GmshMessage.h \
   ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h Field.h ../Post/PView.h
 qualityMeasures${OBJEXT}: qualityMeasures.cpp qualityMeasures.h BDS.h \
   ../Common/GmshMessage.h ../Geo/MVertex.h ../Geo/SPoint2.h \
-  ../Geo/SPoint3.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/SPoint3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  ../Common/GmshConfig.h ../Numeric/Gauss.h ../Numeric/Numeric.h \
+  ../Geo/SPoint3.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/FunctionSpace.h \
+  ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
+  ../Geo/MTetrahedron.h ../Geo/MElement.h ../Numeric/Numeric.h \
   ../Numeric/GmshMatrix.h
 BoundaryLayers${OBJEXT}: BoundaryLayers.cpp ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -398,13 +434,14 @@ BoundaryLayers${OBJEXT}: BoundaryLayers.cpp ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MTriangle.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  BoundaryLayers.h ../Geo/ExtrudeParams.h ../Common/SmoothData.h \
-  meshGEdge.h meshGFace.h
+  ../Geo/MQuadrangle.h ../Geo/MElement.h BoundaryLayers.h \
+  ../Geo/ExtrudeParams.h ../Common/SmoothData.h meshGEdge.h meshGFace.h
 BDS${OBJEXT}: BDS.cpp ../Common/GmshMessage.h ../Numeric/GmshPredicates.h \
   ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/GmshConfig.h \
   BDS.h ../Geo/GFace.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -413,11 +450,11 @@ BDS${OBJEXT}: BDS.cpp ../Common/GmshMessage.h ../Numeric/GmshPredicates.h \
   ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h meshGFaceDelaunayInsertion.h \
-  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
-  qualityMeasures.h
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
+  ../Numeric/Gauss.h qualityMeasures.h
 HighOrder${OBJEXT}: HighOrder.cpp HighOrder.h ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
@@ -428,12 +465,17 @@ HighOrder${OBJEXT}: HighOrder.cpp HighOrder.h ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/SVector3.h \
-  gmshSmoothHighOrder.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/MFace.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
+  gmshSmoothHighOrder.h ../Geo/MLine.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/MEdge.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
+  ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  ../Common/OS.h ../Numeric/Numeric.h ../Numeric/GmshMatrix.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Geo/MTetrahedron.h ../Geo/MElement.h \
+  ../Geo/MHexahedron.h ../Geo/MElement.h ../Geo/MPrism.h \
+  ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h ../Common/OS.h \
+  ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/meshPartitionOptions.h
 meshPartition${OBJEXT}: meshPartition.cpp ../Common/GmshConfig.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
@@ -457,9 +499,12 @@ meshRefine${OBJEXT}: meshRefine.cpp HighOrder.h ../Geo/GModel.h ../Geo/GVertex.h
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/SVector3.h ../Geo/MElement.h \
-  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
+  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/SVector3.h ../Geo/MLine.h \
+  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
+  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
   ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Numeric/Gauss.h \
-  ../Common/OS.h
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Geo/MTetrahedron.h ../Geo/MElement.h \
+  ../Geo/MHexahedron.h ../Geo/MElement.h ../Geo/MPrism.h \
+  ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h ../Common/OS.h
diff --git a/Mesh/gmshSmoothHighOrder.cpp b/Mesh/gmshSmoothHighOrder.cpp
index 087f0f2d1e11d47e816ddd53b36a33027c251e9a..1967a77eaccdfb63e7992afed618cb5a2e53d066 100644
--- a/Mesh/gmshSmoothHighOrder.cpp
+++ b/Mesh/gmshSmoothHighOrder.cpp
@@ -7,6 +7,13 @@
 //   Koen Hillewaert
 //
 
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "HighOrder.h"
 #include "meshGFaceOptimize.h"
 #include "gmshSmoothHighOrder.h"
diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp
index d996c05bb79f345216ba188d3da9edcf38978760..19cdb668def6da8045363c756127d6be215c4752 100644
--- a/Mesh/meshGEdge.cpp
+++ b/Mesh/meshGEdge.cpp
@@ -6,7 +6,7 @@
 #include "GModel.h"
 #include "meshGEdge.h"
 #include "GEdge.h"
-#include "MElement.h"
+#include "MLine.h"
 #include "BackgroundMesh.h"
 #include "Numeric.h"
 #include "GmshMessage.h"
diff --git a/Mesh/meshGEdgeExtruded.cpp b/Mesh/meshGEdgeExtruded.cpp
index 9c3b8181048cbe8fb4639e6e8b0e8cb03d01ae62..5711336f76f1d78c703ec2b5ddf6460797a7e3eb 100644
--- a/Mesh/meshGEdgeExtruded.cpp
+++ b/Mesh/meshGEdgeExtruded.cpp
@@ -5,7 +5,7 @@
 
 #include <set>
 #include "GModel.h"
-#include "MElement.h"
+#include "MLine.h"
 #include "ExtrudeParams.h"
 #include "GmshMessage.h"
 
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index e89f8891315aa7abb8eb26bc961ac673dde35b42..94d5c75eb2d7a3dfccb4ab400a7a31a729e86128 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -16,7 +16,9 @@
 #include "GFace.h"
 #include "GModel.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
 #include "Context.h"
 #include "GPoint.h"
 #include "GmshMessage.h"
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index 102b11fe5d4a87ff43bb3c8d41bcbf1582f81af9..6aebd9d3243ca930858ee38b917e770c92d7905f 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -29,58 +29,6 @@ static bool isActive(MTri3 *t, double limit_, int &active)
   return false;
 }
 
-void circumCenterXY(double *p1, double *p2, double *p3, double *res)
-{
-  double d, a1, a2, a3;
-
-  const double x1 = p1[0];
-  const double x2 = p2[0];
-  const double x3 = p3[0];
-  const double y1 = p1[1];
-  const double y2 = p2[1];
-  const double y3 = p3[1];
-
-  d = 2. * (double)(y1 * (x2 - x3) + y2 * (x3 - x1) + y3 * (x1 - x2));
-  if(d == 0.0) {
-    Msg::Warning("Colinear points in circum circle computation");
-    res[0] = res[1] = -99999.;
-    return ;
-  }
-
-  a1 = x1 * x1 + y1 * y1;
-  a2 = x2 * x2 + y2 * y2;
-  a3 = x3 * x3 + y3 * y3;
-  res[0] = (double)((a1 * (y3 - y2) + a2 * (y1 - y3) + a3 * (y2 - y1)) / d);
-  res[1] = (double)((a1 * (x2 - x3) + a2 * (x3 - x1) + a3 * (x1 - x2)) / d);
-}
-
-void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv)
-{
-  double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
-  double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
-  double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
-  double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
-  double vz[3]; prodve(vx, vy, vz); prodve(vz, vx, vy);
-  norme(vx); norme(vy); norme(vz);
-  double p1P[2] = {0.0, 0.0};
-  double p2P[2]; prosca(v1, vx, &p2P[0]); prosca(v1, vy, &p2P[1]);
-  double p3P[2]; prosca(v2, vx, &p3P[0]); prosca(v2, vy, &p3P[1]);
-  double resP[2];
-
-  circumCenterXY(p1P, p2P, p3P,resP);
-
-  if(uv){
-    double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
-                        {p2P[1] - p1P[1], p3P[1] - p1P[1]}};
-    double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
-    sys2x2(mat, rhs, uv);
-  }
-  
-  res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
-  res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
-  res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
-}
-
 bool circumCenterMetricInTriangle(MTriangle *base, 
                                   const double *metric,
                                   const std::vector<double> &Us,
diff --git a/Mesh/meshGFaceDelaunayInsertion.h b/Mesh/meshGFaceDelaunayInsertion.h
index 10b0672cc9ffd84d4ebf23e78b0818b2f0940b0e..1a86bb49744f2f2b9a96636b31bb2b8ce56f0cd2 100644
--- a/Mesh/meshGFaceDelaunayInsertion.h
+++ b/Mesh/meshGFaceDelaunayInsertion.h
@@ -6,7 +6,7 @@
 #ifndef _MESH_GFACE_DELAUNAY_INSERTIONFACE_H_
 #define _MESH_GFACE_DELAUNAY_INSERTIONFACE_H_
 
-#include "MElement.h"
+#include "MTriangle.h"
 #include <list>
 #include <set>
 #include <map>
@@ -21,7 +21,6 @@ int inCircumCircleAniso(GFace *gf, double *p1, double *p2, double *p3, double *p
                         double *metric);
 int inCircumCircleAniso(GFace *gf, MTriangle *base, const double *uv, const double *metric,
                         const std::vector<double> &Us, const std::vector<double> &Vs);
-void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv=0);
 void circumCenterMetric(double *pa, double *pb, double *pc,
                         const double *metric,
                         double *x, double &Radius2);
diff --git a/Mesh/meshGFaceExtruded.cpp b/Mesh/meshGFaceExtruded.cpp
index 0779a3eccacf016c23617a2e18045355b9285966..f255026cd442db92a1e4fb0279d0414d233861e1 100644
--- a/Mesh/meshGFaceExtruded.cpp
+++ b/Mesh/meshGFaceExtruded.cpp
@@ -5,7 +5,9 @@
 
 #include <set>
 #include "GModel.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
 #include "ExtrudeParams.h"
 #include "Context.h"
 #include "GmshMessage.h"
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 40077361c063c944e7bd3ac6d6b5218151e3c44a..0f0b657d58e7943d277e891342eb906f57a10549 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -9,7 +9,8 @@
 #include "GEdge.h"
 #include "GVertex.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
 #include "BackgroundMesh.h"
 #include "Numeric.h"
 #include "GmshMessage.h"
diff --git a/Mesh/meshGFaceTransfinite.cpp b/Mesh/meshGFaceTransfinite.cpp
index 30547dc1501032c3e073fe9b37610f6b33d763f2..37f782411398cb4372026b514604977683cc2dc0 100644
--- a/Mesh/meshGFaceTransfinite.cpp
+++ b/Mesh/meshGFaceTransfinite.cpp
@@ -9,7 +9,8 @@
 #include "GEdge.h"
 #include "GFace.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
 #include "Context.h"
 #include "GmshMessage.h"
 #include "Numeric.h"
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index b387e5ac1ae8a795fb3be1920f735a837efabb01..f215ba3c160b59822e25063dbcd162e5e84d15a5 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -14,6 +14,10 @@
 #include "GFace.h"
 #include "GEdge.h"
 #include "gmshRegion.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
 #include "BDS.h"
 #include "Context.h"
 
diff --git a/Mesh/meshGRegionCarveHole.cpp b/Mesh/meshGRegionCarveHole.cpp
index 8fe9136d49b6fe1441c66f12ad121b9311c0ea03..f6d24e9ab188d63430a21363cd334dca0ade55f5 100644
--- a/Mesh/meshGRegionCarveHole.cpp
+++ b/Mesh/meshGRegionCarveHole.cpp
@@ -7,7 +7,12 @@
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "GModel.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 
 #if !defined(HAVE_ANN)
 
diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp
index dc453f0cf0b6983d43a83366ea39fe0297a096db..411483e12c59a1689667051d398f5ab695cd0733 100644
--- a/Mesh/meshGRegionDelaunayInsertion.cpp
+++ b/Mesh/meshGRegionDelaunayInsertion.cpp
@@ -15,6 +15,7 @@
 #include "meshGRegionDelaunayInsertion.h"
 #include "GModel.h"
 #include "GRegion.h"
+#include "MTriangle.h"
 #include "Numeric.h"
 
 int MTet4::inCircumSphere(const double *p) const
diff --git a/Mesh/meshGRegionDelaunayInsertion.h b/Mesh/meshGRegionDelaunayInsertion.h
index 0f38b4684bec619982bb6c765931a5be16b204fa..f65fdc3bffeb23419db14e3ab187222c0054fd0f 100644
--- a/Mesh/meshGRegionDelaunayInsertion.h
+++ b/Mesh/meshGRegionDelaunayInsertion.h
@@ -10,7 +10,7 @@
 #include <set>
 #include <map>
 #include <stack>
-#include "MElement.h"
+#include "MTetrahedron.h"
 #include "Numeric.h"
 #include "BackgroundMesh.h"
 #include "qualityMeasures.h"
diff --git a/Mesh/meshGRegionExtruded.cpp b/Mesh/meshGRegionExtruded.cpp
index ef6d57fee97f3f02aaada913f19ab53b8b8f843e..bd953c18ab4fec11c55d57e69d8df3570daebd22 100644
--- a/Mesh/meshGRegionExtruded.cpp
+++ b/Mesh/meshGRegionExtruded.cpp
@@ -5,7 +5,12 @@
 
 #include <set>
 #include "GModel.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "ExtrudeParams.h"
 #include "meshGFace.h"
 #include "meshGRegion.h"
diff --git a/Mesh/meshGRegionTransfinite.cpp b/Mesh/meshGRegionTransfinite.cpp
index 609ba91860fac1fe70f59ecc02d024168f8b31f0..0f319a0d61e891d0631db1beb1f84f92110b1d08 100644
--- a/Mesh/meshGRegionTransfinite.cpp
+++ b/Mesh/meshGRegionTransfinite.cpp
@@ -8,7 +8,9 @@
 #include "GFace.h"
 #include "GRegion.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
 #include "Context.h"
 #include "GmshMessage.h"
 
diff --git a/Mesh/meshRefine.cpp b/Mesh/meshRefine.cpp
index 368f937056648ed9dde1753eed63b1e343cdecb2..a33b4dc568704baf5b595cea8a93dc27e6a5f5af 100644
--- a/Mesh/meshRefine.cpp
+++ b/Mesh/meshRefine.cpp
@@ -8,7 +8,13 @@
 //
 
 #include "HighOrder.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "GmshMessage.h"
 #include "OS.h"
 
diff --git a/Mesh/qualityMeasures.cpp b/Mesh/qualityMeasures.cpp
index 96c9640c7834da267308de3936e387a33499db7b..6a6699c7122d26c626ad838ff01a39d9db01df4a 100644
--- a/Mesh/qualityMeasures.cpp
+++ b/Mesh/qualityMeasures.cpp
@@ -6,7 +6,8 @@
 #include "qualityMeasures.h"
 #include "BDS.h"
 #include "MVertex.h"
-#include "MElement.h"
+#include "MTriangle.h"
+#include "MTetrahedron.h"
 #include "Numeric.h"
 #include "FunctionSpace.h"
 #include "GmshMessage.h"
diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp
index 335e79ea7e7d4a48a99c1c2324482e62ffff516b..6d6804c3e06726e3ed1c25dccacfc1e52ca81f37 100644
--- a/Numeric/Numeric.cpp
+++ b/Numeric/Numeric.cpp
@@ -267,6 +267,58 @@ double triangle_area(double p0[3], double p1[3], double p2[3])
   return 0.5 * sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
 }
 
+void circumCenterXY(double *p1, double *p2, double *p3, double *res)
+{
+  double d, a1, a2, a3;
+
+  const double x1 = p1[0];
+  const double x2 = p2[0];
+  const double x3 = p3[0];
+  const double y1 = p1[1];
+  const double y2 = p2[1];
+  const double y3 = p3[1];
+
+  d = 2. * (double)(y1 * (x2 - x3) + y2 * (x3 - x1) + y3 * (x1 - x2));
+  if(d == 0.0) {
+    Msg::Warning("Colinear points in circum circle computation");
+    res[0] = res[1] = -99999.;
+    return ;
+  }
+
+  a1 = x1 * x1 + y1 * y1;
+  a2 = x2 * x2 + y2 * y2;
+  a3 = x3 * x3 + y3 * y3;
+  res[0] = (double)((a1 * (y3 - y2) + a2 * (y1 - y3) + a3 * (y2 - y1)) / d);
+  res[1] = (double)((a1 * (x2 - x3) + a2 * (x3 - x1) + a3 * (x1 - x2)) / d);
+}
+
+void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv)
+{
+  double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
+  double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
+  double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
+  double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
+  double vz[3]; prodve(vx, vy, vz); prodve(vz, vx, vy);
+  norme(vx); norme(vy); norme(vz);
+  double p1P[2] = {0.0, 0.0};
+  double p2P[2]; prosca(v1, vx, &p2P[0]); prosca(v1, vy, &p2P[1]);
+  double p3P[2]; prosca(v2, vx, &p3P[0]); prosca(v2, vy, &p3P[1]);
+  double resP[2];
+
+  circumCenterXY(p1P, p2P, p3P,resP);
+
+  if(uv){
+    double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
+                        {p2P[1] - p1P[1], p3P[1] - p1P[1]}};
+    double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
+    sys2x2(mat, rhs, uv);
+  }
+  
+  res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
+  res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
+  res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
+}
+
 char float2char(float f)
 {
   // float normalized in [-1, 1], char in [-127, 127]
diff --git a/Numeric/Numeric.h b/Numeric/Numeric.h
index aeeeb0b39dd2ac737e793d92558aca1d32ecb6d9..578a66f736f14e4ab765772494972a8862488d44 100644
--- a/Numeric/Numeric.h
+++ b/Numeric/Numeric.h
@@ -58,6 +58,8 @@ double inv2x2(double mat[2][2], double inv[2][2]);
 double angle_02pi(double A3);
 double angle_plan(double V[3], double P1[3], double P2[3], double n[3]);
 double triangle_area(double p0[3], double p1[3], double p2[3]);
+void circumCenterXY(double *p1, double *p2, double *p3, double *res);
+void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv=0);
 char float2char(float f);
 float char2float(char c);
 void eigenvalue(double mat[3][3], double re[3]);
diff --git a/Post/Makefile b/Post/Makefile
index c214d07f3fe3cd32fcd3ec18aa2b6d7d1e35db68..7329b2514c31e73b292bcebd08f87d9c0c320f1a 100644
--- a/Post/Makefile
+++ b/Post/Makefile
@@ -98,11 +98,15 @@ PViewDataGModel${OBJEXT}: PViewDataGModel.cpp PViewDataGModel.h PViewData.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
   ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
-  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/MElement.h \
-  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
-  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/MLine.h \
+  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
+  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
+  ../Geo/MTriangle.h ../Geo/MElement.h ../Geo/MQuadrangle.h \
+  ../Geo/MElement.h ../Geo/MTetrahedron.h ../Geo/MElement.h \
+  ../Geo/MHexahedron.h ../Geo/MElement.h ../Geo/MPrism.h \
+  ../Geo/MElement.h ../Geo/MPyramid.h ../Geo/MElement.h \
   ../Numeric/Numeric.h ../Numeric/GmshMatrix.h
 PViewDataGModelIO${OBJEXT}: PViewDataGModelIO.cpp ../Common/GmshConfig.h \
   ../Common/GmshMessage.h PViewDataGModel.h PViewData.h \
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index 4207811925b9a8a5c5ea2ae34197faf796685261..b225802f04b707d2b70d27c42071cc041952df12 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -4,7 +4,13 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include "PViewDataGModel.h"
-#include "MElement.h"
+#include "MLine.h"
+#include "MTriangle.h"
+#include "MQuadrangle.h"
+#include "MTetrahedron.h"
+#include "MHexahedron.h"
+#include "MPrism.h"
+#include "MPyramid.h"
 #include "Numeric.h"
 #include "GmshMessage.h"