21 #include "libmesh/boundary_info.h" 22 #include "libmesh/ghosting_functor.h" 23 #include "libmesh/ghost_point_neighbors.h" 24 #include "libmesh/unstructured_mesh.h" 25 #include "libmesh/libmesh_logging.h" 26 #include "libmesh/elem.h" 27 #include "libmesh/mesh_tools.h" 28 #include "libmesh/parallel.h" 29 #include "libmesh/remote_elem.h" 30 #include "libmesh/namebased_io.h" 31 #include "libmesh/partitioner.h" 32 #include "libmesh/enum_order.h" 33 #include "libmesh/mesh_communication.h" 34 #include "libmesh/enum_to_string.h" 35 #include "libmesh/mesh_serializer.h" 36 #include "libmesh/utility.h" 38 #ifdef LIBMESH_HAVE_NANOFLANN 39 #include "libmesh/nanoflann.hpp" 48 #include <unordered_map> 56 std::map<std::vector<dof_id_type>,
Node *>::iterator
57 map_hi_order_node(
unsigned int hon,
59 std::map<std::vector<dof_id_type>,
Node *> & adj_vertices_to_ho_nodes)
66 const unsigned int n_adjacent_vertices =
69 std::vector<dof_id_type> adjacent_vertices_ids(n_adjacent_vertices);
71 for (
unsigned int v=0; v<n_adjacent_vertices; v++)
72 adjacent_vertices_ids[v] =
81 std::sort(adjacent_vertices_ids.begin(),
82 adjacent_vertices_ids.end());
86 return adj_vertices_to_ho_nodes.try_emplace(adjacent_vertices_ids,
nullptr).first;
89 void transfer_elem(
Elem & lo_elem,
90 std::unique_ptr<Elem> hi_elem,
91 #ifdef LIBMESH_ENABLE_UNIQUE_ID
96 std::map<std::vector<dof_id_type>,
Node *> & adj_vertices_to_ho_nodes,
97 std::unordered_map<
Elem *, std::vector<Elem *>> & exterior_children_of)
99 libmesh_assert_equal_to (lo_elem.
n_vertices(), hi_elem->n_vertices());
112 const unsigned int hon_begin = lo_elem.
n_nodes();
113 const unsigned int hon_end = hi_elem->n_nodes();
115 for (
unsigned int hon=hon_begin; hon<hon_end; hon++)
117 auto pos = map_hi_order_node(hon, *hi_elem, adj_vertices_to_ho_nodes);
122 const auto & adjacent_vertices_ids = pos->first;
131 Point new_location = 0;
132 for (
dof_id_type vertex_id : adjacent_vertices_ids)
135 new_location /=
static_cast<Real>(adjacent_vertices_ids.size());
168 #ifdef LIBMESH_ENABLE_UNIQUE_ID 170 max_new_nodes_per_elem * lo_elem.
id() +
182 pos->second = hi_node;
184 hi_elem->set_node(hon) = hi_node;
189 Node * hi_node = pos->second;
193 hi_elem->set_node(hon) = hi_node;
208 chosen_pid == my_pid)
230 libmesh_assert_equal_to (neigh->
level(), 0);
238 hi_elem->set_neighbor(s, neigh);
251 if (
auto parent_exterior_it = exterior_children_of.find(interior_p);
252 parent_exterior_it != exterior_children_of.end())
254 auto & exteriors = parent_exterior_it->second;
256 if (exteriors[i] == &lo_elem)
258 exteriors[i] = hi_elem.get();
267 if (
auto exterior_it = exterior_children_of.find(&lo_elem);
268 exterior_it != exterior_children_of.end())
270 for (
Elem * exterior_elem : exterior_it->second)
296 hi_elem->set_id(lo_elem.
id());
297 #ifdef LIBMESH_ENABLE_UNIQUE_ID 298 hi_elem->set_unique_id(lo_elem.
unique_id());
300 hi_elem->processor_id() = lo_pid;
304 hi_elem->add_extra_integers(nei);
305 for (
unsigned int i=0; i != nei; ++i)
316 template <
typename ElemTypeConverter>
320 const unsigned int max_new_nodes_per_elem,
321 const ElemTypeConverter & elem_type_converter)
357 auto is_higher_order = [&elem_type_converter](
const Elem * elem) {
359 ElemType new_type = elem_type_converter(old_type);
360 return old_type == new_type;
363 bool already_higher_order =
364 std::all_of(range.
begin(), range.
end(), is_higher_order);
368 if (already_higher_order)
386 std::map<std::vector<dof_id_type>,
Node *> adj_vertices_to_ho_nodes;
394 std::unordered_map<Elem *, std::vector<Elem *>> exterior_children_of;
402 #ifdef LIBMESH_ENABLE_UNIQUE_ID 413 n_partitioned_elem = 0;
429 auto track_if_necessary = [&adj_vertices_to_ho_nodes,
430 &exterior_children_of,
431 &elem_type_converter](
Elem * elem) {
434 if (elem->default_order() !=
FIRST)
435 for (
unsigned int hon :
make_range(elem->n_vertices(), elem->n_nodes()))
437 auto pos = map_hi_order_node(hon, *elem, adj_vertices_to_ho_nodes);
438 pos->second = elem->node_ptr(hon);
441 const ElemType old_type = elem->type();
442 const ElemType new_type = elem_type_converter(old_type);
443 if (old_type != new_type)
444 exterior_children_of.emplace(elem, std::vector<Elem *>());
450 if (range.
begin() ==
mesh.elements_begin() &&
451 range.
end() ==
mesh.elements_end())
453 for (
auto & elem : range)
454 track_if_necessary(elem);
461 point_neighbor_finder(range.
begin(), range.
end(),
463 point_neighbor_elements);
465 for (
auto & [elem, coupling_map] : point_neighbor_elements)
468 track_if_necessary(const_cast<Elem *>(elem));
476 for (
auto & elem :
mesh.element_ptr_range())
477 if (
auto exterior_map_it = exterior_children_of.find(elem->interior_parent());
478 exterior_map_it != exterior_children_of.end())
479 exterior_map_it->second.push_back(elem);
487 for (
auto & lo_elem : range)
492 const ElemType new_type = elem_type_converter(old_type);
494 if (old_type == new_type)
498 libmesh_assert_equal_to (lo_elem->
level(), 0);
501 ++n_unpartitioned_elem;
503 ++n_partitioned_elem;
511 libmesh_assert_equal_to (lo_elem->
n_vertices(), ho_elem->n_vertices());
517 for (
unsigned int v=0, lnn=lo_elem->
n_nodes(); v < lnn; v++)
518 ho_elem->set_node(v) = lo_elem->
node_ptr(v);
520 transfer_elem(*lo_elem, std::move(ho_elem),
521 #ifdef LIBMESH_ENABLE_UNIQUE_ID
522 max_unique_id, max_new_nodes_per_elem,
524 mesh, adj_vertices_to_ho_nodes,
525 exterior_children_of);
529 adj_vertices_to_ho_nodes.clear();
531 #ifdef LIBMESH_ENABLE_UNIQUE_ID 545 dof_id_type max_unpartitioned_elem = n_unpartitioned_elem;
547 if (max_unpartitioned_elem)
555 libmesh_not_implemented();
587 const std::vector<std::pair<Point, dof_id_type>>
_nodes;
606 libmesh_assert_less (
idx,
_nodes.size());
607 libmesh_assert_less (
dim, 3);
611 if (
dim==0)
return p(0);
612 if (
dim==1)
return p(1);
619 template <
class BBOX>
644 const bool skip_find_neighbors,
648 #ifdef LIBMESH_ENABLE_UNIQUE_ID
652 std::unordered_map<subdomain_id_type, subdomain_id_type> *
655 LOG_SCOPE(
"copy_nodes_and_elements()",
"UnstructuredMesh");
657 std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
660 const unsigned int n_old_node_ints = extra_int_maps.second.size(),
662 n_old_elem_ints = extra_int_maps.first.size(),
678 MeshTools::libmesh_assert_valid_procids<Node>(other_mesh);
686 for (
const auto & oldn : other_mesh.node_ptr_range())
689 (wrap_proc_ids ? oldn->processor_id() % this->
n_processors() : oldn->processor_id());
694 oldn->id() + node_id_offset,
698 for (
unsigned int i = 0; i != n_old_node_ints; ++i)
699 newn->set_extra_integer(extra_int_maps.second[i],
700 oldn->get_extra_integer(i));
702 #ifdef LIBMESH_ENABLE_UNIQUE_ID 703 newn->set_unique_id(oldn->unique_id() + unique_id_offset);
714 typedef std::unordered_map<const Elem *, Elem *> map_type;
715 map_type old_elems_to_new_elems, ip_map;
718 for (
const auto & old : other_mesh.element_ptr_range())
722 this->
elem_ptr(old->parent()->id() + element_id_offset) :
725 el->set_parent(newparent);
730 auto remapping_it = id_remapping->find(sbd_id);
731 if (remapping_it != id_remapping->end())
732 sbd_id = remapping_it->second;
734 el->subdomain_id() = sbd_id;
738 if (el->dim() < other_mesh.
mesh_dimension() && old->interior_parent())
739 ip_map[old] = el.get();
741 #ifdef LIBMESH_ENABLE_AMR 742 if (old->has_children())
743 for (
unsigned int c = 0, nc = old->n_children(); c != nc; ++c)
745 el->add_child(const_cast<RemoteElem *>(
remote_elem), c);
750 unsigned int oldc = old->parent()->which_child_am_i(old);
755 el->set_refinement_flag(old->refinement_flag());
759 el->hack_p_level(old->p_level());
761 el->set_p_refinement_flag(old->p_refinement_flag());
762 #endif // #ifdef LIBMESH_ENABLE_AMR 765 for (
auto i : el->node_index_range())
767 this->
node_ptr(old->node_id(i) + node_id_offset);
771 (wrap_proc_ids ? old->processor_id() % this->
n_processors() : old->processor_id());
774 el->set_id(old->id() + element_id_offset);
776 el->add_extra_integers(n_new_elem_ints);
777 for (
unsigned int i = 0; i != n_old_elem_ints; ++i)
778 el->set_extra_integer(extra_int_maps.first[i],
779 old->get_extra_integer(i));
781 #ifdef LIBMESH_ENABLE_UNIQUE_ID 782 el->set_unique_id(old->unique_id() + unique_id_offset);
786 if (!skip_find_neighbors)
788 for (
auto s : old->side_index_range())
790 el->set_neighbor(s, const_cast<RemoteElem *>(
remote_elem));
796 old_elems_to_new_elems[old] = new_el;
800 for (
auto & elem_pair : ip_map)
802 this->
elem_ptr(elem_pair.first->interior_parent()->id() + element_id_offset));
805 if (skip_find_neighbors)
809 for (
const auto & old_elem : other_mesh.element_ptr_range())
811 Elem * new_elem = old_elems_to_new_elems[old_elem];
812 for (
auto s : old_elem->side_index_range())
815 Elem * new_neighbor = old_elems_to_new_elems[old_neighbor];
822 #ifdef LIBMESH_ENABLE_UNIQUE_ID 862 const bool reset_current_list)
870 parallel_object_only();
872 LOG_SCOPE(
"find_neighbors()",
"Mesh");
875 if (reset_current_list)
876 for (
const auto & e : this->element_ptr_range())
877 for (
auto s : e->side_index_range())
878 if (e->neighbor_ptr(s) !=
remote_elem || reset_remote_elements)
879 e->set_neighbor(s,
nullptr);
887 typedef std::pair<Elem *, unsigned char> val_type;
888 typedef std::unordered_multimap<key_type, val_type> map_type;
891 map_type side_to_elem_map;
894 std::unique_ptr<Elem> my_side, their_side;
896 for (
const auto & element : this->element_ptr_range())
898 for (
auto ms : element->side_index_range())
904 if (element->neighbor_ptr(ms) ==
nullptr ||
910 const dof_id_type key = element->low_order_key(ms);
913 auto bounds = side_to_elem_map.equal_range(key);
917 if (bounds.first != bounds.second)
920 element->side_ptr(my_side, ms);
923 while (bounds.first != bounds.second)
926 Elem * neighbor = bounds.first->second.first;
929 const unsigned int ns = bounds.first->second.second;
941 if ((*my_side == *their_side) &&
942 (element->level() == neighbor->
level()))
950 if (element->subactive() ==
955 element->set_neighbor (ms,neighbor);
958 else if (element->subactive())
960 element->set_neighbor(ms,neighbor);
966 side_to_elem_map.erase (bounds.first);
978 side_to_elem_map.emplace
979 (key, std::make_pair(element, cast_int<unsigned char>(ms)));
985 #ifdef LIBMESH_ENABLE_AMR 1015 for (
unsigned int level = 1; level <
n_levels; ++level)
1017 for (
auto & current_elem :
as_range(level_elements_begin(level),
1018 level_elements_end(level)))
1025 for (
auto s : current_elem->side_index_range())
1027 if (current_elem->neighbor_ptr(s) ==
nullptr ||
1044 (neigh->
level()+1) == current_elem->level())))
1050 bool neigh_has_remote_children =
false;
1053 neigh_has_remote_children =
true;
1058 if (current_elem->active())
1059 libmesh_assert_not_equal_to (current_elem->processor_id(),
1067 else if (neigh && (current_elem->subactive() &&
1080 bool found_neigh =
false;
1081 for (
unsigned int c = 0, nc = neigh->
n_children();
1082 !found_neigh && c != nc; ++c)
1107 if ((!neigh->
active()) && (!current_elem->subactive()))
1111 libMesh::err <<
"Bad element ID = " << current_elem->id()
1112 <<
", Side " << s <<
", Bad neighbor ID = " << neigh->
id() << std::endl;
1113 libMesh::err <<
"Bad element proc_ID = " << current_elem->processor_id()
1114 <<
", Bad neighbor proc_ID = " << neigh->
processor_id() << std::endl;
1115 libMesh::err <<
"Bad element size = " << current_elem->hmin()
1116 <<
", Bad neighbor size = " << neigh->
hmin() << std::endl;
1117 libMesh::err <<
"Bad element center = " << current_elem->vertex_average()
1118 <<
", Bad neighbor center = " << neigh->
vertex_average() << std::endl;
1120 << (current_elem->active()?
"Active":
"Ancestor")
1121 <<
" Element at level " 1122 << current_elem->level() << std::endl;
1124 << (parent->
active()?
"active":
1125 (parent->
subactive()?
"subactive":
"ancestor"))
1127 << (neigh->
subactive()?
"subactive":
"ancestor")
1128 <<
" neighbor at level " << neigh->
level()
1131 libmesh_error_msg(
"Problematic mesh written to bad_mesh.gmv.");
1139 if (current_elem->dim() >= LIBMESH_DIM)
1143 current_elem->set_interior_parent(
nullptr);
1171 current_elem->set_interior_parent
1176 bool child_contains_our_nodes =
true;
1177 for (
auto & n : current_elem->node_ref_range())
1179 bool child_contains_this_node =
false;
1180 for (
auto & cn : child.node_ref_range())
1181 if (cn.absolute_fuzzy_equals
1182 (n, node_tolerance))
1184 child_contains_this_node =
true;
1187 if (!child_contains_this_node)
1189 child_contains_our_nodes =
false;
1193 if (child_contains_our_nodes)
1195 current_elem->set_interior_parent(&child);
1211 !reset_remote_elements);
1220 bool skip_renumber_nodes_and_elements,
1221 bool skip_find_neighbors)
1229 if (
name.rfind(
".gmv") ==
name.size() - 4)
1234 if (skip_renumber_nodes_and_elements)
1237 libmesh_deprecated();
1252 LOG_SCOPE(
"write()",
"Mesh");
1260 const std::vector<Number> & v,
1261 const std::vector<std::string> & vn)
1263 LOG_SCOPE(
"write()",
"Mesh");
1285 <<
"mesh for a processor id (=" 1287 <<
") greater than " 1288 <<
"the number of processors available for " 1289 <<
"the calculation. (=" 1297 this->active_pid_elements_begin(pid),
1298 this->active_pid_elements_end(pid));
1325 libmesh_assert_not_equal_to (this->
n_nodes(), 0);
1326 libmesh_assert_not_equal_to (this->
n_elem(), 0);
1329 std::vector<boundary_id_type> bc_ids;
1335 for (
const auto & old_elem :
as_range(it, it_end))
1339 auto uelem = old_elem->disconnected_clone();
1344 for (
auto n : old_elem->node_index_range())
1346 const dof_id_type this_node_id = old_elem->node_id(n);
1354 old_elem->node_ptr(n)->processor_id());
1357 for (
unsigned int i = 0; i != n_node_ints; ++i)
1360 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1370 for (
auto s : old_elem->side_index_range())
1383 #ifdef LIBMESH_ENABLE_AMR 1386 LOG_SCOPE (
"contract()",
"Mesh");
1389 bool mesh_changed =
false;
1392 for (
const auto & elem : this->element_ptr_range())
1393 libmesh_assert(elem->active() || elem->subactive() || elem->ancestor());
1397 for (
auto & elem : this->element_ptr_range())
1400 if (elem->subactive())
1414 mesh_changed =
true;
1441 return mesh_changed;
1443 #endif // #ifdef LIBMESH_ENABLE_AMR 1449 LOG_SCOPE(
"all_first_order()",
"Mesh");
1454 std::vector<bool> node_touched_by_me(this->
max_node_id(),
false);
1459 for (
auto & so_elem : element_ptr_range())
1469 (so_elem->type()), so_elem->parent());
1471 const unsigned short n_sides = so_elem->n_sides();
1473 for (
unsigned short s=0; s != n_sides; ++s)
1477 #ifdef LIBMESH_ENABLE_AMR 1481 if (so_elem->has_children())
1482 for (
unsigned int c = 0, nc = so_elem->n_children(); c != nc; ++c)
1493 if (so_elem->parent())
1496 so_elem->parent()->which_child_am_i(so_elem);
1508 libmesh_assert_equal_to (lo_elem->
n_vertices(), so_elem->n_vertices());
1515 for (
unsigned int v=0, snv=so_elem->n_vertices(); v < snv; v++)
1517 lo_elem->
set_node(v) = so_elem->node_ptr(v);
1518 node_touched_by_me[lo_elem->
node_id(v)] =
true;
1525 for (
unsigned short s=0; s != n_sides; s++)
1545 lo_elem->
set_id(so_elem->id());
1546 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1552 const unsigned int nei = so_elem->n_extra_integers();
1554 for (
unsigned int i=0; i != nei; ++i)
1565 for (
const auto & node : this->node_ptr_range())
1566 if (!node_touched_by_me[node->id()])
1586 const bool full_ordered)
1588 LOG_SCOPE(
"all_second_order_range()",
"Mesh");
1595 unsigned int max_new_nodes_per_elem;
1611 max_new_nodes_per_elem = 3 - 2;
1613 (1.5*static_cast<double>(this->
n_nodes())));
1621 max_new_nodes_per_elem = 9 - 4;
1623 (2*static_cast<double>(this->
n_nodes())));
1634 max_new_nodes_per_elem = 27 - 8;
1636 (2.5*static_cast<double>(this->
n_nodes())));
1641 libmesh_error_msg(
"Unknown mesh dimension " << this->
mesh_dimension());
1645 all_increased_order_range(*
this, range, max_new_nodes_per_elem,
1655 LOG_SCOPE(
"all_complete_order()",
"Mesh");
1662 unsigned int max_new_nodes_per_elem;
1678 max_new_nodes_per_elem = 3 - 2;
1680 (1.5*static_cast<double>(this->
n_nodes())));
1689 max_new_nodes_per_elem = 9 - 4;
1691 (2*static_cast<double>(this->
n_nodes())));
1703 max_new_nodes_per_elem = 27 - 8;
1705 (2.5*static_cast<double>(this->
n_nodes())));
1710 libmesh_error_msg(
"Unknown mesh dimension " << this->
mesh_dimension());
1714 all_increased_order_range(*
this, range, max_new_nodes_per_elem,
1726 bool clear_stitched_boundary_ids,
1728 bool use_binary_search,
1729 bool enforce_all_nodes_match_on_boundaries,
1730 bool merge_boundary_nodes_all_or_nothing,
1731 bool remap_subdomain_ids)
1733 LOG_SCOPE(
"stitch_meshes()",
"UnstructuredMesh");
1735 this_mesh_boundary_id,
1736 other_mesh_boundary_id,
1738 clear_stitched_boundary_ids,
1741 enforce_all_nodes_match_on_boundaries,
1743 merge_boundary_nodes_all_or_nothing,
1744 remap_subdomain_ids);
1752 bool clear_stitched_boundary_ids,
1754 bool use_binary_search,
1755 bool enforce_all_nodes_match_on_boundaries,
1756 bool merge_boundary_nodes_all_or_nothing)
1763 clear_stitched_boundary_ids,
1766 enforce_all_nodes_match_on_boundaries,
1768 merge_boundary_nodes_all_or_nothing,
1778 bool clear_stitched_boundary_ids,
1780 bool use_binary_search,
1781 bool enforce_all_nodes_match_on_boundaries,
1782 bool skip_find_neighbors,
1783 bool merge_boundary_nodes_all_or_nothing,
1784 bool remap_subdomain_ids)
1796 std::unique_ptr<MeshSerializer> serialize_other;
1798 serialize_other = std::make_unique<MeshSerializer>
1799 (*
const_cast<MeshBase *
>(other_mesh));
1801 std::map<dof_id_type, dof_id_type> node_to_node_map, other_to_this_node_map;
1802 std::map<dof_id_type, std::vector<dof_id_type>> node_to_elems_map;
1805 typedef std::pair<const Elem *, unsigned char> val_type;
1806 typedef std::pair<key_type, val_type> key_val_pair;
1807 typedef std::unordered_multimap<key_type, val_type> map_type;
1809 map_type side_to_elem_map;
1820 LOG_SCOPE(
"stitch_meshes node merging",
"UnstructuredMesh");
1825 Real h_min = std::numeric_limits<Real>::max();
1826 bool h_min_updated =
false;
1829 std::set<dof_id_type> this_boundary_node_ids, other_boundary_node_ids;
1832 std::unique_ptr<const Elem> side;
1836 boundary_id_type id_array[2] = {this_mesh_boundary_id, other_mesh_boundary_id};
1837 std::set<dof_id_type> * set_array[2] = {&this_boundary_node_ids, &other_boundary_node_ids};
1838 const MeshBase * mesh_array[2] = {
this, other_mesh};
1840 for (
unsigned i=0; i<2; ++i)
1854 if (node_bc_id == id_array[i])
1857 set_array[i]->insert( this_node_id );
1863 std::vector<boundary_id_type> bc_ids;
1870 std::vector<const Elem *> boundary_node_elems;
1872 for (
auto & el : mesh_array[i]->element_ptr_range())
1875 for (
auto side_id : el->side_index_range())
1876 if (el->neighbor_ptr(
side_id) ==
nullptr)
1881 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
1883 el->build_side_ptr(side,
side_id);
1884 for (
auto & n : side->node_ref_range())
1885 set_array[i]->insert(n.id());
1887 h_min = std::min(h_min, side->hmin());
1888 h_min_updated =
true;
1891 if (skip_find_neighbors && (i==0))
1893 key_type key = el->low_order_key(
side_id);
1896 val.second = cast_int<unsigned char>(
side_id);
1901 side_to_elem_map.insert (kvp);
1908 for (
auto edge_id : el->edge_index_range())
1910 if (el->is_edge_on_side(edge_id,
side_id))
1915 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
1917 std::unique_ptr<const Elem> edge (el->build_edge_ptr(edge_id));
1918 for (
auto & n : edge->node_ref_range())
1919 set_array[i]->insert( n.id() );
1921 h_min = std::min(h_min, edge->hmin());
1922 h_min_updated =
true;
1936 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
1938 boundary_node_elems.push_back(el);
1949 const auto N = boundary_node_elems.size();
1951 for (
auto node_elem_j :
make_range(node_elem_i+1, N))
1954 (boundary_node_elems[node_elem_i]->point(0) - boundary_node_elems[node_elem_j]->point(0)).
norm();
1961 h_min = std::min(h_min, node_sep);
1962 h_min_updated =
true;
1971 libMesh::out <<
"In UnstructuredMesh::stitch_meshes:\n" 1972 <<
"This mesh has " << this_boundary_node_ids.size()
1973 <<
" nodes on boundary `" 1975 <<
"' (" << this_mesh_boundary_id <<
").\n" 1976 <<
"Other mesh has " << other_boundary_node_ids.size()
1977 <<
" nodes on boundary `" 1979 <<
"' (" << other_mesh_boundary_id <<
").\n";
1983 libMesh::out <<
"Minimum edge length on both surfaces is " << h_min <<
".\n";
1987 libMesh::out <<
"No minimum edge length determined on specified surfaces." << std::endl;
1995 libmesh_error_msg_if(h_min < std::numeric_limits<Real>::epsilon(),
1996 "Coincident nodes detected on source and/or target " 1997 "surface, stitching meshes is not possible.");
2002 if (use_binary_search)
2004 #ifndef LIBMESH_HAVE_NANOFLANN 2005 use_binary_search =
false;
2006 libmesh_warning(
"The use_binary_search option in the " 2007 "UnstructuredMesh stitching algorithms requires nanoflann " 2008 "support. Falling back on N^2 search algorithm.");
2012 if (!this_boundary_node_ids.empty())
2014 if (use_binary_search)
2016 #ifdef LIBMESH_HAVE_NANOFLANN 2017 typedef nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<Real, VectorOfNodesAdaptor>,
2021 std::vector<std::pair<Point, dof_id_type>> this_mesh_nodes(this_boundary_node_ids.size());
2023 for (
auto [it, ctr] = std::make_tuple(this_boundary_node_ids.begin(), 0u);
2024 it != this_boundary_node_ids.end(); ++it, ++ctr)
2026 this_mesh_nodes[ctr].first = this->
point(*it);
2027 this_mesh_nodes[ctr].second = *it;
2032 kd_tree_t this_kd_tree(3, vec_nodes_adaptor, 10);
2033 this_kd_tree.buildIndex();
2036 std::size_t ret_index;
2040 for (
const auto & node_id : other_boundary_node_ids)
2042 const auto & p = other_mesh->
point(node_id);
2043 const Real query_pt[] = {p(0), p(1), p(2)};
2044 this_kd_tree.knnSearch(&query_pt[0], 1, &ret_index, &ret_dist_sqr);
2051 node_to_node_map[this_mesh_nodes[ret_index].second] = node_id;
2052 other_to_this_node_map[node_id] = this_mesh_nodes[ret_index].second;
2060 libmesh_error_msg_if(node_to_node_map.size() != other_to_this_node_map.size(),
2061 "Error: Found multiple matching nodes in stitch_meshes");
2074 libmesh_warning(
"No valid h_min value was found, falling back on " 2075 "absolute distance check in the N^2 search algorithm.");
2082 for (
const auto & this_node_id : this_boundary_node_ids)
2086 bool found_matching_nodes =
false;
2088 for (
const auto & other_node_id : other_boundary_node_ids)
2090 const Node & other_node = other_mesh->
node_ref(other_node_id);
2092 Real node_distance = (this_node - other_node).
norm();
2094 if (node_distance < tol*h_min)
2097 libmesh_error_msg_if(found_matching_nodes,
2098 "Error: Found multiple matching nodes in stitch_meshes");
2100 node_to_node_map[this_node_id] = other_node_id;
2101 other_to_this_node_map[other_node_id] = this_node_id;
2103 found_matching_nodes =
true;
2111 for (
auto & el : other_mesh->element_ptr_range())
2118 for (
auto & n : el->node_ref_range())
2119 if (
const auto it = other_to_this_node_map.find(n.id());
2120 it != other_to_this_node_map.end())
2121 node_to_elems_map[it->second].push_back( el->id() );
2126 libMesh::out <<
"In UnstructuredMesh::stitch_meshes:\n" 2127 <<
"Found " << node_to_node_map.size()
2128 <<
" matching nodes.\n" 2132 if (enforce_all_nodes_match_on_boundaries)
2134 std::size_t n_matching_nodes = node_to_node_map.size();
2135 std::size_t this_mesh_n_nodes = this_boundary_node_ids.size();
2136 std::size_t other_mesh_n_nodes = other_boundary_node_ids.size();
2137 libmesh_error_msg_if((n_matching_nodes != this_mesh_n_nodes) || (n_matching_nodes != other_mesh_n_nodes),
2138 "Error: We expected the number of nodes to match.");
2141 if (merge_boundary_nodes_all_or_nothing)
2143 std::size_t n_matching_nodes = node_to_node_map.size();
2144 std::size_t this_mesh_n_nodes = this_boundary_node_ids.size();
2145 std::size_t other_mesh_n_nodes = other_boundary_node_ids.size();
2146 if ((n_matching_nodes != this_mesh_n_nodes) || (n_matching_nodes != other_mesh_n_nodes))
2151 "UnstructuredMesh::stitch_meshes because not " 2152 "all boundary nodes were matched." 2155 node_to_node_map.clear();
2156 other_to_this_node_map.clear();
2157 node_to_elems_map.clear();
2165 libMesh::out <<
"Skip node merging in UnstructuredMesh::stitch_meshes:" << std::endl;
2173 #ifdef LIBMESH_ENABLE_UNIQUE_ID 2181 if (
this!=other_mesh)
2183 LOG_SCOPE(
"stitch_meshes copying",
"UnstructuredMesh");
2187 for (
auto & pr : node_to_node_map)
2188 pr.second += node_delta;
2190 for (
auto & pr : node_to_elems_map)
2191 for (
auto & entry : pr.second)
2192 entry += elem_delta;
2214 std::unordered_map<subdomain_id_type, subdomain_id_type> id_remapping;
2215 if (remap_subdomain_ids)
2219 std::unordered_map<std::string, subdomain_id_type> other_map_reversed;
2220 for (
auto & [sid, sname] : other_map)
2221 other_map_reversed.emplace(sname, sid);
2223 std::unordered_map<std::string, subdomain_id_type> this_map_reversed;
2224 for (
auto & [sid, sname] : this_map)
2225 this_map_reversed.emplace(sname, sid);
2230 std::set<subdomain_id_type> all_subdomains;
2231 for (
auto & el :
mesh.element_ptr_range())
2232 all_subdomains.insert(el->subdomain_id());
2233 return all_subdomains;
2236 const auto this_subdomains = get_subdomains(*
this);
2237 const auto other_subdomains = get_subdomains(*other_mesh);
2239 for (
auto & [sid, sname] : this_map)
2244 if (
const auto other_reverse_it = other_map_reversed.find(sname);
2245 other_reverse_it != other_map_reversed.end() && other_reverse_it->second != sid)
2246 id_remapping[other_reverse_it->second] = sid;
2251 if (other_subdomains.count(sid) && !other_map.count(sid))
2252 libmesh_error_msg(
"Can't safely stitch with a mesh sharing subdomain id " 2253 << sid <<
" but not subdomain name " << sname);
2258 if (!this_subdomains.empty())
2259 next_free_id = *this_subdomains.rbegin() + 1;
2260 if (!other_subdomains.empty())
2262 std::max(next_free_id,
2263 cast_int<subdomain_id_type>
2264 (*other_subdomains.rbegin() + 1));
2266 for (
auto & [sid, sname] : other_map)
2271 if (!this_map_reversed.count(sname))
2275 if (this_subdomains.count(sid))
2279 if (!this_map.count(sid))
2280 libmesh_error_msg(
"Can't safely stitch with a mesh sharing subdomain id " 2281 << sid <<
" but under subdomain name " << sname);
2290 libmesh_error_msg_if ((!this_subdomains.empty() &&
2291 next_free_id < *this_subdomains.rbegin()) ||
2292 (!other_subdomains.empty() &&
2293 next_free_id < *other_subdomains.rbegin()),
2294 "Subdomain id overflow");
2296 id_remapping[sid] = next_free_id++;
2310 elem_delta, node_delta,
2311 unique_delta, &id_remapping);
2319 boundary.
add_node(std::get<0>(t) + node_delta,
2323 boundary.
add_side(std::get<0>(t) + elem_delta,
2328 boundary.
add_edge(std::get<0>(t) + elem_delta,
2339 ns_id_to_name.insert(other_ns_id_to_name.begin(), other_ns_id_to_name.end());
2343 ss_id_to_name.insert(other_ss_id_to_name.begin(), other_ss_id_to_name.end());
2347 es_id_to_name.insert(other_es_id_to_name.begin(), other_es_id_to_name.end());
2357 other_mesh->
get_elemsets(elemset_code, other_id_set_to_fill);
2366 this_elemset_codes.end(),
2369 if (it != this_elemset_codes.end())
2377 libmesh_error_msg_if(other_id_set_to_fill != this_id_set_to_fill,
2378 "Attempted to stitch together meshes with conflicting elemset codes.");
2396 LOG_SCOPE(
"stitch_meshes node updates",
"UnstructuredMesh");
2399 std::vector<boundary_id_type> bc_ids;
2401 for (
const auto & [target_node_id, elem_vec] : node_to_elems_map)
2403 dof_id_type other_node_id = node_to_node_map[target_node_id];
2406 std::size_t n_elems = elem_vec.size();
2407 for (std::size_t i=0; i<n_elems; i++)
2413 unsigned int local_node_index = el->
local_node(other_node_id);
2419 el->
set_node(local_node_index) = &target_node;
2426 LOG_SCOPE(
"stitch_meshes node deletion",
"UnstructuredMesh");
2427 for (
const auto & [other_node_id, this_node_id] : node_to_node_map)
2431 if ((
this == other_mesh) && (this_node_id == other_node_id))
2445 if (skip_find_neighbors)
2447 LOG_SCOPE(
"stitch_meshes neighbor fixes",
"UnstructuredMesh");
2450 std::unique_ptr<const Elem> my_side, their_side;
2452 std::set<dof_id_type> fixed_elems;
2453 for (
const auto & pr : node_to_elems_map)
2455 std::size_t n_elems = pr.second.size();
2456 for (std::size_t i=0; i<n_elems; i++)
2459 if (!fixed_elems.count(elem_id))
2462 fixed_elems.insert(elem_id);
2468 auto bounds = side_to_elem_map.equal_range(key);
2470 if (bounds.first != bounds.second)
2476 while (bounds.first != bounds.second)
2479 Elem * neighbor =
const_cast<Elem *
>(bounds.first->second.first);
2482 const unsigned int ns = bounds.first->second.second;
2483 neighbor->
side_ptr(their_side, ns);
2495 if ((*my_side == *their_side) &&
2497 ((el->
dim() != 1) || (ns != s)))
2528 side_to_elem_map.erase (bounds.first);
2552 if (clear_stitched_boundary_ids)
2554 LOG_SCOPE(
"stitch_meshes clear bcids",
"UnstructuredMesh");
2557 this_mesh_boundary_id, other_mesh_boundary_id,
true);
2561 return node_to_node_map.size();
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
void set_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element.
unsigned char mapping_data() const
bool closed()
Checks that the library has been closed.
ElemType
Defines an enum for geometric element types.
The SimpleRange templated class is intended to make it easy to construct ranges from pairs of iterato...
This class supports simple reads and writes in any libMesh-supported format, by dispatching to one of...
unique_id_type & set_unique_id()
virtual void reserve_nodes(const dof_id_type nn)=0
Reserves space for a known number of nodes.
std::size_t stitch_surfaces(boundary_id_type boundary_id_1, boundary_id_type boundary_id_2, Real tol=TOLERANCE, bool clear_stitched_boundary_ids=false, bool verbose=true, bool use_binary_search=true, bool enforce_all_nodes_match_on_boundaries=false, bool merge_boundary_nodes_all_or_nothing=false)
Similar to stitch_meshes, except that we stitch two adjacent surfaces within this mesh...
const Elem * parent() const
virtual void all_complete_order_range(const SimpleRange< element_iterator > &range) override
Converts a (conforming, non-refined) mesh with linear elements into a mesh with "complete" order elem...
virtual void copy_nodes_and_elements(const MeshBase &other_mesh, const bool skip_find_neighbors=false, dof_id_type element_id_offset=0, dof_id_type node_id_offset=0, unique_id_type unique_id_offset=0, std::unordered_map< subdomain_id_type, subdomain_id_type > *id_remapping=nullptr)
Deep copy of nodes and elements from another mesh object (used by subclass copy constructors and by m...
In parallel meshes where a ghost element has neighbors which do not exist on the local processor...
virtual Node *& set_node(const unsigned int i)
A Node is like a Point, but with more information.
bool is_ancestor_of(const Elem *descendant) const
static ElemType complete_order_equivalent_type(const ElemType et)
virtual unique_id_type parallel_max_unique_id() const =0
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
void set_parent(Elem *p)
Sets the pointer to the element's parent.
std::vector< std::string > _elem_integer_names
The array of names for integer data associated with each element in the mesh.
const Elem * interior_parent() const
std::vector< dof_id_type > get_elemset_codes() const
Return a vector of all elemset codes defined on the mesh.
virtual void read(const std::string &mesh_file) override
This method implements reading a mesh from a specified file.
void set_mapping_type(const ElemMappingType type)
Sets the value of the mapping type for the element.
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
IntRange< unsigned short > side_index_range() const
void skip_partitioning(bool skip)
If true is passed in then nothing on this mesh will be (re)partitioned.
The definition of the const_element_iterator struct.
static constexpr Real TOLERANCE
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
size_t kdtree_get_point_count() const
Must return the number of data points.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly ecreated (or read) mesh for use.
virtual dof_id_type low_order_key(const unsigned int s) const =0
const boundary_id_type side_id
VectorOfNodesAdaptor(const std::vector< std::pair< Point, dof_id_type >> &nodes)
void add_elemset_code(dof_id_type code, MeshBase::elemset_type id_set)
Tabulate a user-defined "code" for elements which belong to the element sets specified in id_set...
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
This is the base class from which all geometric element types are derived.
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
unique_id_type unique_id() const
const Parallel::Communicator & comm() const
virtual unsigned int n_children() const =0
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
std::map< const Elem *, const CouplingMatrix *, CompareDofObjectsByPIDAndThenID > map_type
What elements do we care about and what variables do we care about on each element?
virtual void own_node(Node &)
Takes ownership of node n on this partition of a distributed mesh, by setting n.processor_id() to thi...
virtual void all_first_order() override
Converts a mesh with higher-order elements into a mesh with linear elements.
virtual void set_next_unique_id(unique_id_type id)=0
Sets the next available unique id to be used.
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true) override
Other functions from MeshBase requiring re-definition.
The libMesh namespace provides an interface to certain functionality in the library.
void create_pid_mesh(UnstructuredMesh &pid_mesh, const processor_id_type pid) const
Generates a new mesh containing all the elements which are assigned to processor pid.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
std::vector< std::string > _node_integer_names
The array of names for integer data associated with each node in the mesh.
virtual void all_second_order_range(const SimpleRange< element_iterator > &range, const bool full_ordered=true) override
Converts a (conforming, non-refined) mesh with linear elements into a mesh with second-order elements...
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
void set_interior_parent(Elem *p)
Sets the pointer to the element's interior_parent.
uint8_t processor_id_type
This is the MeshBase class.
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of element numbers, sides, and ids for those sides.
void get_elemsets(dof_id_type elemset_code, MeshBase::elemset_type &id_set_to_fill) const
Look up the element sets for a given elemset code and vice-versa.
virtual bool contract() override
Delete subactive (i.e.
std::size_t stitching_helper(const MeshBase *other_mesh, boundary_id_type boundary_id_1, boundary_id_type boundary_id_2, Real tol, bool clear_stitched_boundary_ids, bool verbose, bool use_binary_search, bool enforce_all_nodes_match_on_boundaries, bool skip_find_neighbors, bool merge_boundary_nodes_all_or_nothing, bool remap_subdomain_ids)
Helper function for stitch_meshes and stitch_surfaces that does the mesh stitching.
uint8_t processor_id_type
std::map< boundary_id_type, std::string > & set_sideset_name_map()
void replace_child(Elem *elem, unsigned int c)
Replaces the child pointer at the specified index in the child array.
void allow_remote_element_removal(bool allow)
If false is passed in then this mesh will no longer have remote elements deleted when being prepared ...
processor_id_type n_processors() const
virtual bool is_serial() const
void libmesh_ignore(const Args &...)
void build_node_list(std::vector< dof_id_type > &node_id_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of nodes and ids for those nodes.
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const
static const boundary_id_type invalid_id
Number used for internal use.
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
ElemMappingType mapping_type() const
This is the MeshCommunication class.
void min(const T &r, T &o, Request &req) const
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
virtual Real hmin() const
std::size_t stitch_meshes(const MeshBase &other_mesh, boundary_id_type this_mesh_boundary, boundary_id_type other_mesh_boundary, Real tol=TOLERANCE, bool clear_stitched_boundary_ids=false, bool verbose=true, bool use_binary_search=true, bool enforce_all_nodes_match_on_boundaries=false, bool merge_boundary_nodes_all_or_nothing=false, bool remap_subdomain_ids=false)
Stitch other_mesh to this mesh so that this mesh is the union of the two meshes.
virtual unsigned int n_nodes() const =0
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
The UnstructuredMesh class is derived from the MeshBase class.
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
virtual const Node * query_node_ptr(const dof_id_type i) const =0
void set_mapping_data(const unsigned char data)
Sets the value of the mapping data for the element.
const std::map< boundary_id_type, std::string > & get_edgeset_name_map() const
virtual dof_id_type max_elem_id() const =0
void clear_point_locator()
Releases the current PointLocator object.
bool allow_find_neighbors() const
virtual void write(const std::string &mesh_file) override
This method implements writing a mesh to a specified file.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
virtual void delete_node(Node *n)=0
Removes the Node n from the mesh.
std::pair< std::vector< unsigned int >, std::vector< unsigned int > > merge_extra_integer_names(const MeshBase &other)
Merge extra-integer arrays from an other mesh.
std::string & subdomain_name(subdomain_id_type id)
void allow_find_neighbors(bool allow)
If false is passed then this mesh will no longer work to find element neighbors when being prepared f...
virtual std::unique_ptr< Elem > disconnected_clone() const
virtual unsigned int n_second_order_adjacent_vertices(const unsigned int n) const
bool allow_remote_element_removal() const
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
void build_shellface_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &shellface_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of element numbers, shellfaces, and boundary ids for those shellfaces.
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
virtual void clear()
Deletes all the element and node data that is currently stored.
static ElemType second_order_equivalent_type(const ElemType et, const bool full_ordered=true)
unsigned int which_child_am_i(const Elem *e) const
bool skip_partitioning() const
unsigned int n_partitions() const
virtual const Elem * elem_ptr(const dof_id_type i) const =0
UnstructuredMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
Real kdtree_get_pt(const size_t idx, int dim) const
virtual Elem * insert_elem(Elem *e)=0
Insert elem e to the element array, preserving its id and replacing/deleting any existing element wit...
const Elem * neighbor_ptr(unsigned int i) const
std::set< GhostingFunctor * >::const_iterator ghosting_functors_begin() const
Beginning of range of ghosting functors.
std::set< elemset_id_type > elemset_type
Typedef for the "set" container used to store elemset ids.
unsigned int level() const
virtual unsigned int n_vertices() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< std::pair< Point, dof_id_type > > _nodes
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
virtual ~UnstructuredMesh()
Destructor.
subdomain_id_type subdomain_id() const
timpi_pure bool verify(const T &r) const
void copy_boundary_ids(const BoundaryInfo &old_boundary_info, const Elem *const old_elem, const Elem *const new_elem)
void max(const T &r, T &o, Request &req) const
virtual unsigned short dim() const =0
Temporarily serialize a DistributedMesh for non-distributed-mesh capable code paths.
const Node * node_ptr(const unsigned int i) const
std::map< boundary_id_type, std::string > & set_nodeset_name_map()
void build_edge_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &edge_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of element numbers, edges, and boundary ids for those edges.
void clear_stitched_boundary_side_ids(boundary_id_type sideset_id, boundary_id_type other_sideset_id, bool clear_nodeset_data=false)
Clear sideset information along a stitched mesh interface.
void make_nodes_parallel_consistent(MeshBase &)
Copy processor_ids and ids on ghost nodes from their local processors.
virtual bool is_replicated() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
const std::string & get_sideset_name(boundary_id_type id) const
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
Add shell face shellface of element number elem with boundary id id to the boundary information data ...
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
void add_extra_integers(const unsigned int n_integers)
Assigns a set of extra integers to this DofObject.
ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T &value)
The STL provides std::binary_search() which returns true or false depending on whether the searched-f...
unsigned int mesh_dimension() const
bool initialized()
Checks that library initialization has been done.
unsigned int n_extra_integers() const
Returns how many extra integers are associated to the DofObject.
virtual const Node & node_ref(const dof_id_type i) const
virtual const Point & point(const dof_id_type i) const =0
unsigned int local_node(const dof_id_type i) const
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
bool allow_renumbering() const
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false) override
Reads the file specified by name.
virtual dof_id_type max_node_id() const =0
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
bool kdtree_get_bbox(BBOX &) const
static ElemType first_order_equivalent_type(const ElemType et)
processor_id_type processor_id() const
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
dof_id_type node_id(const unsigned int i) const
virtual void reserve_elem(const dof_id_type ne)=0
Reserves space for a known number of elements.
bool has_children() const
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
void set_extra_integer(const unsigned int index, const dof_id_type value)
Sets the value on this object of the extra integer associated with index, which should have been obta...
virtual void renumber_nodes_and_elements()=0
After partitioning a mesh it is useful to renumber the nodes and elements so that they lie in contigu...
virtual dof_id_type n_nodes() const =0
This class implements the original default geometry ghosting requirements in libMesh: point neighbors...
void create_submesh(UnstructuredMesh &new_mesh, const const_element_iterator &it, const const_element_iterator &it_end) const
Constructs a mesh called "new_mesh" from the current mesh by iterating over the elements between it a...
Point vertex_average() const
virtual void write(const std::string &name) override
Write the file specified by name.
dof_id_type get_extra_integer(const unsigned int index) const
Gets the value on this object of the extra integer associated with index, which should have been obta...
const Elem * child_ptr(unsigned int i) const
std::set< GhostingFunctor * >::const_iterator ghosting_functors_end() const
End of range of ghosting functors.
std::map< boundary_id_type, std::string > & set_edgeset_name_map()
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...
const RemoteElem * remote_elem