diff --git a/CMakeLists.txt b/CMakeLists.txt
index e55427ad08b5a84b22483be83e41ec543fbcfb13..628a5086223ee51298a5733a1eea18cb252d101c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -672,13 +672,16 @@ if(ENABLE_OCC)
                  ${OCC_SYS_NAME}/lib)
     if(OCC_LIB)
       list(APPEND OCC_LIBS ${OCC_LIB})
+    else(OCC_LIB)
+      message(STATUS "OCC lib " ${OCC} " not Found")
     endif(OCC_LIB)
     set(OCC_LIB OCC_LIB-NOTFOUND CACHE INTERNAL "")
     # unset(OCC_LIB CACHE) # cleaner, but only available in cmake >= 2.6.4
   endforeach(OCC)
   list(LENGTH OCC_LIBS NUM_OCC_LIBS)
-  if(NUM_OCC_LIBS EQUAL NUM_OCC_LIBS_REQUIRED)
 
+
+  if(NUM_OCC_LIBS EQUAL NUM_OCC_LIBS_REQUIRED)
     find_path(OCC_INC "BRep_Tool.hxx" PATHS ENV CASROOT PATH_SUFFIXES inc 
               include opencascade)
     if(OCC_INC)
diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index 3c23232d10bef3c2e1ef2f8067b9925f5c7d1941..60ad590ff09f66c0b5d8a78e1f584f86c5a4e802 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -134,9 +134,6 @@
 #define MSH_TET_165  73
 #define MSH_TET_220  74
 #define MSH_TET_286  75
-#define MSH_HEX_64   76
-#define MSH_HEX_125  77
-#define MSH_HEX_196  78
 #define MSH_TET_74   79
 #define MSH_TET_100  80
 #define MSH_TET_130  81 
@@ -150,7 +147,22 @@
 #define MSH_PRI_1    89
 #define MSH_PRI_40   90
 #define MSH_PRI_75   91
-#define MSH_PRI_126  92
+// HEXES COMPLETE (3->9)
+#define MSH_HEX_64   92
+#define MSH_HEX_125  93
+#define MSH_HEX_216  94
+#define MSH_HEX_343  95
+#define MSH_HEX_512  96
+#define MSH_HEX_729  97
+#define MSH_HEX_1000 98
+// HEXES INCOMPLETE (3->9)
+#define MSH_HEX_56   99
+#define MSH_HEX_98  100
+#define MSH_HEX_152 101
+#define MSH_HEX_222 102
+#define MSH_HEX_296 103
+#define MSH_HEX_386 104
+#define MSH_HEX_488 105
 
 #define MSH_NUM_TYPE 92
 
diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp
index a7c6357060fc7cc4dff2fec3eb4b1339ac13f4fa..73faaa148560803ea2149c1d7384aecb72f11923 100644
--- a/Common/GmshMessage.cpp
+++ b/Common/GmshMessage.cpp
@@ -73,6 +73,7 @@ void Msg::Init(int argc, char **argv)
 #endif
 #if defined(HAVE_PETSC)
   PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
+  printf("coucou\n");
 #endif
 #if defined(HAVE_SLEPC)
   SlepcInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 40ca858f718aee2698bb0591896b59441ad5d9a0..5c52edb5b72783283f6a536261e1ba91dfa0730a 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -255,7 +255,7 @@ double MElement::getJacobian(double u, double v, double w, double jac[3][3])
   jac[1][0] = jac[1][1] = jac[1][2] = 0.;
   jac[2][0] = jac[2][1] = jac[2][2] = 0.;
 
-  double gsf[256][3];
+  double gsf[1256][3];
   getGradShapeFunctions(u, v, w, gsf);
   for (int i = 0; i < getNumShapeFunctions(); i++) {
     const MVertex *v = getShapeFunctionNode(i);
@@ -298,7 +298,7 @@ double MElement::getPrimaryJacobian(double u, double v, double w, double jac[3][
   jac[1][0] = jac[1][1] = jac[1][2] = 0.;
   jac[2][0] = jac[2][1] = jac[2][2] = 0.;
 
-  double gsf[256][3];
+  double gsf[1256][3];
   getGradShapeFunctions(u, v, w, gsf, 1);
   for(int i = 0; i < getNumPrimaryShapeFunctions(); i++) {
     const MVertex *v = getShapeFunctionNode(i);
@@ -316,7 +316,7 @@ double MElement::getPrimaryJacobian(double u, double v, double w, double jac[3][
 void MElement::pnt(double u, double v, double w, SPoint3 &p)
 {
   double x = 0., y = 0., z = 0.;
-  double sf[256];
+  double sf[1256];
   getShapeFunctions(u, v, w, sf);
   for (int j = 0; j < getNumShapeFunctions(); j++) {
     const MVertex *v = getShapeFunctionNode(j);
@@ -330,7 +330,7 @@ void MElement::pnt(double u, double v, double w, SPoint3 &p)
 void MElement::primaryPnt(double u, double v, double w, SPoint3 &p)
 {
   double x = 0., y = 0., z = 0.;
-  double sf[256];
+  double sf[1256];
   getShapeFunctions(u, v, w, sf, 1);
   for (int j = 0; j < getNumPrimaryShapeFunctions(); j++) {
     const MVertex *v = getShapeFunctionNode(j);
@@ -354,7 +354,7 @@ void MElement::xyz2uvw(double xyz[3], double uvw[3])
     double jac[3][3];
     if(!getJacobian(uvw[0], uvw[1], uvw[2], jac)) break;
     double xn = 0., yn = 0., zn = 0.;
-    double sf[256];
+    double sf[1256];
     getShapeFunctions(uvw[0], uvw[1], uvw[2], sf);
     for (int i = 0; i < getNumShapeFunctions(); i++) {
       MVertex *v = getShapeFunctionNode(i);
@@ -405,7 +405,7 @@ double MElement::interpolate(double val[], double u, double v, double w, int str
 {
   double sum = 0;
   int j = 0;
-  double sf[256];
+  double sf[1256];
   getShapeFunctions(u, v, w, sf, order);
   for(int i = 0; i < getNumShapeFunctions(); i++){
     sum += val[j] * sf[i];
@@ -419,7 +419,7 @@ void MElement::interpolateGrad(double val[], double u, double v, double w, doubl
 {
   double dfdu[3] = {0., 0., 0.};
   int j = 0;
-  double gsf[256][3];
+  double gsf[1256][3];
   getGradShapeFunctions(u, v, w, gsf, order);
   for(int i = 0; i < getNumShapeFunctions(); i++){
     dfdu[0] += val[j] * gsf[i][0];
@@ -1003,6 +1003,20 @@ int MElement::getInfoMSH(const int typeMSH, const char **const name)
   case MSH_HEX_8  : if(name) *name = "Hexahedron 8";    return 8;
   case MSH_HEX_20 : if(name) *name = "Hexahedron 20";   return 8 + 12;
   case MSH_HEX_27 : if(name) *name = "Hexahedron 27";   return 8 + 12 + 6 + 1;
+  case MSH_HEX_64  : if(name) *name = "Hexahedron 64";    return 64;
+  case MSH_HEX_125  : if(name) *name = "Hexahedron 125";    return 125;
+  case MSH_HEX_216  : if(name) *name = "Hexahedron 216";    return 216;
+  case MSH_HEX_343  : if(name) *name = "Hexahedron 343";    return 343;
+  case MSH_HEX_512  : if(name) *name = "Hexahedron 512";    return 512;
+  case MSH_HEX_729  : if(name) *name = "Hexahedron 729";    return 729;
+  case MSH_HEX_1000  : if(name) *name = "Hexahedron 1000";    return 1000;
+  case MSH_HEX_56  : if(name) *name = "Hexahedron 56";    return 56;
+  case MSH_HEX_98  : if(name) *name = "Hexahedron 98";    return 98;
+  case MSH_HEX_152  : if(name) *name = "Hexahedron 152";    return 152;
+  case MSH_HEX_222  : if(name) *name = "Hexahedron 222";    return 222;
+  case MSH_HEX_296  : if(name) *name = "Hexahedron 296";    return 296;
+  case MSH_HEX_386  : if(name) *name = "Hexahedron 386";    return 386;
+  case MSH_HEX_488  : if(name) *name = "Hexahedron 488";    return 488;
   case MSH_PRI_6  : if(name) *name = "Prism 6";         return 6;
   case MSH_PRI_15 : if(name) *name = "Prism 15";        return 6 + 9;
   case MSH_PRI_18 : if(name) *name = "Prism 18";        return 6 + 9 + 3;
@@ -1164,6 +1178,14 @@ MElement *MElementFactory::create(int type, std::vector<MVertex*> &v,
   case MSH_TET_220: return new MTetrahedronN(v, 9, num, part);
   case MSH_TET_286: return new MTetrahedronN(v, 10, num, part);
   case MSH_POLYH_: return new MPolyhedron(v, num, part, owner, parent);
+  case MSH_HEX_56: return new MHexahedronN(v, 3, num, part);
+  case MSH_HEX_64: return new MHexahedronN(v, 3, num, part);
+  case MSH_HEX_125: return new MHexahedronN(v, 4, num, part);
+  case MSH_HEX_216: return new MHexahedronN(v, 5, num, part);
+  case MSH_HEX_343: return new MHexahedronN(v, 6, num, part);
+  case MSH_HEX_512: return new MHexahedronN(v, 7, num, part);
+  case MSH_HEX_729: return new MHexahedronN(v, 8, num, part);
+  case MSH_HEX_1000: return new MHexahedronN(v, 9, num, part);
   default:         return 0;
   }
 }
diff --git a/Geo/MHexahedron.cpp b/Geo/MHexahedron.cpp
index 1f64319cf53a8ae6f73eff4748c010b8fc292de9..69c03e2527338abcdbcfc3040ebb79d3d4a211ab 100644
--- a/Geo/MHexahedron.cpp
+++ b/Geo/MHexahedron.cpp
@@ -5,6 +5,8 @@
 
 #include "MHexahedron.h"
 #include "Numeric.h"
+#include "Context.h"
+#include "polynomialBasis.h"
 
 int MHexahedron::getVolumeSign()
 { 
@@ -73,3 +75,87 @@ void MHexahedron::getFaceInfo(const MFace &face, int &ithFace, int &sign, int &r
   }
   Msg::Error("Could not get face information for hexahedron %d", getNum());
 }
+
+void MHexahedronN::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
+{
+  const int numSubEdges = CTX::instance()->mesh.numSubEdges;
+  static double pp[8][3] = {
+    {-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1},
+    {-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1} };
+  static int ed [12][2] = {
+    {0,1},{0,3},{0,4},{1,2},{1,5},{2,3},
+    {2,6},{3,7},{4,5},{4,7},{5,6},{7,6}
+  };
+  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;
+  pnt(u1,v1,w1,pnt1);
+  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] = 1 ;
+}
+
+int  MHexahedronN::getNumEdgesRep(){
+  return 12 * CTX::instance()->mesh.numSubEdges;
+}
+
+//int MHexaedronN::getNumFacesRep(){ 
+//  return 8 * SQU(CTX::instance()->mesh.numSubEdges); 
+//}
+
+const polynomialBasis* MHexahedron::getFunctionSpace(int o) const
+{
+  int order = (o == -1) ? getPolynomialOrder() : o;
+
+  int nv = getNumVolumeVertices();
+
+  if ((nv == 0) && (o == -1)) {
+    switch (order) {
+    case 0: return polynomialBases::find(MSH_HEX_1);
+    case 1: return polynomialBases::find(MSH_HEX_8);
+    case 2: return polynomialBases::find(MSH_HEX_20);
+    case 3: return polynomialBases::find(MSH_HEX_56);
+    case 4: return polynomialBases::find(MSH_HEX_98);
+    case 5: return polynomialBases::find(MSH_HEX_152);
+    case 6: return polynomialBases::find(MSH_HEX_222);
+    case 7: return polynomialBases::find(MSH_HEX_296);
+    case 8: return polynomialBases::find(MSH_HEX_386);
+    case 9: return polynomialBases::find(MSH_HEX_488);
+    default: Msg::Error("Order %d hex function space not implemented", order);
+    }
+  }
+  else {
+    switch (order) {
+    case 0: return polynomialBases::find(MSH_HEX_1);
+    case 1: return polynomialBases::find(MSH_HEX_8);
+    case 2: return polynomialBases::find(MSH_HEX_27);
+    case 3: return polynomialBases::find(MSH_HEX_64);
+    case 4: return polynomialBases::find(MSH_HEX_125);
+    case 5: return polynomialBases::find(MSH_HEX_216);
+    case 6: return polynomialBases::find(MSH_HEX_343);
+    case 7: return polynomialBases::find(MSH_HEX_512);
+    case 8: return polynomialBases::find(MSH_HEX_729);
+    case 9: return polynomialBases::find(MSH_HEX_1000);
+    default: Msg::Error("Order %d hex function space not implemented", order);
+    }
+  }
+  return 0;
+}
diff --git a/Geo/MHexahedron.h b/Geo/MHexahedron.h
index efb616abd9a203ab4efeac1a16d9b28152a09ac3..40a4563bc6b7789536c823c83233c7dcb60e3b7d 100644
--- a/Geo/MHexahedron.h
+++ b/Geo/MHexahedron.h
@@ -57,6 +57,7 @@ class MHexahedron : public MElement {
   virtual int getDim() const { return 3; }
   virtual int getNumVertices() const { return 8; }
   virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual const polynomialBasis* getFunctionSpace(int o=-1) const;
   virtual MVertex *getVertexMED(int num)
   {
     static const int map[8] = {0, 3, 2, 1, 4, 7, 6, 5};
@@ -403,7 +404,9 @@ class MHexahedron27 : public MHexahedron {
   }
   virtual int getNumEdgeVertices() const { return 12; }
   virtual int getNumFaceVertices() const { return 6; }
-  virtual int getNumVolumeVertices() const { return 1; }
+  virtual int getNumVolumeVertices() const { 
+    return 8;
+  }
   virtual int getNumEdgesRep(){ return 24; }
   virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
   {
@@ -490,4 +493,141 @@ class MHexahedron27 : public MHexahedron {
   }
 };
 
+/*
+ * MHexahedronN
+ *
+ *   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
+ *
+ *    N = 0RDER - 1
+ *    8 := 8 --> 8 + N
+ *    9 := 8 + N + 1 --> 8 +  2 * N
+ *    : 
+ *   19 := 8 + 11 * N + 1 --> 8 +  12 * N
+ *   20 := 8 + 12 * N + 1 --> 8 +  12 * N + N^2
+ *   21 := 8 + 12 * N + N^2 --> 8 +  12 * N + 2 * N^2
+ *    : 
+ *   25 := 8 + 12 * N + 5 * N^2 + 1 --> 8 +  12 * N + 6 * N^2
+ *   26 := 8 + 12 * N + 6 * N^2 + 1 --> 8 +  12 * N + 6 * N^2 + N^3
+ * 
+ */
+
+
+class MHexahedronN : public MHexahedron {
+ protected:
+  const char _order;
+  std::vector<MVertex*> _vs;
+ public :
+ MHexahedronN(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3,
+	      MVertex *v4, MVertex *v5, MVertex *v6, MVertex *v7,
+	      const std::vector<MVertex*> &v, char order, int num=0, int part=0)
+   : MHexahedron(v0,v1,v2,v3,v4,v5,v6,v7, num, part), _order(order), _vs(v)
+    {
+      for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
+    }
+ MHexahedronN(const std::vector<MVertex*> &v, char order, int num=0, int part=0)
+   :  MHexahedron(v[0], v[1], v[2], v[3],v[4], v[5], v[6], v[7], num, part), _order(order)
+  {
+    for(unsigned int i = 8; i < v.size(); i++) _vs.push_back(v[i]);
+    for(unsigned int i = 0; i < _vs.size(); i++) _vs[i]->setPolynomialOrder(_order);
+  }
+  
+  ~MHexahedronN(){}
+  virtual int getPolynomialOrder() const { return (int)_order; }
+  virtual int getNumVertices() const { return 8 + _vs.size(); }
+  virtual MVertex *getVertex(int num){ return num < 8 ? _v[num] : _vs[num - 8]; }
+  virtual MVertex *getVertexDIFF(int num)
+  {
+    throw;
+  }
+  virtual int getNumEdgeVertices() const { return 12 * (_order - 1); }
+  virtual int getNumFaceVertices() const { return 6 * (_order - 1)*(_order - 1); }
+  virtual int getNumVolumeVertices() const { 
+    switch(getTypeForMSH()){
+    case MSH_HEX_27 : 
+    case MSH_HEX_64 : 
+    case MSH_HEX_125 : 
+    case MSH_HEX_216 : 
+    case MSH_HEX_343 : 
+    case MSH_HEX_512 : 
+    case MSH_HEX_729 : 
+    case MSH_HEX_1000 : 
+      return (_order - 1)*(_order - 1)*(_order - 1); 
+    default:
+      return 0;
+    }
+  }
+  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(_order+1);
+    MHexahedron::_getEdgeVertices(num, v);
+    for (int i=0;i<_order-1;i++) v[2+i] = _vs[(_order-1)*num+i];
+  }
+  //virtual int getNumFacesRep();
+  virtual void getFaceVertices(const int num, std::vector<MVertex*> &v) const
+  {
+    v.resize((_order+1)*(_order+1));
+    MHexahedron::_getFaceVertices(num, v);
+    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}
+    };
+    int count = 4;
+    for (int i=0;i<4;i++){
+      for (int j=0;j<_order-1;j++) v[count++] = _vs[(_order-1)*f[num][i]+j];      
+    }
+    for (int i=0;i<(_order+1)*(_order+1);i++){
+      int N = _order - 1;
+      int start = 8 + 12 * N + num * (_order-1)*(_order-1);
+      v[count++] = _vs[start + i];
+    }
+  }
+  virtual int getTypeForMSH() const
+  {
+    // (p+1)^3
+    if(_order == 3 && _vs.size() + 8 == 64 ) return MSH_HEX_64;
+    if(_order == 4 && _vs.size() + 8 == 125) return MSH_HEX_125;
+    if(_order == 5 && _vs.size() + 8 == 216) return MSH_HEX_216;
+    if(_order == 6 && _vs.size() + 8 == 343) return MSH_HEX_343;
+    if(_order == 7 && _vs.size() + 8 == 512) return MSH_HEX_512;
+    if(_order == 8 && _vs.size() + 8 == 729) return MSH_HEX_729;
+    if(_order == 9 && _vs.size() + 8 == 1000) return MSH_HEX_1000;
+    if(_order == 3 && _vs.size() + 8 == 56 ) return MSH_HEX_56;
+    if(_order == 4 && _vs.size() + 8 == 98) return MSH_HEX_98;
+    if(_order == 5 && _vs.size() + 8 == 152) return MSH_HEX_152;
+    if(_order == 6 && _vs.size() + 8 == 222) return MSH_HEX_222;
+    if(_order == 7 && _vs.size() + 8 == 296) return MSH_HEX_296;
+    if(_order == 8 && _vs.size() + 8 == 386) return MSH_HEX_386;
+    if(_order == 9 && _vs.size() + 8 == 488) return MSH_HEX_488;
+    return 0;
+  }
+  virtual void getShapeFunctions(double u, double v, double w, double s[], int o){
+    MElement::getShapeFunctions (u,v,w,s,o);
+  }
+  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o)
+  {
+    MElement::getGradShapeFunctions (u,v,w,s,o);
+  }
+
+  virtual void revert()
+  {
+    Msg::Error("not done yet reverse hexN");
+  }
+};
+
 #endif
diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp
index 3882923b207854eda2b973d04cdbb2fc39e9bb4d..026a3f6b719c82ca1d6e8aa554e9ca7126c0f8dc 100644
--- a/Mesh/HighOrder.cpp
+++ b/Mesh/HighOrder.cpp
@@ -412,7 +412,7 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele,
     }
     else{
       std::vector<MVertex*> &vtcs = faceVertices[face];
-      SPoint2 pts[100];
+      SPoint2 pts[1000];
       bool reparamOK = true;
       if(!linear){
         for(int k = 0; k < incomplete->getNumVertices(); k++)
@@ -430,7 +430,7 @@ static void getFaceVertices(GFace *gf, MElement *incomplete, MElement *ele,
         }
         else{
           double X(0), Y(0), Z(0), GUESS[2] = {0, 0};
-          double sf[256];
+          double sf[1256];
           incomplete->getShapeFunctions(t1, t2, 0, sf);
           for (int j = 0; j < incomplete->getNumShapeFunctions(); j++){
             MVertex *vt = incomplete->getShapeFunctionNode(j);
@@ -498,6 +498,71 @@ static void reorientTrianglePoints(std::vector<MVertex*> &vtcs, int orientation,
   }
 } 
 
+static void reorientQuadPoints(std::vector<MVertex*> &vtcs, int orientation, 
+			       bool swap, int order)
+{
+  int nbPts = vtcs.size();
+  if (nbPts <= 1) return;
+  std::vector<MVertex*> tmp(nbPts);  
+
+  //  printf("before : ");
+  //  for (int i=0;i<vtcs.size();i++)printf("%d ",vtcs[i]->getNum());
+  //  printf("\n");
+  int start = 0;
+  while (1){
+    // CORNERS
+    int index = 0;
+    if (order == 0){
+      start++;
+    }
+    else{
+      int i1,i2,i3,i4;
+      if (!swap){
+	if      (orientation == 0){i1 = 0; i2=1; i3=2; i4 = 3;}
+	else if (orientation == 1){i1 = 3; i2=0; i3=1; i4 = 2;}
+	else if (orientation == 2){i1 = 2; i2=3; i3=0; i4 = 1;}
+	else if (orientation == 3){i1 = 1; i2=2; i3=3; i4 = 0;}
+      }
+      else{
+	if      (orientation == 0){i1 = 0; i2=3; i3=2; i4 = 1;}
+	else if (orientation == 3){i1 = 3; i2=2; i3=1; i4 = 0;}
+	else if (orientation == 2){i1 = 2; i2=1; i3=0; i4 = 3;}
+	else if (orientation == 1){i1 = 1; i2=0; i3=3; i4 = 2;}
+      }
+
+      int indices[4] = {i1,i2,i3,i4};
+      for (int i=0;i<4;i++)tmp[i] = vtcs[start+indices[i]];
+      for (int i=0;i<4;i++)vtcs[start+i] = tmp[i];
+
+      // EDGES
+      for (int iEdge=0;iEdge<4;iEdge++){
+	int p1 = indices[iEdge];
+	int p2 = indices[(iEdge+1)%4];
+	int nbP = order-1;
+	if      (p1 == 0 && p2 == 1){for (int i=4+0*nbP;i< 4+1*nbP;i++) tmp[index++] = vtcs[i];}
+	else if (p1 == 1 && p2 == 2){for (int i=4+1*nbP;i< 4+2*nbP;i++) tmp[index++] = vtcs[i];}
+	else if (p1 == 2 && p2 == 3){for (int i=4+2*nbP;i< 4+3*nbP;i++) tmp[index++] = vtcs[i];}
+	else if (p1 == 3 && p2 == 0){for (int i=4+3*nbP;i< 4+4*nbP;i++) tmp[index++] = vtcs[i];}
+
+	else if (p1 == 1 && p2 == 0){for (int i=4+1*nbP-1;i>= 4+0*nbP;i--) tmp[index++] = vtcs[i];}
+	else if (p1 == 2 && p2 == 1){for (int i=4+2*nbP-1;i>= 4+1*nbP;i--) tmp[index++] = vtcs[i];}
+	else if (p1 == 3 && p2 == 2){for (int i=4+3*nbP-1;i>= 4+2*nbP;i--) tmp[index++] = vtcs[i];}
+	else if (p1 == 0 && p2 == 3){for (int i=4+4*nbP-1;i>= 4+3*nbP;i--) tmp[index++] = vtcs[i];}
+	else printf("ouuls\n");
+      }	
+      for (int i=0;i<index;i++)vtcs[start+4+i] = tmp[i];      
+      start += (4+index);
+    }
+
+    order -= 2;
+    if (start >= vtcs.size()) break;
+  }
+  //  printf("after : ");
+  //  for (int i=0;i<vtcs.size();i++)printf("%p ",vtcs[i]);
+  //  printf("\n");
+} 
+
+
 // KH: check face orientation wrt element ... 
 
 static void getFaceVertices(GRegion *gr, MElement *ele, std::vector<MVertex*> &vf,
@@ -506,53 +571,100 @@ static void getFaceVertices(GRegion *gr, MElement *ele, std::vector<MVertex*> &v
 {
   fullMatrix<double> points;
   int start = 0;
-  switch (nPts){
-  case 0 :
-  case 1 :
-    // do nothing (e.g. for 2nd order tri faces or for quad faces)
-    break;
-  case 2 :
-    points = polynomialBases::find(MSH_TRI_10)->points;
-    start = 9;
-    break;
-  case 3 :
-    points = polynomialBases::find(MSH_TRI_15)->points;
-    start = 12;
-    break;
-  case 4 :
-    points = polynomialBases::find(MSH_TRI_21)->points;
-    start = 15;
-    break;
-  case 5 :
-    points = polynomialBases::find(MSH_TRI_28)->points;
-    start = 18;
-    break;
-  case 6 :
-    points = polynomialBases::find(MSH_TRI_36)->points;
-    start = 21;
-    break;
-  case 7 :
-    points = polynomialBases::find(MSH_TRI_45)->points;
-    start = 24;
-    break;
-  case 8 :
-    points = polynomialBases::find(MSH_TRI_55)->points;
-    start = 27;
-    break;
-  case 9 :
-    points = polynomialBases::find(MSH_TRI_66)->points;
-    start = 30;
-    break;
-  default :  
-    Msg::Error("getFaceVertices not implemented for order %i\n",nPts +1);
-    break;
+
+  switch(ele->getType()){
+  case TYPE_TET:
+    {
+      switch (nPts){
+      case 0 :
+      case 1 :
+	// do nothing (e.g. for 2nd order tri faces)
+	break;
+      case 2 :
+	points = polynomialBases::find(MSH_TRI_10)->points;
+	start = 9;
+	break;
+      case 3 :
+	points = polynomialBases::find(MSH_TRI_15)->points;
+	start = 12;
+	break;
+      case 4 :
+	points = polynomialBases::find(MSH_TRI_21)->points;
+	start = 15;
+	break;
+      case 5 :
+	points = polynomialBases::find(MSH_TRI_28)->points;
+	start = 18;
+	break;
+      case 6 :
+	points = polynomialBases::find(MSH_TRI_36)->points;
+	start = 21;
+	break;
+      case 7 :
+	points = polynomialBases::find(MSH_TRI_45)->points;
+	start = 24;
+	break;
+      case 8 :
+	points = polynomialBases::find(MSH_TRI_55)->points;
+	start = 27;
+	break;
+      case 9 :
+	points = polynomialBases::find(MSH_TRI_66)->points;
+	start = 30;
+	break;
+      default :  
+	Msg::Error("getFaceVertices not implemented for order %i\n",nPts +1);
+	break;
+      }
+      break;
+    }
+  case TYPE_HEX:
+    {
+      switch (nPts){
+      case 0 :
+	// do nothing (e.g. for 1nd order quad faces)
+	break;
+      case 1 :
+	points = polynomialBases::find(MSH_QUA_9)->points;
+	break;
+      case 2 :
+	points = polynomialBases::find(MSH_QUA_16)->points;
+	break;
+      case 3 :
+	points = polynomialBases::find(MSH_QUA_25)->points;
+	break;
+      case 4 :
+	points = polynomialBases::find(MSH_QUA_36)->points;
+	break;
+      case 5 :
+	points = polynomialBases::find(MSH_QUA_49)->points;
+	break;
+      case 6 :
+	points = polynomialBases::find(MSH_QUA_64)->points;
+	break;
+      case 7 :
+	points = polynomialBases::find(MSH_QUA_81)->points;
+	break;
+      case 8 :
+	points = polynomialBases::find(MSH_QUA_100)->points;
+	break;
+      default :  
+	Msg::Error("getFaceVertices not implemented for order %i\n",nPts +1);
+	break;
+      }
+      start = (nPts+2)*(nPts+2) - nPts*nPts;
+      //      printf("start = %d\n",start);
+      break;
+    }
   }
-  
+
   for(int i = 0; i < ele->getNumFaces(); i++){
     MFace face = ele->getFace(i);
+    //    printf(" face %d %d vertices\n",i,face.getNumVertices());
     faceContainer::iterator fIter = faceVertices.find(face);
-    if (fIter != faceVertices.end()) {
+    if (fIter != faceVertices.end() ) {
       std::vector<MVertex*> vtcs = fIter->second;
+      //      printf("found %d\n",vtcs.size());
       if(face.getNumVertices() == 3 && nPts > 1){ // tri face
         int orientation;
         bool swap;
@@ -562,7 +674,16 @@ static void getFaceVertices(GRegion *gr, MElement *ele, std::vector<MVertex*> &v
           Msg::Error("Error in face lookup for recuperation of high order face nodes");
       }
       else if(face.getNumVertices() == 4){ // quad face
-        // TODO reorient if more than 1 face vertex
+        int orientation;
+        bool swap;
+        if (fIter->first.computeCorrespondence(face, orientation, swap)){
+	  //	  printf("%d %d %d %d\n",face.getVertex(0)->getNum(),face.getVertex(1)->getNum(),face.getVertex(2)->getNum(),face.getVertex(3)->getNum());
+	  //	  printf("%d %d %d %d\n",fIter->first.getVertex(0)->getNum(),fIter->first.getVertex(1)->getNum(),fIter->first.getVertex(2)->getNum(),fIter->first.getVertex(3)->getNum());
+	  //	  printf("%d %d\n",orientation,swap);
+          reorientQuadPoints(vtcs, orientation, swap, nPts-1);
+	}
+        else
+          Msg::Error("Error in face lookup for recuperation of high order face nodes");
       }
       vf.insert(vf.end(), vtcs.begin(), vtcs.end());
     }
@@ -600,17 +721,17 @@ static void getFaceVertices(GRegion *gr, MElement *ele, std::vector<MVertex*> &v
         }         
       }
       else if(face.getNumVertices() == 4){ // quad face
-        for(int j = 0; j < nPts; j++){
-          for(int k = 0; k < nPts; k++){
+	//	printf(" quad face %d pts\n",nPts);
+	// FIXME : CURVED Quad Face
+        for (int k = start; k < points.size1(); k++) {
             // parameters are between -1 and 1
-            double t1 = 2. * (double)(j + 1) / (nPts + 1) - 1.;
-            double t2 = 2. * (double)(k + 1) / (nPts + 1) - 1.;
-            SPoint3 pc = face.interpolate(t1, t2);
-            MVertex *v = new MVertex(pc.x(), pc.y(), pc.z(), gr);
-            vtcs.push_back(v);
-            gr->mesh_vertices.push_back(v);
-            vf.push_back(v);
-          }
+          double t1 = points(k, 0);
+          double t2 = points(k, 1);
+	  SPoint3 pc = face.interpolate(t1, t2);
+	  MVertex *v = new MVertex(pc.x(), pc.y(), pc.z(), gr);
+	  vtcs.push_back(v);
+	  gr->mesh_vertices.push_back(v);
+	  vf.push_back(v);
         }
       }
     }
@@ -623,37 +744,81 @@ static void getRegionVertices(GRegion *gr, MElement *incomplete, MElement *ele,
   fullMatrix<double> points;
   int start = 0;
 
-  switch (nPts){
-    case 0:
-    case 1:
-    case 2:
-    // done: return!
-    return;
-  case 3 :
-    points = polynomialBases::find(MSH_TET_35)->points;
-    break;
-  case 4 :
-    points = polynomialBases::find(MSH_TET_56)->points;
-    break;
-  case 5 :
-    points = polynomialBases::find(MSH_TET_84)->points;
-    break;
-  case 6 :
-    points = polynomialBases::find(MSH_TET_120)->points;
-    break;
-  case 7 :
-    points = polynomialBases::find(MSH_TET_165)->points;
-    break;
-  case 8 :
-    points = polynomialBases::find(MSH_TET_220)->points;
-    break;
-  case 9 :
-    points = polynomialBases::find(MSH_TET_286)->points;
-    break;
-  default :  
-    Msg::Error("getRegionVertices not implemented for order %i\n", nPts+1);
+  switch (incomplete->getType()){
+  case TYPE_TET : 
+    {
+      switch (nPts){
+      case 0:
+      case 1:
+	return;	
+      case 2:
+	points = polynomialBases::find(MSH_TET_20)->points;
+	break;
+      case 3 :
+	points = polynomialBases::find(MSH_TET_35)->points;
+	break;
+      case 4 :
+	points = polynomialBases::find(MSH_TET_56)->points;
+	break;
+      case 5 :
+	points = polynomialBases::find(MSH_TET_84)->points;
+	break;
+      case 6 :
+	points = polynomialBases::find(MSH_TET_120)->points;
+	break;
+      case 7 :
+	points = polynomialBases::find(MSH_TET_165)->points;
+	break;
+      case 8 :
+	points = polynomialBases::find(MSH_TET_220)->points;
+	break;
+      case 9 :
+	points = polynomialBases::find(MSH_TET_286)->points;
+	break;
+      default :  
+	Msg::Error("getRegionVertices not implemented for order %i\n", nPts+1);
+      }
+      start = ((nPts+2)*(nPts+3)*(nPts+4)-(nPts-2)*(nPts-1)*(nPts))/6;
+      break;
+    }
+  case TYPE_HEX :
+    {
+      switch (nPts){
+      case 0:
+	return;
+      case 1:
+	points = polynomialBases::find(MSH_HEX_27)->points;
+	break;
+      case 2 :
+	points = polynomialBases::find(MSH_HEX_64)->points;
+	break;
+      case 3 :
+	points = polynomialBases::find(MSH_HEX_125)->points;
+	break;
+      case 4 :
+	points = polynomialBases::find(MSH_HEX_216)->points;
+	break;
+      case 5 :
+	points = polynomialBases::find(MSH_HEX_343)->points;
+	break;
+      case 6 :
+	points = polynomialBases::find(MSH_HEX_512)->points;
+	break;
+      case 7 :
+	points = polynomialBases::find(MSH_HEX_729)->points;
+	break;
+      case 8 :
+	points = polynomialBases::find(MSH_HEX_1000)->points;
+	break;
+      default :  
+	Msg::Error("getRegionVertices not implemented for order %i\n", nPts+1);
+      }
+      start = (nPts+2)*(nPts+2)*(nPts+2) - (nPts)*(nPts)*(nPts) ;
+      break;
+    }
   }
-  start = ((nPts+2)*(nPts+3)*(nPts+4)-(nPts-2)*(nPts-1)*(nPts))/6;
+  
+  //  printf ("incomplete type %d starts at %d\n",incomplete->getTypeForMSH(),start);
 
   for(int k = start; k < points.size1(); k++){
     MVertex *v;
@@ -662,6 +827,7 @@ static void getRegionVertices(GRegion *gr, MElement *incomplete, MElement *ele,
     const double t3 = points(k, 2);
     SPoint3 pos;
     incomplete->pnt(t1,t2,t3,pos);
+    //    printf("pnt(%g %g %g) = %g %g %g\n",t1,t2,t3,pos.x(),pos.y(),pos.z());
     v = new MVertex(pos.x(),pos.y(),pos.z(),gr);
     gr->mesh_vertices.push_back(v);
     vr.push_back(v);
@@ -841,27 +1007,69 @@ static void setHighOrder(GRegion *gr, edgeContainer &edgeVertices,
   std::vector<MHexahedron*> hexahedra2;
   for(unsigned int i = 0; i < gr->hexahedra.size(); i++){
     MHexahedron *h = gr->hexahedra[i];
-    std::vector<MVertex*> ve, vf;
+    h->revert();
+    std::vector<MVertex*> ve, vf, vr;
     getEdgeVertices(gr, h, ve, edgeVertices, linear, nPts, displ2D, displ3D);
-    if(incomplete){
-      hexahedra2.push_back
-        (new MHexahedron20(h->getVertex(0), h->getVertex(1), h->getVertex(2), 
-                           h->getVertex(3), h->getVertex(4), h->getVertex(5), 
-                           h->getVertex(6), h->getVertex(7), ve[0], ve[1], ve[2], 
-                           ve[3], ve[4], ve[5], ve[6], ve[7], ve[8], ve[9], ve[10], 
-                           ve[11]));
+    if(nPts == 1){
+      if(incomplete){
+	hexahedra2.push_back
+	  (new MHexahedron20(h->getVertex(0), h->getVertex(1), h->getVertex(2), 
+			     h->getVertex(3), h->getVertex(4), h->getVertex(5), 
+			     h->getVertex(6), h->getVertex(7), ve[0], ve[1], ve[2], 
+			     ve[3], ve[4], ve[5], ve[6], ve[7], ve[8], ve[9], ve[10], 
+			     ve[11]));
+      }
+      else{
+	getFaceVertices(gr, h, vf, faceVertices, edgeVertices, linear, nPts);
+	SPoint3 pc = h->barycenter();
+	MVertex *v = new MVertex(pc.x(), pc.y(), pc.z(), gr);
+	gr->mesh_vertices.push_back(v);
+	hexahedra2.push_back
+	  (new MHexahedron27(h->getVertex(0), h->getVertex(1), h->getVertex(2), 
+			     h->getVertex(3), h->getVertex(4), h->getVertex(5), 
+			     h->getVertex(6), h->getVertex(7), ve[0], ve[1], ve[2], 
+			     ve[3], ve[4], ve[5], ve[6], ve[7], ve[8], ve[9], ve[10], 
+			     ve[11], vf[0], vf[1], vf[2], vf[3], vf[4], vf[5], v));
+      }
     }
-    else{
+    else {
+      //      printf("coucou %d\n",ve.size());
       getFaceVertices(gr, h, vf, faceVertices, edgeVertices, linear, nPts);
-      SPoint3 pc = h->barycenter();
-      MVertex *v = new MVertex(pc.x(), pc.y(), pc.z(), gr);
-      gr->mesh_vertices.push_back(v);
-      hexahedra2.push_back
-        (new MHexahedron27(h->getVertex(0), h->getVertex(1), h->getVertex(2), 
-                           h->getVertex(3), h->getVertex(4), h->getVertex(5), 
-                           h->getVertex(6), h->getVertex(7), ve[0], ve[1], ve[2], 
-                           ve[3], ve[4], ve[5], ve[6], ve[7], ve[8], ve[9], ve[10], 
-                           ve[11], vf[0], vf[1], vf[2], vf[3], vf[4], vf[5], v));
+      ve.insert(ve.end(), vf.begin(), vf.end());     
+      //      printf("coucou %d\n",ve.size());
+      MHexahedronN incpl(h->getVertex(0), h->getVertex(1), h->getVertex(2), h->getVertex(3),
+			 h->getVertex(4), h->getVertex(5), h->getVertex(6), h->getVertex(7),
+			 ve, nPts + 1);
+      getRegionVertices(gr, &incpl, h, vr, linear, nPts); 
+
+      //      printf("oulax\n");
+
+      ve.insert(ve.end(), vr.begin(), vr.end());
+      //      printf("coucou %d\n",ve.size());
+      MHexahedron* n = new MHexahedronN(h->getVertex(0), h->getVertex(1), h->getVertex(2), h->getVertex(3),
+			 h->getVertex(4), h->getVertex(5), h->getVertex(6), h->getVertex(7),
+			 ve, nPts + 1);
+
+      /*
+      FILE *F = fopen ("etst.pos","w");
+      fprintf(F,"View \"\"{\n");
+      for (int i=0;i<n->getNumVertices();i++){
+	//	printf("%3d %12.5E %12.5E %12.5E\n",n->getVertex(i)->getNum(),n->getVertex(i)->x(),n->getVertex(i)->y(),n->getVertex(i)->z());
+	fprintf(F,"SP(%12.5E,%12.5E,%12.5E){%3d};\n",n->getVertex(i)->x(),n->getVertex(i)->y(),n->getVertex(i)->z(),i);//n->getVertex(i)->getNum());
+      }
+      fprintf(F,"};\n");
+      fclose(F);
+      */
+      /*
+      const polynomialBasis* temp = n->getFunctionSpace();
+      for (int i=0;i<n->getNumVertices();i++){
+	SPoint3 pt;
+	incpl.pnt(temp->points(i,0),temp->points(i,1),temp->points(i,2),pt);
+	printf("%12.5E %12.5E %12.5E -- %12.5E %12.5E %12.5E -- %12.5E %12.5E %12.5E\n",n->getVertex(i)->x(),n->getVertex(i)->y(),n->getVertex(i)->z(),
+	       pt.x(),pt.y(),pt.z(),pt.x()-n->getVertex(i)->x(),pt.y()-n->getVertex(i)->y(),pt.z()-n->getVertex(i)->z());
+      }
+      */
+      hexahedra2.push_back(n);     
     }
     delete h;
   }
@@ -1113,9 +1321,11 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete)
 
   int nPts = order - 1;
 
-  Msg::StatusBar(2, true, "Meshing order %d...", order);
+  if (!linear)Msg::StatusBar(2, true, "Meshing order %d, curvilinear ON...", order);
+  else Msg::StatusBar(2, true, "Meshing order %d, curvilinear OFF...", order);
   double t1 = Cpu();
 
+
   // first, make sure to remove any existsing second order vertices/elements
   SetOrder1(m);    
 
@@ -1143,6 +1353,7 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete)
   // we do that model face by model face
   std::vector<MElement*> bad;
   double worst;
+  printJacobians(m, "smoothness_b.pos");
   if (displ2D){
     checkHighOrderTriangles("Before optimization", m, bad, worst);
     for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it)
@@ -1166,7 +1377,7 @@ void SetOrderN(GModel *m, int order, bool linear, bool incomplete)
   if(displ2D) delete displ2D;
   if(displ3D) delete displ3D;
 
-  //  printJacobians(m, "smoothness.pos");
+  printJacobians(m, "smoothness.pos");
   
   double t2 = Cpu();
   Msg::StatusBar(2, true, "Done meshing order %d (%g s)", order, t2 - t1);
diff --git a/Mesh/highOrderSmoother.cpp b/Mesh/highOrderSmoother.cpp
index 9dea04cb76c51824508ca0c4bf0b761356aff14c..5afed29d69d9ac1ae414947e56adafbda16dcf70 100644
--- a/Mesh/highOrderSmoother.cpp
+++ b/Mesh/highOrderSmoother.cpp
@@ -29,6 +29,7 @@
 #include "elasticityTerm.h"
 #include "linearSystemCSR.h"
 #include "linearSystemFull.h"
+#include "linearSystemPetsc.h"
 
 #define SQU(a)      ((a)*(a))
 
@@ -323,6 +324,28 @@ void addOneLayer(const std::vector<MElement*> &v,
   }
 }
 
+
+void _printJacobiansAtNodes (const char * name, std::vector<MElement*> &v)
+{
+  FILE *fd = fopen (name,"w");
+  fprintf(fd,"$MeshFormat\n2 0 8\n$EndMeshFormat\n$ElementNodeData\n1\n\"det J\"\n1\n0.0\n3\n1\n1\n%d\n",v.size());
+  for (int i=0; i<v.size(); i++){
+    const polynomialBasis* pb = v[i]->getFunctionSpace();
+    fprintf(fd,"%d %d",v[i]->getNum(),v[i]->getNumVertices());
+    for (int j=0; j < v[i]->getNumVertices(); j++){
+      const double _u = pb->points(j,0);
+      const double _v = pb->points(j,1);
+      const double _w = pb->points(j,2);
+      double jac[3][3];
+      double J = v[i]->getJacobian (_u,_v,_w, jac);
+      fprintf(fd," %g",J);    
+    }
+    fprintf(fd,"\n");    
+  }
+  fprintf(fd,"$EndElementNodeData\n");
+  fclose(fd);
+}
+
 void highOrderSmoother::smooth(GFace *gf, bool metric)
 {
   std::vector<MElement*> v;
@@ -331,6 +354,14 @@ void highOrderSmoother::smooth(GFace *gf, bool metric)
   v.insert(v.begin(), gf->quadrangles.begin(),gf->quadrangles.end());
   Msg::Info("Smoothing high order mesh : model face %d (%d elements)", gf->tag(),
             v.size());
+
+  gf->model()->writeMSH("before_smoothing.msh");
+  _printJacobiansAtNodes ("before_smoothing_jac.msh", v);
+  smooth_with_mixed_formulation(v,0.2);
+  gf->model()->writeMSH("after_smoothing.msh");
+  _printJacobiansAtNodes ("after_smoothing_jac.msh", v);
+  return;
+
   if (metric)smooth_metric(v,gf);
   else smooth(v);
 }
@@ -620,6 +651,196 @@ double highOrderSmoother::smooth_metric_(std::vector<MElement*>  & v,
   return dx;
 }
 
+
+double highOrderSmoother::apply_incremental_displacement (double max_incr,
+							  std::vector<MElement*> & v,
+							  bool mixed,
+							  double thres,
+							  char *meshName,
+							  std::vector<MElement*> & disto)
+{
+#ifdef HAVE_PETSC
+  // assume that the mesh is OK, yet already curved
+  linearSystemPETSc<double> *lsys = new  linearSystemPETSc<double>;    
+  dofManager<double> myAssembler(lsys);
+  elasticityMixedTerm El_mixed (0, 1.0, .333, getTag());
+  elasticityTerm El (0, 1.0, .333, getTag());
+
+  std::set<MVertex*> _vertices;
+
+  //+++++++++ Boundary Conditions & Numbering +++++++++++++++++++++++++++++++
+  // fix all dof that correspond to vertices on the boundary 
+  // the value is equal 
+  for (unsigned int i = 0; i < v.size(); i++){
+    for (int j = 0; j < v[i]->getNumVertices(); j++){
+      MVertex *vert = v[i]->getVertex(j);
+      _vertices.insert(vert);
+    }
+  }
+
+  //+++++++++ Fix d tr(eps) = 0 +++++++++++++++++++++++++++++++
+  if (mixed){
+    for (unsigned int i = 0; i < disto.size(); i++){
+      for (int j = 0; j < disto[i]->getNumVertices(); j++){
+	MVertex *vert = disto[i]->getVertex(j);
+	myAssembler.fixVertex(vert, 4, getTag(), 0.0);
+      }
+    }
+  }
+
+  for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){
+    MVertex *vert = *it;
+    std::map<MVertex*,SVector3>::iterator itt = _targetLocation.find(vert);
+    // impose displacement @ boundary
+    if (vert->onWhat()->geomType() != GEntity::Line && vert->onWhat()->tag() != 1){ // TEST
+      if (itt != _targetLocation.end() && vert->onWhat()->dim() < _dim){
+	myAssembler.fixVertex(vert, 0, getTag(), itt->second.x()-vert->x());
+	myAssembler.fixVertex(vert, 1, getTag(), itt->second.y()-vert->y());
+	myAssembler.fixVertex(vert, 2, getTag(), itt->second.z()-vert->z());
+      }
+      // ensure we do not touch any vertex that is on the boundary
+      else if (vert->onWhat()->dim() < _dim){
+	myAssembler.fixVertex(vert, 0, getTag(), 0);
+	myAssembler.fixVertex(vert, 1, getTag(), 0);
+	myAssembler.fixVertex(vert, 2, getTag(), 0);
+      }
+    }
+    if (_dim == 2)myAssembler.fixVertex(vert, 2, getTag(), 0);
+    // number vertices 
+    myAssembler.numberVertex(vert, 0, getTag());
+    myAssembler.numberVertex(vert, 1, getTag());
+    myAssembler.numberVertex(vert, 2, getTag());
+    if (mixed){
+      myAssembler.numberVertex(vert, 3, getTag());
+      myAssembler.numberVertex(vert, 4, getTag());
+    }
+  }
+
+  //+++++++++ Assembly  & Solve ++++++++++++++++++++++++++++++++++++
+  if (myAssembler.sizeOfR()){
+    // assembly of the elasticity term on the
+    for (unsigned int i = 0; i < v.size(); i++){
+      SElement se(v[i]);
+      if (mixed)El_mixed.addToMatrix(myAssembler, &se);
+      else El.addToMatrix(myAssembler, &se);
+    }
+    // solve the system
+    lsys->systemSolve();
+  }
+  
+  //+++++++++ Move vertices @ maximum ++++++++++++++++++++++++++++++++++++
+  FILE *fd = fopen ("d.msh","w");
+  fprintf(fd,"$MeshFormat\n2 0 8\n$EndMeshFormat\n$NodeData\n1\n\"tr(sigma)\"\n1\n0.0\n3\n1\n3\n%d\n",_vertices.size());
+  for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){
+    double ax, ay, az;
+    myAssembler.getDofValue(*it, 0, getTag(), ax);
+    myAssembler.getDofValue(*it, 1, getTag(), ay);
+    myAssembler.getDofValue(*it, 2, getTag(), az);    
+    (*it)->x() += max_incr*ax;
+    (*it)->y() += max_incr*ay;
+    (*it)->z() += max_incr*az;
+    fprintf(fd,"%d %g %g %g\n",(*it)->getIndex(), ax,ay,az);
+  }
+  fprintf(fd,"$EndNodeData\n");
+  fclose(fd);
+
+  //+------------------- Check now if elements are ok ---------------+++++++
+
+  (*_vertices.begin())->onWhat()->model()->writeMSH(meshName);
+
+  /*
+    std::map<MVertex*,double> facts;
+    while(1){
+    int count = 0; 
+    for (unsigned int i = 0; i < v.size(); i++){
+    double disto = v[i]->distoShapeMeasure();
+    if (disto < thres){
+    count ++;
+    for (int j = 0; j < v[i]->getNumVertices(); j++){
+    MVertex *vert = v[i]->getVertex(j);
+    std::map<MVertex*,double>::iterator it = facts.find(vert);
+    if (it == facts.end())facts[vert] = .1;
+    else if (it->second < 1){
+    it->second += .1;
+    double ax, ay, az;
+    myAssembler.getDofValue(vert, 0, getTag(), ax);
+    myAssembler.getDofValue(vert, 1, getTag(), ay);
+    myAssembler.getDofValue(vert, 2, getTag(), az);    
+    vert->x() -= .1*ax;
+    vert->y() -= .1*ay;
+    vert->z() -= .1*az;
+    }
+    }
+    }
+    if (!count)break;
+    Msg::Info("%d elements are negative : reducing displacement",count);
+    }
+  */
+
+  double percentage = max_incr * 100.;
+  while(1){
+    std::vector<MElement*> disto;
+    double minD;
+    getDistordedElements(v, 0.5, disto, minD);    
+    if (minD < thres){
+      percentage -= 10.;
+      for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end(); ++it){
+	double ax, ay, az;
+	myAssembler.getDofValue(*it, 0, getTag(), ax);
+	myAssembler.getDofValue(*it, 1, getTag(), ay);
+	myAssembler.getDofValue(*it, 2, getTag(), az);    
+	(*it)->x() -= .1*ax;
+	(*it)->y() -= .1*ay;
+	(*it)->z() -= .1*az;
+      }
+    }
+    else break;
+  }
+    
+  delete lsys;
+  return percentage;
+#endif
+  return 0.0;
+}
+
+int highOrderSmoother::smooth_with_mixed_formulation (std::vector<MElement*> &all, 
+						      double alpha)
+{
+  int ITER = 0;
+  double minD, FACT = 1.0;
+  std::vector<MElement*> disto;
+  // move the points to their straight sided locations
+  for (unsigned int i = 0; i < all.size(); i++)
+    moveToStraightSidedLocation(all[i]);
+  // apply the displacement
+  double percentage = 0.0;
+  while(1){
+    char NN[256];
+    sprintf(NN,"smoothing-%d.msh",ITER++);
+    //double percentage_of_what_is_left = apply_incremental_displacement (1.,all, false, alpha,NN,disto);
+    	  double percentage_of_what_is_left = apply_incremental_displacement (1.,all, true, alpha,NN,all);
+    percentage += (1.-percentage) * percentage_of_what_is_left/100.;
+    Msg::Info("The smoother was able to do %3d percent of the motion",(int)(percentage*100.));
+    if (percentage_of_what_is_left == 0.0) break;
+    else if (percentage_of_what_is_left == 100.)break;
+  }
+
+  getDistordedElements(all, 0.3, disto, minD);    
+  Msg::Info("iter %d : %d elements / %d distorted  min Disto = %g ",ITER,
+	    all.size(), disto.size(), minD);       
+
+  if (0 && percentage < 0.99){
+    char NN[256];
+    sprintf(NN,"smoothing-%d.msh",ITER++);
+    double percentage_of_what_is_left = apply_incremental_displacement (1.0,all, true, alpha,NN,disto);    
+    percentage += (1.-percentage) * percentage_of_what_is_left/100.;
+    Msg::Info("The mixed smoother was able to do %3d percent of the motion",(int)(percentage*100.));
+  }
+  
+  return 1;
+}
+
+
 void highOrderSmoother::smooth(std::vector<MElement*> &all)
 {
 #ifdef HAVE_TAUCS
@@ -641,7 +862,7 @@ void highOrderSmoother::smooth(std::vector<MElement*> &all)
   Msg::Info("%d elements / %d distorted  min Disto = %g\n",
              all.size(), v.size(), minD);
 
-  if (!v.size()) return;
+  if (!v.size());
 
   const int nbLayers = 6;
   for (int i = 0; i < nbLayers; i++){
diff --git a/Mesh/highOrderSmoother.h b/Mesh/highOrderSmoother.h
index 9ff58bc77043b8d448697d07bfcffe0454472219..26a684cc08fc396d35d346f85841964fe51b0eef 100644
--- a/Mesh/highOrderSmoother.h
+++ b/Mesh/highOrderSmoother.h
@@ -44,6 +44,11 @@ public:
     _straightSidedLocation[v] = d;
     _targetLocation[v]        = SPoint3(v->x(),v->y(),v->z());
   }  
+  int smooth_with_mixed_formulation(std::vector<MElement*> & , 
+				    double alpha);
+  double apply_incremental_displacement (double max_incr, std::vector<MElement*> & v,
+					 bool mixed, double thres, char *meshName,
+					 std::vector<MElement*> & disto);
   void smooth(std::vector<MElement*> & );
   double smooth_metric_(std::vector<MElement*> &, GFace *gf,
                         dofManager<double> &myAssembler,
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 07956971eb07e8882fafb64d2654effd3f78c934..1b5c8942fe142df3d8b42987ba499841cfa72a83 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -626,7 +626,7 @@ static int _quadWithOneVertexOnBoundary (GFace *gf,
 					 MVertex *v2,
 					 MVertex *v3,
 					 MVertex *v4){
-  return 0;
+  //return 0;
   if (v1->onWhat()->dim() < 2 &&
       v2->onWhat()->dim() == 2 &&
       v3->onWhat()->dim() == 2 &&
@@ -1862,10 +1862,10 @@ void recombineIntoQuads(GFace *gf,
   if(gf->geomType() == GEntity::DiscreteSurface && !gf->getCompound())
     haveParam = false;
 
-  gf->model()->writeMSH("before.msh");
   if(haveParam && topologicalOpti)
     removeFourTrianglesNodes(gf, false);
 
+  gf->model()->writeMSH("before.msh");
   int success = _recombineIntoQuads(gf, 0);
 
   // gf->addLayersOfQuads(1, 0);
diff --git a/Mesh/qualityMeasures.cpp b/Mesh/qualityMeasures.cpp
index 5a9738360601c81093024b37a871cd9214f7c349..2b2e4dc88f984cfd2e972dc151998154b4c365aa 100644
--- a/Mesh/qualityMeasures.cpp
+++ b/Mesh/qualityMeasures.cpp
@@ -235,6 +235,7 @@ double qmDistorsionOfMapping (MTriangle *e)
     const double u = pts[i].pt[0];
     const double v = pts[i].pt[1];
     const double di  = mesh_functional_distorsion (e, u, v);
+    //    printf("di = %g\n",di);
     dmin = (i == 0)? di : std::min(dmin, di);
   }
   const fullMatrix<double>& points = e->getFunctionSpace()->points;
diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp
index 81be8ed044ecfe4b3f402b49d1187a0a78d5c302..59b59416dfe2634417f6dfae31a3aa7b26767e4e 100644
--- a/Numeric/polynomialBasis.cpp
+++ b/Numeric/polynomialBasis.cpp
@@ -159,7 +159,7 @@ const fullMatrix<double> &polynomialBasis::getGradientAtFaceIntegrationPoints(in
       const polynomialBasis *fsFace = polynomialBases::find(closures[iClosure].type);
       gaussIntegration::get(fsFace->parentType, integrationOrder, integrationFace, weight);
       fullMatrix<double> integration(integrationFace.size1(), 3);
-      double f[256];
+      double f[1256];
       for (int i = 0; i < integrationFace.size1(); i++){
         fsFace->f(integrationFace(i,0),integrationFace(i,1),integrationFace(i,2),f);
         for(size_t j=0; j<closures[iClosure].size(); j++) {
@@ -170,7 +170,7 @@ const fullMatrix<double> &polynomialBasis::getGradientAtFaceIntegrationPoints(in
       }
       fullMatrix<double> &v = dfAtFace[iClosure];
       v.resize(nbPsi, integration.size1()*3);
-      double g[256][3];
+      double g[1256][3];
       for (size_t xi = 0; xi< integration.size1(); xi++) {
         df(integration(xi,0 ), integration(xi,1), integration(xi,2), g);
         for (int j = 0; j < nbPsi; j++) {
@@ -203,6 +203,7 @@ static fullMatrix<double> generatePascalQuad(int order)
   return monomials;
 }
 
+
 /*
 00 10 20 30 40 ⋯
 01 11 21 31 41 ⋯
@@ -213,26 +214,25 @@ static fullMatrix<double> generatePascalQuad(int order)
 */
 
 // generate all monomials xi^m * eta^n with n and m <= order
-static fullMatrix<double> generatePascalHex(int order)
+static fullMatrix<double> generatePascalHex(int order, bool serendip)
 {
-
-  fullMatrix<double> monomials( (order+1)*(order+1)*(order+1), 3);
+  int siz = (order+1)*(order+1)*(order+1);
+  if (serendip) siz -= (order-1)*(order-1)*(order-1);
+  fullMatrix<double> monomials( siz, 3);
   int index = 0;
-  for (int p = 0; p <= order; p++) {
-    for(int i = 0; i < p; i++) {
-      for(int j = 0; j < i; j++, index++) {
-	monomials(index, 0) = p;
-	monomials(index, 1) = i;
-	monomials(index, 2) = j;
-      }
-    }
-    for(int i = 0; i <= p; i++, index++) {
-      for(int j = 0; j <= p; i++, index++) {
-	monomials(index, 0) = p-i;
-	monomials(index, 1) = p;
+  for (int i = 0; i <= order; i++) {
+    for (int j = 0; j <= order; j++) {
+      for (int k = 0; k <= order; k++) {
+	if (!serendip || i<2 || j<2 || k<2){
+	  monomials(index,0) = i;
+	  monomials(index,1) = j;
+	  monomials(index,2) = k;
+	  index++;
+	}
       }
     }
   }
+  //  printf("siz %d %d\n",siz,index );	
   return monomials;
 }
 
@@ -265,6 +265,7 @@ static fullMatrix<double> generatePascalQuadSerendip(int order)
   return monomials;
 }
 
+
 /*static fullMatrix<double> generatePascalQuadSerendip(int order)
 {
 
@@ -843,7 +844,8 @@ static fullMatrix<double> gmshGeneratePointsQuad(int order, bool serendip)
           point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order;
         }
       }
-      if (order > 2 && !serendip) {
+      // FIXIT it was > 2 and I beleive it is >= 2 !!
+      if (order >= 2 && !serendip) {
         fullMatrix<double> inner = gmshGeneratePointsQuad(order - 2, false);
         inner.scale(1. - 2./order);
         point.copy(inner, 0, nbPoints - index, 0, 2, index, 0);
@@ -857,6 +859,120 @@ static fullMatrix<double> gmshGeneratePointsQuad(int order, bool serendip)
   return point;
 }
 
+static fullMatrix<double> gmshGeneratePointsHex(int order, bool serendip)
+{
+  int nbPoints = (order+1)*(order+1)*(order+1);
+  if (serendip) nbPoints -= (order-1)*(order-1)*(order-1);
+  fullMatrix<double> point(nbPoints, 3);
+  
+  // should be a public member of MHexahedron, just copied
+  static const int edges[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}
+  };
+  static const int faces[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}
+  };
+
+  if (order > 0) {
+    point(0, 0) = -1;
+    point(0, 1) = -1;
+    point(0, 2) = -1;
+    point(1, 0) = 1;
+    point(1, 1) = -1;
+    point(1, 2) = -1;
+    point(2, 0) = 1;
+    point(2, 1) = 1;
+    point(2, 2) = -1;
+    point(3, 0) = -1;
+    point(3, 1) = 1;
+    point(3, 2) = -1;
+
+    point(4, 0) = -1;
+    point(4, 1) = -1;
+    point(4, 2) = 1;
+    point(5, 0) = 1;
+    point(5, 1) = -1;
+    point(5, 2) = 1;
+    point(6, 0) = 1;
+    point(6, 1) = 1;
+    point(6, 2) = 1;
+    point(7, 0) = -1;
+    point(7, 1) = 1;
+    point(7, 2) = 1;
+
+    if (order > 1) {
+      int index = 8;
+      for (int iedge=0; iedge<12; iedge++) {
+        int p0 = edges[iedge][0];
+        int p1 = edges[iedge][1];
+        for (int i = 1; i < order; i++, index++) {
+          point(index, 0) = point(p0, 0) + i*(point(p1,0)-point(p0,0))/order;
+          point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order;
+          point(index, 2) = point(p0, 2) + i*(point(p1,2)-point(p0,2))/order;
+        }
+      }
+      
+      fullMatrix<double> fp = gmshGeneratePointsQuad(order - 2, false);
+      fp.scale(1. - 2./order);
+      for (int iface=0; iface<6; iface++) {
+	int p0 = faces[iface][0];
+	int p1 = faces[iface][1];
+	int p2 = faces[iface][2];
+	int p3 = faces[iface][3];
+	for (int i=0;i<fp.size1();i++, index++){
+	  const double u = fp(i,0);
+	  const double v = fp(i,1);
+	  const double newU = 
+	    0.25*(1.-u)*(1.-v)*point(p0,0) +
+	    0.25*(1.+u)*(1.-v)*point(p1,0) +
+	    0.25*(1.+u)*(1.+v)*point(p2,0) +
+	    0.25*(1.-u)*(1.+v)*point(p3,0) ;
+	  const double newV = 
+	    0.25*(1.-u)*(1.-v)*point(p0,1) +
+	    0.25*(1.+u)*(1.-v)*point(p1,1) +
+	    0.25*(1.+u)*(1.+v)*point(p2,1) +
+	    0.25*(1.-u)*(1.+v)*point(p3,1) ;
+	  const double newW = 
+	    0.25*(1.-u)*(1.-v)*point(p0,2) +
+	    0.25*(1.+u)*(1.-v)*point(p1,2) +
+	    0.25*(1.+u)*(1.+v)*point(p2,2) +
+	    0.25*(1.-u)*(1.+v)*point(p3,2) ;
+	  point(index, 0) = newU;
+	  point(index, 1) = newV;
+	  point(index, 2) = newW;
+	}
+      } 
+      if (!serendip) {     
+        fullMatrix<double> inner = gmshGeneratePointsHex(order - 2, false);
+        inner.scale(1. - 2./order);
+        point.copy(inner, 0, nbPoints - index, 0, 3, index, 0);
+      }
+    }
+  }
+  else if (order == 0){
+    point(0, 0) = 0;
+    point(0, 1) = 0;
+    point(0, 2) = 0;
+  }  
+  return point;
+}
+
 static fullMatrix<double> generateLagrangeMonomialCoefficients
   (const fullMatrix<double>& monomial, const fullMatrix<double>& point)
 {
@@ -1273,8 +1389,17 @@ static void generateClosureOrder0(polynomialBasis::clCont &closure, int nb)
   }
 }
 
-std::map<int, polynomialBasis> polynomialBases::fs;
+void _oulala_  (const char* a, fullMatrix<double> & m){
+  FILE *f = fopen (a,"w");
+  fprintf(f,"View \"\"{\n");
+  for (int i=0;i<m.size1();i++){
+    fprintf(f,"SP(%g,%g,%g){%d};\n",m(i,0),m(i,1),m(i,2),i);
+  }
+  fprintf(f,"};\n");
+  fclose (f);
+}
 
+std::map<int, polynomialBasis> polynomialBases::fs;
 const polynomialBasis *polynomialBases::find(int tag)
 {
   std::map<int, polynomialBasis>::const_iterator it = fs.find(tag);
@@ -1860,6 +1985,142 @@ const polynomialBasis *polynomialBases::find(int tag)
     generateFaceClosurePrism(F.closures, 2);
     generateFaceClosurePrismFull(F.fullClosures, F.closureRef, 2);
     break;
+  case MSH_HEX_20 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(2,true);
+    F.points =    gmshGeneratePointsHex(2, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_27 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(2,false);
+    F.points =    gmshGeneratePointsHex(2, false);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_56 :
+    //    printf("in complete hex at order 3\n");
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(3,true);
+    F.points =    gmshGeneratePointsHex(3, true);
+    F.parentType = TYPE_HEX;
+    //    _oulala_("hex56.pos",F.points);
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_64 :
+    //    printf("complete hex at order 3\n");
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(3,false);
+    //    printf("pas complete hex at order 3 done\n");
+    F.points =    gmshGeneratePointsHex(3, false);
+    //    printf("complete hex at order 3 done\n");
+    //    F.points.print("P3");
+    F.parentType = TYPE_HEX;
+    //    _oulala_("hex64.pos",F.points);
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_98 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(4,true);
+    F.points =    gmshGeneratePointsHex(4, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_125 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(4,false);
+    F.points =    gmshGeneratePointsHex(4, false);
+    F.parentType = TYPE_HEX;
+    //    _oulala_("hex125.pos",F.points);
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_152 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(5,true);
+    F.points =    gmshGeneratePointsHex(5, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_216 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(5,false);
+    F.points =    gmshGeneratePointsHex(5, false);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_222 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(6,true);
+    F.points =    gmshGeneratePointsHex(6, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_343 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(6,false);
+    F.points =    gmshGeneratePointsHex(6, false);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_296 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(7,true);
+    F.points =    gmshGeneratePointsHex(7, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_512 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(7,false);
+    F.points =    gmshGeneratePointsHex(7, false);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_386 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(8,true);
+    F.points =    gmshGeneratePointsHex(8, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_729 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(8,false);
+    F.points =    gmshGeneratePointsHex(8, false);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_488 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(9,true);
+    F.points =    gmshGeneratePointsHex(9, true);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
+  case MSH_HEX_1000 :
+    F.numFaces = 6;
+    F.monomials = generatePascalHex(9,false);
+    F.points =    gmshGeneratePointsHex(9, false);
+    F.parentType = TYPE_HEX;
+    //    generateFaceClosureHex(F.closures, 2);
+    //    generateFaceClosureHexFull(F.fullClosures, F.closureRef, 2);
+    break;
   default :
     Msg::Error("Unknown function space %d: reverting to TET_4", tag);
     F.numFaces = 4;
@@ -1900,7 +2161,7 @@ const fullMatrix<double> &polynomialBases::findInjector(int tag1, int tag2)
 
   fullMatrix<double> inj(fs1.points.size1(), fs2.points.size1());
 
-  double sf[256];
+  double sf[1256];
 
   for (int i = 0; i < fs1.points.size1(); i++) {
     fs2.f(fs1.points(i, 0), fs1.points(i, 1), fs1.points(i, 2), sf);
diff --git a/Numeric/polynomialBasis.h b/Numeric/polynomialBasis.h
index c1481612e0693ac42ecc342cf671016d8fd186ed..0170b2c63306bbf605aa6905d73bf9d5eb21af56 100644
--- a/Numeric/polynomialBasis.h
+++ b/Numeric/polynomialBasis.h
@@ -115,7 +115,7 @@ class polynomialBasis
   }
   inline void f(double u, double v, double w, double *sf) const
   {
-    double p[256];
+    double p[1256];
     evaluateMonomials(u, v, w, p);
     for (int i = 0; i < coefficients.size1(); i++) {
       sf[i] = 0;
@@ -128,7 +128,7 @@ class polynomialBasis
   // implemented) and is easier to bind
   inline void f(fullMatrix<double> &coord, fullMatrix<double> &sf)
   {
-    double p[256];
+    double p[1256];
     sf.resize (coord.size1(), coefficients.size1());
     for (int iPoint=0; iPoint< coord.size1(); iPoint++) {
       evaluateMonomials(coord(iPoint,0), coord(iPoint,1), coord(iPoint,2), p);
diff --git a/Solver/elasticityTerm.cpp b/Solver/elasticityTerm.cpp
index 7c67875577213c20956dcb7728455f77b5a3da36..f03ec416ac293709a08b6b263f74b75889e27b73 100644
--- a/Solver/elasticityTerm.cpp
+++ b/Solver/elasticityTerm.cpp
@@ -29,10 +29,10 @@ void elasticityTerm::elementMatrix(SElement *se, fullMatrix<double> &m) const
   double C12 = FACT * _nu / (1 - 2 * _nu);
   double C44 = (C11 - C12) / 2;
   // FIXME : PLANE STRESS !!! 
-  FACT = _E / (1-_nu*_nu); 
-  C11  = FACT; 
-  C12  = _nu * FACT; 
-  C44 = (1.-_nu)*.5*FACT;
+  //FACT = _E / (1-_nu*_nu); 
+  //C11  = FACT; 
+  //C12  = _nu * FACT; 
+  //C44 = (1.-_nu)*.5*FACT;
   
   const double C[6][6] =
     { {C11, C12, C12,    0,   0,   0},
@@ -130,3 +130,168 @@ void elasticityTerm::elementVector(SElement *se, fullVector<double> &m) const
     }
   }
 }
+
+/*
+
+B_d is the deviatoric part of the FE strains
+
+K_{uu} = \int_\Omega B^T_d H B_d dv
+
+*/
+
+void elasticityMixedTerm::elementMatrix(SElement *se, fullMatrix<double> &m) const
+{
+  setPolynomialBasis(se);
+  MElement *e = se->getMeshElement();
+  int integrationOrder = 3 * (e->getPolynomialOrder()) + 2;
+  int npts;
+  IntPt *GP;
+  double jac[3][3];
+  double invjac[3][3];
+  double Grads[100][3];
+  double SF[100];
+  e->getIntegrationPoints(integrationOrder, &npts, &GP);
+
+  m.setAll(0.);
+  fullMatrix<double> KUU(3 * _sizeN,3 * _sizeN);
+  fullMatrix<double> KUP(3 * _sizeN,_sizeM);
+  fullMatrix<double> KUG(3 * _sizeN,_sizeM);
+  fullMatrix<double> KPG(_sizeM,_sizeM);
+  fullMatrix<double> KGG(_sizeM,_sizeM);
+
+  double FACT = _E / ((1 + _nu)*(1.-2*_nu));
+  double C11 = FACT * (1 - _nu) ;
+  double C12 = FACT * _nu ;
+  double C44 = FACT* (1 - 2.*_nu)*.5;
+  double _K = 3*_E / (1 - 2 * _nu);
+  // FIXME : PLANE STRESS !!! 
+    //  FACT = _E / (1-_nu*_nu); 
+    //  C11  = FACT; 
+    //  C12  = _nu * FACT; 
+    //  C44 = (1.-_nu)*.5*FACT;
+  
+  const double C[6][6] =
+    { {C11, C12, C12,    0,   0,   0},
+      {C12, C11, C12,    0,   0,   0},
+      {C12, C12, C11,    0,   0,   0},
+      {  0,   0,   0,  C44,   0,   0},
+      {  0,   0,   0,    0, C44,   0},
+      {  0,   0,   0,    0,   0, C44} };
+
+  fullMatrix<double> H (6, 6);
+  fullMatrix<double> B (6, 3 * _sizeN);
+  fullMatrix<double> BDEV (6, 3 * _sizeN);
+  fullMatrix<double> BDIL (1, 3 * _sizeN);
+  fullMatrix<double> BDILT (3 * _sizeN,1);
+  fullMatrix<double> BTH(3 * _sizeN, 6);
+  fullMatrix<double> BT(3 * _sizeN, 6);
+  fullMatrix<double> trBTH(3 * _sizeN, 1);
+  fullMatrix<double> MT(_sizeM, 1);
+  fullMatrix<double> M(1,_sizeM);
+  for (int i = 0; i < 6; i++)
+    for (int j = 0; j < 6; j++)
+      H(i, j) = C[i][j];
+
+  double _dimension = 3.0;
+
+  for (int i = 0; i < npts; i++){
+    const double u = GP[i].pt[0];
+    const double v = GP[i].pt[1];
+    const double w = GP[i].pt[2];
+    const double weight = GP[i].weight;
+    const double detJ = e->getJacobian(u, v, w, jac);
+    inv3x3(jac, invjac);
+    se->gradNodalShapeFunctions(u, v, w, invjac,Grads);
+    e->getShapeFunctions (u,v,w,SF,_polyOrderM);
+
+    B.setAll(0.);
+    BT.setAll(0.);
+    for (int j = 0; j < _sizeN; j++){
+
+      //      printf("%g %g %g\n",Grads[j][0],Grads[j][1],Grads[j][2]);
+
+      BDILT(j, 0) = BDIL(0, j) = Grads[j][0]/_dimension;
+
+      BT(j, 0) = B(0, j) = Grads[j][0]-Grads[j][0]/_dimension;
+      BT(j, 1) = B(1, j) =            -Grads[j][1]/_dimension;
+      BT(j, 2) = B(2, j) =            -Grads[j][2]/_dimension;
+
+      BT(j, 3) = B(3, j) = Grads[j][1];
+      BT(j, 4) = B(4, j) = Grads[j][2];
+      
+      BDILT(j + _sizeN, 0) = BDIL(0, j + _sizeN) = Grads[j][1]/_dimension;
+
+      BT(j + _sizeN, 0) = B(0, j + _sizeN) =            -Grads[j][0]/_dimension;
+      BT(j + _sizeN, 1) = B(1, j + _sizeN) = Grads[j][1]-Grads[j][1]/_dimension;
+      BT(j + _sizeN, 2) = B(2, j + _sizeN) =            -Grads[j][2]/_dimension;
+
+      BT(j + _sizeN, 3) = B(3, j + _sizeN) = Grads[j][0];
+      BT(j + _sizeN, 5) = B(5, j + _sizeN) = Grads[j][2];
+      
+      BDILT(j + 2 * _sizeN, 0) = BDIL(0, j + 2 * _sizeN) = Grads[j][2]/_dimension;
+
+      BT(j + 2 * _sizeN, 0) = B(0, j + 2 * _sizeN) =            -Grads[j][0]/_dimension;
+      BT(j + 2 * _sizeN, 1) = B(1, j + 2 * _sizeN) =            -Grads[j][1]/_dimension;
+      BT(j + 2 * _sizeN, 2) = B(2, j + 2 * _sizeN) = Grads[j][2]-Grads[j][2]/_dimension;
+
+      BT(j + 2 * _sizeN, 4) = B(4, j + 2 * _sizeN) = Grads[j][1];
+      BT(j + 2 * _sizeN, 5) = B(5, j + 2 * _sizeN) = Grads[j][0];
+    }
+
+    for (int j = 0; j < _sizeM; j++){
+      MT(j,0) = M(0,j) = SF[j];
+    }
+
+    //    printf("BT (%d %d) x H (%d,%d) = BTH(%d,%d)\n",BT.size1(),BT.size2(), H.size1(),H.size2(),BTH.size1(),BTH.size2());
+    
+    BTH.setAll(0.);
+    BTH.gemm(BT, H);
+
+    for (int j = 0; j < 3*_sizeN; j++){
+      trBTH(j,0) = BTH(j,0) + BTH(j,1) + BTH(j,2) ;
+    }
+
+    KUU.gemm(BTH, B, weight * detJ);
+    KUP.gemm(BDILT, M, weight * detJ);
+    KPG.gemm(MT, M, -weight * detJ);
+    KUG.gemm(trBTH, M, weight * detJ/_dimension);
+    KGG.gemm(MT, M, weight * detJ * (_K)/(_dimension*_dimension));    
+
+  }
+    /*       
+            3*_sizeN  _sizeM _sizeM
+
+            KUU     KUP     KUG
+      m  =  KUP^t    0      KPG
+            KUG^T    KPG^t  KGG
+      
+     */
+
+  for (int i=0;i<3*_sizeN;i++){
+    for (int j=0;j<3*_sizeN;j++)
+      m(i,j) = KUU(i,j); // assemble KUU 
+
+    for (int j=0;j<_sizeM;j++){
+      m(i,j+3*_sizeN) = KUP(i,j); // assemble KUP
+      m(j+3*_sizeN,i) = KUP(i,j); // assemble KUP^T
+    }
+
+    for (int j=0;j<_sizeM;j++){
+      m(i,j+3*_sizeN+_sizeM) = KUG(i,j); // assemble KUG
+      m(j+3*_sizeN+_sizeM,i) = KUG(i,j); // assemble KUG^t
+    }
+  }
+  for (int i=0;i<_sizeM;i++){
+    for (int j=0;j<_sizeM;j++){
+      m(i+3*_sizeN,j+3*_sizeN+_sizeM) = KPG(i,j); // assemble KPG
+      m(j+3*_sizeN+_sizeM,i+3*_sizeN) = KPG(i,j); // assemble KPG^t
+
+      m(i+3*_sizeN+_sizeM,j+3*_sizeN+_sizeM) = KGG(i,j); // assemble KGG
+
+    }
+  }
+  //    m.print("Mixed");
+  return;
+  
+}
+
diff --git a/Solver/elasticityTerm.h b/Solver/elasticityTerm.h
index c89b1593d749d85c91d2f9f10dfc84af84786968..e167fd4a61a65f0261b939741548f1651a1e4952 100644
--- a/Solver/elasticityTerm.h
+++ b/Solver/elasticityTerm.h
@@ -9,6 +9,7 @@
 #include "femTerm.h"
 #include "Gmsh.h"
 #include "GModel.h"
+#include "polynomialBasis.h"
 #include "SElement.h"
 #include "fullMatrix.h"
 
@@ -57,4 +58,74 @@ class elasticityTerm : public femTerm<double> {
   void elementVector(SElement *se, fullVector<double> &m) const;
 };
 
+/*
+  Formulation of elasticity with 3 fields
+   -) displacement U
+   -) lagrange multipliers p and g
+  
+   g = trace (epsilon) 
+   p = trace (epsilon) 
+
+
+*/
+
+class elasticityMixedTerm : public femTerm<double> {
+protected:
+  double _E, _nu;
+  mutable int _iField, _polyOrderN, _polyOrderM, _sizeN, _sizeM;
+  mutable polynomialBasis *_pN,*_pM;
+  void setPolynomialBasis (SElement *se) const{
+    _polyOrderN =  se->getMeshElement()->getPolynomialOrder();
+    _polyOrderM =  se->getMeshElement()->getPolynomialOrder();
+    _pN =  (polynomialBasis*)se->getMeshElement()->getFunctionSpace(_polyOrderN);
+    _pM =  (polynomialBasis*)se->getMeshElement()->getFunctionSpace(_polyOrderM);
+    _sizeN = _pN->coefficients.size1();
+    _sizeM = _pM->coefficients.size1();
+  }
+public:
+  void setField(int i){_iField = i;}
+  // element matrix size : 3 dofs per vertex
+  virtual int sizeOfR(SElement *se) const
+  {
+    setPolynomialBasis(se);
+    return 3 * _sizeN + 2 * _sizeM;
+  }
+  virtual int sizeOfC(SElement *se) const
+  {
+    return sizeOfR(se);
+  }
+  // order dofs in the local matrix :
+  // dx1, dx2 ... dxn, dy1, ..., dyn, dz1, ... dzn , 
+  // p1,p2,...,pm, g1,g2,...,gm
+  Dof getLocalDofR(SElement *se, int iRow) const
+  {
+    setPolynomialBasis(se);
+    MElement *e = se->getMeshElement();
+    int iComp;
+    int ithLocalVertex;
+    if (iRow < 3 * _sizeN){
+      iComp = iRow / _sizeN;
+      ithLocalVertex = iRow % _sizeN;
+    }
+    else {
+      iRow -= 3 * _sizeN;
+      iComp = 3 + iRow / _sizeM;
+      ithLocalVertex = iRow % _sizeM;      
+    }
+    return Dof(e->getShapeFunctionNode(ithLocalVertex)->getNum(),
+               Dof::createTypeWithTwoInts(iComp, _iField));
+  }
+  Dof getLocalDofC(SElement *se, int iCol) const
+  {
+    return getLocalDofR(se,iCol);
+  }
+ public:
+ elasticityMixedTerm(GModel *gm, double E, double nu, int field)
+   : femTerm<double>(gm), _E(E), _nu(nu), _iField(field) {}
+  void elementMatrix(SElement *se, fullMatrix<double> &m) const;
+  void elementVector(SElement *se, fullVector<double> &m) const {}
+  void setYoung (double E){_E = E;}
+};
+
+
 #endif
diff --git a/Solver/functionSpace.h b/Solver/functionSpace.h
index 644378f0270a6e555612e4c1efcd0c3dd2a170f6..ec0da235b6a2e8d73a8dde19cb4859ed06dc51d0 100644
--- a/Solver/functionSpace.h
+++ b/Solver/functionSpace.h
@@ -237,7 +237,7 @@ class ScalarLagrangeFunctionSpace : public FunctionSpace<double>
     if(ele->getParent()) ele = ele->getParent();
     int ndofs= ele->getNumShapeFunctions();
     vals.reserve(vals.size()+ndofs);
-    double valsuvw[256];
+    double valsuvw[1256];
     ele->getShapeFunctions(u, v, w, valsuvw);
     for(int i = 0; i < ndofs; ++i)
       vals.push_back(valsuvw[i]);
diff --git a/benchmarks/3d/Sphere.geo b/benchmarks/3d/Sphere.geo
index b48c3ef31aa6b4df8b2d2a607a3592326e1aaf51..3e445e48d0de1595b4ceaf6b65f12a87afb1e4ed 100644
--- a/benchmarks/3d/Sphere.geo
+++ b/benchmarks/3d/Sphere.geo
@@ -1,6 +1,6 @@
 // Gmsh project created on Fri Feb  1 12:17:44 2008
 
-Delete All;
+//Delete All;
 
 RSphere = 1.;
 lcSphere = .25;
diff --git a/benchmarks/extrude/u_shape_boundary_layer.geo b/benchmarks/extrude/u_shape_boundary_layer.geo
index 1c157cf1f155a6733d349570445bcd412032dc24..6b66c16d38f84d78ef171d42519badc7332c2ba1 100644
--- a/benchmarks/extrude/u_shape_boundary_layer.geo
+++ b/benchmarks/extrude/u_shape_boundary_layer.geo
@@ -11,8 +11,8 @@ BSpline(1) = {5, 4, 3, 2, 1};
 BSpline(2) = {1, 9, 8, 7, 5};
 Line(3) = {5, 6};
 
-Extrude { Line{1,-3}; Layers{5,0.2}; Using Index[0]; }
-Extrude { Line{2,3}; Layers{5,0.2}; Using Index[1]; }
+Extrude { Line{1,-3}; Layers{5,0.04}; Using Index[0]; }
+Extrude { Line{2,3}; Layers{5,0.04}; Using Index[1]; }
 
 // fix leading edge by hand
 Coherence Point {25, 16};
@@ -27,4 +27,4 @@ Line(22) = {34, 31};
 Line(23) = {31, 32};
 Line Loop(24) = {22, 23, 20, 21};
 Line Loop(25) = {4, 12, 16, -18, 9, 8};
-Plane Surface(26) = {24, 25};
+//Plane Surface(26) = {24, 25};