258 const std::unordered_map<int,int> &lface_to_boundary_attribute)
260 const int num_codim_1 = mesh.GetNumFaces();
262 if (mesh.Dimension() == 3)
266 mesh.DeleteBoundaryElementToEdge();
268 int NumOfBdrElements = 0;
269 for (
int i = 0; i < num_codim_1; i++)
271 if (mesh.GetFaceInformation(i).IsBoundary())
279 boundary.
Reserve(NumOfBdrElements);
280 be_to_face.
Reserve(NumOfBdrElements);
282 const auto &parent = *mesh.GetParent();
283 const auto &parent_face_ids = mesh.GetParentFaceIDMap();
284 const auto &parent_edge_ids = mesh.GetParentEdgeIDMap();
285 const auto &parent_vertex_ids = mesh.GetParentVertexIDMap();
286 const auto &parent_face_to_be = parent.GetFaceToBdrElMap();
287 const auto &face_to_be = mesh.GetFaceToBdrElMap();
288 int max_bdr_attr = parent.bdr_attributes.Max();
289 for (
int i = 0; i < num_codim_1; i++)
291 auto pfid = [&](
int i)
293 switch (mesh.Dimension())
295 case 3:
return parent_face_ids[i];
296 case 2:
return parent_edge_ids[i];
297 case 1:
return parent_vertex_ids[i];
302 if (mesh.GetFaceInformation(i).IsBoundary()
303 && (face_to_be.IsEmpty() || face_to_be[i] == -1))
305 auto * be = mesh.GetFace(i)->Duplicate(&mesh);
309 int pbeid = parent_face_to_be[pfid(i)];
312 be->SetAttribute(parent.GetBdrAttribute(pbeid));
316 auto ghost_attr = lface_to_boundary_attribute.find(pfid(i));
317 int battr = ghost_attr != lface_to_boundary_attribute.end() ?
318 ghost_attr->second : max_bdr_attr + 1;
319 be->SetAttribute(battr);
324 auto ghost_attr = lface_to_boundary_attribute.find(pfid(i));
325 int battr = ghost_attr != lface_to_boundary_attribute.end() ?
326 ghost_attr->second : max_bdr_attr + 1;
327 be->SetAttribute(battr);
337 int InteriorBdrElems = 0;
338 for (
int i=0; i<parent.GetNBE(); i++)
340 const int parentFaceIdx = parent.GetBdrElementFaceIndex(i);
341 const int submeshFaceIdx =
342 mesh.Dimension() == 3 ?
343 mesh.GetSubMeshFaceFromParent(parentFaceIdx) :
344 mesh.GetSubMeshEdgeFromParent(parentFaceIdx);
346 if (submeshFaceIdx == -1) {
continue; }
347 if (mesh.GetFaceInformation(submeshFaceIdx).IsBoundary()) {
continue; }
351 if (InteriorBdrElems > 0)
353 NumOfBdrElements += InteriorBdrElems;
354 boundary.
Reserve(NumOfBdrElements);
355 be_to_face.
Reserve(NumOfBdrElements);
358 for (
int i = 0; i < parent.GetNBE(); i++)
360 const int parentFaceIdx = parent.GetBdrElementFaceIndex(i);
361 const int submeshFaceIdx =
362 mesh.Dimension() == 3 ?
363 mesh.GetSubMeshFaceFromParent(parentFaceIdx) :
364 mesh.GetSubMeshEdgeFromParent(parentFaceIdx);
366 if (submeshFaceIdx == -1) {
continue; }
367 if (mesh.GetFaceInformation(submeshFaceIdx).IsBoundary())
370 auto * be = mesh.GetFace(submeshFaceIdx)->Duplicate(&mesh);
371 be->SetAttribute(parent.GetBdrAttribute(i));
373 be_to_face.
Append(submeshFaceIdx);
377 mesh.AddBdrElements(boundary, be_to_face);
431 auto &parent_node_ids = submesh.parent_node_ids_;
432 auto &parent_element_ids = submesh.parent_element_ids_;
433 auto &parent_to_submesh_node_ids = submesh.parent_to_submesh_node_ids_;
434 auto &parent_to_submesh_element_ids = submesh.parent_to_submesh_element_ids_;
435 const auto &parent = *submesh.GetParent();
440 std::map<FaceNodes, int> pnodes_new_elem;
441 std::set<int> new_nodes;
442 parent_to_submesh_element_ids.reserve(parent.GetNumFaces());
443 parent_element_ids.Reserve(parent.GetNumFaces());
446 const auto &face_list =
const_cast<NCMesh&
>(
static_cast<const NCMesh&
>
450 for (
int i = 0, ipe = 0; ipe < parent.GetNumFaces(); i++)
452 const auto &face = parent.GetFace(i);
453 if (face.Unused()) {
continue; }
459 FaceNodes fn{submesh.parent_->FindFaceNodes(face)};
460 if (pnodes_new_elem.find(fn) != pnodes_new_elem.end()) {
continue; }
466 MFEM_ASSERT(face.elem[0] < 0 || face.elem[1] < 0,
467 "Internal nonconforming boundaries are not reliably supported yet.");
468 auto face_geom = FaceGeomFromNodes(fn.nodes);
469 int new_elem_id = submesh.AddElement(face_geom, face.attribute);
472 submesh.elements[new_elem_id].rank = [&parent, &face]()
474 auto rank0 = face.elem[0] >= 0 ? parent.GetElement(face.elem[0]).rank : -1;
475 auto rank1 = face.elem[1] >= 0 ? parent.GetElement(face.elem[1]).rank : -1;
476 if (rank0 < 0) {
return rank1; }
477 if (rank1 < 0) {
return rank0; }
478 return rank0 < rank1 ? rank0 : rank1;
480 pnodes_new_elem[fn] = new_elem_id;
481 parent_element_ids.Append(i);
482 parent_to_submesh_element_ids[i] = new_elem_id;
486 std::copy(fn.nodes.begin(), fn.nodes.end(), submesh.elements[new_elem_id].node);
487 for (
auto x : fn.nodes)
492 auto &gi = submesh.GI[face_geom];
493 gi.InitGeom(face_geom);
494 for (
int e = 0; e < gi.ne; e++)
496 new_nodes.insert(submesh.ParentNodes().FindId(fn.nodes[gi.edges[e][0]],
497 fn.nodes[gi.edges[e][1]]));
512 bool root_path_is_ambiguous=
false;
516 int child = submesh.parent_->ParentFaceNodes(fn.nodes);
517 if (tri_face && child == 3)
521 root_path_is_ambiguous =
true;
526 submesh.elements[new_elem_id].parent = -1;
529 auto pelem = pnodes_new_elem.find(fn);
530 bool new_parent = pelem == pnodes_new_elem.end();
534 int pelem_id = submesh.AddElement(FaceGeomFromNodes(fn.nodes), face.attribute);
535 pelem = pnodes_new_elem.emplace(fn, pelem_id).first;
536 auto parent_face_id = submesh.ParentFaces().FindId(fn.nodes[0], fn.nodes[1],
539 parent_element_ids.Append(parent_face_id);
552 if (!root_path_is_ambiguous &&
553 !std::equal(fn.nodes.begin(), fn.nodes.end(), pelem->first.nodes.begin()))
556 auto pelem_id = pelem->second;
557 MFEM_ASSERT(!submesh.elements[pelem_id].IsLeaf(), pelem_id);
560 pnodes_new_elem.erase(pelem->first);
561 pelem = pnodes_new_elem.emplace(fn, pelem_id).first;
565 submesh.elements[pelem->second].ref_type = submesh.Dim == 2 ?
Refinement::XY :
567 submesh.elements[new_elem_id].parent = pelem->second;
572 if (!new_parent && !fix_parent) {
break; }
574 new_elem_id = pelem->second;
577 parent_element_ids.ShrinkToFit();
578 MFEM_ASSERT(parent_element_ids.Size() == submesh.elements.Size(),
579 parent_element_ids.Size() <<
' ' << submesh.elements.Size());
584 for (
const auto & fn_elem : pnodes_new_elem)
586 auto fn = fn_elem.first;
587 const auto &child_elem = submesh.elements[fn_elem.second];
588 if (child_elem.parent == -1) {
continue; }
589 int child = submesh.parent_->ParentFaceNodes(fn.nodes);
590 MFEM_ASSERT(pnodes_new_elem[fn] == child_elem.parent,
591 pnodes_new_elem[fn] <<
' ' << child_elem.parent);
592 MFEM_ASSERT(submesh.elements[child_elem.parent].ref_type !=
char(0),
593 int(submesh.elements[child_elem.parent].ref_type));
594 submesh.elements[child_elem.parent].child[child] = fn_elem.second;
609 (pnodes_new_elem.size()));
610 for (
const auto &kv : pnodes_new_elem)
612 new_elem_to_parent_face_nodes[kv.second] = kv.first;
614 pnodes_new_elem.clear();
617 parent_node_ids.Reserve(
static_cast<int>(new_nodes.size()));
618 parent_to_submesh_node_ids.reserve(new_nodes.size());
619 for (
auto n : new_nodes)
622 auto new_node_id = node_ids.
Get(n, new_node);
623 MFEM_ASSERT(new_node,
"!");
624 submesh.nodes.Alloc(new_node_id, new_node_id, new_node_id);
625 parent_node_ids.Append(n);
626 parent_to_submesh_node_ids[n] = new_node_id;
628 parent_node_ids.ShrinkToFit();
633 auto comp_elements = [&](
int l,
int r)
635 const auto &elem_l = submesh.elements[l];
636 const auto &elem_r = submesh.elements[r];
637 if (elem_l.parent == elem_r.parent)
639 const auto &fnl = new_elem_to_parent_face_nodes[l].nodes;
640 const auto &fnr = new_elem_to_parent_face_nodes[r].nodes;
641 return std::lexicographical_compare(fnl.begin(), fnl.end(), fnr.begin(),
646 return elem_l.parent < elem_r.parent;
650 auto parental_sorted = [&]()
652 std::iota(indices.
begin(), indices.
end(), 0);
653 return std::is_sorted(indices.
begin(), indices.
end(), comp_elements);
656 Array<int> new_to_old(submesh.elements.Size()),
657 old_to_new(submesh.elements.Size());
658 while (!parental_sorted())
662 new_to_old.SetSize(submesh.elements.Size()),
663 old_to_new.
SetSize(submesh.elements.Size());
664 std::iota(new_to_old.begin(), new_to_old.end(), 0);
665 std::stable_sort(new_to_old.begin(), new_to_old.end(), comp_elements);
667 for (
int i = 0; i < submesh.elements.Size(); i++)
669 old_to_new[new_to_old[i]] = i;
673 Permute(std::move(new_to_old), submesh.elements, parent_element_ids,
674 new_elem_to_parent_face_nodes);
675 parent_to_submesh_element_ids.clear();
676 for (
int i = 0; i < parent_element_ids.Size(); i++)
678 if (parent_element_ids[i] == -1) {
continue;}
679 parent_to_submesh_element_ids[parent_element_ids[i]] = i;
683 for (
auto &elem : submesh.elements)
688 elem.rank = std::numeric_limits<int>::max();
691 elem.child[c] = old_to_new[elem.child[c]];
692 elem.rank = std::min(elem.rank, submesh.elements[elem.child[c]].rank);
695 elem.parent = elem.parent == -1 ? -1 : old_to_new[elem.parent];
700 for (
auto &elem : submesh.elements)
705 auto &gi = submesh.GI[elem.Geom()];
706 gi.InitGeom(elem.Geom());
707 for (
int e = 0; e < gi.ne; e++)
709 const int pid = submesh.ParentNodes().FindId(
710 elem.node[gi.edges[e][0]], elem.node[gi.edges[e][1]]);
711 MFEM_ASSERT(pid >= 0,
712 elem.node[gi.edges[e][0]] <<
' ' << elem.node[gi.edges[e][1]]);
713 auto submesh_node_id = node_ids.
Get(pid, new_id);
714 MFEM_ASSERT(!new_id,
"!");
715 submesh.nodes[submesh_node_id].edge_refc++;
717 for (
int n = 0; n < gi.nv; n++)
719 MFEM_ASSERT(parent_to_submesh_node_ids.find(elem.node[n]) !=
720 parent_to_submesh_node_ids.end(),
"!");
721 elem.node[n] = parent_to_submesh_node_ids[elem.node[n]];
722 submesh.nodes[elem.node[n]].vert_refc++;
725 for (
int f = 0;
f < gi.nf;
f++)
727 auto *face = submesh.faces.Get(
728 elem.node[gi.faces[
f][0]],
729 elem.node[gi.faces[
f][1]],
730 elem.node[gi.faces[
f][2]],
731 elem.node[gi.faces[
f][3]]);
732 face->attribute = -1;
751 auto &parent_node_ids = submesh.parent_node_ids_;
752 auto &parent_element_ids = submesh.parent_element_ids_;
753 auto &parent_to_submesh_node_ids = submesh.parent_to_submesh_node_ids_;
754 auto &parent_to_submesh_element_ids = submesh.parent_to_submesh_element_ids_;
755 const auto &parent = *submesh.GetParent();
758 parent_to_submesh_element_ids.reserve(parent.GetNumElements());
759 std::set<int> new_nodes;
760 for (
int ipe = 0; ipe < parent.GetNumElements(); ipe++)
762 const auto& pe = parent.GetElement(ipe);
764 const int elem_id = submesh.AddElement(pe);
765 auto &el = submesh.elements[elem_id];
766 parent_element_ids.Append(ipe);
767 parent_to_submesh_element_ids[ipe] = elem_id;
768 if (!pe.IsLeaf()) {
continue; }
769 const auto gi = submesh.GI[pe.Geom()];
770 for (
int n = 0; n < gi.nv; n++)
772 new_nodes.insert(el.node[n]);
774 for (
int e = 0; e < gi.ne; e++)
776 new_nodes.insert(submesh.ParentNodes().FindId(el.node[gi.edges[e][0]],
777 el.node[gi.edges[e][1]]));
781 parent_node_ids.Reserve(
static_cast<int>(new_nodes.size()));
782 parent_to_submesh_node_ids.reserve(new_nodes.size());
783 for (
const auto &n : new_nodes)
786 auto new_node_id = node_ids.
Get(n, new_node);
787 MFEM_ASSERT(new_node,
"!");
788 submesh.nodes.Alloc(new_node_id, new_node_id, new_node_id);
789 parent_node_ids.Append(n);
790 parent_to_submesh_node_ids[n] = new_node_id;
795 for (
auto &el : submesh.elements)
799 const auto gi = submesh.GI[el.Geom()];
802 for (
int n = 0; n < gi.nv; n++)
805 el.node[n] = node_ids.
Get(el.node[n], new_id);
806 MFEM_ASSERT(new_id ==
false,
"Should not be new.");
807 submesh.nodes[el.node[n]].vert_refc++;
809 for (
int e = 0; e < gi.ne; e++)
811 const int pid = submesh.ParentNodes().FindId(
812 parent_node_ids[el.node[gi.edges[e][0]]],
813 parent_node_ids[el.node[gi.edges[e][1]]]);
814 MFEM_ASSERT(pid >= 0,
"Edge not found");
815 auto submesh_node_id = node_ids.
Get(pid, new_id);
816 MFEM_ASSERT(new_id ==
false,
"Should not be new.");
817 submesh.nodes[submesh_node_id].edge_refc++;
819 for (
int f = 0;
f < gi.nf;
f++)
821 const int *fv = gi.faces[
f];
822 const int pid = submesh.ParentFaces().FindId(
823 parent_node_ids[el.node[fv[0]]],
824 parent_node_ids[el.node[fv[1]]],
825 parent_node_ids[el.node[fv[2]]],
826 el.node[fv[3]] >= 0 ? parent_node_ids[el.node[fv[3]]]: - 1);
827 MFEM_ASSERT(pid >= 0,
"Face not found");
828 const int id = submesh.faces.GetId(
829 el.node[fv[0]], el.node[fv[1]], el.node[fv[2]], el.node[fv[3]]);
830 submesh.faces[id].attribute = submesh.ParentFaces()[pid].attribute;
838 el.child[i] = parent_to_submesh_element_ids[el.child[i]];
841 el.parent = el.parent < 0 ? el.parent
842 : parent_to_submesh_element_ids.at(el.parent);