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.");
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]);
965 else if (ref_type == 2)
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]);
985 else if (ref_type == 4)
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]);
1005 else if (ref_type == 3)
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);
1044 else if (ref_type == 5)
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);
1083 else if (ref_type == 6)
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);
1122 else if (ref_type == 7)
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.");
1192 if (ref_type != 7) {
Iso =
false; }
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);
1242 else if (ref_type == 4)
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]);
1260 else if (ref_type > 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);
1318 MFEM_ABORT(
"invalid refinement type.");
1321 if (ref_type != 7) {
Iso =
false; }
1349 -1, fa[1], fa[2], fa[3]);
1352 fa[0], -1, fa[2], fa[3]);
1355 fa[0], fa[1], -1, fa[3]);
1358 fa[0], fa[1], fa[2], -1);
1417 int mid01 =
nodes.GetId(no[0], no[1]);
1418 int mid23 =
nodes.GetId(no[2], no[3]);
1421 attr, fa[0], -1, fa[2], fa[3]);
1424 attr, fa[0], fa[1], fa[2], -1);
1426 else if (ref_type == 2)
1428 int mid12 =
nodes.GetId(no[1], no[2]);
1429 int mid30 =
nodes.GetId(no[3], no[0]);
1432 attr, fa[0], fa[1], -1, fa[3]);
1435 attr, -1, fa[1], fa[2], fa[3]);
1437 else if (ref_type == 3)
1439 int mid01 =
nodes.GetId(no[0], no[1]);
1440 int mid12 =
nodes.GetId(no[1], no[2]);
1441 int mid23 =
nodes.GetId(no[2], no[3]);
1442 int mid30 =
nodes.GetId(no[3], no[0]);
1444 int midel =
nodes.GetId(mid01, mid23);
1447 attr, fa[0], -1, -1, fa[3]);
1450 attr, fa[0], fa[1], -1, -1);
1453 attr, -1, fa[1], fa[2], -1);
1456 attr, -1, -1, fa[2], fa[3]);
1460 MFEM_ABORT(
"Invalid refinement type.");
1463 if (ref_type != 3) {
Iso =
false; }
1470 int mid01 =
nodes.GetId(no[0], no[1]);
1471 int mid12 =
nodes.GetId(no[1], no[2]);
1472 int mid20 =
nodes.GetId(no[2], no[0]);
1474 child[0] =
NewTriangle(no[0], mid01, mid20, attr, fa[0], -1, fa[2]);
1475 child[1] =
NewTriangle(mid01, no[1], mid12, attr, fa[0], fa[1], -1);
1476 child[2] =
NewTriangle(mid20, mid12, no[2], attr, -1, fa[1], fa[2]);
1477 child[3] =
NewTriangle(mid12, mid20, mid01, attr, -1, -1, -1);
1483 int mid =
nodes.GetId(no[0], no[1]);
1484 child[0] =
NewSegment(no[0], mid, attr, fa[0], -1);
1485 child[1] =
NewSegment(mid, no[1], attr, -1, fa[1]);
1489 MFEM_ABORT(
"Unsupported element geometry.");
1493 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1506 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1515 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1524 std::memcpy(el.
child, child,
sizeof(el.
child));
1532 for (
int i = refinements.
Size()-1; i >= 0; i--)
1560 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
1561 mfem::out <<
"Refined " << refinements.
Size() <<
" + " << nforced
1562 <<
" elements" << std::endl;
1589 MFEM_ASSERT(ch != -1,
"");
1604 MFEM_ABORT(
"Unsupported element geometry.");
1616 std::memcpy(child, el.
child,
sizeof(child));
1619 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1630 for (
int i = 0; i < 8; i++) { el.
node[i] = -1; }
1635 for (
int i = 0; i < 8; i++)
1640 for (
int i = 0; i < 6; i++)
1645 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1650 MFEM_ASSERT(prism_deref_table[rt1][0] != -1,
"invalid prism refinement");
1651 for (
int i = 0; i < 6; i++)
1658 for (
int i = 0; i < 5; i++)
1663 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1668 for (
int i = 0; i < 4; i++)
1675 ch2.
node[fv[2]], ch2.
node[fv[3]])->attribute;
1680 for (
int i = 0; i < 4; i++)
1685 for (
int i = 0; i < 4; i++)
1690 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1695 for (
int i = 0; i < 3; i++)
1701 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1706 for (
int i = 0; i < 2; i++)
1708 int ni =
elements[child[i]].node[i];
1710 fa[i] =
faces.Find(ni, ni, ni, ni)->attribute;
1715 MFEM_ABORT(
"Unsupported element geometry.");
1726 el.
rank = std::numeric_limits<int>::max();
1727 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1750 int total = 0, ref = 0, ghost = 0;
1751 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1759 if (!ref && ghost < total)
1762 int next_row = list.
Size() ? (list.
Last().from + 1) : 0;
1763 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1771 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1788 int size = list.
Size() ? (list.
Last().from + 1) : 0;
1797 for (
int i = 0; i < deref_table.
Size(); i++)
1799 const int* fine = deref_table.
GetRow(i), size = deref_table.
RowSize(i);
1803 for (
int j = 0; j < size; j++)
1808 for (
int k = 0; k <
Dim; k++)
1810 if ((parent.
ref_type & (1 << k)) &&
1811 splits[k] >= max_nc_level)
1824 MFEM_VERIFY(
Dim < 3 ||
Iso,
1825 "derefinement of 3D anisotropic meshes not implemented yet.");
1833 for (
int i = 0; i < derefs.
Size(); i++)
1835 int row = derefs[i];
1837 "invalid derefinement number.");
1852 for (
int i = 0; i < fine_coarse.
Size(); i++)
1866 for (
int i = 0; i < nfine; i++)
1877 for (
int i = 0; i < 8 && prn.
child[i] >= 0; i++)
1884 fine_coarse[ch.
index] = parent;
1912 el.
index = counter++;
1931 for (
int i = 0; i < 4; i++)
1933 int ch = quad_hilbert_child_order[state][i];
1934 int st = quad_hilbert_child_state[state][i];
1940 for (
int i = 0; i < 8; i++)
1942 int ch = hex_hilbert_child_order[state][i];
1943 int st = hex_hilbert_child_state[state][i];
1949 for (
int i = 0; i < 8; i++)
1951 if (el.
child[i] >= 0)
1989 #ifndef MFEM_NCMESH_OLD_VERTEX_ORDERING
2015 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2017 node->vert_index = -4;
2023 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2047 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2049 if (node->vert_index == -1)
2059 for (
int i = 0; i < sfc_order.Size(); i++)
2064 for (
int i = 0; i < sfc_order.Size(); i++)
2067 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2077 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2079 if (node->HasVertex() && node->vert_index >= 0)
2090 for (
int i = 0; i < sfc_order.Size(); i++)
2093 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2103 #else // old ordering for debugging/testing only
2104 bool parallel =
false;
2106 if (dynamic_cast<ParNCMesh*>(
this)) { parallel =
true; }
2112 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2114 if (node->HasVertex()) { node->vert_index =
NVertices++; }
2120 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2127 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2129 if (node->HasVertex()) { node->vert_index = -1; }
2138 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2140 int &vindex =
nodes[el.
node[j]].vert_index;
2141 if (vindex < 0) { vindex =
NVertices++; }
2147 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2149 if (node->HasVertex() && node->vert_index >= 0)
2156 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2158 if (node->HasVertex() && node->vert_index < 0)
2179 node_order = (
char*) quad_hilbert_child_order;
2184 node_order = (
char*) hex_hilbert_child_order;
2191 int entry_node = -2;
2194 for (
int i = 0; i < root_count; i++)
2199 if (v_in < 0) { v_in = 0; }
2202 bool shared[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2203 if (i+1 < root_count)
2206 for (
int j = 0; j < nch; j++)
2209 if (node >= 0) { shared[node] =
true; }
2214 int state =
Dim*v_in;
2215 for (
int j = 0; j <
Dim; j++)
2217 if (shared[(
int) node_order[nch*(state + j) + nch-1]])
2226 entry_node =
RetrieveNode(el, node_order[nch*state + nch-1]);
2240 MFEM_ABORT(
"invalid geometry");
2255 MFEM_VERIFY(tv.
visited ==
false,
"cyclic vertex dependencies.");
2261 for (
int i = 0; i < 3; i++)
2263 tv.
pos[i] = (pos1[i] + pos2[i]) * 0.5;
2276 for (
int i = 0; i < mesh.
vertices.Size(); i++)
2296 const int* node = nc_elem.
node;
2303 for (
int j = 0; j < gi.
nv; j++)
2305 elem->GetVertices()[j] =
nodes[node[j]].vert_index;
2310 for (
int k = 0; k < gi.
nf; k++)
2312 const int* fv = gi.
faces[k];
2313 const int nfv = gi.
nfv[k];
2314 const Face* face =
faces.Find(node[fv[0]], node[fv[1]],
2315 node[fv[2]], node[fv[3]]);
2323 for (
int j = 0; j < 4; j++)
2325 quad->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2332 MFEM_ASSERT(nfv == 3,
"");
2335 for (
int j = 0; j < 3; j++)
2337 tri->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2346 for (
int j = 0; j < 2; j++)
2348 segment->GetVertices()[j] =
nodes[node[fv[2*j]]].vert_index;
2357 point->GetVertices()[0] =
nodes[node[fv[0]]].vert_index;
2373 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2375 if (node->HasEdge()) { node->edge_index = -1; }
2377 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2384 for (
int i = 0; i < edge_vertex->
Size(); i++)
2386 const int *ev = edge_vertex->
GetRow(i);
2389 MFEM_ASSERT(node && node->
HasEdge(),
2390 "edge (" << ev[0] <<
"," << ev[1] <<
") not found, "
2398 for (
int i = 0; i <
NFaces; i++)
2400 const int* fv = mesh->
GetFace(i)->GetVertices();
2401 const int nfv = mesh->
GetFace(i)->GetNVertices();
2414 MFEM_ASSERT(nfv == 3,
"");
2422 MFEM_ASSERT(nfv == 2,
"");
2425 face =
faces.Find(n0, n0, n1, n1);
2429 const int *ev = edge_vertex->
GetRow(i);
2430 MFEM_ASSERT((ev[0] == fv[0] && ev[1] == fv[1]) ||
2431 (ev[1] == fv[0] && ev[0] == fv[1]),
"");
2435 MFEM_VERIFY(face,
"face not found.");
2443 for (
auto node =
nodes.begin(); node !=
nodes.end(); ++node)
2445 if (node->HasEdge() && node->edge_index < 0)
2453 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2461 MFEM_ASSERT(NFaces ==
NEdges,
"");
2476 for (
int j = 0; j < gi.
nf; j++)
2478 const int *fv = gi.
faces[j];
2481 MFEM_ASSERT(face,
"face not found!");
2483 if (face->
index < 0)
2485 face->
index = NFaces + (nghosts++);
2499 for (
auto face =
faces.begin(); face !=
faces.end(); ++face)
2501 if (face->index < 0) { face->index = NFaces + (nghosts++); }
2512 MFEM_ASSERT(
Dim >= 3,
"");
2521 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3, mid[3] = e4; }
2524 int midf1 = -1, midf2 = -1;
2529 if (midf1 >= 0 && midf1 == midf2)
2532 if (nd.
p1 != e1 && nd.
p2 != e1) { midf1 = -1; }
2533 if (nd.
p1 != e2 && nd.
p2 != e2) { midf2 = -1; }
2537 MFEM_ASSERT(!(midf1 >= 0 && midf2 >= 0),
"incorrectly split face!");
2539 if (midf1 < 0 && midf2 < 0)
2541 if (mid) { mid[4] = -1; }
2544 else if (midf1 >= 0)
2546 if (mid) { mid[4] = midf1; }
2551 if (mid) { mid[4] = midf2; }
2558 int e1 =
nodes.FindId(v1, v2);
2559 if (e1 < 0 || !
nodes[e1].HasVertex()) {
return false; }
2561 int e2 =
nodes.FindId(v2, v3);
2562 if (e2 < 0 || !
nodes[e2].HasVertex()) {
return false; }
2564 int e3 =
nodes.FindId(v3, v1);
2565 if (e3 < 0 || !
nodes[e3].HasVertex()) {
return false; }
2567 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3; }
2575 for (
int i = 0; i < 8; i++)
2577 if (el.
node[i] == node) {
return i; }
2579 MFEM_ABORT(
"Node not found.");
2585 for (
int i = 0; i <
GI[el.
Geom()].
nv; i++)
2589 if (abort) { MFEM_ABORT(
"Node not found."); }
2598 for (
int i = 0; i < gi.
ne; i++)
2600 const int* ev = gi.
edges[i];
2601 int n0 = el.
node[ev[0]];
2602 int n1 = el.
node[ev[1]];
2603 if ((n0 == vn0 && n1 == vn1) ||
2604 (n0 == vn1 && n1 == vn0)) {
return i; }
2607 if (abort) { MFEM_ABORT(
"Edge (" << vn0 <<
", " << vn1 <<
") not found"); }
2614 for (
int i = 0; i < gi.
nf; i++)
2616 const int* fv = gi.
faces[i];
2617 if ((a == fv[0] || a == fv[1] || a == fv[2] || a == fv[3]) &&
2618 (b == fv[0] || b == fv[1] || b == fv[2] || b == fv[3]) &&
2619 (c == fv[0] || c == fv[1] || c == fv[2] || c == fv[3]))
2624 MFEM_ABORT(
"Face not found.");
2634 MFEM_ASSERT(
sizeof(
double) ==
sizeof(std::uint64_t),
"");
2638 std::uint64_t hash = 0xf9ca9ba106acbba9;
2639 for (
int i = 0; i < pm.
np; i++)
2641 for (
int j = 0; j < pm.
points[i].
dim; j++)
2646 hash = 31*hash + *((std::uint64_t*) &coord);
2658 int GetIndex(
const NCMesh::PointMatrix &pm)
2660 int &
index = map[pm];
2661 if (!index) { index = map.size(); }
2665 void ExportMatrices(Array<DenseMatrix*> &point_matrices)
const
2667 point_matrices.SetSize(map.size());
2668 for (
const auto &pair : map)
2670 DenseMatrix* mat =
new DenseMatrix();
2671 pair.first.GetMatrix(*mat);
2672 point_matrices[pair.second - 1] = mat;
2676 void DumpBucketSizes()
const
2678 for (
unsigned i = 0; i < map.bucket_count(); i++)
2685 std::unordered_map<NCMesh::PointMatrix, int, PointMatrixHash> map;
2699 int nfv = (v3 >= 0) ? 4 : 3;
2704 reordered.
np = pm.
np;
2705 for (
int i = 0, j; i < nfv; i++)
2707 for (j = 0; j < nfv; j++)
2709 if (fv[i] == master[j])
2715 MFEM_ASSERT(j != nfv,
"node not found.");
2727 Face* fa =
faces.Find(vn0, vn1, vn2, vn3);
2739 sl.
matrix = matrix_map.GetIndex(pm_r);
2741 eface[0] = eface[2] = fa;
2742 eface[1] = eface[3] = fa;
2755 Point pmid0(pm(0), pm(1)), pmid2(pm(2), pm(3));
2759 level+1, ef[0], matrix_map);
2763 level+1, ef[1], matrix_map);
2765 eface[1] = ef[1][1];
2766 eface[3] = ef[0][3];
2767 eface[0] = eface[2] = NULL;
2769 else if (split == 2)
2771 Point pmid1(pm(1), pm(2)), pmid3(pm(3), pm(0));
2775 level+1, ef[0], matrix_map);
2779 level+1, ef[1], matrix_map);
2781 eface[0] = ef[0][0];
2782 eface[2] = ef[1][2];
2783 eface[1] = eface[3] = NULL;
2794 const int fi[3][2] = {{0, 0}, {1, 3}, {2, 0}};
2795 if (!ef[0][fi[split][0]] && !ef[1][fi[split][1]])
2805 MFEM_ASSERT(eid.
Size() > 0,
"edge prism not found");
2806 MFEM_ASSERT(eid.
Size() < 2,
"non-unique edge prism");
2816 Point mid0(pm(0), pm(1)), mid2(pm(2), pm(3));
2817 int v1 =
nodes[mid[0]].vert_index;
2818 int v2 =
nodes[mid[2]].vert_index;
2820 matrix_map.GetIndex(
2826 Point mid1(pm(1), pm(2)), mid3(pm(3), pm(0));
2827 int v1 =
nodes[mid[1]].vert_index;
2828 int v2 =
nodes[mid[3]].vert_index;
2830 matrix_map.GetIndex(
2842 int mid =
nodes.FindId(vn0, vn1);
2843 if (mid < 0) {
return; }
2859 int v0index =
nodes[vn0].vert_index;
2860 int v1index =
nodes[vn1].vert_index;
2863 matrix_map.GetIndex((v0index < v1index) ?
PointMatrix(p0, p1, p0)
2895 sl.
matrix = matrix_map.GetIndex(pm_r);
2904 Point pmid0(pm(0), pm(1)), pmid1(pm(1), pm(2)), pmid2(pm(2), pm(0));
2909 level+1, matrix_map);
2913 level+1, matrix_map);
2917 level+1, matrix_map);
2921 level+1, matrix_map);
2926 if (!b[1]) {
TraverseTetEdge(mid[0],mid[1], pmid0,pmid1, matrix_map); }
2927 if (!b[2]) {
TraverseTetEdge(mid[1],mid[2], pmid1,pmid2, matrix_map); }
2928 if (!b[0]) {
TraverseTetEdge(mid[2],mid[0], pmid2,pmid0, matrix_map); }
2938 if (
Dim < 3) {
return; }
2945 processed_faces = 0;
2954 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
2957 for (
int j = 0; j < gi.
nf; j++)
2961 for (
int k = 0; k < 4; k++)
2966 int face =
faces.FindId(node[0], node[1], node[2], node[3]);
2967 MFEM_ASSERT(face >= 0,
"face not found!");
2973 if (processed_faces[face]) {
continue; }
2974 processed_faces[face] = 1;
2979 if (fa.
elem[0] >= 0 && fa.
elem[1] >= 0)
3009 for (
int i = sb; i < se; i++)
3030 int mid =
nodes.FindId(vn0, vn1);
3031 if (mid < 0) {
return; }
3034 if (nd.
HasEdge() && level > 0)
3044 int v0index =
nodes[vn0].vert_index;
3045 int v1index =
nodes[vn1].vert_index;
3046 if (v0index > v1index) { sl.
edge_flags |= 2; }
3050 double tmid = (t0 + t1) / 2;
3051 TraverseEdge(vn0, mid, t0, tmid, flags, level+1, matrix_map);
3052 TraverseEdge(mid, vn1, tmid, t1, flags, level+1, matrix_map);
3061 processed_edges = 0;
3074 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3077 for (
int j = 0; j < gi.
ne; j++)
3080 const int* ev = gi.
edges[j];
3081 int node[2] = { el.
node[ev[0]], el.
node[ev[1]] };
3083 int enode =
nodes.FindId(node[0], node[1]);
3084 MFEM_ASSERT(enode >= 0,
"edge node not found!");
3087 MFEM_ASSERT(nd.
HasEdge(),
"edge not found!");
3095 int face =
faces.FindId(node[0], node[0], node[1], node[1]);
3096 MFEM_ASSERT(face >= 0,
"face not found!");
3108 if (processed_edges[enode]) {
continue; }
3109 processed_edges[enode] = 1;
3112 double t0 = 0.0, t1 = 1.0;
3113 int v0index =
nodes[node[0]].vert_index;
3114 int v1index =
nodes[node[1]].vert_index;
3115 int flags = (v0index > v1index) ? 1 : 0;
3119 TraverseEdge(node[0], node[1], t0, t1, flags, 0, matrix_map);
3129 for (
int i = sb; i < se; i++)
3146 int local = edge_local[sl.
index];
3166 processed_vertices = 0;
3174 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
3176 int node = el.
node[j];
3184 if (processed_vertices[index]) {
continue; }
3185 processed_vertices[
index] = 1;
3196 oriented_matrix = *(point_matrices[slave.
Geom()][slave.
matrix]);
3200 MFEM_ASSERT(oriented_matrix.
Height() == 1 &&
3201 oriented_matrix.
Width() == 2,
"not an edge point matrix");
3205 oriented_matrix(0,0) = 1.0 - oriented_matrix(0,0);
3206 oriented_matrix(0,1) = 1.0 - oriented_matrix(0,1);
3210 std::swap(oriented_matrix(0,0), oriented_matrix(0,1));
3217 conforming.DeleteAll();
3218 masters.DeleteAll();
3223 for (
int j = 0; j < point_matrices[i].Size(); j++)
3225 delete point_matrices[i][j];
3227 point_matrices[i].DeleteAll();
3230 inv_index.DeleteAll();
3235 return conforming.Size() + masters.Size() + slaves.Size();
3240 if (!inv_index.Size())
3243 for (
int i = 0; i < conforming.Size(); i++)
3245 max_index = std::max(conforming[i].index, max_index);
3247 for (
int i = 0; i < masters.Size(); i++)
3249 max_index = std::max(masters[i].index, max_index);
3251 for (
int i = 0; i < slaves.Size(); i++)
3253 if (slaves[i].index < 0) {
continue; }
3254 max_index = std::max(slaves[i].index, max_index);
3257 inv_index.SetSize(max_index + 1);
3260 for (
int i = 0; i < conforming.Size(); i++)
3262 inv_index[conforming[i].index] = (i << 2);
3264 for (
int i = 0; i < masters.Size(); i++)
3266 inv_index[masters[i].index] = (i << 2) + 1;
3268 for (
int i = 0; i < slaves.Size(); i++)
3270 if (slaves[i].index < 0) {
continue; }
3271 inv_index[slaves[i].index] = (i << 2) + 2;
3275 MFEM_ASSERT(index >= 0 && index < inv_index.Size(),
"");
3276 int key = inv_index[
index];
3280 MFEM_VERIFY(key >= 0,
"entity not found.");
3284 *type = (key >= 0) ? (key & 0x3) : -1;
3287 if (*type < 0) {
return invalid; }
3293 case 0:
return conforming[key >> 2];
3294 case 1:
return masters[key >> 2];
3295 case 2:
return slaves[key >> 2];
3296 default: MFEM_ABORT(
"internal error");
return conforming[0];
3305 int mid =
nodes.FindId(v0, v1);
3306 if (mid >= 0 &&
nodes[mid].HasVertex())
3320 for (
int i = 0; i < 3; i++)
3377 int** JJ =
new int*[nrows];
3387 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3390 int* node = el.
node;
3393 for (
int j = 0; j < gi.
ne; j++)
3395 const int* ev = gi.
edges[j];
3401 for (
int j = 0; j < gi.
nf; j++)
3403 const int* fv = gi.
faces[j];
3407 node[fv[2]], node[fv[3]], indices);
3420 int size = indices.
Size();
3422 JJ[i] =
new int[size];
3423 std::memcpy(JJ[i], indices.
GetData(), size *
sizeof(int));
3428 for (
int i = 0; i < nrows; i++)
3439 for (
int i = 0; i < nrows; i++)
3441 int cnt = I[i+1] - I[i];
3442 std::memcpy(J+nnz, JJ[i], cnt *
sizeof(
int));
3469 MFEM_VERIFY(elem_set.
Size() == nleaves,
"");
3478 for (
int i = 0; i < nleaves; i++)
3484 for (
int j = 0; j < nv; j++)
3491 for (
int j = 0; j < nv; j++)
3493 vmark[el.
node[j]] = 1;
3504 neighbor_set->
SetSize(nleaves);
3508 for (
int i = 0; i < nleaves; i++)
3516 for (
int j = 0; j < nv; j++)
3518 if (vmark[v[j]]) { hit =
true;
break; }
3525 for (
int j = 0; j < nv; j++)
3527 if (vmark[el.
node[j]]) { hit =
true;
break; }
3534 if (neighbor_set) { (*neighbor_set)[i] = 1; }
3540 static bool sorted_lists_intersect(
const int*
a,
const int*
b,
int na,
int nb)
3542 if (!na || !nb) {
return false; }
3543 int a_last = a[na-1], b_last = b[nb-1];
3544 if (*b < *a) {
goto l2; }
3546 if (a_last < *b) {
return false; }
3547 while (*a < *b) { a++; }
3548 if (*a == *b) {
return true; }
3550 if (b_last < *a) {
return false; }
3551 while (*b < *a) { b++; }
3552 if (*a == *b) {
return true; }
3575 while (stack.
Size())
3584 for (
int i = 0; i < nv; i++)
3590 for (
int i = 0; i < nv; i++)
3597 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
3608 int nv1 = vert.
Size();
3613 for (
int i = 0; i < search_set->
Size(); i++)
3615 int testme = (*search_set)[i];
3622 bool hit = sorted_lists_intersect(v1, v2, nv1, nv2);
3627 for (
int j = 0; j < nv; j++)
3629 hit = sorted_lists_intersect(&el.
node[j], v1, 1, nv1);
3634 if (hit) { neighbors.
Append(testme); }
3648 for (
int i = 0; i < elems.
Size(); i++)
3654 for (
int j = 0; j < nv; j++)
3660 for (
int j = 0; j < nv; j++)
3662 vmark[el.
node[j]] = 1;
3672 for (
int i = 0; i < search_set->
Size(); i++)
3674 int testme = (*search_set)[i];
3680 for (
int j = 0; j < nv; j++)
3682 if (vmark[v[j]]) { hit =
true;
break; }
3688 for (
int j = 0; j < nv; j++)
3690 if (vmark[el.
node[j]]) { hit =
true;
break; }
3694 if (hit) { expanded.
Append(testme); }
3703 if (el.
parent < 0) {
return elem; }
3706 MFEM_ASSERT(pa.
ref_type,
"internal error");
3709 while (ch < 8 && pa.
child[ch] != elem) { ch++; }
3710 MFEM_ASSERT(ch < 8,
"internal error");
3712 MFEM_ASSERT(geom_parent[el.
Geom()],
"unsupported geometry");
3713 const RefTrf &tr = geom_parent[el.
Geom()][(int) pa.
ref_type][ch];
3714 tr.Apply(coord, coord);
3725 return (pt[0] >= 0) && (pt[0] <= T_ONE) &&
3726 (pt[1] >= 0) && (pt[1] <= T_ONE);
3729 return (pt[0] >= 0) && (pt[0] <= T_ONE) &&
3730 (pt[1] >= 0) && (pt[1] <= T_ONE) &&
3731 (pt[2] >= 0) && (pt[2] <= T_ONE);
3734 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE);
3737 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE) &&
3738 (pt[2] >= 0) && (pt[2] <= T_ONE);
3741 MFEM_ABORT(
"unsupported geometry");
3757 for (
int ch = 0; ch < 8 && el.
child[ch] >= 0; ch++)
3759 const RefTrf &tr = geom_child[el.
Geom()][(int) el.
ref_type][ch];
3760 tr.Apply(coord, tcoord);
3762 if (RefPointInside(el.
Geom(), tcoord))
3774 MFEM_ASSERT(geom_corners[el.
Geom()],
"unsupported geometry");
3775 std::memcpy(coord, geom_corners[el.
Geom()][local],
sizeof(coord));
3788 MFEM_ASSERT(np == pm.
np,
"");
3789 for (
int i = 0; i < np; i++)
3792 for (
int j = 0; j < points[i].dim; j++)
3794 if (points[i].coord[j] != pm.
points[i].
coord[j]) {
return false; }
3803 for (
int i = 0; i < np; i++)
3805 for (
int j = 0; j < points[0].dim; j++)
3807 point_matrix(j, i) = points[i].coord[j];
3822 Point(0, 0, 0),
Point(1, 0, 0),
Point(0, 1, 0),
Point(0, 0, 1)
3829 Point(0, 0, 0),
Point(1, 0, 0),
Point(1, 1, 0),
Point(0, 1, 0),
3830 Point(0, 0, 1),
Point(1, 0, 1),
Point(1, 1, 1),
Point(0, 1, 1)
3844 MFEM_ABORT(
"unsupported geometry " << geom);
3856 int ref_type = *ref_path++;
3857 int child = *ref_path++;
3865 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3866 Point mid67(pm(6), pm(7)), mid45(pm(4), pm(5));
3871 pm(4), mid45, mid67, pm(7));
3873 else if (child == 1)
3876 mid45, pm(5), pm(6), mid67);
3879 else if (ref_type == 2)
3881 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3882 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
3887 pm(4), pm(5), mid56, mid74);
3889 else if (child == 1)
3892 mid74, mid56, pm(6), pm(7));
3895 else if (ref_type == 4)
3897 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3898 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3903 mid04, mid15, mid26, mid37);
3905 else if (child == 1)
3908 pm(4), pm(5), pm(6), pm(7));
3911 else if (ref_type == 3)
3913 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3914 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
3915 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
3916 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
3918 Point midf0(mid23, mid12, mid01, mid30);
3919 Point midf5(mid45, mid56, mid67, mid74);
3924 pm(4), mid45, midf5, mid74);
3926 else if (child == 1)
3929 mid45, pm(5), mid56, midf5);
3931 else if (child == 2)
3934 midf5, mid56, pm(6), mid67);
3936 else if (child == 3)
3939 mid74, midf5, mid67, pm(7));
3942 else if (ref_type == 5)
3944 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3945 Point mid45(pm(4), pm(5)), mid67(pm(6), pm(7));
3946 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3947 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3949 Point midf1(mid01, mid15, mid45, mid04);
3950 Point midf3(mid23, mid37, mid67, mid26);
3955 mid04, midf1, midf3, mid37);
3957 else if (child == 1)
3960 midf1, mid15, mid26, midf3);
3962 else if (child == 2)
3965 mid45, pm(5), pm(6), mid67);
3967 else if (child == 3)
3970 pm(4), mid45, mid67, pm(7));
3973 else if (ref_type == 6)
3975 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3976 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
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 midf2(mid12, mid26, mid56, mid15);
3981 Point midf4(mid30, mid04, mid74, mid37);
3986 mid04, mid15, midf2, midf4);
3988 else if (child == 1)
3991 midf4, midf2, mid26, mid37);
3993 else if (child == 2)
3996 pm(4), pm(5), mid56, mid74);
3998 else if (child == 3)
4001 mid74, mid56, pm(6), pm(7));
4004 else if (ref_type == 7)
4006 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4007 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
4008 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
4009 Point mid67(pm(6), pm(7)), 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 midf0(mid23, mid12, mid01, mid30);
4014 Point midf1(mid01, mid15, mid45, mid04);
4015 Point midf2(mid12, mid26, mid56, mid15);
4016 Point midf3(mid23, mid37, mid67, mid26);
4017 Point midf4(mid30, mid04, mid74, mid37);
4018 Point midf5(mid45, mid56, mid67, mid74);
4020 Point midel(midf1, midf3);
4025 mid04, midf1, midel, midf4);
4027 else if (child == 1)
4030 midf1, mid15, midf2, midel);
4032 else if (child == 2)
4035 midel, midf2, mid26, midf3);
4037 else if (child == 3)
4040 midf4, midel, midf3, mid37);
4042 else if (child == 4)
4045 pm(4), mid45, midf5, mid74);
4047 else if (child == 5)
4050 mid45, pm(5), mid56, midf5);
4052 else if (child == 6)
4055 midf5, mid56, pm(6), mid67);
4057 else if (child == 7)
4060 mid74, midf5, mid67, pm(7));
4068 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4069 Point mid20(pm(2), pm(0)), mid34(pm(3), pm(4));
4070 Point mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
4074 pm =
PointMatrix(pm(0), mid01, mid20, pm(3), mid34, mid53);
4076 else if (child == 1)
4078 pm =
PointMatrix(mid01, pm(1), mid12, mid34, pm(4), mid45);
4080 else if (child == 2)
4082 pm =
PointMatrix(mid20, mid12, pm(2), mid53, mid45, pm(5));
4084 else if (child == 3)
4086 pm =
PointMatrix(mid12, mid20, mid01, mid45, mid53, mid34);
4089 else if (ref_type == 4)
4091 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
4095 pm =
PointMatrix(pm(0), pm(1), pm(2), mid03, mid14, mid25);
4097 else if (child == 1)
4099 pm =
PointMatrix(mid03, mid14, mid25, pm(3), pm(4), pm(5));
4102 else if (ref_type > 4)
4104 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
4105 Point mid34(pm(3), pm(4)), mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
4106 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
4108 Point midf2(mid01, mid14, mid34, mid03);
4109 Point midf3(mid12, mid25, mid45, mid14);
4110 Point midf4(mid20, mid03, mid53, mid25);
4114 pm =
PointMatrix(pm(0), mid01, mid20, mid03, midf2, midf4);
4116 else if (child == 1)
4118 pm =
PointMatrix(mid01, pm(1), mid12, midf2, mid14, midf3);
4120 else if (child == 2)
4122 pm =
PointMatrix(mid20, mid12, pm(2), midf4, midf3, mid25);
4124 else if (child == 3)
4126 pm =
PointMatrix(mid12, mid20, mid01, midf3, midf4, midf2);
4128 else if (child == 4)
4130 pm =
PointMatrix(mid03, midf2, midf4, pm(3), mid34, mid53);
4132 else if (child == 5)
4134 pm =
PointMatrix(midf2, mid14, midf3, mid34, pm(4), mid45);
4136 else if (child == 6)
4138 pm =
PointMatrix(midf4, midf3, mid25, mid53, mid45, pm(5));
4140 else if (child == 7)
4142 pm =
PointMatrix(midf3, midf4, midf2, mid45, mid53, mid34);
4148 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid02(pm(2), pm(0));
4149 Point mid03(pm(0), pm(3)), mid13(pm(1), pm(3)), mid23(pm(2), pm(3));
4155 else if (child == 1)
4159 else if (child == 2)
4163 else if (child == 3)
4167 else if (child == 4)
4171 else if (child == 5)
4175 else if (child == 6)
4179 else if (child == 7)
4188 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
4194 else if (child == 1)
4199 else if (ref_type == 2)
4201 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
4207 else if (child == 1)
4212 else if (ref_type == 3)
4214 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
4215 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
4216 Point midel(mid01, mid23);
4222 else if (child == 1)
4226 else if (child == 2)
4230 else if (child == 3)
4238 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
4244 else if (child == 1)
4248 else if (child == 2)
4252 else if (child == 3)
4260 for (
int i = 0; i < pm.
np; i++)
4262 for (
int j = 0; j < pm(i).dim; j++)
4264 matrix(j, i) = pm(i).coord[j];
4289 int &matrix = map[ref_path];
4290 if (!matrix) { matrix = map.size(); }
4293 emb.
parent = coarse_index;
4298 MFEM_ASSERT(el.
tet_type == 0,
"not implemented");
4301 ref_path.push_back(0);
4303 for (
int i = 0; i < 8; i++)
4305 if (el.
child[i] >= 0)
4307 ref_path[ref_path.length()-1] = i;
4311 ref_path.resize(ref_path.length()-2);
4318 "GetRefinementTransforms() must be preceded by MarkCoarseLevel()"
4326 std::string ref_path;
4327 ref_path.reserve(100);
4332 path_map[g][ref_path] = 1;
4340 used_geoms |= (1 <<
geom);
4345 if (used_geoms & (1 << g))
4354 RefPathMap::iterator it;
4355 for (it = path_map[g].begin(); it != path_map[g].end(); ++it)
4369 "GetDerefinementTransforms() must be preceded by Derefine().");
4385 int geom = code & 0xf;
4386 int ref_type_child = code >> 4;
4388 int &matrix = mat_no[
geom][ref_type_child];
4389 if (!matrix) { matrix = mat_no[
geom].size(); }
4396 if (
Geoms & (1 << g))
4405 for (
auto it = mat_no[geom].begin(); it != mat_no[
geom].end(); ++it)
4407 char path[3] = { 0, 0, 0 };
4409 int code = it->first;
4412 path[0] = code >> 4;
4413 path[1] = code & 0xf;
4436 : geom(g), num_children(n), children(c) { }
4438 bool operator<(
const RefType &other)
const
4440 if (geom < other.geom) {
return true; }
4441 if (geom > other.geom) {
return false; }
4442 if (num_children < other.num_children) {
return true; }
4443 if (num_children > other.num_children) {
return false; }
4444 for (
int i = 0; i < num_children; i++)
4446 if (children[i].one < other.children[i].one) {
return true; }
4447 if (children[i].one > other.children[i].one) {
return false; }
4459 bool get_coarse_to_fine_only)
const
4461 const int fine_ne = embeddings.Size();
4463 for (
int i = 0; i < fine_ne; i++)
4465 coarse_ne = std::max(coarse_ne, embeddings[i].parent);
4469 coarse_to_ref_type.
SetSize(coarse_ne);
4470 coarse_to_fine.
SetDims(coarse_ne, fine_ne);
4475 for (
int i = 0; i < fine_ne; i++)
4477 cf_i[embeddings[i].parent+1]++;
4480 MFEM_ASSERT(cf_i.Last() == cf_j.
Size(),
"internal error");
4481 for (
int i = 0; i < fine_ne; i++)
4485 cf_j[cf_i[e.
parent]].two = i;
4488 std::copy_backward(cf_i.begin(), cf_i.end()-1, cf_i.end());
4490 for (
int i = 0; i < coarse_ne; i++)
4492 std::sort(&cf_j[cf_i[i]], cf_j.
GetData() + cf_i[i+1]);
4494 for (
int i = 0; i < fine_ne; i++)
4496 coarse_to_fine.
GetJ()[i] = cf_j[i].two;
4499 if (get_coarse_to_fine_only) {
return; }
4501 "GetCoarseToFineMap is not fully supported for derefined meshes."
4502 " Set 'get_coarse_to_fine_only=true'.")
4504 using internal::RefType;
4508 map<RefType,int> ref_type_map;
4509 for (
int i = 0; i < coarse_ne; i++)
4511 const int num_children = cf_i[i+1]-cf_i[i];
4512 MFEM_ASSERT(num_children > 0,
"");
4513 const int fine_el = cf_j[cf_i[i]].two;
4516 const RefType ref_type(geom, num_children, &cf_j[cf_i[i]]);
4517 pair<map<RefType,int>::iterator,
bool> res =
4518 ref_type_map.insert(
4519 pair<const RefType,int>(ref_type, (
int)ref_type_map.size()));
4520 coarse_to_ref_type[i] = res.first->second;
4523 ref_type_to_matrix.
MakeI((
int)ref_type_map.size());
4524 ref_type_to_geom.
SetSize((
int)ref_type_map.size());
4525 for (map<RefType,int>::iterator it = ref_type_map.begin();
4526 it != ref_type_map.end(); ++it)
4528 ref_type_to_matrix.
AddColumnsInRow(it->second, it->first.num_children);
4529 ref_type_to_geom[it->second] = it->first.geom;
4532 ref_type_to_matrix.
MakeJ();
4533 for (map<RefType,int>::iterator it = ref_type_map.begin();
4534 it != ref_type_map.end(); ++it)
4536 const RefType &rt = it->first;
4537 for (
int j = 0; j < rt.num_children; j++)
4539 ref_type_to_matrix.
AddConnection(it->second, rt.children[j].one);
4546 Table &coarse_to_fine)
const
4549 Table ref_type_to_matrix;
4551 bool get_coarse_to_fine_only =
true;
4552 GetCoarseToFineMap(fine_mesh, coarse_to_fine, coarse_to_ref_type,
4553 ref_type_to_matrix, ref_type_to_geom,
4554 get_coarse_to_fine_only);
4567 point_matrices[i].SetSize(0, 0, 0);
4569 embeddings.DeleteAll();
4577 if (point_matrices[i].SizeK()) {
return true; }
4594 static int sgn(
int x)
4596 return (x < 0) ? -1 : (x > 0) ? 1 : 0;
4599 static void HilbertSfc2D(
int x,
int y,
int ax,
int ay,
int bx,
int by,
4602 int w = std::abs(ax + ay);
4603 int h = std::abs(bx + by);
4605 int dax = sgn(ax), day = sgn(ay);
4606 int dbx = sgn(bx), dby = sgn(by);
4610 for (
int i = 0; i < w; i++, x += dax, y += day)
4619 for (
int i = 0; i < h; i++, x += dbx, y += dby)
4627 int ax2 = ax/2, ay2 = ay/2;
4628 int bx2 = bx/2, by2 = by/2;
4630 int w2 = std::abs(ax2 + ay2);
4631 int h2 = std::abs(bx2 + by2);
4635 if ((w2 & 0x1) && (w > 2))
4637 ax2 += dax, ay2 += day;
4640 HilbertSfc2D(x, y, ax2, ay2, bx, by, coords);
4641 HilbertSfc2D(x+ax2, y+ay2, ax-ax2, ay-ay2, bx, by, coords);
4645 if ((h2 & 0x1) && (h > 2))
4647 bx2 += dbx, by2 += dby;
4650 HilbertSfc2D(x, y, bx2, by2, ax2, ay2, coords);
4651 HilbertSfc2D(x+bx2, y+by2, ax, ay, bx-bx2, by-by2, coords);
4652 HilbertSfc2D(x+(ax-dax)+(bx2-dbx), y+(ay-day)+(by2-dby),
4653 -bx2, -by2, -(ax-ax2), -(ay-ay2), coords);
4657 static void HilbertSfc3D(
int x,
int y,
int z,
4658 int ax,
int ay,
int az,
4659 int bx,
int by,
int bz,
4660 int cx,
int cy,
int cz,
4663 int w = std::abs(ax + ay + az);
4664 int h = std::abs(bx + by + bz);
4665 int d = std::abs(cx + cy + cz);
4667 int dax = sgn(ax), day = sgn(ay), daz = sgn(az);
4668 int dbx = sgn(bx), dby = sgn(by), dbz = sgn(bz);
4669 int dcx = sgn(cx), dcy = sgn(cy), dcz = sgn(cz);
4672 if (h == 1 && d == 1)
4674 for (
int i = 0; i < w; i++, x += dax, y += day, z += daz)
4682 if (w == 1 && d == 1)
4684 for (
int i = 0; i < h; i++, x += dbx, y += dby, z += dbz)
4692 if (w == 1 && h == 1)
4694 for (
int i = 0; i < d; i++, x += dcx, y += dcy, z += dcz)
4703 int ax2 = ax/2, ay2 = ay/2, az2 = az/2;
4704 int bx2 = bx/2, by2 = by/2, bz2 = bz/2;
4705 int cx2 = cx/2, cy2 = cy/2, cz2 = cz/2;
4707 int w2 = std::abs(ax2 + ay2 + az2);
4708 int h2 = std::abs(bx2 + by2 + bz2);
4709 int d2 = std::abs(cx2 + cy2 + cz2);
4712 if ((w2 & 0x1) && (w > 2))
4714 ax2 += dax, ay2 += day, az2 += daz;
4716 if ((h2 & 0x1) && (h > 2))
4718 bx2 += dbx, by2 += dby, bz2 += dbz;
4720 if ((d2 & 0x1) && (d > 2))
4722 cx2 += dcx, cy2 += dcy, cz2 += dcz;
4726 if ((2*w > 3*h) && (2*w > 3*d))
4728 HilbertSfc3D(x, y, z,
4731 cx, cy, cz, coords);
4733 HilbertSfc3D(x+ax2, y+ay2, z+az2,
4734 ax-ax2, ay-ay2, az-az2,
4736 cx, cy, cz, coords);
4741 HilbertSfc3D(x, y, z,
4744 ax2, ay2, az2, coords);
4746 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4748 bx-bx2, by-by2, bz-bz2,
4749 cx, cy, cz, coords);
4751 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4752 y+(ay-day)+(by2-dby),
4753 z+(az-daz)+(bz2-dbz),
4756 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4761 HilbertSfc3D(x, y, z,
4764 bx, by, bz, coords);
4766 HilbertSfc3D(x+cx2, y+cy2, z+cz2,
4769 cx-cx2, cy-cy2, cz-cz2, coords);
4771 HilbertSfc3D(x+(ax-dax)+(cx2-dcx),
4772 y+(ay-day)+(cy2-dcy),
4773 z+(az-daz)+(cz2-dcz),
4775 -(ax-ax2), -(ay-ay2), -(az-az2),
4776 bx, by, bz, coords);
4781 HilbertSfc3D(x, y, z,
4784 ax2, ay2, az2, coords);
4786 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4789 bx-bx2, by-by2, bz-bz2, coords);
4791 HilbertSfc3D(x+(bx2-dbx)+(cx-dcx),
4792 y+(by2-dby)+(cy-dcy),
4793 z+(bz2-dbz)+(cz-dcz),
4796 -(cx-cx2), -(cy-cy2), -(cz-cz2), coords);
4798 HilbertSfc3D(x+(ax-dax)+bx2+(cx-dcx),
4799 y+(ay-day)+by2+(cy-dcy),
4800 z+(az-daz)+bz2+(cz-dcz),
4802 -(ax-ax2), -(ay-ay2), -(az-az2),
4803 bx-bx2, by-by2, bz-bz2, coords);
4805 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4806 y+(ay-day)+(by2-dby),
4807 z+(az-daz)+(bz2-dbz),
4810 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4817 coords.
Reserve(2*width*height);
4819 if (width >= height)
4821 HilbertSfc2D(0, 0, width, 0, 0, height, coords);
4825 HilbertSfc2D(0, 0, 0, height, width, 0, coords);
4833 coords.
Reserve(3*width*height*depth);
4835 if (width >= height && width >= depth)
4837 HilbertSfc3D(0, 0, 0,
4840 0, 0, depth, coords);
4842 else if (height >= width && height >= depth)
4844 HilbertSfc3D(0, 0, 0,
4847 0, 0, depth, coords);
4851 HilbertSfc3D(0, 0, 0,
4854 0, height, 0, coords);
4862 bool oriented)
const
4866 const int* ev = gi.
edges[(int) edge_id.
local];
4868 int n0 = el.
node[ev[0]], n1 = el.
node[ev[1]];
4869 if (n0 > n1) { std::swap(n0, n1); }
4871 vert_index[0] =
nodes[n0].vert_index;
4872 vert_index[1] =
nodes[n1].vert_index;
4874 if (oriented && vert_index[0] > vert_index[1])
4876 std::swap(vert_index[0], vert_index[1]);
4884 const int* ev = gi.
edges[(int) edge_id.
local];
4886 int v0 =
nodes[el.
node[ev[0]]].vert_index;
4887 int v1 =
nodes[el.
node[ev[1]]].vert_index;
4889 return ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1])) ? -1 : 1;
4893 int vert_index[4],
int edge_index[4],
4894 int edge_orientation[4])
const
4896 MFEM_ASSERT(
Dim >= 3,
"");
4901 const int *fv = gi.
faces[(int) face_id.
local];
4902 const int nfv = gi.
nfv[(
int) face_id.
local];
4904 vert_index[3] = edge_index[3] = -1;
4905 edge_orientation[3] = 0;
4907 for (
int i = 0; i < nfv; i++)
4909 vert_index[i] =
nodes[el.
node[fv[i]]].vert_index;
4912 for (
int i = 0; i < nfv; i++)
4915 if (j >= nfv) { j = 0; }
4917 int n1 = el.
node[fv[i]];
4918 int n2 = el.
node[fv[j]];
4921 MFEM_ASSERT(en != NULL,
"edge not found.");
4924 edge_orientation[i] = (vert_index[i] < vert_index[j]) ? 1 : -1;
4932 MFEM_ASSERT(node >= 0,
"edge node not found.");
4935 int p1 = nd.
p1, p2 = nd.
p2;
4936 MFEM_ASSERT(p1 != p2,
"invalid edge node.");
4940 int n1p1 = n1.
p1, n1p2 = n1.
p2;
4941 int n2p1 = n2.p1, n2p2 = n2.p2;
4943 if ((n2p1 != n2p2) && (p1 == n2p1 || p1 == n2p2))
4947 if (n2.HasEdge()) {
return p2; }
4951 if ((n1p1 != n1p2) && (p2 == n1p1 || p2 == n1p2))
4955 if (n1.
HasEdge()) {
return p1; }
4965 MFEM_ASSERT(node >= 0 &&
nodes[node].HasEdge(),
"(v1, v2) is not an edge.");
4968 return (master >= 0) ?
nodes[master].edge_index : -1;
4974 int depth = 0, parent;
4975 while ((parent =
elements[elem].parent) != -1)
4986 int parent, reduction = 1;
4987 while ((parent =
elements[elem].parent) != -1)
4989 if (
elements[parent].ref_type & 1) { reduction *= 2; }
4990 if (
elements[parent].ref_type & 2) { reduction *= 2; }
4991 if (
elements[parent].ref_type & 4) { reduction *= 2; }
5007 for (
int i = 0; i < gi.
nf; i++)
5009 const int* fv = gi.
faces[i];
5012 MFEM_ASSERT(face,
"face not found");
5013 faces[i] = face->
index;
5025 int elem = fa.
elem[0];
5026 if (elem < 0) { elem = fa.
elem[1]; }
5027 MFEM_ASSERT(elem >= 0,
"Face has no elements?");
5036 for (
int i = 0; i < 4; i++)
5038 node[i] = el.
node[fv[i]];
5055 if (bdr_attr_is_ess[
faces[face].attribute - 1])
5059 int nfv = (node[3] < 0) ? 3 : 4;
5061 for (
int j = 0; j < nfv; j++)
5065 int enode =
nodes.FindId(node[j], node[(j+1) % nfv]);
5066 MFEM_ASSERT(enode >= 0 &&
nodes[enode].HasEdge(),
"Edge not found.");
5095 bdr_vertices.
Sort();
5102 static int max4(
int a,
int b,
int c,
int d)
5104 return std::max(std::max(a, b), std::max(c, d));
5106 static int max6(
int a,
int b,
int c,
int d,
int e,
int f)
5108 return std::max(max4(a, b, c, d), std::max(e, f));
5110 static int max8(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h)
5112 return std::max(max4(a, b, c, d), max4(e, f, g, h));
5117 int mid =
nodes.FindId(vn1, vn2);
5118 if (mid < 0 || !
nodes[mid].HasVertex()) {
return 0; }
5126 faces.FindId(vn1, vn2, vn3) < 0)
5140 int& h_level,
int& v_level)
const
5142 int hl1, hl2, vl1, vl2;
5148 h_level = v_level = 0;
5154 h_level = std::max(hl1, hl2);
5155 v_level = std::max(vl1, vl2) + 1;
5161 h_level = std::max(hl1, hl2) + 1;
5162 v_level = std::max(vl1, vl2);
5169 const int* node = el.
node;
5173 for (
int i = 0; i < gi.
ne; i++)
5175 const int* ev = gi.
edges[i];
5182 for (
int i = 0; i < gi.
nf; i++)
5184 const int* fv = gi.
faces[i];
5188 node[fv[2]], node[fv[3]],
5189 flevel[i][1], flevel[i][0]);
5202 splits[0] = max8(flevel[0][0], flevel[1][0], flevel[3][0], flevel[5][0],
5203 elevel[0], elevel[2], elevel[4], elevel[6]);
5205 splits[1] = max8(flevel[0][1], flevel[2][0], flevel[4][0], flevel[5][1],
5206 elevel[1], elevel[3], elevel[5], elevel[7]);
5208 splits[2] = max8(flevel[1][1], flevel[2][1], flevel[3][1], flevel[4][1],
5209 elevel[8], elevel[9], elevel[10], elevel[11]);
5213 splits[0] = splits[1] =
5215 max6(flevel[0][0], flevel[1][0], 0,
5216 flevel[2][0], flevel[3][0], flevel[4][0]),
5217 max6(elevel[0], elevel[1], elevel[2],
5218 elevel[3], elevel[4], elevel[5]));
5220 splits[2] = max6(flevel[2][1], flevel[3][1], flevel[4][1],
5221 elevel[6], elevel[7], elevel[8]);
5225 splits[0] = std::max(
5226 max4(flevel[0][0], flevel[1][0], flevel[2][0], flevel[3][0]),
5227 max6(elevel[0], elevel[1], elevel[2],
5228 elevel[3], elevel[4], elevel[5]));
5230 splits[1] = splits[0];
5231 splits[2] = splits[0];
5235 splits[0] = std::max(elevel[0], elevel[2]);
5236 splits[1] = std::max(elevel[1], elevel[3]);
5240 splits[0] = std::max(elevel[0], std::max(elevel[1], elevel[2]));
5241 splits[1] = splits[0];
5245 MFEM_ABORT(
"Unsupported element geometry.");
5259 for (
int k = 0; k <
Dim; k++)
5261 if (splits[k] > max_level)
5263 ref_type |= (1 << k);
5281 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
5288 if (!refinements.
Size()) {
break; }
5303 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5305 if (node->HasVertex() && node->p1 != node->p2) { nv++; }
5312 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5314 if (node->HasVertex() && node->p1 != node->p2)
5316 MFEM_ASSERT(
nodes[node->p1].HasVertex(),
"");
5317 MFEM_ASSERT(
nodes[node->p2].HasVertex(),
"");
5319 (*out) << node.index() <<
" " << node->p1 <<
" " << node->p2 <<
"\n";
5333 input >>
id >> p1 >> p2;
5334 MFEM_VERIFY(input,
"problem reading vertex parents.");
5336 MFEM_VERIFY(
nodes.IdExists(
id),
"vertex " <<
id <<
" not found.");
5337 MFEM_VERIFY(
nodes.IdExists(p1),
"parent " << p1 <<
" not found.");
5338 MFEM_VERIFY(
nodes.IdExists(p2),
"parent " << p2 <<
" not found.");
5340 int check =
nodes.FindId(p1, p2);
5341 MFEM_VERIFY(check < 0,
"parents (" << p1 <<
", " << p2 <<
") already "
5342 "assigned to node " << check);
5345 nodes.Reparent(
id, p1, p2);
5351 static const int nfv2geom[5] =
5356 int deg = (
Dim == 2) ? 2 : 1;
5359 for (
int i = 0; i <
elements.Size(); i++)
5362 if (!el.
IsLeaf()) {
continue; }
5365 for (
int k = 0; k < gi.
nf; k++)
5367 const int* fv = gi.
faces[k];
5368 const int nfv = gi.
nfv[k];
5371 MFEM_ASSERT(face != NULL,
"face not found");
5374 if (!out) { count++;
continue; }
5376 (*out) << face->
attribute <<
" " << nfv2geom[nfv];
5377 for (
int j = 0; j < nfv; j++)
5379 (*out) <<
" " << el.
node[fv[j*deg]];
5392 for (
int i = 0; i < nb; i++)
5394 input >> attr >>
geom;
5399 input >> v1 >> v2 >> v3 >> v4;
5405 input >> v1 >> v2 >> v3;
5423 MFEM_ABORT(
"unsupported boundary element geometry: " << geom);
5432 if (!nv) {
return; }
5435 for (
int i = 0; i < nv; i++)
5440 out <<
" " << coordinates[3*i + j];
5450 if (!nv) {
return; }
5457 for (
int i = 0; i < nv; i++)
5462 MFEM_VERIFY(input.good(),
"unexpected EOF");
5478 out <<
"MFEM NC mesh v1.0\n\n"
5479 "# NCMesh supported geometry types:\n"
5483 "# TETRAHEDRON = 4\n"
5487 out <<
"\ndimension\n" <<
Dim <<
"\n";
5489 #ifndef MFEM_USE_MPI
5493 out <<
"\nrank\n" <<
MyRank <<
"\n";
5496 out <<
"\n# rank attr geom ref_type nodes/children";
5497 out <<
"\nelements\n" <<
elements.Size() <<
"\n";
5499 for (
int i = 0; i <
elements.Size(); i++)
5503 if (el.
parent == -2) { out <<
"-1\n";
continue; }
5506 for (
int j = 0; j < 8 && el.
node[j] >= 0; j++)
5508 out <<
" " << el.
node[j];
5516 out <<
"\n# attr geom nodes";
5517 out <<
"\nboundary\n" << nb <<
"\n";
5525 out <<
"\n# vert_id p1 p2";
5526 out <<
"\nvertex_parents\n" << nvp <<
"\n";
5533 out <<
"\n# root element orientation";
5544 out <<
"\n# top-level node coordinates";
5545 out <<
"\ncoordinates\n";
5558 for (
int i = 0; i <
elements.Size(); i++)
5563 for (
int j = 0; j < 8 && el.
child[j] >= 0; j++)
5565 int child = el.
child[j];
5566 MFEM_VERIFY(child <
elements.Size(),
"invalid mesh file: "
5567 "element " << i <<
" references invalid child " << child);
5580 MFEM_VERIFY(nroots,
"invalid mesh file: no root elements found.");
5583 for (
int i = nroots; i <
elements.Size(); i++)
5585 MFEM_VERIFY(
elements[i].parent != -1,
5586 "invalid mesh file: only the first M elements can be roots. "
5587 "Found element " << i <<
" with no parent.");
5598 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
5600 if (node->p1 == node->p2) { ntop = node.index() + 1; }
5616 MFEM_ASSERT(version == 10,
"");
5623 MFEM_VERIFY(ident ==
"dimension",
"Invalid mesh file: " << ident);
5629 if (ident ==
"rank")
5632 MFEM_VERIFY(MyRank >= 0,
"Invalid rank");
5639 if (ident ==
"sfc_version")
5642 input >> sfc_version;
5643 MFEM_VERIFY(sfc_version == 0,
5644 "Unsupported mesh file SFC version (" << sfc_version <<
"). "
5645 "Please update MFEM.");
5652 MFEM_VERIFY(ident ==
"elements",
"Invalid mesh file: " << ident);
5654 for (
int i = 0; i < count; i++)
5656 int rank, attr,
geom, ref_type;
5657 input >> rank >> attr >>
geom;
5662 MFEM_ASSERT(
elements.Size() == i+1,
"");
5668 CheckSupportedGeom(type);
5672 MFEM_VERIFY(ref_type >= 0 && ref_type < 8,
"");
5673 el.ref_type = ref_type;
5677 for (
int j = 0; j < ref_type_num_children[ref_type]; j++)
5679 input >> el.child[j];
5681 if (Dim == 3 && ref_type != 7) {
Iso =
false; }
5685 for (
int j = 0; j <
GI[
geom].
nv; j++)
5690 nodes.Alloc(
id,
id,
id);
5710 if (ident ==
"boundary")
5719 if (ident ==
"vertex_parents")
5728 if (ident ==
"root_state")
5732 for (
int i = 0; i < count; i++)
5742 if (ident ==
"coordinates")
5747 "Invalid mesh file: not all top-level nodes are covered by "
5748 "the 'coordinates' section of the mesh file.");
5751 else if (ident ==
"nodes")
5761 MFEM_ABORT(
"Invalid mesh file: either 'coordinates' or "
5762 "'nodes' must be present");
5766 nodes.UpdateUnused();
5767 for (
int i = 0; i <
elements.Size(); i++)
5785 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
5787 int old_id = el.
child[i];
5789 int new_id =
elements.Append(tmp_elements[old_id]);
5790 el.
child[i] = new_id;
5814 if (
Dim == 3 && ref_type != 7) { iso =
false; }
5817 int nch = ref_type_num_children[ref_type];
5818 for (
int i = 0,
id; i < nch; i++)
5821 MFEM_VERIFY(
id >= 0,
"");
5823 "coarse element cannot be referenced before it is "
5824 "defined (id=" <<
id <<
").");
5827 MFEM_VERIFY(child.parent == -1,
5828 "element " <<
id <<
" cannot have two parents.");
5831 child.parent = elem;
5835 el.
geom = child.geom;
5847 for (
auto el = tmp_elements.
begin(); el != tmp_elements.
end(); ++el)
5849 if (el->parent == -1)
5857 for (
int i = 0; i < root_count; i++)
5870 MFEM_ASSERT(
elements.Size() == 0,
"");
5871 MFEM_ASSERT(
nodes.Size() == 0,
"");
5875 int count, attr,
geom;
5880 MFEM_VERIFY(ident ==
"dimension",
"invalid mesh file");
5886 MFEM_VERIFY(ident ==
"elements",
"invalid mesh file");
5889 for (
int i = 0; i < count; i++)
5891 input >> attr >>
geom;
5894 CheckSupportedGeom(type);
5898 MFEM_ASSERT(
id == i,
"");
5901 for (
int j = 0; j <
GI[
geom].
nv; j++)
5906 nodes.Alloc(
id,
id,
id);
5914 MFEM_VERIFY(ident ==
"boundary",
"invalid mesh file");
5921 if (ident ==
"vertex_parents")
5937 if (ident ==
"coarse_elements")
5952 MFEM_VERIFY(ident ==
"vertices",
"invalid mesh file");
5955 input >> std::ws >> ident;
5956 if (ident !=
"nodes")
5963 for (
int i = 0; i < nvert; i++)
5968 MFEM_VERIFY(input.good(),
"unexpected EOF");
5989 nodes.UpdateUnused();
5991 for (
int i = 0; i <
elements.Size(); i++)
6003 file_leaf_elements = -1;
6004 for (
int i = 0; i <
elements.Size(); i++)
6008 file_leaf_elements[
elements[i].index] = i;
6011 MFEM_ASSERT(file_leaf_elements.
Min() >= 0,
"");
6032 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
6034 if (node->HasVertex())
6036 MFEM_ASSERT(node.index() >= 0,
"");
6037 MFEM_ASSERT(node.index() < order.
Size(),
"");
6038 MFEM_ASSERT(order[node.index()] == -1,
"");
6040 order[node.index()] = node->vert_index;
6044 MFEM_ASSERT(count == order.
Size(),
"");
6070 for (
int j = 0; j < point_matrices[i].Size(); i++)
6072 pm_size += point_matrices[i][j]->MemoryUsage();
6074 pm_size += point_matrices[i].MemoryUsage();
6085 long mem = embeddings.MemoryUsage();
6088 mem += point_matrices[i].MemoryUsage();
6095 return nodes.MemoryUsage() +
6096 faces.MemoryUsage() +
6133 <<
ref_stack.MemoryUsage() <<
" ref_stack\n"
6137 <<
sizeof(*this) <<
" NCMesh"
6150 for (
int j = 0; j <
Dim; j++)
6154 for (
int k = 0; k < 8; k++)
6156 if (elem->
node[k] >= 0)
6162 out << sum / count <<
" ";
6173 out <<
nodes.Size() <<
"\n";
6174 for (
auto node =
nodes.cbegin(); node !=
nodes.cend(); ++node)
6177 out << node.index() <<
" "
6178 << pos[0] <<
" " << pos[1] <<
" " << pos[2] <<
" "
6179 << node->p1 <<
" " << node->p2 <<
" "
6180 << node->vert_index <<
" " << node->edge_index <<
" "
6188 for (
int i = 0; i <
elements.Size(); i++)
6190 if (
elements[i].IsLeaf()) { nleaves++; }
6192 out << nleaves <<
"\n";
6193 for (
int i = 0; i <
elements.Size(); i++)
6199 out << gi.
nv <<
" ";
6200 for (
int j = 0; j < gi.
nv; j++)
6202 out << el.
node[j] <<
" ";
6210 out <<
faces.Size() <<
"\n";
6211 for (
auto face =
faces.cbegin(); face !=
faces.cend(); ++face)
6213 int elem = face->elem[0];
6214 if (elem < 0) { elem = face->elem[1]; }
6215 MFEM_ASSERT(elem >= 0,
"");
6227 for (
int i = 0; i < nfv; i++)
6229 out <<
" " << 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.
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
void AddColumnsInRow(int r, int ncol)
This holds in one place the constants about the geometries we support.
Array< Triple< int, int, int > > reparents
scheduled node reparents (tmp)
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
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().
void SetDims(int rows, int nnz)
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
bool operator<(const Pair< A, B > &p, const Pair< A, B > &q)
Comparison operator for class Pair, based on the first element only.
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.
Geometry::Type GetElementBaseGeometry(int i) const
int spaceDim
dimensions of the elements and the vertex coordinates
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()
update Vertex::index and vertex_nodeId
void AddConnection(int r, int c)
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
virtual void BuildFaceList()
Nonconforming edge/face within a bigger edge/face.
void DerefineElement(int elem)
void GetElementFacesAttributes(int i, Array< int > &faces, Array< int > &fattr) const
Return the faces and face attributes of leaf element 'i'.
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
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()
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()
Operation GetLastOperation() const
Return type of last modification of the mesh.
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
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'.
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
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)
int matrix
Index into the DenseTensor corresponding to the parent Geometry::Type stored in CoarseFineTransformat...
Array< char > face_geom
face geometry by face index, set by OnMeshUpdated
int GetEdgeMaster(int v1, int v2) const