diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp
index e9015df67363116166917c03517c946b4f1e802c..d2221f8ed6b3732a9e6bd715c1150577568c02d4 100644
--- a/Numeric/polynomialBasis.cpp
+++ b/Numeric/polynomialBasis.cpp
@@ -1011,36 +1011,77 @@ static void generate2dEdgeClosureFull(polynomialBasis::clCont &closure, std::vec
   }
 }
 
-static void generateFaceClosureTetFull(polynomialBasis::clCont &closure, std::vector<int> &closureRef, int order, bool serendip)
+static void addEdgeNodes(polynomialBasis::clCont &closureFull, const int *edges, int order) 
+{
+  if (order < 2) 
+    return;
+  int numNodes = 0;
+  for (int i = 0; edges[i] >= 0; ++i) {
+    numNodes = std::max(numNodes, edges[i] + 1);
+  }
+  std::vector<std::vector<int> > nodes2edges(numNodes, std::vector<int>(numNodes, -1));
+  for (int i = 0; edges[i] >= 0; i += 2) {
+    nodes2edges[edges[i]][edges[i + 1]] = i;
+    nodes2edges[edges[i + 1]][edges[i]] = i + 1;
+  }
+  for (int iClosure = 0; iClosure < closureFull.size(); iClosure++) {
+    std::vector<int> &cl = closureFull[iClosure];
+    for (int iEdge = 0; edges[iEdge] >= 0; iEdge += 2) {
+      int n0 = cl[edges[iEdge]];
+      int n1 = cl[edges[iEdge + 1]];
+      int oEdge = nodes2edges[n0][n1];
+      if (oEdge == -1)
+        Msg::Error("invalid p1 closure or invalid edges list");
+      for (int i = 0 ; i < order - 1; i++)
+        cl.push_back(numNodes + oEdge/2 * (order - 1) + ((oEdge % 2) ?  order - 2 - i : i));
+    }
+  }
+}
+
+static void generateFaceClosureTet(polynomialBasis::clCont &closure, int order)
 {
   closure.clear();
+  for (int iRotate = 0; iRotate < 3; iRotate++){
+    for (int iSign = 1; iSign >= -1; iSign -= 2){
+      for (int iFace = 0; iFace < 4; iFace++){
+        polynomialBasis::closure closure_face;
+        getFaceClosureTet(iFace, iSign, iRotate, closure_face, order);
+        closure.push_back(closure_face);
+      }
+    }
+  }
+}
+
+static void generateFaceClosureTetFull(polynomialBasis::clCont &closureFull, std::vector<int> &closureRef, int order, bool serendip)
+{
+  closureFull.clear();
   //input :
   static const short int faces[4][3] = {{0,1,2}, {0,3,1}, {0,2,3}, {3,2,1}};
-  static const short int edges[6][2] = {{0,1}, {1,2}, {2,0}, {3,0}, {3,2}, {3,1}};
+  static const int edges[] = {0, 1,  1, 2,  2, 0,  3, 0,  3, 2,  3, 1,  -1};
   static const int faceOrientation[6] = {0,1,2,5,3,4};
-  closure.resize(24);
+  closureFull.resize(24);
   closureRef.resize(24);
   for (int i = 0; i < 24; i ++)
     closureRef[i] = 0;
   if (order == 0) {
     for (int i = 0; i < 24; i ++) {
-      closure[i].push_back(0);
+      closureFull[i].push_back(0);
     }
     return;
   }
   //Mapping for the p1 nodes
-  for (int iRotate = 0; iRotate < 3; iRotate ++) {
-    for (int iFace = 0; iFace < 4; iFace ++) {
-      for (int iNode = 0; iNode < 3; iNode ++) {
-        closure[iFace + iRotate * 8 + 0].push_back(faces[iFace][(6 + iNode - iRotate) % 3]);
-        closure[iFace + iRotate * 8 + 4].push_back(faces[iFace][(6 - iNode - iRotate) % 3]);
-      }
-    }
-  }
-  short int nodes2Edges [4][4];
-  for (int i = 0; i < 6; i++) {
-    nodes2Edges[edges[i][0]][edges[i][1]] = i * 2;
-    nodes2Edges[edges[i][1]][edges[i][0]] = i * 2 + 1;
+  polynomialBasis::clCont closure;
+  generateFaceClosureTet(closure, 1);
+  for (int i = 0; i < closureFull.size(); i++) {
+    std::vector<int> &clFull = closureFull[i];
+    std::vector<int> &cl = closure[i];
+    clFull.resize(4, -1);
+    closureRef[i] = 0;
+    for (int j = 0; j < cl.size(); j ++)
+      clFull[closure[0][j]] = cl[j];
+    for (int j = 0; j < 4; j ++)
+      if (clFull[j] == -1)
+        clFull[j] = (6 - clFull[(j + 1) % 4] - clFull[(j + 2) % 4] - clFull[(j + 3) % 4]);
   }
   int nodes2Faces[4][4][4];
   for (int i = 0; i < 4; i++) {
@@ -1056,19 +1097,10 @@ static void generateFaceClosureTetFull(polynomialBasis::clCont &closure, std::ve
   std::vector<int> closureTrianglesRef;
   if (order >= 3)
     generate2dEdgeClosureFull(closureTriangles, closureTrianglesRef, order - 3, 3, false); 
-  for (int iClosure = 0; iClosure < closure.size(); iClosure++) {
-    std::vector<int> &cl = closure[iClosure];
-    //last node
-    cl.push_back(6 - cl[0] - cl[1] - cl[2]);
-    //edges
-    for (int iEdge = 0; iEdge < 6; iEdge ++) {
-      int n0 = cl[edges[iEdge][0]];
-      int n1 = cl[edges[iEdge][1]];
-      short int &oEdge = nodes2Edges[n0][n1];
-      for (int i = 0 ; i < order - 1; i++)
-        cl.push_back(4 + oEdge/2 * (order - 1) + ((oEdge % 2) ?  order - 2 - i : i));
-    }
+  addEdgeNodes(closureFull, edges, order);
+  for (int iClosure = 0; iClosure < closureFull.size(); iClosure++) {
     //faces
+    std::vector<int> &cl = closureFull[iClosure];
     if (order >= 3) {
       for (int iFace = 0; iFace < 4; iFace ++) {
         int n0 = cl[faces[iFace][0]];
@@ -1088,24 +1120,10 @@ static void generateFaceClosureTetFull(polynomialBasis::clCont &closure, std::ve
     polynomialBasis::clCont insideClosure;
     std::vector<int> fakeClosureRef;
     generateFaceClosureTetFull(insideClosure, fakeClosureRef, order - 4, false);
-    for (int i = 0; i < closure.size(); i ++) {
-      int shift = closure[i].size();
+    for (int i = 0; i < closureFull.size(); i ++) {
+      int shift = closureFull[i].size();
       for (int j = 0; j < insideClosure[i].size(); j++)
-        closure[i].push_back(insideClosure[i][j] + shift);
-    }
-  }
-}
-
-static void generateFaceClosureTet(polynomialBasis::clCont &closure, int order)
-{
-  closure.clear();
-  for (int iRotate = 0; iRotate < 3; iRotate++){
-    for (int iSign = 1; iSign >= -1; iSign -= 2){
-      for (int iFace = 0; iFace < 4; iFace++){
-        polynomialBasis::closure closure_face;
-        getFaceClosureTet(iFace, iSign, iRotate, closure_face, order);
-        closure.push_back(closure_face);
-      }
+        closureFull[i].push_back(insideClosure[i][j] + shift);
     }
   }
 }
@@ -1145,52 +1163,9 @@ static void getFaceClosurePrism(int iFace, int iSign, int iRotate,
       closure[nNodes-1] = order2node[iFace][4]; // center
   }
 }
-static void generateFaceClosurePrismFull(polynomialBasis::clCont &closure, std::vector<int> &closureRef, int order) {
-  closure.clear();
-  //input :
-  static const int triRotation[3][6] = {{0,1,2,3,4,5},{1,2,0,4,5,3},{2,0,1,5,3,4}};
-  static const int triSign[2][6] = {{0,1,2,3,4,5},{0,2,1,3,5,4}};
-  static const int triFace[5][6] = {{0,2,1,3,5,4},{3,4,5,0,1,2}};
-  static const int quadFace[3][6] = {{0,1,2,3,4,5},{5,2,4,3,0,1},{1,2,0,4,5,3}};
-  static const int quadRotation[4][6] = {{0,1,2,3,4,5},{3,0,5,4,1,2},{4,3,5,1,0,2},{1,4,5,0,3,2}};
-  static const int quadSign[2][6] = {{0,1,2,3,4,5},{4,1,5,3,0,2}};
-  //static const short int edges[6][2] = {{0,1}, {1,2}, {2,0}, {3,0}, {3,2}, {3,1}};
-  closure.resize(40);
-  closureRef.resize(40);
-  if (order == 0) {
-    for (int i = 0; i < 40; i ++) {
-      closure[i].push_back(0);
-    }
-    return;
-  }
-  for (int i = 0; i < 40; i++)
-    closure[i].resize(6);
-  //Mapping for the p1 nodes
-  //triangular faces
-  for (int iRotate = 0; iRotate < 3; iRotate ++)
-    for (int iFace = 0; iFace < 2; iFace ++)
-      for (int iSign = 0; iSign < 2; iSign ++)
-        for (int iNode = 0; iNode < 6; iNode ++) {
-          int i = iFace + iRotate * 10 + iSign * 5;
-          closureRef[i] = 0;
-          closure[i][triFace[0][iNode]] =
-            triFace[iFace][triRotation[iRotate][triSign[iSign][iNode]]];
-        }
-  //quad Horiz face
-  for (int iRotate = 0; iRotate < 4; iRotate ++)
-    for (int iFace = 0; iFace < 3; iFace ++)
-      for (int iSign = 0; iSign < 2; iSign ++)
-        for (int iNode = 0; iNode < 6; iNode ++) {
-          int i = (2 + iFace) + iRotate * 10 + iSign * 5;
-          closureRef[i] = (iFace + iRotate + iSign) % 2 ? 3 : 2;
-          closure[i][quadFace[closureRef[i]-2][quadRotation[0][iNode]]] =
-            quadFace[iFace][quadRotation[iRotate][quadSign[iSign][iNode]]];
-        }
-}
 
 static void generateFaceClosurePrism(polynomialBasis::clCont &closure, int order)
 {
-
   closure.clear();
   for (int iRotate = 0; iRotate < 4; iRotate++){
     for (int iSign = 1; iSign >= -1; iSign -= 2){
@@ -1203,6 +1178,36 @@ static void generateFaceClosurePrism(polynomialBasis::clCont &closure, int order
   }
 }
 
+static void generateFaceClosurePrismFull(polynomialBasis::clCont &closureFull, std::vector<int> &closureRef, int order) 
+{
+  polynomialBasis::clCont closure;
+  closureFull.clear();
+  closureFull.resize(40);
+  closureRef.resize(40);
+  generateFaceClosurePrism(closure, 1);
+  int ref3 = -1, ref4a = -1, ref4b = -1;
+  for (int i = 0; i < closure.size(); i++) {
+    std::vector<int> &clFull = closureFull[i];
+    std::vector<int> &cl = closure[i];
+    clFull.resize(6, -1);
+    int &ref = cl.size() == 3 ? ref3 : (cl[0] / 3 + cl[1] / 3) % 2 ? ref4b : ref4a;
+    if (ref == -1)
+      ref = i;
+    closureRef[i] = ref;
+    for (int j = 0; j < cl.size(); j ++)
+      clFull[closure[ref][j]] = cl[j];
+    for (int j = 0; j < 6; j ++) {
+      if (clFull[j] == -1) {
+        int k = ((j / 3) + 1) % 2 * 3;
+        int sum = (clFull[k + (j + 1) % 3] + clFull[k + (j + 2) % 3]);
+        clFull[j] = ((sum / 6 + 1) % 2) * 3 + (12 - sum) % 3;
+      }
+    }
+  }
+  static const int edges[] = {0, 1,  0, 2,  0, 3,  1, 2,  1, 4,  2, 5,  3, 4,  3, 5,  4, 5,  -1};
+  addEdgeNodes(closureFull, edges, order);
+}
+
 static void generate2dEdgeClosure(polynomialBasis::clCont &closure, int order, int nNod = 3)
 {
   closure.clear();
@@ -1809,13 +1814,14 @@ const polynomialBasis *polynomialBases::find(int tag)
     generateFaceClosurePrism(F.closures, 1);
     generateFaceClosurePrismFull(F.fullClosures, F.closureRef, 1);
     break;
-  /*case MSH_PRI_18 :
+  case MSH_PRI_18 :
     F.numFaces = 5;
     F.monomials = generatePascalPrism(2);
     F.points =    gmshGeneratePointsPrism(2, false);
     F.parentType = TYPE_PRI;
     generateFaceClosurePrism(F.closures, 2);
-    break;*/
+    generateFaceClosurePrismFull(F.fullClosures, F.closureRef, 2);
+    break;
   default :
     Msg::Error("Unknown function space %d: reverting to TET_4", tag);
     F.numFaces = 4;