diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp
index a58d3fbc472c971a4d627b4a278fb415def2363d..8975c7006dfcfda5547138548ba55d7db588cebb 100644
--- a/Numeric/JacobianBasis.cpp
+++ b/Numeric/JacobianBasis.cpp
@@ -18,53 +18,37 @@ JacobianBasis::JacobianBasis(int tag)
 {
   const int parentType = ElementType::ParentTypeFromTag(tag);
   const int order = ElementType::OrderFromTag(tag);
+  const int jacobianOrder =  JacobianBasis::jacobianOrder(parentType, order);
+  const int primJacobianOrder =  JacobianBasis::jacobianOrder(parentType, 1);
 
-  int jacobianOrder, primJacobianOrder;
   switch (parentType) {
     case TYPE_PNT :
-      primJacobianOrder = 0;
-      jacobianOrder = 0;
       lagPoints = gmshGeneratePointsLine(0);
       break;
     case TYPE_LIN :
-      primJacobianOrder = 0;
-      jacobianOrder = order - 1;
       lagPoints = gmshGeneratePointsLine(jacobianOrder);
       break;
     case TYPE_TRI :
-      primJacobianOrder = 0;
-      jacobianOrder = 2*order - 2;
       lagPoints = gmshGeneratePointsTriangle(jacobianOrder);
       break;
     case TYPE_QUA :
-      primJacobianOrder = 1;
-      jacobianOrder = 2*order - 1;
       lagPoints = gmshGeneratePointsQuadrangle(jacobianOrder);
       break;
     case TYPE_TET :
-      primJacobianOrder = 0;
-      jacobianOrder = 3*order - 3;
       lagPoints = gmshGeneratePointsTetrahedron(jacobianOrder);
       break;
     case TYPE_PRI :
-      primJacobianOrder = 2;
-      jacobianOrder = 3*order - 1;
       lagPoints = gmshGeneratePointsPrism(jacobianOrder);
       break;
     case TYPE_HEX :
-      primJacobianOrder = 2;
-      jacobianOrder = 3*order - 1;
       lagPoints = gmshGeneratePointsHexahedron(jacobianOrder);
       break;
     case TYPE_PYR :
-      primJacobianOrder = 0;
-      jacobianOrder = 3*order - 3;
       lagPoints = generateJacPointsPyramid(jacobianOrder);
       break;
     default :
       Msg::Error("Unknown Jacobian function space for element type %d", tag);
-      jacobianOrder = 0;
-      break;
+      return;
   }
   numJacNodes = lagPoints.size1();
 
@@ -680,3 +664,36 @@ fullMatrix<double> JacobianBasis::generateJacMonomialsPyramid(int order)
   }
   return monomials;
 }
+
+fullMatrix<double> JacobianBasis::generateJacPointsPyramid(int order)
+{
+  fullMatrix<double> points = generateJacMonomialsPyramid(order);
+
+  const double p = order + 2;
+  for (int i = 0; i < points.size1(); ++i) {
+    points(i, 2) = points(i, 2) * 1. / p;
+    const double duv = -1. + points(i, 2);
+    points(i, 0) = duv + points(i, 0) * 2. / p;
+    points(i, 1) = duv + points(i, 1) * 2. / p;
+  }
+
+  return points;
+}
+
+int JacobianBasis::jacobianOrder(int parentType, int order) {
+  switch (parentType) {
+    case TYPE_PNT : return 0;
+    case TYPE_LIN : return order - 1;
+    case TYPE_TRI : return 2*order - 2;
+    case TYPE_QUA : return 2*order - 1;
+    case TYPE_TET : return 3*order - 3;
+    case TYPE_PRI : return 3*order - 1;
+    case TYPE_HEX : return 3*order - 1;
+    case TYPE_PYR : return 3*order - 3;
+    // note : for the pyramid, the jacobian space is
+    // different from the space of the mapping
+    default :
+      Msg::Error("Unknown element type %d, return order 0", parentType);
+      return 0;
+  }
+}
diff --git a/Numeric/JacobianBasis.h b/Numeric/JacobianBasis.h
index df8ebac767eb7df3b1e782d8d7fa8cd6f8664c30..5aa77258dca7432f05553b2177dd22e9af5745ed 100644
--- a/Numeric/JacobianBasis.h
+++ b/Numeric/JacobianBasis.h
@@ -67,15 +67,9 @@ class JacobianBasis {
   }
 
   //
+  static int jacobianOrder(int parentType, int order);
   static fullMatrix<double> generateJacMonomialsPyramid(int order);
-  static inline fullMatrix<double> generateJacPointsPyramid(int order) {
-    fullMatrix<double> points = generateJacMonomialsPyramid(order);
-
-    if (order == 0) return points;
-
-    points.scale(1. / (order+2.));
-    return points;
-  }
+  static fullMatrix<double> generateJacPointsPyramid(int order);
 };
 
 #endif
diff --git a/Numeric/bezierBasis.cpp b/Numeric/bezierBasis.cpp
index 7db0b0904cc783aa0cc29cc91fb546d17c623730..cf2d14c8e413d63e9b30f4c83ba82de74c950fc6 100644
--- a/Numeric/bezierBasis.cpp
+++ b/Numeric/bezierBasis.cpp
@@ -13,7 +13,6 @@
 #include "BasisFactory.h"
 #include "Numeric.h"
 
-
 // Sub Control Points
 static std::vector< fullMatrix<double> > generateSubPointsLine(int order)
 {
@@ -223,6 +222,81 @@ static std::vector< fullMatrix<double> > generateSubPointsHex(int order)
   return subPoints;
 }
 
+static std::vector< fullMatrix<double> > generateSubPointsPyr(int order)
+{
+  if (order == 0) {
+    std::vector< fullMatrix<double> > subPoints(4);
+    fullMatrix<double> prox;
+
+    subPoints[0] = JacobianBasis::generateJacMonomialsPyramid(order);
+    subPoints[0].scale(.5/(order+2));
+
+    subPoints[1].copy(subPoints[0]);
+    prox.setAsProxy(subPoints[1], 0, 1);
+    prox.add(.5);
+
+    subPoints[2].copy(subPoints[0]);
+    prox.setAsProxy(subPoints[2], 1, 1);
+    prox.add(.5);
+
+    subPoints[3].copy(subPoints[1]);
+    prox.setAsProxy(subPoints[3], 1, 1);
+    prox.add(.5);
+
+    return subPoints;
+  }
+
+  std::vector< fullMatrix<double> > subPoints(8);
+  fullMatrix<double> ref, prox;
+
+  subPoints[0] = JacobianBasis::generateJacMonomialsPyramid(order);
+  int nPts = subPoints[0].size1();
+  for (int i = 0; i < nPts; ++i) {
+    const double factor = .5 / (order + 2 - subPoints[0](i, 2));
+    subPoints[0](i, 0) = subPoints[0](i, 0) * factor;
+    subPoints[0](i, 1) = subPoints[0](i, 1) * factor;
+    subPoints[0](i, 2) = subPoints[0](i, 2) * .5 / (order + 2);
+  }
+
+  subPoints[1].copy(subPoints[0]);
+  prox.setAsProxy(subPoints[1], 0, 1);
+  prox.add(.5);
+
+  subPoints[2].copy(subPoints[0]);
+  prox.setAsProxy(subPoints[2], 1, 1);
+  prox.add(.5);
+
+  subPoints[3].copy(subPoints[1]);
+  prox.setAsProxy(subPoints[3], 1, 1);
+  prox.add(.5);
+
+  subPoints[4].copy(subPoints[0]);
+  prox.setAsProxy(subPoints[4], 2, 1);
+  prox.add(.5);
+
+  subPoints[5].copy(subPoints[1]);
+  prox.setAsProxy(subPoints[5], 2, 1);
+  prox.add(.5);
+
+  subPoints[6].copy(subPoints[2]);
+  prox.setAsProxy(subPoints[6], 2, 1);
+  prox.add(.5);
+
+  subPoints[7].copy(subPoints[3]);
+  prox.setAsProxy(subPoints[7], 2, 1);
+  prox.add(.5);
+
+  for (int i = 0; i < 8; ++i) {
+    for (int j = 0; j < nPts; ++j) {
+      const double factor = (1. - subPoints[i](j, 2));
+      subPoints[i](j, 0) = subPoints[i](j, 0) * factor;
+      subPoints[i](j, 1) = subPoints[i](j, 1) * factor;
+    }
+  }
+
+  return subPoints;
+}
+
 // Matrices generation
 static int nChoosek(int n, int k)
 {
@@ -246,9 +320,8 @@ static fullMatrix<double> generateBez2LagMatrix
   (const fullMatrix<double> &exponent, const fullMatrix<double> &point,
    int order, int dimSimplex)
 {
-
   if(exponent.size1() != point.size1() || exponent.size2() != point.size2()){
-    Msg::Fatal("Wrong sizes for Bezier coefficients generation %d %d -- %d %d",
+    Msg::Fatal("Wrong sizes for bez2lag matrix generation %d %d -- %d %d",
       exponent.size1(),point.size1(),
       exponent.size2(),point.size2());
     return fullMatrix<double>(1, 1);
@@ -285,6 +358,42 @@ static fullMatrix<double> generateBez2LagMatrix
   return bez2Lag;
 }
 
+static fullMatrix<double> generateBez2LagMatrixPyramid
+  (const fullMatrix<double> &exponent, const fullMatrix<double> &point,
+   int order)
+{
+  if(exponent.size1() != point.size1() || exponent.size2() != point.size2() ||
+      exponent.size2() != 3){
+    Msg::Fatal("Wrong sizes for bez2lag matrix generation %d %d -- %d %d",
+      exponent.size1(),point.size1(),
+      exponent.size2(),point.size2());
+    return fullMatrix<double>(1, 1);
+  }
+
+  int ndofs = exponent.size1();
+
+  fullMatrix<double> bez2Lag(ndofs, ndofs);
+  for (int i = 0; i < ndofs; i++) {
+    for (int j = 0; j < ndofs; j++) {
+      bez2Lag(i, j) =
+          nChoosek(order, exponent(j, 2))
+          * pow(point(i, 2), exponent(j, 2)) //FIXME use pow_int
+          * pow(1. - point(i, 2), order - exponent(j, 2));
+
+      double p = order + 2 - exponent(j, 2);
+      double denom = 1. - point(i, 2);
+      bez2Lag(i, j) *=
+            nChoosek(p, exponent(j, 0))
+          * nChoosek(p, exponent(j, 1))
+          * pow(point(i, 0) / denom, exponent(j, 0))
+          * pow(point(i, 1) / denom, exponent(j, 1))
+          * pow(1. - point(i, 0) / denom, p - exponent(j, 0))
+          * pow(1. - point(i, 1) / denom, p - exponent(j, 1));
+    }
+  }
+  return bez2Lag;
+}
+
 static fullMatrix<double> generateSubDivisor
   (const fullMatrix<double> &exponents, const std::vector< fullMatrix<double> > &subPoints,
    const fullMatrix<double> &lag2Bez, int order, int dimSimplex)
@@ -311,102 +420,130 @@ static fullMatrix<double> generateSubDivisor
   return subDivisor;
 }
 
+static fullMatrix<double> generateSubDivisorPyramid
+  (const fullMatrix<double> &exponents, const std::vector< fullMatrix<double> > &subPoints,
+   const fullMatrix<double> &lag2Bez, int order)
+{
+  if (exponents.size1() != lag2Bez.size1() || exponents.size1() != lag2Bez.size2()){
+    Msg::Fatal("Wrong sizes for Bezier Divisor %d %d -- %d %d",
+      exponents.size1(), lag2Bez.size1(),
+      exponents.size1(), lag2Bez.size2());
+    return fullMatrix<double>(1, 1);
+  }
+
+  int nbPts = lag2Bez.size1();
+  int nbSubPts = nbPts * subPoints.size();
+
+  fullMatrix<double> intermediate2(nbPts, nbPts);
+  fullMatrix<double> subDivisor(nbSubPts, nbPts);
+
+  for (unsigned int i = 0; i < subPoints.size(); i++) {
+    fullMatrix<double> intermediate1 =
+      generateBez2LagMatrixPyramid(exponents, subPoints[i], order);
+    lag2Bez.mult(intermediate1, intermediate2);
+    subDivisor.copy(intermediate2, 0, nbPts, 0, nbPts, i*nbPts, 0);
+  }
+  return subDivisor;
+}
+
 void bezierBasis::_construct(int parentType, int p)
 {
   order = p;
+  fullMatrix<double> exponents;
+  std::vector< fullMatrix<double> > subPoints;
 
-  /*if (parentType == TYPE_PYR) {
+  if (parentType == TYPE_PYR) {
     dim = 3;
-    numLagPts = 5;
-    bezierPoints = gmshGeneratePointsPyramid(order,false);
-    lagPoints = bezierPoints;
-    matrixLag2Bez.resize(bezierPoints.size1(), bezierPoints.size1(), false);
-    matrixBez2Lag.resize(bezierPoints.size1(), bezierPoints.size1(), false);
-    for (int i=0; i<matrixBez2Lag.size1(); ++i) {
-      matrixLag2Bez(i,i) = 1.;
-      matrixBez2Lag(i,i) = 1.;
-    }
-    // TODO: Implement subdidivsor
-  }
-  else {*/
-    int dimSimplex;
-    fullMatrix<double> exponents;
-    std::vector< fullMatrix<double> > subPoints;
-
-    switch (parentType) {
-      case TYPE_PNT :
-        dim = 0;
-        numLagCoeff = 1;
-        dimSimplex = 0;
-        exponents = gmshGenerateMonomialsLine(0);
-        break;
-      case TYPE_LIN : {
-        dim = 1;
-        numLagCoeff = 2;
-        dimSimplex = 0;
-        exponents = gmshGenerateMonomialsLine(order);
-        subPoints = generateSubPointsLine(order);
-        break;
-      }
-      case TYPE_TRI : {
-        dim = 2;
-        numLagCoeff = 3;
-        dimSimplex = 2;
-        exponents = gmshGenerateMonomialsTriangle(order);
-        subPoints = generateSubPointsTriangle(order);
-        break;
-      }
-      case TYPE_QUA : {
-        dim = 2;
-        numLagCoeff = 4;
-        dimSimplex = 0;
-        exponents = gmshGenerateMonomialsQuadrangle(order);
-        subPoints = generateSubPointsQuad(order);
-        break;
-      }
-      case TYPE_TET : {
-        dim = 3;
-        numLagCoeff = 4;
-        dimSimplex = 3;
-        exponents = gmshGenerateMonomialsTetrahedron(order);
-        subPoints = generateSubPointsTetrahedron(order);
-        break;
-      }
-      case TYPE_PRI : {
-        dim = 3;
-        numLagCoeff = 6;
-        dimSimplex = 2;
-        exponents = gmshGenerateMonomialsPrism(order);
-        subPoints = generateSubPointsPrism(order);
-        break;
-      }
-      case TYPE_HEX : {
-        dim = 3;
-        numLagCoeff = 8;
-        dimSimplex = 0;
-        exponents = gmshGenerateMonomialsHexahedron(order);
-        subPoints = generateSubPointsHex(order);
-        break;
-      }
-      default : {
-        Msg::Error("Unknown function space of parentType %d : "
-            "reverting to TET_1", parentType);
-        dim = 3;
-        order = 0;
-        numLagCoeff = 4;
-        dimSimplex = 3;
-        exponents = gmshGenerateMonomialsTetrahedron(order);
-        subPoints = generateSubPointsTetrahedron(order);
-        break;
-      }
-    }
+    numLagCoeff = 8;
+    exponents = JacobianBasis::generateJacMonomialsPyramid(order);
+    subPoints = generateSubPointsPyr(order);
+
+    numDivisions = static_cast<int>(subPoints.size());
 
     fullMatrix<double> bezierPoints = exponents;
-    bezierPoints.scale(1./order);
+    bezierPoints.scale(1. / (order + 2));
 
-    numDivisions = static_cast<int>(subPoints.size());
-    matrixBez2Lag = generateBez2LagMatrix(exponents, bezierPoints, order, dimSimplex);
+    matrixBez2Lag = generateBez2LagMatrixPyramid(exponents, bezierPoints, order);
     matrixBez2Lag.invert(matrixLag2Bez);
-    subDivisor = generateSubDivisor(exponents, subPoints, matrixLag2Bez, order, dimSimplex);
-  //}
+    subDivisor = generateSubDivisorPyramid(exponents, subPoints, matrixLag2Bez, order);
+    return;
+  }
+
+  int dimSimplex;
+  switch (parentType) {
+    case TYPE_PNT :
+      dim = 0;
+      numLagCoeff = 1;
+      dimSimplex = 0;
+      exponents = gmshGenerateMonomialsLine(0);
+      subPoints.push_back(gmshGeneratePointsLine(0));
+      break;
+    case TYPE_LIN : {
+      dim = 1;
+      numLagCoeff = 2;
+      dimSimplex = 0;
+      exponents = gmshGenerateMonomialsLine(order);
+      subPoints = generateSubPointsLine(order);
+      break;
+    }
+    case TYPE_TRI : {
+      dim = 2;
+      numLagCoeff = 3;
+      dimSimplex = 2;
+      exponents = gmshGenerateMonomialsTriangle(order);
+      subPoints = generateSubPointsTriangle(order);
+      break;
+    }
+    case TYPE_QUA : {
+      dim = 2;
+      numLagCoeff = 4;
+      dimSimplex = 0;
+      exponents = gmshGenerateMonomialsQuadrangle(order);
+      subPoints = generateSubPointsQuad(order);
+      break;
+    }
+    case TYPE_TET : {
+      dim = 3;
+      numLagCoeff = 4;
+      dimSimplex = 3;
+      exponents = gmshGenerateMonomialsTetrahedron(order);
+      subPoints = generateSubPointsTetrahedron(order);
+      break;
+    }
+    case TYPE_PRI : {
+      dim = 3;
+      numLagCoeff = 6;
+      dimSimplex = 2;
+      exponents = gmshGenerateMonomialsPrism(order);
+      subPoints = generateSubPointsPrism(order);
+      break;
+    }
+    case TYPE_HEX : {
+      dim = 3;
+      numLagCoeff = 8;
+      dimSimplex = 0;
+      exponents = gmshGenerateMonomialsHexahedron(order);
+      subPoints = generateSubPointsHex(order);
+      break;
+    }
+    default : {
+      Msg::Error("Unknown function space of parentType %d : "
+          "reverting to TET_1", parentType);
+      dim = 3;
+      order = 0;
+      numLagCoeff = 4;
+      dimSimplex = 3;
+      exponents = gmshGenerateMonomialsTetrahedron(order);
+      subPoints = generateSubPointsTetrahedron(order);
+      break;
+    }
+  }
+  numDivisions = static_cast<int>(subPoints.size());
+
+  fullMatrix<double> bezierPoints = exponents;
+  bezierPoints.scale(1./order);
+
+  matrixBez2Lag = generateBez2LagMatrix(exponents, bezierPoints, order, dimSimplex);
+  matrixBez2Lag.invert(matrixLag2Bez);
+  subDivisor = generateSubDivisor(exponents, subPoints, matrixLag2Bez, order, dimSimplex);
 }