From 7569fbeefcb3417f22fd599970cab6d3c07f3897 Mon Sep 17 00:00:00 2001
From: Amaury Johnan <amjohnen@gmail.com>
Date: Wed, 2 Oct 2013 14:21:14 +0000
Subject: [PATCH] fix bad position of high order face vertices

---
 Mesh/HighOrder.cpp | 178 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 165 insertions(+), 13 deletions(-)

diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp
index 2a12ba28a9..20f96999cf 100644
--- a/Mesh/HighOrder.cpp
+++ b/Mesh/HighOrder.cpp
@@ -669,6 +669,147 @@ static void getRegionVertices(GRegion *gr, MElement *incomplete, MElement *ele,
   }
 }
 
+static void getFaceAndInteriorVertices(GRegion *gr, MElement *incomplete, MElement *ele,
+                                       std::vector<MVertex*> &vr, faceContainer &faceVertices,
+                                       bool linear, int nPts = 1)
+{
+  fullMatrix<double> points;
+  int startFace = 0;
+  int startInter = 0;
+
+  switch (incomplete->getType()){
+  case TYPE_TET :
+    switch (nPts){
+    case 0: return;
+    case 1: return;
+    case 2: points = BasisFactory::getNodalBasis(MSH_TET_20)->points; break;
+    case 3: points = BasisFactory::getNodalBasis(MSH_TET_35)->points; break;
+    case 4: points = BasisFactory::getNodalBasis(MSH_TET_56)->points; break;
+    case 5: points = BasisFactory::getNodalBasis(MSH_TET_84)->points; break;
+    case 6: points = BasisFactory::getNodalBasis(MSH_TET_120)->points; break;
+    case 7: points = BasisFactory::getNodalBasis(MSH_TET_165)->points; break;
+    case 8: points = BasisFactory::getNodalBasis(MSH_TET_220)->points; break;
+    case 9: points = BasisFactory::getNodalBasis(MSH_TET_286)->points; break;
+    default:
+      Msg::Error("getRegionVertices not implemented for order %i", nPts+1);
+      break;
+    }
+    startFace = 4 + nPts*6;
+    startInter = ((nPts+2)*(nPts+3)*(nPts+4)-(nPts-2)*(nPts-1)*(nPts))/6;  // = 4+6*(p-1)+4*(p-2)*(p-1)/2 = 4*(p+1)*(p+2)/2-6*(p-1)-2*4 = 2*p*p+2
+    break;
+  case TYPE_HEX :
+    switch (nPts){
+    case 0: return;
+    case 1: points = BasisFactory::getNodalBasis(MSH_HEX_27)->points; break;
+    case 2: points = BasisFactory::getNodalBasis(MSH_HEX_64)->points; break;
+    case 3: points = BasisFactory::getNodalBasis(MSH_HEX_125)->points; break;
+    case 4: points = BasisFactory::getNodalBasis(MSH_HEX_216)->points; break;
+    case 5: points = BasisFactory::getNodalBasis(MSH_HEX_343)->points; break;
+    case 6: points = BasisFactory::getNodalBasis(MSH_HEX_512)->points; break;
+    case 7: points = BasisFactory::getNodalBasis(MSH_HEX_729)->points; break;
+    case 8: points = BasisFactory::getNodalBasis(MSH_HEX_1000)->points; break;
+    default :
+      Msg::Error("getRegionVertices not implemented for order %i", nPts+1);
+      break;
+    }
+    startFace = 8 + nPts*12 ;
+    startInter = (nPts+2)*(nPts+2)*(nPts+2) - (nPts)*(nPts)*(nPts) ; // = 6*(p-1)*(p-1)+12*(p-1)+8 = 6*(p+1)*(p+1)-12*(p-1)-2*8 = 6*p*p+2
+    break;
+  case TYPE_PRI :
+    switch (nPts){
+    case 0: return;
+    case 1: return;
+    case 2: points = BasisFactory::getNodalBasis(MSH_PRI_40)->points; break;
+    case 3: points = BasisFactory::getNodalBasis(MSH_PRI_75)->points; break;
+    case 4: points = BasisFactory::getNodalBasis(MSH_PRI_126)->points; break;
+    case 5: points = BasisFactory::getNodalBasis(MSH_PRI_196)->points; break;
+    case 6: points = BasisFactory::getNodalBasis(MSH_PRI_288)->points; break;
+    case 7: points = BasisFactory::getNodalBasis(MSH_PRI_405)->points; break;
+    case 8: points = BasisFactory::getNodalBasis(MSH_PRI_550)->points; break;
+    default:
+      Msg::Error("getRegionVertices not implemented for order %i", nPts+1);
+      break;
+    }
+    startFace = 6 + nPts*9;
+    startInter = 4*(nPts+1)*(nPts+1)+2;  // = 4*p*p+2 = 6+9*(p-1)+2*(p-2)*(p-1)/2+3*(p-1)*(p-1) = 2*(p+1)*(p+2)/2+3*(p+1)*(p+1)-9*(p-1)-2*6
+    break;
+  case TYPE_PYR:
+    switch (nPts){
+    case 0:
+    case 1: return;
+    case 2: points = BasisFactory::getNodalBasis(MSH_PYR_30)->points; break;
+    case 3: points = BasisFactory::getNodalBasis(MSH_PYR_55)->points; break;
+    case 4: points = BasisFactory::getNodalBasis(MSH_PYR_91)->points; break;
+    case 5: points = BasisFactory::getNodalBasis(MSH_PYR_140)->points; break;
+    case 6: points = BasisFactory::getNodalBasis(MSH_PYR_204)->points; break;
+    case 7: points = BasisFactory::getNodalBasis(MSH_PYR_285)->points; break;
+    case 8: points = BasisFactory::getNodalBasis(MSH_PYR_385)->points; break;
+    default :
+      Msg::Error("getRegionVertices not implemented for order %i", nPts+1);
+      break;
+    }
+    startFace = 5 + nPts*8;
+    startInter = ( nPts+2) * ( (nPts+2) + 1) * (2*(nPts+2) + 1) / 6  -
+      (nPts-1) * ( (nPts-1) + 1) * (2*(nPts-1) + 1) / 6;
+    break;
+
+  }
+
+  int index = startFace;
+  for(int i = 0; i < ele->getNumFaces(); i++){
+    MFace face = ele->getFace(i);
+    int numVert = (face.getNumVertices() == 3) ? nPts * (nPts-1) / 2 : nPts * nPts;
+    faceContainer::iterator fIter = faceVertices.find(face);
+    if(fIter != faceVertices.end()) {
+      std::vector<MVertex*> vtcs = fIter->second;
+      if(face.getNumVertices() == 3 && nPts > 1){ // tri face
+        int orientation;
+        bool swap;
+        if (fIter->first.computeCorrespondence(face, orientation, swap))
+          reorientTrianglePoints(vtcs, orientation, swap);
+        else
+          Msg::Error("Error in face lookup for recuperation of high order face nodes");
+      }
+      else if(face.getNumVertices() == 4){ // quad face
+        int orientation;
+        bool swap;
+        if (fIter->first.computeCorrespondence(face, orientation, swap)){
+          reorientQuadPoints(vtcs, orientation, swap, nPts-1);
+        }
+        else
+          Msg::Error("Error in face lookup for recuperation of high order face nodes");
+      }
+      vr.insert(vr.end(), vtcs.begin(), vtcs.end());
+    }
+    else {
+      for(int k = index; k < index + numVert; k++){
+        MVertex *v;
+        const double t1 = points(k, 0);
+        const double t2 = points(k, 1);
+        const double t3 = points(k, 2);
+        SPoint3 pos;
+        incomplete->pnt(t1, t2, t3, pos);
+        v = new MVertex(pos.x(), pos.y(), pos.z(), gr);
+        gr->mesh_vertices.push_back(v);
+        vr.push_back(v);
+      }
+    }
+    index += numVert;
+  }
+
+  for(int k = startInter; k < points.size1(); k++){
+    MVertex *v;
+    const double t1 = points(k, 0);
+    const double t2 = points(k, 1);
+    const double t3 = points(k, 2);
+    SPoint3 pos;
+    incomplete->pnt(t1, t2, t3, pos);
+    v = new MVertex(pos.x(), pos.y(), pos.z(), gr);
+    gr->mesh_vertices.push_back(v);
+    vr.push_back(v);
+  }
+}
+
 static void setHighOrder(GEdge *ge, edgeContainer &edgeVertices, bool linear,
                          int nbPts = 1)
 {
@@ -792,10 +933,12 @@ static MTetrahedron *setHighOrder(MTetrahedron *t, GRegion *gr,
       // it either way)
       MTetrahedronN incpl(t->getVertex(0), t->getVertex(1), t->getVertex(2),
                           t->getVertex(3), ve, nPts + 1, 0, t->getPartition());
-      getFaceVertices(gr, t, vf, faceVertices, edgeVertices, linear, nPts);
+      //getFaceVertices(gr, t, vf, faceVertices, edgeVertices, linear, nPts);
+      //ve.insert(ve.end(), vf.begin(), vf.end());
+      //getRegionVertices(gr, &incpl, t, vr, linear, nPts);
+      //ve.insert(ve.end(), vr.begin(), vr.end());
+      getFaceAndInteriorVertices(gr, &incpl, t, vf, faceVertices, linear, nPts);
       ve.insert(ve.end(), vf.begin(), vf.end());
-      getRegionVertices(gr, &incpl, t, vr, linear, nPts);
-      ve.insert(ve.end(), vr.begin(), vr.end());
     }
     return new MTetrahedronN(t->getVertex(0), t->getVertex(1),
                              t->getVertex(2), t->getVertex(3), ve, nPts + 1,
@@ -836,13 +979,14 @@ static MHexahedron *setHighOrder(MHexahedron *h, GRegion *gr,
                           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], 0, h->getPartition());
-      getFaceVertices(gr, h, vf, faceVertices, edgeVertices, linear, nPts);
-      getRegionVertices(gr, &incpl, h, vr, linear, nPts);
+      //getFaceVertices(gr, h, vf, faceVertices, edgeVertices, linear, nPts);
+      //getRegionVertices(gr, &incpl, h, vr, linear, nPts);
+      getFaceAndInteriorVertices(gr, &incpl, h, vf, faceVertices, linear, nPts);
       return 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], vr[0],
+                               ve[11], vf[0], vf[1], vf[2], vf[3], vf[4], vf[5], vf[6],
                                0, h->getPartition());
     }
     else {
@@ -850,10 +994,12 @@ static MHexahedron *setHighOrder(MHexahedron *h, GRegion *gr,
                          h->getVertex(3), h->getVertex(4), h->getVertex(5),
                          h->getVertex(6), h->getVertex(7), ve, nPts + 1, 0,
                          h->getPartition());
-      getFaceVertices(gr, h, vf, faceVertices, edgeVertices, linear, nPts);
+      //getFaceVertices(gr, h, vf, faceVertices, edgeVertices, linear, nPts);
+      //ve.insert(ve.end(), vf.begin(), vf.end());
+      //getRegionVertices(gr, &incpl, h, vr, linear, nPts);
+      //ve.insert(ve.end(), vr.begin(), vr.end());
+      getFaceAndInteriorVertices(gr, &incpl, h, vf, faceVertices, linear, nPts);
       ve.insert(ve.end(), vf.begin(), vf.end());
-      getRegionVertices(gr, &incpl, h, vr, linear, nPts);
-      ve.insert(ve.end(), vr.begin(), vr.end());
       return 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,
@@ -884,7 +1030,11 @@ static MPrism *setHighOrder(MPrism *p, GRegion *gr,
   }
   else{
     if (nPts == 1) {
-      getFaceVertices(gr, p, vf, faceVertices, edgeVertices, linear, nPts);
+      MPrismN incpl(p->getVertex(0), p->getVertex(1), p->getVertex(2),
+                    p->getVertex(3), p->getVertex(4), p->getVertex(5),
+                    ve, nPts + 1, 0, p->getPartition());
+      //getFaceVertices(gr, p, vf, faceVertices, edgeVertices, linear, nPts);
+      getFaceAndInteriorVertices(gr, &incpl, p, vf, faceVertices, linear, nPts);
       return new MPrism18(p->getVertex(0), p->getVertex(1), p->getVertex(2),
                           p->getVertex(3), p->getVertex(4), p->getVertex(5),
                           ve[0], ve[1], ve[2], ve[3], ve[4], ve[5], ve[6], ve[7], ve[8],
@@ -899,10 +1049,12 @@ static MPrism *setHighOrder(MPrism *p, GRegion *gr,
       MPrismN incpl(p->getVertex(0), p->getVertex(1), p->getVertex(2),
                     p->getVertex(3), p->getVertex(4), p->getVertex(5),
                     ve, nPts + 1, 0, p->getPartition());
-      getFaceVertices(gr, p, vf, faceVertices, edgeVertices, linear, nPts);
+      //getFaceVertices(gr, p, vf, faceVertices, edgeVertices, linear, nPts);
+      //ve.insert(ve.end(), vf.begin(), vf.end());
+      //getRegionVertices(gr, &incpl, p, vr, linear, nPts);
+      //ve.insert(ve.end(), vr.begin(), vr.end());
+      getFaceAndInteriorVertices(gr, &incpl, p, vf, faceVertices, linear, nPts);
       ve.insert(ve.end(), vf.begin(), vf.end());
-      getRegionVertices(gr, &incpl, p, vr, linear, nPts);
-      ve.insert(ve.end(), vr.begin(), vr.end());
       return new MPrismN(p->getVertex(0), p->getVertex(1), p->getVertex(2),
                          p->getVertex(3), p->getVertex(4), p->getVertex(5),
                          ve, nPts + 1, 0, p->getPartition());
-- 
GitLab