13 #include "../general/sort_pairs.hpp"
14 #include "../general/text.hpp"
40 default: MFEM_ABORT(
"unsupported geometry " << geom);
47 for (
int i = 0; i <
ne; i++)
49 for (
int j = 0; j < 2; j++)
54 for (
int i = 0; i <
nf; i++)
59 for (
int j = 0; j <
nfv[i]; j++)
70 for (
int i = 0; i <
ne; i++)
81 for (
int i = 0; i <
nv; i++)
101 "Element type " << geom <<
" is not supported by NCMesh.");
114 for (
int i = 0; i < mesh->
GetNE(); i++)
119 CheckSupportedGeom(geom);
124 MFEM_ASSERT(root_id == i,
"");
128 for (
int j = 0; j <
GI[geom].
nv; j++)
131 root_elem.
node[j] = id;
132 nodes.Alloc(
id,
id,
id);
143 nodes.Reparent(triple.one, triple.two, triple.three);
148 nodes.UpdateUnused();
149 for (
int i = 0; i <
elements.Size(); i++)
160 for (
int i = 0; i < mesh->
GetNBE(); i++)
169 face =
faces.Find(v[0], v[1], v[2], v[3]);
172 face =
faces.Find(v[0], v[1], v[2]);
175 face =
faces.Find(v[0], v[0], v[1], v[1]);
178 face =
faces.Find(v[0], v[0], v[0], v[0]);
181 MFEM_ABORT(
"Unsupported boundary element geometry.");
184 MFEM_VERIFY(face,
"Boundary face not found.");
192 for (
int i = 0; i < mesh->
GetNV(); i++)
206 , spaceDim(other.spaceDim)
207 , MyRank(other.MyRank)
210 , Legacy(other.Legacy)
213 , elements(other.elements)
248 for (
int i = 0; i <
elements.Size(); i++)
264 "vert_refc: " << (
int)
vert_refc <<
", edge_refc: "
271 int old_p1 = nd.
p1, old_p2 = nd.
p2;
274 nodes.Reparent(node, new_p1, new_p2);
276 MFEM_ASSERT(
shadow.FindId(old_p1, old_p2) < 0,
277 "shadow node already exists");
280 int sh =
shadow.GetId(old_p1, old_p2);
281 shadow[sh].vert_index = node;
286 int mid =
nodes.FindId(node1, node2);
287 if (mid < 0 &&
shadow.Size())
291 mid =
shadow.FindId(node1, node2);
294 mid =
shadow[mid].vert_index;
303 if (mid < 0) { mid =
nodes.GetId(node1, node2); }
311 if (midf >= 0) {
return midf; }
312 return nodes.GetId(en2, en4);
322 for (
int i = 0; i < gi.
nv; i++)
324 nodes[node[i]].vert_refc++;
328 for (
int i = 0; i < gi.
ne; i++)
330 const int* ev = gi.
edges[i];
331 nodes.Get(node[ev[0]], node[ev[1]])->edge_refc++;
335 for (
int i = 0; i < gi.
nf; i++)
337 const int* fv = gi.
faces[i];
338 faces.GetId(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
353 for (
int i = 0; i < gi.
nf; i++)
355 const int* fv = gi.
faces[i];
356 int face =
faces.FindId(node[fv[0]], node[fv[1]],
357 node[fv[2]], node[fv[3]]);
358 MFEM_ASSERT(face >= 0,
"face not found.");
359 faces[face].ForgetElement(elem);
367 for (
int i = 0; i < gi.
ne; i++)
369 const int* ev = gi.
edges[i];
371 MFEM_ASSERT(enode >= 0,
"edge not found.");
372 MFEM_ASSERT(
nodes.IdExists(enode),
"edge does not exist.");
373 if (!
nodes[enode].UnrefEdge())
380 for (
int i = 0; i < gi.
nv; i++)
382 if (!
nodes[node[i]].UnrefVertex())
384 nodes.Delete(node[i]);
394 for (
int i = 0; i < gi.
nf; i++)
397 MFEM_ASSERT(face,
"face not found.");
399 if (fattr) { face->
attribute = fattr[i]; }
405 for (
int i = 0; i < elemFaces.
Size(); i++)
407 if (
faces[elemFaces[i]].Unused())
409 faces.Delete(elemFaces[i]);
416 if (elem[0] < 0) { elem[0] = e; }
417 else if (elem[1] < 0) { elem[1] = e; }
418 else { MFEM_ABORT(
"can't have 3 elements in Face::elem[]."); }
423 if (elem[0] == e) { elem[0] = -1; }
424 else if (elem[1] == e) { elem[1] = -1; }
425 else { MFEM_ABORT(
"element " << e <<
" not found in Face::elem[]."); }
431 const int* fv = gi.
faces[face_no];
432 int* node = elem.
node;
433 return faces.Find(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
440 MFEM_ASSERT(elem[1] < 0,
"not a single element face.");
445 MFEM_ASSERT(elem[1] >= 0,
"no elements in face.");
454 : geom(geom), ref_type(0), tet_type(0), flag(0),
index(-1)
455 , rank(0), attribute(attr), parent(-1)
457 for (
int i = 0; i < 8; i++) {
node[i] = -1; }
466 int n4,
int n5,
int n6,
int n7,
468 int fattr0,
int fattr1,
int fattr2,
469 int fattr3,
int fattr4,
int fattr5)
481 for (
int i = 0; i < gi_hex.
nf; i++)
483 const int* fv = gi_hex.
faces[i];
496 int n3,
int n4,
int n5,
498 int fattr0,
int fattr1,
499 int fattr2,
int fattr3,
int fattr4)
511 for (
int i = 0; i < gi_wedge.
nf; i++)
513 const int* fv = gi_wedge.
faces[i];
528 int fattr0,
int fattr1,
int fattr2,
int fattr3)
539 for (
int i = 0; i < gi_tet.
nf; i++)
541 const int* fv = gi_tet.
faces[i];
555 int eattr0,
int eattr1,
int eattr2,
int eattr3)
566 for (
int i = 0; i < gi_quad.
nf; i++)
568 const int* fv = gi_quad.
faces[i];
580 int attr,
int eattr0,
int eattr1,
int eattr2)
591 for (
int i = 0; i < gi_tri.
nf; i++)
593 const int* fv = gi_tri.
faces[i];
613 int v0 = el.
node[0], v1 = el.
node[1];
614 faces.Get(v0, v0, v0, v0)->attribute = vattr1;
615 faces.Get(v1, v1, v1, v1)->attribute = vattr2;
621 {
return node == n[0] || node == n[3] || node == n[4] || node == n[7]; }
624 {
return node == n[1] || node == n[2] || node == n[5] || node == n[6]; }
627 {
return node == n[0] || node == n[1] || node == n[4] || node == n[5]; }
630 {
return node == n[2] || node == n[3] || node == n[6] || node == n[7]; }
633 {
return node == n[0] || node == n[1] || node == n[2] || node == n[3]; }
636 {
return node == n[4] || node == n[5] || node == n[6] || node == n[7]; }
639 {
return node == n[0] || node == n[1] || node == n[2]; }
642 {
return node == n[3] || node == n[4] || node == n[5]; }
648 Face* face =
faces.Find(vn1, vn2, vn3, vn4);
649 if (!face) {
return; }
653 MFEM_ASSERT(!el.
ref_type,
"element already refined.");
655 int* el_nodes = el.
node;
676 MFEM_ABORT(
"Inconsistent element/face structure.");
693 MFEM_ABORT(
"Inconsistent element/face structure.");
698 MFEM_ABORT(
"Unsupported geometry.")
711 int ev1 = vn1, ev2 = vn4;
719 vn2 = mid[0]; vn3 = mid[2];
723 vn3 = mid[1]; vn4 = mid[3];
727 const Face *face =
faces.Find(vn1, vn2, vn3, vn4);
728 MFEM_ASSERT(face != NULL,
"Face not found: "
729 << vn1 <<
", " << vn2 <<
", " << vn3 <<
", " << vn4
730 <<
" (edge " << ev1 <<
"-" << ev2 <<
").");
739 for (
int i = 0; i < cousins.
Size(); i++)
758 for (
int i = 0, j; i < eid.
Size(); i++)
760 int elem = eid[i].element;
761 for (j = 0; j < nref; j++)
763 if (refs[j].
index == elem) {
break; }
776 int mid12,
int mid34,
int level)
804 if (mid23 >= 0 && mid41 >= 0)
806 int midf =
nodes.FindId(mid23, mid41);
835 for (
int i = 0; i <
reparents.Size(); i++)
871 int en1,
int en2,
int en3,
int en4,
int midf)
889 if (!ref_type) {
return; }
895 char remaining = ref_type & ~el.
ref_type;
898 for (
int i = 0; i < 8; i++)
916 for (
int i = 0; i < 8; i++) { child[i] = -1; }
921 for (
int i = 0; i < gi.
nf; i++)
923 const int* fv = gi.
faces[i];
924 Face* face =
faces.Find(no[fv[0]], no[fv[1]], no[fv[2]], no[fv[3]]);
953 no[4], mid45, mid67, no[7], attr,
954 fa[0], fa[1], -1, fa[3], fa[4], fa[5]);
957 mid45, no[5], no[6], mid67, attr,
958 fa[0], fa[1], fa[2], fa[3], -1, fa[5]);
973 no[4], no[5], mid56, mid74, attr,
974 fa[0], fa[1], fa[2], -1, fa[4], fa[5]);
977 mid74, mid56, no[6], no[7], attr,
978 fa[0], -1, fa[2], fa[3], fa[4], fa[5]);
993 mid04, mid15, mid26, mid37, attr,
994 fa[0], fa[1], fa[2], fa[3], fa[4], -1);
997 no[4], no[5], no[6], no[7], attr,
998 -1, fa[1], fa[2], fa[3], fa[4], fa[5]);
1021 no[4], mid45, midf5, mid74, attr,
1022 fa[0], fa[1], -1, -1, fa[4], fa[5]);
1025 mid45, no[5], mid56, midf5, attr,
1026 fa[0], fa[1], fa[2], -1, -1, fa[5]);
1029 midf5, mid56, no[6], mid67, attr,
1030 fa[0], -1, fa[2], fa[3], -1, fa[5]);
1033 mid74, midf5, mid67, no[7], attr,
1034 fa[0], -1, -1, fa[3], fa[4], fa[5]);
1041 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
1042 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
1060 mid04, midf1, midf3, mid37, attr,
1061 fa[0], fa[1], -1, fa[3], fa[4], -1);
1064 midf1, mid15, mid26, midf3, attr,
1065 fa[0], fa[1], fa[2], fa[3], -1, -1);
1068 mid45, no[5], no[6], mid67, attr,
1069 -1, fa[1], fa[2], fa[3], -1, fa[5]);
1072 no[4], mid45, mid67, no[7], attr,
1073 -1, fa[1], -1, fa[3], fa[4], fa[5]);
1080 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
1081 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
1099 mid04, mid15, midf2, midf4, attr,
1100 fa[0], fa[1], fa[2], -1, fa[4], -1);
1103 midf4, midf2, mid26, mid37, attr,
1104 fa[0], -1, fa[2], fa[3], fa[4], -1);
1107 no[4], no[5], mid56, mid74, attr,
1108 -1, fa[1], fa[2], -1, fa[4], fa[5]);
1111 mid74, mid56, no[6], no[7], attr,
1112 -1, -1, fa[2], fa[3], fa[4], fa[5]);
1119 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
1120 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
1149 mid04, midf1, midel, midf4, attr,
1150 fa[0], fa[1], -1, -1, fa[4], -1);
1153 midf1, mid15, midf2, midel, attr,
1154 fa[0], fa[1], fa[2], -1, -1, -1);
1157 midel, midf2, mid26, midf3, attr,
1158 fa[0], -1, fa[2], fa[3], -1, -1);
1161 midf4, midel, midf3, mid37, attr,
1162 fa[0], -1, -1, fa[3], fa[4], -1);
1165 no[4], mid45, midf5, mid74, attr,
1166 -1, fa[1], -1, -1, fa[4], fa[5]);
1169 mid45, no[5], mid56, midf5, attr,
1170 -1, fa[1], fa[2], -1, -1, fa[5]);
1173 midf5, mid56, no[6], mid67, attr,
1174 -1, -1, fa[2], fa[3], -1, fa[5]);
1177 mid74, midf5, mid67, no[7], attr,
1178 -1, -1, -1, fa[3], fa[4], fa[5]);
1180 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
1181 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
1182 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
1183 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
1184 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
1185 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
1189 MFEM_ABORT(
"invalid refinement type.");
1222 child[0] =
NewWedge(no[0], mid01, mid20,
1223 no[3], mid34, mid53, attr,
1224 fa[0], fa[1], fa[2], -1, fa[4]);
1226 child[1] =
NewWedge(mid01, no[1], mid12,
1227 mid34, no[4], mid45, attr,
1228 fa[0], fa[1], fa[2], fa[3], -1);
1230 child[2] =
NewWedge(mid20, mid12, no[2],
1231 mid53, mid45, no[5], attr,
1232 fa[0], fa[1], -1, fa[3], fa[4]);
1234 child[3] =
NewWedge(mid12, mid20, mid01,
1235 mid45, mid53, mid34, attr,
1236 fa[0], fa[1], -1, -1, -1);
1248 child[0] =
NewWedge(no[0], no[1], no[2],
1249 mid03, mid14, mid25, attr,
1250 fa[0], -1, fa[2], fa[3], fa[4]);
1252 child[1] =
NewWedge(mid03, mid14, mid25,
1253 no[3], no[4], no[5], attr,
1254 -1, fa[1], fa[2], fa[3], fa[4]);
1280 child[0] =
NewWedge(no[0], mid01, mid20,
1281 mid03, midf2, midf4, attr,
1282 fa[0], -1, fa[2], -1, fa[4]);
1284 child[1] =
NewWedge(mid01, no[1], mid12,
1285 midf2, mid14, midf3, attr,
1286 fa[0], -1, fa[2], fa[3], -1);
1288 child[2] =
NewWedge(mid20, mid12, no[2],
1289 midf4, midf3, mid25, attr,
1290 fa[0], -1, -1, fa[3], fa[4]);
1292 child[3] =
NewWedge(mid12, mid20, mid01,
1293 midf3, midf4, midf2, attr,
1294 fa[0], -1, -1, -1, -1);
1296 child[4] =
NewWedge(mid03, midf2, midf4,
1297 no[3], mid34, mid53, attr,
1298 -1, fa[1], fa[2], -1, fa[4]);
1300 child[5] =
NewWedge(midf2, mid14, midf3,
1301 mid34, no[4], mid45, attr,
1302 -1, fa[1], fa[2], fa[3], -1);
1304 child[6] =
NewWedge(midf4, midf3, mid25,
1305 mid53, mid45, no[5], attr,
1306 -1, fa[1], -1, fa[3], fa[4]);
1308 child[7] =
NewWedge(midf3, midf4, midf2,
1309 mid45, mid53, mid34, attr,
1310 -1, fa[1], -1, -1, -1);
1312 CheckIsoFace(no[0], no[1], no[4], no[3], mid01, mid14, mid34, mid03, midf2);
1313 CheckIsoFace(no[1], no[2], no[5], no[4], mid12, mid25, mid45, mid14, midf3);
1314 CheckIsoFace(no[2], no[0], no[3], no[5], mid20, mid03, mid53, mid25, midf4);
1345 -1, fa[1], fa[2], fa[3]);
1348 fa[0], -1, fa[2], fa[3]);
1351 fa[0], fa[1], -1, fa[3]);
1354 fa[0], fa[1], fa[2], -1);
1413 int mid01 =
nodes.GetId(no[0], no[1]);
1414 int mid23 =
nodes.GetId(no[2], no[3]);
1417 attr, fa[0], -1, fa[2], fa[3]);
1420 attr, fa[0], fa[1], fa[2], -1);
1424 int mid12 =
nodes.GetId(no[1], no[2]);
1425 int mid30 =
nodes.GetId(no[3], no[0]);
1428 attr, fa[0], fa[1], -1, fa[3]);
1431 attr, -1, fa[1], fa[2], fa[3]);
1435 int mid01 =
nodes.GetId(no[0], no[1]);
1436 int mid12 =
nodes.GetId(no[1], no[2]);
1437 int mid23 =
nodes.GetId(no[2], no[3]);
1438 int mid30 =
nodes.GetId(no[3], no[0]);
1440 int midel =
nodes.GetId(mid01, mid23);
1443 attr, fa[0], -1, -1, fa[3]);
1446 attr, fa[0], fa[1], -1, -1);
1449 attr, -1, fa[1], fa[2], -1);
1452 attr, -1, -1, fa[2], fa[3]);
1456 MFEM_ABORT(
"Invalid refinement type.");
1466 int mid01 =
nodes.GetId(no[0], no[1]);
1467 int mid12 =
nodes.GetId(no[1], no[2]);
1468 int mid20 =
nodes.GetId(no[2], no[0]);
1470 child[0] =
NewTriangle(no[0], mid01, mid20, attr, fa[0], -1, fa[2]);
1471 child[1] =
NewTriangle(mid01, no[1], mid12, attr, fa[0], fa[1], -1);
1472 child[2] =
NewTriangle(mid20, mid12, no[2], attr, -1, fa[1], fa[2]);
1473 child[3] =
NewTriangle(mid12, mid20, mid01, attr, -1, -1, -1);
1479 int mid =
nodes.GetId(no[0], no[1]);
1480 child[0] =
NewSegment(no[0], mid, attr, fa[0], -1);
1481 child[1] =
NewSegment(mid, no[1], attr, -1, fa[1]);
1485 MFEM_ABORT(
"Unsupported element geometry.");
1489 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1502 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1511 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1520 std::memcpy(el.
child, child,
sizeof(el.
child));
1528 for (
int i = refinements.
Size()-1; i >= 0; i--)
1556 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
1557 mfem::out <<
"Refined " << refinements.
Size() <<
" + " << nforced
1558 <<
" elements" << std::endl;
1560 MFEM_CONTRACT_VAR(nforced);
1587 MFEM_ASSERT(ch != -1,
"");
1602 MFEM_ABORT(
"Unsupported element geometry.");
1614 std::memcpy(child, el.
child,
sizeof(child));
1617 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1625 int faces_attribute[6];
1626 int ref_type_key = el.
ref_type - 1;
1628 for (
int i = 0; i < 8; i++) { el.
node[i] = -1; }
1634 constexpr
int nb_cube_childs = 8;
1635 for (
int i = 0; i < nb_cube_childs; i++)
1637 const int child_local_index = hex_deref_table[ref_type_key][i];
1638 const int child_global_index = child[child_local_index];
1643 constexpr
int nb_cube_faces = 6;
1644 for (
int i = 0; i < nb_cube_faces; i++)
1646 const int child_local_index = hex_deref_table[ref_type_key]
1647 [i + nb_cube_childs];
1648 const int child_global_index = child[child_local_index];
1651 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1658 MFEM_ASSERT(prism_deref_table[ref_type_key][0] != -1,
1659 "invalid prism refinement");
1660 constexpr
int nb_prism_childs = 6;
1661 for (
int i = 0; i < nb_prism_childs; i++)
1663 const int child_local_index = prism_deref_table[ref_type_key][i];
1664 const int child_global_index = child[child_local_index];
1670 constexpr
int nb_prism_faces = 5;
1671 for (
int i = 0; i < nb_prism_faces; i++)
1673 const int child_local_index = prism_deref_table[ref_type_key]
1674 [i + nb_prism_childs];
1675 const int child_global_index = child[child_local_index];
1678 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1685 for (
int i = 0; i < 4; i++)
1691 faces_attribute[i] =
faces.Find(ch2.
node[fv[0]], ch2.
node[fv[1]],
1698 constexpr
int nb_square_childs = 4;
1699 for (
int i = 0; i < nb_square_childs; i++)
1701 const int child_local_index = quad_deref_table[ref_type_key][i];
1702 const int child_global_index = child[child_local_index];
1706 constexpr
int nb_square_faces = 4;
1707 for (
int i = 0; i < nb_square_faces; i++)
1709 const int child_local_index = quad_deref_table[ref_type_key]
1710 [i + nb_square_childs];
1711 const int child_global_index = child[child_local_index];
1714 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1721 constexpr
int nb_triangle_childs = 3;
1722 for (
int i = 0; i < nb_triangle_childs; i++)
1727 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1734 constexpr
int nb_segment_childs = 2;
1735 for (
int i = 0; i < nb_segment_childs; i++)
1737 int ni =
elements[child[i]].node[i];
1739 faces_attribute[i] =
faces.Find(ni, ni, ni, ni)->attribute;
1744 MFEM_ABORT(
"Unsupported element geometry.");
1755 el.
rank = std::numeric_limits<int>::max();
1756 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1779 int total = 0, ref = 0, ghost = 0;
1780 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1788 if (!ref && ghost < total)
1791 int next_row = list.
Size() ? (list.
Last().from + 1) : 0;
1792 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1800 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1817 int size = list.
Size() ? (list.
Last().from + 1) : 0;
1826 for (
int i = 0; i < deref_table.
Size(); i++)
1828 const int* fine = deref_table.
GetRow(i), size = deref_table.
RowSize(i);
1832 for (
int j = 0; j < size; j++)
1837 for (
int k = 0; k <
Dim; k++)
1839 if ((parent.
ref_type & (1 << k)) &&
1840 splits[k] >= max_nc_level)
1853 MFEM_VERIFY(
Dim < 3 ||
Iso,
1854 "derefinement of 3D anisotropic meshes not implemented yet.");
1862 for (
int i = 0; i < derefs.
Size(); i++)
1864 int row = derefs[i];
1866 "invalid derefinement number.");
1881 for (
int i = 0; i < fine_coarse.
Size(); i++)
1895 for (
int i = 0; i < nfine; i++)
1910 for (
int i = 0; i < 8 && prn.
child[i] >= 0; i++)
1915 int code = (prn.
ref_type << 4) | i;
1917 fine_coarse[ch.
index] = parent;
1945 el.
index = counter++;
1964 for (
int i = 0; i < 4; i++)
1966 int ch = quad_hilbert_child_order[state][i];
1967 int st = quad_hilbert_child_state[state][i];
1973 for (
int i = 0; i < 8; i++)
1975 int ch = hex_hilbert_child_order[state][i];
1976 int st = hex_hilbert_child_state[state][i];
1982 for (
int i = 0; i < 8; i++)
1984 if (el.
child[i] >= 0)
2023 #ifndef MFEM_NCMESH_OLD_VERTEX_ORDERING
2049 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2051 node->vert_index = -4;
2057 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2081 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2083 if (node->vert_index == -1)
2093 for (
int i = 0; i < sfc_order.Size(); i++)
2098 for (
int i = 0; i < sfc_order.Size(); i++)
2101 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2111 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2113 if (node->HasVertex() && node->vert_index >= 0)
2124 for (
int i = 0; i < sfc_order.Size(); i++)
2127 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2137 #else // old ordering for debugging/testing only
2138 bool parallel =
false;
2140 if (dynamic_cast<ParNCMesh*>(
this)) { parallel =
true; }
2146 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2148 if (node->HasVertex()) { node->vert_index =
NVertices++; }
2154 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2161 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2163 if (node->HasVertex()) { node->vert_index = -1; }
2172 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2174 int &vindex =
nodes[el.
node[j]].vert_index;
2175 if (vindex < 0) { vindex =
NVertices++; }
2181 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2183 if (node->HasVertex() && node->vert_index >= 0)
2190 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2192 if (node->HasVertex() && node->vert_index < 0)
2213 node_order = (
char*) quad_hilbert_child_order;
2218 node_order = (
char*) hex_hilbert_child_order;
2225 int entry_node = -2;
2228 for (
int i = 0; i < root_count; i++)
2233 if (v_in < 0) { v_in = 0; }
2236 bool shared[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2237 if (i+1 < root_count)
2240 for (
int j = 0; j < nch; j++)
2243 if (node >= 0) { shared[node] =
true; }
2248 int state =
Dim*v_in;
2249 for (
int j = 0; j <
Dim; j++)
2251 if (shared[(
int) node_order[nch*(state + j) + nch-1]])
2260 entry_node =
RetrieveNode(el, node_order[nch*state + nch-1]);
2274 MFEM_ABORT(
"invalid geometry");
2289 MFEM_VERIFY(tv.
visited ==
false,
"cyclic vertex dependencies.");
2295 for (
int i = 0; i < 3; i++)
2297 tv.
pos[i] = (pos1[i] + pos2[i]) * 0.5;
2310 for (
int i = 0; i < mesh.
vertices.Size(); i++)
2329 const int* node = nc_elem.
node;
2336 for (
int j = 0; j < gi.
nv; j++)
2338 elem->GetVertices()[j] =
nodes[node[j]].vert_index;
2343 for (
int k = 0; k < gi.
nf; k++)
2345 const int* fv = gi.
faces[k];
2346 const int nfv = gi.
nfv[k];
2347 const Face* face =
faces.Find(node[fv[0]], node[fv[1]],
2348 node[fv[2]], node[fv[3]]);
2356 for (
int j = 0; j < 4; j++)
2358 quad->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2365 MFEM_ASSERT(nfv == 3,
"");
2368 for (
int j = 0; j < 3; j++)
2370 tri->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2379 for (
int j = 0; j < 2; j++)
2381 segment->GetVertices()[j] =
nodes[node[fv[2*j]]].vert_index;
2390 point->GetVertices()[0] =
nodes[node[fv[0]]].vert_index;
2406 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2408 if (node->HasEdge()) { node->edge_index = -1; }
2410 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2417 for (
int i = 0; i < edge_vertex->
Size(); i++)
2419 const int *ev = edge_vertex->
GetRow(i);
2422 MFEM_ASSERT(node && node->
HasEdge(),
2423 "edge (" << ev[0] <<
"," << ev[1] <<
") not found, "
2431 for (
int i = 0; i <
NFaces; i++)
2433 const int* fv = mesh->
GetFace(i)->GetVertices();
2434 const int nfv = mesh->
GetFace(i)->GetNVertices();
2447 MFEM_ASSERT(nfv == 3,
"");
2455 MFEM_ASSERT(nfv == 2,
"");
2458 face =
faces.Find(n0, n0, n1, n1);
2462 const int *ev = edge_vertex->
GetRow(i);
2463 MFEM_ASSERT((ev[0] == fv[0] && ev[1] == fv[1]) ||
2464 (ev[1] == fv[0] && ev[0] == fv[1]),
"");
2468 MFEM_VERIFY(face,
"face not found.");
2476 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2478 if (node->HasEdge() && node->edge_index < 0)
2486 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2494 MFEM_ASSERT(NFaces ==
NEdges,
"");
2509 for (
int j = 0; j < gi.
nf; j++)
2511 const int *fv = gi.
faces[j];
2514 MFEM_ASSERT(face,
"face not found!");
2516 if (face->
index < 0)
2518 face->
index = NFaces + (nghosts++);
2532 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2534 if (face->index < 0) { face->index = NFaces + (nghosts++); }
2545 MFEM_ASSERT(
Dim >= 3,
"");
2554 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3, mid[3] = e4; }
2557 int midf1 = -1, midf2 = -1;
2562 if (midf1 >= 0 && midf1 == midf2)
2565 if (nd.
p1 != e1 && nd.
p2 != e1) { midf1 = -1; }
2566 if (nd.
p1 != e2 && nd.
p2 != e2) { midf2 = -1; }
2570 MFEM_ASSERT(!(midf1 >= 0 && midf2 >= 0),
"incorrectly split face!");
2572 if (midf1 < 0 && midf2 < 0)
2574 if (mid) { mid[4] = -1; }
2577 else if (midf1 >= 0)
2579 if (mid) { mid[4] = midf1; }
2584 if (mid) { mid[4] = midf2; }
2591 int e1 =
nodes.FindId(v1, v2);
2592 if (e1 < 0 || !
nodes[e1].HasVertex()) {
return false; }
2594 int e2 =
nodes.FindId(v2, v3);
2595 if (e2 < 0 || !
nodes[e2].HasVertex()) {
return false; }
2597 int e3 =
nodes.FindId(v3, v1);
2598 if (e3 < 0 || !
nodes[e3].HasVertex()) {
return false; }
2600 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3; }
2608 for (
int i = 0; i < 8; i++)
2610 if (el.
node[i] == node) {
return i; }
2612 MFEM_ABORT(
"Node not found.");
2618 for (
int i = 0; i <
GI[el.
Geom()].
nv; i++)
2622 if (abort) { MFEM_ABORT(
"Node not found."); }
2631 for (
int i = 0; i < gi.
ne; i++)
2633 const int* ev = gi.
edges[i];
2634 int n0 = el.
node[ev[0]];
2635 int n1 = el.
node[ev[1]];
2636 if ((n0 == vn0 && n1 == vn1) ||
2637 (n0 == vn1 && n1 == vn0)) {
return i; }
2640 if (abort) { MFEM_ABORT(
"Edge (" << vn0 <<
", " << vn1 <<
") not found"); }
2647 for (
int i = 0; i < gi.
nf; i++)
2649 const int* fv = gi.
faces[i];
2650 if ((a == fv[0] || a == fv[1] || a == fv[2] || a == fv[3]) &&
2651 (b == fv[0] || b == fv[1] || b == fv[2] || b == fv[3]) &&
2652 (c == fv[0] || c == fv[1] || c == fv[2] || c == fv[3]))
2657 MFEM_ABORT(
"Face not found.");
2667 MFEM_ASSERT(
sizeof(
double) ==
sizeof(std::uint64_t),
"");
2671 std::uint64_t hash = 0xf9ca9ba106acbba9;
2672 for (
int i = 0; i < pm.
np; i++)
2674 for (
int j = 0; j < pm.
points[i].
dim; j++)
2679 hash = 31*hash + *((std::uint64_t*) &coord);
2691 int GetIndex(
const NCMesh::PointMatrix &pm)
2693 int &
index = map[pm];
2694 if (!index) { index = map.size(); }
2698 void ExportMatrices(Array<DenseMatrix*> &point_matrices)
const
2700 point_matrices.SetSize(map.size());
2701 for (
const auto &pair : map)
2703 DenseMatrix* mat =
new DenseMatrix();
2704 pair.first.GetMatrix(*mat);
2705 point_matrices[pair.second - 1] = mat;
2709 void DumpBucketSizes()
const
2711 for (
unsigned i = 0; i < map.bucket_count(); i++)
2718 std::unordered_map<NCMesh::PointMatrix, int, PointMatrixHash> map;
2732 int nfv = (v3 >= 0) ? 4 : 3;
2737 reordered.
np = pm.
np;
2738 for (
int i = 0, j; i < nfv; i++)
2740 for (j = 0; j < nfv; j++)
2742 if (fv[i] == master[j])
2748 MFEM_ASSERT(j != nfv,
"node not found.");
2760 Face* fa =
faces.Find(vn0, vn1, vn2, vn3);
2772 sl.
matrix = matrix_map.GetIndex(pm_r);
2774 eface[0] = eface[2] = fa;
2775 eface[1] = eface[3] = fa;
2788 Point pmid0(pm(0), pm(1)), pmid2(pm(2), pm(3));
2792 level+1, ef[0], matrix_map);
2796 level+1, ef[1], matrix_map);
2798 eface[1] = ef[1][1];
2799 eface[3] = ef[0][3];
2800 eface[0] = eface[2] = NULL;
2802 else if (split == 2)
2804 Point pmid1(pm(1), pm(2)), pmid3(pm(3), pm(0));
2808 level+1, ef[0], matrix_map);
2812 level+1, ef[1], matrix_map);
2814 eface[0] = ef[0][0];
2815 eface[2] = ef[1][2];
2816 eface[1] = eface[3] = NULL;
2827 const int fi[3][2] = {{0, 0}, {1, 3}, {2, 0}};
2828 if (!ef[0][fi[split][0]] && !ef[1][fi[split][1]])
2838 MFEM_ASSERT(eid.
Size() > 0,
"edge prism not found");
2839 MFEM_ASSERT(eid.
Size() < 2,
"non-unique edge prism");
2849 Point mid0(pm(0), pm(1)), mid2(pm(2), pm(3));
2850 int v1 =
nodes[mid[0]].vert_index;
2851 int v2 =
nodes[mid[2]].vert_index;
2853 matrix_map.GetIndex(
2859 Point mid1(pm(1), pm(2)), mid3(pm(3), pm(0));
2860 int v1 =
nodes[mid[1]].vert_index;
2861 int v2 =
nodes[mid[3]].vert_index;
2863 matrix_map.GetIndex(
2875 int mid =
nodes.FindId(vn0, vn1);
2876 if (mid < 0) {
return; }
2892 int v0index =
nodes[vn0].vert_index;
2893 int v1index =
nodes[vn1].vert_index;
2896 matrix_map.GetIndex((v0index < v1index) ?
PointMatrix(p0, p1, p0)
2928 sl.
matrix = matrix_map.GetIndex(pm_r);
2937 Point pmid0(pm(0), pm(1)), pmid1(pm(1), pm(2)), pmid2(pm(2), pm(0));
2942 level+1, matrix_map);
2946 level+1, matrix_map);
2950 level+1, matrix_map);
2954 level+1, matrix_map);
2959 if (!b[1]) {
TraverseTetEdge(mid[0],mid[1], pmid0,pmid1, matrix_map); }
2960 if (!b[2]) {
TraverseTetEdge(mid[1],mid[2], pmid1,pmid2, matrix_map); }
2961 if (!b[0]) {
TraverseTetEdge(mid[2],mid[0], pmid2,pmid0, matrix_map); }
2971 if (
Dim < 3) {
return; }
2978 processed_faces = 0;
2987 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
2990 for (
int j = 0; j < gi.
nf; j++)
2994 for (
int k = 0; k < 4; k++)
2999 int face =
faces.FindId(node[0], node[1], node[2], node[3]);
3000 MFEM_ASSERT(face >= 0,
"face not found!");
3006 if (processed_faces[face]) {
continue; }
3007 processed_faces[face] = 1;
3012 if (fa.
elem[0] >= 0 && fa.
elem[1] >= 0)
3042 for (
int ii = sb; ii < se; ii++)
3063 int mid =
nodes.FindId(vn0, vn1);
3064 if (mid < 0) {
return; }
3067 if (nd.
HasEdge() && level > 0)
3077 int v0index =
nodes[vn0].vert_index;
3078 int v1index =
nodes[vn1].vert_index;
3079 if (v0index > v1index) { sl.
edge_flags |= 2; }
3083 double tmid = (t0 + t1) / 2;
3084 TraverseEdge(vn0, mid, t0, tmid, flags, level+1, matrix_map);
3085 TraverseEdge(mid, vn1, tmid, t1, flags, level+1, matrix_map);
3094 processed_edges = 0;
3107 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3110 for (
int j = 0; j < gi.
ne; j++)
3113 const int* ev = gi.
edges[j];
3114 int node[2] = { el.
node[ev[0]], el.
node[ev[1]] };
3116 int enode =
nodes.FindId(node[0], node[1]);
3117 MFEM_ASSERT(enode >= 0,
"edge node not found!");
3120 MFEM_ASSERT(nd.
HasEdge(),
"edge not found!");
3128 int face =
faces.FindId(node[0], node[0], node[1], node[1]);
3129 MFEM_ASSERT(face >= 0,
"face not found!");
3141 if (processed_edges[enode]) {
continue; }
3142 processed_edges[enode] = 1;
3145 double t0 = 0.0, t1 = 1.0;
3146 int v0index =
nodes[node[0]].vert_index;
3147 int v1index =
nodes[node[1]].vert_index;
3148 int flags = (v0index > v1index) ? 1 : 0;
3152 TraverseEdge(node[0], node[1], t0, t1, flags, 0, matrix_map);
3162 for (
int ii = sb; ii < se; ii++)
3179 int local = edge_local[sl.
index];
3199 processed_vertices = 0;
3207 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
3209 int node = el.
node[j];
3217 if (processed_vertices[index]) {
continue; }
3218 processed_vertices[
index] = 1;
3229 oriented_matrix = *(point_matrices[slave.
Geom()][slave.
matrix]);
3233 MFEM_ASSERT(oriented_matrix.
Height() == 1 &&
3234 oriented_matrix.
Width() == 2,
"not an edge point matrix");
3238 oriented_matrix(0,0) = 1.0 - oriented_matrix(0,0);
3239 oriented_matrix(0,1) = 1.0 - oriented_matrix(0,1);
3243 std::swap(oriented_matrix(0,0), oriented_matrix(0,1));
3250 conforming.DeleteAll();
3251 masters.DeleteAll();
3256 for (
int j = 0; j < point_matrices[i].Size(); j++)
3258 delete point_matrices[i][j];
3260 point_matrices[i].DeleteAll();
3263 inv_index.DeleteAll();
3268 return conforming.Size() + masters.Size() + slaves.Size();
3273 if (!inv_index.Size())
3276 for (
int i = 0; i < conforming.Size(); i++)
3278 max_index = std::max(conforming[i].index, max_index);
3280 for (
int i = 0; i < masters.Size(); i++)
3282 max_index = std::max(masters[i].index, max_index);
3284 for (
int i = 0; i < slaves.Size(); i++)
3286 if (slaves[i].index < 0) {
continue; }
3287 max_index = std::max(slaves[i].index, max_index);
3290 inv_index.SetSize(max_index + 1);
3293 for (
int i = 0; i < conforming.Size(); i++)
3295 inv_index[conforming[i].index] = (i << 2);
3297 for (
int i = 0; i < masters.Size(); i++)
3299 inv_index[masters[i].index] = (i << 2) + 1;
3301 for (
int i = 0; i < slaves.Size(); i++)
3303 if (slaves[i].index < 0) {
continue; }
3304 inv_index[slaves[i].index] = (i << 2) + 2;
3308 MFEM_ASSERT(index >= 0 && index < inv_index.Size(),
"");
3309 int key = inv_index[
index];
3313 MFEM_VERIFY(key >= 0,
"entity not found.");
3317 *type = (key >= 0) ? (key & 0x3) : -1;
3320 if (*type < 0) {
return invalid; }
3326 case 0:
return conforming[key >> 2];
3327 case 1:
return masters[key >> 2];
3328 case 2:
return slaves[key >> 2];
3329 default: MFEM_ABORT(
"internal error");
return conforming[0];
3338 int mid =
nodes.FindId(v0, v1);
3339 if (mid >= 0 &&
nodes[mid].HasVertex())
3353 for (
int i = 0; i < 3; i++)
3410 int** JJ =
new int*[nrows];
3420 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3423 int* node = el.
node;
3426 for (
int j = 0; j < gi.
ne; j++)
3428 const int* ev = gi.
edges[j];
3434 for (
int j = 0; j < gi.
nf; j++)
3436 const int* fv = gi.
faces[j];
3440 node[fv[2]], node[fv[3]], indices);
3453 int size = indices.
Size();
3455 JJ[i] =
new int[size];
3456 std::memcpy(JJ[i], indices.
GetData(), size *
sizeof(int));
3461 for (
int i = 0; i < nrows; i++)
3472 for (
int i = 0; i < nrows; i++)
3474 int cnt = I[i+1] - I[i];
3475 std::memcpy(J+nnz, JJ[i], cnt *
sizeof(
int));
3502 MFEM_VERIFY(elem_set.
Size() == nleaves,
"");
3511 for (
int i = 0; i < nleaves; i++)
3517 for (
int j = 0; j < nv; j++)
3524 for (
int j = 0; j < nv; j++)
3526 vmark[el.
node[j]] = 1;
3537 neighbor_set->
SetSize(nleaves);
3541 for (
int i = 0; i < nleaves; i++)
3549 for (
int j = 0; j < nv; j++)
3551 if (vmark[v[j]]) { hit =
true;
break; }
3558 for (
int j = 0; j < nv; j++)
3560 if (vmark[el.
node[j]]) { hit =
true;
break; }
3567 if (neighbor_set) { (*neighbor_set)[i] = 1; }
3573 static bool sorted_lists_intersect(
const int*
a,
const int*
b,
int na,
int nb)
3575 if (!na || !nb) {
return false; }
3576 int a_last = a[na-1], b_last = b[nb-1];
3577 if (*b < *a) {
goto l2; }
3579 if (a_last < *b) {
return false; }
3580 while (*a < *b) { a++; }
3581 if (*a == *b) {
return true; }
3583 if (b_last < *a) {
return false; }
3584 while (*b < *a) { b++; }
3585 if (*a == *b) {
return true; }
3608 while (stack.
Size())
3617 for (
int i = 0; i < nv; i++)
3623 for (
int i = 0; i < nv; i++)
3630 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
3641 int nv1 = vert.
Size();
3646 for (
int i = 0; i < search_set->
Size(); i++)
3648 int testme = (*search_set)[i];
3655 bool hit = sorted_lists_intersect(v1, v2, nv1, nv2);
3660 for (
int j = 0; j < nv; j++)
3662 hit = sorted_lists_intersect(&el.
node[j], v1, 1, nv1);
3667 if (hit) { neighbors.
Append(testme); }
3681 for (
int i = 0; i < elems.
Size(); i++)
3687 for (
int j = 0; j < nv; j++)
3693 for (
int j = 0; j < nv; j++)
3695 vmark[el.
node[j]] = 1;
3705 for (
int i = 0; i < search_set->
Size(); i++)
3707 int testme = (*search_set)[i];
3713 for (
int j = 0; j < nv; j++)
3715 if (vmark[v[j]]) { hit =
true;
break; }
3721 for (
int j = 0; j < nv; j++)
3723 if (vmark[el.
node[j]]) { hit =
true;
break; }
3727 if (hit) { expanded.
Append(testme); }
3736 if (el.
parent < 0) {
return elem; }
3739 MFEM_ASSERT(pa.
ref_type,
"internal error");
3742 while (ch < 8 && pa.
child[ch] != elem) { ch++; }
3743 MFEM_ASSERT(ch < 8,
"internal error");
3745 MFEM_ASSERT(geom_parent[el.
Geom()],
"unsupported geometry");
3746 const RefTrf &tr = geom_parent[el.
Geom()][(int) pa.
ref_type][ch];
3747 tr.Apply(coord, coord);
3758 return (pt[0] >= 0) && (pt[0] <= T_ONE) &&
3759 (pt[1] >= 0) && (pt[1] <= T_ONE);
3762 return (pt[0] >= 0) && (pt[0] <= T_ONE) &&
3763 (pt[1] >= 0) && (pt[1] <= T_ONE) &&
3764 (pt[2] >= 0) && (pt[2] <= T_ONE);
3767 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE);
3770 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE) &&
3771 (pt[2] >= 0) && (pt[2] <= T_ONE);
3774 MFEM_ABORT(
"unsupported geometry");
3790 for (
int ch = 0; ch < 8 && el.
child[ch] >= 0; ch++)
3792 const RefTrf &tr = geom_child[el.
Geom()][(int) el.
ref_type][ch];
3793 tr.Apply(coord, tcoord);
3795 if (RefPointInside(el.
Geom(), tcoord))
3807 MFEM_ASSERT(geom_corners[el.
Geom()],
"unsupported geometry");
3808 std::memcpy(coord, geom_corners[el.
Geom()][local],
sizeof(coord));
3821 MFEM_ASSERT(np == pm.
np,
"");
3822 for (
int i = 0; i < np; i++)
3825 for (
int j = 0; j < points[i].dim; j++)
3827 if (points[i].coord[j] != pm.
points[i].
coord[j]) {
return false; }
3836 for (
int i = 0; i < np; i++)
3838 for (
int j = 0; j < points[0].dim; j++)
3840 point_matrix(j, i) = points[i].coord[j];
3855 Point(0, 0, 0),
Point(1, 0, 0),
Point(0, 1, 0),
Point(0, 0, 1)
3862 Point(0, 0, 0),
Point(1, 0, 0),
Point(1, 1, 0),
Point(0, 1, 0),
3863 Point(0, 0, 1),
Point(1, 0, 1),
Point(1, 1, 1),
Point(0, 1, 1)
3877 MFEM_ABORT(
"unsupported geometry " << geom);
3889 int ref_type = *ref_path++;
3890 int child = *ref_path++;
3898 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3899 Point mid67(pm(6), pm(7)), mid45(pm(4), pm(5));
3904 pm(4), mid45, mid67, pm(7));
3906 else if (child == 1)
3909 mid45, pm(5), pm(6), mid67);
3912 else if (ref_type == 2)
3914 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3915 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
3920 pm(4), pm(5), mid56, mid74);
3922 else if (child == 1)
3925 mid74, mid56, pm(6), pm(7));
3928 else if (ref_type == 4)
3930 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3931 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3936 mid04, mid15, mid26, mid37);
3938 else if (child == 1)
3941 pm(4), pm(5), pm(6), pm(7));
3944 else if (ref_type == 3)
3946 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3947 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
3948 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
3949 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
3951 Point midf0(mid23, mid12, mid01, mid30);
3952 Point midf5(mid45, mid56, mid67, mid74);
3957 pm(4), mid45, midf5, mid74);
3959 else if (child == 1)
3962 mid45, pm(5), mid56, midf5);
3964 else if (child == 2)
3967 midf5, mid56, pm(6), mid67);
3969 else if (child == 3)
3972 mid74, midf5, mid67, pm(7));
3975 else if (ref_type == 5)
3977 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3978 Point mid45(pm(4), pm(5)), mid67(pm(6), pm(7));
3979 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3980 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3982 Point midf1(mid01, mid15, mid45, mid04);
3983 Point midf3(mid23, mid37, mid67, mid26);
3988 mid04, midf1, midf3, mid37);
3990 else if (child == 1)
3993 midf1, mid15, mid26, midf3);
3995 else if (child == 2)
3998 mid45, pm(5), pm(6), mid67);
4000 else if (child == 3)
4003 pm(4), mid45, mid67, pm(7));
4006 else if (ref_type == 6)
4008 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
4009 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
4010 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
4011 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
4013 Point midf2(mid12, mid26, mid56, mid15);
4014 Point midf4(mid30, mid04, mid74, mid37);
4019 mid04, mid15, midf2, midf4);
4021 else if (child == 1)
4024 midf4, midf2, mid26, mid37);
4026 else if (child == 2)
4029 pm(4), pm(5), mid56, mid74);
4031 else if (child == 3)
4034 mid74, mid56, pm(6), pm(7));
4037 else if (ref_type == 7)
4039 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4040 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
4041 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
4042 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
4043 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
4044 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
4046 Point midf0(mid23, mid12, mid01, mid30);
4047 Point midf1(mid01, mid15, mid45, mid04);
4048 Point midf2(mid12, mid26, mid56, mid15);
4049 Point midf3(mid23, mid37, mid67, mid26);
4050 Point midf4(mid30, mid04, mid74, mid37);
4051 Point midf5(mid45, mid56, mid67, mid74);
4053 Point midel(midf1, midf3);
4058 mid04, midf1, midel, midf4);
4060 else if (child == 1)
4063 midf1, mid15, midf2, midel);
4065 else if (child == 2)
4068 midel, midf2, mid26, midf3);
4070 else if (child == 3)
4073 midf4, midel, midf3, mid37);
4075 else if (child == 4)
4078 pm(4), mid45, midf5, mid74);
4080 else if (child == 5)
4083 mid45, pm(5), mid56, midf5);
4085 else if (child == 6)
4088 midf5, mid56, pm(6), mid67);
4090 else if (child == 7)
4093 mid74, midf5, mid67, pm(7));
4101 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4102 Point mid20(pm(2), pm(0)), mid34(pm(3), pm(4));
4103 Point mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
4107 pm =
PointMatrix(pm(0), mid01, mid20, pm(3), mid34, mid53);
4109 else if (child == 1)
4111 pm =
PointMatrix(mid01, pm(1), mid12, mid34, pm(4), mid45);
4113 else if (child == 2)
4115 pm =
PointMatrix(mid20, mid12, pm(2), mid53, mid45, pm(5));
4117 else if (child == 3)
4119 pm =
PointMatrix(mid12, mid20, mid01, mid45, mid53, mid34);
4122 else if (ref_type == 4)
4124 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
4128 pm =
PointMatrix(pm(0), pm(1), pm(2), mid03, mid14, mid25);
4130 else if (child == 1)
4132 pm =
PointMatrix(mid03, mid14, mid25, pm(3), pm(4), pm(5));
4137 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
4138 Point mid34(pm(3), pm(4)), mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
4139 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
4141 Point midf2(mid01, mid14, mid34, mid03);
4142 Point midf3(mid12, mid25, mid45, mid14);
4143 Point midf4(mid20, mid03, mid53, mid25);
4147 pm =
PointMatrix(pm(0), mid01, mid20, mid03, midf2, midf4);
4149 else if (child == 1)
4151 pm =
PointMatrix(mid01, pm(1), mid12, midf2, mid14, midf3);
4153 else if (child == 2)
4155 pm =
PointMatrix(mid20, mid12, pm(2), midf4, midf3, mid25);
4157 else if (child == 3)
4159 pm =
PointMatrix(mid12, mid20, mid01, midf3, midf4, midf2);
4161 else if (child == 4)
4163 pm =
PointMatrix(mid03, midf2, midf4, pm(3), mid34, mid53);
4165 else if (child == 5)
4167 pm =
PointMatrix(midf2, mid14, midf3, mid34, pm(4), mid45);
4169 else if (child == 6)
4171 pm =
PointMatrix(midf4, midf3, mid25, mid53, mid45, pm(5));
4173 else if (child == 7)
4175 pm =
PointMatrix(midf3, midf4, midf2, mid45, mid53, mid34);
4181 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid02(pm(2), pm(0));
4182 Point mid03(pm(0), pm(3)), mid13(pm(1), pm(3)), mid23(pm(2), pm(3));
4188 else if (child == 1)
4192 else if (child == 2)
4196 else if (child == 3)
4200 else if (child == 4)
4204 else if (child == 5)
4208 else if (child == 6)
4212 else if (child == 7)
4221 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
4227 else if (child == 1)
4232 else if (ref_type == 2)
4234 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
4240 else if (child == 1)
4245 else if (ref_type == 3)
4247 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4248 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
4249 Point midel(mid01, mid23);
4255 else if (child == 1)
4259 else if (child == 2)
4263 else if (child == 3)
4271 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
4277 else if (child == 1)
4281 else if (child == 2)
4285 else if (child == 3)
4293 for (
int i = 0; i < pm.
np; i++)
4295 for (
int j = 0; j < pm(i).dim; j++)
4297 matrix(j, i) = pm(i).coord[j];
4322 int &matrix = map[ref_path];
4323 if (!matrix) { matrix = map.size(); }
4326 emb.
parent = coarse_index;
4333 MFEM_ASSERT(el.
tet_type == 0,
"not implemented");
4336 ref_path.push_back(0);
4338 for (
int i = 0; i < 8; i++)
4340 if (el.
child[i] >= 0)
4342 ref_path[ref_path.length()-1] = i;
4346 ref_path.resize(ref_path.length()-2);
4353 "GetRefinementTransforms() must be preceded by MarkCoarseLevel()"
4361 std::string ref_path;
4362 ref_path.reserve(100);
4367 path_map[g][ref_path] = 1;
4375 used_geoms |= (1 << geom);
4380 if (used_geoms & (1 << g))
4389 RefPathMap::iterator it;
4390 for (it = path_map[g].begin(); it != path_map[g].end(); ++it)
4404 "GetDerefinementTransforms() must be preceded by Derefine().");
4421 int &matrix = mat_no[emb.
geom][code];
4422 if (!matrix) { matrix = mat_no[emb.
geom].size(); }
4430 if (
Geoms & (1 << g))
4439 for (
auto it = mat_no[geom].begin(); it != mat_no[geom].end(); ++it)
4441 char path[3] = { 0, 0, 0 };
4443 int code = it->first;
4446 path[0] = code >> 4;
4447 path[1] = code & 0xf;
4460 bool want_ghosts)
const
4463 conn.
Reserve(embeddings.Size());
4465 int max_parent = -1;
4466 for (
int i = 0; i < embeddings.Size(); i++)
4470 (!emb.
ghost || want_ghosts))
4473 max_parent = std::max(emb.
parent, max_parent);
4491 point_matrices[i].SetSize(0, 0, 0);
4493 embeddings.DeleteAll();
4501 if (point_matrices[i].SizeK()) {
return true; }
4518 static int sgn(
int x)
4520 return (x < 0) ? -1 : (x > 0) ? 1 : 0;
4523 static void HilbertSfc2D(
int x,
int y,
int ax,
int ay,
int bx,
int by,
4526 int w = std::abs(ax + ay);
4527 int h = std::abs(bx + by);
4529 int dax = sgn(ax), day = sgn(ay);
4530 int dbx = sgn(bx), dby = sgn(by);
4534 for (
int i = 0; i < w; i++, x += dax, y += day)
4543 for (
int i = 0; i < h; i++, x += dbx, y += dby)
4551 int ax2 = ax/2, ay2 = ay/2;
4552 int bx2 = bx/2, by2 = by/2;
4554 int w2 = std::abs(ax2 + ay2);
4555 int h2 = std::abs(bx2 + by2);
4559 if ((w2 & 0x1) && (w > 2))
4561 ax2 += dax, ay2 += day;
4564 HilbertSfc2D(x, y, ax2, ay2, bx, by, coords);
4565 HilbertSfc2D(x+ax2, y+ay2, ax-ax2, ay-ay2, bx, by, coords);
4569 if ((h2 & 0x1) && (h > 2))
4571 bx2 += dbx, by2 += dby;
4574 HilbertSfc2D(x, y, bx2, by2, ax2, ay2, coords);
4575 HilbertSfc2D(x+bx2, y+by2, ax, ay, bx-bx2, by-by2, coords);
4576 HilbertSfc2D(x+(ax-dax)+(bx2-dbx), y+(ay-day)+(by2-dby),
4577 -bx2, -by2, -(ax-ax2), -(ay-ay2), coords);
4581 static void HilbertSfc3D(
int x,
int y,
int z,
4582 int ax,
int ay,
int az,
4583 int bx,
int by,
int bz,
4584 int cx,
int cy,
int cz,
4587 int w = std::abs(ax + ay + az);
4588 int h = std::abs(bx + by + bz);
4589 int d = std::abs(cx + cy + cz);
4591 int dax = sgn(ax), day = sgn(ay), daz = sgn(az);
4592 int dbx = sgn(bx), dby = sgn(by), dbz = sgn(bz);
4593 int dcx = sgn(cx), dcy = sgn(cy), dcz = sgn(cz);
4596 if (h == 1 && d == 1)
4598 for (
int i = 0; i < w; i++, x += dax, y += day, z += daz)
4606 if (w == 1 && d == 1)
4608 for (
int i = 0; i < h; i++, x += dbx, y += dby, z += dbz)
4616 if (w == 1 && h == 1)
4618 for (
int i = 0; i < d; i++, x += dcx, y += dcy, z += dcz)
4627 int ax2 = ax/2, ay2 = ay/2, az2 = az/2;
4628 int bx2 = bx/2, by2 = by/2, bz2 = bz/2;
4629 int cx2 = cx/2, cy2 = cy/2, cz2 = cz/2;
4631 int w2 = std::abs(ax2 + ay2 + az2);
4632 int h2 = std::abs(bx2 + by2 + bz2);
4633 int d2 = std::abs(cx2 + cy2 + cz2);
4636 if ((w2 & 0x1) && (w > 2))
4638 ax2 += dax, ay2 += day, az2 += daz;
4640 if ((h2 & 0x1) && (h > 2))
4642 bx2 += dbx, by2 += dby, bz2 += dbz;
4644 if ((d2 & 0x1) && (d > 2))
4646 cx2 += dcx, cy2 += dcy, cz2 += dcz;
4650 if ((2*w > 3*h) && (2*w > 3*d))
4652 HilbertSfc3D(x, y, z,
4655 cx, cy, cz, coords);
4657 HilbertSfc3D(x+ax2, y+ay2, z+az2,
4658 ax-ax2, ay-ay2, az-az2,
4660 cx, cy, cz, coords);
4665 HilbertSfc3D(x, y, z,
4668 ax2, ay2, az2, coords);
4670 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4672 bx-bx2, by-by2, bz-bz2,
4673 cx, cy, cz, coords);
4675 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4676 y+(ay-day)+(by2-dby),
4677 z+(az-daz)+(bz2-dbz),
4680 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4685 HilbertSfc3D(x, y, z,
4688 bx, by, bz, coords);
4690 HilbertSfc3D(x+cx2, y+cy2, z+cz2,
4693 cx-cx2, cy-cy2, cz-cz2, coords);
4695 HilbertSfc3D(x+(ax-dax)+(cx2-dcx),
4696 y+(ay-day)+(cy2-dcy),
4697 z+(az-daz)+(cz2-dcz),
4699 -(ax-ax2), -(ay-ay2), -(az-az2),
4700 bx, by, bz, coords);
4705 HilbertSfc3D(x, y, z,
4708 ax2, ay2, az2, coords);
4710 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4713 bx-bx2, by-by2, bz-bz2, coords);
4715 HilbertSfc3D(x+(bx2-dbx)+(cx-dcx),
4716 y+(by2-dby)+(cy-dcy),
4717 z+(bz2-dbz)+(cz-dcz),
4720 -(cx-cx2), -(cy-cy2), -(cz-cz2), coords);
4722 HilbertSfc3D(x+(ax-dax)+bx2+(cx-dcx),
4723 y+(ay-day)+by2+(cy-dcy),
4724 z+(az-daz)+bz2+(cz-dcz),
4726 -(ax-ax2), -(ay-ay2), -(az-az2),
4727 bx-bx2, by-by2, bz-bz2, coords);
4729 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4730 y+(ay-day)+(by2-dby),
4731 z+(az-daz)+(bz2-dbz),
4734 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4741 coords.
Reserve(2*width*height);
4743 if (width >= height)
4745 HilbertSfc2D(0, 0, width, 0, 0, height, coords);
4749 HilbertSfc2D(0, 0, 0, height, width, 0, coords);
4757 coords.
Reserve(3*width*height*depth);
4759 if (width >= height && width >= depth)
4761 HilbertSfc3D(0, 0, 0,
4764 0, 0, depth, coords);
4766 else if (height >= width && height >= depth)
4768 HilbertSfc3D(0, 0, 0,
4771 0, 0, depth, coords);
4775 HilbertSfc3D(0, 0, 0,
4778 0, height, 0, coords);
4786 bool oriented)
const
4790 const int* ev = gi.
edges[(int) edge_id.
local];
4792 int n0 = el.
node[ev[0]], n1 = el.
node[ev[1]];
4793 if (n0 > n1) { std::swap(n0, n1); }
4795 vert_index[0] =
nodes[n0].vert_index;
4796 vert_index[1] =
nodes[n1].vert_index;
4798 if (oriented && vert_index[0] > vert_index[1])
4800 std::swap(vert_index[0], vert_index[1]);
4808 const int* ev = gi.
edges[(int) edge_id.
local];
4810 int v0 =
nodes[el.
node[ev[0]]].vert_index;
4811 int v1 =
nodes[el.
node[ev[1]]].vert_index;
4813 return ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1])) ? -1 : 1;
4817 int vert_index[4],
int edge_index[4],
4818 int edge_orientation[4])
const
4820 MFEM_ASSERT(
Dim >= 3,
"");
4825 const int *fv = gi.
faces[(int) face_id.
local];
4826 const int nfv = gi.
nfv[(
int) face_id.
local];
4828 vert_index[3] = edge_index[3] = -1;
4829 edge_orientation[3] = 0;
4831 for (
int i = 0; i < nfv; i++)
4833 vert_index[i] =
nodes[el.
node[fv[i]]].vert_index;
4836 for (
int i = 0; i < nfv; i++)
4839 if (j >= nfv) { j = 0; }
4841 int n1 = el.
node[fv[i]];
4842 int n2 = el.
node[fv[j]];
4845 MFEM_ASSERT(en != NULL,
"edge not found.");
4848 edge_orientation[i] = (vert_index[i] < vert_index[j]) ? 1 : -1;
4856 MFEM_ASSERT(node >= 0,
"edge node not found.");
4859 int p1 = nd.
p1, p2 = nd.
p2;
4860 MFEM_ASSERT(p1 != p2,
"invalid edge node.");
4864 int n1p1 = n1.
p1, n1p2 = n1.
p2;
4865 int n2p1 = n2.p1, n2p2 = n2.p2;
4867 if ((n2p1 != n2p2) && (p1 == n2p1 || p1 == n2p2))
4871 if (n2.HasEdge()) {
return p2; }
4875 if ((n1p1 != n1p2) && (p2 == n1p1 || p2 == n1p2))
4879 if (n1.
HasEdge()) {
return p1; }
4889 MFEM_ASSERT(node >= 0 &&
nodes[node].HasEdge(),
"(v1, v2) is not an edge.");
4892 return (master >= 0) ?
nodes[master].edge_index : -1;
4898 int depth = 0, parent;
4899 while ((parent =
elements[elem].parent) != -1)
4910 int parent, reduction = 1;
4911 while ((parent =
elements[elem].parent) != -1)
4913 if (
elements[parent].ref_type & 1) { reduction *= 2; }
4914 if (
elements[parent].ref_type & 2) { reduction *= 2; }
4915 if (
elements[parent].ref_type & 4) { reduction *= 2; }
4931 for (
int i = 0; i < gi.
nf; i++)
4933 const int* fv = gi.
faces[i];
4936 MFEM_ASSERT(face,
"face not found");
4937 face_indices[i] = face->
index;
4949 int elem = fa.
elem[0];
4950 if (elem < 0) { elem = fa.
elem[1]; }
4951 MFEM_ASSERT(elem >= 0,
"Face has no elements?");
4960 for (
int i = 0; i < 4; i++)
4962 node[i] = el.
node[fv[i]];
4979 if (bdr_attr_is_ess[
faces[face].attribute - 1])
4983 int nfv = (node[3] < 0) ? 3 : 4;
4985 for (
int j = 0; j < nfv; j++)
4989 int enode =
nodes.FindId(node[j], node[(j+1) % nfv]);
4990 MFEM_ASSERT(enode >= 0 &&
nodes[enode].HasEdge(),
"Edge not found.");
5019 bdr_vertices.
Sort();
5026 static int max4(
int a,
int b,
int c,
int d)
5028 return std::max(std::max(a, b), std::max(c, d));
5030 static int max6(
int a,
int b,
int c,
int d,
int e,
int f)
5032 return std::max(max4(a, b, c, d), std::max(e, f));
5034 static int max8(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h)
5036 return std::max(max4(a, b, c, d), max4(e, f, g, h));
5041 int mid =
nodes.FindId(vn1, vn2);
5042 if (mid < 0 || !
nodes[mid].HasVertex()) {
return 0; }
5050 faces.FindId(vn1, vn2, vn3) < 0)
5064 int& h_level,
int& v_level)
const
5066 int hl1, hl2, vl1, vl2;
5072 h_level = v_level = 0;
5078 h_level = std::max(hl1, hl2);
5079 v_level = std::max(vl1, vl2) + 1;
5085 h_level = std::max(hl1, hl2) + 1;
5086 v_level = std::max(vl1, vl2);
5093 const int* node = el.
node;
5097 for (
int i = 0; i < gi.
ne; i++)
5099 const int* ev = gi.
edges[i];
5106 for (
int i = 0; i < gi.
nf; i++)
5108 const int* fv = gi.
faces[i];
5112 node[fv[2]], node[fv[3]],
5113 flevel[i][1], flevel[i][0]);
5126 splits[0] = max8(flevel[0][0], flevel[1][0], flevel[3][0], flevel[5][0],
5127 elevel[0], elevel[2], elevel[4], elevel[6]);
5129 splits[1] = max8(flevel[0][1], flevel[2][0], flevel[4][0], flevel[5][1],
5130 elevel[1], elevel[3], elevel[5], elevel[7]);
5132 splits[2] = max8(flevel[1][1], flevel[2][1], flevel[3][1], flevel[4][1],
5133 elevel[8], elevel[9], elevel[10], elevel[11]);
5137 splits[0] = splits[1] =
5139 max6(flevel[0][0], flevel[1][0], 0,
5140 flevel[2][0], flevel[3][0], flevel[4][0]),
5141 max6(elevel[0], elevel[1], elevel[2],
5142 elevel[3], elevel[4], elevel[5]));
5144 splits[2] = max6(flevel[2][1], flevel[3][1], flevel[4][1],
5145 elevel[6], elevel[7], elevel[8]);
5149 splits[0] = std::max(
5150 max4(flevel[0][0], flevel[1][0], flevel[2][0], flevel[3][0]),
5151 max6(elevel[0], elevel[1], elevel[2],
5152 elevel[3], elevel[4], elevel[5]));
5154 splits[1] = splits[0];
5155 splits[2] = splits[0];
5159 splits[0] = std::max(elevel[0], elevel[2]);
5160 splits[1] = std::max(elevel[1], elevel[3]);
5164 splits[0] = std::max(elevel[0], std::max(elevel[1], elevel[2]));
5165 splits[1] = splits[0];
5169 MFEM_ABORT(
"Unsupported element geometry.");
5183 for (
int k = 0; k <
Dim; k++)
5185 if (splits[k] > max_level)
5187 ref_type |= (1 << k);
5205 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
5212 if (!refinements.
Size()) {
break; }
5227 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5229 if (node->HasVertex() && node->p1 != node->p2) { nv++; }
5236 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5238 if (node->HasVertex() && node->p1 != node->p2)
5240 MFEM_ASSERT(
nodes[node->p1].HasVertex(),
"");
5241 MFEM_ASSERT(
nodes[node->p2].HasVertex(),
"");
5243 (*os) << node.index() <<
" " << node->p1 <<
" " << node->p2 <<
"\n";
5257 input >>
id >> p1 >> p2;
5258 MFEM_VERIFY(input,
"problem reading vertex parents.");
5260 MFEM_VERIFY(
nodes.IdExists(
id),
"vertex " <<
id <<
" not found.");
5261 MFEM_VERIFY(
nodes.IdExists(p1),
"parent " << p1 <<
" not found.");
5262 MFEM_VERIFY(
nodes.IdExists(p2),
"parent " << p2 <<
" not found.");
5264 int check =
nodes.FindId(p1, p2);
5265 MFEM_VERIFY(check < 0,
"parents (" << p1 <<
", " << p2 <<
") already "
5266 "assigned to node " << check);
5269 nodes.Reparent(
id, p1, p2);
5275 static const int nfv2geom[5] =
5280 int deg = (
Dim == 2) ? 2 : 1;
5283 for (
int i = 0; i <
elements.Size(); i++)
5286 if (!el.
IsLeaf()) {
continue; }
5289 for (
int k = 0; k < gi.
nf; k++)
5291 const int* fv = gi.
faces[k];
5292 const int nfv = gi.
nfv[k];
5295 MFEM_ASSERT(face != NULL,
"face not found");
5298 if (!os) { count++;
continue; }
5300 (*os) << face->
attribute <<
" " << nfv2geom[nfv];
5301 for (
int j = 0; j < nfv; j++)
5303 (*os) <<
" " << el.
node[fv[j*deg]];
5316 for (
int i = 0; i < nb; i++)
5318 input >> attr >> geom;
5323 input >> v1 >> v2 >> v3 >> v4;
5329 input >> v1 >> v2 >> v3;
5347 MFEM_ABORT(
"unsupported boundary element geometry: " << geom);
5356 if (!nv) {
return; }
5359 for (
int i = 0; i < nv; i++)
5364 os <<
" " << coordinates[3*i + j];
5374 if (!nv) {
return; }
5381 for (
int i = 0; i < nv; i++)
5386 MFEM_VERIFY(input.good(),
"unexpected EOF");
5402 os <<
"MFEM NC mesh v1.0\n\n"
5403 "# NCMesh supported geometry types:\n"
5407 "# TETRAHEDRON = 4\n"
5411 os <<
"\ndimension\n" <<
Dim <<
"\n";
5413 #ifndef MFEM_USE_MPI
5417 os <<
"\nrank\n" <<
MyRank <<
"\n";
5420 os <<
"\n# rank attr geom ref_type nodes/children";
5421 os <<
"\nelements\n" <<
elements.Size() <<
"\n";
5423 for (
int i = 0; i <
elements.Size(); i++)
5427 if (el.
parent == -2) { os <<
"-1\n";
continue; }
5430 for (
int j = 0; j < 8 && el.
node[j] >= 0; j++)
5432 os <<
" " << el.
node[j];
5440 os <<
"\n# attr geom nodes";
5441 os <<
"\nboundary\n" << nb <<
"\n";
5449 os <<
"\n# vert_id p1 p2";
5450 os <<
"\nvertex_parents\n" << nvp <<
"\n";
5457 os <<
"\n# root element orientation";
5468 os <<
"\n# top-level node coordinates";
5469 os <<
"\ncoordinates\n";
5482 for (
int i = 0; i <
elements.Size(); i++)
5487 for (
int j = 0; j < 8 && el.
child[j] >= 0; j++)
5489 int child = el.
child[j];
5490 MFEM_VERIFY(child <
elements.Size(),
"invalid mesh file: "
5491 "element " << i <<
" references invalid child " << child);
5504 MFEM_VERIFY(nroots,
"invalid mesh file: no root elements found.");
5507 for (
int i = nroots; i <
elements.Size(); i++)
5509 MFEM_VERIFY(
elements[i].parent != -1,
5510 "invalid mesh file: only the first M elements can be roots. "
5511 "Found element " << i <<
" with no parent.");
5522 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5524 if (node->p1 == node->p2) { ntop = node.index() + 1; }
5540 MFEM_ASSERT(version == 10,
"");
5547 MFEM_VERIFY(ident ==
"dimension",
"Invalid mesh file: " << ident);
5553 if (ident ==
"rank")
5556 MFEM_VERIFY(MyRank >= 0,
"Invalid rank");
5563 if (ident ==
"sfc_version")
5566 input >> sfc_version;
5567 MFEM_VERIFY(sfc_version == 0,
5568 "Unsupported mesh file SFC version (" << sfc_version <<
"). "
5569 "Please update MFEM.");
5576 MFEM_VERIFY(ident ==
"elements",
"Invalid mesh file: " << ident);
5578 for (
int i = 0; i < count; i++)
5580 int rank, attr, geom, ref_type;
5581 input >> rank >> attr >> geom;
5586 MFEM_ASSERT(
elements.Size() == i+1,
"");
5592 CheckSupportedGeom(type);
5596 MFEM_VERIFY(ref_type >= 0 && ref_type < 8,
"");
5597 el.ref_type = ref_type;
5601 for (
int j = 0; j < ref_type_num_children[ref_type]; j++)
5603 input >> el.child[j];
5605 if (Dim == 3 && ref_type != 7) {
Iso =
false; }
5609 for (
int j = 0; j <
GI[geom].
nv; j++)
5614 nodes.Alloc(
id,
id,
id);
5634 if (ident ==
"boundary")
5643 if (ident ==
"vertex_parents")
5652 if (ident ==
"root_state")
5656 for (
int i = 0; i < count; i++)
5666 if (ident ==
"coordinates")
5671 "Invalid mesh file: not all top-level nodes are covered by "
5672 "the 'coordinates' section of the mesh file.");
5675 else if (ident ==
"nodes")
5685 MFEM_ABORT(
"Invalid mesh file: either 'coordinates' or "
5686 "'nodes' must be present");
5690 nodes.UpdateUnused();
5691 for (
int i = 0; i <
elements.Size(); i++)
5709 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
5711 int old_id = el.
child[i];
5713 int new_id =
elements.Append(tmp_elements[old_id]);
5714 el.
child[i] = new_id;
5738 if (
Dim == 3 && ref_type != 7) { iso =
false; }
5741 int nch = ref_type_num_children[ref_type];
5742 for (
int i = 0,
id; i < nch; i++)
5745 MFEM_VERIFY(
id >= 0,
"");
5747 "coarse element cannot be referenced before it is "
5748 "defined (id=" <<
id <<
").");
5751 MFEM_VERIFY(child.parent == -1,
5752 "element " <<
id <<
" cannot have two parents.");
5755 child.parent = elem;
5759 el.
geom = child.geom;
5771 for (
auto el = tmp_elements.
begin(); el != tmp_elements.
end(); ++el)
5773 if (el->parent == -1)
5781 for (
int i = 0; i < root_count; i++)
5794 MFEM_ASSERT(
elements.Size() == 0,
"");
5795 MFEM_ASSERT(
nodes.Size() == 0,
"");
5799 int count, attr, geom;
5804 MFEM_VERIFY(ident ==
"dimension",
"invalid mesh file");
5810 MFEM_VERIFY(ident ==
"elements",
"invalid mesh file");
5813 for (
int i = 0; i < count; i++)
5815 input >> attr >> geom;
5818 CheckSupportedGeom(type);
5822 MFEM_ASSERT(eid == i,
"");
5825 for (
int j = 0; j <
GI[geom].
nv; j++)
5830 nodes.Alloc(
id,
id,
id);
5838 MFEM_VERIFY(ident ==
"boundary",
"invalid mesh file");
5845 if (ident ==
"vertex_parents")
5861 if (ident ==
"coarse_elements")
5876 MFEM_VERIFY(ident ==
"vertices",
"invalid mesh file");
5879 input >> std::ws >> ident;
5880 if (ident !=
"nodes")
5887 for (
int i = 0; i < nvert; i++)
5892 MFEM_VERIFY(input.good(),
"unexpected EOF");
5913 nodes.UpdateUnused();
5915 for (
int i = 0; i <
elements.Size(); i++)
5927 file_leaf_elements = -1;
5928 for (
int i = 0; i <
elements.Size(); i++)
5932 file_leaf_elements[
elements[i].index] = i;
5935 MFEM_ASSERT(file_leaf_elements.
Min() >= 0,
"");
5956 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5958 if (node->HasVertex())
5960 MFEM_ASSERT(node.index() >= 0,
"");
5961 MFEM_ASSERT(node.index() < order.
Size(),
"");
5962 MFEM_ASSERT(order[node.index()] == -1,
"");
5964 order[node.index()] = node->vert_index;
5968 MFEM_ASSERT(count == order.
Size(),
"");
5991 std::size_t pm_size = 0;
5994 for (
int j = 0; j < point_matrices[i].Size(); i++)
5996 pm_size += point_matrices[i][j]->MemoryUsage();
5998 pm_size += point_matrices[i].MemoryUsage();
6009 std::size_t mem = embeddings.MemoryUsage();
6012 mem += point_matrices[i].MemoryUsage();
6019 return nodes.MemoryUsage() +
6020 faces.MemoryUsage() +
6057 <<
ref_stack.MemoryUsage() <<
" ref_stack\n"
6061 <<
sizeof(*this) <<
" NCMesh"
6074 for (
int j = 0; j <
Dim; j++)
6078 for (
int k = 0; k < 8; k++)
6080 if (elem->
node[k] >= 0)
6086 os << sum / count <<
" ";
6097 os <<
nodes.Size() <<
"\n";
6098 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
6101 os << node.index() <<
" "
6102 << pos[0] <<
" " << pos[1] <<
" " << pos[2] <<
" "
6103 << node->p1 <<
" " << node->p2 <<
" "
6104 << node->vert_index <<
" " << node->edge_index <<
" "
6112 for (
int i = 0; i <
elements.Size(); i++)
6114 if (
elements[i].IsLeaf()) { nleaves++; }
6116 os << nleaves <<
"\n";
6117 for (
int i = 0; i <
elements.Size(); i++)
6124 for (
int j = 0; j < gi.
nv; j++)
6126 os << el.
node[j] <<
" ";
6134 os <<
faces.Size() <<
"\n";
6135 for (
auto face =
faces.cbegin(); face !=
faces.cend(); ++face)
6137 int elem = face->elem[0];
6138 if (elem < 0) { elem = face->elem[1]; }
6139 MFEM_ASSERT(elem >= 0,
"");
6151 for (
int i = 0; i < nfv; i++)
6153 os <<
" " << el.
node[fv[i]];
NCList face_list
lazy-initialized list of faces, see GetFaceList
bool CubeFaceTop(int node, int *n)
NCList edge_list
lazy-initialized list of edges, see GetEdgeList
void LegacyToNewVertexOrdering(Array< int > &order) const
I/O: Return a map from old (v1.1) vertex indices to new vertex indices.
The PointMatrix stores the coordinates of the slave face using the master face coordinate as referenc...
Geometry::Type GetGeometryType() const
void LoadLegacyFormat(std::istream &input, int &curved, int &is_nc)
Load the deprecated MFEM mesh v1.1 format for backward compatibility.
int Size() const
Return the logical size of the array.
static void GridSfcOrdering3D(int width, int height, int depth, Array< int > &coords)
void CheckAnisoPrism(int vn1, int vn2, int vn3, int vn4, const Refinement *refs, int nref)
CoarseFineTransformations transforms
storage for data returned by Get[De]RefinementTransforms()
static void GridSfcOrdering2D(int width, int height, Array< int > &coords)
int NewQuadrilateral(int n0, int n1, int n2, int n3, int attr, int eattr0, int eattr1, int eattr2, int eattr3)
bool CubeFaceLeft(int node, int *n)
static PointMatrix pm_seg_identity
int elem[2]
up to 2 elements sharing the face
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
char ref_type
refinement XYZ bit mask (7 = full isotropic)
int GetFaceVerticesEdges(const MeshId &face_id, int vert_index[4], int edge_index[4], int edge_orientation[4]) const
void Unique()
Removes duplicities from a sorted array. This requires operator== to be defined for T...
Table * GetEdgeVertexTable() const
Returns the edge-to-vertex Table (3D)
bool TriFaceSplit(int v1, int v2, int v3, int mid[3]=NULL) const
void SetDerefMatrixCodes(int parent, Array< int > &fine_coarse)
const CoarseFineTransformations & GetDerefinementTransforms()
virtual int GetNEdges() const =0
This holds in one place the constants about the geometries we support.
Array< Triple< int, int, int > > reparents
scheduled node reparents (tmp)
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
Array< Element * > boundary
void CollectTriFaceVertices(int v0, int v1, int v2, Array< int > &indices)
char tet_type
tetrahedron split type, currently always 0
int NewSegment(int n0, int n1, int attr, int vattr1, int vattr2)
virtual void LimitNCLevel(int max_nc_level)
int GetNBE() const
Returns number of boundary elements.
virtual void Trim()
Save memory by releasing all non-essential and cached data.
int index
element number in the Mesh, -1 if refined
void ForceRefinement(int vn1, int vn2, int vn3, int vn4)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
bool Legacy
true if the mesh was loaded from the legacy v1.1 format
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
unsigned matrix
index into NCList::point_matrices[geom]
T * GetData()
Returns the data.
void GetMeshComponents(Mesh &mesh) const
Fill Mesh::{vertices,elements,boundary} for the current finest level.
void ClearTransforms()
Free all internal data created by the above three functions.
Table derefinements
possible derefinements, see GetDerefinementTable
Data type dense matrix using column-major storage.
Geometry::Type Geom() const
NCList vertex_list
lazy-initialized list of vertices, see GetVertexList
void InitDerefTransforms()
static PointMatrix pm_prism_identity
void Print(std::ostream &out) const
I/O: Print the mesh in "MFEM NC mesh v1.0" format.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
char geom
Geometry::Type of the element (char for storage only)
void Swap(DenseTensor &t)
void InitRootState(int root_count)
int GetEdgeNCOrientation(const MeshId &edge_id) const
int GetNE() const
Returns number of elements.
const Element * GetFace(int i) const
int NewTetrahedron(int n0, int n1, int n2, int n3, int attr, int fattr0, int fattr1, int fattr2, int fattr3)
void CheckAnisoFace(int vn1, int vn2, int vn3, int vn4, int mid12, int mid34, int level=0)
bool ZeroRootStates() const
Return true if all root_states are zero.
static PointMatrix pm_tri_identity
void CountSplits(int elem, int splits[3]) const
Geometry::Type Geom() const
void CollectDerefinements(int elem, Array< Connection > &list)
Data type quadrilateral element.
void GetLimitRefinements(Array< Refinement > &refinements, int max_level)
int PrintMemoryDetail() const
void TraverseEdge(int vn0, int vn1, double t0, double t1, int flags, int level, MatrixMap &matrix_map)
T Min() const
Find the minimal element in the array, using the comparison operator < for class T.
int spaceDim
dimensions of the elements and the vertex coordinates
bool HavePrisms() const
Return true if the mesh contains prism elements.
Array< int > vertex_nodeId
vertex-index to node-id map, see UpdateVertices
int attribute
boundary element attribute, -1 if internal face
void DebugDump(std::ostream &out) const
void FindFaceNodes(int face, int node[4])
bool CubeFaceBack(int node, int *n)
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
static const PointMatrix & GetGeomIdentity(Geometry::Type geom)
void DeleteAll()
Delete the whole array.
static int find_element_edge(const Element &el, int vn0, int vn1, bool abort=true)
int index
Mesh element number.
const NCList & GetFaceList()
Return the current list of conforming and nonconforming faces.
const MeshId & LookUp(int index, int *type=NULL) const
void OnMeshUpdated(Mesh *mesh)
void DebugLeafOrder(std::ostream &out) const
Element * NewElement(int geom)
int NewWedge(int n0, int n1, int n2, int n3, int n4, int n5, int attr, int fattr0, int fattr1, int fattr2, int fattr3, int fattr4)
void CollectEdgeVertices(int v0, int v1, Array< int > &indices)
void CollectLeafElements(int elem, int state, Array< int > &ghosts, int &counter)
static int find_local_face(int geom, int a, int b, int c)
Array< Refinement > ref_stack
stack of scheduled refinements (temporary)
void CollectIncidentElements(int elem, const RefCoord coord[3], Array< int > &list) const
void ReferenceElement(int elem)
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
void GetPointMatrix(Geometry::Type geom, const char *ref_path, DenseMatrix &matrix)
void CheckIsoFace(int vn1, int vn2, int vn3, int vn4, int en1, int en2, int en3, int en4, int midf)
Data type hexahedron element.
virtual int GetNFaceVertices(int fi) const =0
Face * GetFace(Element &elem, int face_no)
void TraverseRefinements(int elem, int coarse_index, std::string &ref_path, RefPathMap &map)
bool CubeFaceRight(int node, int *n)
int PrintBoundary(std::ostream *out) const
virtual const int * GetEdgeVertices(int) const =0
int GetMidEdgeNode(int node1, int node2)
Element(Geometry::Type geom, int attr)
double f(const Vector &xvec)
int index
face number in the Mesh
const Table & GetDerefinementTable()
void MakeFromList(int nrows, const Array< Connection > &list)
Table element_vertex
leaf-element to vertex table, see FindSetNeighbors
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int Append(const T &el)
Append element 'el' to array, resize if necessary.
int CountTopLevelNodes() const
Return the index of the last top-level node plus one.
bool operator==(const PointMatrix &pm) const
void GetMatrix(DenseMatrix &point_matrix) const
int AddElement(const Element &el)
virtual void Derefine(const Array< int > &derefs)
void QuadFaceSplitLevel(int vn1, int vn2, int vn3, int vn4, int &h_level, int &v_level) const
void FindNeighbors(int elem, Array< int > &neighbors, const Array< int > *search_set=NULL)
void InitGeom(Geometry::Type geom)
Array< int > coarse_elements
state of leaf_elements before Refine(), set by MarkCoarseLevel()
void UpdateVertices()
This method assigns indices to vertices (Node::vert_index) that will be seen by the Mesh class and th...
int ReorderFacePointMat(int v0, int v1, int v2, int v3, int elem, const PointMatrix &pm, PointMatrix &reordered) const
Array< DenseMatrix * > point_matrices[Geometry::NumGeom]
List of unique point matrices for each slave geometry.
void RegisterFaces(int elem, int *fattr=NULL)
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
virtual void BuildEdgeList()
const CoarseFineTransformations & GetRefinementTransforms()
int GetAttribute() const
Return element's attribute.
void LoadCoarseElements(std::istream &input)
Load the element refinement hierarchy from a legacy mesh file.
Identifies a vertex/edge/face in both Mesh and NCMesh.
int FindMidEdgeNode(int node1, int node2) const
int parent
parent element, -1 if this is a root element, -2 if free'd
virtual MFEM_DEPRECATED int GetNFaces(int &nFaceVertices) const =0
Data type triangle element.
const Element * GetElement(int i) const
signed char local
local number within 'element'
virtual void ElementSharesFace(int elem, int local, int face)
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
void LoadCoordinates(std::istream &input)
Load the "coordinates" section of the mesh file.
virtual void ElementSharesVertex(int elem, int local, int vnode)
int MyRank
used in parallel, or when loading a parallel file in serial
int Size() const
Returns the number of TYPE I elements.
bool CubeFaceFront(int node, int *n)
A class for non-conforming AMR. The class is not used directly by the user, rather it is an extension...
int GetElementSizeReduction(int i) const
friend struct PointMatrixHash
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
int element
NCMesh::Element containing this vertex/edge/face.
bool PrismFaceTop(int node, int *n)
static GeomInfo GI[Geometry::NumGeom]
Data type tetrahedron element.
void ReparentNode(int node, int new_p1, int new_p2)
int NewTriangle(int n0, int n1, int n2, int attr, int eattr0, int eattr1, int eattr2)
Array< Triple< int, int, int > > tmp_vertex_parents
void DeleteUnusedFaces(const Array< int > &elemFaces)
int SpaceDimension() const
bool Iso
true if the mesh only contains isotropic refinements
void Swap(Array< T > &, Array< T > &)
std::map< std::string, int > RefPathMap
unsigned ghost
For internal use: 0 if regular fine element, 1 if parallel ghost element.
virtual void BuildFaceList()
Nonconforming edge/face within a bigger edge/face.
void DerefineElement(int elem)
Derefine the element elem, does nothing on leaf elements.
void GetElementFacesAttributes(int i, Array< int > &faces, Array< int > &fattr) const
Return the faces and face attributes of leaf element 'i'.
void RegisterElement(int e)
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
mfem::Element * NewMeshElement(int geom) const
Array< int > leaf_sfc_index
natural tree ordering of leaf elements
bool PrismFaceBottom(int node, int *n)
void DeleteLast()
Delete the last entry of the array.
Helper struct for defining a connectivity table, see Table::MakeFromList.
void UpdateLeafElements()
Update the leaf elements indices in leaf_elements.
Array< Element * > elements
int PrintVertexParents(std::ostream *out) const
Print the "vertex_parents" section of the mesh file.
int TriFaceSplitLevel(int vn1, int vn2, int vn3) const
int RetrieveNode(const Element &el, int index)
Return el.node[index] correctly, even if the element is refined.
int Geoms
bit mask of element geometries present, see InitGeomFlags()
void BuildElementToVertexTable()
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
std::size_t MemoryUsage() const
void ForgetElement(int e)
static PointMatrix pm_tet_identity
int GetMidFaceNode(int en1, int en2, int en3, int en4)
void RefineElement(int elem, char ref_type)
int NewHexahedron(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, int attr, int fattr0, int fattr1, int fattr2, int fattr3, int fattr4, int fattr5)
void TraverseTetEdge(int vn0, int vn1, const Point &p0, const Point &p1, MatrixMap &matrix_map)
Array< int > boundary_faces
subset of all faces, set by BuildFaceList
int child[8]
2-8 children (if ref_type != 0)
Array< double > coordinates
Array< int > leaf_elements
finest elements, in Mesh ordering (+ ghosts)
static PointMatrix pm_quad_identity
int EdgeSplitLevel(int vn1, int vn2) const
void SetIJ(int *newI, int *newJ, int newsize=-1)
Replace the I and J arrays with the given newI and newJ arrays.
Array< MeshId > conforming
std::size_t MemoryUsage() const
Return total number of bytes allocated.
unsigned edge_flags
orientation flags, see OrientedPointMatrix
void FindVertexCousins(int elem, int local, Array< int > &cousins) const
int QuadFaceSplitType(int v1, int v2, int v3, int v4, int mid[5]=NULL) const
void OrientedPointMatrix(const Slave &slave, DenseMatrix &oriented_matrix) const
Return the point matrix oriented according to the master and slave edges.
Array< int > free_element_ids
bool CubeFaceBottom(int node, int *n)
void TraverseQuadFace(int vn0, int vn1, int vn2, int vn3, const PointMatrix &pm, int level, Face *eface[4], MatrixMap &matrix_map)
int index(int i, int j, int nx, int ny)
virtual int GetNVertices() const =0
int parent
Coarse Element index in the coarse mesh.
static PointMatrix pm_hex_identity
void FindEdgeElements(int vn1, int vn2, int vn3, int vn4, Array< MeshId > &prisms) const
virtual const int * GetFaceVertices(int fi) const =0
virtual void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level)
T & Last()
Return the last element in the array.
void NeighborExpand(const Array< int > &elems, Array< int > &expanded, const Array< int > *search_set=NULL)
BlockArray< Element > elements
void FindSetNeighbors(const Array< char > &elem_set, Array< int > *neighbors, Array< char > *neighbor_set=NULL)
int GetNEdges() const
Return the number of edges.
void GetEdgeVertices(const MeshId &edge_id, int vert_index[2], bool oriented=true) const
Return Mesh vertex indices of an edge identified by 'edge_id'.
bool HaveTets() const
Return true if the mesh contains tetrahedral elements.
std::size_t MemoryUsage() const
Returns the number of bytes allocated for the array including any reserve.
void InitRootElements()
Count root elements and initialize root_state.
HashTable< Node > shadow
temporary storage for reparented nodes
virtual void BuildVertexList()
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
void UpdateElementToVertexTable()
bool IsGhost(const Element &el) const
Return true if the Element el is a ghost element.
void LoadBoundary(std::istream &input)
Load the "boundary" section of the mesh file.
void CopyElements(int elem, const BlockArray< Element > &tmp_elements)
virtual void ElementSharesEdge(int elem, int local, int enode)
int GetElementDepth(int i) const
Return the distance of leaf 'i' from the root.
int FindNodeExt(const Element &el, int node, bool abort=true)
Extended version of find_node: works if 'el' is refined.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
char ref_type
bit mask of X,Y,Z refinements (bits 0,1,2 respectively)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void CollectQuadFaceVertices(int v0, int v1, int v2, int v3, Array< int > &indices)
static int find_node(const Element &el, int node)
std::size_t MemoryUsage() const
void UnreferenceElement(int elem, Array< int > &elemFaces)
void LoadVertexParents(std::istream &input)
Load the vertex parent hierarchy from a mesh file.
Abstract data type element.
Data type line segment element.
int GetSingleElement() const
Return one of elem[0] or elem[1] and make sure the other is -1.
void PrintCoordinates(std::ostream &out) const
Print the "coordinates" section of the mesh file.
virtual Type GetType() const =0
Returns element's type.
const double * CalcVertexPos(int node) const
int rank
processor number (ParNCMesh), -1 if undefined/unknown
int node[8]
element corners (if ref_type == 0)
int GetVertexRootCoord(int elem, RefCoord coord[3]) const
const Element * GetBdrElement(int i) const
bool TraverseTriFace(int vn0, int vn1, int vn2, const PointMatrix &pm, int level, MatrixMap &matrix_map)
Defines the position of a fine element within a coarse element.
virtual void Refine(const Array< Refinement > &refinements)
Array< char > face_geom
face geometry by face index, set by OnMeshUpdated
int GetEdgeMaster(int v1, int v2) const