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;