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());
302 hi_elem->add_extra_integers(nei);
303 for (
unsigned int i=0; i != nei; ++i)
306 hi_elem->inherit_data_from(lo_elem);
312 template <
typename ElemTypeConverter>
316 const unsigned int max_new_nodes_per_elem,
317 const ElemTypeConverter & elem_type_converter)
353 auto is_higher_order = [&elem_type_converter](
const Elem * elem) {
355 ElemType new_type = elem_type_converter(old_type);
356 return old_type == new_type;
359 bool already_higher_order =
360 std::all_of(range.
begin(), range.
end(), is_higher_order);
364 if (already_higher_order)
382 std::map<std::vector<dof_id_type>,
Node *> adj_vertices_to_ho_nodes;
390 std::unordered_map<Elem *, std::vector<Elem *>> exterior_children_of;
398 #ifdef LIBMESH_ENABLE_UNIQUE_ID 409 n_partitioned_elem = 0;
425 auto track_if_necessary = [&adj_vertices_to_ho_nodes,
426 &exterior_children_of,
427 &elem_type_converter](
Elem * elem) {
430 if (elem->default_order() !=
FIRST)
431 for (
unsigned int hon :
make_range(elem->n_vertices(), elem->n_nodes()))
433 auto pos = map_hi_order_node(hon, *elem, adj_vertices_to_ho_nodes);
434 pos->second = elem->node_ptr(hon);
437 const ElemType old_type = elem->type();
438 const ElemType new_type = elem_type_converter(old_type);
439 if (old_type != new_type)
440 exterior_children_of.emplace(elem, std::vector<Elem *>());
446 if (range.
begin() ==
mesh.elements_begin() &&
447 range.
end() ==
mesh.elements_end())
449 for (
auto & elem : range)
450 track_if_necessary(elem);
457 point_neighbor_finder(range.
begin(), range.
end(),
459 point_neighbor_elements);
461 for (
auto & [elem, coupling_map] : point_neighbor_elements)
464 track_if_necessary(const_cast<Elem *>(elem));
472 for (
auto & elem :
mesh.element_ptr_range())
473 if (
auto exterior_map_it = exterior_children_of.find(elem->interior_parent());
474 exterior_map_it != exterior_children_of.end())
475 exterior_map_it->second.push_back(elem);
483 for (
auto & lo_elem : range)
488 const ElemType new_type = elem_type_converter(old_type);
490 if (old_type == new_type)
494 libmesh_assert_equal_to (lo_elem->
level(), 0);
497 ++n_unpartitioned_elem;
499 ++n_partitioned_elem;
507 libmesh_assert_equal_to (lo_elem->
n_vertices(), ho_elem->n_vertices());
513 for (
unsigned int v=0, lnn=lo_elem->
n_nodes(); v < lnn; v++)
514 ho_elem->set_node(v, lo_elem->
node_ptr(v));
516 transfer_elem(*lo_elem, std::move(ho_elem),
517 #ifdef LIBMESH_ENABLE_UNIQUE_ID
518 max_unique_id, max_new_nodes_per_elem,
520 mesh, adj_vertices_to_ho_nodes,
521 exterior_children_of);
525 adj_vertices_to_ho_nodes.clear();
527 #ifdef LIBMESH_ENABLE_UNIQUE_ID 541 dof_id_type max_unpartitioned_elem = n_unpartitioned_elem;
543 if (max_unpartitioned_elem)
551 libmesh_not_implemented();
583 const std::vector<std::pair<Point, dof_id_type>>
_nodes;
602 libmesh_assert_less (
idx,
_nodes.size());
603 libmesh_assert_less (
dim, 3);
607 if (
dim==0)
return p(0);
608 if (
dim==1)
return p(1);
615 template <
class BBOX>
640 const bool skip_find_neighbors,
644 #ifdef LIBMESH_ENABLE_UNIQUE_ID
648 std::unordered_map<subdomain_id_type, subdomain_id_type> *
651 LOG_SCOPE(
"copy_nodes_and_elements()",
"UnstructuredMesh");
653 std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
656 const unsigned int n_old_node_ints = extra_int_maps.second.size(),
658 n_old_elem_ints = extra_int_maps.first.size(),
674 MeshTools::libmesh_assert_valid_procids<Node>(other_mesh);
682 for (
const auto & oldn : other_mesh.node_ptr_range())
685 (wrap_proc_ids ? oldn->processor_id() % this->
n_processors() : oldn->processor_id());
690 oldn->id() + node_id_offset,
694 for (
unsigned int i = 0; i != n_old_node_ints; ++i)
695 newn->set_extra_integer(extra_int_maps.second[i],
696 oldn->get_extra_integer(i));
698 #ifdef LIBMESH_ENABLE_UNIQUE_ID 699 newn->set_unique_id(oldn->unique_id() + unique_id_offset);
710 typedef std::unordered_map<const Elem *, Elem *> map_type;
711 map_type old_elems_to_new_elems, ip_map;
714 for (
const auto & old : other_mesh.element_ptr_range())
718 this->
elem_ptr(old->parent()->id() + element_id_offset) :
721 el->set_parent(newparent);
726 auto remapping_it = id_remapping->find(sbd_id);
727 if (remapping_it != id_remapping->end())
728 sbd_id = remapping_it->second;
730 el->subdomain_id() = sbd_id;
734 if (el->dim() < other_mesh.
mesh_dimension() && old->interior_parent())
735 ip_map[old] = el.get();
737 #ifdef LIBMESH_ENABLE_AMR 738 if (old->has_children())
739 for (
unsigned int c = 0, nc = old->n_children(); c != nc; ++c)
741 el->add_child(const_cast<RemoteElem *>(
remote_elem), c);
746 unsigned int oldc = old->parent()->which_child_am_i(old);
751 el->set_refinement_flag(old->refinement_flag());
755 el->hack_p_level(old->p_level());
757 el->set_p_refinement_flag(old->p_refinement_flag());
758 #endif // #ifdef LIBMESH_ENABLE_AMR 761 for (
auto i : el->node_index_range())
763 this->node_ptr(old->node_id(i) + node_id_offset));
766 el->processor_id() = cast_int<processor_id_type>
767 (wrap_proc_ids ? old->processor_id() % this->
n_processors() : old->processor_id());
770 el->set_id(old->id() + element_id_offset);
772 el->add_extra_integers(n_new_elem_ints);
773 for (
unsigned int i = 0; i != n_old_elem_ints; ++i)
774 el->set_extra_integer(extra_int_maps.first[i],
775 old->get_extra_integer(i));
777 #ifdef LIBMESH_ENABLE_UNIQUE_ID 778 el->set_unique_id(old->unique_id() + unique_id_offset);
782 if (!skip_find_neighbors)
784 for (
auto s : old->side_index_range())
786 el->set_neighbor(s, const_cast<RemoteElem *>(
remote_elem));
792 old_elems_to_new_elems[old] = new_el;
796 for (
auto & elem_pair : ip_map)
798 this->
elem_ptr(elem_pair.first->interior_parent()->id() + element_id_offset));
801 if (skip_find_neighbors)
805 for (
const auto & old_elem : other_mesh.element_ptr_range())
807 Elem * new_elem = old_elems_to_new_elems[old_elem];
808 for (
auto s : old_elem->side_index_range())
811 Elem * new_neighbor = old_elems_to_new_elems[old_neighbor];
818 #ifdef LIBMESH_ENABLE_UNIQUE_ID 854 if (skip_find_neighbors ||
873 const bool reset_current_list)
881 parallel_object_only();
883 LOG_SCOPE(
"find_neighbors()",
"Mesh");
886 if (reset_current_list)
887 for (
const auto & e : this->element_ptr_range())
888 for (
auto s : e->side_index_range())
889 if (e->neighbor_ptr(s) !=
remote_elem || reset_remote_elements)
890 e->set_neighbor(s,
nullptr);
898 typedef std::pair<Elem *, unsigned char> val_type;
899 typedef std::unordered_multimap<key_type, val_type> map_type;
902 map_type side_to_elem_map;
905 std::unique_ptr<Elem> my_side, their_side;
907 for (
const auto & element : this->element_ptr_range())
909 for (
auto ms : element->side_index_range())
915 if (element->neighbor_ptr(ms) ==
nullptr ||
921 const dof_id_type key = element->low_order_key(ms);
924 auto bounds = side_to_elem_map.equal_range(key);
928 if (bounds.first != bounds.second)
931 element->side_ptr(my_side, ms);
934 while (bounds.first != bounds.second)
937 Elem * neighbor = bounds.first->second.first;
940 const unsigned int ns = bounds.first->second.second;
952 if ((*my_side == *their_side) &&
953 (element->level() == neighbor->
level()))
961 if (element->subactive() ==
966 element->set_neighbor (ms,neighbor);
969 else if (element->subactive())
971 element->set_neighbor(ms,neighbor);
977 side_to_elem_map.erase (bounds.first);
989 side_to_elem_map.emplace
990 (key, std::make_pair(element, cast_int<unsigned char>(ms)));
996 #ifdef LIBMESH_ENABLE_AMR 1026 for (
unsigned int level = 1; level <
n_levels; ++level)
1028 for (
auto & current_elem :
as_range(level_elements_begin(level),
1029 level_elements_end(level)))
1036 for (
auto s : current_elem->side_index_range())
1038 if (current_elem->neighbor_ptr(s) ==
nullptr ||
1055 (neigh->
level()+1) == current_elem->level())))
1061 bool neigh_has_remote_children =
false;
1064 neigh_has_remote_children =
true;
1069 if (current_elem->active())
1070 libmesh_assert_not_equal_to (current_elem->processor_id(),
1078 else if (neigh && (current_elem->subactive() &&
1091 bool found_neigh =
false;
1092 for (
unsigned int c = 0, nc = neigh->
n_children();
1093 !found_neigh && c != nc; ++c)
1118 if ((!neigh->
active()) && (!current_elem->subactive()))
1122 libMesh::err <<
"Bad element ID = " << current_elem->id()
1123 <<
", Side " << s <<
", Bad neighbor ID = " << neigh->
id() << std::endl;
1124 libMesh::err <<
"Bad element proc_ID = " << current_elem->processor_id()
1125 <<
", Bad neighbor proc_ID = " << neigh->
processor_id() << std::endl;
1126 libMesh::err <<
"Bad element size = " << current_elem->hmin()
1127 <<
", Bad neighbor size = " << neigh->
hmin() << std::endl;
1128 libMesh::err <<
"Bad element center = " << current_elem->vertex_average()
1129 <<
", Bad neighbor center = " << neigh->
vertex_average() << std::endl;
1131 << (current_elem->active()?
"Active":
"Ancestor")
1132 <<
" Element at level " 1133 << current_elem->level() << std::endl;
1135 << (parent->
active()?
"active":
1136 (parent->
subactive()?
"subactive":
"ancestor"))
1138 << (neigh->
subactive()?
"subactive":
"ancestor")
1139 <<
" neighbor at level " << neigh->
level()
1142 libmesh_error_msg(
"Problematic mesh written to bad_mesh.gmv.");
1150 if (current_elem->dim() >= LIBMESH_DIM)
1154 current_elem->set_interior_parent(
nullptr);
1182 current_elem->set_interior_parent
1187 bool child_contains_our_nodes =
true;
1188 for (
auto & n : current_elem->node_ref_range())
1190 bool child_contains_this_node =
false;
1191 for (
auto & cn : child.node_ref_range())
1192 if (cn.absolute_fuzzy_equals
1193 (n, node_tolerance))
1195 child_contains_this_node =
true;
1198 if (!child_contains_this_node)
1200 child_contains_our_nodes =
false;
1204 if (child_contains_our_nodes)
1206 current_elem->set_interior_parent(&child);
1222 !reset_remote_elements);
1231 bool skip_renumber_nodes_and_elements,
1232 bool skip_find_neighbors)
1240 if (
name.rfind(
".gmv") ==
name.size() - 4)
1245 if (skip_renumber_nodes_and_elements)
1248 libmesh_deprecated();
1263 LOG_SCOPE(
"write()",
"Mesh");
1271 const std::vector<Number> & v,
1272 const std::vector<std::string> & vn)
const 1274 LOG_SCOPE(
"write()",
"Mesh");
1296 <<
"mesh for a processor id (=" 1298 <<
") greater than " 1299 <<
"the number of processors available for " 1300 <<
"the calculation. (=" 1308 this->active_pid_elements_begin(pid),
1309 this->active_pid_elements_end(pid));
1336 libmesh_assert_not_equal_to (this->
n_nodes(), 0);
1337 libmesh_assert_not_equal_to (this->
n_elem(), 0);
1340 std::vector<boundary_id_type> bc_ids;
1346 for (
const auto & old_elem :
as_range(it, it_end))
1350 auto uelem = old_elem->disconnected_clone();
1355 for (
auto n : old_elem->node_index_range())
1357 const dof_id_type this_node_id = old_elem->node_id(n);
1365 old_elem->node_ptr(n)->processor_id());
1368 for (
unsigned int i = 0; i != n_node_ints; ++i)
1371 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1381 for (
auto s : old_elem->side_index_range())
1394 #ifdef LIBMESH_ENABLE_AMR 1397 LOG_SCOPE (
"contract()",
"Mesh");
1400 bool mesh_changed =
false;
1403 for (
const auto & elem : this->element_ptr_range())
1404 libmesh_assert(elem->active() || elem->subactive() || elem->ancestor());
1408 for (
auto & elem : this->element_ptr_range())
1411 if (elem->subactive())
1425 mesh_changed =
true;
1452 return mesh_changed;
1454 #endif // #ifdef LIBMESH_ENABLE_AMR 1460 LOG_SCOPE(
"all_first_order()",
"Mesh");
1465 std::vector<bool> node_touched_by_me(this->
max_node_id(),
false);
1470 for (
auto & so_elem : element_ptr_range())
1480 (so_elem->type()), so_elem->parent());
1482 const unsigned short n_sides = so_elem->n_sides();
1484 for (
unsigned short s=0; s != n_sides; ++s)
1488 #ifdef LIBMESH_ENABLE_AMR 1492 if (so_elem->has_children())
1493 for (
unsigned int c = 0, nc = so_elem->n_children(); c != nc; ++c)
1504 if (so_elem->parent())
1507 so_elem->parent()->which_child_am_i(so_elem);
1519 libmesh_assert_equal_to (lo_elem->
n_vertices(), so_elem->n_vertices());
1526 for (
unsigned int v=0, snv=so_elem->n_vertices(); v < snv; v++)
1528 lo_elem->
set_node(v, so_elem->node_ptr(v));
1529 node_touched_by_me[lo_elem->
node_id(v)] =
true;
1536 for (
unsigned short s=0; s != n_sides; s++)
1556 lo_elem->
set_id(so_elem->id());
1557 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1561 const unsigned int nei = so_elem->n_extra_integers();
1563 for (
unsigned int i=0; i != nei; ++i)
1572 for (
const auto & node : this->node_ptr_range())
1573 if (!node_touched_by_me[node->id()])
1593 const bool full_ordered)
1595 LOG_SCOPE(
"all_second_order_range()",
"Mesh");
1602 unsigned int max_new_nodes_per_elem;
1618 max_new_nodes_per_elem = 3 - 2;
1620 (1.5*static_cast<double>(this->
n_nodes())));
1628 max_new_nodes_per_elem = 9 - 4;
1630 (2*static_cast<double>(this->
n_nodes())));
1641 max_new_nodes_per_elem = 27 - 8;
1643 (2.5*static_cast<double>(this->
n_nodes())));
1648 libmesh_error_msg(
"Unknown mesh dimension " << this->
mesh_dimension());
1652 all_increased_order_range(*
this, range, max_new_nodes_per_elem,
1662 LOG_SCOPE(
"all_complete_order()",
"Mesh");
1669 unsigned int max_new_nodes_per_elem;
1685 max_new_nodes_per_elem = 3 - 2;
1687 (1.5*static_cast<double>(this->
n_nodes())));
1696 max_new_nodes_per_elem = 9 - 4;
1698 (2*static_cast<double>(this->
n_nodes())));
1710 max_new_nodes_per_elem = 27 - 8;
1712 (2.5*static_cast<double>(this->
n_nodes())));
1717 libmesh_error_msg(
"Unknown mesh dimension " << this->
mesh_dimension());
1721 all_increased_order_range(*
this, range, max_new_nodes_per_elem,
1733 bool clear_stitched_boundary_ids,
1735 bool use_binary_search,
1736 bool enforce_all_nodes_match_on_boundaries,
1737 bool merge_boundary_nodes_all_or_nothing,
1738 bool remap_subdomain_ids)
1740 LOG_SCOPE(
"stitch_meshes()",
"UnstructuredMesh");
1742 this_mesh_boundary_id,
1743 other_mesh_boundary_id,
1745 clear_stitched_boundary_ids,
1748 enforce_all_nodes_match_on_boundaries,
1750 merge_boundary_nodes_all_or_nothing,
1751 remap_subdomain_ids);
1759 bool clear_stitched_boundary_ids,
1761 bool use_binary_search,
1762 bool enforce_all_nodes_match_on_boundaries,
1763 bool merge_boundary_nodes_all_or_nothing)
1770 clear_stitched_boundary_ids,
1773 enforce_all_nodes_match_on_boundaries,
1775 merge_boundary_nodes_all_or_nothing,
1785 bool clear_stitched_boundary_ids,
1787 bool use_binary_search,
1788 bool enforce_all_nodes_match_on_boundaries,
1789 bool skip_find_neighbors,
1790 bool merge_boundary_nodes_all_or_nothing,
1791 bool remap_subdomain_ids)
1807 std::unique_ptr<MeshSerializer> serialize_other;
1809 serialize_other = std::make_unique<MeshSerializer>
1810 (*
const_cast<MeshBase *
>(other_mesh));
1812 std::map<dof_id_type, dof_id_type> node_to_node_map, other_to_this_node_map;
1813 std::map<dof_id_type, std::vector<dof_id_type>> node_to_elems_map;
1816 typedef std::pair<const Elem *, unsigned char> val_type;
1817 typedef std::pair<key_type, val_type> key_val_pair;
1818 typedef std::unordered_multimap<key_type, val_type> map_type;
1820 map_type side_to_elem_map;
1831 LOG_SCOPE(
"stitch_meshes node merging",
"UnstructuredMesh");
1836 Real h_min = std::numeric_limits<Real>::max();
1837 bool h_min_updated =
false;
1840 std::set<dof_id_type> this_boundary_node_ids, other_boundary_node_ids;
1843 std::unique_ptr<const Elem> side;
1847 boundary_id_type id_array[2] = {this_mesh_boundary_id, other_mesh_boundary_id};
1848 std::set<dof_id_type> * set_array[2] = {&this_boundary_node_ids, &other_boundary_node_ids};
1849 const MeshBase * mesh_array[2] = {
this, other_mesh};
1851 for (
unsigned i=0; i<2; ++i)
1865 if (node_bc_id == id_array[i])
1868 set_array[i]->insert( this_node_id );
1874 std::vector<boundary_id_type> bc_ids;
1881 std::vector<const Elem *> boundary_node_elems;
1883 for (
auto & el : mesh_array[i]->element_ptr_range())
1886 for (
auto side_id : el->side_index_range())
1887 if (el->neighbor_ptr(
side_id) ==
nullptr)
1892 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
1894 el->build_side_ptr(side,
side_id);
1895 for (
auto & n : side->node_ref_range())
1896 set_array[i]->insert(n.id());
1898 h_min = std::min(h_min, side->hmin());
1899 h_min_updated =
true;
1902 if (skip_find_neighbors && (i==0))
1904 key_type key = el->low_order_key(
side_id);
1907 val.second = cast_int<unsigned char>(
side_id);
1912 side_to_elem_map.insert (kvp);
1919 for (
auto edge_id : el->edge_index_range())
1921 if (el->is_edge_on_side(edge_id,
side_id))
1926 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
1928 std::unique_ptr<const Elem> edge (el->build_edge_ptr(edge_id));
1929 for (
auto & n : edge->node_ref_range())
1930 set_array[i]->insert( n.id() );
1932 h_min = std::min(h_min, edge->hmin());
1933 h_min_updated =
true;
1947 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
1949 boundary_node_elems.push_back(el);
1960 const auto N = boundary_node_elems.size();
1962 for (
auto node_elem_j :
make_range(node_elem_i+1, N))
1965 (boundary_node_elems[node_elem_i]->point(0) - boundary_node_elems[node_elem_j]->point(0)).
norm();
1972 h_min = std::min(h_min, node_sep);
1973 h_min_updated =
true;
1982 libMesh::out <<
"In UnstructuredMesh::stitch_meshes:\n" 1983 <<
"This mesh has " << this_boundary_node_ids.size()
1984 <<
" nodes on boundary `" 1986 <<
"' (" << this_mesh_boundary_id <<
").\n" 1987 <<
"Other mesh has " << other_boundary_node_ids.size()
1988 <<
" nodes on boundary `" 1990 <<
"' (" << other_mesh_boundary_id <<
").\n";
1994 libMesh::out <<
"Minimum edge length on both surfaces is " << h_min <<
".\n";
1998 libMesh::out <<
"No minimum edge length determined on specified surfaces." << std::endl;
2006 libmesh_error_msg_if(h_min < std::numeric_limits<Real>::epsilon(),
2007 "Coincident nodes detected on source and/or target " 2008 "surface, stitching meshes is not possible.");
2013 if (use_binary_search)
2015 #ifndef LIBMESH_HAVE_NANOFLANN 2016 use_binary_search =
false;
2017 libmesh_warning(
"The use_binary_search option in the " 2018 "UnstructuredMesh stitching algorithms requires nanoflann " 2019 "support. Falling back on N^2 search algorithm.");
2023 if (!this_boundary_node_ids.empty())
2025 if (use_binary_search)
2027 #ifdef LIBMESH_HAVE_NANOFLANN 2028 typedef nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<Real, VectorOfNodesAdaptor>,
2032 std::vector<std::pair<Point, dof_id_type>> this_mesh_nodes(this_boundary_node_ids.size());
2034 for (
auto [it, ctr] = std::make_tuple(this_boundary_node_ids.begin(), 0u);
2035 it != this_boundary_node_ids.end(); ++it, ++ctr)
2037 this_mesh_nodes[ctr].first = this->
point(*it);
2038 this_mesh_nodes[ctr].second = *it;
2043 kd_tree_t this_kd_tree(3, vec_nodes_adaptor, 10);
2044 this_kd_tree.buildIndex();
2047 std::size_t ret_index;
2051 for (
const auto & node_id : other_boundary_node_ids)
2053 const auto & p = other_mesh->
point(node_id);
2054 const Real query_pt[] = {p(0), p(1), p(2)};
2055 this_kd_tree.knnSearch(&query_pt[0], 1, &ret_index, &ret_dist_sqr);
2062 node_to_node_map[this_mesh_nodes[ret_index].second] = node_id;
2063 other_to_this_node_map[node_id] = this_mesh_nodes[ret_index].second;
2071 libmesh_error_msg_if(node_to_node_map.size() != other_to_this_node_map.size(),
2072 "Error: Found multiple matching nodes in stitch_meshes");
2085 libmesh_warning(
"No valid h_min value was found, falling back on " 2086 "absolute distance check in the N^2 search algorithm.");
2093 for (
const auto & this_node_id : this_boundary_node_ids)
2097 bool found_matching_nodes =
false;
2099 for (
const auto & other_node_id : other_boundary_node_ids)
2101 const Node & other_node = other_mesh->
node_ref(other_node_id);
2103 Real node_distance = (this_node - other_node).
norm();
2105 if (node_distance < tol*h_min)
2108 libmesh_error_msg_if(found_matching_nodes,
2109 "Error: Found multiple matching nodes in stitch_meshes");
2111 node_to_node_map[this_node_id] = other_node_id;
2112 other_to_this_node_map[other_node_id] = this_node_id;
2114 found_matching_nodes =
true;
2122 for (
auto & el : other_mesh->element_ptr_range())
2129 for (
auto & n : el->node_ref_range())
2130 if (
const auto it = other_to_this_node_map.find(n.id());
2131 it != other_to_this_node_map.end())
2132 node_to_elems_map[it->second].push_back( el->id() );
2137 libMesh::out <<
"In UnstructuredMesh::stitch_meshes:\n" 2138 <<
"Found " << node_to_node_map.size()
2139 <<
" matching nodes.\n" 2143 if (enforce_all_nodes_match_on_boundaries)
2145 std::size_t n_matching_nodes = node_to_node_map.size();
2146 std::size_t this_mesh_n_nodes = this_boundary_node_ids.size();
2147 std::size_t other_mesh_n_nodes = other_boundary_node_ids.size();
2148 libmesh_error_msg_if((n_matching_nodes != this_mesh_n_nodes) || (n_matching_nodes != other_mesh_n_nodes),
2149 "Error: We expected the number of nodes to match.");
2152 if (merge_boundary_nodes_all_or_nothing)
2154 std::size_t n_matching_nodes = node_to_node_map.size();
2155 std::size_t this_mesh_n_nodes = this_boundary_node_ids.size();
2156 std::size_t other_mesh_n_nodes = other_boundary_node_ids.size();
2157 if ((n_matching_nodes != this_mesh_n_nodes) || (n_matching_nodes != other_mesh_n_nodes))
2162 "UnstructuredMesh::stitch_meshes because not " 2163 "all boundary nodes were matched." 2166 node_to_node_map.clear();
2167 other_to_this_node_map.clear();
2168 node_to_elems_map.clear();
2176 libMesh::out <<
"Skip node merging in UnstructuredMesh::stitch_meshes:" << std::endl;
2184 #ifdef LIBMESH_ENABLE_UNIQUE_ID 2192 if (
this!=other_mesh)
2194 LOG_SCOPE(
"stitch_meshes copying",
"UnstructuredMesh");
2198 for (
auto & pr : node_to_node_map)
2199 pr.second += node_delta;
2201 for (
auto & pr : node_to_elems_map)
2202 for (
auto & entry : pr.second)
2203 entry += elem_delta;
2225 std::unordered_map<subdomain_id_type, subdomain_id_type> id_remapping;
2226 if (remap_subdomain_ids)
2230 std::unordered_map<std::string, subdomain_id_type> other_map_reversed;
2231 for (
auto & [sid, sname] : other_map)
2232 other_map_reversed.emplace(sname, sid);
2234 std::unordered_map<std::string, subdomain_id_type> this_map_reversed;
2235 for (
auto & [sid, sname] : this_map)
2236 this_map_reversed.emplace(sname, sid);
2241 std::set<subdomain_id_type> all_subdomains;
2242 for (
auto & el :
mesh.element_ptr_range())
2243 all_subdomains.insert(el->subdomain_id());
2244 return all_subdomains;
2247 const auto this_subdomains = get_subdomains(*
this);
2248 const auto other_subdomains = get_subdomains(*other_mesh);
2250 for (
auto & [sid, sname] : this_map)
2255 if (
const auto other_reverse_it = other_map_reversed.find(sname);
2256 other_reverse_it != other_map_reversed.end() && other_reverse_it->second != sid)
2257 id_remapping[other_reverse_it->second] = sid;
2262 if (other_subdomains.count(sid) && !other_map.count(sid))
2263 libmesh_error_msg(
"Can't safely stitch with a mesh sharing subdomain id " 2264 << sid <<
" but not subdomain name " << sname);
2269 if (!this_subdomains.empty())
2270 next_free_id = *this_subdomains.rbegin() + 1;
2271 if (!other_subdomains.empty())
2273 std::max(next_free_id,
2274 cast_int<subdomain_id_type>
2275 (*other_subdomains.rbegin() + 1));
2277 for (
auto & [sid, sname] : other_map)
2282 if (!this_map_reversed.count(sname))
2286 if (this_subdomains.count(sid))
2290 if (!this_map.count(sid))
2291 libmesh_error_msg(
"Can't safely stitch with a mesh sharing subdomain id " 2292 << sid <<
" but under subdomain name " << sname);
2301 libmesh_error_msg_if ((!this_subdomains.empty() &&
2302 next_free_id < *this_subdomains.rbegin()) ||
2303 (!other_subdomains.empty() &&
2304 next_free_id < *other_subdomains.rbegin()),
2305 "Subdomain id overflow");
2307 id_remapping[sid] = next_free_id++;
2321 elem_delta, node_delta,
2322 unique_delta, &id_remapping);
2330 boundary.
add_node(std::get<0>(t) + node_delta,
2334 boundary.
add_side(std::get<0>(t) + elem_delta,
2339 boundary.
add_edge(std::get<0>(t) + elem_delta,
2350 ns_id_to_name.insert(other_ns_id_to_name.begin(), other_ns_id_to_name.end());
2354 ss_id_to_name.insert(other_ss_id_to_name.begin(), other_ss_id_to_name.end());
2358 es_id_to_name.insert(other_es_id_to_name.begin(), other_es_id_to_name.end());
2368 other_mesh->
get_elemsets(elemset_code, other_id_set_to_fill);
2377 this_elemset_codes.end(),
2380 if (it != this_elemset_codes.end())
2388 libmesh_error_msg_if(other_id_set_to_fill != this_id_set_to_fill,
2389 "Attempted to stitch together meshes with conflicting elemset codes.");
2407 LOG_SCOPE(
"stitch_meshes node updates",
"UnstructuredMesh");
2410 std::vector<boundary_id_type> bc_ids;
2412 for (
const auto & [target_node_id, elem_vec] : node_to_elems_map)
2414 dof_id_type other_node_id = node_to_node_map[target_node_id];
2417 std::size_t n_elems = elem_vec.size();
2418 for (std::size_t i=0; i<n_elems; i++)
2424 unsigned int local_node_index = el->
local_node(other_node_id);
2430 el->
set_node(local_node_index, &target_node);
2437 LOG_SCOPE(
"stitch_meshes node deletion",
"UnstructuredMesh");
2438 for (
const auto & [other_node_id, this_node_id] : node_to_node_map)
2442 if ((
this == other_mesh) && (this_node_id == other_node_id))
2456 if (skip_find_neighbors)
2458 LOG_SCOPE(
"stitch_meshes neighbor fixes",
"UnstructuredMesh");
2461 std::unique_ptr<const Elem> my_side, their_side;
2463 std::set<dof_id_type> fixed_elems;
2464 for (
const auto & pr : node_to_elems_map)
2466 std::size_t n_elems = pr.second.size();
2467 for (std::size_t i=0; i<n_elems; i++)
2470 if (!fixed_elems.count(elem_id))
2473 fixed_elems.insert(elem_id);
2479 auto bounds = side_to_elem_map.equal_range(key);
2481 if (bounds.first != bounds.second)
2487 while (bounds.first != bounds.second)
2490 Elem * neighbor =
const_cast<Elem *
>(bounds.first->second.first);
2493 const unsigned int ns = bounds.first->second.second;
2494 neighbor->
side_ptr(their_side, ns);
2506 if ((*my_side == *their_side) &&
2508 ((el->
dim() != 1) || (ns != s)))
2539 side_to_elem_map.erase (bounds.first);
2563 if (clear_stitched_boundary_ids)
2565 LOG_SCOPE(
"stitch_meshes clear bcids",
"UnstructuredMesh");
2568 this_mesh_boundary_id, other_mesh_boundary_id,
true);
2572 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.
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.
IntRange< unsigned short > side_index_range() const
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.
void set_isnt_prepared()
Tells this we have done some operation where we should no longer consider ourself prepared...
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.
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.
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
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.
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
void inherit_data_from(const Elem &src)
A helper function for copying generic element data (mapping, subdomain, processor) from an element to...
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
virtual void write(const std::string &name) const override
Write the file specified by name.
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
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