13 #include "../fem/fem.hpp"
37 for (
int i = 0; i <
ne; i++)
39 for (
int j = 0; j < 2; j++)
44 for (
int i = 0; i <
nf; i++)
46 for (
int j = 0; j <
nfv; j++)
55 for (
int i = 0; i <
ne; i++)
74 Iso = vertex_parents ?
false :
true;
79 for (
int i = 0; i < mesh->
GetNE(); i++)
83 for (
int j = 0; j < nv; j++)
85 max_id = std::max(max_id, v[j]);
88 for (
int id = 0;
id <= max_id;
id++)
91 int node =
nodes.GetId(
id,
id);
92 MFEM_CONTRACT_VAR(node);
93 MFEM_ASSERT(node ==
id,
"");
105 for (
int i = 0; i < mesh->
GetNV(); i++)
122 MFEM_ABORT(
"only triangles, quads and hexes are supported by NCMesh.");
130 MFEM_ASSERT(root_id == i,
"");
134 for (
int j = 0; j <
GI[
geom].
nv; j++)
136 root_elem.
node[j] = v[j];
148 for (
int i = 0; i < mesh->
GetNBE(); i++)
155 Face* face =
faces.Find(v[0], v[1], v[2], v[3]);
156 MFEM_VERIFY(face,
"boundary face not found.");
161 Face* face =
faces.Find(v[0], v[0], v[1], v[1]);
162 MFEM_VERIFY(face,
"boundary face not found.");
167 MFEM_ABORT(
"only segment and quadrilateral boundary "
168 "elements are supported by NCMesh.");
205 for (
int i = 0; i <
elements.Size(); i++)
227 "vert_refc: " << (
int)
vert_refc <<
", edge_refc: "
238 for (
int i = 0; i < gi.
nv; i++)
240 nodes[node[i]].vert_refc++;
244 for (
int i = 0; i < gi.
ne; i++)
246 const int* ev = gi.
edges[i];
247 nodes.Get(node[ev[0]], node[ev[1]])->edge_refc++;
251 for (
int i = 0; i < gi.
nf; i++)
253 const int* fv = gi.
faces[i];
254 faces.GetId(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
269 for (
int i = 0; i < gi.
nf; i++)
271 const int* fv = gi.
faces[i];
272 int face =
faces.FindId(node[fv[0]], node[fv[1]],
273 node[fv[2]], node[fv[3]]);
274 MFEM_ASSERT(face >= 0,
"face not found.");
275 faces[face].ForgetElement(elem);
283 for (
int i = 0; i < gi.
ne; i++)
285 const int* ev = gi.
edges[i];
287 MFEM_ASSERT(enode >= 0,
"edge not found.");
288 MFEM_ASSERT(
nodes.IdExists(enode),
"edge does not exist.");
289 if (!
nodes[enode].UnrefEdge())
296 for (
int i = 0; i < gi.
nv; i++)
298 if (!
nodes[node[i]].UnrefVertex())
300 nodes.Delete(node[i]);
310 for (
int i = 0; i < gi.
nf; i++)
313 MFEM_ASSERT(face,
"face not found.");
315 if (fattr) { face->
attribute = fattr[i]; }
321 for (
int i = 0; i < elemFaces.
Size(); i++)
323 if (
faces[elemFaces[i]].Unused())
325 faces.Delete(elemFaces[i]);
332 if (elem[0] < 0) { elem[0] = e; }
333 else if (elem[1] < 0) { elem[1] = e; }
334 else { MFEM_ABORT(
"can't have 3 elements in Face::elem[]."); }
339 if (elem[0] == e) { elem[0] = -1; }
340 else if (elem[1] == e) { elem[1] = -1; }
341 else { MFEM_ABORT(
"element " << e <<
" not found in Face::elem[]."); }
347 const int* fv = gi.
faces[face_no];
348 int* node = elem.
node;
349 return faces.Find(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
356 MFEM_ASSERT(elem[1] < 0,
"not a single element face.");
361 MFEM_ASSERT(elem[1] >= 0,
"no elements in face.");
368 int mid =
nodes.FindId(node1, node2);
369 if (mid < 0 && Dim >= 3 && !
Iso)
396 int n1p1 = n1.
p1, n1p2 = n1.
p2;
397 int n2p1 = n2.p1, n2p2 = n2.p2;
399 if ((n1p1 != n1p2) && (n2p1 != n2p2))
404 if (a1 < 0 || a2 < 0)
411 if (a1 >= 0 && a2 >= 0)
413 mid =
nodes.FindId(a1, a2);
424 : geom(geom), ref_type(0), flag(0), index(-1), rank(0), attribute(attr)
427 for (
int i = 0; i < 8; i++) {
node[i] = -1; }
436 int n4,
int n5,
int n6,
int n7,
438 int fattr0,
int fattr1,
int fattr2,
439 int fattr3,
int fattr4,
int fattr5)
450 for (
int i = 0; i < gi_hex.
nf; i++)
452 const int* fv = gi_hex.
faces[i];
466 int eattr0,
int eattr1,
int eattr2,
int eattr3)
476 for (
int i = 0; i < gi_quad.
nf; i++)
478 const int* fv = gi_quad.
faces[i];
490 int attr,
int eattr0,
int eattr1,
int eattr2)
499 for (
int i = 0; i < gi_tri.
nf; i++)
501 const int* fv = gi_tri.
faces[i];
517 if (mid < 0) { mid =
nodes.GetId(vn1, vn2); }
524 int midf =
nodes.FindId(en1, en3);
525 if (midf >= 0) {
return midf; }
526 return nodes.GetId(en2, en4);
531 {
return node == n[0] || node == n[3] || node == n[4] || node == n[7]; }
534 {
return node == n[1] || node == n[2] || node == n[5] || node == n[6]; }
537 {
return node == n[0] || node == n[1] || node == n[4] || node == n[5]; }
540 {
return node == n[2] || node == n[3] || node == n[6] || node == n[7]; }
543 {
return node == n[0] || node == n[1] || node == n[2] || node == n[3]; }
546 {
return node == n[4] || node == n[5] || node == n[6] || node == n[7]; }
552 Face* face =
faces.Find(vn1, vn2, vn3, vn4);
553 if (!face) {
return; }
556 MFEM_ASSERT(!
elements[elem].ref_type,
"element already refined.");
578 MFEM_ABORT(
"inconsistent element/face structure.");
584 int mid12,
int mid34,
int level)
610 int mid23 =
nodes.FindId(vn2, vn3);
611 int mid41 =
nodes.FindId(vn4, vn1);
612 if (mid23 >= 0 && mid41 >= 0)
614 int midf =
nodes.FindId(mid23, mid41);
617 nodes.Reparent(midf, mid12, mid34);
650 int en1,
int en2,
int en3,
int en4,
int midf)
668 if (!ref_type) {
return; }
674 char remaining = ref_type & ~el.
ref_type;
677 for (
int i = 0; i < 8; i++)
688 for (
int i = 0; i < 8; i++) { child[i] = -1; }
693 for (
int i = 0; i < gi.
nf; i++)
695 const int* fv = gi.
faces[i];
696 Face* face =
faces.Find(no[fv[0]], no[fv[1]], no[fv[2]], no[fv[3]]);
725 no[4], mid45, mid67, no[7], attr,
726 fa[0], fa[1], -1, fa[3], fa[4], fa[5]);
729 mid45, no[5], no[6], mid67, attr,
730 fa[0], fa[1], fa[2], fa[3], -1, fa[5]);
737 else if (ref_type == 2)
745 no[4], no[5], mid56, mid74, attr,
746 fa[0], fa[1], fa[2], -1, fa[4], fa[5]);
749 mid74, mid56, no[6], no[7], attr,
750 fa[0], -1, fa[2], fa[3], fa[4], fa[5]);
757 else if (ref_type == 4)
765 mid04, mid15, mid26, mid37, attr,
766 fa[0], fa[1], fa[2], fa[3], fa[4], -1);
769 no[4], no[5], no[6], no[7], attr,
770 -1, fa[1], fa[2], fa[3], fa[4], fa[5]);
777 else if (ref_type == 3)
793 no[4], mid45, midf5, mid74, attr,
794 fa[0], fa[1], -1, -1, fa[4], fa[5]);
797 mid45, no[5], mid56, midf5, attr,
798 fa[0], fa[1], fa[2], -1, -1, fa[5]);
801 midf5, mid56, no[6], mid67, attr,
802 fa[0], -1, fa[2], fa[3], -1, fa[5]);
805 mid74, midf5, mid67, no[7], attr,
806 fa[0], -1, -1, fa[3], fa[4], fa[5]);
813 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
814 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
816 else if (ref_type == 5)
832 mid04, midf1, midf3, mid37, attr,
833 fa[0], fa[1], -1, fa[3], fa[4], -1);
836 midf1, mid15, mid26, midf3, attr,
837 fa[0], fa[1], fa[2], fa[3], -1, -1);
840 mid45, no[5], no[6], mid67, attr,
841 -1, fa[1], fa[2], fa[3], -1, fa[5]);
844 no[4], mid45, mid67, no[7], attr,
845 -1, fa[1], -1, fa[3], fa[4], fa[5]);
852 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
853 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
855 else if (ref_type == 6)
871 mid04, mid15, midf2, midf4, attr,
872 fa[0], fa[1], fa[2], -1, fa[4], -1);
875 midf4, midf2, mid26, mid37, attr,
876 fa[0], -1, fa[2], fa[3], fa[4], -1);
879 no[4], no[5], mid56, mid74, attr,
880 -1, fa[1], fa[2], -1, fa[4], fa[5]);
883 mid74, mid56, no[6], no[7], attr,
884 -1, -1, fa[2], fa[3], fa[4], fa[5]);
891 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
892 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
894 else if (ref_type == 7)
921 mid04, midf1, midel, midf4, attr,
922 fa[0], fa[1], -1, -1, fa[4], -1);
925 midf1, mid15, midf2, midel, attr,
926 fa[0], fa[1], fa[2], -1, -1, -1);
929 midel, midf2, mid26, midf3, attr,
930 fa[0], -1, fa[2], fa[3], -1, -1);
933 midf4, midel, midf3, mid37, attr,
934 fa[0], -1, -1, fa[3], fa[4], -1);
937 no[4], mid45, midf5, mid74, attr,
938 -1, fa[1], -1, -1, fa[4], fa[5]);
941 mid45, no[5], mid56, midf5, attr,
942 -1, fa[1], fa[2], -1, -1, fa[5]);
945 midf5, mid56, no[6], mid67, attr,
946 -1, -1, fa[2], fa[3], -1, fa[5]);
949 mid74, midf5, mid67, no[7], attr,
950 -1, -1, -1, fa[3], fa[4], fa[5]);
952 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
953 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
954 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
955 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
956 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
957 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
961 MFEM_ABORT(
"invalid refinement type.");
964 if (ref_type != 7) {
Iso =
false; }
972 int mid01 =
nodes.GetId(no[0], no[1]);
973 int mid23 =
nodes.GetId(no[2], no[3]);
976 attr, fa[0], -1, fa[2], fa[3]);
979 attr, fa[0], fa[1], fa[2], -1);
981 else if (ref_type == 2)
983 int mid12 =
nodes.GetId(no[1], no[2]);
984 int mid30 =
nodes.GetId(no[3], no[0]);
987 attr, fa[0], fa[1], -1, fa[3]);
990 attr, -1, fa[1], fa[2], fa[3]);
992 else if (ref_type == 3)
994 int mid01 =
nodes.GetId(no[0], no[1]);
995 int mid12 =
nodes.GetId(no[1], no[2]);
996 int mid23 =
nodes.GetId(no[2], no[3]);
997 int mid30 =
nodes.GetId(no[3], no[0]);
999 int midel =
nodes.GetId(mid01, mid23);
1002 attr, fa[0], -1, -1, fa[3]);
1005 attr, fa[0], fa[1], -1, -1);
1008 attr, -1, fa[1], fa[2], -1);
1011 attr, -1, -1, fa[2], fa[3]);
1015 MFEM_ABORT(
"Invalid refinement type.");
1018 if (ref_type != 3) {
Iso =
false; }
1025 int mid01 =
nodes.GetId(no[0], no[1]);
1026 int mid12 =
nodes.GetId(no[1], no[2]);
1027 int mid20 =
nodes.GetId(no[2], no[0]);
1029 child[0] =
NewTriangle(no[0], mid01, mid20, attr, fa[0], -1, fa[2]);
1030 child[1] =
NewTriangle(mid01, no[1], mid12, attr, fa[0], fa[1], -1);
1031 child[2] =
NewTriangle(mid20, mid12, no[2], attr, -1, fa[1], fa[2]);
1032 child[3] =
NewTriangle(mid01, mid12, mid20, attr, -1, -1, -1);
1036 MFEM_ABORT(
"Unsupported element geometry.");
1040 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1053 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1062 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1079 for (
int i = refinements.
Size()-1; i >= 0; i--)
1107 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
1108 mfem::out <<
"Refined " << refinements.
Size() <<
" + " << nforced
1109 <<
" elements" << std::endl;
1125 memcpy(child, el.
child,
sizeof(child));
1128 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1140 const int table[7][8 + 6] =
1142 { 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
1143 { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1 },
1144 { 0, 1, 2, 3, 0, 1, 2, 3, 1, 1, 1, 3, 3, 3 },
1145 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1 },
1146 { 0, 1, 1, 0, 3, 2, 2, 3, 1, 1, 1, 3, 3, 3 },
1147 { 0, 0, 1, 1, 2, 2, 3, 3, 0, 0, 0, 3, 3, 3 },
1148 { 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 1, 7, 7, 7 }
1150 for (
int i = 0; i < 8; i++)
1154 for (
int i = 0; i < 6; i++)
1157 const int* fv = gi_hex.
faces[i];
1159 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1164 const int table[3][4 + 4] =
1166 { 0, 1, 1, 0, 1, 1, 0, 0 },
1167 { 0, 0, 1, 1, 0, 0, 1, 1 },
1168 { 0, 1, 2, 3, 1, 1, 3, 3 }
1170 for (
int i = 0; i < 4; i++)
1174 for (
int i = 0; i < 4; i++)
1177 const int* fv = gi_quad.
faces[i];
1179 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1184 for (
int i = 0; i < 3; i++)
1188 const int* fv = gi_tri.
faces[i];
1190 ch.
node[fv[2]], ch.
node[fv[3]])->attribute;
1195 MFEM_ABORT(
"Unsupported element geometry.");
1207 for (
int i = 0; i < 8 && child[i] >= 0; i++)
1230 int total = 0, ref = 0, ghost = 0;
1231 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1239 if (!ref && ghost < total)
1242 int next_row = list.
Size() ? (list.
Last().from + 1) : 0;
1243 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1251 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
1268 int size = list.
Size() ? (list.
Last().from + 1) : 0;
1277 for (
int i = 0; i < deref_table.
Size(); i++)
1279 const int* fine = deref_table.
GetRow(i), size = deref_table.
RowSize(i);
1283 for (
int j = 0; j < size; j++)
1288 for (
int k = 0; k <
Dim; k++)
1290 if ((parent.
ref_type & (1 << k)) &&
1291 splits[k] >= max_nc_level)
1304 MFEM_VERIFY(
Dim < 3 ||
Iso,
1305 "derefinement of 3D anisotropic meshes not implemented yet.");
1313 for (
int i = 0; i < derefs.
Size(); i++)
1315 int row = derefs[i];
1317 "invalid derefinement number.");
1332 for (
int i = 0; i < fine_coarse.
Size(); i++)
1343 for (
int i = 0; i < nfine; i++)
1357 for (
int i = 0; i < 8 && prn.
child[i] >= 0; i++)
1362 int code = (prn.
ref_type << 3) + i;
1364 fine_coarse[ch.
index] = parent;
1378 if (node->HasVertex()) { node->vert_index = num_vert++; }
1386 if (node->HasVertex()) {
vertex_nodeId[num_vert++] = node.index(); }
1390 static char quad_hilbert_child_order[8][4] =
1392 {0,1,2,3}, {0,3,2,1}, {1,2,3,0}, {1,0,3,2},
1393 {2,3,0,1}, {2,1,0,3}, {3,0,1,2}, {3,2,1,0}
1395 static char quad_hilbert_child_state[8][4] =
1397 {1,0,0,5}, {0,1,1,4}, {3,2,2,7}, {2,3,3,6},
1398 {5,4,4,1}, {4,5,5,0}, {7,6,6,3}, {6,7,7,2}
1400 static char hex_hilbert_child_order[24][8] =
1402 {0,1,2,3,7,6,5,4}, {0,3,7,4,5,6,2,1}, {0,4,5,1,2,6,7,3},
1403 {1,0,3,2,6,7,4,5}, {1,2,6,5,4,7,3,0}, {1,5,4,0,3,7,6,2},
1404 {2,1,5,6,7,4,0,3}, {2,3,0,1,5,4,7,6}, {2,6,7,3,0,4,5,1},
1405 {3,0,4,7,6,5,1,2}, {3,2,1,0,4,5,6,7}, {3,7,6,2,1,5,4,0},
1406 {4,0,1,5,6,2,3,7}, {4,5,6,7,3,2,1,0}, {4,7,3,0,1,2,6,5},
1407 {5,1,0,4,7,3,2,6}, {5,4,7,6,2,3,0,1}, {5,6,2,1,0,3,7,4},
1408 {6,2,3,7,4,0,1,5}, {6,5,1,2,3,0,4,7}, {6,7,4,5,1,0,3,2},
1409 {7,3,2,6,5,1,0,4}, {7,4,0,3,2,1,5,6}, {7,6,5,4,0,1,2,3}
1411 static char hex_hilbert_child_state[24][8] =
1413 {1,2,2,7,7,21,21,17}, {2,0,0,22,22,16,16,8}, {0,1,1,15,15,6,6,23},
1414 {4,5,5,10,10,18,18,14}, {5,3,3,19,19,13,13,11}, {3,4,4,12,12,9,9,20},
1415 {8,7,7,17,17,23,23,2}, {6,8,8,0,0,15,15,22}, {7,6,6,21,21,1,1,16},
1416 {11,10,10,14,14,20,20,5}, {9,11,11,3,3,12,12,19}, {10,9,9,18,18,4,4,13},
1417 {13,14,14,5,5,19,19,10}, {14,12,12,20,20,11,11,4}, {12,13,13,9,9,3,3,18},
1418 {16,17,17,2,2,22,22,7}, {17,15,15,23,23,8,8,1}, {15,16,16,6,6,0,0,21},
1419 {20,19,19,11,11,14,14,3}, {18,20,20,4,4,10,10,12}, {19,18,18,13,13,5,5,9},
1420 {23,22,22,8,8,17,17,0}, {21,23,23,1,1,7,7,15}, {22,21,21,16,16,2,2,6}
1437 for (
int i = 0; i < 4; i++)
1439 int ch = quad_hilbert_child_order[state][i];
1440 int st = quad_hilbert_child_state[state][i];
1446 for (
int i = 0; i < 8; i++)
1448 int ch = hex_hilbert_child_order[state][i];
1449 int st = hex_hilbert_child_state[state][i];
1455 for (
int i = 0; i < 8; i++)
1495 MFEM_ABORT(
"invalid geometry");
1510 MFEM_VERIFY(tv.
visited ==
false,
"cyclic vertex dependencies.");
1516 for (
int i = 0; i < 3; i++)
1518 tv.
pos[i] = (pos1[i] + pos2[i]) * 0.5;
1533 for (
int i = 0; i < mvertices.
Size(); i++)
1552 if (
IsGhost(nc_elem)) {
continue; }
1554 const int* node = nc_elem.
node;
1561 for (
int j = 0; j < gi.
nv; j++)
1563 elem->GetVertices()[j] =
nodes[node[j]].vert_index;
1567 for (
int k = 0; k < gi.
nf; k++)
1569 const int* fv = gi.
faces[k];
1570 const Face* face =
faces.Find(node[fv[0]], node[fv[1]],
1571 node[fv[2]], node[fv[3]]);
1578 for (
int j = 0; j < 4; j++)
1588 for (
int j = 0; j < 2; j++)
1592 mboundary.
Append(segment);
1604 for (
int i = 0; i < edge_vertex->
Size(); i++)
1606 const int *ev = edge_vertex->
GetRow(i);
1609 MFEM_ASSERT(node && node->
HasEdge(),
"edge not found.");
1616 const int* fv = mesh->
GetFace(i)->GetVertices();
1620 MFEM_ASSERT(mesh->
GetFace(i)->GetNVertices() == 4,
"");
1626 MFEM_ASSERT(mesh->
GetFace(i)->GetNVertices() == 2,
"");
1628 face =
faces.Find(n0, n0, n1, n1);
1632 const int *ev = edge_vertex->
GetRow(i);
1633 MFEM_ASSERT((ev[0] == fv[0] && ev[1] == fv[1]) ||
1634 (ev[1] == fv[0] && ev[0] == fv[1]),
"");
1637 MFEM_ASSERT(face,
"face not found.");
1648 MFEM_ASSERT(
Dim >= 3,
"");
1651 int e1 =
nodes.FindId(v1, v2);
1652 int e2 =
nodes.FindId(v2, v3);
1653 int e3 = (e1 >= 0 &&
nodes[e1].HasVertex()) ?
nodes.FindId(v3, v4) : -1;
1654 int e4 = (e2 >= 0 &&
nodes[e2].HasVertex()) ?
nodes.FindId(v4, v1) : -1;
1657 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3, mid[3] = e4; }
1660 int midf1 = -1, midf2 = -1;
1661 if (e1 >= 0 && e3 >= 0) { midf1 =
nodes.FindId(e1, e3); }
1662 if (e2 >= 0 && e4 >= 0) { midf2 =
nodes.FindId(e2, e4); }
1665 MFEM_ASSERT(!(midf1 >= 0 && midf2 >= 0),
"incorrectly split face!");
1667 if (midf1 < 0 && midf2 < 0) {
return 0; }
1668 else if (midf1 >= 0) {
return 1; }
1674 for (
int i = 0; i < 8; i++)
1676 if (el.
node[i] == node) {
return i; }
1678 MFEM_ABORT(
"Node not found.");
1686 for (
int i = 0; i < gi.
ne; i++)
1688 const int* ev = gi.
edges[i];
1689 int n0 = el.
node[ev[0]];
1690 int n1 = el.
node[ev[1]];
1691 if ((n0 == vn0 && n1 == vn1) ||
1692 (n0 == vn1 && n1 == vn0)) {
return i; }
1694 MFEM_ABORT(
"Edge not found");
1700 for (
int i = 0; i < 6; i++)
1702 const int* fv = gi_hex.
faces[i];
1703 if ((a == fv[0] || a == fv[1] || a == fv[2] || a == fv[3]) &&
1704 (b == fv[0] || b == fv[1] || b == fv[2] || b == fv[3]) &&
1705 (c == fv[0] || c == fv[1] || c == fv[2] || c == fv[3]))
1710 MFEM_ABORT(
"Face not found.");
1725 const int* fv = gi_hex.
faces[local];
1728 for (
int i = 0, j; i < 4; i++)
1730 for (j = 0; j < 4; j++)
1732 if (fv[i] == master[j])
1735 for (
int k = 0; k < mat.
Height(); k++)
1737 mat(k,i) = tmp(k,j);
1742 MFEM_ASSERT(j != 4,
"node not found.");
1753 Face* fa =
faces.Find(vn0, vn1, vn2, vn3);
1776 Point mid0(pm(0), pm(1)), mid2(pm(2), pm(3));
1784 else if (split == 2)
1786 Point mid1(pm(1), pm(2)), mid3(pm(3), pm(0));
1801 if (
Dim < 3) {
return; }
1804 processed_faces = 0;
1811 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
1814 for (
int j = 0; j < gi.
nf; j++)
1818 for (
int k = 0; k < 4; k++)
1823 int face =
faces.FindId(node[0], node[1], node[2], node[3]);
1824 MFEM_ASSERT(face >= 0,
"face not found!");
1830 if (processed_faces[face]) {
continue; }
1831 processed_faces[face] = 1;
1834 if (fa.
elem[0] >= 0 && fa.
elem[1] >= 0)
1846 TraverseFace(node[0], node[1], node[2], node[3], pm, 0);
1855 for (
int i = sb; i < se; i++)
1870 int mid =
nodes.FindId(vn0, vn1);
1871 if (mid < 0) {
return; }
1874 if (nd.
HasEdge() && level > 0)
1886 int v0index =
nodes[vn0].vert_index;
1887 int v1index =
nodes[vn1].vert_index;
1888 if (v0index > v1index) { sl.
edge_flags |= 2; }
1893 Face* fa =
faces.Find(vn0, vn0, vn1, vn1);
1894 MFEM_ASSERT(fa != NULL,
"");
1901 double tmid = (t0 + t1) / 2;
1915 processed_edges = 0;
1922 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
1925 for (
int j = 0; j < gi.
ne; j++)
1928 const int* ev = gi.
edges[j];
1929 int node[2] = { el.
node[ev[0]], el.
node[ev[1]] };
1931 int enode =
nodes.FindId(node[0], node[1]);
1932 MFEM_ASSERT(enode >= 0,
"edge node not found!");
1935 MFEM_ASSERT(nd.
HasEdge(),
"edge not found!");
1943 int face =
faces.FindId(node[0], node[0], node[1], node[1]);
1944 MFEM_ASSERT(face >= 0,
"face not found!");
1952 if (processed_edges[enode]) {
continue; }
1953 processed_edges[enode] = 1;
1956 double t0 = 0.0, t1 = 1.0;
1957 int v0index =
nodes[node[0]].vert_index;
1958 int v1index =
nodes[node[1]].vert_index;
1959 int flags = (v0index > v1index) ? 1 : 0;
1972 for (
int i = sb; i < se; i++)
1988 oriented_matrix = point_matrix;
1992 MFEM_ASSERT(oriented_matrix.
Height() == 1 &&
1993 oriented_matrix.
Width() == 2,
"not an edge point matrix");
1997 oriented_matrix(0,0) = 1.0 - oriented_matrix(0,0);
1998 oriented_matrix(0,1) = 1.0 - oriented_matrix(0,1);
2002 std::swap(oriented_matrix(0,0), oriented_matrix(0,1));
2012 int mid =
nodes.FindId(v0, v1);
2013 if (mid >= 0 &&
nodes[mid].HasVertex())
2049 int* I =
new int[nrows + 1];
2050 int** JJ =
new int*[nrows];
2060 MFEM_ASSERT(!el.
ref_type,
"not a leaf element.");
2063 int* node = el.
node;
2066 for (
int j = 0; j < gi.
ne; j++)
2068 const int* ev = gi.
edges[j];
2074 for (
int j = 0; j < gi.
nf; j++)
2076 const int* fv = gi.
faces[j];
2078 node[fv[2]], node[fv[3]], indices);
2085 int size = indices.
Size();
2087 JJ[i] =
new int[size];
2088 memcpy(JJ[i], indices.
GetData(), size *
sizeof(int));
2093 for (
int i = 0; i < nrows; i++)
2102 int *J =
new int[nnz];
2104 for (
int i = 0; i < nrows; i++)
2106 int cnt = I[i+1] - I[i];
2107 memcpy(J+nnz, JJ[i], cnt *
sizeof(
int));
2134 MFEM_VERIFY(elem_set.
Size() == nleaves,
"");
2143 for (
int i = 0; i < nleaves; i++)
2149 for (
int j = 0; j < nv; j++)
2156 for (
int j = 0; j < nv; j++)
2158 vmark[el.
node[j]] = 1;
2169 neighbor_set->
SetSize(nleaves);
2173 for (
int i = 0; i < nleaves; i++)
2181 for (
int j = 0; j < nv; j++)
2183 if (vmark[v[j]]) { hit =
true;
break; }
2190 for (
int j = 0; j < nv; j++)
2192 if (vmark[el.
node[j]]) { hit =
true;
break; }
2199 if (neighbor_set) { (*neighbor_set)[i] = 1; }
2205 static bool sorted_lists_intersect(
const int* a,
const int* b,
int na,
int nb)
2207 if (!na || !nb) {
return false; }
2208 int a_last = a[na-1], b_last = b[nb-1];
2209 if (*b < *a) {
goto l2; }
2211 if (a_last < *b) {
return false; }
2212 while (*a < *b) { a++; }
2213 if (*a == *b) {
return true; }
2215 if (b_last < *a) {
return false; }
2216 while (*b < *a) { b++; }
2217 if (*a == *b) {
return true; }
2240 while (stack.
Size())
2249 for (
int i = 0; i < nv; i++)
2255 for (
int i = 0; i < nv; i++)
2262 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
2273 int nv1 = vert.
Size();
2278 for (
int i = 0; i < search_set->
Size(); i++)
2280 int testme = (*search_set)[i];
2287 bool hit = sorted_lists_intersect(v1, v2, nv1, nv2);
2292 for (
int j = 0; j < nv; j++)
2294 hit = sorted_lists_intersect(&el.
node[j], v1, 1, nv1);
2299 if (hit) { neighbors.
Append(testme); }
2313 for (
int i = 0; i < elems.
Size(); i++)
2319 for (
int j = 0; j < nv; j++)
2325 for (
int j = 0; j < nv; j++)
2327 vmark[el.
node[j]] = 1;
2337 for (
int i = 0; i < search_set->
Size(); i++)
2339 int testme = (*search_set)[i];
2345 for (
int j = 0; j < nv; j++)
2347 if (vmark[v[j]]) { hit =
true;
break; }
2353 for (
int j = 0; j < nv; j++)
2355 if (vmark[el.
node[j]]) { hit =
true;
break; }
2359 if (hit) { expanded.
Append(testme); }
2369 for (
int i = 0; i < neighbors.
Size(); i++)
2371 elem_set[
elements[neighbors[i]].index] = 2;
2382 for (
int i = 0; i < np; i++)
2384 for (
int j = 0; j < points[0].dim; j++)
2386 point_matrix(j, i) = points[i].coord[j];
2398 Point(0, 0, 0),
Point(1, 0, 0),
Point(1, 1, 0),
Point(0, 1, 0),
2399 Point(0, 0, 1),
Point(1, 0, 1),
Point(1, 1, 1),
Point(0, 1, 1)
2410 MFEM_ABORT(
"unsupported geometry.");
2421 int ref_type = *ref_path++;
2422 int child = *ref_path++;
2428 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
2429 Point mid67(pm(6), pm(7)), mid45(pm(4), pm(5));
2434 pm(4), mid45, mid67, pm(7));
2436 else if (child == 1)
2439 mid45, pm(5), pm(6), mid67);
2442 else if (ref_type == 2)
2444 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
2445 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
2450 pm(4), pm(5), mid56, mid74);
2452 else if (child == 1)
2455 mid74, mid56, pm(6), pm(7));
2458 else if (ref_type == 4)
2460 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2461 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2466 mid04, mid15, mid26, mid37);
2468 else if (child == 1)
2471 pm(4), pm(5), pm(6), pm(7));
2474 else if (ref_type == 3)
2476 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
2477 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
2478 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
2479 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
2481 Point midf0(mid23, mid12, mid01, mid30);
2482 Point midf5(mid45, mid56, mid67, mid74);
2487 pm(4), mid45, midf5, mid74);
2489 else if (child == 1)
2492 mid45, pm(5), mid56, midf5);
2494 else if (child == 2)
2497 midf5, mid56, pm(6), mid67);
2499 else if (child == 3)
2502 mid74, midf5, mid67, pm(7));
2505 else if (ref_type == 5)
2507 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
2508 Point mid45(pm(4), pm(5)), mid67(pm(6), pm(7));
2509 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2510 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2512 Point midf1(mid01, mid15, mid45, mid04);
2513 Point midf3(mid23, mid37, mid67, mid26);
2518 mid04, midf1, midf3, mid37);
2520 else if (child == 1)
2523 midf1, mid15, mid26, midf3);
2525 else if (child == 2)
2528 mid45, pm(5), pm(6), mid67);
2530 else if (child == 3)
2533 pm(4), mid45, mid67, pm(7));
2536 else if (ref_type == 6)
2538 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
2539 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
2540 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2541 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2543 Point midf2(mid12, mid26, mid56, mid15);
2544 Point midf4(mid30, mid04, mid74, mid37);
2549 mid04, mid15, midf2, midf4);
2551 else if (child == 1)
2554 midf4, midf2, mid26, mid37);
2556 else if (child == 2)
2559 pm(4), pm(5), mid56, mid74);
2561 else if (child == 3)
2564 mid74, mid56, pm(6), pm(7));
2567 else if (ref_type == 7)
2569 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
2570 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
2571 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
2572 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
2573 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2574 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2576 Point midf0(mid23, mid12, mid01, mid30);
2577 Point midf1(mid01, mid15, mid45, mid04);
2578 Point midf2(mid12, mid26, mid56, mid15);
2579 Point midf3(mid23, mid37, mid67, mid26);
2580 Point midf4(mid30, mid04, mid74, mid37);
2581 Point midf5(mid45, mid56, mid67, mid74);
2583 Point midel(midf1, midf3);
2588 mid04, midf1, midel, midf4);
2590 else if (child == 1)
2593 midf1, mid15, midf2, midel);
2595 else if (child == 2)
2598 midel, midf2, mid26, midf3);
2600 else if (child == 3)
2603 midf4, midel, midf3, mid37);
2605 else if (child == 4)
2608 pm(4), mid45, midf5, mid74);
2610 else if (child == 5)
2613 mid45, pm(5), mid56, midf5);
2615 else if (child == 6)
2618 midf5, mid56, pm(6), mid67);
2620 else if (child == 7)
2623 mid74, midf5, mid67, pm(7));
2631 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
2637 else if (child == 1)
2642 else if (ref_type == 2)
2644 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
2650 else if (child == 1)
2655 else if (ref_type == 3)
2657 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
2658 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
2659 Point midel(mid01, mid23);
2665 else if (child == 1)
2669 else if (child == 2)
2673 else if (child == 3)
2681 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
2687 else if (child == 1)
2691 else if (child == 2)
2695 else if (child == 3)
2703 for (
int i = 0; i < pm.
np; i++)
2705 for (
int j = 0; j < pm(i).dim; j++)
2707 matrix(j, i) = pm(i).coord[j];
2732 int &matrix = map[ref_path];
2733 if (!matrix) { matrix = map.size(); }
2736 emb.
parent = coarse_index;
2742 ref_path.push_back(0);
2744 for (
int i = 0; i < 8; i++)
2746 if (el.
child[i] >= 0)
2748 ref_path[ref_path.length()-1] = i;
2752 ref_path.resize(ref_path.length()-2);
2759 "GetRefinementTransforms() must be preceded by MarkCoarseLevel()"
2766 std::string ref_path;
2767 ref_path.reserve(100);
2784 for (RefPathMap::iterator it = map.begin(); it != map.end(); ++it)
2796 "GetDerefinementTransforms() must be preceded by Derefine().");
2800 std::map<int, int> mat_no;
2809 int &matrix = mat_no[code];
2810 if (!matrix) { matrix = mat_no.size(); }
2821 std::map<int, int>::iterator it;
2822 for (it = mat_no.begin(); it != mat_no.end(); ++it)
2825 int code = it->first;
2826 path[0] = code >> 3;
2848 MFEM_ASSERT(node >= 0,
"edge node not found.");
2851 int p1 = nd.
p1, p2 = nd.
p2;
2852 MFEM_ASSERT(p1 != p2,
"invalid edge node.");
2856 int n1p1 = n1.
p1, n1p2 = n1.
p2;
2857 int n2p1 = n2.p1, n2p2 = n2.p2;
2859 if ((n2p1 != n2p2) && (p1 == n2p1 || p1 == n2p2))
2863 if (n2.HasEdge()) {
return p2; }
2867 if ((n1p1 != n1p2) && (p2 == n1p1 || p2 == n1p2))
2871 if (n1.
HasEdge()) {
return p1; }
2881 MFEM_ASSERT(node >= 0 &&
nodes[node].HasEdge(),
"(v1, v2) is not an edge.");
2884 return (master >= 0) ?
nodes[master].edge_index : -1;
2890 int depth = 0, parent;
2891 while ((parent =
elements[elem].parent) != -1)
2906 int elem = fa.
elem[0];
2907 if (elem < 0) { elem = fa.
elem[1]; }
2908 MFEM_ASSERT(elem >= 0,
"Face has no elements?");
2916 for (
int i = 0; i < 4; i++)
2918 node[i] = el.
node[fv[i]];
2935 if (bdr_attr_is_ess[
faces[face].attribute - 1])
2940 for (
int j = 0; j < 4; j++)
2944 int enode =
nodes.FindId(node[j], node[(j+1) % 4]);
2945 MFEM_ASSERT(enode >= 0 &&
nodes[enode].HasEdge(),
"Edge not found.");
2974 bdr_vertices.
Sort();
2983 int mid =
nodes.FindId(vn1, vn2);
2984 if (mid < 0 || !
nodes[mid].HasVertex()) {
return 0; }
2989 int& h_level,
int& v_level)
const
2991 int hl1, hl2, vl1, vl2;
2997 h_level = v_level = 0;
3003 h_level = std::max(hl1, hl2);
3004 v_level = std::max(vl1, vl2) + 1;
3010 h_level = std::max(hl1, hl2) + 1;
3011 v_level = std::max(vl1, vl2);
3015 static int max8(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h)
3017 return std::max(std::max(std::max(a, b), std::max(c, d)),
3018 std::max(std::max(e, f), std::max(g, h)));
3024 const int* node = el.
node;
3028 for (
int i = 0; i < gi.
ne; i++)
3030 const int* ev = gi.
edges[i];
3037 for (
int i = 0; i < gi.
nf; i++)
3039 const int* fv = gi.
faces[i];
3040 FaceSplitLevel(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]],
3041 flevel[i][1], flevel[i][0]);
3044 splits[0] = max8(flevel[0][0], flevel[1][0], flevel[3][0], flevel[5][0],
3045 elevel[0], elevel[2], elevel[4], elevel[6]);
3047 splits[1] = max8(flevel[0][1], flevel[2][0], flevel[4][0], flevel[5][1],
3048 elevel[1], elevel[3], elevel[5], elevel[7]);
3050 splits[2] = max8(flevel[1][1], flevel[2][1], flevel[3][1], flevel[4][1],
3051 elevel[8], elevel[9], elevel[10], elevel[11]);
3055 splits[0] = std::max(elevel[0], elevel[2]);
3056 splits[1] = std::max(elevel[1], elevel[3]);
3060 splits[0] = std::max(elevel[0], std::max(elevel[1], elevel[2]));
3061 splits[1] = splits[0];
3065 MFEM_ABORT(
"Unsupported element geometry.");
3079 for (
int k = 0; k <
Dim; k++)
3081 if (splits[k] > max_level)
3083 ref_type |= (1 << k);
3101 MFEM_VERIFY(max_nc_level >= 1,
"'max_nc_level' must be 1 or greater.");
3108 if (!refinements.
Size()) {
break; }
3120 if (node->HasVertex() && node->p1 != node->p2) { nv++; }
3127 if (node->HasVertex() && node->p1 != node->p2)
3135 out << node->vert_index <<
" "
3148 input >>
id >> p1 >> p2;
3149 MFEM_VERIFY(input,
"problem reading vertex parents.");
3151 MFEM_VERIFY(
nodes.IdExists(
id),
"vertex " <<
id <<
" not found.");
3152 MFEM_VERIFY(
nodes.IdExists(p1),
"parent " << p1 <<
" not found.");
3153 MFEM_VERIFY(
nodes.IdExists(p2),
"parent " << p2 <<
" not found.");
3156 nodes.Reparent(
id, p1, p2);
3165 int num_top_level = 0;
3168 if (node->p1 == node->p2)
3170 MFEM_VERIFY(node.index() == node->p1,
"invalid top-level vertex.");
3171 MFEM_VERIFY(node->HasVertex(),
"top-level vertex not found.");
3172 MFEM_VERIFY(node->vert_index == node->p1,
"bad top-level vertex index");
3173 num_top_level = std::max(num_top_level, node->p1 + 1);
3178 for (
int i = 0; i < num_top_level; i++)
3184 static int ref_type_num_children[8] = { 0, 2, 2, 4, 2, 4, 4, 8 };
3191 int child_id[8], nch = 0;
3192 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
3196 MFEM_ASSERT(nch == ref_type_num_children[(
int) el.
ref_type],
"");
3199 for (
int i = 0; i < nch; i++)
3201 out <<
" " << child_id[i];
3233 for (
int i = 0; i < 8 && el.
child[i] >= 0; i++)
3235 int old_id = el.
child[i];
3237 int new_id =
elements.Append(tmp_elements[old_id]);
3238 index_map[old_id] = new_id;
3239 el.
child[i] = new_id;
3263 if (
Dim == 3 && ref_type != 7) { iso =
false; }
3266 int nch = ref_type_num_children[ref_type];
3267 for (
int i = 0,
id; i < nch; i++)
3270 MFEM_VERIFY(
id >= 0,
"");
3273 "coarse element cannot be referenced before it is "
3274 "defined (id=" <<
id <<
").");
3277 MFEM_VERIFY(child.parent == -1,
3278 "element " <<
id <<
" cannot have two parents.");
3281 child.parent = elem;
3285 el.
geom = child.geom;
3303 if (el->parent == -1)
3306 index_map[el.index()] = new_id;
3320 for (
int i = 0; i < 2; i++)
3322 if (face->elem[i] >= 0)
3324 face->elem[i] = index_map[face->elem[i]];
3325 MFEM_ASSERT(face->elem[i] >= 0,
"");
3341 pmsize = slaves[0].point_matrix.MemoryUsage();
3344 return conforming.capacity() *
sizeof(
MeshId) +
3345 masters.capacity() *
sizeof(
Master) +
3346 slaves.capacity() *
sizeof(
Slave) +
3347 slaves.size() * pmsize;
3352 return point_matrices.MemoryUsage() + embeddings.MemoryUsage();
3357 return nodes.MemoryUsage() +
3358 faces.MemoryUsage() +
3389 <<
ref_stack.MemoryUsage() <<
" ref_stack\n"
3391 <<
sizeof(*this) <<
" NCMesh" << std::endl;
3398 static const double MiB = 1024.*1024.;
3400 "NCMesh statistics:\n"
3401 "------------------\n"
3402 " mesh and space dimensions : " <<
Dim <<
", " <<
spaceDim <<
"\n"
3403 " isotropic only : " << (
Iso ?
"yes" :
"no") <<
"\n"
3404 " number of Nodes : " << std::setw(9)
3405 <<
nodes.Size() <<
" + [ " << std::setw(9)
3406 <<
nodes.MemoryUsage()/MiB <<
" MiB ]\n"
3407 " free " << std::setw(9)
3408 <<
nodes.NumFreeIds() <<
"\n"
3409 " number of Faces : " << std::setw(9)
3410 <<
faces.Size() <<
" + [ " << std::setw(9)
3411 <<
faces.MemoryUsage()/MiB <<
" MiB ]\n"
3412 " free " << std::setw(9)
3413 <<
faces.NumFreeIds() <<
"\n"
3414 " number of Elements : " << std::setw(9)
3418 " free " << std::setw(9)
3420 " number of root elements : " << std::setw(9) <<
root_count <<
"\n"
3421 " number of leaf elements : " << std::setw(9)
3423 " number of vertices : " << std::setw(9)
3425 " number of faces : " << std::setw(9)
3428 " conforming " << std::setw(9)
3430 " master " << std::setw(9)
3432 " slave " << std::setw(9)
3434 " number of edges : " << std::setw(9)
3437 " conforming " << std::setw(9)
3439 " master " << std::setw(9)
3441 " slave " << std::setw(9)
3443 " total memory : " << std::setw(17)
3444 <<
"[ " << std::setw(9) <<
MemoryUsage()/MiB <<
" MiB ]\n"
3448 #if 0//def MFEM_DEBUG
3454 for (
int j = 0; j <
Dim; j++)
3458 for (
int k = 0; k < 8; k++)
3462 sum += elem->
node[k]->vertex->pos[j];
NCList face_list
lazy-initialized list of faces, see GetFaceList
void CollectLeafElements(int elem, int state)
NCList edge_list
lazy-initialized list of edges, see GetEdgeList
NCMesh(const Mesh *mesh, std::istream *vertex_parents=NULL)
int Size() const
Logical size of the array.
CoarseFineTransformations transforms
storage for data returned by Get[De]RefinementTransforms()
int NewQuadrilateral(int n0, int n1, int n2, int n3, int attr, int eattr0, int eattr1, int eattr2, int eattr3)
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)
Array< double > top_vertex_pos
Table * GetEdgeVertexTable() const
Returns the edge-to-vertex Table (3D)
void SetDerefMatrixCodes(int parent, Array< int > &fine_coarse)
const CoarseFineTransformations & GetDerefinementTransforms()
virtual int GetNEdges() const =0
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).
void GetPointMatrix(int geom, const char *ref_path, DenseMatrix &matrix)
virtual void LimitNCLevel(int max_nc_level)
int GetNBE() const
Returns number of boundary elements.
int index
element number in the Mesh, -1 if refined
virtual int GetNumGhosts() const
void CopyElements(int elem, const BlockArray< Element > &tmp_elements, Array< int > &index_map)
void ForceRefinement(int vn1, int vn2, int vn3, int vn4)
void DebugLeafOrder() const
Print the space-filling curve formed by the sequence of leaf elements.
void GetMeshComponents(Array< mfem::Vertex > &mvertices, Array< mfem::Element * > &melements, Array< mfem::Element * > &mboundary) const
Return the basic Mesh arrays for the current finest level.
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 Copy(Array ©) const
Create a copy of the current array.
void TraverseEdge(int vn0, int vn1, double t0, double t1, int flags, int level)
T * GetData()
Returns the data.
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.
void CollectFaceVertices(int v0, int v1, int v2, int v3, Array< int > &indices)
void InitDerefTransforms()
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.
void SetSize(int i, int j, int k)
int GetNE() const
Returns number of elements.
void OrientedPointMatrix(DenseMatrix &oriented_matrix) const
Return the point matrix oriented according to the master and slave edges.
const Element * GetFace(int i) const
void CheckAnisoFace(int vn1, int vn2, int vn3, int vn4, int mid12, int mid34, int level=0)
static PointMatrix pm_tri_identity
void CountSplits(int elem, int splits[3]) const
void CollectDerefinements(int elem, Array< Connection > &list)
std::vector< MeshId > conforming
Data type quadrilateral element.
void GetLimitRefinements(Array< Refinement > &refinements, int max_level)
int PrintMemoryDetail() 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 FindFaceNodes(int face, int node[4])
int GetGeometryType() const
void DeleteAll()
Delete whole array.
int index
Mesh element number.
const NCList & GetFaceList()
Return the current list of conforming and nonconforming faces.
virtual void ElementSharesEdge(int elem, int enode)
virtual void OnMeshUpdated(Mesh *mesh)
void CollectEdgeVertices(int v0, int v1, Array< int > &indices)
void DebugNeighbors(Array< char > &elem_set)
Array< Refinement > ref_stack
stack of scheduled refinements (temporary)
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
virtual bool IsGhost(const Element &el) const
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
void CheckIsoFace(int vn1, int vn2, int vn3, int vn4, int en1, int en2, int en3, int en4, int midf)
Data type hexahedron element.
Face * GetFace(Element &elem, int face_no)
void TraverseRefinements(int elem, int coarse_index, std::string &ref_path, RefPathMap &map)
virtual const int * GetEdgeVertices(int) const =0
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 local
local number within 'element'
int FindAltParents(int node1, int node2)
int Append(const T &el)
Append element to array, resize if necessary.
void GetMatrix(DenseMatrix &point_matrix) const
int AddElement(const Element &el)
bool NodeSetY1(int node, int *n)
virtual void Derefine(const Array< int > &derefs)
void FindNeighbors(int elem, Array< int > &neighbors, const Array< int > *search_set=NULL)
std::vector< Master > masters
Array< int > coarse_elements
state of leaf_elements before Refine(), set by MarkCoarseLevel()
virtual void UpdateVertices()
update Vertex::index and vertex_nodeId
void RegisterFaces(int elem, int *fattr=NULL)
std::size_t TotalSize() const
Element(int geom, int attr)
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 parent
parent element, -1 if this is a root element, -2 if free
Data type triangle element.
const Element * GetElement(int i) const
void Sort()
Sorts the array. This requires operator< to be defined for T.
int Size() const
Returns the number of TYPE I elements.
A class for non-conforming AMR on higher-order hexahedral, quadrilateral or triangular meshes...
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.
static GeomInfo GI[Geometry::NumGeom]
bool NodeSetY2(int node, int *n)
int NewTriangle(int n0, int n1, int n2, int attr, int eattr0, int eattr1, int eattr2)
void DeleteUnusedFaces(const Array< int > &elemFaces)
virtual void ElementSharesFace(int elem, int face)
int SpaceDimension() const
bool Iso
true if the mesh only contains isotropic refinements
std::map< std::string, int > RefPathMap
int FaceSplitType(int v1, int v2, int v3, int v4, int mid[4]=NULL) const
std::vector< Slave > slaves
virtual void BuildFaceList()
void DerefineElement(int elem)
int ReorderFacePointMat(int v0, int v1, int v2, int v3, int elem, DenseMatrix &mat) const
void SetVertexPositions(const Array< mfem::Vertex > &vertices)
I/O: Set positions of all vertices (used by mesh loader).
int edge_flags
edge orientation flags
void RegisterElement(int e)
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
static const PointMatrix & GetGeomIdentity(int geom)
mfem::Element * NewMeshElement(int geom) const
void DeleteLast()
Delete the last entry.
Helper struct for defining a connectivity table, see Table::MakeFromList.
void UpdateLeafElements()
bool NodeSetZ2(int node, int *n)
void BuildElementToVertexTable()
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
bool NodeSetZ1(int node, int *n)
void ForgetElement(int e)
int GetMidFaceNode(int en1, int en2, int en3, int en4)
void RefineElement(int elem, char ref_type)
virtual int GetNFaces(int &nFaceVertices) const =0
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)
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
void TraverseFace(int vn0, int vn1, int vn2, int vn3, const PointMatrix &pm, int level)
int EdgeSplitLevel(int vn1, int vn2) const
void SetIJ(int *newI, int *newJ, int newsize=-1)
static int find_element_edge(const Element &el, int vn0, int vn1)
void Initialize(const mfem::Element *elem)
Array< int > free_element_ids
bool NodeSetX2(int node, int *n)
virtual int GetNVertices() const =0
int parent
element index in the coarse mesh
void SetAttribute(const int attr)
Set element's attribute.
virtual void AssignLeafIndices()
static PointMatrix pm_hex_identity
static int find_hex_face(int a, int b, int c)
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)
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).
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
void UpdateElementToVertexTable()
int GetElementDepth(int i) const
Return the distance of leaf 'i' from the root.
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...
static int find_node(const Element &el, int node)
void LoadVertexParents(std::istream &input)
int GetMidEdgeNode(int vn1, int vn2)
Abstract data type element.
void UnrefElement(int elem, Array< int > &elemFaces)
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.
const double * CalcVertexPos(int node) const
int rank
processor number (ParNCMesh), -1 if undefined/unknown
bool NodeSetX1(int node, int *n)
int node[8]
element corners (if ref_type == 0)
const Element * GetBdrElement(int i) const
virtual int GetType() const =0
Returns element's type.
DenseMatrix point_matrix
position within the master edge/face
Defines the position of a fine element within a coarse element.
void RefElement(int elem)
void FaceSplitLevel(int vn1, int vn2, int vn3, int vn4, int &h_level, int &v_level) const
virtual void Refine(const Array< Refinement > &refinements)
int matrix
index into CoarseFineTransformations::point_matrices
int GetEdgeMaster(int v1, int v2) const