12 #include "GmshConfig.h"
23 #if defined(HAVE_QUADTRI)
24 #include "QuadTriTransfinite3D.h"
59 new MHexahedron(tab[i][j][k], tab[i + 1][j][k], tab[i + 1][j + 1][k], \
60 tab[i][j + 1][k], tab[i][j][k + 1], tab[i + 1][j][k + 1], \
61 tab[i + 1][j + 1][k + 1], tab[i][j + 1][k + 1])
63 #define CREATE_PRISM_1 \
64 new MPrism(tab[i][j][k], tab[i + 1][j][k], tab[i][j + 1][k], \
65 tab[i][j][k + 1], tab[i + 1][j][k + 1], tab[i][j + 1][k + 1])
67 #define CREATE_PRISM_2 \
68 new MPrism(tab[i + 1][j + 1][k], tab[i][j + 1][k], tab[i + 1][j][k], \
69 tab[i + 1][j + 1][k + 1], tab[i][j + 1][k + 1], \
72 #define CREATE_PRISM_3 \
73 new MPrism(tab[i][j][k], tab[i][j + 1][k], tab[i + 1][j + 1][k], \
74 tab[i][j][k + 1], tab[i][j + 1][k + 1], tab[i + 1][j + 1][k + 1])
76 #define CREATE_PRISM_4 \
77 new MPrism(tab[i][j][k], tab[i + 1][j][k], tab[i + 1][j + 1][k], \
78 tab[i][j][k + 1], tab[i + 1][j][k + 1], tab[i + 1][j + 1][k + 1])
80 #define CREATE_SIM_1 \
81 new MTetrahedron(tab[i][j][k], tab[i + 1][j][k], tab[i][j + 1][k], \
84 #define CREATE_SIM_2 \
85 new MTetrahedron(tab[i + 1][j][k], tab[i][j + 1][k], tab[i][j][k + 1], \
88 #define CREATE_SIM_3 \
89 new MTetrahedron(tab[i][j][k + 1], tab[i + 1][j][k + 1], tab[i][j + 1][k], \
92 #define CREATE_SIM_4 \
93 new MTetrahedron(tab[i + 1][j][k], tab[i][j + 1][k], tab[i + 1][j][k + 1], \
96 #define CREATE_SIM_5 \
97 new MTetrahedron(tab[i][j + 1][k], tab[i][j + 1][k + 1], \
98 tab[i + 1][j][k + 1], tab[i + 1][j + 1][k])
100 #define CREATE_SIM_6 \
101 new MTetrahedron(tab[i + 1][j][k + 1], tab[i][j + 1][k + 1], \
102 tab[i + 1][j + 1][k + 1], tab[i + 1][j + 1][k])
104 #define CREATE_SIM_7 \
105 new MTetrahedron(tab[i][j][k], tab[i][j + 1][k], tab[i][j][k + 1], \
106 tab[i + 1][j + 1][k])
108 #define CREATE_SIM_8 \
109 new MTetrahedron(tab[i][j + 1][k], tab[i][j + 1][k + 1], tab[i][j][k + 1], \
110 tab[i + 1][j + 1][k])
112 #define CREATE_SIM_9 \
113 new MTetrahedron(tab[i][j][k + 1], tab[i][j + 1][k + 1], \
114 tab[i + 1][j + 1][k + 1], tab[i + 1][j + 1][k])
116 #define CREATE_SIM_10 \
117 new MTetrahedron(tab[i][j][k], tab[i + 1][j][k], tab[i + 1][j + 1][k], \
120 #define CREATE_SIM_11 \
121 new MTetrahedron(tab[i + 1][j][k], tab[i + 1][j + 1][k], tab[i][j][k + 1], \
122 tab[i + 1][j][k + 1])
124 #define CREATE_SIM_12 \
125 new MTetrahedron(tab[i][j][k + 1], tab[i + 1][j][k + 1], \
126 tab[i + 1][j + 1][k], tab[i + 1][j + 1][k + 1])
129 double f5,
double f6,
double c1,
double c2,
130 double c3,
double c4,
double c5,
double c6,
131 double c7,
double c8,
double c9,
double c10,
132 double c11,
double c12,
double s1,
double s2,
133 double s3,
double s4,
double s5,
double s6,
134 double s7,
double s8,
double u,
double v,
double w)
136 return (1 - u) * f4 + u * f2 + (1 - v) * f1 + v * f3 + (1 - w) * f5 + w * f6 -
137 ((1 - u) * (1 - v) * c9 + (1 - u) * v * c12 + u * (1 - v) * c10 +
139 ((1 - v) * (1 - w) *
c1 + (1 - v) * w * c5 + v * (1 - w) * c3 +
141 ((1 - u) * (1 - w) * c4 + (1 - w) * u * c2 + w * (1 - u) * c8 +
143 (1 - u) * (1 - v) * (1 - w) * s1 + u * (1 - v) * (1 - w) * s2 +
144 u * v * (1 - w) * s3 + (1 - u) * v * (1 - w) * s4 +
145 (1 - u) * (1 - v) * w * s5 + u * (1 - v) * w * s6 + u * v * w * s7 +
146 (1 - u) * v * w * s8;
159 f1->
x(), f2->
x(), f3->
x(), f4->
x(), f5->
x(), f6->
x(),
c1->x(), c2->
x(),
160 c3->
x(), c4->
x(), c5->
x(), c6->
x(), c7->
x(), c8->
x(), c9->
x(), c10->
x(),
161 c11->
x(), c12->
x(), s1->
x(), s2->
x(), s3->
x(), s4->
x(), s5->
x(), s6->
x(),
162 s7->
x(), s8->
x(), u, v, w);
164 f1->
y(), f2->
y(), f3->
y(), f4->
y(), f5->
y(), f6->
y(),
c1->y(), c2->
y(),
165 c3->
y(), c4->
y(), c5->
y(), c6->
y(), c7->
y(), c8->
y(), c9->
y(), c10->
y(),
166 c11->
y(), c12->
y(), s1->
y(), s2->
y(), s3->
y(), s4->
y(), s5->
y(), s6->
y(),
167 s7->
y(), s8->
y(), u, v, w);
169 f1->
z(), f2->
z(), f3->
z(), f4->
z(), f5->
z(), f6->
z(),
c1->z(), c2->
z(),
170 c3->
z(), c4->
z(), c5->
z(), c6->
z(), c7->
z(), c8->
z(), c9->
z(), c10->
z(),
171 c11->
z(), c12->
z(), s1->
z(), s2->
z(), s3->
z(), s4->
z(), s5->
z(), s6->
z(),
172 s7->
z(), s8->
z(), u, v, w);
198 std::vector<MVertex *> s(8);
199 if(corners.size() == 8) {
200 for(
int i = 0; i < 8; i++) s[i] = corners[i];
202 else if(corners.size() == 6) {
216 std::vector<MVertex *>
c(4);
234 int faces[] = {0, 1, 5, 4, 1, 2, 6, 5, 3, 2, 6, 7,
235 0, 3, 7, 4, 0, 1, 2, 3, 4, 5, 6, 7};
236 int permutations[] = {0, 1, 2, 3, 1, 2, 3, 0, 2, 3, 0, 1, 3, 0, 1, 2,
237 3, 2, 1, 0, 2, 1, 0, 3, 1, 0, 3, 2, 0, 3, 2, 1};
238 for(
int p = 0; p < 8; p++) {
239 for(
int f = 0;
f < 6;
f++) {
240 if(s[
faces[4 *
f + 0]] ==
c[permutations[4 * p + 0]] &&
241 s[
faces[4 *
f + 1]] ==
c[permutations[4 * p + 1]] &&
242 s[
faces[4 *
f + 2]] ==
c[permutations[4 * p + 2]] &&
243 s[
faces[4 *
f + 3]] ==
c[permutations[4 * p + 3]]) {
251 for(
int i = 0; i <=
_ll; i++)
252 for(
int j = 0; j <=
_hh; j++)
274 case 0:
index = (n + N * m);
break;
275 case 1:
index = (M * N - M * (n + 1) + m);
break;
276 case 2:
index = (M * N - (n + N * m) - 1);
break;
277 case 3:
index = (M + n * M - m - 1);
break;
278 case 4:
index = (N + m * N - n - 1);
break;
279 case 5:
index = (M * N - (m + M * n) - 1);
break;
280 case 6:
index = (M * N - N * (m + 1) + n);
break;
281 case 7:
index = (m + M * n);
break;
285 if(index < 0 || index >= (
int)
_list.size() || !v) {
286 Msg::Error(
"Wrong index in transfinite mesh of surface %d: "
287 "m=%d n=%d M=%d N=%d perm=%d",
306 if(
faces.size() == 6) {
310 else if(
faces.size() == 5) {
312 auto found_it = std::find_if(begin(
faces), end(
faces), [](
GFace *face) {
313 return face->
edges().size() == 3 ||
316 if(found_it != end(
faces)) { gf = *found_it; }
319 std::vector<GEdge *> redges = gr->
edges();
320 for(
auto *fedge : gf->
edges()) {
321 const auto found_it = std::find(begin(redges), end(redges), fedge);
322 if(found_it != end(redges)) { redges.erase(found_it); }
325 std::size_t N = corners.size();
326 for(std::size_t i = 0; i < N; i++) {
327 for(
auto it = redges.begin(); it != redges.end(); it++) {
328 if((*it)->getBeginVertex()->mesh_vertices[0] == corners[i]) {
329 corners.push_back((*it)->getEndVertex()->mesh_vertices[0]);
332 else if((*it)->getEndVertex()->mesh_vertices[0] == corners[i]) {
333 corners.push_back((*it)->getBeginVertex()->mesh_vertices[0]);
346 Msg::Info(
"Meshing volume %d (Transfinite)", gr->
tag());
351 "Transfinite algorithm only available for 5- and 6-face volumes");
357 const std::vector<GEdge *> &
edges = gr->
edges();
358 for(
auto it =
edges.begin(); it !=
edges.end(); it++) {
359 if(!(*it)->getBeginVertex() || !(*it)->getEndVertex()) {
360 Msg::Error(
"Transfinite algorithm cannot be applied with curve %d which "
361 "has no begin or end point",
367 std::vector<MVertex *> corners;
369 if(corners.size() != 6 && corners.size() != 8) {
370 Msg::Error(
"Volume %d is transfinite but has %d corners", gr->
tag(),
375 std::vector<GOrientedTransfiniteFace> orientedFaces(6);
376 for(
auto it =
faces.begin(); it !=
faces.end(); ++it) {
379 Msg::Error(
"Incompatible surface %d in transfinite volume %d",
380 (*it)->tag(), gr->
tag());
383 else if(orientedFaces[
f.index()].getSurface()) {
384 Msg::Error(
"Surfaces %d and %d mapped to the same index in transfinite "
386 orientedFaces[
f.index()].getSurface()->tag(), (*it)->tag(),
390 orientedFaces[
f.index()] =
f;
393 int N_i = orientedFaces[4].getNumU();
394 int N_j = orientedFaces[4].getNumV();
395 int N_k = orientedFaces[1].getNumV();
397 std::vector<double> lengths_i, lengths_j, lengths_k;
398 double L_i = 0., L_j = 0., L_k = 0.;
399 lengths_i.push_back(0.);
400 lengths_j.push_back(0.);
401 lengths_k.push_back(0.);
402 for(
int i = 0; i < N_i - 1; i++) {
403 MVertex *v1 = orientedFaces[4].getVertex(i, 0);
404 MVertex *v2 = orientedFaces[4].getVertex(i + 1, 0);
406 lengths_i.push_back(L_i);
408 for(
int i = 0; i < N_j - 1; i++) {
409 MVertex *v1 = orientedFaces[1].getVertex(i, 0);
410 MVertex *v2 = orientedFaces[1].getVertex(i + 1, 0);
412 lengths_j.push_back(L_j);
414 for(
int i = 0; i < N_k - 1; i++) {
415 MVertex *v1 = orientedFaces[1].getVertex(0, i);
416 MVertex *v2 = orientedFaces[1].getVertex(0, i + 1);
418 lengths_k.push_back(L_k);
423 MVertex *s0 = orientedFaces[4].getVertex(0, 0);
424 MVertex *s1 = orientedFaces[4].getVertex(N_i - 1, 0);
425 MVertex *s2 = orientedFaces[4].getVertex(N_i - 1, N_j - 1);
426 MVertex *s3 = orientedFaces[4].getVertex(0, N_j - 1);
428 MVertex *s4 = orientedFaces[5].getVertex(0, 0);
429 MVertex *s5 = orientedFaces[5].getVertex(N_i - 1, 0);
430 MVertex *s6 = orientedFaces[5].getVertex(N_i - 1, N_j - 1);
431 MVertex *s7 = orientedFaces[5].getVertex(0, N_j - 1);
433 std::vector<std::vector<std::vector<MVertex *> > > &tab(
436 for(
int i = 0; i < N_i; i++) {
438 for(
int j = 0; j < N_j; j++) { tab[i][j].resize(N_k); }
441 for(
int i = 0; i < N_i; i++) {
442 double u = lengths_i[i] / L_i;
444 for(
int j = 0; j < N_j; j++) {
445 double v = lengths_j[j] / L_j;
447 MVertex *c0 = orientedFaces[4].getVertex(i, 0);
448 MVertex *
c1 = orientedFaces[4].getVertex(N_i - 1, j);
449 MVertex *c2 = orientedFaces[4].getVertex(i, N_j - 1);
450 MVertex *c3 = orientedFaces[4].getVertex(0, j);
452 MVertex *c4 = orientedFaces[5].getVertex(i, 0);
453 MVertex *c5 = orientedFaces[5].getVertex(N_i - 1, j);
454 MVertex *c6 = orientedFaces[5].getVertex(i, N_j - 1);
455 MVertex *c7 = orientedFaces[5].getVertex(0, j);
457 MVertex *f4 = orientedFaces[4].getVertex(i, j);
458 MVertex *f5 = orientedFaces[5].getVertex(i, j);
460 for(
int k = 0; k < N_k; k++) {
461 double w = lengths_k[k] / L_k;
463 MVertex *c8 = orientedFaces[0].getVertex(0, k);
464 MVertex *c9 = orientedFaces[0].getVertex(N_i - 1, k);
465 MVertex *c10 = orientedFaces[2].getVertex(N_i - 1, k);
466 MVertex *c11 = orientedFaces[2].getVertex(0, k);
468 MVertex *f0 = orientedFaces[0].getVertex(i, k);
469 MVertex *f1 = orientedFaces[1].getVertex(j, k);
470 MVertex *f2 = orientedFaces[2].getVertex(i, k);
472 if(corners.size() == 8)
473 f3 = orientedFaces[3].getVertex(j, k);
477 if(i && j && k && i != N_i - 1 && j != N_j - 1 && k != N_k - 1) {
479 gr, f0, f1, f2, f3, f4, f5, c0,
c1, c2, c3, c4, c5, c6, c7, c8, c9,
480 c10, c11, s0, s1, s2, s3, s4, s5, s6, s7, u, v, w);
493 else if(i == N_i - 1) {
496 else if(j == N_j - 1) {
499 else if(k == N_k - 1) {
506 #if defined(HAVE_QUADTRI)
509 std::set<std::pair<MVertex *, MVertex *> > boundary_diags;
511 if(!getTransfiniteBoundaryDiags(gr, &boundary_diags)) {
513 "In MeshTransfiniteVolume(), getTransfiniteBoundaryDiags() failed. "
514 "Aborting mesh of region %d.",
523 if(
faces.size() == 6) {
524 for(
int i = 0; i < N_i - 1; i++) {
525 for(
int j = 0; j < N_j - 1; j++) {
526 for(
int k = 0; k < N_k - 1; k++) {
527 #if defined(HAVE_QUADTRI)
530 std::vector<MVertex *> verts;
532 verts[0] = tab[i][j][k];
533 verts[1] = tab[i + 1][j][k];
534 verts[2] = tab[i + 1][j + 1][k];
535 verts[3] = tab[i][j + 1][k];
536 verts[4] = tab[i][j][k + 1];
537 verts[5] = tab[i + 1][j][k + 1];
538 verts[6] = tab[i + 1][j + 1][k + 1];
539 verts[7] = tab[i][j + 1][k + 1];
540 if((!orientedFaces[3].recombined() && i == 0) ||
541 (!orientedFaces[1].recombined() && i == N_i - 2) ||
542 (!orientedFaces[0].recombined() && j == 0) ||
543 (!orientedFaces[2].recombined() && j == N_j - 2) ||
544 (!orientedFaces[4].recombined() && k == 0) ||
545 (!orientedFaces[5].recombined() && k == N_k - 2)) {
547 meshTransfElemWithInternalVertex(gr, verts, &boundary_diags);
552 new MHexahedron(verts[0], verts[1], verts[2], verts[3],
553 verts[4], verts[5], verts[6], verts[7]));
558 if(orientedFaces[0].recombined() && orientedFaces[1].recombined() &&
559 orientedFaces[2].recombined() && orientedFaces[3].recombined() &&
560 orientedFaces[4].recombined() && orientedFaces[5].recombined()) {
563 else if(!orientedFaces[0].recombined() &&
564 orientedFaces[1].recombined() &&
565 !orientedFaces[2].recombined() &&
566 orientedFaces[3].recombined() &&
567 orientedFaces[4].recombined() &&
568 orientedFaces[5].recombined()) {
570 tab[i][j][k], tab[i + 1][j][k], tab[i][j][k + 1],
571 tab[i][j + 1][k], tab[i + 1][j + 1][k], tab[i][j + 1][k + 1]));
573 new MPrism(tab[i + 1][j][k + 1], tab[i][j][k + 1],
574 tab[i + 1][j][k], tab[i + 1][j + 1][k + 1],
575 tab[i][j + 1][k + 1], tab[i + 1][j + 1][k]));
577 else if(orientedFaces[0].recombined() &&
578 !orientedFaces[1].recombined() &&
579 orientedFaces[2].recombined() &&
580 !orientedFaces[3].recombined() &&
581 orientedFaces[4].recombined() &&
582 orientedFaces[5].recombined()) {
584 tab[i + 1][j][k], tab[i + 1][j + 1][k], tab[i + 1][j][k + 1],
585 tab[i][j][k], tab[i][j + 1][k], tab[i][j][k + 1]));
587 new MPrism(tab[i + 1][j + 1][k + 1], tab[i + 1][j][k + 1],
588 tab[i + 1][j + 1][k], tab[i][j + 1][k + 1],
589 tab[i][j][k + 1], tab[i][j + 1][k]));
591 else if(orientedFaces[0].recombined() &&
592 orientedFaces[1].recombined() &&
593 orientedFaces[2].recombined() &&
594 orientedFaces[3].recombined() &&
595 !orientedFaces[4].recombined() &&
596 !orientedFaces[5].recombined()) {
600 else if(!orientedFaces[0].recombined() &&
601 !orientedFaces[1].recombined() &&
602 !orientedFaces[2].recombined() &&
603 !orientedFaces[3].recombined() &&
604 !orientedFaces[4].recombined() &&
605 !orientedFaces[5].recombined()) {
614 Msg::Error(
"Wrong surface recombination in transfinite volume %d",
622 else if(
faces.size() == 5) {
623 bool standard_algo =
true;
624 for(
int i = 0; i < 5; i++) {
625 if(orientedFaces[i].getSurface() &&
626 orientedFaces[i].getSurface()->meshAttributes.transfinite3) {
627 standard_algo =
false;
632 for(
int j = 0; j < N_j - 1; j++) {
633 for(
int k = 0; k < N_k - 1; k++) {
634 #if defined(HAVE_QUADTRI)
636 std::vector<MVertex *> verts;
638 verts[0] = tab[0][j][k];
639 verts[1] = tab[1][j][k];
640 verts[2] = tab[1][j + 1][k];
641 verts[3] = tab[0][j][k + 1];
642 verts[4] = tab[1][j][k + 1];
643 verts[5] = tab[1][j + 1][k + 1];
644 if((!orientedFaces[0].recombined() && j == 0) ||
645 (!orientedFaces[2].recombined() && j == N_j - 2) ||
646 (!orientedFaces[4].recombined() && k == 0) ||
647 (!orientedFaces[5].recombined() && k == N_k - 2)) {
649 meshTransfElemWithInternalVertex(gr, verts, &boundary_diags);
652 gr->
prisms.push_back(
new MPrism(verts[0], verts[1], verts[2],
653 verts[3], verts[4], verts[5]));
658 if((orientedFaces[0].recombined() && orientedFaces[1].recombined() &&
659 orientedFaces[2].recombined() && orientedFaces[4].recombined() &&
660 orientedFaces[5].recombined()) ||
661 (orientedFaces[0].recombined() && orientedFaces[1].recombined() &&
662 orientedFaces[2].recombined() && !orientedFaces[4].recombined() &&
663 !orientedFaces[5].recombined())) {
665 tab[0][j][k], tab[1][j][k], tab[1][j + 1][k], tab[0][j][k + 1],
666 tab[1][j][k + 1], tab[1][j + 1][k + 1]));
668 else if(!orientedFaces[0].recombined() &&
669 !orientedFaces[1].recombined() &&
670 !orientedFaces[2].recombined() &&
671 !orientedFaces[4].recombined() &&
672 !orientedFaces[5].recombined()) {
674 tab[0][j][k], tab[1][j][k], tab[1][j + 1][k], tab[0][j][k + 1]));
676 new MTetrahedron(tab[1][j][k], tab[1][j + 1][k], tab[0][j][k + 1],
679 new MTetrahedron(tab[0][j][k + 1], tab[1][j + 1][k + 1],
680 tab[1][j][k + 1], tab[1][j + 1][k]));
683 Msg::Error(
"Wrong surface recombination in transfinite volume %d",
689 for(
int i = 1; i < N_i - 1; i++) {
690 for(
int j = 0; j < N_j - 1; j++) {
691 for(
int k = 0; k < N_k - 1; k++) {
692 #if defined(HAVE_QUADTRI)
695 std::vector<MVertex *> verts;
697 verts[0] = tab[i][j][k];
698 verts[1] = tab[i + 1][j][k];
699 verts[2] = tab[i + 1][j + 1][k];
700 verts[3] = tab[i][j + 1][k];
701 verts[4] = tab[i][j][k + 1];
702 verts[5] = tab[i + 1][j][k + 1];
703 verts[6] = tab[i + 1][j + 1][k + 1];
704 verts[7] = tab[i][j + 1][k + 1];
705 if((!orientedFaces[1].recombined() && i == N_i - 2) ||
706 (!orientedFaces[0].recombined() && j == 0) ||
707 (!orientedFaces[2].recombined() && j == N_j - 2) ||
708 (!orientedFaces[4].recombined() && k == 0) ||
709 (!orientedFaces[5].recombined() && k == N_k - 2)) {
711 meshTransfElemWithInternalVertex(gr, verts, &boundary_diags);
715 new MHexahedron(verts[0], verts[1], verts[2], verts[3],
716 verts[4], verts[5], verts[6], verts[7]));
721 if(orientedFaces[0].recombined() && orientedFaces[1].recombined() &&
722 orientedFaces[2].recombined() && orientedFaces[4].recombined() &&
723 orientedFaces[5].recombined()) {
726 else if(orientedFaces[0].recombined() &&
727 orientedFaces[1].recombined() &&
728 orientedFaces[2].recombined() &&
729 !orientedFaces[4].recombined() &&
730 !orientedFaces[5].recombined()) {
734 else if(!orientedFaces[0].recombined() &&
735 !orientedFaces[1].recombined() &&
736 !orientedFaces[2].recombined() &&
737 !orientedFaces[4].recombined() &&
738 !orientedFaces[5].recombined()) {
747 Msg::Error(
"Wrong surface recombination in transfinite volume %d",
756 for(
int i = 0; i < N_i - 1; i++) {
758 for(
int k = 0; k < N_k - 1; k++) {
759 if(orientedFaces[0].recombined() && orientedFaces[1].recombined() &&
760 orientedFaces[2].recombined()) {
763 else if(!orientedFaces[0].recombined() &&
764 !orientedFaces[1].recombined() &&
765 !orientedFaces[2].recombined() &&
766 !orientedFaces[4].recombined() &&
767 !orientedFaces[5].recombined()) {
773 Msg::Error(
"Wrong surface recombination in transfinite volume %d",
779 for(
int i = 1; i < N_i - 1; i++) {
780 for(
int j = 0; j < i; j++) {
781 for(
int k = 0; k < N_k - 1; k++) {
782 if(orientedFaces[0].recombined() && orientedFaces[1].recombined() &&
783 orientedFaces[2].recombined()) {
787 else if(!orientedFaces[0].recombined() &&
788 !orientedFaces[1].recombined() &&
789 !orientedFaces[2].recombined() &&
790 !orientedFaces[4].recombined() &&
791 !orientedFaces[5].recombined()) {
800 Msg::Error(
"Wrong surface recombination in transfinite volume %d",