21 #include "libmesh/libmesh_config.h" 22 #include "libmesh/libmesh_logging.h" 23 #include "libmesh/boundary_info.h" 24 #include "libmesh/distributed_mesh.h" 25 #include "libmesh/elem.h" 26 #include "libmesh/mesh_communication.h" 27 #include "libmesh/mesh_serializer.h" 28 #include "libmesh/parallel.h" 29 #include "libmesh/partitioner.h" 30 #include "libmesh/remote_elem.h" 31 #include "libmesh/unstructured_mesh.h" 32 #include "libmesh/elem_side_builder.h" 47 template <
class Key,
class T,
class Pred>
48 void erase_if(std::multimap<Key,T> & map, Key k, Pred pred)
50 auto rng = map.equal_range(k);
52 while (it != rng.second)
63 template <
class Key,
class T,
class Pred>
64 void erase_if(std::multimap<Key,T> & map, Pred pred)
66 auto it = map.begin();
67 while (it != map.end())
77 template <
typename Map,
typename T>
78 void renumber_name(Map & m, T old_id, T new_id)
80 if (
const auto it = std::as_const(m).find(old_id);
83 m[new_id] = it->second;
106 _children_on_boundary(false)
170 const Node * other_node =
178 auto compare_edges = [&](
const Elem * elem,
179 const Elem * other_elem,
180 unsigned short int edge)
187 std::vector<boundary_id_type> our_edges, other_edges;
190 if (our_edges.size() != other_edges.size())
193 std::sort(our_edges.begin(), our_edges.end());
194 std::sort(other_edges.begin(), other_edges.end());
196 if (our_edges[i] != other_edges[i])
201 for (
const auto & [other_elem, edge_id_pair] : other_boundary_info.
_boundary_edge_id)
204 if (!compare_edges(elem, other_elem, edge_id_pair.first))
211 if (!compare_edges(elem, other_elem, edge_id_pair.first))
215 auto compare_sides = [&](
const Elem * elem,
216 const Elem * other_elem,
217 unsigned short int side)
224 std::vector<boundary_id_type> our_sides, other_sides;
226 other_boundary_info.
boundary_ids(other_elem, side, other_sides);
227 if (our_sides.size() != other_sides.size())
230 std::sort(our_sides.begin(), our_sides.end());
231 std::sort(other_sides.begin(), other_sides.end());
233 if (our_sides[i] != other_sides[i])
238 for (
const auto & [other_elem, side_id_pair] : other_boundary_info.
_boundary_side_id)
241 if (!compare_sides(elem, other_elem, side_id_pair.first))
248 if (!compare_sides(elem, other_elem, side_id_pair.first))
252 auto compare_shellfaces = [&](
const Elem * elem,
253 const Elem * other_elem,
254 unsigned short int shellface)
261 std::vector<boundary_id_type> our_shellfaces, other_shellfaces;
264 if (our_shellfaces.size() != other_shellfaces.size())
267 std::sort(our_shellfaces.begin(), our_shellfaces.end());
268 std::sort(other_shellfaces.begin(), other_shellfaces.end());
270 if (our_shellfaces[i] != other_shellfaces[i])
278 if (!compare_shellfaces(elem, other_elem, shellface_id_pair.first))
285 if (!compare_shellfaces(elem, other_elem, shellface_id_pair.first))
292 auto compare_sets = [](
const auto & set1,
const auto & set2)
294 if (set1.size() != set2.size())
297 if (!set2.count(bid))
317 auto compare_maps = [](
const auto & map1,
const auto & map2)
319 if (map1.size() != map2.size())
321 for (
const auto & pair : map1)
322 if (!map2.count(pair.first) ||
323 map2.at(pair.first) != pair.second)
385 if (
const auto it = old_ns_id_to_name.find(
id);
386 it != old_ns_id_to_name.end())
395 if (
const auto it = old_es_id_to_name.find(
id);
396 it != old_es_id_to_name.end())
405 if (
const auto it = old_ss_id_to_name.find(
id);
406 it != old_ss_id_to_name.end())
446 std::set<boundary_id_type> request_boundary_ids(
_boundary_ids);
451 this->
sync(request_boundary_ids,
461 std::set<subdomain_id_type> subdomains_relative_to;
464 this->
sync(requested_boundary_ids,
466 subdomains_relative_to);
473 const std::set<subdomain_id_type> & subdomains_relative_to)
475 LOG_SCOPE(
"sync()",
"BoundaryInfo");
477 boundary_mesh.
clear();
504 std::unique_ptr<MeshBase> mesh_copy;
508 auto serializer = std::make_unique<MeshSerializer>
517 std::map<dof_id_type, dof_id_type> node_id_map;
519 this->
_find_id_maps(requested_boundary_ids, 0, &node_id_map, 0,
nullptr, subdomains_relative_to);
522 for (
const auto & node :
_mesh->node_ptr_range())
525 if (node_id_map.count(node_id))
527 boundary_mesh.
add_point(*node, node_id_map[node_id], node->processor_id());
530 std::vector<boundary_id_type> node_boundary_ids;
532 for (
const auto & node_bid : node_boundary_ids)
542 subdomains_relative_to,
551 for (
auto & new_elem : boundary_mesh.element_ptr_range())
553 for (
auto nn : new_elem->node_index_range())
557 boundary_mesh.
node_ptr(node_id_map[new_elem->node_id(nn)]);
562 libmesh_assert_equal_to (new_node->
id(),
563 node_id_map[new_elem->node_id(nn)]);
566 new_elem->set_node(nn, new_node);
575 for (
auto & new_elem : boundary_mesh.element_ptr_range())
578 new_elem->interior_parent()->id();
580 if (!mesh_copy->query_elem_ptr(interior_parent_id))
581 new_elem->set_interior_parent
604 std::map<dof_id_type, dof_id_type> & node_id_map,
605 std::map<dof_id_type, unsigned char> & side_id_map,
608 LOG_SCOPE(
"get_side_and_node_maps()",
"BoundaryInfo");
616 const Elem * interior_parent_side;
618 for (
const auto & boundary_elem : boundary_mesh.active_element_ptr_range())
624 unsigned char interior_parent_side_index = 0;
625 bool found_matching_sides =
false;
628 interior_parent_side = &side_builder(*interior_parent, side);
631 if (va_distance < (tolerance * boundary_elem->hmin()))
633 interior_parent_side_index = cast_int<unsigned char>(side);
634 found_matching_sides =
true;
639 libmesh_error_msg_if(!found_matching_sides,
"No matching side found within the specified tolerance");
641 side_id_map[boundary_elem->id()] = interior_parent_side_index;
643 for (
auto local_node_index : boundary_elem->node_index_range())
645 dof_id_type boundary_node_id = boundary_elem->node_id(local_node_index);
648 node_id_map[interior_node_id] = boundary_node_id;
657 bool store_parent_side_ids)
660 std::set<subdomain_id_type> subdomains_relative_to;
665 subdomains_relative_to,
666 store_parent_side_ids);
673 const std::set<subdomain_id_type> & subdomains_relative_to,
674 bool store_parent_side_ids)
676 LOG_SCOPE(
"add_elements()",
"BoundaryInfo");
695 std::map<std::pair<dof_id_type, unsigned char>,
dof_id_type> side_id_map;
701 subdomains_relative_to);
707 typedef std::vector<std::pair<dof_id_type, unsigned char>>
709 side_container sides_to_add;
711 for (
const auto & elem :
_mesh->element_ptr_range())
720 !subdomains_relative_to.count(elem->subdomain_id()))
723 for (
auto s : elem->side_index_range())
725 bool add_this_side =
false;
728 std::vector<boundary_id_type> bcids;
734 if (requested_boundary_ids.count(bcid))
736 add_this_side =
true;
747 if (requested_boundary_ids.count(
invalid_id) &&
748 elem->neighbor_ptr(s) ==
nullptr)
749 add_this_side =
true;
752 sides_to_add.emplace_back(elem->id(), s);
756 #ifdef LIBMESH_ENABLE_UNIQUE_ID 763 unsigned int parent_side_index_tag = store_parent_side_ids ?
766 for (
const auto & [elem_id, s] : sides_to_add)
774 const std::pair<dof_id_type, unsigned char> side_pair(elem_id, s);
778 const dof_id_type new_side_id = side_id_map[side_pair];
780 side->set_id(new_side_id);
782 #ifdef LIBMESH_ENABLE_UNIQUE_ID 783 side->set_unique_id(old_max_unique_id + new_side_id);
787 Elem * new_elem = boundary_mesh.
add_elem(std::move(side));
791 if (store_parent_side_ids)
794 #ifdef LIBMESH_ENABLE_AMR 801 const std::pair<dof_id_type, unsigned char> parent_side_pair(elem->
parent()->
id(), s);
805 Elem * side_parent = boundary_mesh.
elem_ptr(side_id_map[parent_side_pair]);
816 bool found_child =
false;
818 if (new_elem->
node_ptr(v) == side_parent->node_ptr(v))
820 side_parent->add_child(new_elem, v);
829 libmesh_assert_equal_to (new_elem->
n_vertices(), 3);
830 side_parent->add_child(new_elem, 3);
860 const unsigned short bdy_n_sides = new_elem->
n_sides();
861 const unsigned short bdy_n_nodes = new_elem->
n_nodes();
872 for (
unsigned short boundary_side = 0;
873 boundary_side != bdy_n_sides; ++boundary_side)
877 bool found_all_nodes =
true;
878 for (
unsigned short boundary_node = 0;
879 boundary_node != bdy_n_nodes; ++boundary_node)
885 bool found_this_node =
false;
886 for (
unsigned short interior_node = 0;
887 interior_node !=
n_nodes; ++interior_node)
893 if (new_elem->
point(boundary_node) ==
894 elem->
point(interior_node))
896 found_this_node =
true;
900 if (!found_this_node)
902 found_all_nodes =
false;
927 # ifdef LIBMESH_HAVE_RTTI 944 libmesh_error_msg_if(!node_ptr,
945 "BoundaryInfo::add_node(): Could not retrieve pointer for node " 947 <<
", no boundary id was added.");
958 "ERROR: You may not set a boundary ID of " 960 <<
"\n That is reserved for internal use.");
975 const std::vector<boundary_id_type> & ids)
990 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
991 std::sort(unique_ids.begin(), unique_ids.end());
992 std::vector<boundary_id_type>::iterator new_end =
993 std::unique(unique_ids.begin(), unique_ids.end());
995 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
998 "ERROR: You may not set a boundary ID of " 1000 <<
"\n That is reserved for internal use.");
1002 bool already_inserted =
false;
1003 for (
const auto & pr :
as_range(bounds))
1004 if (pr.second ==
id)
1006 already_inserted =
true;
1009 if (already_inserted)
1026 const unsigned short int edge,
1035 const unsigned short int edge,
1041 libmesh_assert_equal_to (elem->
level(), 0);
1044 libmesh_assert_less (edge, elem->
n_edges());
1047 "ERROR: You may not set a boundary ID of " 1049 <<
"\n That is reserved for internal use.");
1053 if (pr.second.first == edge &&
1054 pr.second.second ==
id)
1065 const unsigned short int edge,
1066 const std::vector<boundary_id_type> & ids)
1074 libmesh_assert_equal_to (elem->
level(), 0);
1077 libmesh_assert_less (edge, elem->
n_edges());
1087 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1088 std::sort(unique_ids.begin(), unique_ids.end());
1089 std::vector<boundary_id_type>::iterator new_end =
1090 std::unique(unique_ids.begin(), unique_ids.end());
1092 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1095 "ERROR: You may not set a boundary ID of " 1097 <<
"\n That is reserved for internal use.");
1099 bool already_inserted =
false;
1100 for (
const auto & pr :
as_range(bounds))
1101 if (pr.second.first == edge &&
1102 pr.second.second ==
id)
1104 already_inserted =
true;
1107 if (already_inserted)
1119 const unsigned short int shellface,
1128 const unsigned short int shellface,
1134 libmesh_assert_equal_to (elem->
level(), 0);
1137 libmesh_assert_less(shellface, 2);
1140 "ERROR: You may not set a boundary ID of " 1142 <<
"\n That is reserved for internal use.");
1146 if (pr.second.first == shellface &&
1147 pr.second.second ==
id)
1158 const unsigned short int shellface,
1159 const std::vector<boundary_id_type> & ids)
1167 libmesh_assert_equal_to (elem->
level(), 0);
1170 libmesh_assert_less(shellface, 2);
1180 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1181 std::sort(unique_ids.begin(), unique_ids.end());
1182 std::vector<boundary_id_type>::iterator new_end =
1183 std::unique(unique_ids.begin(), unique_ids.end());
1185 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1188 "ERROR: You may not set a boundary ID of " 1190 <<
"\n That is reserved for internal use.");
1192 bool already_inserted =
false;
1193 for (
const auto & pr :
as_range(bounds))
1194 if (pr.second.first == shellface &&
1195 pr.second.second ==
id)
1197 already_inserted =
true;
1200 if (already_inserted)
1211 const unsigned short int side,
1220 const unsigned short int side,
1226 libmesh_assert_less (side, elem->
n_sides());
1228 libmesh_error_msg_if(
id ==
invalid_id,
"ERROR: You may not set a boundary ID of " 1230 <<
"\n That is reserved for internal use.");
1234 if (pr.second.first == side &&
1235 pr.second.second ==
id)
1238 #ifdef LIBMESH_ENABLE_AMR 1248 std::vector<boundary_id_type> bd_ids;
1251 if(std::find(bd_ids.begin(), bd_ids.end(), id) != bd_ids.end())
1252 libmesh_not_implemented_msg(
"Trying to add boundary ID " 1253 + std::to_string(
id)
1254 +
" which already exists on the ancestors.");
1266 const unsigned short int side,
1267 const std::vector<boundary_id_type> & ids)
1275 libmesh_assert_less (side, elem->
n_sides());
1277 #ifdef LIBMESH_ENABLE_AMR 1287 std::vector<boundary_id_type> bd_ids;
1290 for (
const auto id : ids)
1291 if(std::find(bd_ids.begin(), bd_ids.end(), id) != bd_ids.end())
1292 libmesh_not_implemented_msg(
"Trying to add boundary ID " 1293 + std::to_string(
id)
1294 +
" which already exists on the ancestors.");
1306 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1307 std::sort(unique_ids.begin(), unique_ids.end());
1308 std::vector<boundary_id_type>::iterator new_end =
1309 std::unique(unique_ids.begin(), unique_ids.end());
1311 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1314 "ERROR: You may not set a boundary ID of " 1316 <<
"\n That is reserved for internal use.");
1318 bool already_inserted =
false;
1319 for (
const auto & pr :
as_range(bounds))
1320 if (pr.second.first == side && pr.second.second ==
id)
1322 already_inserted =
true;
1325 if (already_inserted)
1340 if (pr.second ==
id)
1349 std::vector<boundary_id_type> & vec_to_fill)
const 1352 vec_to_fill.clear();
1355 vec_to_fill.push_back(pr.second);
1363 return cast_int<unsigned int>(
std::distance(pos.first, pos.second));
1369 const unsigned short int edge,
1370 std::vector<boundary_id_type> & vec_to_fill)
const 1375 vec_to_fill.clear();
1378 libmesh_assert_less (edge, elem->
n_edges());
1382 const Elem * searched_elem = elem;
1383 #ifdef LIBMESH_ENABLE_AMR 1384 if (elem->
level() != 0)
1389 bool found_boundary_edge =
false;
1397 found_boundary_edge =
true;
1403 if (!found_boundary_edge)
1409 while (searched_elem->parent() !=
nullptr)
1411 const Elem * parent = searched_elem->
parent();
1414 searched_elem = parent;
1422 if (pr.second.first == edge)
1423 vec_to_fill.push_back(pr.second.second);
1429 const unsigned short int edge)
const 1431 std::vector<boundary_id_type> ids;
1433 return cast_int<unsigned int>(ids.size());
1439 const unsigned short int edge,
1440 std::vector<boundary_id_type> & vec_to_fill)
const 1445 libmesh_assert_less (edge, elem->
n_edges());
1448 vec_to_fill.clear();
1456 if (pr.second.first == edge)
1457 vec_to_fill.push_back(pr.second.second);
1463 const unsigned short int shellface,
1464 std::vector<boundary_id_type> & vec_to_fill)
const 1469 libmesh_assert_less(shellface, 2);
1472 vec_to_fill.clear();
1476 const Elem * searched_elem = elem;
1477 #ifdef LIBMESH_ENABLE_AMR 1478 if (elem->
level() != 0)
1480 while (searched_elem->
parent() !=
nullptr)
1482 const Elem * parent = searched_elem->
parent();
1483 searched_elem = parent;
1490 if (pr.second.first == shellface)
1491 vec_to_fill.push_back(pr.second.second);
1497 const unsigned short int shellface)
const 1499 std::vector<boundary_id_type> ids;
1501 return cast_int<unsigned int>(ids.size());
1507 const unsigned short int shellface,
1508 std::vector<boundary_id_type> & vec_to_fill)
const 1513 libmesh_assert_less(shellface, 2);
1516 vec_to_fill.clear();
1524 if (pr.second.first == shellface)
1525 vec_to_fill.push_back(pr.second.second);
1531 const unsigned short int side,
1534 std::vector<boundary_id_type> ids;
1536 return (std::find(ids.begin(), ids.end(), id) != ids.end());
1541 std::vector<std::vector<boundary_id_type>> & vec_to_fill)
const 1546 vec_to_fill.clear();
1547 auto num_sides = elem->
n_sides();
1554 vec_to_fill.resize(num_sides);
1559 const Elem * searched_elem = elem;
1561 #ifdef LIBMESH_ENABLE_AMR 1562 if (elem->
level() != 0)
1569 std::vector<bool> search_on_side(elem->
n_sides(),
true);
1570 bool keep_searching =
true;
1571 while (searched_elem && keep_searching)
1577 if (search_on_side[side] && pr.second.first == side &&
1578 std::find(vec_to_fill[side].begin(), vec_to_fill[side].end(), pr.second.second) ==
1579 vec_to_fill[side].end())
1580 vec_to_fill[side].push_back(pr.second.second);
1583 const Elem * parent = searched_elem->
parent();
1588 if (search_on_side[side] &&
1590 search_on_side[side] =
false;
1592 searched_elem = parent;
1594 keep_searching = *std::max_element(search_on_side.begin(), search_on_side.end());
1603 std::vector<bool> search_on_side(elem->
n_sides(),
true);
1607 const Elem * searched_elem_for_side = elem;
1615 while (searched_elem_for_side->
parent() !=
nullptr)
1617 const Elem * parent = searched_elem_for_side->
parent();
1619 search_on_side[side] =
false;
1620 searched_elem_for_side = parent;
1624 if (*std::max_element(search_on_side.begin(), search_on_side.end()))
1626 if (search_on_side[pr.second.first])
1627 vec_to_fill[pr.second.first].push_back(pr.second.second);
1634 vec_to_fill[pr.second.first].push_back(pr.second.second);
1638 const unsigned short int side,
1639 std::vector<boundary_id_type> & vec_to_fill)
const 1644 libmesh_assert_less (side, elem->
n_sides());
1647 vec_to_fill.clear();
1653 const Elem * searched_elem = elem;
1655 #ifdef LIBMESH_ENABLE_AMR 1657 if (elem->
level() != 0)
1664 while (searched_elem)
1668 if (pr.second.first == side &&
1669 std::find(vec_to_fill.begin(), vec_to_fill.end(), pr.second.second) ==
1671 vec_to_fill.push_back(pr.second.second);
1674 const Elem * parent = searched_elem->
parent();
1680 searched_elem = parent;
1692 while (searched_elem->
parent() !=
nullptr)
1694 const Elem * parent = searched_elem->
parent();
1698 searched_elem = parent;
1706 if (pr.second.first == side)
1707 vec_to_fill.push_back(pr.second.second);
1714 const unsigned short int side)
const 1716 std::vector<boundary_id_type> ids;
1718 return cast_int<unsigned int>(ids.size());
1723 const unsigned short int side)
const 1725 std::vector<boundary_id_type> ids;
1727 return cast_int<unsigned int>(ids.size());
1733 const unsigned short int side,
1734 std::vector<boundary_id_type> & vec_to_fill)
const 1739 libmesh_assert_less (side, elem->
n_sides());
1742 vec_to_fill.clear();
1750 if (pr.second.first == side)
1751 vec_to_fill.push_back(pr.second.second);
1757 const Elem *
const old_elem,
1758 const Elem *
const new_elem)
1760 libmesh_assert_equal_to (old_elem->
n_sides(), new_elem->
n_sides());
1761 libmesh_assert_equal_to (old_elem->
n_edges(), new_elem->
n_edges());
1763 std::vector<boundary_id_type> bndry_ids;
1768 this->
add_side (new_elem, s, bndry_ids);
1774 this->
add_edge (new_elem, e, bndry_ids);
1777 for (
unsigned short sf=0; sf != 2; sf++)
1804 {
return val == id;});
1822 const unsigned short int edge)
1827 libmesh_assert_less (edge, elem->
n_edges());
1830 libmesh_assert_equal_to (elem->
level(), 0);
1835 {
return pr.first == edge;});
1841 const unsigned short int edge,
1847 libmesh_assert_less (edge, elem->
n_edges());
1850 libmesh_assert_equal_to (elem->
level(), 0);
1855 {
return pr.first == edge && pr.second == id;});
1860 const unsigned short int shellface)
1865 libmesh_assert_equal_to (elem->
level(), 0);
1868 libmesh_assert_less(shellface, 2);
1873 {
return pr.first == shellface;});
1879 const unsigned short int shellface,
1885 libmesh_assert_equal_to (elem->
level(), 0);
1888 libmesh_assert_less(shellface, 2);
1893 {
return pr.first == shellface && pr.second == id;});
1897 const unsigned short int side)
1902 libmesh_assert_less (side, elem->
n_sides());
1907 {
return pr.first == side;});
1913 const unsigned short int side,
1919 libmesh_assert_less (side, elem->
n_sides());
1921 #ifdef LIBMESH_ENABLE_AMR 1926 std::vector<boundary_id_type> bd_ids;
1928 if(std::find(bd_ids.begin(), bd_ids.end(), id) != bd_ids.end())
1930 std::vector<boundary_id_type> raw_bd_ids;
1932 if(std::find(raw_bd_ids.begin(), raw_bd_ids.end(), id) == raw_bd_ids.end())
1933 libmesh_not_implemented_msg(
"We cannot delete boundary ID " 1934 + std::to_string(
id) +
1935 " using a child because it is inherited from an ancestor.");
1943 {
return pr.first == side && pr.second == id;});
1977 this->
comm().
max(someone_has_it);
1978 if (!someone_has_it)
1985 {
return pr.second == id;});
2004 this->
comm().
max(someone_has_it);
2005 if (!someone_has_it)
2012 {
return pr.second == id;});
2030 this->
comm().
max(someone_has_it);
2031 if (!someone_has_it)
2038 {
return pr.second == id;});
2057 this->
comm().
max(someone_has_it);
2058 if (!someone_has_it)
2065 {
return val == id;});
2073 if (old_id == new_id)
2079 bool found_node =
false;
2081 if (p.second == old_id)
2095 bool found_edge =
false;
2097 if (p.second.second == old_id)
2101 this->
remove_edge(p.first, p.second.first, new_id);
2102 p.second.second = new_id;
2111 bool found_shellface =
false;
2113 if (p.second.second == old_id)
2118 p.second.second = new_id;
2119 found_shellface =
true;
2121 if (found_shellface)
2127 bool found_side =
false;
2129 if (p.second.second == old_id)
2133 this->
remove_side(p.first, p.second.first, new_id);
2134 p.second.second = new_id;
2143 if (found_node || found_edge || found_shellface || found_side)
2162 if (old_id == new_id)
2165 bool found_side =
false;
2167 if (p.second.second == old_id)
2171 this->
remove_side(p.first, p.second.first, new_id);
2172 p.second.second = new_id;
2201 if (old_id == new_id)
2204 bool found_edge =
false;
2206 if (p.second.second == old_id)
2210 this->
remove_edge(p.first, p.second.first, new_id);
2211 p.second.second = new_id;
2240 if (old_id == new_id)
2243 bool found_shellface =
false;
2245 if (p.second.second == old_id)
2250 p.second.second = new_id;
2251 found_shellface =
true;
2255 if (found_shellface)
2277 if (old_id == new_id)
2280 bool found_node =
false;
2282 if (p.second == old_id)
2315 const Elem * searched_elem = elem;
2327 if (pr.second.second == boundary_id_in)
2329 unsigned int side = pr.second.first;
2335 #ifdef LIBMESH_ENABLE_AMR 2342 const Elem * p = elem;
2346 while (p !=
nullptr)
2369 #ifdef LIBMESH_ENABLE_AMR 2377 const Elem * p = elem;
2378 while (p->
parent() !=
nullptr)
2389 if (pr.second.first == side && pr.second.second == boundary_id_in)
2408 std::vector<unsigned int>
2412 std::vector<unsigned int> returnval;
2414 const Elem * searched_elem = elem;
2423 if (pr.second.second == boundary_id_in)
2425 unsigned int side = pr.second.first;
2435 returnval.push_back(side);
2441 const Elem * p = elem;
2443 #ifdef LIBMESH_ENABLE_AMR 2445 while (p !=
nullptr)
2455 returnval.push_back(side);
2459 returnval.push_back(side);
2463 #ifdef LIBMESH_ENABLE_AMR 2470 const Elem * p = elem;
2471 while (p->
parent() !=
nullptr)
2484 if (pr.second.first == side && pr.second.second == boundary_id_in &&
2485 std::find(returnval.begin(), returnval.end(), side) == returnval.end())
2486 returnval.push_back(side);
2510 if (std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
2511 b_ids.push_back(
id);
2524 if (std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
2525 b_ids.push_back(
id);
2538 if (std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
2539 b_ids.push_back(
id);
2543 #ifdef LIBMESH_ENABLE_AMR 2556 const double number_of_sides_on_children =
std::pow(2, parent->
dim()-1);
2560 for (
unsigned int side_i = 0; side_i < parent->
n_sides(); ++side_i)
2565 std::map<unsigned short int, unsigned short int> boundary_counts;
2576 if (pr.second.first == side_i)
2577 ++boundary_counts[pr.second.second];
2584 for (
const auto & boundary : boundary_counts)
2585 if (boundary.second / number_of_sides_on_children > 0.5)
2586 this->
add_side(parent, side_i, boundary.first);
2590 this->
remove(parent->
child_ptr(child_i));
2602 parallel_object_only();
2623 parallel_object_only();
2625 std::size_t n_edge_bcs=0;
2631 this->
comm().
sum (n_edge_bcs);
2645 parallel_object_only();
2647 std::size_t n_shellface_bcs=0;
2653 this->
comm().
sum (n_shellface_bcs);
2655 return n_shellface_bcs;
2667 parallel_object_only();
2669 std::size_t n_nodesets=0;
2675 this->
comm().
sum (n_nodesets);
2682 std::vector<BoundaryInfo::NodeBCTuple>
2685 std::vector<NodeBCTuple> bc_tuples;
2689 bc_tuples.emplace_back(node->id(), bid);
2694 std::sort(bc_tuples.begin(), bc_tuples.end());
2696 std::sort(bc_tuples.begin(), bc_tuples.end(),
2698 {
return std::get<1>(left) < std::get<1>(right);});
2713 typedef std::set<std::pair<dof_id_type, boundary_id_type>> set_type;
2714 typedef std::vector<std::pair<dof_id_type, boundary_id_type>> vec_type;
2717 std::unordered_map<processor_id_type, set_type> nodes_to_push;
2718 std::unordered_map<processor_id_type, vec_type> node_vecs_to_push;
2729 if (elem->is_remote())
2732 auto [sidenum, bcid] = id_pair;
2734 if (!sideset_list.empty() && !sideset_list.count(bcid))
2738 std::vector<const Elem *> family;
2739 #ifdef LIBMESH_ENABLE_AMR 2742 family.push_back(elem);
2745 for (
const auto & cur_elem : family)
2747 side = &side_builder(*cur_elem, sidenum);
2753 if (!mesh_is_serial)
2757 if (proc_id != my_proc_id)
2758 nodes_to_push[proc_id].emplace(side->
node_id(i), bcid);
2771 for (
auto & [proc_id, s] : nodes_to_push)
2773 node_vecs_to_push[proc_id].assign(s.begin(), s.end());
2777 auto nodes_action_functor =
2780 const vec_type & received_nodes)
2782 for (
const auto & [dof_id, bndry_id] : received_nodes)
2786 Parallel::push_parallel_vector_data
2787 (this->
comm(), node_vecs_to_push, nodes_action_functor);
2791 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2795 for (
const auto & node :
_mesh->node_ptr_range())
2798 if (pid != my_proc_id)
2799 node_ids_requested[pid].push_back(node->id());
2802 typedef std::vector<boundary_id_type> datum_type;
2804 auto node_bcid_gather_functor =
2807 const std::vector<dof_id_type> & ids,
2808 std::vector<datum_type> & data)
2810 const std::size_t query_size = ids.size();
2811 data.resize(query_size);
2813 for (std::size_t i=0; i != query_size; ++i)
2817 auto node_bcid_action_functor =
2820 const std::vector<dof_id_type> & ids,
2821 const std::vector<datum_type> & data)
2827 datum_type * datum_type_ex =
nullptr;
2828 Parallel::pull_parallel_vector_data
2829 (this->
comm(), node_ids_requested, node_bcid_gather_functor,
2830 node_bcid_action_functor, datum_type_ex);
2836 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2840 for (
const auto & elem :
_mesh->element_ptr_range())
2844 elem_ids_requested[pid].push_back(elem->id());
2847 typedef std::vector<std::pair<unsigned short int, boundary_id_type>> datum_type;
2850 auto elem_id_gather_functor =
2853 const std::vector<dof_id_type> & ids,
2854 std::vector<datum_type> & data)
2856 data.resize(ids.size());
2861 data[i].push_back(std::make_pair(pr.second.first, pr.second.second));
2865 auto elem_id_action_functor =
2868 const std::vector<dof_id_type> & ids,
2869 std::vector<datum_type> & data)
2877 for (
const auto & [
side_id, bndry_id] : data[i])
2883 datum_type * datum_type_ex =
nullptr;
2884 Parallel::pull_parallel_vector_data
2885 (this->
comm(), elem_ids_requested, elem_id_gather_functor,
2886 elem_id_action_functor, datum_type_ex);
2892 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2896 for (
const auto & node :
_mesh->node_ptr_range())
2900 node_ids_requested[pid].push_back(node->id());
2903 typedef std::vector<boundary_id_type> datum_type;
2906 auto node_id_gather_functor =
2909 const std::vector<dof_id_type> & ids,
2910 std::vector<datum_type> & data)
2912 data.resize(ids.size());
2917 data[i].push_back(pr.second);
2922 auto node_id_action_functor =
2925 const std::vector<dof_id_type> & ids,
2926 std::vector<datum_type> & data)
2934 for (
const auto & pr : data[i])
2940 datum_type * datum_type_ex =
nullptr;
2941 Parallel::pull_parallel_vector_data
2942 (this->
comm(), node_ids_requested, node_id_gather_functor,
2943 node_id_action_functor, datum_type_ex);
2951 libMesh::out <<
"No boundary node IDs have been added: cannot build side list!" << std::endl;
2958 const Elem * side_elem;
2960 for (
const auto & elem :
_mesh->active_element_ptr_range())
2961 for (
auto side : elem->side_index_range())
2963 side_elem = &side_builder(*elem, side);
2966 std::map<boundary_id_type, unsigned> nodesets_node_count;
2972 if (nodeset_list.empty() || nodeset_list.count(pr.second))
2973 nodesets_node_count[pr.second]++;
2979 for (
const auto & pr : nodesets_node_count)
2980 if (pr.second == side_elem->
n_nodes())
2987 if (nset_name !=
"")
2996 std::vector<BoundaryInfo::BCTuple>
2999 std::vector<BCTuple> bc_triples;
3003 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3010 std::sort(bc_triples.begin(), bc_triples.end());
3012 std::sort(bc_triples.begin(), bc_triples.end(),
3014 {
return std::get<1>(left) < std::get<1>(right);});
3016 std::sort(bc_triples.begin(), bc_triples.end(),
3018 {
return std::get<2>(left) < std::get<2>(right);});
3025 std::vector<BoundaryInfo::BCTuple>
3028 std::vector<BCTuple> bc_triples;
3034 if (elem->is_remote())
3038 std::vector<const Elem *> family;
3039 #ifdef LIBMESH_ENABLE_AMR 3040 elem->active_family_tree_by_side(family, id_pair.first);
3042 family.push_back(elem);
3046 for (
const auto & f : family)
3047 bc_triples.emplace_back(f->id(), id_pair.first, id_pair.second);
3052 std::sort(bc_triples.begin(), bc_triples.end());
3058 std::vector<BoundaryInfo::BCTuple>
3061 std::vector<BCTuple> bc_triples;
3065 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3069 std::sort(bc_triples.begin(), bc_triples.end());
3075 std::vector<BoundaryInfo::BCTuple>
3078 std::vector<BCTuple> bc_triples;
3082 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3086 std::sort(bc_triples.begin(), bc_triples.end());
3097 out_stream <<
"Nodal Boundary conditions:" << std::endl
3098 <<
"--------------------------" << std::endl
3099 <<
" (Node No., ID) " << std::endl;
3102 out_stream <<
" (" << node->id()
3104 <<
")" << std::endl;
3110 out_stream << std::endl
3111 <<
"Edge Boundary conditions:" << std::endl
3112 <<
"-------------------------" << std::endl
3113 <<
" (Elem No., Edge No., ID) " << std::endl;
3116 out_stream <<
" (" << elem->id()
3117 <<
", " << id_pair.first
3118 <<
", " << id_pair.second
3119 <<
")" << std::endl;
3125 out_stream << std::endl
3126 <<
"Shell-face Boundary conditions:" << std::endl
3127 <<
"-------------------------" << std::endl
3128 <<
" (Elem No., Shell-face No., ID) " << std::endl;
3131 out_stream <<
" (" << elem->id()
3132 <<
", " << id_pair.first
3133 <<
", " << id_pair.second
3134 <<
")" << std::endl;
3140 out_stream << std::endl
3141 <<
"Side Boundary conditions:" << std::endl
3142 <<
"-------------------------" << std::endl
3143 <<
" (Elem No., Side No., ID) " << std::endl;
3146 out_stream <<
" (" << elem->id()
3147 <<
", " << id_pair.first
3148 <<
", " << id_pair.second
3149 <<
")" << std::endl;
3160 out_stream <<
"Nodal Boundary conditions:" << std::endl
3161 <<
"--------------------------" << std::endl
3162 <<
" (ID, number of nodes) " << std::endl;
3164 std::map<boundary_id_type, std::size_t> ID_counts;
3167 ID_counts[pr.second]++;
3169 for (
const auto & [bndry_id, cnt] : ID_counts)
3170 out_stream <<
" (" << bndry_id
3172 <<
")" << std::endl;
3178 out_stream << std::endl
3179 <<
"Edge Boundary conditions:" << std::endl
3180 <<
"-------------------------" << std::endl
3181 <<
" (ID, number of edges) " << std::endl;
3183 std::map<boundary_id_type, std::size_t> ID_counts;
3186 ID_counts[pr.second.second]++;
3188 for (
const auto & [bndry_id, cnt] : ID_counts)
3189 out_stream <<
" (" << bndry_id
3191 <<
")" << std::endl;
3198 out_stream << std::endl
3199 <<
"Shell-face Boundary conditions:" << std::endl
3200 <<
"-------------------------" << std::endl
3201 <<
" (ID, number of shellfaces) " << std::endl;
3203 std::map<boundary_id_type, std::size_t> ID_counts;
3206 ID_counts[pr.second.second]++;
3208 for (
const auto & [bndry_id, cnt] : ID_counts)
3209 out_stream <<
" (" << bndry_id
3211 <<
")" << std::endl;
3217 out_stream << std::endl
3218 <<
"Side Boundary conditions:" << std::endl
3219 <<
"-------------------------" << std::endl
3220 <<
" (ID, number of sides) " << std::endl;
3222 std::map<boundary_id_type, std::size_t> ID_counts;
3225 ID_counts[pr.second.second]++;
3227 for (
const auto & [bndry_id, cnt] : ID_counts)
3228 out_stream <<
" (" << bndry_id
3230 <<
")" << std::endl;
3237 static const std::string empty_string;
3240 return empty_string;
3253 static const std::string empty_string;
3256 return empty_string;
3268 static const std::string empty_string;
3271 return empty_string;
3286 if (ss_name ==
name)
3291 if (ns_name ==
name)
3296 if (es_name ==
name)
3308 std::map<dof_id_type, dof_id_type> * node_id_map,
3310 std::map<std::pair<dof_id_type, unsigned char>,
dof_id_type> * side_id_map,
3311 const std::set<subdomain_id_type> & subdomains_relative_to)
3316 next_node_id = first_free_node_id + this->
processor_id();
3333 <std::set<std::pair<dof_id_type, unsigned char>>>
3334 side_id_set_by_level;
3352 bool hit_end_el =
false;
3357 !hit_end_el || (el != end_unpartitioned_el); ++el)
3359 if ((el == end_el) && !hit_end_el)
3368 std::size_t
n_levels = side_id_set_by_level.size();
3370 side_id_set_by_level.resize(
n_levels);
3379 next_node_id = first_free_node_id + this->
n_processors();
3382 if (el == end_unpartitioned_el)
3386 const Elem * elem = *el;
3400 bool add_this_side =
false;
3403 std::vector<boundary_id_type> bcids;
3409 if (requested_boundary_ids.count(bcid))
3411 add_this_side =
true;
3422 if (requested_boundary_ids.count(
invalid_id) &&
3424 add_this_side =
true;
3435 std::pair<dof_id_type, unsigned char> side_pair(elem->
id(), s);
3436 auto level = elem->
level();
3437 if (side_id_set_by_level.size() <= level)
3438 side_id_set_by_level.resize(level+1);
3439 auto & level_side_id_set = side_id_set_by_level[level];
3441 level_side_id_set.insert(side_pair);
3444 side = &side_builder(*elem, s);
3456 if (node_id_map && !node_id_map->count(node_id))
3458 (*node_id_map)[node_id] = next_node_id;
3475 for (
auto level :
make_range(side_id_set_by_level.size()))
3477 for (
auto side_pair : side_id_set_by_level[level])
3478 (*side_id_map)[side_pair] = next_elem_id++;
3485 const bool clear_nodeset_data)
3496 [sideset_id, other_sideset_id](
3497 const std::pair<const Elem *, std::pair<unsigned short int, boundary_id_type>> & pred_pr,
3498 const std::multimap<const Elem *, std::pair<unsigned short int, boundary_id_type>> &
3500 const Elem & elem = *pred_pr.first;
3501 const auto elem_side = pred_pr.second.first;
3504 return std::make_pair(
false, pred_container.end());
3506 const auto elem_side_bnd_id = pred_pr.second.second;
3508 if (elem_side_bnd_id == sideset_id)
3509 other_elem_side_bnd_id = other_sideset_id;
3510 else if (elem_side_bnd_id == other_sideset_id)
3511 other_elem_side_bnd_id = sideset_id;
3513 return std::make_pair(
false, pred_container.end());
3516 const typename std::decay<decltype(pred_container)>::type::value_type other_sideset_info(
3517 other_elem, std::make_pair(other_elem_side, other_elem_side_bnd_id));
3518 auto other_range = pred_container.equal_range(other_elem);
3520 other_range.first != other_range.second,
3521 "No matching sideset information for other element in boundary information");
3522 auto other_it = std::find(other_range.first, other_range.second, other_sideset_info);
3524 other_it != pred_container.end(),
3525 "No matching sideset information for other element in boundary information");
3526 return std::make_pair(
true, other_it);
3529 for (; it != end_it;)
3532 if (pred_result.first)
3538 if (clear_nodeset_data)
3540 const Elem & elem = *it->first;
3541 const Elem & neigh = *pred_result.second->first;
3542 const auto elem_side = it->second.first;
3544 const auto elem_bcid = it->second.second;
3547 for (
const auto local_node_num : elem.
nodes_on_side(elem_side))
3550 for (
const auto local_node_num : neigh.
nodes_on_side(neigh_side))
3571 const std::set<boundary_id_type> &
3582 auto verify_multimap = [](
const auto & themap) {
3583 for (
const auto & [key, val] : themap)
3585 auto range = themap.equal_range(key);
3588 for (
auto it = range.first; it != range.second; ++it)
3589 if (it->second == val)
void remove_shellface_id(boundary_id_type id, bool global=false)
Removes all shellfaces with boundary id id from the BoundaryInfo object, removes it from the set of s...
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
void renumber_shellface_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all shellfaces with boundary id old_id to instead be labeled by boundary id new_id...
void remove_id(boundary_id_type id, bool global=false)
Removes all entities (nodes, sides, edges, shellfaces) with boundary id id from their respective cont...
void libmesh_assert_valid_multimaps() const
Helper method for ensuring that our multimaps don't contain entries with duplicate keys and values...
std::size_t n_boundary_conds() const
RefinementState refinement_flag() const
std::tuple< dof_id_type, unsigned short int, boundary_id_type > BCTuple
Create a list of (element_id, side_id, boundary_id) tuples for relevant sides.
std::map< boundary_id_type, std::string > _ns_id_to_name
This structure maintains the mapping of named node sets for file formats (Exodus, Gmsh) that support ...
bool _children_on_boundary
std::set< boundary_id_type > _node_boundary_ids
Set of user-specified boundary IDs for nodes only.
std::vector< BCTuple > build_shellface_list() const
Create a list of (element_id, shellface_id, boundary_id) tuples for all relevant shellfaces.
const Elem * parent() const
void raw_boundary_ids(const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const
void make_node_unique_ids_parallel_consistent(MeshBase &)
Assuming all unique_ids on local nodes are globally unique, and assuming all processor ids are parall...
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
std::vector< BCTuple > build_active_side_list() const
Create a list of (element_id, side_id, boundary_id) tuples for all relevant active sides...
void active_family_tree_by_side(std::vector< const Elem *> &family, unsigned int side, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to side...
void remove_edge(const Elem *elem, const unsigned short int edge)
Removes all boundary conditions associated with edge edge of element elem, if any exist...
A Node is like a Point, but with more information.
const MeshBase & interior_mesh() const
virtual unique_id_type parallel_max_unique_id() const =0
std::string & nodeset_name(boundary_id_type id)
void set_interior_mesh(MeshBase &int_mesh)
Sets the interior mesh.
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
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::set< boundary_id_type > _edge_boundary_ids
Set of user-specified boundary IDs for edges only.
virtual void libmesh_assert_valid_parallel_ids() const override
Verify id and processor_id consistency of our elements and nodes containers.
void sync(UnstructuredMesh &boundary_mesh)
Generates boundary_mesh data structures corresponding to the mesh data structures.
void add_elements(const std::set< boundary_id_type > &requested_boundary_ids, UnstructuredMesh &boundary_mesh, bool store_parent_side_ids=false)
Generates elements along the boundary of our _mesh, which use pre-existing nodes on the boundary_mesh...
const Elem * interior_parent() const
~BoundaryInfo()
Destructor.
std::vector< unsigned int > sides_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
void remove_node(const Node *node, const boundary_id_type id)
Removes boundary id id from node node, if it exists.
void synchronize_global_id_set()
Synchronizes the boundary_ids set on each processor to determine global_boundary_ids.
std::size_t n_edge_conds() const
IntRange< unsigned short > side_index_range() const
void side_boundary_ids(const Elem *const elem, std::vector< std::vector< boundary_id_type >> &vec_to_fill) const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
The definition of the const_element_iterator struct.
BoundaryInfo(MeshBase &m)
Constructor.
const Elem * top_parent() const
bool operator==(const BoundaryInfo &other_boundary_info) const
This tests for data equality via element ids.
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const =0
void remove_shellface(const Elem *elem, const unsigned short int shellface)
Removes all boundary conditions associated with shell face shellface of element elem, if any exist.
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.
std::size_t n_shellface_conds() const
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
void raw_edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
unsigned int n_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface) const
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
RefinementState p_refinement_flag() const
void build_node_list_from_side_list(const std::set< boundary_id_type > &sideset_list={})
Adds nodes with boundary ids based on the side's boundary ids they are connected to.
const boundary_id_type side_id
std::set< boundary_id_type > _boundary_ids
A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
Register an integer datum (of type dof_id_type) to be added to each element in the mesh...
void remove_side_id(boundary_id_type id, bool global=false)
Removes all sides with boundary id id from the BoundaryInfo object, removes it from the set of side b...
unsigned int side_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) 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.
virtual std::unique_ptr< Partitioner > & partitioner()
A partitioner to use at each partitioning.
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
const Parallel::Communicator & comm() const
virtual unsigned int n_children() const =0
std::set< boundary_id_type > _side_boundary_ids
Set of user-specified boundary IDs for sides only.
void build_side_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique side boundary ids.
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
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.
const Parallel::Communicator & _communicator
MeshBase * _mesh
A pointer to the Mesh this boundary info pertains to.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
void renumber_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all entities (nodes, sides, edges, shellfaces) with boundary id old_id to instead be labeled ...
std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > _boundary_side_id
Data structure that maps sides of elements to boundary ids.
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
Real distance(const Point &p)
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.
std::set< boundary_id_type > _global_boundary_ids
A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
uint8_t processor_id_type
This is the MeshBase class.
std::size_t n_boundary_ids() const
void build_side_list_from_node_list(const std::set< boundary_id_type > &nodeset_list={})
Adds sides to a sideset if every node on that side are in the same sideset.
IntRange< unsigned short > edge_index_range() const
std::tuple< dof_id_type, boundary_id_type > NodeBCTuple
Create a list of (node_id, boundary_id) tuples for all relevant nodes.
std::map< boundary_id_type, std::string > _ss_id_to_name
This structure maintains the mapping of named side sets for file formats (Exodus, Gmsh) that support ...
void renumber_side_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all sides with boundary id old_id to instead be labeled by boundary id new_id.
boundary_id_type get_id_by_name(std::string_view name) const
void clear_boundary_node_ids()
Clears all the boundary information from all of the nodes in the mesh.
processor_id_type n_processors() const
virtual bool is_serial() const
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 dof_id_type n_nodes
void remove_edge_id(boundary_id_type id, bool global=false)
Removes all edges with boundary id id from the BoundaryInfo object, removes it from the set of edge b...
const std::string & get_edgeset_name(boundary_id_type id) const
static const boundary_id_type invalid_id
Number used for internal use.
unsigned int n_raw_boundary_ids(const Elem *const elem, const unsigned short int side) const
This is the MeshCommunication class.
const Node & node_ref(const unsigned int i) const
std::map< boundary_id_type, std::string > _es_id_to_name
This structure maintains the mapping of named edge sets for file formats (Exodus, Gmsh) that support ...
virtual unsigned int n_nodes() const =0
std::multimap< const Node *, boundary_id_type > _boundary_node_id
Data structure that maps nodes in the mesh to boundary ids.
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.
void print_info(std::ostream &out_stream=libMesh::out) const
Prints the boundary information data structure.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
void raw_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
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 parallel_sync_side_ids()
Synchronize the boundary element side and node across processors.
virtual dof_id_type max_elem_id() const =0
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
std::vector< BCTuple > build_edge_list() const
Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.
void parallel_sync_node_ids()
Helper for building element sides that minimizes the construction of new elements.
virtual unsigned int n_edges() const =0
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
An object whose state is distributed along a set of processors.
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
const std::string & get_nodeset_name(boundary_id_type id) const
virtual void clear()
Deletes all the element and node data that is currently stored.
void clear()
Clears the underlying data structures and restores the object to a pristine state with no data stored...
unsigned int which_child_am_i(const Elem *e) const
std::string & sideset_name(boundary_id_type id)
void renumber_node_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all nodes with boundary id old_id to instead be labeled by boundary id new_id.
BoundaryInfo & operator=(const BoundaryInfo &other_boundary_info)
Copy assignment operator.
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
unsigned int n_partitions() const
virtual const Elem * elem_ptr(const dof_id_type i) const =0
void build_node_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique node boundary ids.
virtual unsigned int n_sides() const =0
const Elem * neighbor_ptr(unsigned int i) const
void remove_side(const Elem *elem, const unsigned short int side)
Removes all boundary conditions associated with side side of element elem, if any exist...
Preparation _preparation
Flags indicating in what ways this mesh has been prepared.
unsigned int level() const
const Elem * raw_child_ptr(unsigned int i) const
virtual unsigned int n_vertices() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int n_edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
subdomain_id_type subdomain_id() 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
const Node * node_ptr(const unsigned int i) const
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.
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
const std::set< boundary_id_type > & get_global_boundary_ids() 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...
std::size_t n_nodeset_conds() const
std::string & edgeset_name(boundary_id_type id)
bool has_boundary_id_sets
IntRange< unsigned short > node_index_range() const
void renumber_edge_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all edges with boundary id old_id to instead be labeled by boundary id new_id.
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
std::set< boundary_id_type > _shellface_boundary_ids
Set of user-specified boundary IDs for shellfaces only.
void _find_id_maps(const std::set< boundary_id_type > &requested_boundary_ids, dof_id_type first_free_node_id, std::map< dof_id_type, dof_id_type > *node_id_map, dof_id_type first_free_elem_id, std::map< std::pair< dof_id_type, unsigned char >, dof_id_type > *side_id_map, const std::set< subdomain_id_type > &subdomains_relative_to)
Helper method for finding consistent maps of interior to boundary dof_object ids. ...
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > _boundary_shellface_id
Data structure that maps faces of shell elements to boundary ids.
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
void print_summary(std::ostream &out_stream=libMesh::out) const
Prints a summary of the boundary information.
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
static constexpr subdomain_id_type invalid_subdomain_id
A static integral constant representing an invalid subdomain id.
void remove_node_id(boundary_id_type id, bool global=false)
Removes all nodes with boundary id id from the BoundaryInfo object, removes it from the set of node b...
processor_id_type processor_id() const
dof_id_type node_id(const unsigned int i) const
const Point & point(const unsigned int i) const
bool has_children() const
unsigned int & set_n_partitions()
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 build_shellface_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique shellface boundary ids.
virtual bool is_child_on_edge(const unsigned int c, const unsigned int e) const
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...
std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > _boundary_edge_id
Data structure that maps edges of elements to boundary ids.
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
Point vertex_average() const
const Elem * child_ptr(unsigned int i) const
void get_side_and_node_maps(UnstructuredMesh &boundary_mesh, std::map< dof_id_type, dof_id_type > &node_id_map, std::map< dof_id_type, unsigned char > &side_id_map, Real tolerance=1.e-6)
Suppose we have used sync to create boundary_mesh.
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...
void transfer_boundary_ids_from_children(const Elem *const parent)
Update parent's boundary id list so that this information is consistent with its children.
void set_union(T &data, const unsigned int root_id) const
const RemoteElem * remote_elem