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;
1585 MFEM_ASSERT(ch != -1,
"");
1600 MFEM_ABORT(
"Unsupported element geometry.");
1612 std::memcpy(child, el.
child,
sizeof(child));
1615 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1623 int faces_attribute[6];
1624 int ref_type_key = el.
ref_type - 1;
1626 for (
int i = 0; i < 8; i++) { el.
node[i] = -1; }
1632 constexpr
int nb_cube_childs = 8;
1633 for (
int i = 0; i < nb_cube_childs; i++)
1635 const int child_local_index = hex_deref_table[ref_type_key][i];
1636 const int child_global_index = child[child_local_index];
1641 constexpr
int nb_cube_faces = 6;
1642 for (
int i = 0; i < nb_cube_faces; i++)
1644 const int child_local_index = hex_deref_table[ref_type_key]
1645 [i + nb_cube_childs];
1646 const int child_global_index = child[child_local_index];
1649 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1656 MFEM_ASSERT(prism_deref_table[ref_type_key][0] != -1,
1657 "invalid prism refinement");
1658 constexpr
int nb_prism_childs = 6;
1659 for (
int i = 0; i < nb_prism_childs; i++)
1661 const int child_local_index = prism_deref_table[ref_type_key][i];
1662 const int child_global_index = child[child_local_index];
1668 constexpr
int nb_prism_faces = 5;
1669 for (
int i = 0; i < nb_prism_faces; i++)
1671 const int child_local_index = prism_deref_table[ref_type_key]
1672 [i + nb_prism_childs];
1673 const int child_global_index = child[child_local_index];
1676 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1683 for (
int i = 0; i < 4; i++)
1689 faces_attribute[i] =
faces.Find(ch2.
node[fv[0]], ch2.
node[fv[1]],
1696 constexpr
int nb_square_childs = 4;
1697 for (
int i = 0; i < nb_square_childs; i++)
1699 const int child_local_index = quad_deref_table[ref_type_key][i];
1700 const int child_global_index = child[child_local_index];
1704 constexpr
int nb_square_faces = 4;
1705 for (
int i = 0; i < nb_square_faces; i++)
1707 const int child_local_index = quad_deref_table[ref_type_key]
1708 [i + nb_square_childs];
1709 const int child_global_index = child[child_local_index];
1712 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1719 constexpr
int nb_triangle_childs = 3;
1720 for (
int i = 0; i < nb_triangle_childs; i++)
1725 faces_attribute[i] =
faces.Find(ch.
node[fv[0]], ch.
node[fv[1]],
1732 constexpr
int nb_segment_childs = 2;
1733 for (
int i = 0; i < nb_segment_childs; i++)
1735 int ni =
elements[child[i]].node[i];
1737 faces_attribute[i] =
faces.Find(ni, ni, ni, ni)->attribute;
1742 MFEM_ABORT(
"Unsupported element geometry.");
1753 el.
rank = std::numeric_limits<int>::max();
1754 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1777 int total = 0, ref = 0, ghost = 0;
1778 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1786 if (!ref && ghost < total)
1789 int next_row = list.
Size() ? (list.
Last().from + 1) : 0;
1790 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1798 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1815 int size = list.
Size() ? (list.
Last().from + 1) : 0;
1824 for (
int i = 0; i < deref_table.
Size(); i++)
1826 const int* fine = deref_table.
GetRow(i), size = deref_table.
RowSize(i);
1830 for (
int j = 0; j < size; j++)
1835 for (
int k = 0; k <
Dim; k++)
1837 if ((parent.
ref_type & (1 << k)) &&
1838 splits[k] >= max_nc_level)
1851 MFEM_VERIFY(
Dim < 3 ||
Iso,
1852 "derefinement of 3D anisotropic meshes not implemented yet.");
1860 for (
int i = 0; i < derefs.
Size(); i++)
1862 int row = derefs[i];
1864 "invalid derefinement number.");
1879 for (
int i = 0; i < fine_coarse.
Size(); i++)
1893 for (
int i = 0; i < nfine; i++)
1908 for (
int i = 0; i < 8 && prn.
child[i] >= 0; i++)
1913 int code = (prn.
ref_type << 4) | i;
1915 fine_coarse[ch.
index] = parent;
1943 el.
index = counter++;
1962 for (
int i = 0; i < 4; i++)
1964 int ch = quad_hilbert_child_order[state][i];
1965 int st = quad_hilbert_child_state[state][i];
1971 for (
int i = 0; i < 8; i++)
1973 int ch = hex_hilbert_child_order[state][i];
1974 int st = hex_hilbert_child_state[state][i];
1980 for (
int i = 0; i < 8; i++)
1982 if (el.
child[i] >= 0)
2021 #ifndef MFEM_NCMESH_OLD_VERTEX_ORDERING
2047 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2049 node->vert_index = -4;
2055 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2079 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2081 if (node->vert_index == -1)
2091 for (
int i = 0; i < sfc_order.Size(); i++)
2096 for (
int i = 0; i < sfc_order.Size(); i++)
2099 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2109 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2111 if (node->HasVertex() && node->vert_index >= 0)
2122 for (
int i = 0; i < sfc_order.Size(); i++)
2125 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2135 #else // old ordering for debugging/testing only
2136 bool parallel =
false;
2138 if (dynamic_cast<ParNCMesh*>(
this)) { parallel =
true; }
2144 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2146 if (node->HasVertex()) { node->vert_index =
NVertices++; }
2152 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2159 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2161 if (node->HasVertex()) { node->vert_index = -1; }
2170 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2172 int &vindex =
nodes[el.
node[j]].vert_index;
2173 if (vindex < 0) { vindex =
NVertices++; }
2179 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2181 if (node->HasVertex() && node->vert_index >= 0)
2188 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2190 if (node->HasVertex() && node->vert_index < 0)
2211 node_order = (
char*) quad_hilbert_child_order;
2216 node_order = (
char*) hex_hilbert_child_order;
2223 int entry_node = -2;
2226 for (
int i = 0; i < root_count; i++)
2231 if (v_in < 0) { v_in = 0; }
2234 bool shared[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2235 if (i+1 < root_count)
2238 for (
int j = 0; j < nch; j++)
2241 if (node >= 0) { shared[node] =
true; }
2246 int state =
Dim*v_in;
2247 for (
int j = 0; j <
Dim; j++)
2249 if (shared[(
int) node_order[nch*(state + j) + nch-1]])
2258 entry_node =
RetrieveNode(el, node_order[nch*state + nch-1]);
2272 MFEM_ABORT(
"invalid geometry");
2287 MFEM_VERIFY(tv.
visited ==
false,
"cyclic vertex dependencies.");
2293 for (
int i = 0; i < 3; i++)
2295 tv.
pos[i] = (pos1[i] + pos2[i]) * 0.5;
2308 for (
int i = 0; i < mesh.
vertices.Size(); i++)
2327 const int* node = nc_elem.
node;
2334 for (
int j = 0; j < gi.
nv; j++)
2336 elem->GetVertices()[j] =
nodes[node[j]].vert_index;
2341 for (
int k = 0; k < gi.
nf; k++)
2343 const int* fv = gi.
faces[k];
2344 const int nfv = gi.
nfv[k];
2345 const Face* face =
faces.Find(node[fv[0]], node[fv[1]],
2346 node[fv[2]], node[fv[3]]);
2354 for (
int j = 0; j < 4; j++)
2356 quad->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2363 MFEM_ASSERT(nfv == 3,
"");
2366 for (
int j = 0; j < 3; j++)
2368 tri->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2377 for (
int j = 0; j < 2; j++)
2379 segment->GetVertices()[j] =
nodes[node[fv[2*j]]].vert_index;
2388 point->GetVertices()[0] =
nodes[node[fv[0]]].vert_index;
2404 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2406 if (node->HasEdge()) { node->edge_index = -1; }
2408 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2415 for (
int i = 0; i < edge_vertex->
Size(); i++)
2417 const int *ev = edge_vertex->
GetRow(i);
2420 MFEM_ASSERT(node && node->
HasEdge(),
2421 "edge (" << ev[0] <<
"," << ev[1] <<
") not found, "
2429 for (
int i = 0; i <
NFaces; i++)
2431 const int* fv = mesh->
GetFace(i)->GetVertices();
2432 const int nfv = mesh->
GetFace(i)->GetNVertices();
2445 MFEM_ASSERT(nfv == 3,
"");
2453 MFEM_ASSERT(nfv == 2,
"");
2456 face =
faces.Find(n0, n0, n1, n1);
2460 const int *ev = edge_vertex->
GetRow(i);
2461 MFEM_ASSERT((ev[0] == fv[0] && ev[1] == fv[1]) ||
2462 (ev[1] == fv[0] && ev[0] == fv[1]),
"");
2466 MFEM_VERIFY(face,
"face not found.");
2474 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2476 if (node->HasEdge() && node->edge_index < 0)
2484 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2492 MFEM_ASSERT(NFaces ==
NEdges,
"");
2507 for (
int j = 0; j < gi.
nf; j++)
2509 const int *fv = gi.
faces[j];
2512 MFEM_ASSERT(face,
"face not found!");
2514 if (face->
index < 0)
2516 face->
index = NFaces + (nghosts++);
2530 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2532 if (face->index < 0) { face->index = NFaces + (nghosts++); }
2543 MFEM_ASSERT(
Dim >= 3,
"");
2552 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3, mid[3] = e4; }
2555 int midf1 = -1, midf2 = -1;
2560 if (midf1 >= 0 && midf1 == midf2)
2563 if (nd.
p1 != e1 && nd.
p2 != e1) { midf1 = -1; }
2564 if (nd.
p1 != e2 && nd.
p2 != e2) { midf2 = -1; }
2568 MFEM_ASSERT(!(midf1 >= 0 && midf2 >= 0),
"incorrectly split face!");
2570 if (midf1 < 0 && midf2 < 0)
2572 if (mid) { mid[4] = -1; }
2575 else if (midf1 >= 0)
2577 if (mid) { mid[4] = midf1; }
2582 if (mid) { mid[4] = midf2; }
2589 int e1 =
nodes.FindId(v1, v2);
2590 if (e1 < 0 || !
nodes[e1].HasVertex()) {
return false; }
2592 int e2 =
nodes.FindId(v2, v3);
2593 if (e2 < 0 || !
nodes[e2].HasVertex()) {
return false; }
2595 int e3 =
nodes.FindId(v3, v1);
2596 if (e3 < 0 || !
nodes[e3].HasVertex()) {
return false; }
2598 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3; }
2606 for (
int i = 0; i < 8; i++)
2608 if (el.
node[i] == node) {
return i; }
2610 MFEM_ABORT(
"Node not found.");
2616 for (
int i = 0; i <
GI[el.
Geom()].
nv; i++)
2620 if (abort) { MFEM_ABORT(
"Node not found."); }
2629 for (
int i = 0; i < gi.
ne; i++)
2631 const int* ev = gi.
edges[i];
2632 int n0 = el.
node[ev[0]];
2633 int n1 = el.
node[ev[1]];
2634 if ((n0 == vn0 && n1 == vn1) ||
2635 (n0 == vn1 && n1 == vn0)) {
return i; }
2638 if (abort) { MFEM_ABORT(
"Edge (" << vn0 <<
", " << vn1 <<
") not found"); }
2645 for (
int i = 0; i < gi.
nf; i++)
2647 const int* fv = gi.
faces[i];
2648 if ((a == fv[0] || a == fv[1] || a == fv[2] || a == fv[3]) &&
2649 (b == fv[0] || b == fv[1] || b == fv[2] || b == fv[3]) &&
2650 (c == fv[0] || c == fv[1] || c == fv[2] || c == fv[3]))
2655 MFEM_ABORT(
"Face not found.");
2665 MFEM_ASSERT(
sizeof(
double) ==
sizeof(std::uint64_t),
"");
2669 std::uint64_t hash = 0xf9ca9ba106acbba9;
2670 for (
int i = 0; i < pm.
np; i++)
2672 for (
int j = 0; j < pm.
points[i].
dim; j++)
2677 hash = 31*hash + *((std::uint64_t*) &coord);
2689 int GetIndex(
const NCMesh::PointMatrix &pm)
2691 int &
index = map[pm];
2692 if (!index) { index = map.size(); }
2696 void ExportMatrices(Array<DenseMatrix*> &point_matrices)
const
2698 point_matrices.SetSize(map.size());
2699 for (
const auto &pair : map)
2701 DenseMatrix* mat =
new DenseMatrix();
2702 pair.first.GetMatrix(*mat);
2703 point_matrices[pair.second - 1] = mat;
2707 void DumpBucketSizes()
const
2709 for (
unsigned i = 0; i < map.bucket_count(); i++)
2716 std::unordered_map<NCMesh::PointMatrix, int, PointMatrixHash> map;
2730 int nfv = (v3 >= 0) ? 4 : 3;
2735 reordered.
np = pm.
np;
2736 for (
int i = 0, j; i < nfv; i++)
2738 for (j = 0; j < nfv; j++)
2740 if (fv[i] == master[j])
2746 MFEM_ASSERT(j != nfv,
"node not found.");
2758 Face* fa =
faces.Find(vn0, vn1, vn2, vn3);
2770 sl.
matrix = matrix_map.GetIndex(pm_r);
2772 eface[0] = eface[2] = fa;
2773 eface[1] = eface[3] = fa;
2786 Point pmid0(pm(0), pm(1)), pmid2(pm(2), pm(3));
2790 level+1, ef[0], matrix_map);
2794 level+1, ef[1], matrix_map);
2796 eface[1] = ef[1][1];
2797 eface[3] = ef[0][3];
2798 eface[0] = eface[2] = NULL;
2800 else if (split == 2)
2802 Point pmid1(pm(1), pm(2)), pmid3(pm(3), pm(0));
2806 level+1, ef[0], matrix_map);
2810 level+1, ef[1], matrix_map);
2812 eface[0] = ef[0][0];
2813 eface[2] = ef[1][2];
2814 eface[1] = eface[3] = NULL;
2825 const int fi[3][2] = {{0, 0}, {1, 3}, {2, 0}};
2826 if (!ef[0][fi[split][0]] && !ef[1][fi[split][1]])
2836 MFEM_ASSERT(eid.
Size() > 0,
"edge prism not found");
2837 MFEM_ASSERT(eid.
Size() < 2,
"non-unique edge prism");
2847 Point mid0(pm(0), pm(1)), mid2(pm(2), pm(3));
2848 int v1 =
nodes[mid[0]].vert_index;
2849 int v2 =
nodes[mid[2]].vert_index;
2851 matrix_map.GetIndex(
2857 Point mid1(pm(1), pm(2)), mid3(pm(3), pm(0));
2858 int v1 =
nodes[mid[1]].vert_index;
2859 int v2 =
nodes[mid[3]].vert_index;
2861 matrix_map.GetIndex(
2873 int mid =
nodes.FindId(vn0, vn1);
2874 if (mid < 0) {
return; }
2890 int v0index =
nodes[vn0].vert_index;
2891 int v1index =
nodes[vn1].vert_index;
2894 matrix_map.GetIndex((v0index < v1index) ?
PointMatrix(p0, p1, p0)
2926 sl.
matrix = matrix_map.GetIndex(pm_r);
2935 Point pmid0(pm(0), pm(1)), pmid1(pm(1), pm(2)), pmid2(pm(2), pm(0));
2940 level+1, matrix_map);
2944 level+1, matrix_map);
2948 level+1, matrix_map);
2952 level+1, matrix_map);
2957 if (!b[1]) {
TraverseTetEdge(mid[0],mid[1], pmid0,pmid1, matrix_map); }
2958 if (!b[2]) {
TraverseTetEdge(mid[1],mid[2], pmid1,pmid2, matrix_map); }
2959 if (!b[0]) {
TraverseTetEdge(mid[2],mid[0], pmid2,pmid0, matrix_map); }
2969 if (
Dim < 3) {
return; }
2976 processed_faces = 0;
2985 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
2988 for (
int j = 0; j < gi.
nf; j++)
2992 for (
int k = 0; k < 4; k++)
2997 int face =
faces.FindId(node[0], node[1], node[2], node[3]);
2998 MFEM_ASSERT(face >= 0,
"face not found!");
3004 if (processed_faces[face]) {
continue; }
3005 processed_faces[face] = 1;
3010 if (fa.
elem[0] >= 0 && fa.
elem[1] >= 0)
3040 for (
int ii = sb; ii < se; ii++)
3061 int mid =
nodes.FindId(vn0, vn1);
3062 if (mid < 0) {
return; }
3065 if (nd.
HasEdge() && level > 0)
3075 int v0index =
nodes[vn0].vert_index;
3076 int v1index =
nodes[vn1].vert_index;
3077 if (v0index > v1index) { sl.
edge_flags |= 2; }
3081 double tmid = (t0 + t1) / 2;
3082 TraverseEdge(vn0, mid, t0, tmid, flags, level+1, matrix_map);
3083 TraverseEdge(mid, vn1, tmid, t1, flags, level+1, matrix_map);
3092 processed_edges = 0;
3105 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3108 for (
int j = 0; j < gi.
ne; j++)
3111 const int* ev = gi.
edges[j];
3112 int node[2] = { el.
node[ev[0]], el.
node[ev[1]] };
3114 int enode =
nodes.FindId(node[0], node[1]);
3115 MFEM_ASSERT(enode >= 0,
"edge node not found!");
3118 MFEM_ASSERT(nd.
HasEdge(),
"edge not found!");
3126 int face =
faces.FindId(node[0], node[0], node[1], node[1]);
3127 MFEM_ASSERT(face >= 0,
"face not found!");
3139 if (processed_edges[enode]) {
continue; }
3140 processed_edges[enode] = 1;
3143 double t0 = 0.0, t1 = 1.0;
3144 int v0index =
nodes[node[0]].vert_index;
3145 int v1index =
nodes[node[1]].vert_index;
3146 int flags = (v0index > v1index) ? 1 : 0;
3150 TraverseEdge(node[0], node[1], t0, t1, flags, 0, matrix_map);
3160 for (
int ii = sb; ii < se; ii++)
3177 int local = edge_local[sl.
index];
3197 processed_vertices = 0;
3205 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
3207 int node = el.
node[j];
3215 if (processed_vertices[index]) {
continue; }
3216 processed_vertices[
index] = 1;
3227 oriented_matrix = *(point_matrices[slave.
Geom()][slave.
matrix]);
3231 MFEM_ASSERT(oriented_matrix.
Height() == 1 &&
3232 oriented_matrix.
Width() == 2,
"not an edge point matrix");
3236 oriented_matrix(0,0) = 1.0 - oriented_matrix(0,0);
3237 oriented_matrix(0,1) = 1.0 - oriented_matrix(0,1);
3241 std::swap(oriented_matrix(0,0), oriented_matrix(0,1));
3248 conforming.DeleteAll();
3249 masters.DeleteAll();
3254 for (
int j = 0; j < point_matrices[i].Size(); j++)
3256 delete point_matrices[i][j];
3258 point_matrices[i].DeleteAll();
3261 inv_index.DeleteAll();
3266 return conforming.Size() + masters.Size() + slaves.Size();
3271 if (!inv_index.Size())
3274 for (
int i = 0; i < conforming.Size(); i++)
3276 max_index = std::max(conforming[i].index, max_index);
3278 for (
int i = 0; i < masters.Size(); i++)
3280 max_index = std::max(masters[i].index, max_index);
3282 for (
int i = 0; i < slaves.Size(); i++)
3284 if (slaves[i].index < 0) {
continue; }
3285 max_index = std::max(slaves[i].index, max_index);
3288 inv_index.SetSize(max_index + 1);
3291 for (
int i = 0; i < conforming.Size(); i++)
3293 inv_index[conforming[i].index] = (i << 2);
3295 for (
int i = 0; i < masters.Size(); i++)
3297 inv_index[masters[i].index] = (i << 2) + 1;
3299 for (
int i = 0; i < slaves.Size(); i++)
3301 if (slaves[i].index < 0) {
continue; }
3302 inv_index[slaves[i].index] = (i << 2) + 2;
3306 MFEM_ASSERT(index >= 0 && index < inv_index.Size(),
"");
3307 int key = inv_index[
index];
3311 MFEM_VERIFY(key >= 0,
"entity not found.");
3315 *type = (key >= 0) ? (key & 0x3) : -1;
3318 if (*type < 0) {
return invalid; }
3324 case 0:
return conforming[key >> 2];
3325 case 1:
return masters[key >> 2];
3326 case 2:
return slaves[key >> 2];
3327 default: MFEM_ABORT(
"internal error");
return conforming[0];
3336 int mid =
nodes.FindId(v0, v1);
3337 if (mid >= 0 &&
nodes[mid].HasVertex())
3351 for (
int i = 0; i < 3; i++)
3408 int** JJ =
new int*[nrows];
3418 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3421 int* node = el.
node;
3424 for (
int j = 0; j < gi.
ne; j++)
3426 const int* ev = gi.
edges[j];
3432 for (
int j = 0; j < gi.
nf; j++)
3434 const int* fv = gi.
faces[j];
3438 node[fv[2]], node[fv[3]], indices);
3451 int size = indices.
Size();
3453 JJ[i] =
new int[size];
3454 std::memcpy(JJ[i], indices.
GetData(), size *
sizeof(int));
3459 for (
int i = 0; i < nrows; i++)
3470 for (
int i = 0; i < nrows; i++)
3472 int cnt = I[i+1] - I[i];
3473 std::memcpy(J+nnz, JJ[i], cnt *
sizeof(
int));
3500 MFEM_VERIFY(elem_set.
Size() == nleaves,
"");
3509 for (
int i = 0; i < nleaves; i++)
3515 for (
int j = 0; j < nv; j++)
3522 for (
int j = 0; j < nv; j++)
3524 vmark[el.
node[j]] = 1;
3535 neighbor_set->
SetSize(nleaves);
3539 for (
int i = 0; i < nleaves; i++)
3547 for (
int j = 0; j < nv; j++)
3549 if (vmark[v[j]]) { hit =
true;
break; }
3556 for (
int j = 0; j < nv; j++)
3558 if (vmark[el.
node[j]]) { hit =
true;
break; }
3565 if (neighbor_set) { (*neighbor_set)[i] = 1; }
3571 static bool sorted_lists_intersect(
const int*
a,
const int*
b,
int na,
int nb)
3573 if (!na || !nb) {
return false; }
3574 int a_last = a[na-1], b_last = b[nb-1];
3575 if (*b < *a) {
goto l2; }
3577 if (a_last < *b) {
return false; }
3578 while (*a < *b) { a++; }
3579 if (*a == *b) {
return true; }
3581 if (b_last < *a) {
return false; }
3582 while (*b < *a) { b++; }
3583 if (*a == *b) {
return true; }
3606 while (stack.
Size())
3615 for (
int i = 0; i < nv; i++)
3621 for (
int i = 0; i < nv; i++)
3628 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
3639 int nv1 = vert.
Size();
3644 for (
int i = 0; i < search_set->
Size(); i++)
3646 int testme = (*search_set)[i];
3653 bool hit = sorted_lists_intersect(v1, v2, nv1, nv2);
3658 for (
int j = 0; j < nv; j++)
3660 hit = sorted_lists_intersect(&el.
node[j], v1, 1, nv1);
3665 if (hit) { neighbors.
Append(testme); }
3679 for (
int i = 0; i < elems.
Size(); i++)
3685 for (
int j = 0; j < nv; j++)
3691 for (
int j = 0; j < nv; j++)
3693 vmark[el.
node[j]] = 1;
3703 for (
int i = 0; i < search_set->
Size(); i++)
3705 int testme = (*search_set)[i];
3711 for (
int j = 0; j < nv; j++)
3713 if (vmark[v[j]]) { hit =
true;
break; }
3719 for (
int j = 0; j < nv; j++)
3721 if (vmark[el.
node[j]]) { hit =
true;
break; }
3725 if (hit) { expanded.
Append(testme); }
3734 if (el.
parent < 0) {
return elem; }
3737 MFEM_ASSERT(pa.
ref_type,
"internal error");
3740 while (ch < 8 && pa.
child[ch] != elem) { ch++; }
3741 MFEM_ASSERT(ch < 8,
"internal error");
3743 MFEM_ASSERT(geom_parent[el.
Geom()],
"unsupported geometry");
3744 const RefTrf &tr = geom_parent[el.
Geom()][(int) pa.
ref_type][ch];
3745 tr.Apply(coord, coord);
3756 return (pt[0] >= 0) && (pt[0] <= T_ONE) &&
3757 (pt[1] >= 0) && (pt[1] <= T_ONE);
3760 return (pt[0] >= 0) && (pt[0] <= T_ONE) &&
3761 (pt[1] >= 0) && (pt[1] <= T_ONE) &&
3762 (pt[2] >= 0) && (pt[2] <= T_ONE);
3765 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE);
3768 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE) &&
3769 (pt[2] >= 0) && (pt[2] <= T_ONE);
3772 MFEM_ABORT(
"unsupported geometry");
3788 for (
int ch = 0; ch < 8 && el.
child[ch] >= 0; ch++)
3790 const RefTrf &tr = geom_child[el.
Geom()][(int) el.
ref_type][ch];
3791 tr.Apply(coord, tcoord);
3793 if (RefPointInside(el.
Geom(), tcoord))
3805 MFEM_ASSERT(geom_corners[el.
Geom()],
"unsupported geometry");
3806 std::memcpy(coord, geom_corners[el.
Geom()][local],
sizeof(coord));
3819 MFEM_ASSERT(np == pm.
np,
"");
3820 for (
int i = 0; i < np; i++)
3823 for (
int j = 0; j < points[i].dim; j++)
3825 if (points[i].coord[j] != pm.
points[i].
coord[j]) {
return false; }
3834 for (
int i = 0; i < np; i++)
3836 for (
int j = 0; j < points[0].dim; j++)
3838 point_matrix(j, i) = points[i].coord[j];
3853 Point(0, 0, 0),
Point(1, 0, 0),
Point(0, 1, 0),
Point(0, 0, 1)
3860 Point(0, 0, 0),
Point(1, 0, 0),
Point(1, 1, 0),
Point(0, 1, 0),
3861 Point(0, 0, 1),
Point(1, 0, 1),
Point(1, 1, 1),
Point(0, 1, 1)
3875 MFEM_ABORT(
"unsupported geometry " << geom);
3887 int ref_type = *ref_path++;
3888 int child = *ref_path++;
3896 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3897 Point mid67(pm(6), pm(7)), mid45(pm(4), pm(5));
3902 pm(4), mid45, mid67, pm(7));
3904 else if (child == 1)
3907 mid45, pm(5), pm(6), mid67);
3910 else if (ref_type == 2)
3912 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3913 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
3918 pm(4), pm(5), mid56, mid74);
3920 else if (child == 1)
3923 mid74, mid56, pm(6), pm(7));
3926 else if (ref_type == 4)
3928 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3929 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3934 mid04, mid15, mid26, mid37);
3936 else if (child == 1)
3939 pm(4), pm(5), pm(6), pm(7));
3942 else if (ref_type == 3)
3944 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3945 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
3946 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
3947 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
3949 Point midf0(mid23, mid12, mid01, mid30);
3950 Point midf5(mid45, mid56, mid67, mid74);
3955 pm(4), mid45, midf5, mid74);
3957 else if (child == 1)
3960 mid45, pm(5), mid56, midf5);
3962 else if (child == 2)
3965 midf5, mid56, pm(6), mid67);
3967 else if (child == 3)
3970 mid74, midf5, mid67, pm(7));
3973 else if (ref_type == 5)
3975 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3976 Point mid45(pm(4), pm(5)), mid67(pm(6), pm(7));
3977 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3978 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3980 Point midf1(mid01, mid15, mid45, mid04);
3981 Point midf3(mid23, mid37, mid67, mid26);
3986 mid04, midf1, midf3, mid37);
3988 else if (child == 1)
3991 midf1, mid15, mid26, midf3);
3993 else if (child == 2)
3996 mid45, pm(5), pm(6), mid67);
3998 else if (child == 3)
4001 pm(4), mid45, mid67, pm(7));
4004 else if (ref_type == 6)
4006 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
4007 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
4008 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
4009 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
4011 Point midf2(mid12, mid26, mid56, mid15);
4012 Point midf4(mid30, mid04, mid74, mid37);
4017 mid04, mid15, midf2, midf4);
4019 else if (child == 1)
4022 midf4, midf2, mid26, mid37);
4024 else if (child == 2)
4027 pm(4), pm(5), mid56, mid74);
4029 else if (child == 3)
4032 mid74, mid56, pm(6), pm(7));
4035 else if (ref_type == 7)
4037 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4038 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
4039 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
4040 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
4041 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
4042 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
4044 Point midf0(mid23, mid12, mid01, mid30);
4045 Point midf1(mid01, mid15, mid45, mid04);
4046 Point midf2(mid12, mid26, mid56, mid15);
4047 Point midf3(mid23, mid37, mid67, mid26);
4048 Point midf4(mid30, mid04, mid74, mid37);
4049 Point midf5(mid45, mid56, mid67, mid74);
4051 Point midel(midf1, midf3);
4056 mid04, midf1, midel, midf4);
4058 else if (child == 1)
4061 midf1, mid15, midf2, midel);
4063 else if (child == 2)
4066 midel, midf2, mid26, midf3);
4068 else if (child == 3)
4071 midf4, midel, midf3, mid37);
4073 else if (child == 4)
4076 pm(4), mid45, midf5, mid74);
4078 else if (child == 5)
4081 mid45, pm(5), mid56, midf5);
4083 else if (child == 6)
4086 midf5, mid56, pm(6), mid67);
4088 else if (child == 7)
4091 mid74, midf5, mid67, pm(7));
4099 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4100 Point mid20(pm(2), pm(0)), mid34(pm(3), pm(4));
4101 Point mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
4105 pm =
PointMatrix(pm(0), mid01, mid20, pm(3), mid34, mid53);
4107 else if (child == 1)
4109 pm =
PointMatrix(mid01, pm(1), mid12, mid34, pm(4), mid45);
4111 else if (child == 2)
4113 pm =
PointMatrix(mid20, mid12, pm(2), mid53, mid45, pm(5));
4115 else if (child == 3)
4117 pm =
PointMatrix(mid12, mid20, mid01, mid45, mid53, mid34);
4120 else if (ref_type == 4)
4122 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
4126 pm =
PointMatrix(pm(0), pm(1), pm(2), mid03, mid14, mid25);
4128 else if (child == 1)
4130 pm =
PointMatrix(mid03, mid14, mid25, pm(3), pm(4), pm(5));
4135 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
4136 Point mid34(pm(3), pm(4)), mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
4137 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
4139 Point midf2(mid01, mid14, mid34, mid03);
4140 Point midf3(mid12, mid25, mid45, mid14);
4141 Point midf4(mid20, mid03, mid53, mid25);
4145 pm =
PointMatrix(pm(0), mid01, mid20, mid03, midf2, midf4);
4147 else if (child == 1)
4149 pm =
PointMatrix(mid01, pm(1), mid12, midf2, mid14, midf3);
4151 else if (child == 2)
4153 pm =
PointMatrix(mid20, mid12, pm(2), midf4, midf3, mid25);
4155 else if (child == 3)
4157 pm =
PointMatrix(mid12, mid20, mid01, midf3, midf4, midf2);
4159 else if (child == 4)
4161 pm =
PointMatrix(mid03, midf2, midf4, pm(3), mid34, mid53);
4163 else if (child == 5)
4165 pm =
PointMatrix(midf2, mid14, midf3, mid34, pm(4), mid45);
4167 else if (child == 6)
4169 pm =
PointMatrix(midf4, midf3, mid25, mid53, mid45, pm(5));
4171 else if (child == 7)
4173 pm =
PointMatrix(midf3, midf4, midf2, mid45, mid53, mid34);
4179 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid02(pm(2), pm(0));
4180 Point mid03(pm(0), pm(3)), mid13(pm(1), pm(3)), mid23(pm(2), pm(3));
4186 else if (child == 1)
4190 else if (child == 2)
4194 else if (child == 3)
4198 else if (child == 4)
4202 else if (child == 5)
4206 else if (child == 6)
4210 else if (child == 7)
4219 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
4225 else if (child == 1)
4230 else if (ref_type == 2)
4232 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
4238 else if (child == 1)
4243 else if (ref_type == 3)
4245 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4246 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
4247 Point midel(mid01, mid23);
4253 else if (child == 1)
4257 else if (child == 2)
4261 else if (child == 3)
4269 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
4275 else if (child == 1)
4279 else if (child == 2)
4283 else if (child == 3)
4291 for (
int i = 0; i < pm.
np; i++)
4293 for (
int j = 0; j < pm(i).dim; j++)
4295 matrix(j, i) = pm(i).coord[j];
4320 int &matrix = map[ref_path];
4321 if (!matrix) { matrix = map.size(); }
4324 emb.
parent = coarse_index;
4331 MFEM_ASSERT(el.
tet_type == 0,
"not implemented");
4334 ref_path.push_back(0);
4336 for (
int i = 0; i < 8; i++)
4338 if (el.
child[i] >= 0)
4340 ref_path[ref_path.length()-1] = i;
4344 ref_path.resize(ref_path.length()-2);
4351 "GetRefinementTransforms() must be preceded by MarkCoarseLevel()"
4359 std::string ref_path;
4360 ref_path.reserve(100);
4365 path_map[g][ref_path] = 1;
4373 used_geoms |= (1 << geom);
4378 if (used_geoms & (1 << g))
4387 RefPathMap::iterator it;
4388 for (it = path_map[g].begin(); it != path_map[g].end(); ++it)
4402 "GetDerefinementTransforms() must be preceded by Derefine().");
4419 int &matrix = mat_no[emb.
geom][code];
4420 if (!matrix) { matrix = mat_no[emb.
geom].size(); }
4428 if (
Geoms & (1 << g))
4437 for (
auto it = mat_no[geom].begin(); it != mat_no[geom].end(); ++it)
4439 char path[3] = { 0, 0, 0 };
4441 int code = it->first;
4444 path[0] = code >> 4;
4445 path[1] = code & 0xf;
4458 bool want_ghosts)
const
4461 conn.
Reserve(embeddings.Size());
4463 int max_parent = -1;
4464 for (
int i = 0; i < embeddings.Size(); i++)
4468 (!emb.
ghost || want_ghosts))
4471 max_parent = std::max(emb.
parent, max_parent);
4489 point_matrices[i].SetSize(0, 0, 0);
4491 embeddings.DeleteAll();
4499 if (point_matrices[i].SizeK()) {
return true; }
4516 static int sgn(
int x)
4518 return (x < 0) ? -1 : (x > 0) ? 1 : 0;
4521 static void HilbertSfc2D(
int x,
int y,
int ax,
int ay,
int bx,
int by,
4524 int w = std::abs(ax + ay);
4525 int h = std::abs(bx + by);
4527 int dax = sgn(ax), day = sgn(ay);
4528 int dbx = sgn(bx), dby = sgn(by);
4532 for (
int i = 0; i < w; i++, x += dax, y += day)
4541 for (
int i = 0; i < h; i++, x += dbx, y += dby)
4549 int ax2 = ax/2, ay2 = ay/2;
4550 int bx2 = bx/2, by2 = by/2;
4552 int w2 = std::abs(ax2 + ay2);
4553 int h2 = std::abs(bx2 + by2);
4557 if ((w2 & 0x1) && (w > 2))
4559 ax2 += dax, ay2 += day;
4562 HilbertSfc2D(x, y, ax2, ay2, bx, by, coords);
4563 HilbertSfc2D(x+ax2, y+ay2, ax-ax2, ay-ay2, bx, by, coords);
4567 if ((h2 & 0x1) && (h > 2))
4569 bx2 += dbx, by2 += dby;
4572 HilbertSfc2D(x, y, bx2, by2, ax2, ay2, coords);
4573 HilbertSfc2D(x+bx2, y+by2, ax, ay, bx-bx2, by-by2, coords);
4574 HilbertSfc2D(x+(ax-dax)+(bx2-dbx), y+(ay-day)+(by2-dby),
4575 -bx2, -by2, -(ax-ax2), -(ay-ay2), coords);
4579 static void HilbertSfc3D(
int x,
int y,
int z,
4580 int ax,
int ay,
int az,
4581 int bx,
int by,
int bz,
4582 int cx,
int cy,
int cz,
4585 int w = std::abs(ax + ay + az);
4586 int h = std::abs(bx + by + bz);
4587 int d = std::abs(cx + cy + cz);
4589 int dax = sgn(ax), day = sgn(ay), daz = sgn(az);
4590 int dbx = sgn(bx), dby = sgn(by), dbz = sgn(bz);
4591 int dcx = sgn(cx), dcy = sgn(cy), dcz = sgn(cz);
4594 if (h == 1 && d == 1)
4596 for (
int i = 0; i < w; i++, x += dax, y += day, z += daz)
4604 if (w == 1 && d == 1)
4606 for (
int i = 0; i < h; i++, x += dbx, y += dby, z += dbz)
4614 if (w == 1 && h == 1)
4616 for (
int i = 0; i < d; i++, x += dcx, y += dcy, z += dcz)
4625 int ax2 = ax/2, ay2 = ay/2, az2 = az/2;
4626 int bx2 = bx/2, by2 = by/2, bz2 = bz/2;
4627 int cx2 = cx/2, cy2 = cy/2, cz2 = cz/2;
4629 int w2 = std::abs(ax2 + ay2 + az2);
4630 int h2 = std::abs(bx2 + by2 + bz2);
4631 int d2 = std::abs(cx2 + cy2 + cz2);
4634 if ((w2 & 0x1) && (w > 2))
4636 ax2 += dax, ay2 += day, az2 += daz;
4638 if ((h2 & 0x1) && (h > 2))
4640 bx2 += dbx, by2 += dby, bz2 += dbz;
4642 if ((d2 & 0x1) && (d > 2))
4644 cx2 += dcx, cy2 += dcy, cz2 += dcz;
4648 if ((2*w > 3*h) && (2*w > 3*d))
4650 HilbertSfc3D(x, y, z,
4653 cx, cy, cz, coords);
4655 HilbertSfc3D(x+ax2, y+ay2, z+az2,
4656 ax-ax2, ay-ay2, az-az2,
4658 cx, cy, cz, coords);
4663 HilbertSfc3D(x, y, z,
4666 ax2, ay2, az2, coords);
4668 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4670 bx-bx2, by-by2, bz-bz2,
4671 cx, cy, cz, coords);
4673 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4674 y+(ay-day)+(by2-dby),
4675 z+(az-daz)+(bz2-dbz),
4678 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4683 HilbertSfc3D(x, y, z,
4686 bx, by, bz, coords);
4688 HilbertSfc3D(x+cx2, y+cy2, z+cz2,
4691 cx-cx2, cy-cy2, cz-cz2, coords);
4693 HilbertSfc3D(x+(ax-dax)+(cx2-dcx),
4694 y+(ay-day)+(cy2-dcy),
4695 z+(az-daz)+(cz2-dcz),
4697 -(ax-ax2), -(ay-ay2), -(az-az2),
4698 bx, by, bz, coords);
4703 HilbertSfc3D(x, y, z,
4706 ax2, ay2, az2, coords);
4708 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4711 bx-bx2, by-by2, bz-bz2, coords);
4713 HilbertSfc3D(x+(bx2-dbx)+(cx-dcx),
4714 y+(by2-dby)+(cy-dcy),
4715 z+(bz2-dbz)+(cz-dcz),
4718 -(cx-cx2), -(cy-cy2), -(cz-cz2), coords);
4720 HilbertSfc3D(x+(ax-dax)+bx2+(cx-dcx),
4721 y+(ay-day)+by2+(cy-dcy),
4722 z+(az-daz)+bz2+(cz-dcz),
4724 -(ax-ax2), -(ay-ay2), -(az-az2),
4725 bx-bx2, by-by2, bz-bz2, coords);
4727 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4728 y+(ay-day)+(by2-dby),
4729 z+(az-daz)+(bz2-dbz),
4732 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4739 coords.
Reserve(2*width*height);
4741 if (width >= height)
4743 HilbertSfc2D(0, 0, width, 0, 0, height, coords);
4747 HilbertSfc2D(0, 0, 0, height, width, 0, coords);
4755 coords.
Reserve(3*width*height*depth);
4757 if (width >= height && width >= depth)
4759 HilbertSfc3D(0, 0, 0,
4762 0, 0, depth, coords);
4764 else if (height >= width && height >= depth)
4766 HilbertSfc3D(0, 0, 0,
4769 0, 0, depth, coords);
4773 HilbertSfc3D(0, 0, 0,
4776 0, height, 0, coords);
4784 bool oriented)
const
4788 const int* ev = gi.
edges[(int) edge_id.
local];
4790 int n0 = el.
node[ev[0]], n1 = el.
node[ev[1]];
4791 if (n0 > n1) { std::swap(n0, n1); }
4793 vert_index[0] =
nodes[n0].vert_index;
4794 vert_index[1] =
nodes[n1].vert_index;
4796 if (oriented && vert_index[0] > vert_index[1])
4798 std::swap(vert_index[0], vert_index[1]);
4806 const int* ev = gi.
edges[(int) edge_id.
local];
4808 int v0 =
nodes[el.
node[ev[0]]].vert_index;
4809 int v1 =
nodes[el.
node[ev[1]]].vert_index;
4811 return ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1])) ? -1 : 1;
4815 int vert_index[4],
int edge_index[4],
4816 int edge_orientation[4])
const
4818 MFEM_ASSERT(
Dim >= 3,
"");
4823 const int *fv = gi.
faces[(int) face_id.
local];
4824 const int nfv = gi.
nfv[(
int) face_id.
local];
4826 vert_index[3] = edge_index[3] = -1;
4827 edge_orientation[3] = 0;
4829 for (
int i = 0; i < nfv; i++)
4831 vert_index[i] =
nodes[el.
node[fv[i]]].vert_index;
4834 for (
int i = 0; i < nfv; i++)
4837 if (j >= nfv) { j = 0; }
4839 int n1 = el.
node[fv[i]];
4840 int n2 = el.
node[fv[j]];
4843 MFEM_ASSERT(en != NULL,
"edge not found.");
4846 edge_orientation[i] = (vert_index[i] < vert_index[j]) ? 1 : -1;
4854 MFEM_ASSERT(node >= 0,
"edge node not found.");
4857 int p1 = nd.
p1, p2 = nd.
p2;
4858 MFEM_ASSERT(p1 != p2,
"invalid edge node.");
4862 int n1p1 = n1.
p1, n1p2 = n1.
p2;
4863 int n2p1 = n2.p1, n2p2 = n2.p2;
4865 if ((n2p1 != n2p2) && (p1 == n2p1 || p1 == n2p2))
4869 if (n2.HasEdge()) {
return p2; }
4873 if ((n1p1 != n1p2) && (p2 == n1p1 || p2 == n1p2))
4877 if (n1.
HasEdge()) {
return p1; }
4887 MFEM_ASSERT(node >= 0 &&
nodes[node].HasEdge(),
"(v1, v2) is not an edge.");
4890 return (master >= 0) ?
nodes[master].edge_index : -1;
4896 int depth = 0, parent;
4897 while ((parent =
elements[elem].parent) != -1)
4908 int parent, reduction = 1;
4909 while ((parent =
elements[elem].parent) != -1)
4911 if (
elements[parent].ref_type & 1) { reduction *= 2; }
4912 if (
elements[parent].ref_type & 2) { reduction *= 2; }
4913 if (
elements[parent].ref_type & 4) { reduction *= 2; }
4929 for (
int i = 0; i < gi.
nf; i++)
4931 const int* fv = gi.
faces[i];
4934 MFEM_ASSERT(face,
"face not found");
4935 face_indices[i] = face->
index;
4947 int elem = fa.
elem[0];
4948 if (elem < 0) { elem = fa.
elem[1]; }
4949 MFEM_ASSERT(elem >= 0,
"Face has no elements?");
4958 for (
int i = 0; i < 4; i++)
4960 node[i] = el.
node[fv[i]];
4977 if (bdr_attr_is_ess[
faces[face].attribute - 1])
4981 int nfv = (node[3] < 0) ? 3 : 4;
4983 for (
int j = 0; j < nfv; j++)
4987 int enode =
nodes.FindId(node[j], node[(j+1) % nfv]);
4988 MFEM_ASSERT(enode >= 0 &&
nodes[enode].HasEdge(),
"Edge not found.");
5017 bdr_vertices.
Sort();
5024 static int max4(
int a,
int b,
int c,
int d)
5026 return std::max(std::max(a, b), std::max(c, d));
5028 static int max6(
int a,
int b,
int c,
int d,
int e,
int f)
5030 return std::max(max4(a, b, c, d), std::max(e, f));
5032 static int max8(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h)
5034 return std::max(max4(a, b, c, d), max4(e, f, g, h));
5039 int mid =
nodes.FindId(vn1, vn2);
5040 if (mid < 0 || !
nodes[mid].HasVertex()) {
return 0; }
5048 faces.FindId(vn1, vn2, vn3) < 0)
5062 int& h_level,
int& v_level)
const
5064 int hl1, hl2, vl1, vl2;
5070 h_level = v_level = 0;
5076 h_level = std::max(hl1, hl2);
5077 v_level = std::max(vl1, vl2) + 1;
5083 h_level = std::max(hl1, hl2) + 1;
5084 v_level = std::max(vl1, vl2);
5091 const int* node = el.
node;
5095 for (
int i = 0; i < gi.
ne; i++)
5097 const int* ev = gi.
edges[i];
5104 for (
int i = 0; i < gi.
nf; i++)
5106 const int* fv = gi.
faces[i];
5110 node[fv[2]], node[fv[3]],
5111 flevel[i][1], flevel[i][0]);
5124 splits[0] = max8(flevel[0][0], flevel[1][0], flevel[3][0], flevel[5][0],
5125 elevel[0], elevel[2], elevel[4], elevel[6]);
5127 splits[1] = max8(flevel[0][1], flevel[2][0], flevel[4][0], flevel[5][1],
5128 elevel[1], elevel[3], elevel[5], elevel[7]);
5130 splits[2] = max8(flevel[1][1], flevel[2][1], flevel[3][1], flevel[4][1],
5131 elevel[8], elevel[9], elevel[10], elevel[11]);
5135 splits[0] = splits[1] =
5137 max6(flevel[0][0], flevel[1][0], 0,
5138 flevel[2][0], flevel[3][0], flevel[4][0]),
5139 max6(elevel[0], elevel[1], elevel[2],
5140 elevel[3], elevel[4], elevel[5]));
5142 splits[2] = max6(flevel[2][1], flevel[3][1], flevel[4][1],
5143 elevel[6], elevel[7], elevel[8]);
5147 splits[0] = std::max(
5148 max4(flevel[0][0], flevel[1][0], flevel[2][0], flevel[3][0]),
5149 max6(elevel[0], elevel[1], elevel[2],
5150 elevel[3], elevel[4], elevel[5]));
5152 splits[1] = splits[0];
5153 splits[2] = splits[0];
5157 splits[0] = std::max(elevel[0], elevel[2]);
5158 splits[1] = std::max(elevel[1], elevel[3]);
5162 splits[0] = std::max(elevel[0], std::max(elevel[1], elevel[2]));
5163 splits[1] = splits[0];
5167 MFEM_ABORT(
"Unsupported element geometry.");
5181 for (
int k = 0; k <
Dim; k++)
5183 if (splits[k] > max_level)
5185 ref_type |= (1 << k);
5203 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
5210 if (!refinements.
Size()) {
break; }
5225 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5227 if (node->HasVertex() && node->p1 != node->p2) { nv++; }
5234 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5236 if (node->HasVertex() && node->p1 != node->p2)
5238 MFEM_ASSERT(
nodes[node->p1].HasVertex(),
"");
5239 MFEM_ASSERT(
nodes[node->p2].HasVertex(),
"");
5241 (*os) << node.index() <<
" " << node->p1 <<
" " << node->p2 <<
"\n";
5255 input >>
id >> p1 >> p2;
5256 MFEM_VERIFY(input,
"problem reading vertex parents.");
5258 MFEM_VERIFY(
nodes.IdExists(
id),
"vertex " <<
id <<
" not found.");
5259 MFEM_VERIFY(
nodes.IdExists(p1),
"parent " << p1 <<
" not found.");
5260 MFEM_VERIFY(
nodes.IdExists(p2),
"parent " << p2 <<
" not found.");
5262 int check =
nodes.FindId(p1, p2);
5263 MFEM_VERIFY(check < 0,
"parents (" << p1 <<
", " << p2 <<
") already "
5264 "assigned to node " << check);
5267 nodes.Reparent(
id, p1, p2);
5273 static const int nfv2geom[5] =
5278 int deg = (
Dim == 2) ? 2 : 1;
5281 for (
int i = 0; i <
elements.Size(); i++)
5284 if (!el.
IsLeaf()) {
continue; }
5287 for (
int k = 0; k < gi.
nf; k++)
5289 const int* fv = gi.
faces[k];
5290 const int nfv = gi.
nfv[k];
5293 MFEM_ASSERT(face != NULL,
"face not found");
5296 if (!os) { count++;
continue; }
5298 (*os) << face->
attribute <<
" " << nfv2geom[nfv];
5299 for (
int j = 0; j < nfv; j++)
5301 (*os) <<
" " << el.
node[fv[j*deg]];
5314 for (
int i = 0; i < nb; i++)
5316 input >> attr >> geom;
5321 input >> v1 >> v2 >> v3 >> v4;
5327 input >> v1 >> v2 >> v3;
5345 MFEM_ABORT(
"unsupported boundary element geometry: " << geom);
5354 if (!nv) {
return; }
5357 for (
int i = 0; i < nv; i++)
5362 os <<
" " << coordinates[3*i + j];
5372 if (!nv) {
return; }
5379 for (
int i = 0; i < nv; i++)
5384 MFEM_VERIFY(input.good(),
"unexpected EOF");
5400 os <<
"MFEM NC mesh v1.0\n\n"
5401 "# NCMesh supported geometry types:\n"
5405 "# TETRAHEDRON = 4\n"
5409 os <<
"\ndimension\n" <<
Dim <<
"\n";
5411 #ifndef MFEM_USE_MPI
5415 os <<
"\nrank\n" <<
MyRank <<
"\n";
5418 os <<
"\n# rank attr geom ref_type nodes/children";
5419 os <<
"\nelements\n" <<
elements.Size() <<
"\n";
5421 for (
int i = 0; i <
elements.Size(); i++)
5425 if (el.
parent == -2) { os <<
"-1\n";
continue; }
5428 for (
int j = 0; j < 8 && el.
node[j] >= 0; j++)
5430 os <<
" " << el.
node[j];
5438 os <<
"\n# attr geom nodes";
5439 os <<
"\nboundary\n" << nb <<
"\n";
5447 os <<
"\n# vert_id p1 p2";
5448 os <<
"\nvertex_parents\n" << nvp <<
"\n";
5455 os <<
"\n# root element orientation";
5466 os <<
"\n# top-level node coordinates";
5467 os <<
"\ncoordinates\n";
5480 for (
int i = 0; i <
elements.Size(); i++)
5485 for (
int j = 0; j < 8 && el.
child[j] >= 0; j++)
5487 int child = el.
child[j];
5488 MFEM_VERIFY(child <
elements.Size(),
"invalid mesh file: "
5489 "element " << i <<
" references invalid child " << child);
5502 MFEM_VERIFY(nroots,
"invalid mesh file: no root elements found.");
5505 for (
int i = nroots; i <
elements.Size(); i++)
5507 MFEM_VERIFY(
elements[i].parent != -1,
5508 "invalid mesh file: only the first M elements can be roots. "
5509 "Found element " << i <<
" with no parent.");
5520 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5522 if (node->p1 == node->p2) { ntop = node.index() + 1; }
5538 MFEM_ASSERT(version == 10,
"");
5545 MFEM_VERIFY(ident ==
"dimension",
"Invalid mesh file: " << ident);
5551 if (ident ==
"rank")
5554 MFEM_VERIFY(MyRank >= 0,
"Invalid rank");
5561 if (ident ==
"sfc_version")
5564 input >> sfc_version;
5565 MFEM_VERIFY(sfc_version == 0,
5566 "Unsupported mesh file SFC version (" << sfc_version <<
"). "
5567 "Please update MFEM.");
5574 MFEM_VERIFY(ident ==
"elements",
"Invalid mesh file: " << ident);
5576 for (
int i = 0; i < count; i++)
5578 int rank, attr, geom, ref_type;
5579 input >> rank >> attr >> geom;
5584 MFEM_ASSERT(
elements.Size() == i+1,
"");
5590 CheckSupportedGeom(type);
5594 MFEM_VERIFY(ref_type >= 0 && ref_type < 8,
"");
5595 el.ref_type = ref_type;
5599 for (
int j = 0; j < ref_type_num_children[ref_type]; j++)
5601 input >> el.child[j];
5603 if (Dim == 3 && ref_type != 7) {
Iso =
false; }
5607 for (
int j = 0; j <
GI[geom].
nv; j++)
5612 nodes.Alloc(
id,
id,
id);
5632 if (ident ==
"boundary")
5641 if (ident ==
"vertex_parents")
5650 if (ident ==
"root_state")
5654 for (
int i = 0; i < count; i++)
5664 if (ident ==
"coordinates")
5669 "Invalid mesh file: not all top-level nodes are covered by "
5670 "the 'coordinates' section of the mesh file.");
5673 else if (ident ==
"nodes")
5683 MFEM_ABORT(
"Invalid mesh file: either 'coordinates' or "
5684 "'nodes' must be present");
5688 nodes.UpdateUnused();
5689 for (
int i = 0; i <
elements.Size(); i++)
5707 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
5709 int old_id = el.
child[i];
5711 int new_id =
elements.Append(tmp_elements[old_id]);
5712 el.
child[i] = new_id;
5736 if (
Dim == 3 && ref_type != 7) { iso =
false; }
5739 int nch = ref_type_num_children[ref_type];
5740 for (
int i = 0,
id; i < nch; i++)
5743 MFEM_VERIFY(
id >= 0,
"");
5745 "coarse element cannot be referenced before it is "
5746 "defined (id=" <<
id <<
").");
5749 MFEM_VERIFY(child.parent == -1,
5750 "element " <<
id <<
" cannot have two parents.");
5753 child.parent = elem;
5757 el.
geom = child.geom;
5769 for (
auto el = tmp_elements.
begin(); el != tmp_elements.
end(); ++el)
5771 if (el->parent == -1)
5779 for (
int i = 0; i < root_count; i++)
5792 MFEM_ASSERT(
elements.Size() == 0,
"");
5793 MFEM_ASSERT(
nodes.Size() == 0,
"");
5797 int count, attr, geom;
5802 MFEM_VERIFY(ident ==
"dimension",
"invalid mesh file");
5808 MFEM_VERIFY(ident ==
"elements",
"invalid mesh file");
5811 for (
int i = 0; i < count; i++)
5813 input >> attr >> geom;
5816 CheckSupportedGeom(type);
5820 MFEM_ASSERT(eid == i,
"");
5823 for (
int j = 0; j <
GI[geom].
nv; j++)
5828 nodes.Alloc(
id,
id,
id);
5836 MFEM_VERIFY(ident ==
"boundary",
"invalid mesh file");
5843 if (ident ==
"vertex_parents")
5859 if (ident ==
"coarse_elements")
5874 MFEM_VERIFY(ident ==
"vertices",
"invalid mesh file");
5877 input >> std::ws >> ident;
5878 if (ident !=
"nodes")
5885 for (
int i = 0; i < nvert; i++)
5890 MFEM_VERIFY(input.good(),
"unexpected EOF");
5911 nodes.UpdateUnused();
5913 for (
int i = 0; i <
elements.Size(); i++)
5925 file_leaf_elements = -1;
5926 for (
int i = 0; i <
elements.Size(); i++)
5930 file_leaf_elements[
elements[i].index] = i;
5933 MFEM_ASSERT(file_leaf_elements.
Min() >= 0,
"");
5954 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5956 if (node->HasVertex())
5958 MFEM_ASSERT(node.index() >= 0,
"");
5959 MFEM_ASSERT(node.index() < order.
Size(),
"");
5960 MFEM_ASSERT(order[node.index()] == -1,
"");
5962 order[node.index()] = node->vert_index;
5966 MFEM_ASSERT(count == order.
Size(),
"");
5992 for (
int j = 0; j < point_matrices[i].Size(); i++)
5994 pm_size += point_matrices[i][j]->MemoryUsage();
5996 pm_size += point_matrices[i].MemoryUsage();
6007 long mem = embeddings.MemoryUsage();
6010 mem += point_matrices[i].MemoryUsage();
6017 return nodes.MemoryUsage() +
6018 faces.MemoryUsage() +
6055 <<
ref_stack.MemoryUsage() <<
" ref_stack\n"
6059 <<
sizeof(*this) <<
" NCMesh"
6072 for (
int j = 0; j <
Dim; j++)
6076 for (
int k = 0; k < 8; k++)
6078 if (elem->
node[k] >= 0)
6084 os << sum / count <<
" ";
6095 os <<
nodes.Size() <<
"\n";
6096 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
6099 os << node.index() <<
" "
6100 << pos[0] <<
" " << pos[1] <<
" " << pos[2] <<
" "
6101 << node->p1 <<
" " << node->p2 <<
" "
6102 << node->vert_index <<
" " << node->edge_index <<
" "
6110 for (
int i = 0; i <
elements.Size(); i++)
6112 if (
elements[i].IsLeaf()) { nleaves++; }
6114 os << nleaves <<
"\n";
6115 for (
int i = 0; i <
elements.Size(); i++)
6122 for (
int j = 0; j < gi.
nv; j++)
6124 os << el.
node[j] <<
" ";
6132 os <<
faces.Size() <<
"\n";
6133 for (
auto face =
faces.cbegin(); face !=
faces.cend(); ++face)
6135 int elem = face->elem[0];
6136 if (elem < 0) { elem = face->elem[1]; }
6137 MFEM_ASSERT(elem >= 0,
"");
6149 for (
int i = 0; i < nfv; i++)
6151 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
long MemoryUsage() const
Returns the number of bytes allocated for the array including any reserve.
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...
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
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.
void InitRootElements()
Count root elements and initialize root_state.
long MemoryUsage() const
Return total number of bytes allocated.
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)
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