15   inline double pow2(
double x) { 
return x * x; }
 
   17   void rotateHex(
int iFace, 
int iRot, 
int iSign, 
double uI, 
double vI,
 
   18                  double &uO, 
double &vO, 
double &wO)
 
   25     for(
int i = 0; i < iRot; i++) {
 
   64   void rotateHexFull(
int iFace, 
int iRot, 
int iSign, 
double uI, 
double vI,
 
   65                      double wI, 
double &uO, 
double &vO, 
double &wO)
 
   99     for(
int i = 0; i < iRot; i++) {
 
  111   void rotatePyr(
int iFace, 
int iRot, 
int iSign, 
double uI, 
double vI,
 
  112                  double &uO, 
double &vO, 
double &wO)
 
  119     for(
int i = 0; i < iRot; i++) {
 
  157     closure[0].push_back(0);
 
  158     closure[1].push_back(order == 0 ? 0 : 1);
 
  164                                    std::vector<int> &closureRef, 
int order)
 
  168     closure[0].push_back(0);
 
  170       closure[0].push_back(1);
 
  171       closure[1].push_back(1);
 
  173     closure[1].push_back(0);
 
  174     for(
int i = 0; i < order - 1; i++) {
 
  175       closure[0].push_back(2 + i);
 
  176       closure[1].push_back(2 + order - 2 - i);
 
  178     closureRef.resize(2);
 
  187     closure.resize((order + 1) * (order + 2) / 2);
 
  191     case 0: closure[0] = 0; 
break;
 
  193       int face[4][3] = {{-3, -2, -1}, {1, -6, 4}, {-4, 5, 3}, {6, 2, -5}};
 
  194       int order1node[4][3] = {{0, 2, 1}, {0, 1, 3}, {0, 3, 2}, {3, 1, 2}};
 
  195       for(
int i = 0; i < 3; ++i) {
 
  196         int k = (3 + (iSign * i) + iRotate) % 3; 
 
  197         closure[i] = order1node[iFace][k];
 
  199       for(
int i = 0; i < 3; ++i) {
 
  201           iSign * face[iFace][(6 + i * iSign + (-1 + iSign) / 2 + iRotate) %
 
  203         for(
int k = 0; k < (order - 1); k++) {
 
  205             closure[3 + i * (order - 1) + k] =
 
  206               4 + (edgenumber - 1) * (order - 1) + k;
 
  208             closure[3 + i * (order - 1) + k] =
 
  209               4 + (-edgenumber) * (order - 1) - 1 - k;
 
  212       int fi = 3 + 3 * (order - 1);
 
  213       int ti = 4 + 6 * (order - 1);
 
  214       int ndofff = (order - 3 + 2) * (order - 3 + 1) / 2;
 
  215       ti = ti + iFace * ndofff;
 
  216       for(
int k = 0; k < order / 3; k++) {
 
  217         int orderint = order - 3 - k * 3;
 
  219           for(
int ci = 0; ci < 3; ci++) {
 
  220             int shift = (3 + iSign * ci + iRotate) % 3; 
 
  221             closure[fi + ci] = ti + shift;
 
  225           for(
int l = 0; l < orderint - 1; l++) {
 
  226             for(
int ei = 0; ei < 3; ei++) {
 
  228                 (6 + ei * iSign + (-1 + iSign) / 2 + iRotate) % 3;
 
  231                 closure[fi + ei * (orderint - 1) + l] =
 
  232                   ti + edgenumber * (orderint - 1) + l;
 
  234                 closure[fi + ei * (orderint - 1) + l] =
 
  235                   ti + (1 + edgenumber) * (orderint - 1) - 1 - l;
 
  238           fi = fi + 3 * (orderint - 1);
 
  239           ti = ti + 3 * (orderint - 1);
 
  252                                  std::vector<int> &closureRef, 
int order,
 
  253                                  int nNod, 
bool serendip)
 
  256     closure.resize(2 * nNod);
 
  257     closureRef.resize(2 * nNod);
 
  259     for(
int corder = order; corder >= 0; corder -= (nNod == 3 ? 3 : 2)) {
 
  261         for(
int r = 0; r < nNod; r++) {
 
  262           closure[r].push_back(shift);
 
  263           closure[r + nNod].push_back(shift);
 
  267       for(
int r = 0; r < nNod; r++) {
 
  268         for(
int j = 0; j < nNod; j++) {
 
  269           closure[r].push_back(shift + (r + j) % nNod);
 
  270           closure[r + nNod].push_back(shift + (r - j + 1 + nNod) % nNod);
 
  274       int n = nNod * (corder - 1);
 
  275       for(
int r = 0; r < nNod; r++) {
 
  276         for(
int j = 0; j < n; j++) {
 
  277           closure[r].push_back(shift + (j + (corder - 1) * r) % n);
 
  278           closure[r + nNod].push_back(shift +
 
  279                                       (n - j - 1 + (corder - 1) * (r + 1)) % n);
 
  285     for(
int r = 0; r < nNod * 2; r++) {
 
  294     if(order < 2) 
return;
 
  296     for(
int i = 0; 
edges[i] >= 0; ++i) {
 
  297       numNodes = std::max(numNodes, 
edges[i] + 1);
 
  299     std::vector<std::vector<int> > nodes2edges(numNodes,
 
  300                                                std::vector<int>(numNodes, -1));
 
  301     for(
int i = 0; 
edges[i] >= 0; i += 2) {
 
  305     for(std::size_t iClosure = 0; iClosure < closureFull.size(); iClosure++) {
 
  306       std::vector<int> &cl = closureFull[iClosure];
 
  307       for(
int iEdge = 0; 
edges[iEdge] >= 0; iEdge += 2) {
 
  308         if(cl.empty()) 
continue;
 
  309         int n0 = cl[
edges[iEdge]];
 
  310         int n1 = cl[
edges[iEdge + 1]];
 
  311         int oEdge = nodes2edges[n0][n1];
 
  312         if(oEdge == -1) 
Msg::Error(
"invalid p1 closure or invalid edges list");
 
  313         for(
int i = 0; i < order - 1; i++)
 
  314           cl.push_back(numNodes + oEdge / 2 * (order - 1) +
 
  315                        ((oEdge % 2) ? order - 2 - i : i));
 
  323     for(
int iRotate = 0; iRotate < 3; iRotate++) {
 
  324       for(
int iSign = 1; iSign >= -1; iSign -= 2) {
 
  325         for(
int iFace = 0; iFace < 4; iFace++) {
 
  328           closure.push_back(closure_face);
 
  335                                   std::vector<int> &closureRef, 
int order,
 
  340     static const short int faces[4][3] = {
 
  341       {0, 1, 2}, {0, 3, 1}, {0, 2, 3}, {3, 2, 1}};
 
  342     static const int edges[] = {0, 1, 1, 2, 2, 0, 3, 0, 3, 2, 3, 1, -1};
 
  343     static const int faceOrientation[6] = {0, 1, 2, 5, 3, 4};
 
  344     closureFull.resize(24);
 
  345     closureRef.resize(24);
 
  346     for(
int i = 0; i < 24; i++) closureRef[i] = 0;
 
  348       for(
int i = 0; i < 24; i++) { closureFull[i].push_back(0); }
 
  354     for(std::size_t i = 0; i < closureFull.size(); i++) {
 
  355       std::vector<int> &clFull = closureFull[i];
 
  356       std::vector<int> &cl = closure[i];
 
  357       clFull.resize(4, -1);
 
  359       for(std::size_t j = 0; j < cl.size(); j++) clFull[closure[0][j]] = cl[j];
 
  360       for(
int j = 0; j < 4; j++)
 
  362           clFull[j] = (6 - clFull[(j + 1) % 4] - clFull[(j + 2) % 4] -
 
  363                        clFull[(j + 3) % 4]);
 
  365     int nodes2Faces[4][4][4];
 
  366     for(
int i = 0; i < 4; i++) {
 
  367       for(
int iRotate = 0; iRotate < 3; iRotate++) {
 
  368         short int n0 = 
faces[i][(3 - iRotate) % 3];
 
  369         short int n1 = 
faces[i][(4 - iRotate) % 3];
 
  370         short int n2 = 
faces[i][(5 - iRotate) % 3];
 
  371         nodes2Faces[n0][n1][n2] = i * 6 + iRotate;
 
  372         nodes2Faces[n0][n2][n1] = i * 6 + iRotate + 3;
 
  376     std::vector<int> closureTrianglesRef;
 
  379                                 order - 3, 3, 
false);
 
  381     for(std::size_t iClosure = 0; iClosure < closureFull.size(); iClosure++) {
 
  383       std::vector<int> &cl = closureFull[iClosure];
 
  385         for(
int iFace = 0; iFace < 4; iFace++) {
 
  386           int n0 = cl[
faces[iFace][0]];
 
  387           int n1 = cl[
faces[iFace][1]];
 
  388           int n2 = cl[
faces[iFace][2]];
 
  389           short int id = nodes2Faces[n0][n1][n2];
 
  390           short int iTriClosure = faceOrientation[
id % 6];
 
  391           short int idFace = 
id / 6;
 
  392           int nOnFace = closureTriangles[iTriClosure].size();
 
  393           for(
int i = 0; i < nOnFace; i++) {
 
  394             cl.push_back(4 + 6 * (order - 1) + idFace * nOnFace +
 
  395                          closureTriangles[iTriClosure][i]);
 
  400     if(order >= 4 && !serendip) {
 
  402       std::vector<int> fakeClosureRef;
 
  405       for(std::size_t i = 0; i < closureFull.size(); i++) {
 
  406         std::size_t shift = closureFull[i].size();
 
  407         for(std::size_t j = 0; j < insideClosure[i].size(); j++)
 
  408           closureFull[i].push_back(insideClosure[i][j] + shift);
 
  440     for(
int iRotate = 0; iRotate < 4; iRotate++) {
 
  441       for(
int iSign = 1; iSign >= -1; iSign -= 2) {
 
  442         for(
int iFace = 0; iFace < 6; iFace++) {
 
  446           for(std::size_t iNode = 0; iNode < cl.size(); ++iNode) {
 
  449                       fsFace.
points(iNode, 1), u, v, w);
 
  451             double D = std::numeric_limits<double>::max();
 
  452             for(
int jNode = 0; jNode < points.
size1(); ++jNode) {
 
  453               double d = 
pow2(points(jNode, 0) - u) +
 
  454                          pow2(points(jNode, 1) - v) +
 
  455                          pow2(points(jNode, 2) - w);
 
  462           closure.push_back(cl);
 
  469                                   std::vector<int> &closureRef, 
int order,
 
  475     for(
int iRotate = 0; iRotate < 4; iRotate++) {
 
  476       for(
int iSign = 1; iSign >= -1; iSign -= 2) {
 
  477         for(
int iFace = 0; iFace < 6; iFace++) {
 
  479           cl.resize(points.
size1());
 
  480           for(
int iNode = 0; iNode < points.
size1(); ++iNode) {
 
  483                           points(iNode, 1), points(iNode, 2), u, v, w);
 
  485             double D = std::numeric_limits<double>::max();
 
  486             for(
int jNode = 0; jNode < points.
size1(); ++jNode) {
 
  487               double d = 
pow2(points(jNode, 0) - u) +
 
  488                          pow2(points(jNode, 1) - v) +
 
  489                          pow2(points(jNode, 2) - w);
 
  497           closure.push_back(cl);
 
  498           closureRef.push_back(0);
 
  506                              int isTriangle, 
int start)
 
  516       isTriangle ? (order - 2) * (order - 1) / 2 : (order - 1) * (order - 1);
 
  517     for(
int i = 0; i < nNodes; ++i, ++idx, ++start) { closure[idx] = start; }
 
  521                           int idx, 
int order, 
int isTriangle)
 
  523     if(order <= 0) 
return;
 
  527     const int nCorner = isTriangle ? 3 : 4;
 
  528     for(
int i = 0; i < nCorner; ++i, ++idx) {
 
  529       closure[idx] = old[start + (nCorner + i * iSign + iRotate) % nCorner];
 
  532     const int &nEdge = nCorner;
 
  533     for(
int i = 0; i < nEdge; ++i) {
 
  535         (nEdge + i * iSign + iRotate + (iSign == -1 ? -1 : 0)) % nEdge;
 
  536       int startOldEdge = start + nCorner + iOldEdge * (order - 1);
 
  538         for(
int j = startOldEdge; j < startOldEdge + order - 1; ++j, ++idx)
 
  539           closure[idx] = old[j];
 
  542         for(
int j = startOldEdge + order - 2; j >= startOldEdge; --j, ++idx)
 
  543           closure[idx] = old[j];
 
  546     if(isTriangle && order > 3)
 
  548     else if(!isTriangle && order > 2)
 
  556     bool isTriangle = iFace < 2;
 
  557     if(isTriangle && iRotate > 2) 
return;
 
  562       isTriangle ? (order + 1) * (order + 2) / 2 : (order + 1) * (order + 1);
 
  563     closure.resize(nNodes);
 
  572     for(
int i = 0; i < 9; ++i) {
 
  573       edge2nodes[i] = 
new int[order - 1];
 
  574       for(
int k = 0; k < order - 1; ++k, ++n) edge2nodes[i][k] = n;
 
  578     const int nCorner = isTriangle ? 3 : 4;
 
  579     for(
int i = 0; i < nCorner; ++i) {
 
  586       const int &nEdge = nCorner;
 
  589       for(
int i = 0; i < nEdge; ++i) {
 
  593           for(
int k = 0; k < order - 1; ++k, ++idx) {
 
  594             closure[idx] = edge2nodes[edge][k];
 
  599           for(
int k = order - 2; k >= 0; --k, ++idx) {
 
  600             closure[idx] = edge2nodes[edge][k];
 
  604       for(
int i = 0; i < 9; ++i) 
delete edge2nodes[i];
 
  607       int start = 6 + 9 * (order - 1) +
 
  608                   std::min(iFace, 2) * (order - 2) * (order - 1) / 2 +
 
  609                   std::max(iFace - 2, 0) * (order - 1) * (order - 1);
 
  621     for(
int iRotate = 0; iRotate < 4; iRotate++) {
 
  622       for(
int iSign = 1; iSign >= -1; iSign -= 2) {
 
  623         for(
int iFace = 0; iFace < 5; iFace++) {
 
  626           closure.push_back(closure_face);
 
  633                                     std::vector<int> &closureRef, 
int order)
 
  637     closureFull.resize(40);
 
  638     closureRef.resize(40);
 
  640     int ref3 = -1, ref4a = -1, ref4b = -1;
 
  641     for(std::size_t i = 0; i < closure.size(); i++) {
 
  642       std::vector<int> &clFull = closureFull[i];
 
  643       std::vector<int> &cl = closure[i];
 
  644       if(cl.size() == 0) 
continue;
 
  645       clFull.resize(6, -1);
 
  646       int &ref = cl.size() == 3              ? ref3 :
 
  647                  (cl[0] / 3 + cl[1] / 3) % 2 ? ref4b :
 
  649       if(ref == -1) ref = i;
 
  651       for(std::size_t j = 0; j < cl.size(); j++)
 
  652         clFull[closure[ref][j]] = cl[j];
 
  653       for(
int j = 0; j < 6; j++) {
 
  654         if(clFull[j] == -1) {
 
  655           int k = ((j / 3) + 1) % 2 * 3;
 
  656           int sum = (clFull[k + (j + 1) % 3] + clFull[k + (j + 2) % 3]);
 
  657           clFull[j] = ((sum / 6 + 1) % 2) * 3 + (12 - sum) % 3;
 
  661     static const int edges[] = {0, 1, 0, 2, 0, 3, 1, 2, 1, 4,
 
  662                                 2, 5, 3, 4, 3, 5, 4, 5, -1};
 
  664     if(order < 2) 
return;
 
  666     static const int faces[5][4] = {
 
  667       {0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, {0, 3, 5, 2}, {1, 2, 5, 4}};
 
  670       int nextFaceNode = 15;
 
  672       int numFaceNodes = 4;
 
  673       std::map<int, int> nodeSum2Face;
 
  674       for(
int iFace = 0; iFace < numFaces; iFace++) {
 
  676         for(
int iNode = 0; iNode < numFaceNodes; iNode++) {
 
  677           nodeSum += 
faces[iFace][iNode];
 
  679         nodeSum2Face[nodeSum] = iFace;
 
  681       for(std::size_t i = 0; i < closureFull.size(); i++) {
 
  682         if(closureFull[i].empty()) 
continue;
 
  683         for(
int iFace = 0; iFace < numFaces; iFace++) {
 
  685           for(
int iNode = 0; iNode < numFaceNodes; iNode++)
 
  686             nodeSum += 
faces[iFace][iNode] < 0 ?
 
  687                          faces[iFace][iNode] :
 
  688                          closureFull[i][
faces[iFace][iNode]];
 
  689           auto it = nodeSum2Face.find(nodeSum);
 
  690           if(it == nodeSum2Face.end()) 
Msg::Error(
"Prism face not found");
 
  691           int mappedFaceId = it->second;
 
  692           if(mappedFaceId > 1) {
 
  693             closureFull[i].push_back(nextFaceNode + mappedFaceId - 2);
 
  699       Msg::Error(
"FaceClosureFull not implemented for prisms of order %d",
 
  713     for(
int iRotate = 0; iRotate < 4; iRotate++) {
 
  714       for(
int iSign = 1; iSign >= -1; iSign -= 2) {
 
  715         for(
int iFace = 0; iFace < 5; iFace++) {
 
  724           for(std::size_t iNode = 0; iNode < cl.size(); ++iNode) {
 
  727                       fsFace->
points(iNode, 1), u, v, w);
 
  729             double D = std::numeric_limits<double>::max();
 
  730             for(
int jNode = 0; jNode < points.
size1(); ++jNode) {
 
  731               double d = 
pow2(points(jNode, 0) - u) +
 
  732                          pow2(points(jNode, 1) - v) +
 
  733                          pow2(points(jNode, 2) - w);
 
  740           closure.push_back(cl);
 
  750     closure.resize(2 * nNod);
 
  751     for(
int j = 0; j < nNod; j++) {
 
  752       closure[j].push_back(j);
 
  753       closure[j].push_back((j + 1) % nNod);
 
  754       closure[nNod + j].push_back((j + 1) % nNod);
 
  755       closure[nNod + j].push_back(j);
 
  756       for(
int i = 0; i < order - 1; i++) {
 
  757         closure[j].push_back(nNod + (order - 1) * j + i);
 
  758         closure[nNod + j].push_back(nNod + (order - 1) * (j + 1) - i - 1);
 
  760       closure[j].type = closure[nNod + j].type =
 
  769     for(
int i = 0; i < nb; i++) {
 
  770       closure[i].push_back(0);
 
  867   case TYPE_PNT: numBubble = 0; 
break;
 
  902       numBubble = (
order - 2) * ((
order - 2) + 1) * (2 * (
order - 2) + 1) / 6;
 
  912                                        int elementType)
 const 
  914   if(elementType != -1 && elementType != 
type) {
 
  915     std::cout << 
"Incorrect element type " << std::endl;
 
  929                                     int elementType)
 const 
  932     std::cout << 
"Non-matching node counts " << nodes.
size1() << 
" vs " 
  941     std::cout << 
"Could not find forward transformation " << std::endl;
 
  947   for(
int i = 0; i < nodes.
size1(); i++) {
 
  951     for(
int j = 0; j < nodes.
size1(); j++) {
 
  952       if(fabs(tfo(i, j) - 1.0) < tol) {
 
  956       if(fabs(tfo(i, j)) < tol) { nbZeroes++; }
 
  958     if(nbOnes != 1) 
return false;
 
  959     if(nbZeroes != nodes.
size1() - 1) 
return false;