12 #include "../fem/fem.hpp"
36 for (
int i = 0; i <
ne; i++)
38 for (
int j = 0; j < 2; j++)
43 for (
int i = 0; i <
nf; i++)
45 for (
int j = 0; j <
nfv; j++)
61 Iso = vertex_parents ?
false :
true;
66 for (
int i = 0; i < mesh->
GetNE(); i++)
70 for (
int j = 0; j < nv; j++)
72 max_id = std::max(max_id, v[j]);
75 for (
int i = 0; i <= max_id; i++)
79 MFEM_CONTRACT_VAR(node);
80 MFEM_ASSERT(node->
id == i,
"");
91 for (
int i = 0; i < mesh->
GetNE(); i++)
101 MFEM_ABORT(
"only triangles, quads and hexes are supported by NCMesh.");
111 for (
int j = 0; j <
GI[geom].
nv; j++)
116 if (v[j] < mesh->
GetNV())
119 const double* pos = mesh->
GetVertex(v[j]);
128 nc_elem->
node[j] = node;
140 for (
int i = 0; i < mesh->
GetNBE(); i++)
148 node[i] =
nodes.Peek(v[i]);
149 MFEM_VERIFY(node[i],
"boundary elements inconsistent.");
154 Face* face =
faces.Peek(node[0], node[1], node[2], node[3]);
155 MFEM_VERIFY(face,
"boundary face not found.");
160 Edge* edge =
nodes.Peek(node[0], node[1])->edge;
161 MFEM_VERIFY(edge,
"boundary edge not found.");
166 MFEM_ABORT(
"only segment and quadrilateral boundary "
167 "elements are supported by NCMesh.");
190 for (
int i = 0; i < 8; i++)
202 for (
int i = 0; i < gi.
nv; i++)
215 for (
int i = 0; i < 8; i++)
254 MFEM_ASSERT(
vertex,
"can't create vertex here.");
260 if (!edge) { edge =
new Edge; }
266 MFEM_ASSERT(vertex,
"cannot unref a nonexistent vertex.");
267 if (!vertex->Unref()) { vertex = NULL; }
268 if (!vertex && !edge) { nodes.
Delete(
this); }
273 MFEM_ASSERT(
this,
"node not found.");
274 MFEM_ASSERT(edge,
"cannot unref a nonexistent edge.");
275 if (!edge->Unref()) { edge = NULL; }
276 if (!vertex && !edge) { nodes.
Delete(
this); }
281 std::memcpy(
this, &other,
sizeof(*
this));
282 if (vertex) { vertex =
new Vertex(*vertex); }
283 if (edge) { edge =
new Edge(*edge); }
288 MFEM_ASSERT(!vertex && !edge,
"node was not unreffed properly.");
289 if (vertex) {
delete vertex; }
290 if (edge) {
delete edge; }
299 for (
int i = 0; i < gi.
nv; i++)
305 for (
int i = 0; i < gi.
ne; i++)
307 const int* ev = gi.
edges[i];
308 nodes.Get(node[ev[0]], node[ev[1]])->RefEdge();
312 for (
int i = 0; i < gi.
nf; i++)
314 const int* fv = gi.
faces[i];
315 faces.Get(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]])->Ref();
328 for (
int i = 0; i < gi.
nf; i++)
330 const int* fv = gi.
faces[i];
331 Face* face =
faces.Peek(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
337 for (
int i = 0; i < gi.
ne; i++)
339 const int* ev = gi.
edges[i];
345 for (
int i = 0; i < gi.
nv; i++)
360 std::memcpy(
this, &other,
sizeof(*
this));
361 elem[0] = elem[1] = NULL;
366 if (elem[0] == NULL) { elem[0] = e; }
367 else if (elem[1] == NULL) { elem[1] = e; }
368 else { MFEM_ABORT(
"can't have 3 elements in Face::elem[]."); }
373 if (elem[0] == e) { elem[0] = NULL; }
374 else if (elem[1] == e) { elem[1] = NULL; }
375 else { MFEM_ABORT(
"element not found in Face::elem[]."); }
383 for (
int i = 0; i < gi.
nf; i++)
385 const int* fv = gi.
faces[i];
386 Face* face =
faces.Peek(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]]);
388 if (fattr) { face->
attribute = fattr[i]; }
396 MFEM_ASSERT(!elem[1],
"not a single element face.");
401 MFEM_ASSERT(elem[1],
"no elements in face.");
434 if ((v1->
p1 != v1->
p2) && (v2->
p1 != v2->
p2))
450 mid =
nodes.Peek(w1, w2);
461 : geom(geom), ref_type(0), index(-1), rank(-1), attribute(attr), parent(NULL)
475 int fattr0,
int fattr1,
int fattr2,
476 int fattr3,
int fattr4,
int fattr5)
485 for (
int i = 0; i < gi_hex.
nf; i++)
487 const int* fv = gi_hex.
faces[i];
502 int eattr0,
int eattr1,
int eattr2,
int eattr3)
510 for (
int i = 0; i < gi_quad.
ne; i++)
512 const int* ev = gi_quad.
edges[i];
515 edge[i] = node->
edge;
528 int attr,
int eattr0,
int eattr1,
int eattr2)
536 for (
int i = 0; i < gi_tri.
ne; i++)
538 const int* ev = gi_tri.
edges[i];
541 edge[i] = node->
edge;
553 MFEM_ASSERT(v1->
vertex && v2->
vertex,
"missing parent vertices.");
557 for (
int i = 0; i < 3; i++)
569 if (!mid) { mid =
nodes.Get(v1, v2); }
594 midf =
nodes.Get(e2, e4);
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]; }
624 if (!face) {
return; }
627 MFEM_ASSERT(!elem->
ref_type,
"element already refined.");
649 MFEM_ABORT(
"inconsistent element/face structure.");
655 Node* mid12,
Node* mid34,
int level)
688 nodes.Reparent(midf, mid12->
id, mid34->
id);
727 if (!ref_type) {
return; }
732 char remaining = ref_type & ~elem->
ref_type;
735 for (
int i = 0; i < 8; i++)
746 memset(child, 0,
sizeof(child));
753 for (
int i = 0; i < gi_hex.
nf; i++)
755 const int* fv = gi_hex.
faces[i];
756 Face* face =
faces.Peek(no[fv[0]], no[fv[1]], no[fv[2]], no[fv[3]]);
782 no[4], mid45, mid67, no[7], attr,
783 fa[0], fa[1], -1, fa[3], fa[4], fa[5]);
786 mid45, no[5], no[6], mid67, attr,
787 fa[0], fa[1], fa[2], fa[3], -1, fa[5]);
794 else if (ref_type == 2)
802 no[4], no[5], mid56, mid74, attr,
803 fa[0], fa[1], fa[2], -1, fa[4], fa[5]);
806 mid74, mid56, no[6], no[7], attr,
807 fa[0], -1, fa[2], fa[3], fa[4], fa[5]);
814 else if (ref_type == 4)
822 mid04, mid15, mid26, mid37, attr,
823 fa[0], fa[1], fa[2], fa[3], fa[4], -1);
826 no[4], no[5], no[6], no[7], attr,
827 -1, fa[1], fa[2], fa[3], fa[4], fa[5]);
834 else if (ref_type == 3)
850 no[4], mid45, midf5, mid74, attr,
851 fa[0], fa[1], -1, -1, fa[4], fa[5]);
854 mid45, no[5], mid56, midf5, attr,
855 fa[0], fa[1], fa[2], -1, -1, fa[5]);
858 midf5, mid56, no[6], mid67, attr,
859 fa[0], -1, fa[2], fa[3], -1, fa[5]);
862 mid74, midf5, mid67, no[7], attr,
863 fa[0], -1, -1, fa[3], fa[4], fa[5]);
870 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
871 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
873 else if (ref_type == 5)
889 mid04, midf1, midf3, mid37, attr,
890 fa[0], fa[1], -1, fa[3], fa[4], -1);
893 midf1, mid15, mid26, midf3, attr,
894 fa[0], fa[1], fa[2], fa[3], -1, -1);
897 mid45, no[5], no[6], mid67, attr,
898 -1, fa[1], fa[2], fa[3], -1, fa[5]);
901 no[4], mid45, mid67, no[7], attr,
902 -1, fa[1], -1, fa[3], fa[4], fa[5]);
909 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
910 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
912 else if (ref_type == 6)
928 mid04, mid15, midf2, midf4, attr,
929 fa[0], fa[1], fa[2], -1, fa[4], -1);
932 midf4, midf2, mid26, mid37, attr,
933 fa[0], -1, fa[2], fa[3], fa[4], -1);
936 no[4], no[5], mid56, mid74, attr,
937 -1, fa[1], fa[2], -1, fa[4], fa[5]);
940 mid74, mid56, no[6], no[7], attr,
941 -1, -1, fa[2], fa[3], fa[4], fa[5]);
948 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
949 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
951 else if (ref_type == 7)
978 mid04, midf1, midel, midf4, attr,
979 fa[0], fa[1], -1, -1, fa[4], -1);
982 midf1, mid15, midf2, midel, attr,
983 fa[0], fa[1], fa[2], -1, -1, -1);
986 midel, midf2, mid26, midf3, attr,
987 fa[0], -1, fa[2], fa[3], -1, -1);
990 midf4, midel, midf3, mid37, attr,
991 fa[0], -1, -1, fa[3], fa[4], -1);
994 no[4], mid45, midf5, mid74, attr,
995 -1, fa[1], -1, -1, fa[4], fa[5]);
998 mid45, no[5], mid56, midf5, attr,
999 -1, fa[1], fa[2], -1, -1, fa[5]);
1002 midf5, mid56, no[6], mid67, attr,
1003 -1, -1, fa[2], fa[3], -1, fa[5]);
1006 mid74, midf5, mid67, no[7], attr,
1007 -1, -1, -1, fa[3], fa[4], fa[5]);
1009 CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid30, midf0);
1010 CheckIsoFace(no[0], no[1], no[5], no[4], mid01, mid15, mid45, mid04, midf1);
1011 CheckIsoFace(no[1], no[2], no[6], no[5], mid12, mid26, mid56, mid15, midf2);
1012 CheckIsoFace(no[2], no[3], no[7], no[6], mid23, mid37, mid67, mid26, midf3);
1013 CheckIsoFace(no[3], no[0], no[4], no[7], mid30, mid04, mid74, mid37, midf4);
1014 CheckIsoFace(no[4], no[5], no[6], no[7], mid45, mid56, mid67, mid74, midf5);
1018 MFEM_ABORT(
"invalid refinement type.");
1021 if (ref_type != 7) {
Iso =
false; }
1026 int ea0 =
nodes.Peek(no[0], no[1])->edge->attribute;
1027 int ea1 =
nodes.Peek(no[1], no[2])->edge->attribute;
1028 int ea2 =
nodes.Peek(no[2], no[3])->edge->attribute;
1029 int ea3 =
nodes.Peek(no[3], no[0])->edge->attribute;
1039 attr, ea0, -1, ea2, ea3);
1042 attr, ea0, ea1, ea2, -1);
1044 else if (ref_type == 2)
1050 attr, ea0, ea1, -1, ea3);
1053 attr, -1, ea1, ea2, ea3);
1055 else if (ref_type == 3)
1065 attr, ea0, -1, -1, ea3);
1068 attr, ea0, ea1, -1, -1);
1071 attr, -1, ea1, ea2, -1);
1074 attr, -1, -1, ea2, ea3);
1078 MFEM_ABORT(
"Invalid refinement type.");
1081 if (ref_type != 3) {
Iso =
false; }
1086 int ea0 =
nodes.Peek(no[0], no[1])->edge->attribute;
1087 int ea1 =
nodes.Peek(no[1], no[2])->edge->attribute;
1088 int ea2 =
nodes.Peek(no[2], no[0])->edge->attribute;
1097 child[0] =
NewTriangle(no[0], mid01, mid20, attr, ea0, -1, ea2);
1098 child[1] =
NewTriangle(mid01, no[1], mid12, attr, ea0, ea1, -1);
1099 child[2] =
NewTriangle(mid20, mid12, no[2], attr, -1, ea1, ea2);
1100 child[3] =
NewTriangle(mid01, mid12, mid20, attr, -1, -1, -1);
1104 MFEM_ABORT(
"Unsupported element geometry.");
1108 for (
int i = 0; i < 8; i++)
1117 for (
int i = 0; i < 8; i++)
1123 for (
int i = 0; i < 8; i++)
1134 memcpy(elem->
child, child,
sizeof(elem->
child));
1142 for (
int i = refinements.
Size()-1; i >= 0; i--)
1171 std::cout <<
"Refined " << refinements.
Size() <<
" + " << nforced
1172 <<
" elements" << std::endl;
1184 std::memcpy(child, elem->
child,
sizeof(child));
1187 for (
int i = 0; i < 8; i++)
1189 if (child[i] && child[i]->ref_type)
1199 const int table[7][8 + 6] =
1201 { 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
1202 { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1 },
1203 { 0, 1, 2, 3, 0, 1, 2, 3, 1, 1, 1, 3, 3, 3 },
1204 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1 },
1205 { 0, 1, 1, 0, 3, 2, 2, 3, 1, 1, 1, 3, 3, 3 },
1206 { 0, 0, 1, 1, 2, 2, 3, 3, 0, 0, 0, 3, 3, 3 },
1207 { 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 1, 7, 7, 7 }
1209 for (
int i = 0; i < 8; i++)
1213 for (
int i = 0; i < 6; i++)
1216 const int* fv = gi_hex.
faces[i];
1218 ch->
node[fv[2]], ch->
node[fv[3]])->attribute;
1223 const int table[3][4 + 4] =
1225 { 0, 1, 1, 0, 1, 1, 0, 0 },
1226 { 0, 0, 1, 1, 0, 0, 1, 1 },
1227 { 0, 1, 2, 3, 1, 1, 3, 3 }
1229 for (
int i = 0; i < 4; i++)
1233 for (
int i = 0; i < 4; i++)
1236 const int* ev = gi_quad.
edges[i];
1237 ea[i] =
nodes.Peek(ch->
node[ev[0]], ch->
node[ev[1]])->edge->attribute;
1242 for (
int i = 0; i < 3; i++)
1246 const int* ev = gi_tri.
edges[i];
1247 ea[i] =
nodes.Peek(ch->
node[ev[0]], ch->
node[ev[1]])->edge->attribute;
1252 MFEM_ABORT(
"Unsupported element geometry.");
1259 elem->
rank = std::numeric_limits<int>::max();
1260 for (
int i = 0; i < 8; i++)
1278 for (
int i = 0; i < gi.
ne; i++)
1280 const int* ev = gi.
edges[i];
1281 nodes.Peek(node[ev[0]], node[ev[1]])->edge->attribute = ea[i];
1297 if (it->vertex) { it->vertex->index = num_vert++; }
1317 for (
int i = 0; i < 8; i++)
1350 for (
int i = 0; i < vertices.
Size(); i++)
1353 vertices[i].SetCoords(node->
vertex->
pos);
1365 if (
IsGhost(nc_elem)) {
continue; }
1371 switch (nc_elem->
geom)
1380 for (
int j = 0; j < gi.
nv; j++)
1388 for (
int k = 0; k < gi.
nf; k++)
1390 const int* fv = gi.
faces[k];
1391 Face* face =
faces.Peek(node[fv[0]], node[fv[1]],
1392 node[fv[2]], node[fv[3]]);
1397 for (
int j = 0; j < 4; j++)
1407 for (
int k = 0; k < gi.
ne; k++)
1409 const int* ev = gi.
edges[k];
1410 Edge* edge =
nodes.Peek(node[ev[0]], node[ev[1]])->edge;
1415 for (
int j = 0; j < 2; j++)
1419 boundary.
Append(segment);
1430 for (
int i = 0; i < edge_vertex->
Size(); i++)
1432 const int *ev = edge_vertex->
GetRow(i);
1435 MFEM_ASSERT(node && node->
edge,
"edge not found.");
1439 for (
int i = 0; i < mesh->
GetNFaces(); i++)
1441 const int* fv = mesh->
GetFace(i)->GetVertices();
1445 MFEM_ASSERT(face,
"face not found.");
1459 Node* e3 = e1 ?
nodes.Peek(v3, v4) : NULL;
1460 Node* e4 = e2 ?
nodes.Peek(v4, v1) : NULL;
1463 if (mid) { mid[0] = e1, mid[1] = e2, mid[2] = e3, mid[3] = e4; }
1466 Node *midf1 = NULL, *midf2 = NULL;
1467 if (e1 && e3) { midf1 =
nodes.Peek(e1, e3); }
1468 if (e2 && e4) { midf2 =
nodes.Peek(e2, e4); }
1471 MFEM_ASSERT(!(midf1 && midf2),
"incorrectly split face!");
1473 if (!midf1 && !midf2) {
return 0; }
1475 if (midf1) {
return 1; }
1481 for (
int i = 0; i < 8; i++)
1482 if (elem->
node[i] == node) {
return i; }
1484 MFEM_ABORT(
"Node not found.");
1490 for (
int i = 0; i < 8; i++)
1491 if (elem->
node[i]->
id == node_id) {
return i; }
1493 MFEM_ABORT(
"Node not found.");
1499 for (
int i = 0; i < 6; i++)
1501 const int* fv = gi_hex.
faces[i];
1502 if ((a == fv[0] || a == fv[1] || a == fv[2] || a == fv[3]) &&
1503 (b == fv[0] || b == fv[1] || b == fv[2] || b == fv[3]) &&
1504 (c == fv[0] || c == fv[1] || c == fv[2] || c == fv[3]))
1509 MFEM_ABORT(
"Face not found.");
1523 const int* fv = gi_hex.
faces[fi];
1526 for (
int i = 0, j; i < 4; i++)
1528 for (j = 0; j < 4; j++)
1530 if (fv[i] == master[j])
1533 for (
int k = 0; k < mat.
Height(); k++)
1535 mat(k,i) = tmp(k,j);
1540 MFEM_ASSERT(j != 4,
"node not found.");
1550 Face* face =
faces.Peek(v0, v1, v2, v3);
1571 Point mid0(pm(0), pm(1)), mid2(pm(2), pm(3));
1579 else if (split == 2)
1581 Point mid1(pm(1), pm(2)), mid3(pm(3), pm(0));
1596 if (
Dim < 3) {
return; }
1603 MFEM_ASSERT(!elem->
ref_type,
"not a leaf element.");
1606 for (
int j = 0; j < gi.
nf; j++)
1610 for (
int k = 0; k < 4; k++)
1615 Face* face =
faces.Peek(node[0], node[1], node[2], node[3]);
1616 MFEM_ASSERT(face,
"face not found!");
1622 int index = face->
index;
1623 if (index >= processed_faces.
Size())
1625 processed_faces.
SetSize(index + 1, 0);
1627 else if (processed_faces[index])
1631 processed_faces[index] = 1;
1645 TraverseFace(node[0], node[1], node[2], node[3], pm, 0);
1654 for (
int i = sb; i < se; i++)
1669 if (!mid) {
return; }
1671 if (mid->
edge && level > 0)
1678 mat(0,0) = t0, mat(0,1) = t1;
1683 std::swap(mat(0,0), mat(0,1));
1688 double tmid = (t0 + t1) / 2;
1703 MFEM_ASSERT(!elem->
ref_type,
"not a leaf element.");
1706 for (
int j = 0; j < gi.
ne; j++)
1709 const int* ev = gi.
edges[j];
1710 Node* node[2] = { elem->
node[ev[0]], elem->
node[ev[1]] };
1712 Node* edge =
nodes.Peek(node[0], node[1]);
1713 MFEM_ASSERT(edge && edge->
edge,
"edge not found!");
1726 if (index >= processed_edges.
Size())
1728 processed_edges.
SetSize(index + 1, 0);
1730 else if (processed_edges[index])
1734 processed_edges[index] = 1;
1737 double t0 = 0.0, t1 = 1.0;
1738 if (node[0]->vertex->index > node[1]->
vertex->
index)
1754 for (
int i = sb; i < se; i++)
1790 indices.
Append(mid[0]->vertex->index);
1791 indices.
Append(mid[2]->vertex->index);
1798 indices.
Append(mid[1]->vertex->index);
1799 indices.
Append(mid[3]->vertex->index);
1810 int* I =
new int[nrows + 1];
1811 int** JJ =
new int*[nrows];
1820 MFEM_ASSERT(!elem->
ref_type,
"not a leaf element.");
1826 for (
int j = 0; j < gi.
nv; j++)
1828 indices.
Append(node[j]->vertex->index);
1831 for (
int j = 0; j < gi.
ne; j++)
1833 const int* ev = gi.
edges[j];
1837 for (
int j = 0; j < gi.
nf; j++)
1839 const int* fv = gi.
faces[j];
1847 int size = indices.
Size();
1849 JJ[i] =
new int[size];
1850 memcpy(JJ[i], indices.
GetData(), size *
sizeof(int));
1855 for (
int i = 0; i < nrows; i++)
1864 int *J =
new int[nnz];
1866 for (
int i = 0; i < nrows; i++)
1868 int cnt = I[i+1] - I[i];
1869 memcpy(J+nnz, JJ[i], cnt *
sizeof(
int));
1898 MFEM_VERIFY(elem_set.
Size() == nleaves,
"");
1907 for (
int i = 0; i < nleaves; i++)
1913 for (
int j = 0; j < nv; j++)
1926 neighbor_set->
SetSize(nleaves);
1930 for (
int i = 0; i < nleaves; i++)
1936 for (
int j = 0; j < nv; j++)
1941 if (neighbor_set) { (*neighbor_set)[i] = 1; }
1949 static bool sorted_lists_intersect(
const int* a,
const int* b,
int na,
int nb)
1951 if (!na || !nb) {
return false; }
1952 int a_last = a[na-1], b_last = b[nb-1];
1953 if (*b < *a) {
goto l2; }
1955 if (a_last < *b) {
return false; }
1956 while (*a < *b) { a++; }
1957 if (*a == *b) {
return true; }
1959 if (b_last < *a) {
return false; }
1960 while (*b < *a) { b++; }
1961 if (*a == *b) {
return true; }
1969 MFEM_ASSERT(!elem->
ref_type,
"not a leaf.");
1978 for (
int i = 0; i < search_set->
Size(); i++)
1980 Element* testme = (*search_set)[i];
1986 if (sorted_lists_intersect(v1, v2, nv1, nv2))
1988 neighbors.
Append(testme);
2000 for (
int i = 0; i < neighbors.
Size(); i++)
2002 elem_set[neighbors[i]->index] = 2;
2013 for (
int i = 0; i < np; i++)
2015 for (
int j = 0; j < points[0].dim; j++)
2017 point_matrix(j, i) = points[i].coord[j];
2043 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
2044 Point mid67(pm(6), pm(7)), mid45(pm(4), pm(5));
2048 pm(4), mid45, mid67, pm(7)));
2052 mid45, pm(5), pm(6), mid67));
2056 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
2057 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
2061 pm(4), pm(5), mid56, mid74));
2065 mid74, mid56, pm(6), pm(7)));
2069 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2070 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2074 mid04, mid15, mid26, mid37));
2078 pm(4), pm(5), pm(6), pm(7)));
2082 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
2083 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
2084 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
2085 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
2087 Point midf0(mid23, mid12, mid01, mid30);
2088 Point midf5(mid45, mid56, mid67, mid74);
2092 pm(4), mid45, midf5, mid74));
2096 mid45, pm(5), mid56, midf5));
2100 midf5, mid56, pm(6), mid67));
2104 mid74, midf5, mid67, pm(7)));
2108 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
2109 Point mid45(pm(4), pm(5)), mid67(pm(6), pm(7));
2110 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2111 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2113 Point midf1(mid01, mid15, mid45, mid04);
2114 Point midf3(mid23, mid37, mid67, mid26);
2118 mid04, midf1, midf3, mid37));
2122 midf1, mid15, mid26, midf3));
2126 mid45, pm(5), pm(6), mid67));
2130 pm(4), mid45, mid67, pm(7)));
2134 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
2135 Point mid56(pm(5), pm(6)), mid74(pm(7), pm(4));
2136 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2137 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2139 Point midf2(mid12, mid26, mid56, mid15);
2140 Point midf4(mid30, mid04, mid74, mid37);
2144 mid04, mid15, midf2, midf4));
2148 midf4, midf2, mid26, mid37));
2152 pm(4), pm(5), mid56, mid74));
2156 mid74, mid56, pm(6), pm(7)));
2160 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
2161 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
2162 Point mid45(pm(4), pm(5)), mid56(pm(5), pm(6));
2163 Point mid67(pm(6), pm(7)), mid74(pm(7), pm(4));
2164 Point mid04(pm(0), pm(4)), mid15(pm(1), pm(5));
2165 Point mid26(pm(2), pm(6)), mid37(pm(3), pm(7));
2167 Point midf0(mid23, mid12, mid01, mid30);
2168 Point midf1(mid01, mid15, mid45, mid04);
2169 Point midf2(mid12, mid26, mid56, mid15);
2170 Point midf3(mid23, mid37, mid67, mid26);
2171 Point midf4(mid30, mid04, mid74, mid37);
2172 Point midf5(mid45, mid56, mid67, mid74);
2174 Point midel(midf1, midf3);
2178 mid04, midf1, midel, midf4));
2182 midf1, mid15, midf2, midel));
2186 midel, midf2, mid26, midf3));
2190 midf4, midel, midf3, mid37));
2194 pm(4), mid45, midf5, mid74));
2198 mid45, pm(5), mid56, midf5));
2202 midf5, mid56, pm(6), mid67));
2206 mid74, midf5, mid67, pm(7)));
2213 Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
2223 Point mid12(pm(1), pm(2)), mid30(pm(3), pm(0));
2233 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2));
2234 Point mid23(pm(2), pm(3)), mid30(pm(3), pm(0));
2235 Point midel(mid01, mid23);
2252 Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid20(pm(2), pm(0));
2284 MFEM_ABORT(
"You need to call MarkCoarseLevel before calling Refine and "
2285 "GetFineTransforms.");
2299 (
Point(0,0,0),
Point(1,0,0),
Point(1,1,0),
Point(0,1,0),
2300 Point(0,0,1),
Point(1,0,1),
Point(1,1,1),
Point(0,1,1));
2315 MFEM_ABORT(
"Bad geometry.");
2334 MFEM_ASSERT(node != NULL && node->
p1 != node->
p2,
"Invalid edge node.");
2339 if ((n2->
p1 != n2->
p2) && (n1->
id == n2->
p1 || n1->
id == n2->
p2))
2343 if (n2->
edge) {
return n2; }
2347 if ((n1->
p1 != n1->
p2) && (n2->
id == n1->
p1 || n2->
id == n1->
p2))
2351 if (n1->
edge) {
return n1; }
2361 MFEM_ASSERT(node->
edge != NULL,
"(v1, v2) is not an edge.");
2364 return master ? master->
edge->
index : -1;
2373 if (!elem) { elem = face->
elem[1]; }
2374 MFEM_ASSERT(elem,
"Face has no elements?");
2381 for (
int i = 0; i < 4; i++)
2383 node[i] = elem->
node[fv[i]];
2399 if (bdr_attr_is_ess[face->
attribute - 1])
2404 for (
int j = 0; j < 4; j++)
2406 bdr_vertices.
Append(node[j]->vertex->index);
2408 Node* edge =
nodes.Peek(node[j], node[(j+1) % 4]);
2409 MFEM_ASSERT(edge && edge->
edge,
"Edge not found.");
2436 bdr_vertices.
Sort();
2446 if (!mid || !mid->
vertex) {
return 0; }
2451 int& h_level,
int& v_level)
const
2453 int hl1, hl2, vl1, vl2;
2459 h_level = v_level = 0;
2465 h_level = std::max(hl1, hl2);
2466 v_level = std::max(vl1, vl2) + 1;
2472 h_level = std::max(hl1, hl2) + 1;
2473 v_level = std::max(vl1, vl2);
2477 static int max8(
int a,
int b,
int c,
int d,
int e,
int f,
int g,
int h)
2479 return std::max(std::max(std::max(a, b), std::max(c, d)),
2480 std::max(std::max(e, f), std::max(g, h)));
2489 for (
int i = 0; i < gi.
ne; i++)
2491 const int* ev = gi.
edges[i];
2496 for (
int i = 0; i < gi.
nf; i++)
2498 const int* fv = gi.
faces[i];
2499 FaceSplitLevel(node[fv[0]], node[fv[1]], node[fv[2]], node[fv[3]],
2500 flevel[i][1], flevel[i][0]);
2505 splits[0] = max8(flevel[0][0], flevel[1][0], flevel[3][0], flevel[5][0],
2506 elevel[0], elevel[2], elevel[4], elevel[6]);
2508 splits[1] = max8(flevel[0][1], flevel[2][0], flevel[4][0], flevel[5][1],
2509 elevel[1], elevel[3], elevel[5], elevel[7]);
2511 splits[2] = max8(flevel[1][1], flevel[2][1], flevel[3][1], flevel[4][1],
2512 elevel[8], elevel[9], elevel[10], elevel[11]);
2516 splits[0] = std::max(elevel[0], elevel[2]);
2517 splits[1] = std::max(elevel[1], elevel[3]);
2521 splits[0] = std::max(elevel[0], std::max(elevel[1], elevel[2]));
2522 splits[1] = splits[0];
2526 MFEM_ABORT(
"Unsupported element geometry.");
2532 MFEM_VERIFY(max_level >= 1,
"'max_level' must be 1 or greater.");
2543 for (
int k = 0; k <
Dim; k++)
2545 if (splits[k] > max_level)
2547 ref_type |= (1 << k);
2562 if (!refinements.
Size()) {
break; }
2574 if (it->vertex && it->p1 != it->p2) { nv++; }
2581 if (it->vertex && it->p1 != it->p2)
2586 MFEM_ASSERT(p1 && p1->
vertex,
"");
2587 MFEM_ASSERT(p2 && p2->
vertex,
"");
2589 out << it->vertex->index <<
" "
2603 input >>
id >> p1 >> p2;
2604 MFEM_VERIFY(input,
"problem reading vertex parents.");
2607 MFEM_VERIFY(node,
"vertex " <<
id <<
" not found.");
2608 MFEM_VERIFY(
nodes.Peek(p1),
"parent " << p1 <<
" not found.");
2609 MFEM_VERIFY(
nodes.Peek(p2),
"parent " << p2 <<
" not found.");
2612 nodes.Reparent(node, p1, p2);
2618 for (
int i = 0; i < vertices.
Size(); i++)
2621 MFEM_ASSERT(node && node->
vertex,
"");
2623 const double* pos = vertices[i]();
2628 static int ref_type_num_children[8] = {0, 2, 2, 4, 2, 4, 4, 8 };
2631 int &coarse_id)
const
2635 int child_id[8], nch = 0;
2636 for (
int i = 0; i < 8; i++)
2643 MFEM_ASSERT(nch == ref_type_num_children[(
int) elem->
ref_type],
"");
2646 for (
int i = 0; i < nch; i++)
2648 out <<
" " << child_id[i];
2685 int nleaf = leaves.
Size();
2697 if (
Dim == 3 && ref_type != 7) { iso =
false; }
2700 int nch = ref_type_num_children[ref_type];
2701 for (
int i = 0,
id; i < nch; i++)
2704 MFEM_VERIFY(
id >= 0,
"");
2705 MFEM_VERIFY(
id < nleaf ||
id - nleaf < coarse.
Size(),
2706 "coarse element cannot be referenced before it is "
2707 "defined (id=" <<
id <<
").");
2709 Element* &child = (
id < nleaf) ? leaves[
id] : coarse[
id - nleaf];
2711 MFEM_VERIFY(child,
"element " <<
id <<
" cannot have two parents.");
2712 elem->
child[i] = child;
2728 for (
int i = 0; i < coarse.
Size(); i++)
2732 for (
int i = 0; i < leaves.
Size(); i++)
2746 for (
int i = 0; i < 8; i++)
2760 pmsize = pm.
Width() * pm.
Height() *
sizeof(double);
2763 return conforming.capacity() *
sizeof(
MeshId) +
2764 masters.capacity() *
sizeof(
Master) +
2765 slaves.capacity() *
sizeof(
Slave) +
2766 slaves.size() * pmsize;
2771 nelem = nvert = nedges = 0;
2778 if (it->vertex) { nvert++; }
2779 if (it->edge) { nedges++; }
2785 int nelem, nvert, nedges;
2788 return nelem *
sizeof(
Element) +
2790 nedges *
sizeof(
Edge) +
2791 nodes.MemoryUsage() +
2792 faces.MemoryUsage() +
2808 int nelem, nvert, nedges;
2811 std::cout << nelem *
sizeof(
Element) <<
" elements\n"
2812 << nvert *
sizeof(
Vertex) <<
" vertices\n"
2813 << nedges *
sizeof(
Edge) <<
" edges\n";
2815 nodes.PrintMemoryDetail(); std::cout <<
" nodes\n";
2816 faces.PrintMemoryDetail(); std::cout <<
" faces\n";
2818 std::cout <<
root_elements.MemoryUsage() <<
" root_elements\n"
2826 <<
ref_stack.MemoryUsage() <<
" ref_stack\n"
2828 <<
sizeof(*this) <<
" NCMesh" << std::endl;
NCList face_list
lazy-initialized list of faces, see GetFaceList
NCList edge_list
lazy-initialized list of edges, see GetEdgeList
NCMesh(const Mesh *mesh, std::istream *vertex_parents=NULL)
virtual void LimitNCLevel(int max_level)
int Size() const
Logical size of the array.
Element * NewHexahedron(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4, Node *n5, Node *n6, Node *n7, int attr, int fattr0, int fattr1, int fattr2, int fattr3, int fattr4, int fattr5)
void FindNeighbors(const Element *elem, Array< Element * > &neighbors, const Array< Element * > *search_set=NULL)
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
char ref_type
refinement XYZ bit mask (7 = full isotropic)
Table * GetEdgeVertexTable() const
Returns the edge-to-vertex Table (3D)
int index
edge number in the Mesh
Array< Element * > coarse_elements
state of leaf_elements before Refine(), set by MarkCoarseLevel()
virtual int GetNEdges() const =0
Iterator over items contained in the HashTable.
int PrintElements(std::ostream &out, Element *elem, int &coarse_id) const
FineTransform * GetFineTransforms()
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).
Node * PeekAltParents(Node *v1, Node *v2)
void PrintMemoryDetail() const
int GetNBE() const
Returns number of boundary elements.
int index
element number in the Mesh, -1 if refined
virtual int GetNumGhosts() const
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols.
T * GetData()
Returns the data.
int attribute
boundary element attribute, -1 if internal edge (2D)
Data type dense matrix using column-major storage.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
void RefElementNodes(Element *elem)
char geom
Geometry::Type of the element.
static int find_node(Element *elem, Node *node)
int FaceSplitType(Node *v1, Node *v2, Node *v3, Node *v4, Node *mid[4]=NULL) const
int GetNE() const
Returns number of elements.
virtual void ElementSharesFace(Element *elem, Face *face)
const Element * GetFace(int i) const
int index
vertex number in the Mesh
void CountObjects(int &nelem, int &nvert, int &nedges) const
std::vector< MeshId > conforming
Data type quadrilateral element.
void Delete(ItemT *item)
Remove an item from the hash table and also delete the item itself.
Element * parent
parent element, NULL if this is a root element
Vertex * NewVertex(Node *v1, Node *v2)
bool NodeSetY1(Node *node, Node **n)
int spaceDim
dimensions of the elements and the vertex coordinates
Array< int > vertex_nodeId
int attribute
boundary element attribute, -1 if internal face
int GetGeometryType() const
int index
Mesh element number.
const NCList & GetFaceList()
Return the current list of conforming and nonconforming faces.
virtual void OnMeshUpdated(Mesh *mesh)
int Width() const
Returns the number of TYPE II elements (after Finalize() is called).
Element * NewQuadrilateral(Node *n0, Node *n1, Node *n2, Node *n3, int attr, int eattr0, int eattr1, int eattr2, int eattr3)
void DebugNeighbors(Array< char > &elem_set)
void CollectEdgeVertices(Node *v0, Node *v1, Array< int > &indices)
virtual bool IsGhost(const Element *elem) const
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
Data type hexahedron element.
virtual const int * GetEdgeVertices(int) const =0
int num_vertices
width of the table
int index
face number in the Mesh
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 to array, resize if necessary.
Element * elem[2]
up to 2 elements sharing the face
void GetMatrix(DenseMatrix &point_matrix) const
void CheckAnisoFace(Node *v1, Node *v2, Node *v3, Node *v4, Node *mid12, Node *mid34, int level=0)
void RegisterFaces(Element *elem, int *fattr=NULL)
std::vector< Master > masters
virtual void UpdateVertices()
update Vertex::index and vertex_nodeId
void RegisterElement(Element *e)
Element * CopyHierarchy(Element *elem)
void ReorderFacePointMat(Node *v0, Node *v1, Node *v2, Node *v3, Element *elem, DenseMatrix &mat) const
void RefineElement(Element *elem, char ref_type)
void FaceSplitLevel(Node *v1, Node *v2, Node *v3, Node *v4, int &h_level, int &v_level) const
Element(int geom, int attr)
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
virtual void BuildEdgeList()
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.
void CollectLeafElements(Element *elem)
Data type triangle element.
const Element * GetElement(int i) const
virtual void ElementSharesEdge(Element *elem, Edge *edge)
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...
bool NodeSetX1(Node *node, Node **n)
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
static GeomInfo GI[Geometry::NumGeom]
void DeleteHierarchy(Element *elem)
int SpaceDimension() const
void TraverseEdge(Node *v0, Node *v1, double t0, double t1, int level)
bool Iso
true if the mesh only contains isotropic refinements
void DerefineElement(Element *elem)
Array< Node * > boundary_edges
subset of all edges, set by BuildEdgeList
void UnrefEdge(HashTable< Node > &nodes)
void FindSetNeighbors(const Array< char > &elem_set, Array< Element * > *neighbors, Array< char > *neighbor_set=NULL)
std::vector< Slave > slaves
virtual void BuildFaceList()
void ForceRefinement(Node *v1, Node *v2, Node *v3, Node *v4)
void SetVertexPositions(const Array< mfem::Vertex > &vertices)
I/O: Set positions of all vertices (used by mesh loader).
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Element * child[8]
2-8 children (if ref_type != 0)
Array< Element * > leaf_elements
void UpdateLeafElements()
bool NodeSetZ1(Node *node, Node **n)
Node * GetMidEdgeVertexSimple(Node *v1, Node *v2)
void BuildElementToVertexTable()
void UnrefElementNodes(Element *elem)
virtual int GetNFaces(int &nFaceVertices) const =0
void CheckIsoFace(Node *v1, Node *v2, Node *v3, Node *v4, Node *e1, Node *e2, Node *e3, Node *e4, Node *midf)
void SetIJ(int *newI, int *newJ, int newsize=-1)
Node * GetMidFaceVertex(Node *e1, Node *e2, Node *e3, Node *e4)
void CollectFaceVertices(Node *v0, Node *v1, Node *v2, Node *v3, Array< int > &indices)
bool NodeSetZ2(Node *node, Node **n)
void Initialize(const mfem::Element *elem)
bool NodeSetX2(Node *node, Node **n)
void GetMeshComponents(Array< mfem::Vertex > &vertices, Array< mfem::Element * > &elements, Array< mfem::Element * > &boundary) const
Return the basic Mesh arrays for the current finest level.
Node * node[8]
element corners (if ref_type == 0)
Element * NewTriangle(Node *n0, Node *n1, Node *n2, int attr, int eattr0, int eattr1, int eattr2)
virtual int GetNVertices() const =0
void SetAttribute(const int attr)
Set element's attribute.
virtual void AssignLeafIndices()
static int find_hex_face(int a, int b, int c)
virtual const int * GetFaceVertices(int fi) const =0
Array< ElemRefType > ref_stack
stack of scheduled refinements (temporary)
static void find_face_nodes(const Face *face, Node *node[4])
Array< Element * > root_elements
int GetNFaces() const
Return the number of faces in a 3D mesh.
long MemoryUsage() const
Return total number of bytes allocated.
Node * GetMidEdgeVertex(Node *v1, Node *v2)
int EdgeSplitLevel(Node *v1, Node *v2) const
Element * GetSingleElement() const
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.
void TraverseFace(Node *v0, Node *v1, Node *v2, Node *v3, const PointMatrix &pm, int level)
virtual void GetVertices(Array< int > &v) const
Returns the indices of the element's vertices.
void UpdateElementToVertexTable()
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
void CountSplits(Element *elem, int splits[3]) const
void ForgetElement(Element *e)
char ref_type
bit mask of X,Y,Z refinements (bits 0,1,2 respectively)
bool NodeSetY2(Node *node, Node **n)
void LoadVertexParents(std::istream &input)
int CountElements(Element *elem) const
Abstract data type element.
Data type line segment element.
Array< Face * > boundary_faces
subset of all faces, set by BuildFaceList
int rank
processor number (ParNCMesh)
const Element * GetBdrElement(int i) const
virtual int GetType() const =0
Returns element's type.
virtual void Refine(const Array< Refinement > &refinements)
int GetEdgeMaster(int v1, int v2) const
void UnrefVertex(HashTable< Node > &nodes)