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"
33#include "libmesh/utility.h"
48template <
class Key,
class T,
class Pred>
49void erase_if(std::multimap<Key,T> & map, Key k, Pred pred)
51 auto rng = map.equal_range(k);
53 while (it != rng.second)
64template <
class Key,
class T,
class Pred>
65void erase_if(std::multimap<Key,T> & map, Pred pred)
67 auto it = map.begin();
68 while (it != map.end())
78template <
typename Map,
typename T>
79void renumber_name(Map & m, T old_id, T new_id)
81 if (
const auto it = std::as_const(m).find(old_id);
84 m[new_id] = it->second;
107 _children_on_boundary(false)
171 const Node * other_node =
179 auto compare_edges = [&](
const Elem * elem,
180 const Elem * other_elem,
181 unsigned short int edge)
188 std::vector<boundary_id_type> our_edges, other_edges;
191 if (our_edges.size() != other_edges.size())
194 std::sort(our_edges.begin(), our_edges.end());
195 std::sort(other_edges.begin(), other_edges.end());
197 if (our_edges[i] != other_edges[i])
202 for (
const auto & [other_elem, edge_id_pair] : other_boundary_info.
_boundary_edge_id)
205 if (!compare_edges(elem, other_elem, edge_id_pair.first))
212 if (!compare_edges(elem, other_elem, edge_id_pair.first))
216 auto compare_sides = [&](
const Elem * elem,
217 const Elem * other_elem,
218 unsigned short int side)
225 std::vector<boundary_id_type> our_sides, other_sides;
227 other_boundary_info.
boundary_ids(other_elem, side, other_sides);
228 if (our_sides.size() != other_sides.size())
231 std::sort(our_sides.begin(), our_sides.end());
232 std::sort(other_sides.begin(), other_sides.end());
234 if (our_sides[i] != other_sides[i])
239 for (
const auto & [other_elem, side_id_pair] : other_boundary_info.
_boundary_side_id)
242 if (!compare_sides(elem, other_elem, side_id_pair.first))
249 if (!compare_sides(elem, other_elem, side_id_pair.first))
253 auto compare_shellfaces = [&](
const Elem * elem,
254 const Elem * other_elem,
255 unsigned short int shellface)
262 std::vector<boundary_id_type> our_shellfaces, other_shellfaces;
265 if (our_shellfaces.size() != other_shellfaces.size())
268 std::sort(our_shellfaces.begin(), our_shellfaces.end());
269 std::sort(other_shellfaces.begin(), other_shellfaces.end());
271 if (our_shellfaces[i] != other_shellfaces[i])
279 if (!compare_shellfaces(elem, other_elem, shellface_id_pair.first))
286 if (!compare_shellfaces(elem, other_elem, shellface_id_pair.first))
293 auto compare_sets = [](
const auto & set1,
const auto & set2)
295 if (set1.size() != set2.size())
298 if (!set2.count(bid))
318 auto compare_maps = [](
const auto & map1,
const auto & map2)
320 if (map1.size() != map2.size())
322 for (
const auto & pair : map1)
323 if (!map2.count(pair.first) ||
324 map2.at(pair.first) != pair.second)
386 if (
const auto it = old_ns_id_to_name.find(
id);
387 it != old_ns_id_to_name.end())
396 if (
const auto it = old_es_id_to_name.find(
id);
397 it != old_es_id_to_name.end())
406 if (
const auto it = old_ss_id_to_name.find(
id);
407 it != old_ss_id_to_name.end())
447 std::set<boundary_id_type> request_boundary_ids(
_boundary_ids);
452 this->
sync(request_boundary_ids,
462 std::set<subdomain_id_type> subdomains_relative_to;
465 this->
sync(requested_boundary_ids,
467 subdomains_relative_to);
474 const std::set<subdomain_id_type> & subdomains_relative_to)
476 LOG_SCOPE(
"sync()",
"BoundaryInfo");
478 boundary_mesh.
clear();
505 std::unique_ptr<MeshBase> mesh_copy;
509 auto serializer = std::make_unique<MeshSerializer>
518 std::map<dof_id_type, dof_id_type> node_id_map;
520 this->
_find_id_maps(requested_boundary_ids, 0, &node_id_map, 0,
nullptr, subdomains_relative_to);
523 for (
const auto & node :
_mesh->node_ptr_range())
526 if (node_id_map.count(node_id))
528 boundary_mesh.
add_point(*node, node_id_map[node_id], node->processor_id());
531 std::vector<boundary_id_type> node_boundary_ids;
533 for (
const auto & node_bid : node_boundary_ids)
543 subdomains_relative_to,
552 for (
auto & new_elem : boundary_mesh.element_ptr_range())
554 for (
auto nn : new_elem->node_index_range())
558 boundary_mesh.
node_ptr(node_id_map[new_elem->node_id(nn)]);
563 libmesh_assert_equal_to (new_node->
id(),
564 node_id_map[new_elem->node_id(nn)]);
567 new_elem->set_node(nn, new_node);
576 for (
auto & new_elem : boundary_mesh.element_ptr_range())
579 new_elem->interior_parent()->id();
581 if (!mesh_copy->query_elem_ptr(interior_parent_id))
582 new_elem->set_interior_parent
605 std::map<dof_id_type, dof_id_type> & node_id_map,
606 std::map<dof_id_type, unsigned char> & side_id_map,
609 LOG_SCOPE(
"get_side_and_node_maps()",
"BoundaryInfo");
617 const Elem * interior_parent_side;
619 for (
const auto & boundary_elem : boundary_mesh.active_element_ptr_range())
625 unsigned char interior_parent_side_index = 0;
626 bool found_matching_sides =
false;
629 interior_parent_side = &side_builder(*interior_parent, side);
630 Real va_distance = (boundary_elem->vertex_average() - interior_parent_side->
vertex_average()).norm();
632 if (va_distance < (tolerance * boundary_elem->hmin()))
634 interior_parent_side_index = cast_int<unsigned char>(side);
635 found_matching_sides =
true;
640 libmesh_error_msg_if(!found_matching_sides,
"No matching side found within the specified tolerance");
642 side_id_map[boundary_elem->id()] = interior_parent_side_index;
644 for (
auto local_node_index : boundary_elem->node_index_range())
646 dof_id_type boundary_node_id = boundary_elem->node_id(local_node_index);
649 node_id_map[interior_node_id] = boundary_node_id;
658 bool store_parent_side_ids,
659 const std::vector<subdomain_id_type> & new_subdomain_ids)
662 std::set<subdomain_id_type> subdomains_relative_to;
667 subdomains_relative_to,
668 store_parent_side_ids,
676 const std::set<subdomain_id_type> & subdomains_relative_to,
677 bool store_parent_side_ids,
678 const std::vector<subdomain_id_type> & new_subdomain_ids)
681 new_subdomain_ids.size() == 1 ||
682 new_subdomain_ids.size() == requested_boundary_ids.size());
683 LOG_SCOPE(
"add_elements()",
"BoundaryInfo");
702 std::map<std::pair<dof_id_type, unsigned char>,
dof_id_type> side_id_map;
708 subdomains_relative_to);
714 typedef std::vector<std::tuple<dof_id_type, unsigned char, boundary_id_type>>
716 side_container sides_to_add;
718 for (
const auto & elem :
_mesh->element_ptr_range())
727 !subdomains_relative_to.count(elem->subdomain_id()))
730 for (
auto s : elem->side_index_range())
732 bool add_this_side =
false;
736 std::vector<boundary_id_type> bcids;
742 if (requested_boundary_ids.count(bcid))
744 add_this_side =
true;
745 triggering_bcid = bcid;
756 if (requested_boundary_ids.count(
invalid_id) &&
757 elem->neighbor_ptr(s) ==
nullptr)
758 add_this_side =
true;
761 sides_to_add.emplace_back(elem->id(), s, triggering_bcid);
765#ifdef LIBMESH_ENABLE_UNIQUE_ID
772 unsigned int parent_side_index_tag = store_parent_side_ids ?
781 std::vector<boundary_id_type> requested_boundary_ids_vec;
782 if (new_subdomain_ids.size() > 1)
783 requested_boundary_ids_vec.assign(requested_boundary_ids.begin(),
784 requested_boundary_ids.end());
786 for (
const auto & [elem_id, s, triggering_bcid] : sides_to_add)
794 const std::pair<dof_id_type, unsigned char> side_pair(elem_id, s);
798 const dof_id_type new_side_id = side_id_map[side_pair];
800 side->set_id(new_side_id);
802#ifdef LIBMESH_ENABLE_UNIQUE_ID
803 side->set_unique_id(old_max_unique_id + new_side_id);
807 Elem * new_elem = boundary_mesh.
add_elem(std::move(side));
811 if (store_parent_side_ids)
815 if (new_subdomain_ids.size() == 1)
817 else if (new_subdomain_ids.size() > 1)
820 requested_boundary_ids_vec.end(),
824 new_subdomain_ids[std::distance(requested_boundary_ids_vec.begin(), it)];
827#ifdef LIBMESH_ENABLE_AMR
834 const std::pair<dof_id_type, unsigned char> parent_side_pair(elem->
parent()->
id(), s);
838 Elem * side_parent = boundary_mesh.
elem_ptr(side_id_map[parent_side_pair]);
849 bool found_child =
false;
862 libmesh_assert_equal_to (new_elem->
n_vertices(), 3);
893 const unsigned short bdy_n_sides = new_elem->
n_sides();
894 const unsigned short bdy_n_nodes = new_elem->
n_nodes();
905 for (
unsigned short boundary_side = 0;
906 boundary_side != bdy_n_sides; ++boundary_side)
910 bool found_all_nodes =
true;
911 for (
unsigned short boundary_node = 0;
912 boundary_node != bdy_n_nodes; ++boundary_node)
918 bool found_this_node =
false;
919 for (
unsigned short interior_node = 0;
920 interior_node !=
n_nodes; ++interior_node)
926 if (new_elem->
point(boundary_node) ==
927 elem->
point(interior_node))
929 found_this_node =
true;
933 if (!found_this_node)
935 found_all_nodes =
false;
960# ifdef LIBMESH_HAVE_RTTI
985 libmesh_error_msg_if(!node_ptr,
986 "BoundaryInfo::add_node(): Could not retrieve pointer for node "
988 <<
", no boundary id was added.");
999 "ERROR: You may not set a boundary ID of "
1001 <<
"\n That is reserved for internal use.");
1005 if (pr.second ==
id)
1016 const std::vector<boundary_id_type> & ids)
1031 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1032 std::sort(unique_ids.begin(), unique_ids.end());
1033 std::vector<boundary_id_type>::iterator new_end =
1034 std::unique(unique_ids.begin(), unique_ids.end());
1036 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1039 "ERROR: You may not set a boundary ID of "
1041 <<
"\n That is reserved for internal use.");
1043 bool already_inserted =
false;
1044 for (
const auto & pr :
as_range(bounds))
1045 if (pr.second ==
id)
1047 already_inserted =
true;
1050 if (already_inserted)
1067 const unsigned short int edge,
1076 const unsigned short int edge,
1082 libmesh_assert_equal_to (elem->
level(), 0);
1085 libmesh_assert_less (edge, elem->
n_edges());
1088 "ERROR: You may not set a boundary ID of "
1090 <<
"\n That is reserved for internal use.");
1094 if (pr.second.first == edge &&
1095 pr.second.second ==
id)
1106 const unsigned short int edge,
1107 const std::vector<boundary_id_type> & ids)
1115 libmesh_assert_equal_to (elem->
level(), 0);
1118 libmesh_assert_less (edge, elem->
n_edges());
1128 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1129 std::sort(unique_ids.begin(), unique_ids.end());
1130 std::vector<boundary_id_type>::iterator new_end =
1131 std::unique(unique_ids.begin(), unique_ids.end());
1133 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1136 "ERROR: You may not set a boundary ID of "
1138 <<
"\n That is reserved for internal use.");
1140 bool already_inserted =
false;
1141 for (
const auto & pr :
as_range(bounds))
1142 if (pr.second.first == edge &&
1143 pr.second.second ==
id)
1145 already_inserted =
true;
1148 if (already_inserted)
1160 const unsigned short int shellface,
1169 const unsigned short int shellface,
1175 libmesh_assert_equal_to (elem->
level(), 0);
1178 libmesh_assert_less(shellface, 2);
1181 "ERROR: You may not set a boundary ID of "
1183 <<
"\n That is reserved for internal use.");
1187 if (pr.second.first == shellface &&
1188 pr.second.second ==
id)
1199 const unsigned short int shellface,
1200 const std::vector<boundary_id_type> & ids)
1208 libmesh_assert_equal_to (elem->
level(), 0);
1211 libmesh_assert_less(shellface, 2);
1221 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1222 std::sort(unique_ids.begin(), unique_ids.end());
1223 std::vector<boundary_id_type>::iterator new_end =
1224 std::unique(unique_ids.begin(), unique_ids.end());
1226 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1229 "ERROR: You may not set a boundary ID of "
1231 <<
"\n That is reserved for internal use.");
1233 bool already_inserted =
false;
1234 for (
const auto & pr :
as_range(bounds))
1235 if (pr.second.first == shellface &&
1236 pr.second.second ==
id)
1238 already_inserted =
true;
1241 if (already_inserted)
1252 const unsigned short int side,
1261 const unsigned short int side,
1267 libmesh_assert_less (side, elem->
n_sides());
1269 libmesh_error_msg_if(
id ==
invalid_id,
"ERROR: You may not set a boundary ID of "
1271 <<
"\n That is reserved for internal use.");
1275 if (pr.second.first == side &&
1276 pr.second.second ==
id)
1279#ifdef LIBMESH_ENABLE_AMR
1289 std::vector<boundary_id_type> bd_ids;
1292 if(std::find(bd_ids.begin(), bd_ids.end(),
id) != bd_ids.end())
1293 libmesh_not_implemented_msg(
"Trying to add boundary ID "
1294 + std::to_string(
id)
1295 +
" which already exists on the ancestors.");
1307 const unsigned short int side,
1308 const std::vector<boundary_id_type> & ids)
1316 libmesh_assert_less (side, elem->
n_sides());
1318#ifdef LIBMESH_ENABLE_AMR
1328 std::vector<boundary_id_type> bd_ids;
1331 for (
const auto id : ids)
1332 if(std::find(bd_ids.begin(), bd_ids.end(),
id) != bd_ids.end())
1333 libmesh_not_implemented_msg(
"Trying to add boundary ID "
1334 + std::to_string(
id)
1335 +
" which already exists on the ancestors.");
1347 std::vector<boundary_id_type> unique_ids(ids.begin(), ids.end());
1348 std::sort(unique_ids.begin(), unique_ids.end());
1349 std::vector<boundary_id_type>::iterator new_end =
1350 std::unique(unique_ids.begin(), unique_ids.end());
1352 for (
auto &
id :
as_range(unique_ids.begin(), new_end))
1355 "ERROR: You may not set a boundary ID of "
1357 <<
"\n That is reserved for internal use.");
1359 bool already_inserted =
false;
1360 for (
const auto & pr :
as_range(bounds))
1361 if (pr.second.first == side && pr.second.second ==
id)
1363 already_inserted =
true;
1366 if (already_inserted)
1381 if (pr.second ==
id)
1390 std::vector<boundary_id_type> & vec_to_fill)
const
1393 vec_to_fill.clear();
1396 vec_to_fill.push_back(pr.second);
1404 return cast_int<unsigned int>(std::distance(pos.first, pos.second));
1410 const unsigned short int edge,
1411 std::vector<boundary_id_type> & vec_to_fill)
const
1416 vec_to_fill.clear();
1419 libmesh_assert_less (edge, elem->
n_edges());
1423 const Elem * searched_elem = elem;
1424#ifdef LIBMESH_ENABLE_AMR
1425 if (elem->
level() != 0)
1430 bool found_boundary_edge =
false;
1438 found_boundary_edge =
true;
1444 if (!found_boundary_edge)
1450 while (searched_elem->
parent() !=
nullptr)
1452 const Elem * parent = searched_elem->
parent();
1455 searched_elem = parent;
1463 if (pr.second.first == edge)
1464 vec_to_fill.push_back(pr.second.second);
1470 const unsigned short int edge)
const
1472 std::vector<boundary_id_type> ids;
1474 return cast_int<unsigned int>(ids.size());
1480 const unsigned short int edge,
1481 std::vector<boundary_id_type> & vec_to_fill)
const
1486 libmesh_assert_less (edge, elem->
n_edges());
1489 vec_to_fill.clear();
1497 if (pr.second.first == edge)
1498 vec_to_fill.push_back(pr.second.second);
1504 const unsigned short int shellface,
1505 std::vector<boundary_id_type> & vec_to_fill)
const
1510 libmesh_assert_less(shellface, 2);
1513 vec_to_fill.clear();
1517 const Elem * searched_elem = elem;
1518#ifdef LIBMESH_ENABLE_AMR
1519 if (elem->
level() != 0)
1521 while (searched_elem->
parent() !=
nullptr)
1523 const Elem * parent = searched_elem->
parent();
1524 searched_elem = parent;
1531 if (pr.second.first == shellface)
1532 vec_to_fill.push_back(pr.second.second);
1538 const unsigned short int shellface)
const
1540 std::vector<boundary_id_type> ids;
1542 return cast_int<unsigned int>(ids.size());
1548 const unsigned short int shellface,
1549 std::vector<boundary_id_type> & vec_to_fill)
const
1554 libmesh_assert_less(shellface, 2);
1557 vec_to_fill.clear();
1565 if (pr.second.first == shellface)
1566 vec_to_fill.push_back(pr.second.second);
1572 const unsigned short int side,
1575 std::vector<boundary_id_type> ids;
1577 return (std::find(ids.begin(), ids.end(),
id) != ids.end());
1582 std::vector<std::vector<boundary_id_type>> & vec_to_fill)
const
1587 vec_to_fill.clear();
1588 auto num_sides = elem->
n_sides();
1595 vec_to_fill.resize(num_sides);
1600 const Elem * searched_elem = elem;
1602#ifdef LIBMESH_ENABLE_AMR
1603 if (elem->
level() != 0)
1610 std::vector<bool> search_on_side(elem->
n_sides(),
true);
1611 bool keep_searching =
true;
1612 while (searched_elem && keep_searching)
1618 if (search_on_side[side] && pr.second.first == side &&
1619 std::find(vec_to_fill[side].begin(), vec_to_fill[side].end(), pr.second.second) ==
1620 vec_to_fill[side].end())
1621 vec_to_fill[side].push_back(pr.second.second);
1624 const Elem * parent = searched_elem->
parent();
1629 if (search_on_side[side] &&
1631 search_on_side[side] =
false;
1633 searched_elem = parent;
1635 keep_searching = *std::max_element(search_on_side.begin(), search_on_side.end());
1644 std::vector<bool> search_on_side(elem->
n_sides(),
true);
1648 const Elem * searched_elem_for_side = elem;
1656 while (searched_elem_for_side->
parent() !=
nullptr)
1658 const Elem * parent = searched_elem_for_side->
parent();
1660 search_on_side[side] =
false;
1661 searched_elem_for_side = parent;
1665 if (*std::max_element(search_on_side.begin(), search_on_side.end()))
1667 if (search_on_side[pr.second.first])
1668 vec_to_fill[pr.second.first].push_back(pr.second.second);
1675 vec_to_fill[pr.second.first].push_back(pr.second.second);
1679 const unsigned short int side,
1680 std::vector<boundary_id_type> & vec_to_fill)
const
1685 libmesh_assert_less (side, elem->
n_sides());
1688 vec_to_fill.clear();
1694 const Elem * searched_elem = elem;
1696#ifdef LIBMESH_ENABLE_AMR
1698 if (elem->
level() != 0)
1705 while (searched_elem)
1709 if (pr.second.first == side &&
1710 std::find(vec_to_fill.begin(), vec_to_fill.end(), pr.second.second) ==
1712 vec_to_fill.push_back(pr.second.second);
1715 const Elem * parent = searched_elem->
parent();
1721 searched_elem = parent;
1733 while (searched_elem->
parent() !=
nullptr)
1735 const Elem * parent = searched_elem->
parent();
1739 searched_elem = parent;
1747 if (pr.second.first == side)
1748 vec_to_fill.push_back(pr.second.second);
1755 const unsigned short int side)
const
1757 std::vector<boundary_id_type> ids;
1759 return cast_int<unsigned int>(ids.size());
1764 const unsigned short int side)
const
1766 std::vector<boundary_id_type> ids;
1768 return cast_int<unsigned int>(ids.size());
1774 const unsigned short int side,
1775 std::vector<boundary_id_type> & vec_to_fill)
const
1780 libmesh_assert_less (side, elem->
n_sides());
1783 vec_to_fill.clear();
1791 if (pr.second.first == side)
1792 vec_to_fill.push_back(pr.second.second);
1798 const Elem *
const old_elem,
1799 const Elem *
const new_elem)
1801 libmesh_assert_equal_to (old_elem->
n_sides(), new_elem->
n_sides());
1802 libmesh_assert_equal_to (old_elem->
n_edges(), new_elem->
n_edges());
1804 std::vector<boundary_id_type> bndry_ids;
1809 this->
add_side (new_elem, s, bndry_ids);
1815 this->
add_edge (new_elem, e, bndry_ids);
1818 for (
unsigned short sf=0; sf != 2; sf++)
1845 {
return val == id;});
1863 const unsigned short int edge)
1868 libmesh_assert_less (edge, elem->
n_edges());
1871 libmesh_assert_equal_to (elem->
level(), 0);
1876 {
return pr.first == edge;});
1882 const unsigned short int edge,
1888 libmesh_assert_less (edge, elem->
n_edges());
1891 libmesh_assert_equal_to (elem->
level(), 0);
1896 {
return pr.first == edge && pr.second == id;});
1901 const unsigned short int shellface)
1906 libmesh_assert_equal_to (elem->
level(), 0);
1909 libmesh_assert_less(shellface, 2);
1914 {
return pr.first == shellface;});
1920 const unsigned short int shellface,
1926 libmesh_assert_equal_to (elem->
level(), 0);
1929 libmesh_assert_less(shellface, 2);
1934 {
return pr.first == shellface && pr.second == id;});
1938 const unsigned short int side)
1943 libmesh_assert_less (side, elem->
n_sides());
1948 {
return pr.first == side;});
1954 const unsigned short int side,
1960 libmesh_assert_less (side, elem->
n_sides());
1962#ifdef LIBMESH_ENABLE_AMR
1967 std::vector<boundary_id_type> bd_ids;
1969 if(std::find(bd_ids.begin(), bd_ids.end(),
id) != bd_ids.end())
1971 std::vector<boundary_id_type> raw_bd_ids;
1973 if(std::find(raw_bd_ids.begin(), raw_bd_ids.end(),
id) == raw_bd_ids.end())
1974 libmesh_not_implemented_msg(
"We cannot delete boundary ID "
1975 + std::to_string(
id) +
1976 " using a child because it is inherited from an ancestor.");
1984 {
return pr.first == side && pr.second == id;});
2018 this->
comm().
max(someone_has_it);
2019 if (!someone_has_it)
2026 {
return pr.second == id;});
2045 this->
comm().
max(someone_has_it);
2046 if (!someone_has_it)
2053 {
return pr.second == id;});
2071 this->
comm().
max(someone_has_it);
2072 if (!someone_has_it)
2079 {
return pr.second == id;});
2098 this->
comm().
max(someone_has_it);
2099 if (!someone_has_it)
2106 {
return val == id;});
2114 if (old_id == new_id)
2120 bool found_node =
false;
2122 if (p.second == old_id)
2136 bool found_edge =
false;
2138 if (p.second.second == old_id)
2142 this->
remove_edge(p.first, p.second.first, new_id);
2143 p.second.second = new_id;
2152 bool found_shellface =
false;
2154 if (p.second.second == old_id)
2159 p.second.second = new_id;
2160 found_shellface =
true;
2162 if (found_shellface)
2168 bool found_side =
false;
2170 if (p.second.second == old_id)
2174 this->
remove_side(p.first, p.second.first, new_id);
2175 p.second.second = new_id;
2184 if (found_node || found_edge || found_shellface || found_side)
2205 if (old_id == new_id)
2208 bool found_side =
false;
2210 if (p.second.second == old_id)
2214 this->
remove_side(p.first, p.second.first, new_id);
2215 p.second.second = new_id;
2246 if (old_id == new_id)
2249 bool found_edge =
false;
2251 if (p.second.second == old_id)
2255 this->
remove_edge(p.first, p.second.first, new_id);
2256 p.second.second = new_id;
2287 if (old_id == new_id)
2290 bool found_shellface =
false;
2292 if (p.second.second == old_id)
2297 p.second.second = new_id;
2298 found_shellface =
true;
2302 if (found_shellface)
2326 if (old_id == new_id)
2329 bool found_node =
false;
2331 if (p.second == old_id)
2366 const Elem * searched_elem = elem;
2378 if (pr.second.second == boundary_id_in)
2380 unsigned int side = pr.second.first;
2386#ifdef LIBMESH_ENABLE_AMR
2393 const Elem * p = elem;
2397 while (p !=
nullptr)
2420#ifdef LIBMESH_ENABLE_AMR
2428 const Elem * p = elem;
2429 while (p->
parent() !=
nullptr)
2440 if (pr.second.first == side && pr.second.second == boundary_id_in)
2459std::vector<unsigned int>
2463 std::vector<unsigned int> returnval;
2465 const Elem * searched_elem = elem;
2474 if (pr.second.second == boundary_id_in)
2476 unsigned int side = pr.second.first;
2486 returnval.push_back(side);
2492 const Elem * p = elem;
2494#ifdef LIBMESH_ENABLE_AMR
2496 while (p !=
nullptr)
2506 returnval.push_back(side);
2510 returnval.push_back(side);
2514#ifdef LIBMESH_ENABLE_AMR
2521 const Elem * p = elem;
2522 while (p->
parent() !=
nullptr)
2535 if (pr.second.first == side && pr.second.second == boundary_id_in &&
2536 std::find(returnval.begin(), returnval.end(), side) == returnval.end())
2537 returnval.push_back(side);
2561 if (std::find(b_ids.begin(),b_ids.end(),
id) == b_ids.end())
2562 b_ids.push_back(
id);
2575 if (std::find(b_ids.begin(),b_ids.end(),
id) == b_ids.end())
2576 b_ids.push_back(
id);
2589 if (std::find(b_ids.begin(),b_ids.end(),
id) == b_ids.end())
2590 b_ids.push_back(
id);
2594#ifdef LIBMESH_ENABLE_AMR
2607 const double number_of_sides_on_children = std::pow(2, parent->
dim()-1);
2611 for (
unsigned int side_i = 0; side_i < parent->
n_sides(); ++side_i)
2616 std::map<unsigned short int, unsigned short int> boundary_counts;
2627 if (pr.second.first == side_i)
2628 ++boundary_counts[pr.second.second];
2635 for (
const auto & boundary : boundary_counts)
2636 if (boundary.second / number_of_sides_on_children > 0.5)
2637 this->
add_side(parent, side_i, boundary.first);
2653 parallel_object_only();
2674 parallel_object_only();
2676 std::size_t n_edge_bcs=0;
2682 this->
comm().
sum (n_edge_bcs);
2696 parallel_object_only();
2698 std::size_t n_shellface_bcs=0;
2704 this->
comm().
sum (n_shellface_bcs);
2706 return n_shellface_bcs;
2718 parallel_object_only();
2720 std::size_t n_nodesets=0;
2726 this->
comm().
sum (n_nodesets);
2733std::vector<BoundaryInfo::NodeBCTuple>
2736 std::vector<NodeBCTuple> bc_tuples;
2740 bc_tuples.emplace_back(node->id(), bid);
2745 std::sort(bc_tuples.begin(), bc_tuples.end());
2747 std::sort(bc_tuples.begin(), bc_tuples.end(),
2749 {return std::get<1>(left) < std::get<1>(right);});
2764 typedef std::set<std::pair<dof_id_type, boundary_id_type>> set_type;
2765 typedef std::vector<std::pair<dof_id_type, boundary_id_type>> vec_type;
2768 std::unordered_map<processor_id_type, set_type> nodes_to_push;
2769 std::unordered_map<processor_id_type, vec_type> node_vecs_to_push;
2780 if (elem->is_remote())
2783 auto [sidenum, bcid] = id_pair;
2785 if (!sideset_list.empty() && !sideset_list.count(bcid))
2789 std::vector<const Elem *> family;
2790#ifdef LIBMESH_ENABLE_AMR
2793 family.push_back(elem);
2796 for (
const auto & cur_elem : family)
2798 side = &side_builder(*cur_elem, sidenum);
2804 if (!mesh_is_serial)
2808 if (proc_id != my_proc_id)
2809 nodes_to_push[proc_id].emplace(side->
node_id(i), bcid);
2822 for (
auto & [proc_id, s] : nodes_to_push)
2824 node_vecs_to_push[proc_id].assign(s.begin(), s.end());
2828 auto nodes_action_functor =
2831 const vec_type & received_nodes)
2833 for (
const auto & [dof_id, bndry_id] : received_nodes)
2838 (this->
comm(), node_vecs_to_push, nodes_action_functor);
2842 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2846 for (
const auto & node :
_mesh->node_ptr_range())
2849 if (pid != my_proc_id)
2850 node_ids_requested[pid].push_back(node->id());
2853 typedef std::vector<boundary_id_type> datum_type;
2855 auto node_bcid_gather_functor =
2858 const std::vector<dof_id_type> & ids,
2859 std::vector<datum_type> & data)
2861 const std::size_t query_size = ids.size();
2862 data.resize(query_size);
2864 for (std::size_t i=0; i != query_size; ++i)
2868 auto node_bcid_action_functor =
2871 const std::vector<dof_id_type> & ids,
2872 const std::vector<datum_type> & data)
2878 datum_type * datum_type_ex =
nullptr;
2880 (this->
comm(), node_ids_requested, node_bcid_gather_functor,
2881 node_bcid_action_functor, datum_type_ex);
2887 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2891 for (
const auto & elem :
_mesh->element_ptr_range())
2895 elem_ids_requested[pid].push_back(elem->id());
2898 typedef std::vector<std::pair<unsigned short int, boundary_id_type>> datum_type;
2901 auto elem_id_gather_functor =
2904 const std::vector<dof_id_type> & ids,
2905 std::vector<datum_type> & data)
2907 data.resize(ids.size());
2912 data[i].push_back(std::make_pair(pr.second.first, pr.second.second));
2916 auto elem_id_action_functor =
2919 const std::vector<dof_id_type> & ids,
2920 std::vector<datum_type> & data)
2928 for (
const auto & [
side_id, bndry_id] : data[i])
2934 datum_type * datum_type_ex =
nullptr;
2936 (this->
comm(), elem_ids_requested, elem_id_gather_functor,
2937 elem_id_action_functor, datum_type_ex);
2943 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2947 for (
const auto & node :
_mesh->node_ptr_range())
2951 node_ids_requested[pid].push_back(node->id());
2954 typedef std::vector<boundary_id_type> datum_type;
2957 auto node_id_gather_functor =
2960 const std::vector<dof_id_type> & ids,
2961 std::vector<datum_type> & data)
2963 data.resize(ids.size());
2968 data[i].push_back(pr.second);
2973 auto node_id_action_functor =
2976 const std::vector<dof_id_type> & ids,
2977 std::vector<datum_type> & data)
2985 for (
const auto & pr : data[i])
2991 datum_type * datum_type_ex =
nullptr;
2993 (this->
comm(), node_ids_requested, node_id_gather_functor,
2994 node_id_action_functor, datum_type_ex);
3002 libMesh::out <<
"No boundary node IDs have been added: cannot build side list!" << std::endl;
3009 const Elem * side_elem;
3011 for (
const auto & elem :
_mesh->active_element_ptr_range())
3012 for (
auto side : elem->side_index_range())
3014 side_elem = &side_builder(*elem, side);
3017 std::map<boundary_id_type, unsigned> nodesets_node_count;
3023 if (nodeset_list.empty() || nodeset_list.count(pr.second))
3024 nodesets_node_count[pr.second]++;
3030 for (
const auto & pr : nodesets_node_count)
3031 if (pr.second == side_elem->
n_nodes())
3038 if (nset_name !=
"")
3047std::vector<BoundaryInfo::BCTuple>
3050 std::vector<BCTuple> bc_triples;
3054 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3061 std::sort(bc_triples.begin(), bc_triples.end());
3063 std::sort(bc_triples.begin(), bc_triples.end(),
3065 {return std::get<1>(left) < std::get<1>(right);});
3067 std::sort(bc_triples.begin(), bc_triples.end(),
3069 {return std::get<2>(left) < std::get<2>(right);});
3076std::vector<BoundaryInfo::BCTuple>
3079 std::vector<BCTuple> bc_triples;
3085 if (elem->is_remote())
3089 std::vector<const Elem *> family;
3090#ifdef LIBMESH_ENABLE_AMR
3091 elem->active_family_tree_by_side(family, id_pair.first);
3093 family.push_back(elem);
3097 for (
const auto & f : family)
3098 bc_triples.emplace_back(f->id(), id_pair.first, id_pair.second);
3103 std::sort(bc_triples.begin(), bc_triples.end());
3109std::vector<BoundaryInfo::BCTuple>
3112 std::vector<BCTuple> bc_triples;
3116 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3120 std::sort(bc_triples.begin(), bc_triples.end());
3126std::vector<BoundaryInfo::BCTuple>
3129 std::vector<BCTuple> bc_triples;
3133 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3137 std::sort(bc_triples.begin(), bc_triples.end());
3148 out_stream <<
"Nodal Boundary conditions:" << std::endl
3149 <<
"--------------------------" << std::endl
3150 <<
" (Node No., ID) " << std::endl;
3153 out_stream <<
" (" << node->id()
3155 <<
")" << std::endl;
3161 out_stream << std::endl
3162 <<
"Edge Boundary conditions:" << std::endl
3163 <<
"-------------------------" << std::endl
3164 <<
" (Elem No., Edge No., ID) " << std::endl;
3167 out_stream <<
" (" << elem->id()
3168 <<
", " << id_pair.first
3169 <<
", " << id_pair.second
3170 <<
")" << std::endl;
3176 out_stream << std::endl
3177 <<
"Shell-face Boundary conditions:" << std::endl
3178 <<
"-------------------------" << std::endl
3179 <<
" (Elem No., Shell-face No., ID) " << std::endl;
3182 out_stream <<
" (" << elem->id()
3183 <<
", " << id_pair.first
3184 <<
", " << id_pair.second
3185 <<
")" << std::endl;
3191 out_stream << std::endl
3192 <<
"Side Boundary conditions:" << std::endl
3193 <<
"-------------------------" << std::endl
3194 <<
" (Elem No., Side No., ID) " << std::endl;
3197 out_stream <<
" (" << elem->id()
3198 <<
", " << id_pair.first
3199 <<
", " << id_pair.second
3200 <<
")" << std::endl;
3211 out_stream <<
"Nodal Boundary conditions:" << std::endl
3212 <<
"--------------------------" << std::endl
3213 <<
" (ID, number of nodes) " << std::endl;
3215 std::map<boundary_id_type, std::size_t> ID_counts;
3218 ID_counts[pr.second]++;
3220 for (
const auto & [bndry_id, cnt] : ID_counts)
3221 out_stream <<
" (" << bndry_id
3223 <<
")" << std::endl;
3229 out_stream << std::endl
3230 <<
"Edge Boundary conditions:" << std::endl
3231 <<
"-------------------------" << std::endl
3232 <<
" (ID, number of edges) " << std::endl;
3234 std::map<boundary_id_type, std::size_t> ID_counts;
3237 ID_counts[pr.second.second]++;
3239 for (
const auto & [bndry_id, cnt] : ID_counts)
3240 out_stream <<
" (" << bndry_id
3242 <<
")" << std::endl;
3249 out_stream << std::endl
3250 <<
"Shell-face Boundary conditions:" << std::endl
3251 <<
"-------------------------" << std::endl
3252 <<
" (ID, number of shellfaces) " << std::endl;
3254 std::map<boundary_id_type, std::size_t> ID_counts;
3257 ID_counts[pr.second.second]++;
3259 for (
const auto & [bndry_id, cnt] : ID_counts)
3260 out_stream <<
" (" << bndry_id
3262 <<
")" << std::endl;
3268 out_stream << std::endl
3269 <<
"Side Boundary conditions:" << std::endl
3270 <<
"-------------------------" << std::endl
3271 <<
" (ID, number of sides) " << std::endl;
3273 std::map<boundary_id_type, std::size_t> ID_counts;
3276 ID_counts[pr.second.second]++;
3278 for (
const auto & [bndry_id, cnt] : ID_counts)
3279 out_stream <<
" (" << bndry_id
3281 <<
")" << std::endl;
3288 static const std::string empty_string;
3291 return empty_string;
3304 static const std::string empty_string;
3307 return empty_string;
3319 static const std::string empty_string;
3322 return empty_string;
3337 if (ss_name == name)
3342 if (ns_name == name)
3347 if (es_name == name)
3359 std::map<dof_id_type, dof_id_type> * node_id_map,
3361 std::map<std::pair<dof_id_type, unsigned char>,
dof_id_type> * side_id_map,
3362 const std::set<subdomain_id_type> & subdomains_relative_to)
3367 next_node_id = first_free_node_id + this->
processor_id();
3384 <std::set<std::pair<dof_id_type, unsigned char>>>
3385 side_id_set_by_level;
3403 bool hit_end_el =
false;
3408 !hit_end_el || (el != end_unpartitioned_el); ++el)
3410 if ((el == end_el) && !hit_end_el)
3419 std::size_t n_levels = side_id_set_by_level.size();
3421 side_id_set_by_level.resize(n_levels);
3430 next_node_id = first_free_node_id + this->
n_processors();
3433 if (el == end_unpartitioned_el)
3437 const Elem * elem = *el;
3451 bool add_this_side =
false;
3454 std::vector<boundary_id_type> bcids;
3460 if (requested_boundary_ids.count(bcid))
3462 add_this_side =
true;
3473 if (requested_boundary_ids.count(
invalid_id) &&
3475 add_this_side =
true;
3486 std::pair<dof_id_type, unsigned char> side_pair(elem->
id(), s);
3487 auto level = elem->
level();
3488 if (side_id_set_by_level.size() <= level)
3489 side_id_set_by_level.resize(level+1);
3490 auto & level_side_id_set = side_id_set_by_level[level];
3492 level_side_id_set.insert(side_pair);
3495 side = &side_builder(*elem, s);
3507 if (node_id_map && !node_id_map->count(node_id))
3509 (*node_id_map)[node_id] = next_node_id;
3526 for (
auto level :
make_range(side_id_set_by_level.size()))
3528 for (
auto side_pair : side_id_set_by_level[level])
3529 (*side_id_map)[side_pair] = next_elem_id++;
3536 const bool clear_nodeset_data)
3547 [sideset_id, other_sideset_id](
3548 const std::pair<const Elem *, std::pair<unsigned short int, boundary_id_type>> & pred_pr,
3549 const std::multimap<const Elem *, std::pair<unsigned short int, boundary_id_type>> &
3551 const Elem & elem = *pred_pr.first;
3552 const auto elem_side = pred_pr.second.first;
3555 return std::make_pair(
false, pred_container.end());
3557 const auto elem_side_bnd_id = pred_pr.second.second;
3559 if (elem_side_bnd_id == sideset_id)
3560 other_elem_side_bnd_id = other_sideset_id;
3561 else if (elem_side_bnd_id == other_sideset_id)
3562 other_elem_side_bnd_id = sideset_id;
3564 return std::make_pair(
false, pred_container.end());
3567 const typename std::decay<
decltype(pred_container)>::type::value_type other_sideset_info(
3568 other_elem, std::make_pair(other_elem_side, other_elem_side_bnd_id));
3569 auto other_range = pred_container.equal_range(other_elem);
3571 other_range.first != other_range.second,
3572 "No matching sideset information for other element in boundary information");
3573 auto other_it = std::find(other_range.first, other_range.second, other_sideset_info);
3575 other_it != pred_container.end(),
3576 "No matching sideset information for other element in boundary information");
3577 return std::make_pair(
true, other_it);
3580 for (; it != end_it;)
3583 if (pred_result.first)
3589 if (clear_nodeset_data)
3591 const Elem & elem = *it->first;
3592 const Elem & neigh = *pred_result.second->first;
3593 const auto elem_side = it->second.first;
3595 const auto elem_bcid = it->second.second;
3598 for (
const auto local_node_num : elem.
nodes_on_side(elem_side))
3601 for (
const auto local_node_num : neigh.
nodes_on_side(neigh_side))
3622const std::set<boundary_id_type> &
3633 auto verify_multimap = [](
const auto & themap) {
3634 for (
const auto & [key, val] : themap)
3636 auto range = themap.equal_range(key);
3639 for (
auto it = range.first; it != range.second; ++it)
3640 if (it->second == val)
void max(const T &r, T &o, Request &req) const
void set_union(T &data, const unsigned int root_id) const
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
std::size_t n_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 ...
std::string & sideset_name(boundary_id_type id)
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
void side_boundary_ids(const Elem *const elem, std::vector< std::vector< boundary_id_type > > &vec_to_fill) 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.
unsigned int n_raw_boundary_ids(const Elem *const elem, const unsigned short int side) const
void add_elements(const std::set< boundary_id_type > &requested_boundary_ids, UnstructuredMesh &boundary_mesh, bool store_parent_side_ids=false, const std::vector< subdomain_id_type > &new_subdomain_ids={})
Generates elements along the boundary of our _mesh, which use pre-existing nodes on the boundary_mesh...
std::size_t n_nodeset_conds() 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.
void synchronize_global_id_set()
Synchronizes the boundary_ids set on each processor to determine global_boundary_ids.
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.
std::set< boundary_id_type > _node_boundary_ids
Set of user-specified boundary IDs for nodes only.
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.
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.
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...
const std::set< boundary_id_type > & get_global_boundary_ids() const
unsigned int side_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.
MeshBase * _mesh
A pointer to the Mesh this boundary info pertains to.
void sync(UnstructuredMesh &boundary_mesh)
Generates boundary_mesh data structures corresponding to the mesh data structures.
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
std::size_t n_boundary_conds() const
void raw_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
std::set< boundary_id_type > _boundary_ids
A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
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.
std::set< boundary_id_type > _global_boundary_ids
A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
std::size_t n_edge_conds() const
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...
std::vector< unsigned int > sides_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
bool operator==(const BoundaryInfo &other_boundary_info) const
This tests for data equality via element ids.
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
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.
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
void print_summary(std::ostream &out_stream=libMesh::out) const
Prints a summary of the boundary information.
std::set< boundary_id_type > _side_boundary_ids
Set of user-specified boundary IDs for sides only.
boundary_id_type get_id_by_name(std::string_view name) const
unsigned int n_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface) 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.
bool _children_on_boundary
std::string & nodeset_name(boundary_id_type id)
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 remove_id(boundary_id_type id, bool global=false)
Removes all entities (nodes, sides, edges, shellfaces) with boundary id id from their respective cont...
std::set< boundary_id_type > _shellface_boundary_ids
Set of user-specified boundary IDs for shellfaces only.
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.
std::vector< BCTuple > build_shellface_list() const
Create a list of (element_id, shellface_id, boundary_id) tuples for all relevant shellfaces.
void remove_shellface(const Elem *elem, const unsigned short int shellface)
Removes all boundary conditions associated with shell face shellface of element elem,...
unsigned int n_edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
std::multimap< const Node *, boundary_id_type > _boundary_node_id
Data structure that maps nodes in the mesh to boundary ids.
void raw_boundary_ids(const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const
std::size_t n_shellface_conds() const
void clear_boundary_node_ids()
Clears all the boundary information from all of the nodes in the mesh.
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.
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...
void clear()
Clears the underlying data structures and restores the object to a pristine state with no data stored...
const std::string & get_nodeset_name(boundary_id_type id) const
void print_info(std::ostream &out_stream=libMesh::out) const
Prints the boundary information data structure.
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.
void copy_boundary_ids(const BoundaryInfo &old_boundary_info, const Elem *const old_elem, const Elem *const new_elem)
std::tuple< dof_id_type, boundary_id_type > NodeBCTuple
Create a list of (node_id, boundary_id) tuples for all relevant 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...
void parallel_sync_side_ids()
Synchronize the boundary element side and node across processors.
~BoundaryInfo()
Destructor.
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.
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.
const std::string & get_sideset_name(boundary_id_type id) const
std::string & edgeset_name(boundary_id_type id)
void parallel_sync_node_ids()
void raw_edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) 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.
static const boundary_id_type invalid_id
Number used for internal use.
std::set< boundary_id_type > _edge_boundary_ids
Set of user-specified boundary IDs for edges only.
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 ...
const std::string & get_edgeset_name(boundary_id_type id) 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.
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
void build_node_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique node boundary ids.
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.
void build_side_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique side boundary ids.
BoundaryInfo & operator=(const BoundaryInfo &other_boundary_info)
Copy assignment operator.
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.
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
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.
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 ...
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.
std::vector< BCTuple > build_edge_list() const
Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.
void build_shellface_boundary_ids(std::vector< boundary_id_type > &b_ids) const
Builds the list of unique shellface boundary ids.
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.
void libmesh_assert_valid_multimaps() const
Helper method for ensuring that our multimaps don't contain entries with duplicate keys and values.
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 ...
BoundaryInfo(MeshBase &m)
Constructor.
std::vector< BCTuple > build_active_side_list() const
Create a list of (element_id, side_id, boundary_id) tuples for all relevant active sides.
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
virtual void libmesh_assert_valid_parallel_ids() const override
Verify id and processor_id consistency of our elements and nodes containers.
processor_id_type processor_id() const
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
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...
Helper for building element sides that minimizes the construction of new elements.
This is the base class from which all geometric element types are derived.
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
const Elem * raw_child_ptr(unsigned int i) const
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
RefinementState refinement_flag() const
virtual unsigned int n_vertices() const =0
const Point & point(const unsigned int i) const
const Node & node_ref(const unsigned int i) const
virtual bool is_child_on_edge(const unsigned int c, const unsigned int e) const
bool has_children() const
virtual unsigned int n_nodes() const =0
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.
const Elem * parent() const
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
const Elem * child_ptr(unsigned int i) const
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
void set_interior_parent(Elem *p)
Sets the pointer to the element's interior_parent.
static constexpr subdomain_id_type invalid_subdomain_id
A static integral constant representing an invalid subdomain id.
unsigned int which_child_am_i(const Elem *e) const
virtual unsigned short dim() const =0
subdomain_id_type subdomain_id() const
unsigned int level() const
void set_parent(Elem *p)
Sets the pointer to the element's parent.
const Node * node_ptr(const unsigned int i) const
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
IntRange< unsigned short > edge_index_range() const
virtual unsigned int n_children() const =0
IntRange< unsigned short > node_index_range() const
const Elem * interior_parent() const
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
virtual unsigned int n_edges() const =0
virtual unsigned int n_sides() const =0
dof_id_type node_id(const unsigned int i) const
RefinementState p_refinement_flag() const
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const =0
const Elem * neighbor_ptr(unsigned int i) const
Point vertex_average() const
IntRange< unsigned short > side_index_range() const
const Elem * top_parent() const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
This is the MeshBase class.
void unset_has_reinit_ghosting_functors()
Tells this we have done some operation (e.g.
virtual bool is_serial() const
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
virtual std::unique_ptr< Partitioner > & partitioner()
A partitioner to use at each partitioning.
virtual const Node * node_ptr(const dof_id_type i) const =0
virtual bool is_replicated() const
void unset_has_neighbor_ptrs()
Tells this we have done some operation (e.g.
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.
void unset_has_boundary_id_sets()
Tells this we have done some operation which may have invalidated our cached boundary id sets.
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
virtual const Node * query_node_ptr(const dof_id_type i) const =0
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.
virtual const Elem * elem_ptr(const dof_id_type i) const =0
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.
unsigned int n_partitions() const
virtual dof_id_type max_elem_id() const =0
void unset_has_cached_elem_data()
Tells this we have done some operation (e.g.
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
virtual void clear()
Deletes all the element and node data that is currently stored.
const MeshBase & interior_mesh() const
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
Preparation _preparation
Flags indicating in what ways this mesh has been prepared.
void set_interior_mesh(MeshBase &int_mesh)
Sets the interior mesh.
unsigned int & set_n_partitions()
virtual unique_id_type parallel_max_unique_id() const =0
This is the MeshCommunication class.
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...
A Node is like a Point, but with more information.
An object whose state is distributed along a set of processors.
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.
In parallel meshes where a ghost element has neighbors which do not exist on the local processor,...
The UnstructuredMesh class is derived from the MeshBase class.
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, GatherFunctor &gather_data, const ActionFunctor &act_on_data, const datum *example)
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
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...
The libMesh namespace provides an interface to certain functionality in the library.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
const RemoteElem * remote_elem
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
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...
const boundary_id_type side_id
bool has_boundary_id_sets
The definition of the const_element_iterator struct.
const dof_id_type n_nodes