13 #include "../fem/fem.hpp"
14 #include "../general/sort_pairs.hpp"
38 for (
int i = 0; i <
ne; i++)
40 for (
int j = 0; j < 2; j++)
45 for (
int i = 0; i <
nf; i++)
50 for (
int j = 0; j <
nfv[i]; j++)
59 for (
int i = 0; i <
ne; i++)
79 Iso = vertex_parents ?
false :
true;
84 for (
int i = 0; i < mesh->
GetNE(); i++)
88 for (
int j = 0; j < nv; j++)
90 max_id = std::max(max_id, v[j]);
93 for (
int id = 0;
id <= max_id;
id++)
96 int node =
nodes.GetId(
id,
id);
97 MFEM_CONTRACT_VAR(node);
98 MFEM_ASSERT(node ==
id,
"");
113 nodes.Reparent(triple.one, triple.two, triple.three);
119 for (
int i = 0; i < mesh->
GetNV(); i++)
126 for (
int i = 0; i < mesh->
GetNE(); i++)
134 "Element type " << geom <<
" not supported by NCMesh.");
141 MFEM_ASSERT(root_id == i,
"");
145 for (
int j = 0; j <
GI[
geom].
nv; j++)
147 root_elem.
node[j] = v[j];
159 for (
int i = 0; i < mesh->
GetNBE(); i++)
166 Face* face =
faces.Find(v[0], v[1], v[2], v[3]);
167 MFEM_VERIFY(face,
"boundary face not found.");
172 Face* face =
faces.Find(v[0], v[1], v[2]);
173 MFEM_VERIFY(face,
"boundary face not found.");
178 Face* face =
faces.Find(v[0], v[0], v[1], v[1]);
179 MFEM_VERIFY(face,
"boundary face not found.");
184 MFEM_ABORT(
"Unsupported boundary element geometry.");
199 , spaceDim(other.spaceDim)
204 , elements(other.elements)
239 for (
int i = 0; i <
elements.Size(); i++)
261 "vert_refc: " << (
int)
vert_refc <<
", edge_refc: "
268 int old_p1 = nd.
p1, old_p2 = nd.
p2;
271 nodes.Reparent(node, new_p1, new_p2);
273 MFEM_ASSERT(
shadow.FindId(old_p1, old_p2) < 0,
274 "shadow node already exists");
277 int sh =
shadow.GetId(old_p1, old_p2);
278 shadow[sh].vert_index = node;
283 int mid =
nodes.FindId(node1, node2);
284 if (mid < 0 &&
shadow.Size())
288 mid =
shadow.FindId(node1, node2);
291 mid =
shadow[mid].vert_index;
300 if (mid < 0) { mid =
nodes.GetId(node1, node2); }
308 if (midf >= 0) {
return midf; }
309 return nodes.GetId(en2, en4);
319 for (
int i = 0; i < gi.
nv; i++)
321 nodes[node[i]].vert_refc++;
325 for (
int i = 0; i < gi.
ne; i++)
327 const int* ev = gi.
edges[i];
328 nodes.Get(node[ev[0]], node[ev[1]])->edge_refc++;
332 for (
int i = 0; i < gi.
nf; i++)
334 const int* fv = gi.
faces[i];
335 faces.GetId(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
350 for (
int i = 0; i < gi.
nf; i++)
352 const int* fv = gi.
faces[i];
353 int face =
faces.FindId(node[fv[0]], node[fv[1]],
354 node[fv[2]], node[fv[3]]);
355 MFEM_ASSERT(face >= 0,
"face not found.");
356 faces[face].ForgetElement(elem);
364 for (
int i = 0; i < gi.
ne; i++)
366 const int* ev = gi.
edges[i];
368 MFEM_ASSERT(enode >= 0,
"edge not found.");
369 MFEM_ASSERT(
nodes.IdExists(enode),
"edge does not exist.");
370 if (!
nodes[enode].UnrefEdge())
377 for (
int i = 0; i < gi.
nv; i++)
379 if (!
nodes[node[i]].UnrefVertex())
381 nodes.Delete(node[i]);
391 for (
int i = 0; i < gi.
nf; i++)
394 MFEM_ASSERT(face,
"face not found.");
396 if (fattr) { face->
attribute = fattr[i]; }
402 for (
int i = 0; i < elemFaces.
Size(); i++)
404 if (
faces[elemFaces[i]].Unused())
406 faces.Delete(elemFaces[i]);
413 if (elem[0] < 0) { elem[0] = e; }
414 else if (elem[1] < 0) { elem[1] = e; }
415 else { MFEM_ABORT(
"can't have 3 elements in Face::elem[]."); }
420 if (elem[0] == e) { elem[0] = -1; }
421 else if (elem[1] == e) { elem[1] = -1; }
422 else { MFEM_ABORT(
"element " << e <<
" not found in Face::elem[]."); }
428 const int* fv = gi.
faces[face_no];
429 int* node = elem.
node;
430 return faces.Find(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
437 MFEM_ASSERT(elem[1] < 0,
"not a single element face.");
442 MFEM_ASSERT(elem[1] >= 0,
"no elements in face.");
451 : geom(geom), ref_type(0), tet_type(0), flag(0),
index(-1)
452 , rank(0), attribute(attr), parent(-1)
454 for (
int i = 0; i < 8; i++) {
node[i] = -1; }
463 int n4,
int n5,
int n6,
int n7,
465 int fattr0,
int fattr1,
int fattr2,
466 int fattr3,
int fattr4,
int fattr5)
478 for (
int i = 0; i < gi_hex.
nf; i++)
480 const int* fv = gi_hex.
faces[i];
493 int n3,
int n4,
int n5,
495 int fattr0,
int fattr1,
496 int fattr2,
int fattr3,
int fattr4)
508 for (
int i = 0; i < gi_wedge.
nf; i++)
510 const int* fv = gi_wedge.
faces[i];
525 int fattr0,
int fattr1,
int fattr2,
int fattr3)
536 for (
int i = 0; i < gi_tet.
nf; i++)
538 const int* fv = gi_tet.
faces[i];
552 int eattr0,
int eattr1,
int eattr2,
int eattr3)
563 for (
int i = 0; i < gi_quad.
nf; i++)
565 const int* fv = gi_quad.
faces[i];
577 int attr,
int eattr0,
int eattr1,
int eattr2)
587 for (
int i = 0; i < gi_tri.
nf; i++)
589 const int* fv = gi_tri.
faces[i];
602 {
return node == n[0] || node == n[3] || node == n[4] || node == n[7]; }
605 {
return node == n[1] || node == n[2] || node == n[5] || node == n[6]; }
608 {
return node == n[0] || node == n[1] || node == n[4] || node == n[5]; }
611 {
return node == n[2] || node == n[3] || node == n[6] || node == n[7]; }
614 {
return node == n[0] || node == n[1] || node == n[2] || node == n[3]; }
617 {
return node == n[4] || node == n[5] || node == n[6] || node == n[7]; }
620 {
return node == n[0] || node == n[1] || node == n[2]; }
623 {
return node == n[3] || node == n[4] || node == n[5]; }
629 Face* face =
faces.Find(vn1, vn2, vn3, vn4);
630 if (!face) {
return; }
634 MFEM_ASSERT(!el.
ref_type,
"element already refined.");
657 MFEM_ABORT(
"Inconsistent element/face structure.");
674 MFEM_ABORT(
"Inconsistent element/face structure.");
679 MFEM_ABORT(
"Unsupported geometry.")
692 int ev1 = vn1, ev2 = vn4;
700 vn2 = mid[0]; vn3 = mid[2];
704 vn3 = mid[1]; vn4 = mid[3];
708 const Face *face =
faces.Find(vn1, vn2, vn3, vn4);
709 MFEM_ASSERT(face != NULL,
"Face not found: "
710 << vn1 <<
", " << vn2 <<
", " << vn3 <<
", " << vn4
711 <<
" (edge " << ev1 <<
"-" << ev2 <<
").");
720 for (
int i = 0; i < cousins.
Size(); i++)
739 for (
int i = 0, j; i < eid.
Size(); i++)
741 int elem = eid[i].element;
742 for (j = 0; j < nref; j++)
744 if (refs[j].
index == elem) {
break; }
757 int mid12,
int mid34,
int level)
785 if (mid23 >= 0 && mid41 >= 0)
787 int midf =
nodes.FindId(mid23, mid41);
816 for (
int i = 0; i <
reparents.Size(); i++)
852 int en1,
int en2,
int en3,
int en4,
int midf)
870 if (!ref_type) {
return; }
876 char remaining = ref_type & ~el.
ref_type;
879 for (
int i = 0; i < 8; i++)
897 for (
int i = 0; i < 8; i++) { child[i] = -1; }
902 for (
int i = 0; i < gi.
nf; i++)
904 const int* fv = gi.
faces[i];
905 Face* face =
faces.Find(no[fv[0]], no[fv[1]], no[fv[2]], no[fv[3]]);
934 no[4], mid45, mid67, no[7], attr,
935 fa[0], fa[1], -1, fa[3], fa[4], fa[5]);
938 mid45, no[5], no[6], mid67, attr,
939 fa[0], fa[1], fa[2], fa[3], -1, fa[5]);
946 else if (ref_type == 2)
954 no[4], no[5], mid56, mid74, attr,
955 fa[0], fa[1], fa[2], -1, fa[4], fa[5]);
958 mid74, mid56, no[6], no[7], attr,
959 fa[0], -1, fa[2], fa[3], fa[4], fa[5]);
966 else if (ref_type == 4)
974 mid04, mid15, mid26, mid37, attr,
975 fa[0], fa[1], fa[2], fa[3], fa[4], -1);
978 no[4], no[5], no[6], no[7], attr,
979 -1, fa[1], fa[2], fa[3], fa[4], fa[5]);
986 else if (ref_type == 3)
1002 no[4], mid45, midf5, mid74, attr,
1003 fa[0], fa[1], -1, -1, fa[4], fa[5]);
1006 mid45, no[5], mid56, midf5, attr,
1007 fa[0], fa[1], fa[2], -1, -1, fa[5]);
1010 midf5, mid56, no[6], mid67, attr,
1011 fa[0], -1, fa[2], fa[3], -1, fa[5]);
1014 mid74, midf5, mid67, no[7], attr,
1015 fa[0], -1, -1, fa[3], fa[4], fa[5]);
1022 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
1023 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
1025 else if (ref_type == 5)
1041 mid04, midf1, midf3, mid37, attr,
1042 fa[0], fa[1], -1, fa[3], fa[4], -1);
1045 midf1, mid15, mid26, midf3, attr,
1046 fa[0], fa[1], fa[2], fa[3], -1, -1);
1049 mid45, no[5], no[6], mid67, attr,
1050 -1, fa[1], fa[2], fa[3], -1, fa[5]);
1053 no[4], mid45, mid67, no[7], attr,
1054 -1, fa[1], -1, fa[3], fa[4], fa[5]);
1061 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
1062 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
1064 else if (ref_type == 6)
1080 mid04, mid15, midf2, midf4, attr,
1081 fa[0], fa[1], fa[2], -1, fa[4], -1);
1084 midf4, midf2, mid26, mid37, attr,
1085 fa[0], -1, fa[2], fa[3], fa[4], -1);
1088 no[4], no[5], mid56, mid74, attr,
1089 -1, fa[1], fa[2], -1, fa[4], fa[5]);
1092 mid74, mid56, no[6], no[7], attr,
1093 -1, -1, fa[2], fa[3], fa[4], fa[5]);
1100 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
1101 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
1103 else if (ref_type == 7)
1130 mid04, midf1, midel, midf4, attr,
1131 fa[0], fa[1], -1, -1, fa[4], -1);
1134 midf1, mid15, midf2, midel, attr,
1135 fa[0], fa[1], fa[2], -1, -1, -1);
1138 midel, midf2, mid26, midf3, attr,
1139 fa[0], -1, fa[2], fa[3], -1, -1);
1142 midf4, midel, midf3, mid37, attr,
1143 fa[0], -1, -1, fa[3], fa[4], -1);
1146 no[4], mid45, midf5, mid74, attr,
1147 -1, fa[1], -1, -1, fa[4], fa[5]);
1150 mid45, no[5], mid56, midf5, attr,
1151 -1, fa[1], fa[2], -1, -1, fa[5]);
1154 midf5, mid56, no[6], mid67, attr,
1155 -1, -1, fa[2], fa[3], -1, fa[5]);
1158 mid74, midf5, mid67, no[7], attr,
1159 -1, -1, -1, fa[3], fa[4], fa[5]);
1161 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
1162 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
1163 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
1164 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
1165 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
1166 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
1170 MFEM_ABORT(
"invalid refinement type.");
1173 if (ref_type != 7) {
Iso =
false; }
1203 child[0] =
NewWedge(no[0], mid01, mid20,
1204 no[3], mid34, mid53, attr,
1205 fa[0], fa[1], fa[2], -1, fa[4]);
1207 child[1] =
NewWedge(mid01, no[1], mid12,
1208 mid34, no[4], mid45, attr,
1209 fa[0], fa[1], fa[2], fa[3], -1);
1211 child[2] =
NewWedge(mid20, mid12, no[2],
1212 mid53, mid45, no[5], attr,
1213 fa[0], fa[1], -1, fa[3], fa[4]);
1215 child[3] =
NewWedge(mid12, mid20, mid01,
1216 mid45, mid53, mid34, attr,
1217 fa[0], fa[1], -1, -1, -1);
1223 else if (ref_type == 4)
1229 child[0] =
NewWedge(no[0], no[1], no[2],
1230 mid03, mid14, mid25, attr,
1231 fa[0], -1, fa[2], fa[3], fa[4]);
1233 child[1] =
NewWedge(mid03, mid14, mid25,
1234 no[3], no[4], no[5], attr,
1235 -1, fa[1], fa[2], fa[3], fa[4]);
1241 else if (ref_type > 4)
1261 child[0] =
NewWedge(no[0], mid01, mid20,
1262 mid03, midf2, midf4, attr,
1263 fa[0], -1, fa[2], -1, fa[4]);
1265 child[1] =
NewWedge(mid01, no[1], mid12,
1266 midf2, mid14, midf3, attr,
1267 fa[0], -1, fa[2], fa[3], -1);
1269 child[2] =
NewWedge(mid20, mid12, no[2],
1270 midf4, midf3, mid25, attr,
1271 fa[0], -1, -1, fa[3], fa[4]);
1273 child[3] =
NewWedge(mid12, mid20, mid01,
1274 midf3, midf4, midf2, attr,
1275 fa[0], -1, -1, -1, -1);
1277 child[4] =
NewWedge(mid03, midf2, midf4,
1278 no[3], mid34, mid53, attr,
1279 -1, fa[1], fa[2], -1, fa[4]);
1281 child[5] =
NewWedge(midf2, mid14, midf3,
1282 mid34, no[4], mid45, attr,
1283 -1, fa[1], fa[2], fa[3], -1);
1285 child[6] =
NewWedge(midf4, midf3, mid25,
1286 mid53, mid45, no[5], attr,
1287 -1, fa[1], -1, fa[3], fa[4]);
1289 child[7] =
NewWedge(midf3, midf4, midf2,
1290 mid45, mid53, mid34, attr,
1291 -1, fa[1], -1, -1, -1);
1293 CheckIsoFace(no[0], no[1], no[4], no[3], mid01, mid14, mid34, mid03, midf2);
1294 CheckIsoFace(no[1], no[2], no[5], no[4], mid12, mid25, mid45, mid14, midf3);
1295 CheckIsoFace(no[2], no[0], no[3], no[5], mid20, mid03, mid53, mid25, midf4);
1299 MFEM_ABORT(
"invalid refinement type.");
1302 if (ref_type != 7) {
Iso =
false; }
1330 -1, fa[1], fa[2], fa[3]);
1333 fa[0], -1, fa[2], fa[3]);
1336 fa[0], fa[1], -1, fa[3]);
1339 fa[0], fa[1], fa[2], -1);
1398 int mid01 =
nodes.GetId(no[0], no[1]);
1399 int mid23 =
nodes.GetId(no[2], no[3]);
1402 attr, fa[0], -1, fa[2], fa[3]);
1405 attr, fa[0], fa[1], fa[2], -1);
1407 else if (ref_type == 2)
1409 int mid12 =
nodes.GetId(no[1], no[2]);
1410 int mid30 =
nodes.GetId(no[3], no[0]);
1413 attr, fa[0], fa[1], -1, fa[3]);
1416 attr, -1, fa[1], fa[2], fa[3]);
1418 else if (ref_type == 3)
1420 int mid01 =
nodes.GetId(no[0], no[1]);
1421 int mid12 =
nodes.GetId(no[1], no[2]);
1422 int mid23 =
nodes.GetId(no[2], no[3]);
1423 int mid30 =
nodes.GetId(no[3], no[0]);
1425 int midel =
nodes.GetId(mid01, mid23);
1428 attr, fa[0], -1, -1, fa[3]);
1431 attr, fa[0], fa[1], -1, -1);
1434 attr, -1, fa[1], fa[2], -1);
1437 attr, -1, -1, fa[2], fa[3]);
1441 MFEM_ABORT(
"Invalid refinement type.");
1444 if (ref_type != 3) {
Iso =
false; }
1451 int mid01 =
nodes.GetId(no[0], no[1]);
1452 int mid12 =
nodes.GetId(no[1], no[2]);
1453 int mid20 =
nodes.GetId(no[2], no[0]);
1455 child[0] =
NewTriangle(no[0], mid01, mid20, attr, fa[0], -1, fa[2]);
1456 child[1] =
NewTriangle(mid01, no[1], mid12, attr, fa[0], fa[1], -1);
1457 child[2] =
NewTriangle(mid20, mid12, no[2], attr, -1, fa[1], fa[2]);
1458 child[3] =
NewTriangle(mid12, mid20, mid01, attr, -1, -1, -1);
1462 MFEM_ABORT(
"Unsupported element geometry.");
1466 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1479 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1488 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1497 std::memcpy(el.
child, child,
sizeof(el.
child));
1505 for (
int i = refinements.
Size()-1; i >= 0; i--)
1533 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
1534 mfem::out <<
"Refined " << refinements.
Size() <<
" + " << nforced
1535 <<
" elements" << std::endl;
1562 MFEM_ASSERT(ch != -1,
"");
1577 MFEM_ABORT(
"Unsupported element geometry.");
1589 std::memcpy(child, el.
child,
sizeof(child));
1592 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1603 for (
int i = 0; i < 8; i++) { el.
node[i] = -1; }
1608 for (
int i = 0; i < 8; i++)
1613 for (
int i = 0; i < 6; i++)
1618 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1623 MFEM_ASSERT(prism_deref_table[rt1][0] != -1,
"invalid prism refinement");
1624 for (
int i = 0; i < 6; i++)
1631 for (
int i = 0; i < 5; i++)
1636 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1641 for (
int i = 0; i < 4; i++)
1648 ch2.
node[fv[2]], ch2.
node[fv[3]])->attribute;
1653 for (
int i = 0; i < 4; i++)
1658 for (
int i = 0; i < 4; i++)
1663 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1668 for (
int i = 0; i < 3; i++)
1674 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1679 MFEM_ABORT(
"Unsupported element geometry.");
1691 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1714 int total = 0, ref = 0, ghost = 0;
1715 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1723 if (!ref && ghost < total)
1726 int next_row = list.
Size() ? (list.
Last().from + 1) : 0;
1727 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1735 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1752 int size = list.
Size() ? (list.
Last().from + 1) : 0;
1761 for (
int i = 0; i < deref_table.
Size(); i++)
1763 const int* fine = deref_table.
GetRow(i), size = deref_table.
RowSize(i);
1767 for (
int j = 0; j < size; j++)
1772 for (
int k = 0; k <
Dim; k++)
1774 if ((parent.
ref_type & (1 << k)) &&
1775 splits[k] >= max_nc_level)
1788 MFEM_VERIFY(
Dim < 3 ||
Iso,
1789 "derefinement of 3D anisotropic meshes not implemented yet.");
1797 for (
int i = 0; i < derefs.
Size(); i++)
1799 int row = derefs[i];
1801 "invalid derefinement number.");
1816 for (
int i = 0; i < fine_coarse.
Size(); i++)
1830 for (
int i = 0; i < nfine; i++)
1841 for (
int i = 0; i < 8 && prn.
child[i] >= 0; i++)
1848 fine_coarse[ch.
index] = parent;
1862 if (node->HasVertex()) { node->vert_index =
NVertices++; }
1889 for (
int i = 0; i < 4; i++)
1891 int ch = quad_hilbert_child_order[state][i];
1892 int st = quad_hilbert_child_state[state][i];
1898 for (
int i = 0; i < 8; i++)
1900 int ch = hex_hilbert_child_order[state][i];
1901 int st = hex_hilbert_child_state[state][i];
1907 for (
int i = 0; i < 8; i++)
1948 node_order = (
char*) quad_hilbert_child_order;
1953 node_order = (
char*) hex_hilbert_child_order;
1960 int entry_node = -2;
1963 for (
int i = 0; i < root_count; i++)
1968 if (v_in < 0) { v_in = 0; }
1971 bool shared[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1972 if (i+1 < root_count)
1975 for (
int j = 0; j < nch; j++)
1978 if (node >= 0) { shared[node] =
true; }
1983 int state =
Dim*v_in;
1984 for (
int j = 0; j <
Dim; j++)
1986 if (shared[(
int) node_order[nch*(state + j) + nch-1]])
1995 entry_node =
RetrieveNode(el, node_order[nch*state + nch-1]);
2009 MFEM_ABORT(
"invalid geometry");
2028 MFEM_VERIFY(tv.
visited ==
false,
"cyclic vertex dependencies.");
2034 for (
int i = 0; i < 3; i++)
2036 tv.
pos[i] = (pos1[i] + pos2[i]) * 0.5;
2049 for (
int i = 0; i < mesh.
vertices.Size(); i++)
2068 if (
IsGhost(nc_elem)) {
continue; }
2070 const int* node = nc_elem.
node;
2077 for (
int j = 0; j < gi.
nv; j++)
2079 elem->GetVertices()[j] =
nodes[node[j]].vert_index;
2084 for (
int k = 0; k < gi.
nf; k++)
2086 const int* fv = gi.
faces[k];
2087 const int nfv = gi.
nfv[k];
2088 const Face* face =
faces.Find(node[fv[0]], node[fv[1]],
2089 node[fv[2]], node[fv[3]]);
2097 for (
int j = 0; j < 4; j++)
2099 quad->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2106 MFEM_ASSERT(nfv == 3,
"");
2109 for (
int j = 0; j < 3; j++)
2111 tri->GetVertices()[j] =
nodes[node[fv[j]]].vert_index;
2119 for (
int j = 0; j < 2; j++)
2121 segment->GetVertices()[j] =
nodes[node[fv[2*j]]].vert_index;
2138 for (
int i = 0; i < edge_vertex->
Size(); i++)
2140 const int *ev = edge_vertex->
GetRow(i);
2143 MFEM_ASSERT(node && node->
HasEdge(),
2144 "edge (" << ev[0] <<
"," << ev[1] <<
") not found, "
2152 for (
int i = 0; i <
NFaces; i++)
2154 const int* fv = mesh->
GetFace(i)->GetVertices();
2155 const int nfv = mesh->
GetFace(i)->GetNVertices();
2168 MFEM_ASSERT(nfv == 3,
"");
2176 MFEM_ASSERT(nfv == 2,
"");
2179 face =
faces.Find(n0, n0, n1, n1);
2183 const int *ev = edge_vertex->
GetRow(i);
2184 MFEM_ASSERT((ev[0] == fv[0] && ev[1] == fv[1]) ||
2185 (ev[1] == fv[0] && ev[0] == fv[1]),
"");
2188 MFEM_VERIFY(face,
"face not found.");
2199 MFEM_ASSERT(
Dim >= 3,
"");
2208 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3, mid[3] = e4; }
2211 int midf1 = -1, midf2 = -1;
2216 if (midf1 >= 0 && midf1 == midf2)
2219 if (nd.
p1 != e1 && nd.
p2 != e1) { midf1 = -1; }
2220 if (nd.
p1 != e2 && nd.
p2 != e2) { midf2 = -1; }
2224 MFEM_ASSERT(!(midf1 >= 0 && midf2 >= 0),
"incorrectly split face!");
2226 if (midf1 < 0 && midf2 < 0)
2228 if (mid) { mid[4] = -1; }
2231 else if (midf1 >= 0)
2233 if (mid) { mid[4] = midf1; }
2238 if (mid) { mid[4] = midf2; }
2245 int e1 =
nodes.FindId(v1, v2);
2246 if (e1 < 0 || !
nodes[e1].HasVertex()) {
return false; }
2248 int e2 =
nodes.FindId(v2, v3);
2249 if (e2 < 0 || !
nodes[e2].HasVertex()) {
return false; }
2251 int e3 =
nodes.FindId(v3, v1);
2252 if (e3 < 0 || !
nodes[e3].HasVertex()) {
return false; }
2254 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3; }
2262 for (
int i = 0; i < 8; i++)
2264 if (el.
node[i] == node) {
return i; }
2266 MFEM_ABORT(
"Node not found.");
2272 for (
int i = 0; i <
GI[el.
Geom()].
nv; i++)
2276 if (abort) { MFEM_ABORT(
"Node not found."); }
2285 for (
int i = 0; i < gi.
ne; i++)
2287 const int* ev = gi.
edges[i];
2288 int n0 = el.
node[ev[0]];
2289 int n1 = el.
node[ev[1]];
2290 if ((n0 == vn0 && n1 == vn1) ||
2291 (n0 == vn1 && n1 == vn0)) {
return i; }
2294 if (abort) { MFEM_ABORT(
"Edge (" << vn0 <<
", " << vn1 <<
") not found"); }
2301 for (
int i = 0; i < gi.
nf; i++)
2303 const int* fv = gi.
faces[i];
2304 if ((a == fv[0] || a == fv[1] || a == fv[2] || a == fv[3]) &&
2305 (b == fv[0] || b == fv[1] || b == fv[2] || b == fv[3]) &&
2306 (c == fv[0] || c == fv[1] || c == fv[2] || c == fv[3]))
2311 MFEM_ABORT(
"Face not found.");
2321 MFEM_ASSERT(
sizeof(
double) ==
sizeof(std::uint64_t),
"");
2325 std::uint64_t hash = 0xf9ca9ba106acbba9;
2326 for (
int i = 0; i < pm.
np; i++)
2328 for (
int j = 0; j < pm.
points[i].
dim; j++)
2333 hash = 31*hash + *((std::uint64_t*) &coord);
2345 int GetIndex(
const NCMesh::PointMatrix &pm)
2347 int &
index = map[pm];
2348 if (!index) { index = map.size(); }
2352 void ExportMatrices(Array<DenseMatrix*> &point_matrices)
const
2354 point_matrices.SetSize(map.size());
2355 for (
const auto &pair : map)
2357 DenseMatrix* mat =
new DenseMatrix();
2358 pair.first.GetMatrix(*mat);
2359 point_matrices[pair.second - 1] = mat;
2363 void DumpBucketSizes()
const
2365 for (
unsigned i = 0; i < map.bucket_count(); i++)
2372 std::unordered_map<NCMesh::PointMatrix, int, PointMatrixHash> map;
2386 int nfv = (v3 >= 0) ? 4 : 3;
2391 reordered.
np = pm.
np;
2392 for (
int i = 0, j; i < nfv; i++)
2394 for (j = 0; j < nfv; j++)
2396 if (fv[i] == master[j])
2402 MFEM_ASSERT(j != nfv,
"node not found.");
2414 Face* fa =
faces.Find(vn0, vn1, vn2, vn3);
2426 sl.
matrix = matrix_map.GetIndex(pm_r);
2428 eface[0] = eface[2] = fa;
2429 eface[1] = eface[3] = fa;
2442 Point pmid0(pm(0), pm(1)), pmid2(pm(2), pm(3));
2446 level+1, ef[0], matrix_map);
2450 level+1, ef[1], matrix_map);
2452 eface[1] = ef[1][1];
2453 eface[3] = ef[0][3];
2454 eface[0] = eface[2] = NULL;
2456 else if (split == 2)
2458 Point pmid1(pm(1), pm(2)), pmid3(pm(3), pm(0));
2462 level+1, ef[0], matrix_map);
2466 level+1, ef[1], matrix_map);
2468 eface[0] = ef[0][0];
2469 eface[2] = ef[1][2];
2470 eface[1] = eface[3] = NULL;
2481 const int fi[3][2] = {{0, 0}, {1, 3}, {2, 0}};
2482 if (!ef[0][fi[split][0]] && !ef[1][fi[split][1]])
2492 MFEM_ASSERT(eid.
Size() > 0,
"edge prism not found");
2493 MFEM_ASSERT(eid.
Size() < 2,
"non-unique edge prism");
2503 Point mid0(pm(0), pm(1)), mid2(pm(2), pm(3));
2504 int v1 =
nodes[mid[0]].vert_index;
2505 int v2 =
nodes[mid[2]].vert_index;
2507 matrix_map.GetIndex(
2513 Point mid1(pm(1), pm(2)), mid3(pm(3), pm(0));
2514 int v1 =
nodes[mid[1]].vert_index;
2515 int v2 =
nodes[mid[3]].vert_index;
2517 matrix_map.GetIndex(
2529 int mid =
nodes.FindId(vn0, vn1);
2530 if (mid < 0) {
return; }
2546 int v0index =
nodes[vn0].vert_index;
2547 int v1index =
nodes[vn1].vert_index;
2550 matrix_map.GetIndex((v0index < v1index) ?
PointMatrix(p0, p1, p0)
2582 sl.
matrix = matrix_map.GetIndex(pm_r);
2591 Point pmid0(pm(0), pm(1)), pmid1(pm(1), pm(2)), pmid2(pm(2), pm(0));
2596 level+1, matrix_map);
2600 level+1, matrix_map);
2604 level+1, matrix_map);
2608 level+1, matrix_map);
2613 if (!b[1]) {
TraverseTetEdge(mid[0],mid[1], pmid0,pmid1, matrix_map); }
2614 if (!b[2]) {
TraverseTetEdge(mid[1],mid[2], pmid1,pmid2, matrix_map); }
2615 if (!b[0]) {
TraverseTetEdge(mid[2],mid[0], pmid2,pmid0, matrix_map); }
2625 if (
Dim < 3) {
return; }
2632 processed_faces = 0;
2641 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
2644 for (
int j = 0; j < gi.
nf; j++)
2648 for (
int k = 0; k < 4; k++)
2653 int face =
faces.FindId(node[0], node[1], node[2], node[3]);
2654 MFEM_ASSERT(face >= 0,
"face not found!");
2660 if (processed_faces[face]) {
continue; }
2661 processed_faces[face] = 1;
2666 if (fa.
elem[0] >= 0 && fa.
elem[1] >= 0)
2696 for (
int i = sb; i < se; i++)
2717 int mid =
nodes.FindId(vn0, vn1);
2718 if (mid < 0) {
return; }
2721 if (nd.
HasEdge() && level > 0)
2731 int v0index =
nodes[vn0].vert_index;
2732 int v1index =
nodes[vn1].vert_index;
2733 if (v0index > v1index) { sl.
edge_flags |= 2; }
2737 double tmid = (t0 + t1) / 2;
2738 TraverseEdge(vn0, mid, t0, tmid, flags, level+1, matrix_map);
2739 TraverseEdge(mid, vn1, tmid, t1, flags, level+1, matrix_map);
2751 processed_edges = 0;
2764 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
2767 for (
int j = 0; j < gi.
ne; j++)
2770 const int* ev = gi.
edges[j];
2771 int node[2] = { el.
node[ev[0]], el.
node[ev[1]] };
2773 int enode =
nodes.FindId(node[0], node[1]);
2774 MFEM_ASSERT(enode >= 0,
"edge node not found!");
2777 MFEM_ASSERT(nd.
HasEdge(),
"edge not found!");
2785 int face =
faces.FindId(node[0], node[0], node[1], node[1]);
2786 MFEM_ASSERT(face >= 0,
"face not found!");
2798 if (processed_edges[enode]) {
continue; }
2799 processed_edges[enode] = 1;
2802 double t0 = 0.0, t1 = 1.0;
2803 int v0index =
nodes[node[0]].vert_index;
2804 int v1index =
nodes[node[1]].vert_index;
2805 int flags = (v0index > v1index) ? 1 : 0;
2809 TraverseEdge(node[0], node[1], t0, t1, flags, 0, matrix_map);
2819 for (
int i = sb; i < se; i++)
2836 int local = edge_local[sl.
index];
2856 processed_vertices = 0;
2864 for (
int j = 0; j <
GI[el.
Geom()].
nv; j++)
2866 int node = el.
node[j];
2874 if (processed_vertices[index]) {
continue; }
2875 processed_vertices[
index] = 1;
2886 oriented_matrix = *(point_matrices[slave.
Geom()][slave.
matrix]);
2890 MFEM_ASSERT(oriented_matrix.
Height() == 1 &&
2891 oriented_matrix.
Width() == 2,
"not an edge point matrix");
2895 oriented_matrix(0,0) = 1.0 - oriented_matrix(0,0);
2896 oriented_matrix(0,1) = 1.0 - oriented_matrix(0,1);
2900 std::swap(oriented_matrix(0,0), oriented_matrix(0,1));
2907 conforming.DeleteAll();
2908 masters.DeleteAll();
2913 for (
int j = 0; j < point_matrices[i].Size(); j++)
2915 delete point_matrices[i][j];
2917 point_matrices[i].DeleteAll();
2920 inv_index.DeleteAll();
2925 return conforming.Size() + masters.Size() + slaves.Size();
2930 if (!inv_index.Size())
2933 for (
int i = 0; i < conforming.Size(); i++)
2935 max_index = std::max(conforming[i].index, max_index);
2937 for (
int i = 0; i < masters.Size(); i++)
2939 max_index = std::max(masters[i].index, max_index);
2941 for (
int i = 0; i < slaves.Size(); i++)
2943 if (slaves[i].index < 0) {
continue; }
2944 max_index = std::max(slaves[i].index, max_index);
2947 inv_index.SetSize(max_index + 1);
2950 for (
int i = 0; i < conforming.Size(); i++)
2952 inv_index[conforming[i].index] = (i << 2);
2954 for (
int i = 0; i < masters.Size(); i++)
2956 inv_index[masters[i].index] = (i << 2) + 1;
2958 for (
int i = 0; i < slaves.Size(); i++)
2960 if (slaves[i].index < 0) {
continue; }
2961 inv_index[slaves[i].index] = (i << 2) + 2;
2965 MFEM_ASSERT(index >= 0 && index < inv_index.Size(),
"");
2966 int key = inv_index[
index];
2970 MFEM_VERIFY(key >= 0,
"entity not found.");
2974 *type = (key >= 0) ? (key & 0x3) : -1;
2977 if (*type < 0) {
return invalid; }
2983 case 0:
return conforming[key >> 2];
2984 case 1:
return masters[key >> 2];
2985 case 2:
return slaves[key >> 2];
2986 default: MFEM_ABORT(
"internal error");
return conforming[0];
2995 int mid =
nodes.FindId(v0, v1);
2996 if (mid >= 0 &&
nodes[mid].HasVertex())
3010 for (
int i = 0; i < 3; i++)
3067 int** JJ =
new int*[nrows];
3077 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
3080 int* node = el.
node;
3083 for (
int j = 0; j < gi.
ne; j++)
3085 const int* ev = gi.
edges[j];
3091 for (
int j = 0; j < gi.
nf; j++)
3093 const int* fv = gi.
faces[j];
3097 node[fv[2]], node[fv[3]], indices);
3110 int size = indices.
Size();
3112 JJ[i] =
new int[size];
3113 std::memcpy(JJ[i], indices.
GetData(), size *
sizeof(int));
3118 for (
int i = 0; i < nrows; i++)
3129 for (
int i = 0; i < nrows; i++)
3131 int cnt = I[i+1] - I[i];
3132 std::memcpy(J+nnz, JJ[i], cnt *
sizeof(
int));
3159 MFEM_VERIFY(elem_set.
Size() == nleaves,
"");
3168 for (
int i = 0; i < nleaves; i++)
3174 for (
int j = 0; j < nv; j++)
3181 for (
int j = 0; j < nv; j++)
3183 vmark[el.
node[j]] = 1;
3194 neighbor_set->
SetSize(nleaves);
3198 for (
int i = 0; i < nleaves; i++)
3206 for (
int j = 0; j < nv; j++)
3208 if (vmark[v[j]]) { hit =
true;
break; }
3215 for (
int j = 0; j < nv; j++)
3217 if (vmark[el.
node[j]]) { hit =
true;
break; }
3224 if (neighbor_set) { (*neighbor_set)[i] = 1; }
3230 static bool sorted_lists_intersect(
const int*
a,
const int*
b,
int na,
int nb)
3232 if (!na || !nb) {
return false; }
3233 int a_last = a[na-1], b_last = b[nb-1];
3234 if (*b < *a) {
goto l2; }
3236 if (a_last < *b) {
return false; }
3237 while (*a < *b) { a++; }
3238 if (*a == *b) {
return true; }
3240 if (b_last < *a) {
return false; }
3241 while (*b < *a) { b++; }
3242 if (*a == *b) {
return true; }
3265 while (stack.
Size())
3274 for (
int i = 0; i < nv; i++)
3280 for (
int i = 0; i < nv; i++)
3287 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
3298 int nv1 = vert.
Size();
3303 for (
int i = 0; i < search_set->
Size(); i++)
3305 int testme = (*search_set)[i];
3312 bool hit = sorted_lists_intersect(v1, v2, nv1, nv2);
3317 for (
int j = 0; j < nv; j++)
3319 hit = sorted_lists_intersect(&el.
node[j], v1, 1, nv1);
3324 if (hit) { neighbors.
Append(testme); }
3338 for (
int i = 0; i < elems.
Size(); i++)
3344 for (
int j = 0; j < nv; j++)
3350 for (
int j = 0; j < nv; j++)
3352 vmark[el.
node[j]] = 1;
3362 for (
int i = 0; i < search_set->
Size(); i++)
3364 int testme = (*search_set)[i];
3370 for (
int j = 0; j < nv; j++)
3372 if (vmark[v[j]]) { hit =
true;
break; }
3378 for (
int j = 0; j < nv; j++)
3380 if (vmark[el.
node[j]]) { hit =
true;
break; }
3384 if (hit) { expanded.
Append(testme); }
3390 for (
int i = 0; i < 3; i++)
3392 dst[i] = (src[i]*s[i] >> 1) + t[i];
3401 if (el.
parent < 0) {
return elem; }
3404 MFEM_ASSERT(pa.
ref_type,
"internal error");
3407 while (ch < 8 && pa.
child[ch] != elem) { ch++; }
3408 MFEM_ASSERT(ch < 8,
"internal error");
3410 MFEM_ASSERT(geom_parent[el.
Geom()],
"unsupported geometry");
3412 tr.
Apply(coord, coord);
3423 return (pt[0] >= 0) && (pt[0] <=
T_ONE) &&
3424 (pt[1] >= 0) && (pt[1] <=
T_ONE);
3427 return (pt[0] >= 0) && (pt[0] <=
T_ONE) &&
3428 (pt[1] >= 0) && (pt[1] <=
T_ONE) &&
3429 (pt[2] >= 0) && (pt[2] <=
T_ONE);
3432 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <=
T_ONE);
3435 return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <=
T_ONE) &&
3436 (pt[2] >= 0) && (pt[2] <=
T_ONE);
3439 MFEM_ABORT(
"unsupported geometry");
3455 for (
int ch = 0; ch < 8 && el.
child[ch] >= 0; ch++)
3458 tr.
Apply(coord, tcoord);
3460 if (RefPointInside(el.
Geom(), tcoord))
3472 MFEM_ASSERT(geom_corners[el.
Geom()],
"unsupported geometry");
3473 std::memcpy(coord, geom_corners[el.
Geom()][local],
sizeof(coord));
3486 MFEM_ASSERT(np == pm.
np,
"");
3487 for (
int i = 0; i < np; i++)
3490 for (
int j = 0; j < points[i].dim; j++)
3492 if (points[i].coord[j] != pm.
points[i].
coord[j]) {
return false; }
3501 for (
int i = 0; i < np; i++)
3503 for (
int j = 0; j < points[0].dim; j++)
3505 point_matrix(j, i) = points[i].coord[j];
3517 Point(0, 0, 0),
Point(1, 0, 0),
Point(0, 1, 0),
Point(0, 0, 1)
3524 Point(0, 0, 0),
Point(1, 0, 0),
Point(1, 1, 0),
Point(0, 1, 0),
3525 Point(0, 0, 1),
Point(1, 0, 1),
Point(1, 1, 1),
Point(0, 1, 1)
3538 MFEM_ABORT(
"unsupported geometry " << geom);
3550 int ref_type = *ref_path++;
3551 int child = *ref_path++;
3559 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3560 Point mid67(pm(6), pm(7)), mid45(pm(4), pm(5));
3565 pm(4), mid45, mid67, pm(7));
3567 else if (child == 1)
3570 mid45, pm(5), pm(6), mid67);
3573 else if (ref_type == 2)
3575 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3576 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
3581 pm(4), pm(5), mid56, mid74);
3583 else if (child == 1)
3586 mid74, mid56, pm(6), pm(7));
3589 else if (ref_type == 4)
3591 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3592 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3597 mid04, mid15, mid26, mid37);
3599 else if (child == 1)
3602 pm(4), pm(5), pm(6), pm(7));
3605 else if (ref_type == 3)
3607 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3608 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
3609 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
3610 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
3612 Point midf0(mid23, mid12, mid01, mid30);
3613 Point midf5(mid45, mid56, mid67, mid74);
3618 pm(4), mid45, midf5, mid74);
3620 else if (child == 1)
3623 mid45, pm(5), mid56, midf5);
3625 else if (child == 2)
3628 midf5, mid56, pm(6), mid67);
3630 else if (child == 3)
3633 mid74, midf5, mid67, pm(7));
3636 else if (ref_type == 5)
3638 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3639 Point mid45(pm(4), pm(5)), mid67(pm(6), pm(7));
3640 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3641 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3643 Point midf1(mid01, mid15, mid45, mid04);
3644 Point midf3(mid23, mid37, mid67, mid26);
3649 mid04, midf1, midf3, mid37);
3651 else if (child == 1)
3654 midf1, mid15, mid26, midf3);
3656 else if (child == 2)
3659 mid45, pm(5), pm(6), mid67);
3661 else if (child == 3)
3664 pm(4), mid45, mid67, pm(7));
3667 else if (ref_type == 6)
3669 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3670 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
3671 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3672 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3674 Point midf2(mid12, mid26, mid56, mid15);
3675 Point midf4(mid30, mid04, mid74, mid37);
3680 mid04, mid15, midf2, midf4);
3682 else if (child == 1)
3685 midf4, midf2, mid26, mid37);
3687 else if (child == 2)
3690 pm(4), pm(5), mid56, mid74);
3692 else if (child == 3)
3695 mid74, mid56, pm(6), pm(7));
3698 else if (ref_type == 7)
3700 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3701 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
3702 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
3703 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
3704 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
3705 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
3707 Point midf0(mid23, mid12, mid01, mid30);
3708 Point midf1(mid01, mid15, mid45, mid04);
3709 Point midf2(mid12, mid26, mid56, mid15);
3710 Point midf3(mid23, mid37, mid67, mid26);
3711 Point midf4(mid30, mid04, mid74, mid37);
3712 Point midf5(mid45, mid56, mid67, mid74);
3714 Point midel(midf1, midf3);
3719 mid04, midf1, midel, midf4);
3721 else if (child == 1)
3724 midf1, mid15, midf2, midel);
3726 else if (child == 2)
3729 midel, midf2, mid26, midf3);
3731 else if (child == 3)
3734 midf4, midel, midf3, mid37);
3736 else if (child == 4)
3739 pm(4), mid45, midf5, mid74);
3741 else if (child == 5)
3744 mid45, pm(5), mid56, midf5);
3746 else if (child == 6)
3749 midf5, mid56, pm(6), mid67);
3751 else if (child == 7)
3754 mid74, midf5, mid67, pm(7));
3762 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3763 Point mid20(pm(2), pm(0)), mid34(pm(3), pm(4));
3764 Point mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
3768 pm =
PointMatrix(pm(0), mid01, mid20, pm(3), mid34, mid53);
3770 else if (child == 1)
3772 pm =
PointMatrix(mid01, pm(1), mid12, mid34, pm(4), mid45);
3774 else if (child == 2)
3776 pm =
PointMatrix(mid20, mid12, pm(2), mid53, mid45, pm(5));
3778 else if (child == 3)
3780 pm =
PointMatrix(mid12, mid20, mid01, mid45, mid53, mid34);
3783 else if (ref_type == 4)
3785 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
3789 pm =
PointMatrix(pm(0), pm(1), pm(2), mid03, mid14, mid25);
3791 else if (child == 1)
3793 pm =
PointMatrix(mid03, mid14, mid25, pm(3), pm(4), pm(5));
3796 else if (ref_type > 4)
3798 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
3799 Point mid34(pm(3), pm(4)), mid45(pm(4), pm(5)), mid53(pm(5), pm(3));
3800 Point mid03(pm(0), pm(3)), mid14(pm(1), pm(4)), mid25(pm(2), pm(5));
3802 Point midf2(mid01, mid14, mid34, mid03);
3803 Point midf3(mid12, mid25, mid45, mid14);
3804 Point midf4(mid20, mid03, mid53, mid25);
3808 pm =
PointMatrix(pm(0), mid01, mid20, mid03, midf2, midf4);
3810 else if (child == 1)
3812 pm =
PointMatrix(mid01, pm(1), mid12, midf2, mid14, midf3);
3814 else if (child == 2)
3816 pm =
PointMatrix(mid20, mid12, pm(2), midf4, midf3, mid25);
3818 else if (child == 3)
3820 pm =
PointMatrix(mid12, mid20, mid01, midf3, midf4, midf2);
3822 else if (child == 4)
3824 pm =
PointMatrix(mid03, midf2, midf4, pm(3), mid34, mid53);
3826 else if (child == 5)
3828 pm =
PointMatrix(midf2, mid14, midf3, mid34, pm(4), mid45);
3830 else if (child == 6)
3832 pm =
PointMatrix(midf4, midf3, mid25, mid53, mid45, pm(5));
3834 else if (child == 7)
3836 pm =
PointMatrix(midf3, midf4, midf2, mid45, mid53, mid34);
3842 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid02(pm(2), pm(0));
3843 Point mid03(pm(0), pm(3)), mid13(pm(1), pm(3)), mid23(pm(2), pm(3));
3849 else if (child == 1)
3853 else if (child == 2)
3857 else if (child == 3)
3861 else if (child == 4)
3865 else if (child == 5)
3869 else if (child == 6)
3873 else if (child == 7)
3882 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
3888 else if (child == 1)
3893 else if (ref_type == 2)
3895 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
3901 else if (child == 1)
3906 else if (ref_type == 3)
3908 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
3909 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
3910 Point midel(mid01, mid23);
3916 else if (child == 1)
3920 else if (child == 2)
3924 else if (child == 3)
3932 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
3938 else if (child == 1)
3942 else if (child == 2)
3946 else if (child == 3)
3954 for (
int i = 0; i < pm.
np; i++)
3956 for (
int j = 0; j < pm(i).dim; j++)
3958 matrix(j, i) = pm(i).coord[j];
3983 int &matrix = map[ref_path];
3984 if (!matrix) { matrix = map.size(); }
3987 emb.
parent = coarse_index;
3992 MFEM_ASSERT(el.
tet_type == 0,
"not implemented");
3995 ref_path.push_back(0);
3997 for (
int i = 0; i < 8; i++)
3999 if (el.
child[i] >= 0)
4001 ref_path[ref_path.length()-1] = i;
4005 ref_path.resize(ref_path.length()-2);
4012 "GetRefinementTransforms() must be preceded by MarkCoarseLevel()"
4020 std::string ref_path;
4021 ref_path.reserve(100);
4026 path_map[g][ref_path] = 1;
4034 used_geoms |= (1 <<
geom);
4039 if (used_geoms & (1 << g))
4048 RefPathMap::iterator it;
4049 for (it = path_map[g].begin(); it != path_map[g].end(); ++it)
4063 "GetDerefinementTransforms() must be preceded by Derefine().");
4079 int geom = code & 0xf;
4080 int ref_type_child = code >> 4;
4082 int &matrix = mat_no[
geom][ref_type_child];
4083 if (!matrix) { matrix = mat_no[
geom].size(); }
4090 if (
Geoms & (1 << g))
4099 for (
auto it = mat_no[geom].begin(); it != mat_no[
geom].end(); ++it)
4101 char path[3] = { 0, 0, 0 };
4103 int code = it->first;
4106 path[0] = code >> 4;
4107 path[1] = code & 0xf;
4130 : geom(g), num_children(n), children(c) { }
4132 bool operator<(
const RefType &other)
const
4134 if (geom < other.geom) {
return true; }
4135 if (geom > other.geom) {
return false; }
4136 if (num_children < other.num_children) {
return true; }
4137 if (num_children > other.num_children) {
return false; }
4138 for (
int i = 0; i < num_children; i++)
4140 if (children[i].one < other.children[i].one) {
return true; }
4141 if (children[i].one > other.children[i].one) {
return false; }
4154 const int fine_ne = embeddings.Size();
4156 for (
int i = 0; i < fine_ne; i++)
4158 coarse_ne = std::max(coarse_ne, embeddings[i].parent);
4162 coarse_to_ref_type.
SetSize(coarse_ne);
4163 coarse_to_fine.
SetDims(coarse_ne, fine_ne);
4168 for (
int i = 0; i < fine_ne; i++)
4170 cf_i[embeddings[i].parent+1]++;
4173 MFEM_ASSERT(cf_i.Last() == cf_j.
Size(),
"internal error");
4174 for (
int i = 0; i < fine_ne; i++)
4178 cf_j[cf_i[e.
parent]].two = i;
4181 std::copy_backward(cf_i.begin(), cf_i.end()-1, cf_i.end());
4183 for (
int i = 0; i < coarse_ne; i++)
4185 std::sort(&cf_j[cf_i[i]], cf_j.
GetData() + cf_i[i+1]);
4187 for (
int i = 0; i < fine_ne; i++)
4189 coarse_to_fine.
GetJ()[i] = cf_j[i].two;
4192 using internal::RefType;
4196 map<RefType,int> ref_type_map;
4197 for (
int i = 0; i < coarse_ne; i++)
4199 const int num_children = cf_i[i+1]-cf_i[i];
4200 MFEM_ASSERT(num_children > 0,
"");
4201 const int fine_el = cf_j[cf_i[i]].two;
4204 const RefType ref_type(geom, num_children, &cf_j[cf_i[i]]);
4205 pair<map<RefType,int>::iterator,
bool> res =
4206 ref_type_map.insert(
4207 pair<const RefType,int>(ref_type, (
int)ref_type_map.size()));
4208 coarse_to_ref_type[i] = res.first->second;
4211 ref_type_to_matrix.
MakeI((
int)ref_type_map.size());
4212 ref_type_to_geom.
SetSize((
int)ref_type_map.size());
4213 for (map<RefType,int>::iterator it = ref_type_map.begin();
4214 it != ref_type_map.end(); ++it)
4216 ref_type_to_matrix.
AddColumnsInRow(it->second, it->first.num_children);
4217 ref_type_to_geom[it->second] = it->first.geom;
4220 ref_type_to_matrix.
MakeJ();
4221 for (map<RefType,int>::iterator it = ref_type_map.begin();
4222 it != ref_type_map.end(); ++it)
4224 const RefType &rt = it->first;
4225 for (
int j = 0; j < rt.num_children; j++)
4227 ref_type_to_matrix.
AddConnection(it->second, rt.children[j].one);
4243 point_matrices[i].SetSize(0, 0, 0);
4245 embeddings.DeleteAll();
4253 if (point_matrices[i].SizeK()) {
return true; }
4261 static int sgn(
int x)
4263 return (x < 0) ? -1 : (x > 0) ? 1 : 0;
4266 static void HilbertSfc2D(
int x,
int y,
int ax,
int ay,
int bx,
int by,
4269 int w = std::abs(ax + ay);
4270 int h = std::abs(bx + by);
4272 int dax = sgn(ax), day = sgn(ay);
4273 int dbx = sgn(bx), dby = sgn(by);
4277 for (
int i = 0; i < w; i++, x += dax, y += day)
4286 for (
int i = 0; i < h; i++, x += dbx, y += dby)
4294 int ax2 = ax/2, ay2 = ay/2;
4295 int bx2 = bx/2, by2 = by/2;
4297 int w2 = std::abs(ax2 + ay2);
4298 int h2 = std::abs(bx2 + by2);
4302 if ((w2 & 0x1) && (w > 2))
4304 ax2 += dax, ay2 += day;
4307 HilbertSfc2D(x, y, ax2, ay2, bx, by, coords);
4308 HilbertSfc2D(x+ax2, y+ay2, ax-ax2, ay-ay2, bx, by, coords);
4312 if ((h2 & 0x1) && (h > 2))
4314 bx2 += dbx, by2 += dby;
4317 HilbertSfc2D(x, y, bx2, by2, ax2, ay2, coords);
4318 HilbertSfc2D(x+bx2, y+by2, ax, ay, bx-bx2, by-by2, coords);
4319 HilbertSfc2D(x+(ax-dax)+(bx2-dbx), y+(ay-day)+(by2-dby),
4320 -bx2, -by2, -(ax-ax2), -(ay-ay2), coords);
4324 static void HilbertSfc3D(
int x,
int y,
int z,
4325 int ax,
int ay,
int az,
4326 int bx,
int by,
int bz,
4327 int cx,
int cy,
int cz,
4330 int w = std::abs(ax + ay + az);
4331 int h = std::abs(bx + by + bz);
4332 int d = std::abs(cx + cy + cz);
4334 int dax = sgn(ax), day = sgn(ay), daz = sgn(az);
4335 int dbx = sgn(bx), dby = sgn(by), dbz = sgn(bz);
4336 int dcx = sgn(cx), dcy = sgn(cy), dcz = sgn(cz);
4339 if (h == 1 && d == 1)
4341 for (
int i = 0; i < w; i++, x += dax, y += day, z += daz)
4349 if (w == 1 && d == 1)
4351 for (
int i = 0; i < h; i++, x += dbx, y += dby, z += dbz)
4359 if (w == 1 && h == 1)
4361 for (
int i = 0; i < d; i++, x += dcx, y += dcy, z += dcz)
4370 int ax2 = ax/2, ay2 = ay/2, az2 = az/2;
4371 int bx2 = bx/2, by2 = by/2, bz2 = bz/2;
4372 int cx2 = cx/2, cy2 = cy/2, cz2 = cz/2;
4374 int w2 = std::abs(ax2 + ay2 + az2);
4375 int h2 = std::abs(bx2 + by2 + bz2);
4376 int d2 = std::abs(cx2 + cy2 + cz2);
4379 if ((w2 & 0x1) && (w > 2))
4381 ax2 += dax, ay2 += day, az2 += daz;
4383 if ((h2 & 0x1) && (h > 2))
4385 bx2 += dbx, by2 += dby, bz2 += dbz;
4387 if ((d2 & 0x1) && (d > 2))
4389 cx2 += dcx, cy2 += dcy, cz2 += dcz;
4393 if ((2*w > 3*h) && (2*w > 3*d))
4395 HilbertSfc3D(x, y, z,
4398 cx, cy, cz, coords);
4400 HilbertSfc3D(x+ax2, y+ay2, z+az2,
4401 ax-ax2, ay-ay2, az-az2,
4403 cx, cy, cz, coords);
4408 HilbertSfc3D(x, y, z,
4411 ax2, ay2, az2, coords);
4413 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4415 bx-bx2, by-by2, bz-bz2,
4416 cx, cy, cz, coords);
4418 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4419 y+(ay-day)+(by2-dby),
4420 z+(az-daz)+(bz2-dbz),
4423 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4428 HilbertSfc3D(x, y, z,
4431 bx, by, bz, coords);
4433 HilbertSfc3D(x+cx2, y+cy2, z+cz2,
4436 cx-cx2, cy-cy2, cz-cz2, coords);
4438 HilbertSfc3D(x+(ax-dax)+(cx2-dcx),
4439 y+(ay-day)+(cy2-dcy),
4440 z+(az-daz)+(cz2-dcz),
4442 -(ax-ax2), -(ay-ay2), -(az-az2),
4443 bx, by, bz, coords);
4448 HilbertSfc3D(x, y, z,
4451 ax2, ay2, az2, coords);
4453 HilbertSfc3D(x+bx2, y+by2, z+bz2,
4456 bx-bx2, by-by2, bz-bz2, coords);
4458 HilbertSfc3D(x+(bx2-dbx)+(cx-dcx),
4459 y+(by2-dby)+(cy-dcy),
4460 z+(bz2-dbz)+(cz-dcz),
4463 -(cx-cx2), -(cy-cy2), -(cz-cz2), coords);
4465 HilbertSfc3D(x+(ax-dax)+bx2+(cx-dcx),
4466 y+(ay-day)+by2+(cy-dcy),
4467 z+(az-daz)+bz2+(cz-dcz),
4469 -(ax-ax2), -(ay-ay2), -(az-az2),
4470 bx-bx2, by-by2, bz-bz2, coords);
4472 HilbertSfc3D(x+(ax-dax)+(bx2-dbx),
4473 y+(ay-day)+(by2-dby),
4474 z+(az-daz)+(bz2-dbz),
4477 -(ax-ax2), -(ay-ay2), -(az-az2), coords);
4484 coords.
Reserve(2*width*height);
4486 if (width >= height)
4488 HilbertSfc2D(0, 0, width, 0, 0, height, coords);
4492 HilbertSfc2D(0, 0, 0, height, width, 0, coords);
4500 coords.
Reserve(3*width*height*depth);
4502 if (width >= height && width >= depth)
4504 HilbertSfc3D(0, 0, 0,
4507 0, 0, depth, coords);
4509 else if (height >= width && height >= depth)
4511 HilbertSfc3D(0, 0, 0,
4514 0, 0, depth, coords);
4518 HilbertSfc3D(0, 0, 0,
4521 0, height, 0, coords);
4529 bool oriented)
const
4533 const int* ev = gi.
edges[(int) edge_id.
local];
4535 int n0 = el.
node[ev[0]], n1 = el.
node[ev[1]];
4536 if (n0 > n1) { std::swap(n0, n1); }
4538 vert_index[0] =
nodes[n0].vert_index;
4539 vert_index[1] =
nodes[n1].vert_index;
4541 if (oriented && vert_index[0] > vert_index[1])
4543 std::swap(vert_index[0], vert_index[1]);
4551 const int* ev = gi.
edges[(int) edge_id.
local];
4553 int v0 =
nodes[el.
node[ev[0]]].vert_index;
4554 int v1 =
nodes[el.
node[ev[1]]].vert_index;
4556 return ((v0 < v1 && ev[0] > ev[1]) || (v0 > v1 && ev[0] < ev[1])) ? -1 : 1;
4560 int vert_index[4],
int edge_index[4],
4561 int edge_orientation[4])
const
4563 MFEM_ASSERT(
Dim >= 3,
"");
4568 const int *fv = gi.
faces[(int) face_id.
local];
4569 const int nfv = gi.
nfv[(
int) face_id.
local];
4571 vert_index[3] = edge_index[3] = -1;
4572 edge_orientation[3] = 0;
4574 for (
int i = 0; i < nfv; i++)
4576 vert_index[i] =
nodes[el.
node[fv[i]]].vert_index;
4579 for (
int i = 0; i < nfv; i++)
4582 if (j >= nfv) { j = 0; }
4584 int n1 = el.
node[fv[i]];
4585 int n2 = el.
node[fv[j]];
4588 MFEM_ASSERT(en != NULL,
"edge not found.");
4591 edge_orientation[i] = (vert_index[i] < vert_index[j]) ? 1 : -1;
4599 MFEM_ASSERT(node >= 0,
"edge node not found.");
4602 int p1 = nd.
p1, p2 = nd.
p2;
4603 MFEM_ASSERT(p1 != p2,
"invalid edge node.");
4607 int n1p1 = n1.
p1, n1p2 = n1.
p2;
4608 int n2p1 = n2.p1, n2p2 = n2.p2;
4610 if ((n2p1 != n2p2) && (p1 == n2p1 || p1 == n2p2))
4614 if (n2.HasEdge()) {
return p2; }
4618 if ((n1p1 != n1p2) && (p2 == n1p1 || p2 == n1p2))
4622 if (n1.
HasEdge()) {
return p1; }
4632 MFEM_ASSERT(node >= 0 &&
nodes[node].HasEdge(),
"(v1, v2) is not an edge.");
4635 return (master >= 0) ?
nodes[master].edge_index : -1;
4641 int depth = 0, parent;
4642 while ((parent =
elements[elem].parent) != -1)
4653 int parent, reduction = 1;
4654 while ((parent =
elements[elem].parent) != -1)
4656 if (
elements[parent].ref_type & 1) { reduction *= 2; }
4657 if (
elements[parent].ref_type & 2) { reduction *= 2; }
4658 if (
elements[parent].ref_type & 4) { reduction *= 2; }
4674 for (
int i = 0; i < gi.
nf; i++)
4676 const int* fv = gi.
faces[i];
4679 MFEM_ASSERT(face,
"face not found");
4680 faces[i] = face->
index;
4692 int elem = fa.
elem[0];
4693 if (elem < 0) { elem = fa.
elem[1]; }
4694 MFEM_ASSERT(elem >= 0,
"Face has no elements?");
4703 for (
int i = 0; i < 4; i++)
4705 node[i] = el.
node[fv[i]];
4722 if (bdr_attr_is_ess[
faces[face].attribute - 1])
4726 int nfv = (node[3] < 0) ? 3 : 4;
4728 for (
int j = 0; j < nfv; j++)
4732 int enode =
nodes.FindId(node[j], node[(j+1) % nfv]);
4733 MFEM_ASSERT(enode >= 0 &&
nodes[enode].HasEdge(),
"Edge not found.");
4762 bdr_vertices.
Sort();
4769 static int max4(
int a,
int b,
int c,
int d)
4771 return std::max(std::max(a, b), std::max(c, d));
4773 static int max6(
int a,
int b,
int c,
int d,
int e,
int f)
4775 return std::max(max4(a, b, c, d), std::max(e, f));
4777 static int max8(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h)
4779 return std::max(max4(a, b, c, d), max4(e, f, g, h));
4784 int mid =
nodes.FindId(vn1, vn2);
4785 if (mid < 0 || !
nodes[mid].HasVertex()) {
return 0; }
4793 faces.FindId(vn1, vn2, vn3) < 0)
4807 int& h_level,
int& v_level)
const
4809 int hl1, hl2, vl1, vl2;
4815 h_level = v_level = 0;
4821 h_level = std::max(hl1, hl2);
4822 v_level = std::max(vl1, vl2) + 1;
4828 h_level = std::max(hl1, hl2) + 1;
4829 v_level = std::max(vl1, vl2);
4836 const int* node = el.
node;
4840 for (
int i = 0; i < gi.
ne; i++)
4842 const int* ev = gi.
edges[i];
4849 for (
int i = 0; i < gi.
nf; i++)
4851 const int* fv = gi.
faces[i];
4855 node[fv[2]], node[fv[3]],
4856 flevel[i][1], flevel[i][0]);
4869 splits[0] = max8(flevel[0][0], flevel[1][0], flevel[3][0], flevel[5][0],
4870 elevel[0], elevel[2], elevel[4], elevel[6]);
4872 splits[1] = max8(flevel[0][1], flevel[2][0], flevel[4][0], flevel[5][1],
4873 elevel[1], elevel[3], elevel[5], elevel[7]);
4875 splits[2] = max8(flevel[1][1], flevel[2][1], flevel[3][1], flevel[4][1],
4876 elevel[8], elevel[9], elevel[10], elevel[11]);
4880 splits[0] = splits[1] =
4882 max6(flevel[0][0], flevel[1][0], 0,
4883 flevel[2][0], flevel[3][0], flevel[4][0]),
4884 max6(elevel[0], elevel[1], elevel[2],
4885 elevel[3], elevel[4], elevel[5]));
4887 splits[2] = max6(flevel[2][1], flevel[3][1], flevel[4][1],
4888 elevel[6], elevel[7], elevel[8]);
4892 splits[0] = std::max(
4893 max4(flevel[0][0], flevel[1][0], flevel[2][0], flevel[3][0]),
4894 max6(elevel[0], elevel[1], elevel[2],
4895 elevel[3], elevel[4], elevel[5]));
4897 splits[1] = splits[0];
4898 splits[2] = splits[0];
4902 splits[0] = std::max(elevel[0], elevel[2]);
4903 splits[1] = std::max(elevel[1], elevel[3]);
4907 splits[0] = std::max(elevel[0], std::max(elevel[1], elevel[2]));
4908 splits[1] = splits[0];
4912 MFEM_ABORT(
"Unsupported element geometry.");
4926 for (
int k = 0; k <
Dim; k++)
4928 if (splits[k] > max_level)
4930 ref_type |= (1 << k);
4948 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
4955 if (!refinements.
Size()) {
break; }
4967 if (node->HasVertex() && node->p1 != node->p2) { nv++; }
4974 if (node->HasVertex() && node->p1 != node->p2)
4982 out << node->vert_index <<
" "
4995 input >>
id >> p1 >> p2;
4996 MFEM_VERIFY(input,
"problem reading vertex parents.");
4998 MFEM_VERIFY(
nodes.IdExists(
id),
"vertex " <<
id <<
" not found.");
4999 MFEM_VERIFY(
nodes.IdExists(p1),
"parent " << p1 <<
" not found.");
5000 MFEM_VERIFY(
nodes.IdExists(p2),
"parent " << p2 <<
" not found.");
5003 nodes.Reparent(
id, p1, p2);
5012 int num_top_level = 0;
5015 if (node->p1 == node->p2)
5017 MFEM_VERIFY(node.index() == node->p1,
"invalid top-level vertex.");
5018 MFEM_VERIFY(node->HasVertex(),
"top-level vertex not found.");
5019 MFEM_VERIFY(node->vert_index == node->p1,
"bad top-level vertex index");
5020 num_top_level = std::max(num_top_level, node->p1 + 1);
5025 for (
int i = 0; i < num_top_level; i++)
5027 std::memcpy(&
top_vertex_pos[3*i], mvertices[i](), 3*
sizeof(
double));
5036 int child_id[8], nch = 0;
5037 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
5041 MFEM_ASSERT(nch == ref_type_num_children[(
int) el.
ref_type],
"");
5044 for (
int i = 0; i < nch; i++)
5046 out <<
" " << child_id[i];
5078 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
5080 int old_id = el.
child[i];
5082 int new_id =
elements.Append(tmp_elements[old_id]);
5083 index_map[old_id] = new_id;
5084 el.
child[i] = new_id;
5108 if (
Dim == 3 && ref_type != 7) { iso =
false; }
5111 int nch = ref_type_num_children[ref_type];
5112 for (
int i = 0,
id; i < nch; i++)
5115 MFEM_VERIFY(
id >= 0,
"");
5118 "coarse element cannot be referenced before it is "
5119 "defined (id=" <<
id <<
").");
5122 MFEM_VERIFY(child.parent == -1,
5123 "element " <<
id <<
" cannot have two parents.");
5126 child.parent = elem;
5130 el.
geom = child.geom;
5148 if (el->parent == -1)
5151 index_map[el.index()] = new_id;
5157 for (
int i = 0; i < root_count; i++)
5165 for (
int i = 0; i < 2; i++)
5167 if (face->elem[i] >= 0)
5169 face->elem[i] = index_map[face->elem[i]];
5170 MFEM_ASSERT(face->elem[i] >= 0,
"");
5201 for (
int j = 0; j < point_matrices[i].Size(); i++)
5203 pm_size += point_matrices[i][j]->MemoryUsage();
5205 pm_size += point_matrices[i].MemoryUsage();
5208 return conforming.MemoryUsage() +
5209 masters.MemoryUsage() +
5210 slaves.MemoryUsage() +
5216 long mem = embeddings.MemoryUsage();
5219 mem += point_matrices[i].MemoryUsage();
5226 return nodes.MemoryUsage() +
5227 faces.MemoryUsage() +
5262 <<
ref_stack.MemoryUsage() <<
" ref_stack\n"
5266 <<
sizeof(*this) <<
" NCMesh"
5274 static const double MiB = 1024.*1024.;
5276 "NCMesh statistics:\n"
5277 "------------------\n"
5278 " mesh and space dimensions : " <<
Dim <<
", " <<
spaceDim <<
"\n"
5279 " isotropic only : " << (
Iso ?
"yes" :
"no") <<
"\n"
5280 " number of Nodes : " << std::setw(9)
5281 <<
nodes.Size() <<
" + [ " << std::setw(9)
5282 <<
nodes.MemoryUsage()/MiB <<
" MiB ]\n"
5283 " free " << std::setw(9)
5284 <<
nodes.NumFreeIds() <<
"\n"
5285 " number of Faces : " << std::setw(9)
5286 <<
faces.Size() <<
" + [ " << std::setw(9)
5287 <<
faces.MemoryUsage()/MiB <<
" MiB ]\n"
5288 " free " << std::setw(9)
5289 <<
faces.NumFreeIds() <<
"\n"
5290 " number of Elements : " << std::setw(9)
5294 " free " << std::setw(9)
5296 " number of root elements : " << std::setw(9)
5298 " number of leaf elements : " << std::setw(9)
5300 " number of vertices : " << std::setw(9)
5302 " number of faces : " << std::setw(9)
5305 " conforming " << std::setw(9)
5307 " master " << std::setw(9)
5309 " slave " << std::setw(9)
5311 " number of edges : " << std::setw(9)
5314 " conforming " << std::setw(9)
5316 " master " << std::setw(9)
5318 " slave " << std::setw(9)
5320 " total memory : " << std::setw(17)
5321 <<
"[ " << std::setw(9) <<
MemoryUsage()/MiB <<
" MiB ]\n"
5332 for (
int j = 0; j <
Dim; j++)
5336 for (
int k = 0; k < 8; k++)
5338 if (elem->
node[k] >= 0)
5344 out << sum / count <<
" ";
5355 out <<
nodes.Size() <<
"\n";
5359 out << node.index() <<
" "
5360 << pos[0] <<
" " << pos[1] <<
" " << pos[2] <<
" "
5361 << node->p1 <<
" " << node->p2 <<
" "
5362 << node->vert_index <<
" " << node->edge_index <<
" "
5370 for (
int i = 0; i <
elements.Size(); i++)
5375 out << nleaves <<
"\n";
5376 for (
int i = 0; i <
elements.Size(); i++)
5381 out << gi.
nv <<
" ";
5382 for (
int j = 0; j < gi.
nv; j++)
5384 out << el.
node[j] <<
" ";
5391 out <<
faces.Size() <<
"\n";
5394 int elem = face->elem[0];
5395 if (elem < 0) { elem = face->elem[1]; }
5396 MFEM_ASSERT(elem >= 0,
"");
5408 for (
int i = 0; i < nfv; i++)
5410 out <<
" " << el.
node[fv[i]];
NCList face_list
lazy-initialized list of faces, see GetFaceList
void CollectLeafElements(int elem, int state)
bool CubeFaceTop(int node, int *n)
NCList edge_list
lazy-initialized list of edges, see GetEdgeList
NCMesh(const Mesh *mesh, std::istream *vertex_parents=NULL)
Geometry::Type GetGeometryType() const
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)
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
Array< double > top_vertex_pos
coordinates of top-level vertices (organized as triples)
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)
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.
void PrintVertexParents(std::ostream &out) const
I/O: Print the "vertex_parents" section of the mesh file (ver. >= 1.1).
Array< Element * > boundary
void CollectTriFaceVertices(int v0, int v1, int v2, Array< int > &indices)
char tet_type
tetrahedron split type, currently always 0
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 CopyElements(int elem, const BlockArray< Element > &tmp_elements, Array< int > &index_map)
void ForceRefinement(int vn1, int vn2, int vn3, int vn4)
virtual int GetNumGhostElements() const
int Size() const
Return the number of items actually stored.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
void SetDims(int rows, int nnz)
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 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 InitRootState(int root_count)
int GetEdgeNCOrientation(const MeshId &edge_id) const
void SetSize(int i, int j, int k)
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)
virtual int GetNumGhostVertices() const
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)
Geometry::Type GetElementBaseGeometry(int i) const
int spaceDim
dimensions of the elements and the vertex coordinates
Array< int > vertex_nodeId
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)
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
virtual 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)
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).
virtual bool IsGhost(const Element &el) const
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)
virtual const int * GetEdgeVertices(int) const =0
int GetMidEdgeNode(int node1, int node2)
Element(Geometry::Type geom, int attr)
int PrintElements(std::ostream &out, int elem, int &coarse_id) const
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.
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)
Array< int > coarse_elements
state of leaf_elements before Refine(), set by MarkCoarseLevel()
virtual 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)
I/O: Load the element refinement hierarchy from a 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
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 Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
virtual void ElementSharesVertex(int elem, int local, int vnode)
int Size() const
Returns the number of TYPE I elements.
bool CubeFaceFront(int node, int *n)
A class for non-conforming AMR on higher-order hexahedral, prismatic, quadrilateral or triangular mes...
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.
NCMesh::RefCoord RefCoord
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
Used during initialization only.
void DeleteUnusedFaces(const Array< int > &elemFaces)
int SpaceDimension() const
bool Iso
true if the mesh only contains isotropic refinements
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'.
void SetVertexPositions(const Array< mfem::Vertex > &vertices)
I/O: Set positions of all vertices (used by mesh loader).
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
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 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 Apply(const RefCoord src[3], RefCoord dst[3]) const
void ForgetElement(int e)
static PointMatrix pm_tet_identity
int GetMidFaceNode(int en1, int en2, int en3, int en4)
void RefineElement(int elem, char ref_type)
int NewHexahedron(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, int attr, int fattr0, int fattr1, int fattr2, int fattr3, int fattr4, int fattr5)
void TraverseTetEdge(int vn0, int vn1, const Point &p0, const Point &p1, MatrixMap &matrix_map)
Array< int > boundary_faces
subset of all faces, set by BuildFaceList
int child[8]
2-8 children (if ref_type != 0)
Array< int > leaf_elements
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 Initialize(const mfem::Element *elem)
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.
virtual void AssignLeafIndices()
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'.
long MemoryUsage() const
Return total number of bytes allocated.
void PrintCoarseElements(std::ostream &out) const
I/O: Print the "coarse_elements" section of the mesh file (ver. >= 1.1).
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()
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)
Abstract data type element.
Data type line segment element.
void PrintStats(std::ostream &out=mfem::out) const
int GetSingleElement() const
Return one of elem[0] or elem[1] and make sure the other is -1.
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
double f(const Vector &p)