libMesh
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Friends | List of all members
libMesh::BoundaryInfo Class Reference

The BoundaryInfo class contains information relevant to boundary conditions including storing faces, edges, and nodes on the boundary, along with ids that can be used to identify the type of boundary each entity is part of. More...

#include <boundary_info.h>

Inheritance diagram for libMesh::BoundaryInfo:
[legend]

Public Types

enum class  NodeBCTupleSortBy { NODE_ID , BOUNDARY_ID , UNSORTED }
 
enum class  BCTupleSortBy { ELEM_ID , SIDE_ID , BOUNDARY_ID , UNSORTED }
 
typedef std::tuple< dof_id_type, boundary_id_typeNodeBCTuple
 Create a list of (node_id, boundary_id) tuples for all relevant nodes.
 
typedef std::tuple< dof_id_type, unsigned short int, boundary_id_typeBCTuple
 Create a list of (element_id, side_id, boundary_id) tuples for relevant sides.
 

Public Member Functions

BoundaryInfooperator= (const BoundaryInfo &other_boundary_info)
 Copy assignment operator.
 
bool operator== (const BoundaryInfo &other_boundary_info) const
 This tests for data equality via element ids.
 
bool operator!= (const BoundaryInfo &other_boundary_info) const
 
 ~BoundaryInfo ()
 Destructor.
 
void clear ()
 Clears the underlying data structures and restores the object to a pristine state with no data stored.
 
void regenerate_id_sets ()
 Clears and regenerates the cached sets of ids.
 
void synchronize_global_id_set ()
 Synchronizes the boundary_ids set on each processor to determine global_boundary_ids.
 
void sync (UnstructuredMesh &boundary_mesh)
 Generates boundary_mesh data structures corresponding to the mesh data structures.
 
void sync (const std::set< boundary_id_type > &requested_boundary_ids, UnstructuredMesh &boundary_mesh)
 Generates boundary_mesh data structures corresponding to the mesh data structures.
 
void sync (const std::set< boundary_id_type > &requested_boundary_ids, UnstructuredMesh &boundary_mesh, const std::set< subdomain_id_type > &subdomains_relative_to)
 Like the other sync() implementations, but specifically intended for building "boundary" meshes from internal sidesets.
 
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_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, and which have interior_parent values properly defined.
 
void add_elements (const std::set< boundary_id_type > &requested_boundary_ids, UnstructuredMesh &boundary_mesh, const std::set< subdomain_id_type > &subdomains_relative_to, bool store_parent_side_ids=false, const std::vector< subdomain_id_type > &new_subdomain_ids={})
 Same as the add_elements() function above, but takes a set of subdomains for which the sides must be relative to.
 
void add_node (const Node *node, const boundary_id_type id)
 Add Node node with boundary id id to the boundary information data structures.
 
void add_node (const dof_id_type node, const boundary_id_type id)
 Add node number node with boundary id id to the boundary information data structures.
 
void add_node (const Node *node, const std::vector< boundary_id_type > &ids)
 Add Node node with boundary ids ids to the boundary information data structure.
 
void clear_boundary_node_ids ()
 Clears all the boundary information from all of the nodes in the 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 add_edge (const Elem *elem, const unsigned short int edge, const boundary_id_type id)
 Add edge edge of element elem with boundary id id to the boundary information data structure.
 
void add_edge (const Elem *elem, const unsigned short int edge, const std::vector< boundary_id_type > &ids)
 Add edge edge of element elem with boundary ids ids to the boundary information data structure.
 
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 structure.
 
void add_shellface (const Elem *elem, const unsigned short int shellface, const boundary_id_type id)
 Add shell face shellface of element elem with boundary id id to the boundary information data structure.
 
void add_shellface (const Elem *elem, const unsigned short int shellface, const std::vector< boundary_id_type > &ids)
 Add shell face shellface of element elem with boundary ids ids to the boundary information data structure.
 
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 add_side (const Elem *elem, const unsigned short int side, const boundary_id_type id)
 Add side side of element elem with boundary id id to the boundary information data structure.
 
void add_side (const Elem *elem, const unsigned short int side, const std::vector< boundary_id_type > &ids)
 Add side side of element elem with boundary ids ids to the boundary information data structure.
 
void remove (const Node *node)
 Removes the boundary conditions associated with node node, if any exist.
 
void remove (const Elem *elem)
 Removes the boundary conditions associated with element elem, if any exist.
 
void remove_node (const Node *node, const boundary_id_type id)
 Removes boundary id id from node node, if it exists.
 
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 remove_edge (const Elem *elem, const unsigned short int edge, const boundary_id_type id)
 Removes the boundary id id from edge edge of element elem, if it exists.
 
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.
 
void remove_shellface (const Elem *elem, const unsigned short int shellface, const boundary_id_type id)
 Removes all boundary conditions associated with shell face shellface of element elem, if any exist.
 
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_side (const Elem *elem, const unsigned short int side, const boundary_id_type id)
 Removes the boundary id id from side side of element elem, if it exists.
 
void clear_stitched_boundary_side_ids (boundary_id_type sideset_id, boundary_id_type other_sideset_id, bool clear_nodeset_data=false)
 Clear sideset information along a stitched mesh interface.
 
void remove_id (boundary_id_type id, bool global=false)
 Removes all entities (nodes, sides, edges, shellfaces) with boundary id id from their respective containers and erases any record of id's existence from the BoundaryInfo object.
 
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 boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.
 
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 boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.
 
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 shellface boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.
 
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 boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.
 
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 by boundary id new_id.
 
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.
 
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 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 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.
 
std::size_t n_boundary_ids () const
 
bool has_boundary_id (const Node *const node, const boundary_id_type id) 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.
 
unsigned int n_boundary_ids (const Node *node) const
 
unsigned int n_edge_boundary_ids (const Elem *const elem, const unsigned short int edge) const
 
void edge_boundary_ids (const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
 
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 shellface_boundary_ids (const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
 
void raw_shellface_boundary_ids (const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
 
bool has_boundary_id (const Elem *const elem, const unsigned short int side, const boundary_id_type id) const
 
unsigned int n_boundary_ids (const Elem *const elem, const unsigned short int side) const
 
unsigned int n_raw_boundary_ids (const Elem *const elem, const unsigned short int side) const
 
void side_boundary_ids (const Elem *const elem, std::vector< std::vector< boundary_id_type > > &vec_to_fill) const
 
void boundary_ids (const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const
 
void raw_boundary_ids (const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const
 
void copy_boundary_ids (const BoundaryInfo &old_boundary_info, const Elem *const old_elem, const Elem *const new_elem)
 
unsigned int side_with_boundary_id (const Elem *const elem, const boundary_id_type boundary_id) const
 
std::vector< unsigned intsides_with_boundary_id (const Elem *const elem, const boundary_id_type boundary_id) const
 
void build_node_boundary_ids (std::vector< boundary_id_type > &b_ids) const
 Builds the list of unique node boundary ids.
 
void build_side_boundary_ids (std::vector< boundary_id_type > &b_ids) const
 Builds the list of unique side boundary ids.
 
void build_shellface_boundary_ids (std::vector< boundary_id_type > &b_ids) const
 Builds the list of unique shellface boundary ids.
 
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::size_t n_boundary_conds () const
 
std::size_t n_edge_conds () const
 
std::size_t n_shellface_conds () const
 
std::size_t n_nodeset_conds () const
 
std::vector< NodeBCTuplebuild_node_list (NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) 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.
 
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::vector< BCTuplebuild_side_list (BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
 
std::vector< BCTuplebuild_active_side_list () const
 Create a list of (element_id, side_id, boundary_id) tuples for all relevant active sides.
 
std::vector< BCTuplebuild_edge_list () const
 Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.
 
std::vector< BCTuplebuild_shellface_list () const
 Create a list of (element_id, shellface_id, boundary_id) tuples for all relevant shellfaces.
 
void parallel_sync_side_ids ()
 Synchronize the boundary element side and node across processors.
 
void parallel_sync_node_ids ()
 
const std::set< boundary_id_type > & get_boundary_ids () const
 
const std::set< boundary_id_type > & get_global_boundary_ids () const
 
const std::set< boundary_id_type > & get_side_boundary_ids () const
 
const std::set< boundary_id_type > & get_edge_boundary_ids () const
 
const std::set< boundary_id_type > & get_shellface_boundary_ids () const
 
const std::set< boundary_id_type > & get_node_boundary_ids () const
 
void print_info (std::ostream &out_stream=libMesh::out) const
 Prints the boundary information data structure.
 
void print_summary (std::ostream &out_stream=libMesh::out) const
 Prints a summary of the boundary information.
 
const std::string & get_sideset_name (boundary_id_type id) const
 
std::string & sideset_name (boundary_id_type id)
 
const std::string & get_nodeset_name (boundary_id_type id) const
 
std::string & nodeset_name (boundary_id_type id)
 
const std::string & get_edgeset_name (boundary_id_type id) const
 
std::string & edgeset_name (boundary_id_type id)
 
boundary_id_type get_id_by_name (std::string_view name) const
 
std::map< boundary_id_type, std::string > & set_sideset_name_map ()
 
const std::map< boundary_id_type, std::string > & get_sideset_name_map () const
 
std::map< boundary_id_type, std::string > & set_nodeset_name_map ()
 
const std::map< boundary_id_type, std::string > & get_nodeset_name_map () const
 
std::map< boundary_id_type, std::string > & set_edgeset_name_map ()
 
const std::map< boundary_id_type, std::string > & get_edgeset_name_map () const
 
const std::multimap< const Node *, boundary_id_type > & get_nodeset_map () const
 
const std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > & get_edgeset_map () const
 
const std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > & get_sideset_map () const
 
bool is_children_on_boundary_side () const
 
void allow_children_on_boundary_side (const bool children_on_boundary)
 Whether or not to allow directly setting boundary sides on child elements.
 
const Parallel::Communicatorcomm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Static Public Attributes

static const boundary_id_type invalid_id = -123
 Number used for internal use.
 

Protected Member Functions

 BoundaryInfo (MeshBase &m)
 Constructor.
 
void set_mesh (MeshBase &m)
 

Protected Attributes

const Parallel::Communicator_communicator
 

Private Member Functions

void libmesh_assert_valid_multimaps () const
 Helper method for ensuring that our multimaps don't contain entries with duplicate keys and values.
 
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.
 

Private Attributes

MeshBase_mesh
 A pointer to the Mesh this boundary info pertains to.
 
std::multimap< const Node *, boundary_id_type_boundary_node_id
 Data structure that maps nodes in the mesh to boundary ids.
 
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.
 
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.
 
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.
 
bool _children_on_boundary
 
std::set< boundary_id_type_boundary_ids
 A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
 
std::set< boundary_id_type_global_boundary_ids
 A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
 
std::set< boundary_id_type_side_boundary_ids
 Set of user-specified boundary IDs for sides only.
 
std::set< boundary_id_type_edge_boundary_ids
 Set of user-specified boundary IDs for edges only.
 
std::set< boundary_id_type_node_boundary_ids
 Set of user-specified boundary IDs for nodes only.
 
std::set< boundary_id_type_shellface_boundary_ids
 Set of user-specified boundary IDs for shellfaces only.
 
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 this.
 
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 this.
 
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 this.
 

Friends

class MeshBase
 

Detailed Description

The BoundaryInfo class contains information relevant to boundary conditions including storing faces, edges, and nodes on the boundary, along with ids that can be used to identify the type of boundary each entity is part of.

It can also build a mesh that just includes boundary elements/faces.

Author
Benjamin S. Kirk
Date
2002

Used by the Mesh to keep track of boundary nodes and elements.

Definition at line 57 of file boundary_info.h.

Member Typedef Documentation

◆ BCTuple

typedef std::tuple<dof_id_type, unsigned short int, boundary_id_type> libMesh::BoundaryInfo::BCTuple

Create a list of (element_id, side_id, boundary_id) tuples for relevant sides.

On a ReplicatedMesh this will include all sides; on a DistributedMesh only sides of semilocal elements will be included.

The returned vector is sorted by element id by default, but this can be changed by passing SIDE_ID, BOUNDARY_ID, or UNSORTED to this function. Note: choosing UNSORTED is not recommended since the resulting list will potentially be in different orders on different processors when running in parallel.

Definition at line 759 of file boundary_info.h.

◆ NodeBCTuple

Create a list of (node_id, boundary_id) tuples for all relevant nodes.

On a ReplicatedMesh this will include all nodes; on a DistributedMesh only semilocal nodes will be included. Note: we could use std::pairs for this, but for consistency with the other build_XYZ_list functions, we're using tuples.

The "sort_by" parameter controls how the resulting list of tuples is sorted. It is possible (but not recommended) to choose UNSORTED, since in that case the resulting vectors will potentially be in different orders on different procs.

Definition at line 725 of file boundary_info.h.

Member Enumeration Documentation

◆ BCTupleSortBy

◆ NodeBCTupleSortBy

Enumerator
NODE_ID 
BOUNDARY_ID 
UNSORTED 

Definition at line 726 of file boundary_info.h.

Constructor & Destructor Documentation

◆ BoundaryInfo()

libMesh::BoundaryInfo::BoundaryInfo ( MeshBase m)
protected

Constructor.

Takes a reference to the mesh. The BoundaryInfo class is only used internally by the Mesh class. A user should never instantiate this class. Therefore the constructor is protected.

Definition at line 104 of file boundary_info.C.

104 :
105 ParallelObject(m.comm()),
106 _mesh (&m),
108{
109}
MeshBase * _mesh
A pointer to the Mesh this boundary info pertains to.
ParallelObject(const Parallel::Communicator &comm_in)
Constructor.

◆ ~BoundaryInfo()

libMesh::BoundaryInfo::~BoundaryInfo ( )
default

Destructor.

Not much to do.

Member Function Documentation

◆ _find_id_maps()

void libMesh::BoundaryInfo::_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 
)
private

Helper method for finding consistent maps of interior to boundary dof_object ids.

Either node_id_map or side_id_map can be nullptr, in which case it will not be filled.

Definition at line 3357 of file boundary_info.C.

3363{
3364 // We'll use the standard DistributedMesh trick of dividing up id
3365 // ranges by processor_id to avoid picking duplicate node ids.
3367 next_node_id = first_free_node_id + this->processor_id();
3368
3369 // We have to be careful how we select different element ids on
3370 // different processors, because we may be adding sides of refined
3371 // elements and sides of their parents (which are thereby also
3372 // parents of their sides), but libMesh convention requires (and
3373 // some libMesh communication code assumes) that parent elements
3374 // have lower ids than their children.
3375 //
3376 // We'll start with temporary ids in a temporary map stratefied by
3377 // element level, so we can sort by element level after.
3378 // Make sure we're sorting by ids here, not anything that might
3379 // differ from processor to processor, so we can do an
3380 // embarrassingly parallel sort. This is a serialized data
3381 // structure, but it's at worst O(N^2/3) so we'll hold off on doing
3382 // this distributed until someone's benchmark screams at us.
3383 std::vector
3384 <std::set<std::pair<dof_id_type, unsigned char>>>
3385 side_id_set_by_level;
3386
3387 // For avoiding extraneous element side construction
3388 ElemSideBuilder side_builder;
3389 // Pull objects out of the loop to reduce heap operations
3390 const Elem * side;
3391
3392 // We'll pass through the mesh once first to build
3393 // the maps and count boundary nodes and elements.
3394 // To find local boundary nodes, we have to examine all elements
3395 // here rather than just local elements, because it's possible to
3396 // have a local boundary node that's not on a local boundary
3397 // element, e.g. at the tip of a triangle.
3398
3399 // We'll loop through two different ranges here: first all elements,
3400 // looking for local nodes, and second through unpartitioned
3401 // elements, looking for all remaining nodes.
3402 const MeshBase::const_element_iterator end_el = _mesh->elements_end();
3403 bool hit_end_el = false;
3404 const MeshBase::const_element_iterator end_unpartitioned_el =
3405 _mesh->pid_elements_end(DofObject::invalid_processor_id);
3406
3407 for (MeshBase::const_element_iterator el = _mesh->elements_begin();
3408 !hit_end_el || (el != end_unpartitioned_el); ++el)
3409 {
3410 if ((el == end_el) && !hit_end_el)
3411 {
3412 // Note that we're done with local nodes and just looking
3413 // for remaining unpartitioned nodes
3414 hit_end_el = true;
3415
3416 // Join up the local results from other processors
3417 if (side_id_map)
3418 {
3419 std::size_t n_levels = side_id_set_by_level.size();
3420 this->comm().max(n_levels);
3421 side_id_set_by_level.resize(n_levels);
3422 for (auto l : make_range(n_levels))
3423 this->comm().set_union(side_id_set_by_level[l]);
3424 }
3425 if (node_id_map)
3426 this->comm().set_union(*node_id_map);
3427
3428 // Finally we'll pass through any unpartitioned elements to add them
3429 // to the maps and counts.
3430 next_node_id = first_free_node_id + this->n_processors();
3431
3432 el = _mesh->pid_elements_begin(DofObject::invalid_processor_id);
3433 if (el == end_unpartitioned_el)
3434 break;
3435 }
3436
3437 const Elem * elem = *el;
3438
3439 // If the subdomains_relative_to container has the
3440 // invalid_subdomain_id, we fall back on the "old" behavior of
3441 // adding sides regardless of this Elem's subdomain. Otherwise,
3442 // if the subdomains_relative_to container doesn't contain the
3443 // current Elem's subdomain_id(), we won't add any sides from
3444 // it.
3445 if (!subdomains_relative_to.count(Elem::invalid_subdomain_id) &&
3446 !subdomains_relative_to.count(elem->subdomain_id()))
3447 continue;
3448
3449 for (auto s : elem->side_index_range())
3450 {
3451 bool add_this_side = false;
3452
3453 // Find all the boundary side ids for this Elem side.
3454 std::vector<boundary_id_type> bcids;
3455 this->boundary_ids(elem, s, bcids);
3456
3457 for (const boundary_id_type bcid : bcids)
3458 {
3459 // if the user wants this id, we want this side
3460 if (requested_boundary_ids.count(bcid))
3461 {
3462 add_this_side = true;
3463 break;
3464 }
3465 }
3466
3467 // We may still want to add this side if the user called
3468 // sync() with no requested_boundary_ids. This corresponds
3469 // to the "old" style of calling sync() in which the entire
3470 // boundary was copied to the BoundaryMesh, and handles the
3471 // case where elements on the geometric boundary are not in
3472 // any sidesets.
3473 if (requested_boundary_ids.count(invalid_id) &&
3474 elem->neighbor_ptr(s) == nullptr)
3475 add_this_side = true;
3476
3477 if (add_this_side)
3478 {
3479 // We only assign ids for our own and for
3480 // unpartitioned elements
3481 if (side_id_map &&
3482 ((elem->processor_id() == this->processor_id()) ||
3483 (elem->processor_id() ==
3485 {
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];
3491 libmesh_assert (!level_side_id_set.count(side_pair));
3492 level_side_id_set.insert(side_pair);
3493 }
3494
3495 side = &side_builder(*elem, s);
3496 for (auto n : side->node_index_range())
3497 {
3498 const Node & node = side->node_ref(n);
3499
3500 // In parallel we don't know enough to number
3501 // others' nodes ourselves.
3502 if (!hit_end_el &&
3503 (node.processor_id() != this->processor_id()))
3504 continue;
3505
3506 dof_id_type node_id = node.id();
3507 if (node_id_map && !node_id_map->count(node_id))
3508 {
3509 (*node_id_map)[node_id] = next_node_id;
3510 next_node_id += this->n_processors() + 1;
3511 }
3512 }
3513 }
3514 }
3515 }
3516
3517 // FIXME: should we renumber node_id_map's image to be contiguous
3518 // here, rather than waiting for renumbering in mesh preparation to
3519 // do it later?
3520
3521 // We do need to build up side_id_map here, to handle proper sorting
3522 // by level.
3523 if (side_id_map)
3524 {
3525 dof_id_type next_elem_id = first_free_elem_id;
3526 for (auto level : make_range(side_id_set_by_level.size()))
3527 {
3528 for (auto side_pair : side_id_set_by_level[level])
3529 (*side_id_map)[side_pair] = next_elem_id++;
3530 }
3531 }
3532}
void max(const T &r, T &o, Request &req) const
void set_union(T &data, const unsigned int root_id) 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.
static const boundary_id_type invalid_id
Number used for internal use.
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
Definition dof_object.h:484
static constexpr subdomain_id_type invalid_subdomain_id
A static integral constant representing an invalid subdomain id.
Definition elem.h:246
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
unsigned int n_levels(const MeshBase &mesh)
Definition mesh_tools.C:826
int8_t boundary_id_type
Definition id_types.h:51
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67
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...
Definition int_range.h:176

References _mesh, boundary_ids(), libMesh::ParallelObject::comm(), libMesh::DofObject::id(), invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::Elem::invalid_subdomain_id, libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::make_range(), libMesh::Parallel::Communicator::max(), libMesh::ParallelObject::n_processors(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::node_index_range(), libMesh::Elem::node_ref(), libMesh::DofObject::processor_id(), libMesh::ParallelObject::processor_id(), libMesh::Parallel::Communicator::set_union(), libMesh::Elem::side_index_range(), and libMesh::Elem::subdomain_id().

Referenced by add_elements(), and sync().

◆ add_edge() [1/3]

void libMesh::BoundaryInfo::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.

Edge-based boundary IDs should only be used in 3D.

Definition at line 1066 of file boundary_info.C.

1069{
1070 this->add_edge (_mesh->elem_ptr(e), edge, id);
1071}
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.
virtual const Elem * elem_ptr(const dof_id_type i) const =0

References _mesh, add_edge(), and libMesh::MeshBase::elem_ptr().

Referenced by add_edge(), copy_boundary_ids(), main(), libMesh::ExodusII_IO_Helper::read_edge_blocks(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::UnstructuredMesh::stitching_helper(), libMesh::Elem::swap2boundaryedges(), SystemsTest::testBoundaryProjectCube(), BoundaryInfoTest::testEdgeBoundaryConditions(), BoundaryInfoTest::testSelectiveRenumber(), WriteEdgesetData::testWriteImpl(), and libMesh::Parallel::Packing< Elem * >::unpack().

◆ add_edge() [2/3]

void libMesh::BoundaryInfo::add_edge ( const Elem elem,
const unsigned short int  edge,
const boundary_id_type  id 
)

Add edge edge of element elem with boundary id id to the boundary information data structure.

Edge-based boundary IDs should only be used in 3D.

Definition at line 1075 of file boundary_info.C.

1078{
1079 libmesh_assert(elem);
1080
1081 // Only add BCs for level-0 elements.
1082 libmesh_assert_equal_to (elem->level(), 0);
1083
1084 // Only add BCs for edges that exist.
1085 libmesh_assert_less (edge, elem->n_edges());
1086
1087 libmesh_error_msg_if(id == invalid_id,
1088 "ERROR: You may not set a boundary ID of "
1089 << invalid_id
1090 << "\n That is reserved for internal use.");
1091
1092 // Don't add the same ID twice
1093 for (const auto & pr : as_range(_boundary_edge_id.equal_range(elem)))
1094 if (pr.second.first == edge &&
1095 pr.second.second == id)
1096 return;
1097
1098 _boundary_edge_id.emplace(elem, std::make_pair(edge, id));
1099 _boundary_ids.insert(id);
1100 _edge_boundary_ids.insert(id); // Also add this ID to the set of edge boundary IDs
1101}
std::set< boundary_id_type > _boundary_ids
A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
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.
std::set< boundary_id_type > _edge_boundary_ids
Set of user-specified boundary IDs for edges only.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.

References _boundary_edge_id, _boundary_ids, _edge_boundary_ids, libMesh::as_range(), invalid_id, libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::n_edges().

◆ add_edge() [3/3]

void libMesh::BoundaryInfo::add_edge ( const Elem elem,
const unsigned short int  edge,
const std::vector< boundary_id_type > &  ids 
)

Add edge edge of element elem with boundary ids ids to the boundary information data structure.

Edge-based boundary IDs should only be used in 3D.

Definition at line 1105 of file boundary_info.C.

1108{
1109 if (ids.empty())
1110 return;
1111
1112 libmesh_assert(elem);
1113
1114 // Only add BCs for level-0 elements.
1115 libmesh_assert_equal_to (elem->level(), 0);
1116
1117 // Only add BCs for edges that exist.
1118 libmesh_assert_less (edge, elem->n_edges());
1119
1120 // Don't add the same ID twice
1121 auto bounds = _boundary_edge_id.equal_range(elem);
1122
1123 // The entries in the ids vector may be non-unique. If we expected
1124 // *lots* of ids, it might be fastest to construct a std::set from
1125 // the entries, but for a small number of entries, which is more
1126 // typical, it is probably faster to copy the vector and do sort+unique.
1127 // http://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector
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());
1132
1133 for (auto & id : as_range(unique_ids.begin(), new_end))
1134 {
1135 libmesh_error_msg_if(id == invalid_id,
1136 "ERROR: You may not set a boundary ID of "
1137 << invalid_id
1138 << "\n That is reserved for internal use.");
1139
1140 bool already_inserted = false;
1141 for (const auto & pr : as_range(bounds))
1142 if (pr.second.first == edge &&
1143 pr.second.second == id)
1144 {
1145 already_inserted = true;
1146 break;
1147 }
1148 if (already_inserted)
1149 continue;
1150
1151 _boundary_edge_id.emplace(elem, std::make_pair(edge, id));
1152 _boundary_ids.insert(id);
1153 _edge_boundary_ids.insert(id); // Also add this ID to the set of edge boundary IDs
1154 }
1155}

References _boundary_edge_id, _boundary_ids, _edge_boundary_ids, libMesh::as_range(), invalid_id, libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::n_edges().

◆ add_elements() [1/2]

void libMesh::BoundaryInfo::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, and which have interior_parent values properly defined.

The boundary_mesh may be the same as the interior mesh; this generates a mesh with elements of mixed dimension.

Only boundary element sides with boundary ids in the requested_boundary_ids set are considered for addition.

If new_subdomain_ids is empty, newly created elements retain the default subdomain id. If it contains a single entry, all new elements are assigned that subdomain id. If its size equals requested_boundary_ids.size(), new elements are assigned subdomain ids in one-to-one correspondence with the boundary ids (iterated in sorted order).

Definition at line 656 of file boundary_info.C.

660{
661 // Call the 3 argument version of this function with a dummy value for the third arg.
662 std::set<subdomain_id_type> subdomains_relative_to;
663 subdomains_relative_to.insert(Elem::invalid_subdomain_id);
664
665 this->add_elements(requested_boundary_ids,
666 boundary_mesh,
667 subdomains_relative_to,
668 store_parent_side_ids,
669 new_subdomain_ids);
670}
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...

References add_elements(), and libMesh::Elem::invalid_subdomain_id.

Referenced by add_elements(), main(), sync(), BoundaryMeshSubdomainTest::testDefaultSubdomain(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), and BoundaryMeshSubdomainTest::testSingleSubdomain().

◆ add_elements() [2/2]

void libMesh::BoundaryInfo::add_elements ( const std::set< boundary_id_type > &  requested_boundary_ids,
UnstructuredMesh boundary_mesh,
const std::set< subdomain_id_type > &  subdomains_relative_to,
bool  store_parent_side_ids = false,
const std::vector< subdomain_id_type > &  new_subdomain_ids = {} 
)

Same as the add_elements() function above, but takes a set of subdomains for which the sides must be relative to.

This is necessary to avoid double-adding sides of internal sidesets to the BoundaryMesh.

Definition at line 674 of file boundary_info.C.

679{
680 libmesh_assert(new_subdomain_ids.empty() ||
681 new_subdomain_ids.size() == 1 ||
682 new_subdomain_ids.size() == requested_boundary_ids.size());
683 LOG_SCOPE("add_elements()", "BoundaryInfo");
684
685 // We're not prepared to mix serial and distributed meshes in this
686 // method, so make sure their statuses match from the start.
687 //
688 // Specifically test *is_serial* here - we can handle a mix of
689 // ReplicatedMesh and serialized DistributedMesh.
690 libmesh_assert_equal_to(_mesh->is_serial(),
691 boundary_mesh.is_serial());
692
693 // If the boundary mesh already has interior pointers pointing at
694 // elements in a third mesh then we're in trouble
695 libmesh_assert(&boundary_mesh.interior_mesh() == &boundary_mesh ||
696 &boundary_mesh.interior_mesh() == _mesh);
697
698 // And now we're going to add interior pointers to elements from
699 // this mesh
700 boundary_mesh.set_interior_mesh(*_mesh);
701
702 std::map<std::pair<dof_id_type, unsigned char>, dof_id_type> side_id_map;
703 this->_find_id_maps(requested_boundary_ids,
704 0,
705 nullptr,
706 boundary_mesh.max_elem_id(),
707 &side_id_map,
708 subdomains_relative_to);
709
710 // We have to add sides *outside* any element loop, because if
711 // boundary_mesh and _mesh are the same then those additions can
712 // invalidate our element iterators. So we just use the element
713 // loop to make a list of sides to add.
714 typedef std::vector<std::tuple<dof_id_type, unsigned char, boundary_id_type>>
715 side_container;
716 side_container sides_to_add;
717
718 for (const auto & elem : _mesh->element_ptr_range())
719 {
720 // If the subdomains_relative_to container has the
721 // invalid_subdomain_id, we fall back on the "old" behavior of
722 // adding sides regardless of this Elem's subdomain. Otherwise,
723 // if the subdomains_relative_to container doesn't contain the
724 // current Elem's subdomain_id(), we won't add any sides from
725 // it.
726 if (!subdomains_relative_to.count(Elem::invalid_subdomain_id) &&
727 !subdomains_relative_to.count(elem->subdomain_id()))
728 continue;
729
730 for (auto s : elem->side_index_range())
731 {
732 bool add_this_side = false;
733 boundary_id_type triggering_bcid = invalid_id;
734
735 // Find all the boundary side ids for this Elem side.
736 std::vector<boundary_id_type> bcids;
737 this->boundary_ids(elem, s, bcids);
738
739 for (const boundary_id_type bcid : bcids)
740 {
741 // if the user wants this id, we want this side
742 if (requested_boundary_ids.count(bcid))
743 {
744 add_this_side = true;
745 triggering_bcid = bcid;
746 break;
747 }
748 }
749
750 // We may still want to add this side if the user called
751 // sync() with no requested_boundary_ids. This corresponds
752 // to the "old" style of calling sync() in which the entire
753 // boundary was copied to the BoundaryMesh, and handles the
754 // case where elements on the geometric boundary are not in
755 // any sidesets.
756 if (requested_boundary_ids.count(invalid_id) &&
757 elem->neighbor_ptr(s) == nullptr)
758 add_this_side = true;
759
760 if (add_this_side)
761 sides_to_add.emplace_back(elem->id(), s, triggering_bcid);
762 }
763 }
764
765#ifdef LIBMESH_ENABLE_UNIQUE_ID
766 unique_id_type old_max_unique_id = boundary_mesh.parallel_max_unique_id();
767#endif
768
769 // Add an "extra" integer for storing the side index of the parent
770 // Elem which each boundary Elem corresponds to. We do this once
771 // before any Elems have been added.
772 unsigned int parent_side_index_tag = store_parent_side_ids ?
773 boundary_mesh.add_elem_integer("parent_side_index") : libMesh::invalid_uint;
774
775 // When new elements are assigned subdomain ids in one-to-one
776 // correspondence with the requested boundary ids, we need to map a
777 // boundary id to its index in the (sorted) set. Copying the set into a
778 // contiguous vector lets us do that index lookup in O(1) (after an
779 // O(log N) Utility::binary_find()) rather than the O(N) std::distance()
780 // between std::set iterators.
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());
785
786 for (const auto & [elem_id, s, triggering_bcid] : sides_to_add)
787 {
788 Elem * elem = _mesh->elem_ptr(elem_id);
789
790 std::unique_ptr<Elem> side = elem->build_side_ptr(s);
791
792 side->processor_id() = elem->processor_id();
793
794 const std::pair<dof_id_type, unsigned char> side_pair(elem_id, s);
795
796 libmesh_assert(side_id_map.count(side_pair));
797
798 const dof_id_type new_side_id = side_id_map[side_pair];
799
800 side->set_id(new_side_id);
801
802#ifdef LIBMESH_ENABLE_UNIQUE_ID
803 side->set_unique_id(old_max_unique_id + new_side_id);
804#endif
805
806 // Add the side
807 Elem * new_elem = boundary_mesh.add_elem(std::move(side));
808
809 // If requested, new_elem gets an "extra" integer equal to the
810 // side id "s" of the interior_parent it corresponds to.
811 if (store_parent_side_ids)
812 new_elem->set_extra_integer(parent_side_index_tag, s);
813
814 // Assign subdomain id if requested.
815 if (new_subdomain_ids.size() == 1)
816 new_elem->subdomain_id() = new_subdomain_ids[0];
817 else if (new_subdomain_ids.size() > 1)
818 {
819 auto it = Utility::binary_find(requested_boundary_ids_vec.begin(),
820 requested_boundary_ids_vec.end(),
821 triggering_bcid);
822 libmesh_assert(it != requested_boundary_ids_vec.end());
823 new_elem->subdomain_id() =
824 new_subdomain_ids[std::distance(requested_boundary_ids_vec.begin(), it)];
825 }
826
827#ifdef LIBMESH_ENABLE_AMR
828 new_elem->set_refinement_flag(elem->refinement_flag());
829 new_elem->set_p_refinement_flag(elem->p_refinement_flag());
830
831 // Set parent links
832 if (elem->parent())
833 {
834 const std::pair<dof_id_type, unsigned char> parent_side_pair(elem->parent()->id(), s);
835
836 libmesh_assert(side_id_map.count(parent_side_pair));
837
838 Elem * side_parent = boundary_mesh.elem_ptr(side_id_map[parent_side_pair]);
839
840 libmesh_assert(side_parent);
841
842 new_elem->set_parent(side_parent);
843
844 // Figuring out which child we are of our parent
845 // is a trick. Due to libMesh child numbering
846 // conventions, if we are an element on a vertex,
847 // then we share that vertex with our parent, with
848 // the same local index.
849 bool found_child = false;
850 for (auto v : make_range(new_elem->n_vertices()))
851 if (new_elem->node_ptr(v) == side_parent->node_ptr(v))
852 {
853 side_parent->add_child(new_elem, v);
854 found_child = true;
855 }
856
857 // If we don't share any vertex with our parent,
858 // then we're the fourth child (index 3) of a
859 // triangle.
860 if (!found_child)
861 {
862 libmesh_assert_equal_to (new_elem->n_vertices(), 3);
863 side_parent->add_child(new_elem, 3);
864 }
865 }
866
867 // Set remote_elem child links if necessary. Rather than
868 // worrying about which interior child corresponds to which side
869 // child we'll just set all null links to be remote and we'll
870 // rely on our detection of actual semilocal children to
871 // overwrite the links that shouldn't be remote.
872 if (elem->has_children())
873 for (auto c : make_range(elem->n_children()))
874 if (elem->child_ptr(c) == remote_elem &&
875 elem->is_child_on_side(c, s))
876 {
877 for (auto sc : make_range(new_elem->n_children()))
878 if (!new_elem->raw_child_ptr(sc))
879 new_elem->add_child
880 (const_cast<RemoteElem*>(remote_elem), sc);
881 }
882#endif
883
884 new_elem->set_interior_parent (elem);
885
886 // On non-local elements on DistributedMesh we might have
887 // RemoteElem neighbor links to construct
888 if (!_mesh->is_serial() &&
889 (elem->processor_id() != this->processor_id()))
890 {
891 const unsigned short n_nodes = elem->n_nodes();
892
893 const unsigned short bdy_n_sides = new_elem->n_sides();
894 const unsigned short bdy_n_nodes = new_elem->n_nodes();
895
896 // Check every interior side for a RemoteElem
897 for (auto interior_side : elem->side_index_range())
898 {
899 // Might this interior side have a RemoteElem that
900 // needs a corresponding Remote on a boundary side?
901 if (elem->neighbor_ptr(interior_side) != remote_elem)
902 continue;
903
904 // Which boundary side?
905 for (unsigned short boundary_side = 0;
906 boundary_side != bdy_n_sides; ++boundary_side)
907 {
908 // Look for matching node points. This is safe in
909 // *this* context.
910 bool found_all_nodes = true;
911 for (unsigned short boundary_node = 0;
912 boundary_node != bdy_n_nodes; ++boundary_node)
913 {
914 if (!new_elem->is_node_on_side(boundary_node,
915 boundary_side))
916 continue;
917
918 bool found_this_node = false;
919 for (unsigned short interior_node = 0;
920 interior_node != n_nodes; ++interior_node)
921 {
922 if (!elem->is_node_on_side(interior_node,
923 interior_side))
924 continue;
925
926 if (new_elem->point(boundary_node) ==
927 elem->point(interior_node))
928 {
929 found_this_node = true;
930 break;
931 }
932 }
933 if (!found_this_node)
934 {
935 found_all_nodes = false;
936 break;
937 }
938 }
939
940 if (found_all_nodes)
941 {
942 new_elem->set_neighbor
943 (boundary_side,
944 const_cast<RemoteElem *>(remote_elem));
945 break;
946 }
947 }
948 }
949 }
950 }
951
952 // We haven't been bothering to keep unique ids consistent on ghost
953 // elements or nodes, unless we're doing everything the same on
954 // every processor.
955 if (!boundary_mesh.is_replicated())
956 MeshCommunication().make_node_unique_ids_parallel_consistent(boundary_mesh);
957
958 // Make sure we didn't add ids inconsistently
959#ifdef DEBUG
960# ifdef LIBMESH_HAVE_RTTI
961 DistributedMesh * parmesh = dynamic_cast<DistributedMesh *>(&boundary_mesh);
962 if (parmesh)
963 parmesh->libmesh_assert_valid_parallel_ids();
964# endif
965#endif
966
967 // global containers are not synced
968 boundary_mesh.unset_has_boundary_id_sets();
969
970 // New elements were added; mark the affected preparation flags invalid.
971 boundary_mesh.unset_has_neighbor_ptrs();
972 boundary_mesh.unset_has_cached_elem_data();
973 boundary_mesh.unset_has_reinit_ghosting_functors();
974}
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.
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
virtual bool is_serial() const
Definition mesh_base.h:357
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...
Definition utility.h:233
uint8_t unique_id_type
Definition id_types.h:86
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303
const RemoteElem * remote_elem
Definition remote_elem.C:57
const dof_id_type n_nodes
Definition tecplot_io.C:67

References _find_id_maps(), _mesh, libMesh::Elem::add_child(), libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_elem_integer(), libMesh::Utility::binary_find(), boundary_ids(), libMesh::Elem::build_side_ptr(), libMesh::Elem::child_ptr(), libMesh::MeshBase::elem_ptr(), libMesh::Elem::has_children(), libMesh::DofObject::id(), libMesh::MeshBase::interior_mesh(), invalid_id, libMesh::Elem::invalid_subdomain_id, libMesh::invalid_uint, libMesh::Elem::is_child_on_side(), libMesh::Elem::is_node_on_side(), libMesh::MeshBase::is_replicated(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_ids(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::make_range(), libMesh::MeshBase::max_elem_id(), libMesh::Elem::n_children(), libMesh::Elem::n_nodes(), n_nodes, libMesh::Elem::n_sides(), libMesh::Elem::n_vertices(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::node_ptr(), libMesh::Elem::p_refinement_flag(), libMesh::MeshBase::parallel_max_unique_id(), libMesh::Elem::parent(), libMesh::Elem::point(), libMesh::DofObject::processor_id(), libMesh::ParallelObject::processor_id(), libMesh::Elem::raw_child_ptr(), libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::DofObject::set_extra_integer(), libMesh::MeshBase::set_interior_mesh(), libMesh::Elem::set_interior_parent(), libMesh::Elem::set_neighbor(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_parent(), libMesh::Elem::set_refinement_flag(), libMesh::Elem::side_index_range(), libMesh::Elem::subdomain_id(), libMesh::MeshBase::unset_has_boundary_id_sets(), libMesh::MeshBase::unset_has_cached_elem_data(), libMesh::MeshBase::unset_has_neighbor_ptrs(), and libMesh::MeshBase::unset_has_reinit_ghosting_functors().

◆ add_node() [1/3]

void libMesh::BoundaryInfo::add_node ( const dof_id_type  node,
const boundary_id_type  id 
)

Add node number node with boundary id id to the boundary information data structures.

Definition at line 978 of file boundary_info.C.

980{
981 const Node * node_ptr = _mesh->query_node_ptr(node_id);
982
983 // The user could easily ask for an invalid node id, so let's throw
984 // an easy-to-understand error message when this happens.
985 libmesh_error_msg_if(!node_ptr,
986 "BoundaryInfo::add_node(): Could not retrieve pointer for node "
987 << node_id
988 << ", no boundary id was added.");
989
990 this->add_node (node_ptr, id);
991}
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
virtual const Node * query_node_ptr(const dof_id_type i) const =0

References _mesh, add_node(), and libMesh::MeshBase::query_node_ptr().

◆ add_node() [2/3]

void libMesh::BoundaryInfo::add_node ( const Node node,
const boundary_id_type  id 
)

Add Node node with boundary id id to the boundary information data structures.

Definition at line 995 of file boundary_info.C.

997{
998 libmesh_error_msg_if(id == invalid_id,
999 "ERROR: You may not set a boundary ID of "
1000 << invalid_id
1001 << "\n That is reserved for internal use.");
1002
1003 // Don't add the same ID twice
1004 for (const auto & pr : as_range(_boundary_node_id.equal_range(node)))
1005 if (pr.second == id)
1006 return;
1007
1008 _boundary_node_id.emplace(node, id);
1009 _boundary_ids.insert(id);
1010 _node_boundary_ids.insert(id); // Also add this ID to the set of node boundary IDs
1011}
std::set< boundary_id_type > _node_boundary_ids
Set of user-specified boundary IDs for nodes only.
std::multimap< const Node *, boundary_id_type > _boundary_node_id
Data structure that maps nodes in the mesh to boundary ids.

References _boundary_ids, _boundary_node_id, _node_boundary_ids, libMesh::as_range(), and invalid_id.

Referenced by libMesh::MeshTools::Subdivision::add_boundary_ghosts(), add_node(), libMesh::AbaqusIO::assign_boundary_node_ids(), libMesh::MeshTools::Generation::build_cube(), libMesh::MeshTools::Generation::build_extrusion(), build_node_list_from_side_list(), main(), libMesh::Nemesis_IO::read(), libMesh::ExodusII_IO::read(), libMesh::GmshIO::read_mesh(), libMesh::CheckpointIO::read_nodesets(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::UnstructuredMesh::stitching_helper(), sync(), SystemsTest::testBoundaryProjectCube(), and libMesh::Parallel::Packing< Node * >::unpack().

◆ add_node() [3/3]

void libMesh::BoundaryInfo::add_node ( const Node node,
const std::vector< boundary_id_type > &  ids 
)

Add Node node with boundary ids ids to the boundary information data structure.

Definition at line 1015 of file boundary_info.C.

1017{
1018 if (ids.empty())
1019 return;
1020
1021 libmesh_assert(node);
1022
1023 // Don't add the same ID twice
1024 auto bounds = _boundary_node_id.equal_range(node);
1025
1026 // The entries in the ids vector may be non-unique. If we expected
1027 // *lots* of ids, it might be fastest to construct a std::set from
1028 // the entries, but for a small number of entries, which is more
1029 // typical, it is probably faster to copy the vector and do sort+unique.
1030 // http://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector
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());
1035
1036 for (auto & id : as_range(unique_ids.begin(), new_end))
1037 {
1038 libmesh_error_msg_if(id == invalid_id,
1039 "ERROR: You may not set a boundary ID of "
1040 << invalid_id
1041 << "\n That is reserved for internal use.");
1042
1043 bool already_inserted = false;
1044 for (const auto & pr : as_range(bounds))
1045 if (pr.second == id)
1046 {
1047 already_inserted = true;
1048 break;
1049 }
1050 if (already_inserted)
1051 continue;
1052
1053 _boundary_node_id.emplace(node, id);
1054 _boundary_ids.insert(id);
1055 _node_boundary_ids.insert(id); // Also add this ID to the set of node boundary IDs
1056 }
1057}

References _boundary_ids, _boundary_node_id, _node_boundary_ids, libMesh::as_range(), invalid_id, and libMesh::libmesh_assert().

◆ add_shellface() [1/3]

void libMesh::BoundaryInfo::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 structure.

This is only relevant for shell elements.

Definition at line 1159 of file boundary_info.C.

1162{
1163 this->add_shellface (_mesh->elem_ptr(e), shellface, id);
1164}
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 ...

References _mesh, add_shellface(), and libMesh::MeshBase::elem_ptr().

Referenced by add_shellface(), copy_boundary_ids(), libMesh::ExodusII_IO::read(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::UnstructuredMesh::stitching_helper(), BoundaryInfoTest::testShellFaceConstraints(), and libMesh::Parallel::Packing< Elem * >::unpack().

◆ add_shellface() [2/3]

void libMesh::BoundaryInfo::add_shellface ( const Elem elem,
const unsigned short int  shellface,
const boundary_id_type  id 
)

Add shell face shellface of element elem with boundary id id to the boundary information data structure.

This is only relevant for shell elements.

Definition at line 1168 of file boundary_info.C.

1171{
1172 libmesh_assert(elem);
1173
1174 // Only add BCs for level-0 elements.
1175 libmesh_assert_equal_to (elem->level(), 0);
1176
1177 // Shells only have 2 faces
1178 libmesh_assert_less(shellface, 2);
1179
1180 libmesh_error_msg_if(id == invalid_id,
1181 "ERROR: You may not set a boundary ID of "
1182 << invalid_id
1183 << "\n That is reserved for internal use.");
1184
1185 // Don't add the same ID twice
1186 for (const auto & pr : as_range(_boundary_shellface_id.equal_range(elem)))
1187 if (pr.second.first == shellface &&
1188 pr.second.second == id)
1189 return;
1190
1191 _boundary_shellface_id.emplace(elem, std::make_pair(shellface, id));
1192 _boundary_ids.insert(id);
1193 _shellface_boundary_ids.insert(id); // Also add this ID to the set of shellface boundary IDs
1194}
std::set< boundary_id_type > _shellface_boundary_ids
Set of user-specified boundary IDs for shellfaces only.
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.

References _boundary_ids, _boundary_shellface_id, _shellface_boundary_ids, libMesh::as_range(), invalid_id, libMesh::Elem::level(), and libMesh::libmesh_assert().

◆ add_shellface() [3/3]

void libMesh::BoundaryInfo::add_shellface ( const Elem elem,
const unsigned short int  shellface,
const std::vector< boundary_id_type > &  ids 
)

Add shell face shellface of element elem with boundary ids ids to the boundary information data structure.

This is only relevant for shell elements.

Definition at line 1198 of file boundary_info.C.

1201{
1202 if (ids.empty())
1203 return;
1204
1205 libmesh_assert(elem);
1206
1207 // Only add BCs for level-0 elements.
1208 libmesh_assert_equal_to (elem->level(), 0);
1209
1210 // Shells only have 2 faces
1211 libmesh_assert_less(shellface, 2);
1212
1213 // Don't add the same ID twice
1214 auto bounds = _boundary_shellface_id.equal_range(elem);
1215
1216 // The entries in the ids vector may be non-unique. If we expected
1217 // *lots* of ids, it might be fastest to construct a std::set from
1218 // the entries, but for a small number of entries, which is more
1219 // typical, it is probably faster to copy the vector and do sort+unique.
1220 // http://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector
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());
1225
1226 for (auto & id : as_range(unique_ids.begin(), new_end))
1227 {
1228 libmesh_error_msg_if(id == invalid_id,
1229 "ERROR: You may not set a boundary ID of "
1230 << invalid_id
1231 << "\n That is reserved for internal use.");
1232
1233 bool already_inserted = false;
1234 for (const auto & pr : as_range(bounds))
1235 if (pr.second.first == shellface &&
1236 pr.second.second == id)
1237 {
1238 already_inserted = true;
1239 break;
1240 }
1241 if (already_inserted)
1242 continue;
1243
1244 _boundary_shellface_id.emplace(elem, std::make_pair(shellface, id));
1245 _boundary_ids.insert(id);
1246 _shellface_boundary_ids.insert(id); // Also add this ID to the set of shellface boundary IDs
1247 }
1248}

References _boundary_ids, _boundary_shellface_id, _shellface_boundary_ids, libMesh::as_range(), invalid_id, libMesh::Elem::level(), and libMesh::libmesh_assert().

◆ add_side() [1/3]

void libMesh::BoundaryInfo::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.

Definition at line 1251 of file boundary_info.C.

1254{
1255 this->add_side (_mesh->elem_ptr(e), side, id);
1256}
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.

References _mesh, add_side(), and libMesh::MeshBase::elem_ptr().

Referenced by add_side(), libMesh::MeshTools::Subdivision::all_subdivision(), libMesh::MeshTools::Modification::all_tri(), libMesh::AbaqusIO::assign_sideset_ids(), libMesh::MeshTools::Generation::build_cube(), libMesh::MeshTools::Generation::build_delaunay_square(), libMesh::MeshTools::Generation::build_extrusion(), DisjointNeighborTest::build_four_disjoint_elems(), BoundaryMesh0DTest::build_mesh(), BoundaryMeshTest::build_mesh(), build_side_list_from_node_list(), DisjointNeighborTest::build_split_mesh_with_interface(), DisjointNeighborTest::build_two_disjoint_elems(), copy_boundary_ids(), libMesh::TriangleWrapper::copy_tri_to_mesh(), libMesh::UnstructuredMesh::create_submesh(), libMesh::MeshTools::Modification::flatten(), libMesh::UNVIO::groups_in(), libMesh::Poly2TriTriangulator::insert_refinement_points(), main(), libMesh::Nemesis_IO::read(), libMesh::ExodusII_IO::read(), libMesh::CheckpointIO::read_bcs(), libMesh::GmshIO::read_mesh(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::UnstructuredMesh::stitching_helper(), libMesh::Elem::swap2boundarysides(), AllTriTest::test_helper_c0polyhedron(), AllTriTest::testAllTriC0PolygonOctagon(), BoundaryInfoTest::testBoundaryIDs(), BoundaryInfoTest::testBoundaryOnChildrenBoundaryIDs(), BoundaryInfoTest::testBoundaryOnChildrenBoundarySides(), BoundaryInfoTest::testBoundaryOnChildrenElementsRefineCoarsen(), BoundaryInfoTest::testBoundaryOnChildrenErrors(), DisjointNeighborTest::testDisjointNeighborConflictError(), BoundaryInfoTest::testInternalBoundary(), PeriodicBCTest::testPeriodicBC(), DisjointNeighborTest::testStitchCrossMesh(), transfer_boundary_ids_from_children(), libMesh::NetGenMeshInterface::triangulate(), libMesh::Poly2TriTriangulator::triangulate_current_points(), and libMesh::Parallel::Packing< Elem * >::unpack().

◆ add_side() [2/3]

void libMesh::BoundaryInfo::add_side ( const Elem elem,
const unsigned short int  side,
const boundary_id_type  id 
)

Add side side of element elem with boundary id id to the boundary information data structure.

Definition at line 1260 of file boundary_info.C.

1263{
1264 libmesh_assert(elem);
1265
1266 // Only add BCs for sides that exist.
1267 libmesh_assert_less (side, elem->n_sides());
1268
1269 libmesh_error_msg_if(id == invalid_id, "ERROR: You may not set a boundary ID of "
1270 << invalid_id
1271 << "\n That is reserved for internal use.");
1272
1273 // Don't add the same ID twice
1274 for (const auto & pr : as_range(_boundary_side_id.equal_range(elem)))
1275 if (pr.second.first == side &&
1276 pr.second.second == id)
1277 return;
1278
1279#ifdef LIBMESH_ENABLE_AMR
1280 // Users try to mark boundary on child elements
1281 // If this happens, we will allow users to remove
1282 // side from child elements as well
1283 if (elem->level())
1284 {
1285 _children_on_boundary = true;
1286
1287 // Here we have to stop and check if we already have this boundary defined on the
1288 // parent (if yes, no need to add)
1289 std::vector<boundary_id_type> bd_ids;
1290 this->boundary_ids(elem,side,bd_ids);
1291
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.");
1296 }
1297#endif
1298
1299 _boundary_side_id.emplace(elem, std::make_pair(side, id));
1300 _boundary_ids.insert(id);
1301 _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs
1302}
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.
std::set< boundary_id_type > _side_boundary_ids
Set of user-specified boundary IDs for sides only.

References _boundary_ids, _boundary_side_id, _children_on_boundary, _side_boundary_ids, libMesh::as_range(), boundary_ids(), invalid_id, libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::n_sides().

◆ add_side() [3/3]

void libMesh::BoundaryInfo::add_side ( const Elem elem,
const unsigned short int  side,
const std::vector< boundary_id_type > &  ids 
)

Add side side of element elem with boundary ids ids to the boundary information data structure.

Definition at line 1306 of file boundary_info.C.

1309{
1310 if (ids.empty())
1311 return;
1312
1313 libmesh_assert(elem);
1314
1315 // Only add BCs for sides that exist.
1316 libmesh_assert_less (side, elem->n_sides());
1317
1318#ifdef LIBMESH_ENABLE_AMR
1319 // Users try to mark boundary on child elements
1320 // If this happens, we will allow users to remove
1321 // side from child elements as well
1322 if (elem->level())
1323 {
1324 _children_on_boundary = true;
1325
1326 // Here we have to stop and check if we already have this boundary defined on the
1327 // parent (if yes, no need to add)
1328 std::vector<boundary_id_type> bd_ids;
1329 this->boundary_ids(elem,side,bd_ids);
1330
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.");
1336 }
1337#endif
1338
1339 // Don't add the same ID twice
1340 auto bounds = _boundary_side_id.equal_range(elem);
1341
1342 // The entries in the ids vector may be non-unique. If we expected
1343 // *lots* of ids, it might be fastest to construct a std::set from
1344 // the entries, but for a small number of entries, which is more
1345 // typical, it is probably faster to copy the vector and do sort+unique.
1346 // http://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector
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());
1351
1352 for (auto & id : as_range(unique_ids.begin(), new_end))
1353 {
1354 libmesh_error_msg_if(id == invalid_id,
1355 "ERROR: You may not set a boundary ID of "
1356 << invalid_id
1357 << "\n That is reserved for internal use.");
1358
1359 bool already_inserted = false;
1360 for (const auto & pr : as_range(bounds))
1361 if (pr.second.first == side && pr.second.second == id)
1362 {
1363 already_inserted = true;
1364 break;
1365 }
1366 if (already_inserted)
1367 continue;
1368
1369 _boundary_side_id.emplace(elem, std::make_pair(side, id));
1370 _boundary_ids.insert(id);
1371 _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs
1372 }
1373}

References _boundary_ids, _boundary_side_id, _children_on_boundary, _side_boundary_ids, libMesh::as_range(), boundary_ids(), invalid_id, libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::n_sides().

◆ allow_children_on_boundary_side()

void libMesh::BoundaryInfo::allow_children_on_boundary_side ( const bool  children_on_boundary)
inline

Whether or not to allow directly setting boundary sides on child elements.

Definition at line 951 of file boundary_info.h.

952 { _children_on_boundary = children_on_boundary; }

References _children_on_boundary.

Referenced by BoundaryInfoTest::testBoundaryOnChildrenBoundaryIDs().

◆ boundary_ids() [1/2]

void libMesh::BoundaryInfo::boundary_ids ( const Elem *const  elem,
const unsigned short int  side,
std::vector< boundary_id_type > &  vec_to_fill 
) const
Returns
The list of boundary ids associated with the side side of element elem.

Definition at line 1678 of file boundary_info.C.

1681{
1682 libmesh_assert(elem);
1683
1684 // Only query BCs for sides that exist.
1685 libmesh_assert_less (side, elem->n_sides());
1686
1687 // Clear out any previous contents
1688 vec_to_fill.clear();
1689
1690 // In most cases only level-0 elements store BCs.
1691 // In certain applications (such as time-dependent domains), however, children
1692 // need to store BCs too. This case is covered with the _children_on_boundary
1693 // flag.
1694 const Elem * searched_elem = elem;
1695
1696#ifdef LIBMESH_ENABLE_AMR
1697
1698 if (elem->level() != 0)
1699 {
1700 // If we have children on the boundaries, we need to search for boundary IDs on the
1701 // child and its ancestors too if they share the side.
1703 {
1704 // Loop over ancestors to check if they have boundary ids on the same side
1705 while (searched_elem)
1706 {
1707 for (const auto & pr : as_range(_boundary_side_id.equal_range(searched_elem)))
1708 // Here we need to check if the boundary id already exists
1709 if (pr.second.first == side &&
1710 std::find(vec_to_fill.begin(), vec_to_fill.end(), pr.second.second) ==
1711 vec_to_fill.end())
1712 vec_to_fill.push_back(pr.second.second);
1713
1714
1715 const Elem * parent = searched_elem->parent();
1716 // If the parent doesn't exist or if the child is not on the correct side of the
1717 // parent we are done checking the ancestors
1718 if (!parent || parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false)
1719 return;
1720
1721 searched_elem = parent;
1722 }
1723
1724 return;
1725 }
1726
1727 // If we don't have children on boundaries and we are on an external boundary,
1728 // we just look for the top parent
1729 if (elem->neighbor_ptr(side) == nullptr)
1730 searched_elem = elem->top_parent();
1731 // Otherwise we loop over the ancestors and check if they have a different BC for us
1732 else
1733 while (searched_elem->parent() != nullptr)
1734 {
1735 const Elem * parent = searched_elem->parent();
1736 if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false)
1737 return;
1738
1739 searched_elem = parent;
1740 }
1741 }
1742
1743#endif
1744
1745 // Check each element in the range to see if its side matches the requested side.
1746 for (const auto & pr : as_range(_boundary_side_id.equal_range(searched_elem)))
1747 if (pr.second.first == side)
1748 vec_to_fill.push_back(pr.second.second);
1749}

References _boundary_side_id, _children_on_boundary, libMesh::as_range(), libMesh::Elem::is_child_on_side(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::parent(), libMesh::Elem::top_parent(), and libMesh::Elem::which_child_am_i().

◆ boundary_ids() [2/2]

void libMesh::BoundaryInfo::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.

Definition at line 1389 of file boundary_info.C.

1391{
1392 // Clear out any previous contents
1393 vec_to_fill.clear();
1394
1395 for (const auto & pr : as_range(_boundary_node_id.equal_range(node)))
1396 vec_to_fill.push_back(pr.second);
1397}

References _boundary_node_id, and libMesh::as_range().

Referenced by _find_id_maps(), add_elements(), add_side(), add_side(), libMesh::MeshTools::Subdivision::all_subdivision(), libMesh::MeshTools::Modification::all_tri(), assemble_elasticity(), AssemblyA0::boundary_assembly(), AssemblyA1::boundary_assembly(), AssemblyA2::boundary_assembly(), libMesh::MeshTools::Generation::build_cube(), libMesh::MeshTools::Generation::build_extrusion(), build_node_list_from_side_list(), libMesh::FEGenericBase< OutputType >::compute_periodic_constraints(), libMesh::UnstructuredMesh::create_submesh(), libMesh::MeshTools::Modification::flatten(), has_boundary_id(), libMesh::Poly2TriTriangulator::insert_refinement_points(), libMesh::Poly2TriTriangulator::is_refine_boundary_allowed(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), main(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), n_boundary_ids(), libMesh::VariationalSmootherConstraint::nodes_share_boundary_id(), libMesh::BoundaryProjectSolution::operator()(), libMesh::GhostPointNeighbors::operator()(), operator==(), libMesh::SimplexRefiner::refine_via_edges(), remove_side(), libMesh::FEMContext::side_boundary_ids(), libMesh::RBEIMEvaluation::side_distribute_bfs(), libMesh::UnstructuredMesh::stitching_helper(), libMesh::Elem::swap2boundarysides(), sync(), ElemTest< elem_type >::test_flip(), ElemTest< elem_type >::test_orient(), ElemTest< elem_type >::test_orient_elements(), BoundaryInfoTest::testBoundaryIDs(), BoundaryInfoTest::testBoundaryOnChildrenBoundaryIDs(), SystemsTest::testBoundaryProjectCube(), MeshInputTest::testExodusIGASidesets(), libMesh::XdrIO::write_serialized_bcs_helper(), and libMesh::XdrIO::write_serialized_nodesets().

◆ build_active_side_list()

std::vector< BoundaryInfo::BCTuple > libMesh::BoundaryInfo::build_active_side_list ( ) const

Create a list of (element_id, side_id, boundary_id) tuples for all relevant active sides.

On a ReplicatedMesh this will include all sides; on a DistributedMesh only sides of semilocal elements will be included.

Definition at line 3077 of file boundary_info.C.

3078{
3079 std::vector<BCTuple> bc_triples;
3080 bc_triples.reserve(_boundary_side_id.size());
3081
3082 for (const auto & [elem, id_pair] : _boundary_side_id)
3083 {
3084 // Don't add remote sides
3085 if (elem->is_remote())
3086 continue;
3087
3088 // Loop over the sides of possible children
3089 std::vector<const Elem *> family;
3090#ifdef LIBMESH_ENABLE_AMR
3091 elem->active_family_tree_by_side(family, id_pair.first);
3092#else
3093 family.push_back(elem);
3094#endif
3095
3096 // Populate the list items
3097 for (const auto & f : family)
3098 bc_triples.emplace_back(f->id(), id_pair.first, id_pair.second);
3099 }
3100
3101 // This list is currently in memory address (arbitrary) order, so
3102 // sort to make it consistent on all procs.
3103 std::sort(bc_triples.begin(), bc_triples.end());
3104
3105 return bc_triples;
3106}

References _boundary_side_id.

◆ build_edge_list()

std::vector< BoundaryInfo::BCTuple > libMesh::BoundaryInfo::build_edge_list ( ) const

Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.

On a ReplicatedMesh this will include all edges; on a DistributedMesh only edges of semilocal elements will be included.

Definition at line 3110 of file boundary_info.C.

3111{
3112 std::vector<BCTuple> bc_triples;
3113 bc_triples.reserve(_boundary_edge_id.size());
3114
3115 for (const auto & [elem, id_pair] : _boundary_edge_id)
3116 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3117
3118 // This list is currently in memory address (arbitrary) order, so
3119 // sort to make it consistent on all procs.
3120 std::sort(bc_triples.begin(), bc_triples.end());
3121
3122 return bc_triples;
3123}

References _boundary_edge_id.

Referenced by libMesh::UnstructuredMesh::stitching_helper(), MeshInputTest::testLowOrderEdgeBlocks(), WriteEdgesetData::testWriteImpl(), and libMesh::ExodusII_IO_Helper::write_elements().

◆ build_node_boundary_ids()

void libMesh::BoundaryInfo::build_node_boundary_ids ( std::vector< boundary_id_type > &  b_ids) const

Builds the list of unique node boundary ids.

On a ReplicatedMesh this will be all ids; on a DistributedMesh only ids on semilocal nodes will be included.

Definition at line 2553 of file boundary_info.C.

2554{
2555 b_ids.clear();
2556
2557 for (const auto & pr : _boundary_node_id)
2558 {
2559 boundary_id_type id = pr.second;
2560
2561 if (std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
2562 b_ids.push_back(id);
2563 }
2564}

References _boundary_node_id.

Referenced by libMesh::ExodusII_IO_Helper::initialize(), and libMesh::ExodusII_IO_Helper::write_nodesets().

◆ build_node_list()

std::vector< BoundaryInfo::NodeBCTuple > libMesh::BoundaryInfo::build_node_list ( NodeBCTupleSortBy  sort_by = NodeBCTupleSortBy::NODE_ID) const

Definition at line 2734 of file boundary_info.C.

2735{
2736 std::vector<NodeBCTuple> bc_tuples;
2737 bc_tuples.reserve(_boundary_node_id.size());
2738
2739 for (const auto & [node, bid] : _boundary_node_id)
2740 bc_tuples.emplace_back(node->id(), bid);
2741
2742 // This list is currently in memory address (arbitrary) order, so
2743 // sort, using the specified ordering, to make it consistent on all procs.
2744 if (sort_by == NodeBCTupleSortBy::NODE_ID)
2745 std::sort(bc_tuples.begin(), bc_tuples.end());
2746 else if (sort_by == NodeBCTupleSortBy::BOUNDARY_ID)
2747 std::sort(bc_tuples.begin(), bc_tuples.end(),
2748 [](const NodeBCTuple & left, const NodeBCTuple & right)
2749 {return std::get<1>(left) < std::get<1>(right);});
2750
2751 return bc_tuples;
2752}
std::tuple< dof_id_type, boundary_id_type > NodeBCTuple
Create a list of (node_id, boundary_id) tuples for all relevant nodes.

References _boundary_node_id, BOUNDARY_ID, and NODE_ID.

Referenced by libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::UnstructuredMesh::stitching_helper(), BoundaryInfoTest::testBuildNodeListFromSideList(), WriteNodesetData::testWriteImpl(), libMesh::CheckpointIO::write(), and libMesh::ExodusII_IO_Helper::write_nodesets().

◆ build_node_list_from_side_list()

void libMesh::BoundaryInfo::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.

Parameters
sideset_listsidesets to build nodesets from. If empty (default), builds from all existing sidesets

Definition at line 2756 of file boundary_info.C.

2757{
2758 // If we're on a distributed mesh, even the owner of a node is not
2759 // guaranteed to be able to properly assign its new boundary id(s)!
2760 // Nodal neighbors are not always ghosted, and a nodal neighbor
2761 // might have a boundary side.
2762 const bool mesh_is_serial = _mesh->is_serial();
2763
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;
2766
2767 const processor_id_type my_proc_id = this->processor_id();
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;
2770
2771 // For avoiding extraneous element side construction
2772 ElemSideBuilder side_builder;
2773 // Pull objects out of the loop to reduce heap operations
2774 const Elem * side;
2775
2776 // Loop over the side list
2777 for (const auto & [elem, id_pair] : _boundary_side_id)
2778 {
2779 // Don't add remote sides
2780 if (elem->is_remote())
2781 continue;
2782
2783 auto [sidenum, bcid] = id_pair;
2784
2785 if (!sideset_list.empty() && !sideset_list.count(bcid))
2786 continue;
2787
2788 // Need to loop over the sides of any possible children
2789 std::vector<const Elem *> family;
2790#ifdef LIBMESH_ENABLE_AMR
2791 elem->active_family_tree_by_side (family, sidenum);
2792#else
2793 family.push_back(elem);
2794#endif
2795
2796 for (const auto & cur_elem : family)
2797 {
2798 side = &side_builder(*cur_elem, sidenum);
2799
2800 // Add each node node on the side with the side's boundary id
2801 for (auto i : side->node_index_range())
2802 {
2803 this->add_node(side->node_ptr(i), bcid);
2804 if (!mesh_is_serial)
2805 {
2806 const processor_id_type proc_id =
2807 side->node_ptr(i)->processor_id();
2808 if (proc_id != my_proc_id)
2809 nodes_to_push[proc_id].emplace(side->node_id(i), bcid);
2810 }
2811 }
2812 }
2813 }
2814
2815 // If we're on a serial mesh then we're done.
2816 if (mesh_is_serial)
2817 return;
2818
2819 // Otherwise we need to push ghost node bcids to their owners, then
2820 // pull ghost node bcids from their owners.
2821
2822 for (auto & [proc_id, s] : nodes_to_push)
2823 {
2824 node_vecs_to_push[proc_id].assign(s.begin(), s.end());
2825 s.clear();
2826 }
2827
2828 auto nodes_action_functor =
2829 [this]
2831 const vec_type & received_nodes)
2832 {
2833 for (const auto & [dof_id, bndry_id] : received_nodes)
2834 this->add_node(_mesh->node_ptr(dof_id), bndry_id);
2835 };
2836
2838 (this->comm(), node_vecs_to_push, nodes_action_functor);
2839
2840 // At this point we should know all the BCs for our own nodes; now
2841 // we need BCs for ghost nodes.
2842 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2843 node_ids_requested;
2844
2845 // Determine what nodes we need to request
2846 for (const auto & node : _mesh->node_ptr_range())
2847 {
2848 const processor_id_type pid = node->processor_id();
2849 if (pid != my_proc_id)
2850 node_ids_requested[pid].push_back(node->id());
2851 }
2852
2853 typedef std::vector<boundary_id_type> datum_type;
2854
2855 auto node_bcid_gather_functor =
2856 [this]
2858 const std::vector<dof_id_type> & ids,
2859 std::vector<datum_type> & data)
2860 {
2861 const std::size_t query_size = ids.size();
2862 data.resize(query_size);
2863
2864 for (std::size_t i=0; i != query_size; ++i)
2865 this->boundary_ids(_mesh->node_ptr(ids[i]), data[i]);
2866 };
2867
2868 auto node_bcid_action_functor =
2869 [this]
2871 const std::vector<dof_id_type> & ids,
2872 const std::vector<datum_type> & data)
2873 {
2874 for (auto i : index_range(ids))
2875 this->add_node(_mesh->node_ptr(ids[i]), data[i]);
2876 };
2877
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);
2882}
virtual const Node * node_ptr(const dof_id_type i) const =0
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)
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
uint8_t processor_id_type
Definition id_types.h:104

References _boundary_side_id, _mesh, libMesh::Elem::active_family_tree_by_side(), add_node(), boundary_ids(), libMesh::ParallelObject::comm(), libMesh::index_range(), libMesh::MeshBase::is_serial(), libMesh::Elem::node_id(), libMesh::Elem::node_index_range(), libMesh::MeshBase::node_ptr(), libMesh::Elem::node_ptr(), libMesh::DofObject::processor_id(), libMesh::ParallelObject::processor_id(), TIMPI::pull_parallel_vector_data(), and TIMPI::push_parallel_vector_data().

Referenced by BoundaryInfoTest::testBuildNodeListFromSideList(), and WriteNodesetData::testWriteImpl().

◆ build_shellface_boundary_ids()

void libMesh::BoundaryInfo::build_shellface_boundary_ids ( std::vector< boundary_id_type > &  b_ids) const

Builds the list of unique shellface boundary ids.

On a ReplicatedMesh this will be all ids; on a DistributedMesh only ids on shellfaces of semilocal elements will be included.

Definition at line 2581 of file boundary_info.C.

2582{
2583 b_ids.clear();
2584
2585 for (const auto & pr :_boundary_shellface_id)
2586 {
2587 boundary_id_type id = pr.second.second;
2588
2589 if (std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
2590 b_ids.push_back(id);
2591 }
2592}

References _boundary_shellface_id.

Referenced by libMesh::ExodusII_IO_Helper::initialize(), and libMesh::ExodusII_IO_Helper::write_sidesets().

◆ build_shellface_list()

std::vector< BoundaryInfo::BCTuple > libMesh::BoundaryInfo::build_shellface_list ( ) const

Create a list of (element_id, shellface_id, boundary_id) tuples for all relevant shellfaces.

On a ReplicatedMesh this will include all shellfaces; on a DistributedMesh only shellfaces of semilocal elements will be included.

Definition at line 3127 of file boundary_info.C.

3128{
3129 std::vector<BCTuple> bc_triples;
3130 bc_triples.reserve(_boundary_shellface_id.size());
3131
3132 for (const auto & [elem, id_pair] : _boundary_shellface_id)
3133 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3134
3135 // This list is currently in memory address (arbitrary) order, so
3136 // sort to make it consistent on all procs.
3137 std::sort(bc_triples.begin(), bc_triples.end());
3138
3139 return bc_triples;
3140}

References _boundary_shellface_id.

Referenced by libMesh::UnstructuredMesh::stitching_helper(), and libMesh::ExodusII_IO_Helper::write_sidesets().

◆ build_side_boundary_ids()

void libMesh::BoundaryInfo::build_side_boundary_ids ( std::vector< boundary_id_type > &  b_ids) const

Builds the list of unique side boundary ids.

On a ReplicatedMesh this will be all ids; on a DistributedMesh only ids on sides of semilocal elements will be included.

Definition at line 2567 of file boundary_info.C.

2568{
2569 b_ids.clear();
2570
2571 for (const auto & pr : _boundary_side_id)
2572 {
2573 boundary_id_type id = pr.second.second;
2574
2575 if (std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
2576 b_ids.push_back(id);
2577 }
2578}

References _boundary_side_id.

Referenced by libMesh::ExodusII_IO_Helper::initialize(), and libMesh::ExodusII_IO_Helper::write_sidesets().

◆ build_side_list()

std::vector< BoundaryInfo::BCTuple > libMesh::BoundaryInfo::build_side_list ( BCTupleSortBy  sort_by = BCTupleSortBy::ELEM_ID) const

Definition at line 3048 of file boundary_info.C.

3049{
3050 std::vector<BCTuple> bc_triples;
3051 bc_triples.reserve(_boundary_side_id.size());
3052
3053 for (const auto & [elem, id_pair] : _boundary_side_id)
3054 bc_triples.emplace_back(elem->id(), id_pair.first, id_pair.second);
3055
3056 // bc_triples is currently in whatever order the Elem pointers in
3057 // the _boundary_side_id multimap are in, and in particular might be
3058 // in different orders on different processors. To avoid this
3059 // inconsistency, we'll sort using the default operator< for tuples.
3060 if (sort_by == BCTupleSortBy::ELEM_ID)
3061 std::sort(bc_triples.begin(), bc_triples.end());
3062 else if (sort_by == BCTupleSortBy::SIDE_ID)
3063 std::sort(bc_triples.begin(), bc_triples.end(),
3064 [](const BCTuple & left, const BCTuple & right)
3065 {return std::get<1>(left) < std::get<1>(right);});
3066 else if (sort_by == BCTupleSortBy::BOUNDARY_ID)
3067 std::sort(bc_triples.begin(), bc_triples.end(),
3068 [](const BCTuple & left, const BCTuple & right)
3069 {return std::get<2>(left) < std::get<2>(right);});
3070
3071 return bc_triples;
3072}
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.

References _boundary_side_id, BOUNDARY_ID, ELEM_ID, and SIDE_ID.

Referenced by libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::UnstructuredMesh::stitching_helper(), BoundaryInfoTest::testBuildSideListFromNodeList(), BoundaryInfoTest::testMesh(), MeshTriangulationTest::testPoly2TriHolesInteriorRefinedBase(), BoundaryInfoTest::testRenumber(), WriteEdgesetData::testWriteImpl(), WriteSidesetData::testWriteImpl(), libMesh::FroIO::write(), libMesh::CheckpointIO::write(), libMesh::GmshIO::write_mesh(), and libMesh::ExodusII_IO_Helper::write_sidesets().

◆ build_side_list_from_node_list()

void libMesh::BoundaryInfo::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.

Parameters
nodeset_listnodesets to build sidesets from. If empty (default), builds from all existing sidesets

Definition at line 2997 of file boundary_info.C.

2998{
2999 // Check for early return
3000 if (_boundary_node_id.empty())
3001 {
3002 libMesh::out << "No boundary node IDs have been added: cannot build side list!" << std::endl;
3003 return;
3004 }
3005
3006 // For avoiding extraneous element side construction
3007 ElemSideBuilder side_builder;
3008 // Pull objects out of the loop to reduce heap operations
3009 const Elem * side_elem;
3010
3011 for (const auto & elem : _mesh->active_element_ptr_range())
3012 for (auto side : elem->side_index_range())
3013 {
3014 side_elem = &side_builder(*elem, side);
3015
3016 // map from nodeset_id to count for that ID
3017 std::map<boundary_id_type, unsigned> nodesets_node_count;
3018
3019 // For each nodeset that this node is a member of, increment the associated
3020 // nodeset ID count
3021 for (const auto & node : side_elem->node_ref_range())
3022 for (const auto & pr : as_range(_boundary_node_id.equal_range(&node)))
3023 if (nodeset_list.empty() || nodeset_list.count(pr.second))
3024 nodesets_node_count[pr.second]++;
3025
3026 // Now check to see what nodeset_counts have the correct
3027 // number of nodes in them. For any that do, add this side to
3028 // the sideset, making sure the sideset inherits the
3029 // nodeset's name, if there is one.
3030 for (const auto & pr : nodesets_node_count)
3031 if (pr.second == side_elem->n_nodes())
3032 {
3033 add_side(elem, side, pr.first);
3034
3035 // Let the sideset inherit any non-empty name from the nodeset
3036 std::string & nset_name = nodeset_name(pr.first);
3037
3038 if (nset_name != "")
3039 sideset_name(pr.first) = nset_name;
3040 }
3041 } // end for side
3042}
std::string & sideset_name(boundary_id_type id)
std::string & nodeset_name(boundary_id_type id)
OStreamProxy out

References _boundary_node_id, _mesh, add_side(), libMesh::as_range(), libMesh::Elem::n_nodes(), libMesh::Elem::node_ref_range(), nodeset_name(), libMesh::out, and sideset_name().

Referenced by libMesh::AbaqusIO::read(), and BoundaryInfoTest::testBuildSideListFromNodeList().

◆ clear()

void libMesh::BoundaryInfo::clear ( )

Clears the underlying data structures and restores the object to a pristine state with no data stored.

Definition at line 346 of file boundary_info.C.

347{
348 _boundary_node_id.clear();
349 _boundary_side_id.clear();
350 _boundary_edge_id.clear();
352 _boundary_ids.clear();
353 _side_boundary_ids.clear();
354 _node_boundary_ids.clear();
355 _edge_boundary_ids.clear();
357 _ss_id_to_name.clear();
358 _ns_id_to_name.clear();
359 _es_id_to_name.clear();
360}
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 ...
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 ...
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 ...

References _boundary_edge_id, _boundary_ids, _boundary_node_id, _boundary_shellface_id, _boundary_side_id, _edge_boundary_ids, _es_id_to_name, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, and _ss_id_to_name.

Referenced by operator=(), ExodusC0PolyhedronTest::test_write_cube_header(), and libMesh::Poly2TriTriangulator::triangulate_current_points().

◆ clear_boundary_node_ids()

void libMesh::BoundaryInfo::clear_boundary_node_ids ( )

Clears all the boundary information from all of the nodes in the mesh.

Definition at line 1061 of file boundary_info.C.

1062{
1063 _boundary_node_id.clear();
1064}

References _boundary_node_id.

◆ clear_stitched_boundary_side_ids()

void libMesh::BoundaryInfo::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.

Parameters
sideset_idA sideset on one side of the stitched mesh interface
other_sideset_idThe sideset on the other side of the stitched mesh interface
clear_nodeset_dataWhether to clear boundary information for the nodes along the stitched mesh interface

Definition at line 3534 of file boundary_info.C.

3537{
3538 auto end_it = _boundary_side_id.end();
3539 auto it = _boundary_side_id.begin();
3540
3541 // This predicate checks to see whether the pred_pr triplet's boundary ID matches sideset_id
3542 // (other_sideset_id) *and* whether there is a boundary information triplet on the other side of
3543 // the face whose boundary ID matches the other_sideset_id (sideset_id). We return a pair where
3544 // first is a boolean indicating our condition is true or false, and second is an iterator to the
3545 // neighboring triplet if our condition is true
3546 auto predicate =
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>> &
3550 pred_container) {
3551 const Elem & elem = *pred_pr.first;
3552 const auto elem_side = pred_pr.second.first;
3553 const Elem * const other_elem = elem.neighbor_ptr(elem_side);
3554 if (!other_elem)
3555 return std::make_pair(false, pred_container.end());
3556
3557 const auto elem_side_bnd_id = pred_pr.second.second;
3558 auto other_elem_side_bnd_id = BoundaryInfo::invalid_id;
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;
3563 else
3564 return std::make_pair(false, pred_container.end());
3565
3566 const auto other_elem_side = other_elem->which_neighbor_am_i(&elem);
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);
3570 libmesh_assert_msg(
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);
3574 libmesh_assert_msg(
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);
3578 };
3579
3580 for (; it != end_it;)
3581 {
3582 auto pred_result = predicate(*it, _boundary_side_id);
3583 if (pred_result.first)
3584 {
3585 // First erase associated nodeset information. Do it from both
3586 // sides, so we get any higher-order nodes if we're looking at
3587 // them from a lower-order side, and so we only remove the two
3588 // boundary ids used for stitching.
3589 if (clear_nodeset_data)
3590 {
3591 const Elem & elem = *it->first;
3592 const Elem & neigh = *pred_result.second->first;
3593 const auto elem_side = it->second.first;
3594 const boundary_id_type neigh_side = pred_result.second->second.first;
3595 const auto elem_bcid = it->second.second;
3596 const boundary_id_type neigh_bcid = pred_result.second->second.second;
3597
3598 for (const auto local_node_num : elem.nodes_on_side(elem_side))
3599 this->remove_node(elem.node_ptr(local_node_num), elem_bcid);
3600
3601 for (const auto local_node_num : neigh.nodes_on_side(neigh_side))
3602 this->remove_node(neigh.node_ptr(local_node_num), neigh_bcid);
3603 }
3604
3605 // Now erase the sideset information for our element and its
3606 // neighbor, together. This is safe since a multimap doesn't
3607 // invalidate iterators.
3608 _boundary_side_id.erase(pred_result.second);
3609 it = _boundary_side_id.erase(it);
3610 }
3611 else
3612 ++it;
3613 }
3614
3615 // Removing stitched-away boundary ids might have removed an id
3616 // *entirely*, so we need to recompute boundary id sets to check
3617 // for that.
3618 this->regenerate_id_sets();
3620}
void remove_node(const Node *node, const boundary_id_type id)
Removes boundary id id from node node, if it exists.
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
void libmesh_assert_valid_multimaps() const
Helper method for ensuring that our multimaps don't contain entries with duplicate keys and values.

References _boundary_side_id, invalid_id, libmesh_assert_valid_multimaps(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::node_ptr(), libMesh::Elem::nodes_on_side(), regenerate_id_sets(), remove_node(), and libMesh::Elem::which_neighbor_am_i().

Referenced by libMesh::UnstructuredMesh::stitching_helper().

◆ comm()

const Parallel::Communicator & libMesh::ParallelObject::comm ( ) const
inlineinherited
Returns
A reference to the Parallel::Communicator object used by this mesh.

Definition at line 97 of file parallel_object.h.

98 { return _communicator; }
const Parallel::Communicator & _communicator

References libMesh::ParallelObject::_communicator.

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::Partitioner::_find_global_index_by_pid_map(), _find_id_maps(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult_add(), libMesh::DofMap::add_constraints_to_send_list(), add_cube_convex_hull_to_mesh(), libMesh::PetscDMWrapper::add_dofs_helper(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::TransientRBConstruction::add_IC_to_RB_space(), libMesh::RBEIMEvaluation::add_interpolation_data(), libMesh::CondensedEigenSystem::add_matrices(), libMesh::EigenSystem::add_matrices(), libMesh::System::add_matrix(), libMesh::System::add_matrix(), libMesh::System::add_matrix(), libMesh::RBConstruction::add_scaled_matrix_and_vector(), libMesh::System::add_vector(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::RBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::assemble_affine_expansion(), libMesh::AdvectionSystem::assemble_claw_rhs(), libMesh::FEMSystem::assemble_qoi(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::MeshCommunication::assign_global_indices(), libMesh::Partitioner::assign_partitioning(), libMesh::MeshTools::Generation::build_extrusion(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::PetscDMWrapper::build_section(), libMesh::PetscDMWrapper::build_sf(), libMesh::MeshBase::cache_elem_data(), libMesh::DofMap::check_dirichlet_bcid_consistency(), libMesh::MeshTetInterface::check_hull_integrity(), libMesh::MeshBase::complete_preparation(), libMesh::RBConstruction::compute_Fq_representor_innerprods(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::RBConstruction::compute_output_dual_innerprods(), libMesh::RBConstruction::compute_residual_dual_norm_slow(), libMesh::RBSCMConstruction::compute_SCM_bounds_on_training_set(), libMesh::DofMap::computed_sparsity_already(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), PetscSolverConfiguration::configure_solver(), libMesh::ContinuationSystem::ContinuationSystem(), libMesh::MeshBase::copy_constraint_rows(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::CondensedEigenSystem::copy_super_to_sub(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshTools::create_bounding_box(), libMesh::DofMap::create_dof_constraints(), libMesh::MeshTools::create_nodal_bounding_box(), libMesh::MeshRefinement::create_parent_error_vector(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::MeshTools::create_subdomain_bounding_box(), libMesh::PetscMatrix< T >::create_submatrix_nosort(), create_wrapped_function(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::MeshBase::detect_interior_parents(), libMesh::RBEIMEvaluation::distribute_bfs(), DMlibMeshFunction(), DMlibMeshJacobian(), DMlibMeshSetSystem_libMesh(), DMVariableBounds_libMesh(), libMesh::DTKSolutionTransfer::DTKSolutionTransfer(), libMesh::MeshRefinement::eliminate_unrefined_patches(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_interiors(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_nodes(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_sides(), libMesh::TransientRBConstruction::enrich_RB_space(), libMesh::EpetraVector< T >::EpetraVector(), AssembleOptimization::equality_constraints(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::SmoothnessEstimator::estimate_smoothness(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::MeshRefinement::flag_elements_by_error_tolerance(), libMesh::MeshRefinement::flag_elements_by_mean_stddev(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::DofMap::gather_constraints(), libMesh::MeshfreeInterpolation::gather_remote_data(), libMesh::CondensedEigenSystem::get_eigenpair(), libMesh::RBEIMEvaluation::get_eim_basis_function_node_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_side_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_value(), libMesh::MeshBase::get_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::RBEIMConstruction::get_max_abs_value(), libMesh::RBEIMConstruction::get_node_max_abs_value(), libMesh::RBEIMEvaluation::get_parametrized_function_node_value(), libMesh::RBEIMEvaluation::get_parametrized_function_side_value(), libMesh::RBEIMEvaluation::get_parametrized_function_value(), libMesh::RBEIMConstruction::get_random_point(), libMesh::RBEIMConstruction::get_random_point(), libMesh::RBEIMConstruction::get_random_point(), libMesh::MeshTetInterface::improve_hull_integrity(), AssembleOptimization::inequality_constraints(), AssembleOptimization::inequality_constraints_jacobian(), libMesh::StaticCondensation::init(), libMesh::TimeSolver::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::LocationMap< T >::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), ElasticitySystem::init_data(), libMesh::AdvectionSystem::init_data(), libMesh::ClawSystem::init_data(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), libMesh::RBEIMConstruction::initialize_parametrized_functions_in_training_set(), libMesh::RBEIMConstruction::inner_product(), integrate_function(), libMesh::MeshTools::Modification::interpolate_surface(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_equal_connectivity(), libMesh::MeshTools::libmesh_assert_equal_points(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_constraint_rows(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_flags(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_p_levels(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshTools::libmesh_assert_valid_unique_ids(), libMesh::libmesh_petsc_linesearch_shellfunc(), libMesh::libmesh_petsc_preconditioner_apply(), libMesh::libmesh_petsc_snes_mffd_interface(), libMesh::libmesh_petsc_snes_postcheck(), libMesh::MeshRefinement::limit_level_mismatch_at_edge(), libMesh::MeshRefinement::limit_level_mismatch_at_node(), libMesh::MeshRefinement::limit_overrefined_boundary(), libMesh::MeshRefinement::limit_underrefined_boundary(), libMesh::LinearImplicitSystem::LinearImplicitSystem(), main(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), libMesh::MeshCommunication::make_node_bcids_parallel_consistent(), libMesh::MeshCommunication::make_node_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), libMesh::TransientRBConstruction::mass_matrix_scaled_matvec(), libMesh::FEMSystem::mesh_position_set(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), LinearElasticityWithContact::move_mesh(), libMesh::DistributedMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::DofMap::n_constrained_dofs(), libMesh::MeshBase::n_constraint_rows(), libMesh::DofMap::n_dofs(), libMesh::DofMap::n_dofs_per_processor(), n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), MixedOrderTest::n_neighbor_links(), n_nodeset_conds(), libMesh::SparsityPattern::Build::n_nonzeros(), libMesh::MeshTools::n_p_levels(), n_shellface_conds(), libMesh::RBEIMEvaluation::node_distribute_bfs(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::RBEIMConstruction::node_inner_product(), libMesh::PetscVector< T >::operator=(), libMesh::MeshBase::operator==(), libMesh::DistributedMesh::parallel_max_elem_id(), libMesh::DistributedMesh::parallel_max_node_id(), libMesh::DistributedMesh::parallel_max_unique_id(), libMesh::ReplicatedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_n_elem(), libMesh::DistributedMesh::parallel_n_nodes(), libMesh::SparsityPattern::Build::parallel_sync(), parallel_sync_node_ids(), parallel_sync_side_ids(), libMesh::MeshTools::paranoid_n_levels(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::petsc_auto_fieldsplit(), LaplaceSystem::postprocess(), PoissonSystem::postprocess(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::DofMap::process_mesh_constraint_rows(), libMesh::Partitioner::processor_pairs_to_interface_nodes(), libMesh::InterMeshProjection::project_system_vectors(), libMesh::XdrIO::read(), libMesh::Nemesis_IO::read(), FEMParameters::read(), libMesh::EquationSystems::read(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::RBEIMEvaluation::read_in_interior_basis_functions(), libMesh::RBEIMEvaluation::read_in_node_basis_functions(), libMesh::RBEIMEvaluation::read_in_side_basis_functions(), libMesh::RBEvaluation::read_in_vectors_from_multiple_files(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), MeshFunctionTest::read_variable_info_from_output_data(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), remove_edge_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), LinearElasticityWithContact::residual_and_jacobian(), OverlappingAlgebraicGhostingTest::run_ghosting_test(), OverlappingCouplingGhostingTest::run_sparsity_pattern_test(), scale_mesh_and_plot(), libMesh::DofMap::scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::send_and_insert_dof_values(), libMesh::TransientRBConstruction::set_error_temporal_data(), libMesh::Partitioner::set_interface_node_processor_ids_BFS(), libMesh::Partitioner::set_interface_node_processor_ids_linear(), libMesh::Partitioner::set_interface_node_processor_ids_petscpartitioner(), libMesh::Partitioner::set_node_processor_ids(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::RBEIMEvaluation::side_distribute_bfs(), libMesh::RBEIMEvaluation::side_gather_bfs(), libMesh::RBEIMConstruction::side_inner_product(), libMesh::Partitioner::single_partition(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::VariationalMeshSmoother::smooth(), libMesh::NoxNonlinearSolver< Number >::solve(), libMesh::ClawSystem::solve_conservation_law(), libMesh::split_mesh(), libMesh::RBEIMConstruction::store_eim_solutions_for_training_set(), libMesh::MeshBase::subdomain_ids(), sync(), libMesh::MeshBase::sync_subdomain_name_map(), ConstraintOperatorTest::test1DCoarseningNewNodes(), ConstraintOperatorTest::test1DCoarseningOperator(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), MeshfunctionDFEM::test_mesh_function_dfem(), MeshfunctionDFEM::test_mesh_function_dfem_grad(), MeshFunctionTest::test_p_level(), ExodusC0PolyhedronTest::test_write_and_read_hexagonal_prism(), ExodusC0PolygonTest::test_write_and_read_pentagon(), DofMapTest::testBadElemFECombo(), SystemsTest::testBlockRestrictedVarNDofs(), BoundaryInfoTest::testBoundaryOnChildrenErrors(), CheckpointIOTest::testC0PolygonCheckpoint(), VolumeTest::testC0PolygonMethods(), CheckpointIOTest::testC0PolyhedronCheckpoint(), VolumeTest::testC0PolyhedronMethods(), ConstraintOperatorTest::testCoreform(), ConnectedComponentsTest::testEdge(), MeshInputTest::testExodusIGASidesets(), MeshTriangulationTest::testFoundCenters(), PointLocatorTest::testLocator(), BoundaryInfoTest::testMesh(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), PointLocatorTest::testPlanar(), MeshTriangulationTest::testPoly2TriEdge3ToTri7CenterFixup(), MeshTriangulationTest::testPoly2TriRefinementBase(), SystemsTest::testProjectCubeWithMeshFunction(), SystemsTest::testProjectScalarCoarsening(), BoundaryInfoTest::testRenumber(), BoundaryInfoTest::testSelectiveRenumber(), BoundaryMeshSubdomainTest::testSingleSubdomain(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshTriangulationTest::testTriangulatorInterp(), MeshTriangulationTest::testTriangulatorMeshedHoles(), MeshTriangulationTest::testTriangulatorRoundHole(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::RBConstruction::train_reduced_basis_with_POD(), libMesh::MeshfreeSolutionTransfer::transfer(), libMesh::MeshFunctionSolutionTransfer::transfer(), libMesh::Poly2TriTriangulator::triangulate(), libMesh::RBConstruction::truth_assembly(), libMesh::TransientRBConstruction::truth_assembly(), update_current_local_solution(), libMesh::TransientRBConstruction::update_RB_initial_condition_all_N(), libMesh::RBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_residual_terms(), libMesh::RBConstruction::update_residual_terms(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::XdrIO::write(), libMesh::NameBasedIO::write(), libMesh::VTKIO::write_nodal_data(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), libMesh::RBEvaluation::write_out_vectors(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::TransientRBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::RBDataSerialization::RBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::TransientRBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::RBEIMEvaluationSerialization::write_to_file(), and libMesh::RBDataSerialization::RBSCMEvaluationSerialization::write_to_file().

◆ copy_boundary_ids()

void libMesh::BoundaryInfo::copy_boundary_ids ( const BoundaryInfo old_boundary_info,
const Elem *const  old_elem,
const Elem *const  new_elem 
)

Definition at line 1797 of file boundary_info.C.

1800{
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());
1803
1804 std::vector<boundary_id_type> bndry_ids;
1805
1806 for (auto s : old_elem->side_index_range())
1807 {
1808 old_boundary_info.raw_boundary_ids (old_elem, s, bndry_ids);
1809 this->add_side (new_elem, s, bndry_ids);
1810 }
1811
1812 for (auto e : old_elem->edge_index_range())
1813 {
1814 old_boundary_info.raw_edge_boundary_ids (old_elem, e, bndry_ids);
1815 this->add_edge (new_elem, e, bndry_ids);
1816 }
1817
1818 for (unsigned short sf=0; sf != 2; sf++)
1819 {
1820 old_boundary_info.raw_shellface_boundary_ids (old_elem, sf, bndry_ids);
1821 this->add_shellface (new_elem, sf, bndry_ids);
1822 }
1823}

References add_edge(), add_shellface(), add_side(), libMesh::Elem::edge_index_range(), libMesh::Elem::n_edges(), libMesh::Elem::n_sides(), raw_boundary_ids(), raw_edge_boundary_ids(), raw_shellface_boundary_ids(), and libMesh::Elem::side_index_range().

Referenced by libMesh::UnstructuredMesh::all_first_order().

◆ edge_boundary_ids()

void libMesh::BoundaryInfo::edge_boundary_ids ( const Elem *const  elem,
const unsigned short int  edge,
std::vector< boundary_id_type > &  vec_to_fill 
) const
Returns
The list of boundary ids associated with the edge edge of element elem.
Note
Edge-based boundary IDs should only be used in 3D.

Definition at line 1409 of file boundary_info.C.

1412{
1413 libmesh_assert(elem);
1414
1415 // Clear out any previous contents
1416 vec_to_fill.clear();
1417
1418 // Only query BCs for edges that exist.
1419 libmesh_assert_less (edge, elem->n_edges());
1420
1421 // Only level-0 elements store BCs. If this is not a level-0
1422 // element get its level-0 parent and infer the BCs.
1423 const Elem * searched_elem = elem;
1424#ifdef LIBMESH_ENABLE_AMR
1425 if (elem->level() != 0)
1426 {
1427 // Find all the sides that contain edge. If one of those is a boundary
1428 // side, then this must be a boundary edge. In that case, we just use the
1429 // top-level parent.
1430 bool found_boundary_edge = false;
1431 for (auto side : elem->side_index_range())
1432 {
1433 if (elem->is_edge_on_side(edge,side))
1434 {
1435 if (elem->neighbor_ptr(side) == nullptr)
1436 {
1437 searched_elem = elem->top_parent ();
1438 found_boundary_edge = true;
1439 break;
1440 }
1441 }
1442 }
1443
1444 if (!found_boundary_edge)
1445 {
1446 // Child element is not on external edge, but it may have internal
1447 // "boundary" IDs. We will walk up the tree, at each level checking that
1448 // the current child is actually on the same edge of the parent that is
1449 // currently being searched for (i.e. that was passed in as "edge").
1450 while (searched_elem->parent() != nullptr)
1451 {
1452 const Elem * parent = searched_elem->parent();
1453 if (parent->is_child_on_edge(parent->which_child_am_i(searched_elem), edge) == false)
1454 return;
1455 searched_elem = parent;
1456 }
1457 }
1458 }
1459#endif
1460
1461 // Check each element in the range to see if its edge matches the requested edge.
1462 for (const auto & pr : as_range(_boundary_edge_id.equal_range(searched_elem)))
1463 if (pr.second.first == edge)
1464 vec_to_fill.push_back(pr.second.second);
1465}

References _boundary_edge_id, libMesh::as_range(), libMesh::Elem::is_child_on_edge(), libMesh::Elem::is_edge_on_side(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::n_edges(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::parent(), libMesh::Elem::side_index_range(), libMesh::Elem::top_parent(), and libMesh::Elem::which_child_am_i().

Referenced by libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), n_edge_boundary_ids(), libMesh::BoundaryProjectSolution::operator()(), operator==(), libMesh::UnstructuredMesh::stitching_helper(), libMesh::Elem::swap2boundaryedges(), and libMesh::XdrIO::write_serialized_bcs_helper().

◆ edgeset_name()

std::string & libMesh::BoundaryInfo::edgeset_name ( boundary_id_type  id)
Returns
A writable reference to an optional edgeset name.

Definition at line 3328 of file boundary_info.C.

3329{
3330 return _es_id_to_name[id];
3331}

References _es_id_to_name.

Referenced by libMesh::ExodusII_IO_Helper::read_edge_blocks(), BoundaryInfoTest::testSelectiveRenumber(), and WriteEdgesetData::testWriteImpl().

◆ get_boundary_ids()

const std::set< boundary_id_type > & libMesh::BoundaryInfo::get_boundary_ids ( ) const
inline
Returns
A set of the boundary ids which exist on semilocal parts of the mesh.

Code that wishes to access boundary ids on all parts of the mesh, including non-local parts, should call get_global_boundary_ids

Definition at line 804 of file boundary_info.h.

805 { return _boundary_ids; }

References _boundary_ids.

Referenced by libMesh::DofMap::check_dirichlet_bcid_consistency(), ElasticitySystem::init_data(), libMesh::UnstructuredMesh::stitching_helper(), MeshInputTest::testExodusIGASidesets(), BoundaryInfoTest::testMesh(), BoundaryInfoTest::testRenumber(), BoundaryInfoTest::testSelectiveRenumber(), and libMesh::FroIO::write().

◆ get_edge_boundary_ids()

const std::set< boundary_id_type > & libMesh::BoundaryInfo::get_edge_boundary_ids ( ) const
inline
Returns
A reference to the set of all boundary IDs specified on edges of semilocal mesh elements.
Note
Edge-based boundary IDs should only be used in 3D.

Definition at line 826 of file boundary_info.h.

827 { return _edge_boundary_ids; }

References _edge_boundary_ids.

Referenced by libMesh::DofMap::check_dirichlet_bcid_consistency(), libMesh::MeshBase::get_info(), libMesh::ExodusII_IO_Helper::initialize(), BoundaryInfoTest::testSelectiveRenumber(), and WriteEdgesetData::testWriteImpl().

◆ get_edgeset_map()

const std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > & libMesh::BoundaryInfo::get_edgeset_map ( ) const
inline
Returns
A const reference to the edgeset map.

Definition at line 933 of file boundary_info.h.

934 { return _boundary_edge_id; }

References _boundary_edge_id.

Referenced by libMesh::MeshBase::get_info().

◆ get_edgeset_name()

const std::string & libMesh::BoundaryInfo::get_edgeset_name ( boundary_id_type  id) const
Returns
A const reference to an optional edgeset name.

Definition at line 3317 of file boundary_info.C.

3318{
3319 static const std::string empty_string;
3320 if (const auto it = _es_id_to_name.find(id);
3321 it == _es_id_to_name.end())
3322 return empty_string;
3323 else
3324 return it->second;
3325}

References _es_id_to_name.

Referenced by libMesh::ExodusII_IO_Helper::write_elements().

◆ get_edgeset_name_map()

const std::map< boundary_id_type, std::string > & libMesh::BoundaryInfo::get_edgeset_name_map ( ) const
inline

◆ get_global_boundary_ids()

const std::set< boundary_id_type > & libMesh::BoundaryInfo::get_global_boundary_ids ( ) const
Returns
A set of the boundary ids which exist globally on the mesh. Relies on the mesh being prepared

Definition at line 3623 of file boundary_info.C.

3624{
3626 return _global_boundary_ids;
3627}
std::set< boundary_id_type > _global_boundary_ids
A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.
Preparation _preparation
Flags indicating in what ways this mesh has been prepared.
Definition mesh_base.h:2195

References _global_boundary_ids, _mesh, libMesh::MeshBase::_preparation, libMesh::MeshBase::Preparation::has_boundary_id_sets, and libMesh::libmesh_assert().

Referenced by MeshStitchTest::renameAndShift().

◆ get_id_by_name()

boundary_id_type libMesh::BoundaryInfo::get_id_by_name ( std::string_view  name) const
Returns
The id of the named boundary if it exists, invalid_id otherwise.

Definition at line 3333 of file boundary_info.C.

3334{
3335 // Search sidesets
3336 for (const auto & [ss_id, ss_name] : _ss_id_to_name)
3337 if (ss_name == name)
3338 return ss_id;
3339
3340 // Search nodesets
3341 for (const auto & [ns_id, ns_name] : _ns_id_to_name)
3342 if (ns_name == name)
3343 return ns_id;
3344
3345 // Search edgesets
3346 for (const auto & [es_id, es_name] : _es_id_to_name)
3347 if (es_name == name)
3348 return es_id;
3349
3350 // If we made it here without returning, we don't have a sideset,
3351 // nodeset, or edgeset by the requested name, so return invalid_id
3352 return invalid_id;
3353}
std::string name(const ElemQuality q)
This function returns a string containing some name for q.

References _es_id_to_name, _ns_id_to_name, _ss_id_to_name, and invalid_id.

Referenced by libMesh::HDGProblem::init(), and BoundaryMeshSubdomainTest::testPerBoundarySubdomain().

◆ get_node_boundary_ids()

const std::set< boundary_id_type > & libMesh::BoundaryInfo::get_node_boundary_ids ( ) const
inline

◆ get_nodeset_map()

const std::multimap< const Node *, boundary_id_type > & libMesh::BoundaryInfo::get_nodeset_map ( ) const
inline
Returns
A const reference to the nodeset map.

Definition at line 927 of file boundary_info.h.

928 { return _boundary_node_id; }

References _boundary_node_id.

Referenced by libMesh::MeshBase::get_info().

◆ get_nodeset_name()

const std::string & libMesh::BoundaryInfo::get_nodeset_name ( boundary_id_type  id) const
Returns
A reference for getting an optional name for a nodeset.

Definition at line 3302 of file boundary_info.C.

3303{
3304 static const std::string empty_string;
3305 if (const auto it = _ns_id_to_name.find(id);
3306 it == _ns_id_to_name.end())
3307 return empty_string;
3308 else
3309 return it->second;
3310}

References _ns_id_to_name.

Referenced by BoundaryInfoTest::testNameCopying(), and libMesh::ExodusII_IO_Helper::write_nodesets().

◆ get_nodeset_name_map()

const std::map< boundary_id_type, std::string > & libMesh::BoundaryInfo::get_nodeset_name_map ( ) const
inline

◆ get_shellface_boundary_ids()

const std::set< boundary_id_type > & libMesh::BoundaryInfo::get_shellface_boundary_ids ( ) const
inline
Returns
A reference to the set of all boundary IDs specified on shell faces.
Note
This is only relevant on shell elements.

Definition at line 835 of file boundary_info.h.

836 { return _shellface_boundary_ids; }

References _shellface_boundary_ids.

◆ get_side_and_node_maps()

void libMesh::BoundaryInfo::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.

Then each element in boundary_mesh will have interior_parent defined. This method gets extra data for us:

  • node_id_map stores a map from the node ids on the interior mesh to the corresponding node ids of boundary_mesh.
  • side_id_map stores a map from the element ids of the boundary mesh to the side index of the interior_parent that the boundary element corresponds to. tolerance is used to identify when we have matching elements.

Definition at line 604 of file boundary_info.C.

608{
609 LOG_SCOPE("get_side_and_node_maps()", "BoundaryInfo");
610
611 node_id_map.clear();
612 side_id_map.clear();
613
614 // For building element sides without extraneous allocation
615 ElemSideBuilder side_builder;
616 // Pull objects out of the loop to reduce heap operations
617 const Elem * interior_parent_side;
618
619 for (const auto & boundary_elem : boundary_mesh.active_element_ptr_range())
620 {
621 const Elem * interior_parent = boundary_elem->interior_parent();
622
623 // Find out which side of interior_parent boundary_elem corresponds to.
624 // Use distance between average vertex location as a way to check.
625 unsigned char interior_parent_side_index = 0;
626 bool found_matching_sides = false;
627 for (auto side : interior_parent->side_index_range())
628 {
629 interior_parent_side = &side_builder(*interior_parent, side);
630 Real va_distance = (boundary_elem->vertex_average() - interior_parent_side->vertex_average()).norm();
631
632 if (va_distance < (tolerance * boundary_elem->hmin()))
633 {
634 interior_parent_side_index = cast_int<unsigned char>(side);
635 found_matching_sides = true;
636 break;
637 }
638 }
639
640 libmesh_error_msg_if(!found_matching_sides, "No matching side found within the specified tolerance");
641
642 side_id_map[boundary_elem->id()] = interior_parent_side_index;
643
644 for (auto local_node_index : boundary_elem->node_index_range())
645 {
646 dof_id_type boundary_node_id = boundary_elem->node_id(local_node_index);
647 dof_id_type interior_node_id = interior_parent_side->node_id(local_node_index);
648
649 node_id_map[interior_node_id] = boundary_node_id;
650 }
651 }
652}
auto norm(const T &a)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

References libMesh::Elem::interior_parent(), libMesh::Elem::node_id(), libMesh::Real, libMesh::Elem::side_index_range(), and libMesh::Elem::vertex_average().

◆ get_side_boundary_ids()

const std::set< boundary_id_type > & libMesh::BoundaryInfo::get_side_boundary_ids ( ) const
inline

◆ get_sideset_map()

const std::multimap< const Elem *, std::pair< unsigned short int, boundary_id_type > > & libMesh::BoundaryInfo::get_sideset_map ( ) const
inline
Returns
A const reference to the sideset map.

Definition at line 939 of file boundary_info.h.

940 { return _boundary_side_id; }

References _boundary_side_id.

Referenced by libMesh::MeshBase::get_info().

◆ get_sideset_name()

const std::string & libMesh::BoundaryInfo::get_sideset_name ( boundary_id_type  id) const
Returns
A reference for getting an optional name for a sideset.

Definition at line 3286 of file boundary_info.C.

3287{
3288 static const std::string empty_string;
3289 if (const auto it = _ss_id_to_name.find(id);
3290 it == _ss_id_to_name.end())
3291 return empty_string;
3292 else
3293 return it->second;
3294}

References _ss_id_to_name.

Referenced by libMesh::UnstructuredMesh::stitching_helper(), BoundaryInfoTest::testNameCopying(), and libMesh::ExodusII_IO_Helper::write_sidesets().

◆ get_sideset_name_map()

const std::map< boundary_id_type, std::string > & libMesh::BoundaryInfo::get_sideset_name_map ( ) const
inline

◆ has_boundary_id() [1/2]

bool libMesh::BoundaryInfo::has_boundary_id ( const Elem *const  elem,
const unsigned short int  side,
const boundary_id_type  id 
) const
Returns
true if side side of Elem elem is associated with id.

Definition at line 1571 of file boundary_info.C.

1574{
1575 std::vector<boundary_id_type> ids;
1576 this->boundary_ids(elem, side, ids);
1577 return (std::find(ids.begin(), ids.end(), id) != ids.end());
1578}

References boundary_ids().

◆ has_boundary_id() [2/2]

bool libMesh::BoundaryInfo::has_boundary_id ( const Node *const  node,
const boundary_id_type  id 
) const

◆ is_children_on_boundary_side()

bool libMesh::BoundaryInfo::is_children_on_boundary_side ( ) const
inline
Returns
Whether or not there may be child elements directly assigned boundary sides

Definition at line 945 of file boundary_info.h.

946 { return _children_on_boundary; }

References _children_on_boundary.

Referenced by libMesh::PetscDiffSolver::solve(), and BoundaryInfoTest::testBoundaryOnChildrenElementsRefineCoarsen().

◆ libmesh_assert_valid_multimaps()

void libMesh::BoundaryInfo::libmesh_assert_valid_multimaps ( ) const
private

Helper method for ensuring that our multimaps don't contain entries with duplicate keys and values.

Probably should have picked a different data structure there, and also not given users an accessor with raw access to it...

Definition at line 3630 of file boundary_info.C.

3631{
3632#ifndef NDEBUG
3633 auto verify_multimap = [](const auto & themap) {
3634 for (const auto & [key, val] : themap)
3635 {
3636 auto range = themap.equal_range(key);
3637
3638 int count = 0;
3639 for (auto it = range.first; it != range.second; ++it)
3640 if (it->second == val)
3641 ++count;
3642
3643 libmesh_assert(count == 1);
3644 }
3645 };
3646
3647 verify_multimap(this->_boundary_node_id);
3648 verify_multimap(this->_boundary_edge_id);
3649 verify_multimap(this->_boundary_shellface_id);
3650 verify_multimap(this->_boundary_side_id);
3651#else
3652 return;
3653#endif
3654}

References _boundary_edge_id, _boundary_node_id, _boundary_shellface_id, _boundary_side_id, and libMesh::libmesh_assert().

Referenced by clear_stitched_boundary_side_ids(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), and renumber_side_id().

◆ n_boundary_conds()

std::size_t libMesh::BoundaryInfo::n_boundary_conds ( ) const
Returns
The number of element-side-based boundary conditions.

This will be the correct global count even on a distributed mesh.

Definition at line 2645 of file boundary_info.C.

2646{
2647 // in serial we know the number of bcs from the
2648 // size of the container
2649 if (_mesh->is_serial())
2650 return _boundary_side_id.size();
2651
2652 // in parallel we need to sum the number of local bcs
2653 parallel_object_only();
2654
2655 std::size_t nbcs=0;
2656
2657 for (const auto & pr : _boundary_side_id)
2658 if (pr.first->processor_id() == this->processor_id())
2659 nbcs++;
2660
2661 this->comm().sum (nbcs);
2662
2663 return nbcs;
2664}

References _boundary_side_id, _mesh, libMesh::ParallelObject::comm(), libMesh::MeshBase::is_serial(), libMesh::ParallelObject::processor_id(), and libMesh::Parallel::Communicator::sum().

Referenced by libMesh::MeshTools::Modification::all_tri(), libMesh::MeshTools::Modification::flatten(), libMesh::Nemesis_IO::read(), libMesh::AbaqusIO::read(), AllTriTest::test_helper(), AllTriTest::test_helper_c0polyhedron(), AllTriTest::testAllTriC0Polygon(), AllTriTest::testAllTriC0PolygonOctagon(), libMesh::XdrIO::write(), and libMesh::GmshIO::write_mesh().

◆ n_boundary_ids() [1/3]

std::size_t libMesh::BoundaryInfo::n_boundary_ids ( ) const
inline
Returns
The number of user-specified boundary ids on the semilocal part of the mesh.
Note
DistributedMesh users may need to compare boundary_ids sets via inter-processor communication.

Definition at line 485 of file boundary_info.h.

485{ return _boundary_ids.size(); }

References _boundary_ids.

Referenced by libMesh::MeshTools::Subdivision::all_subdivision(), AllTriTest::test_helper(), MeshTetTest::testBcids(), BoundaryInfoTest::testBuildSideListFromNodeList(), MeshInputTest::testExodusIGASidesets(), MeshInputTest::testLowOrderEdgeBlocks(), BoundaryInfoTest::testMesh(), BoundaryInfoTest::testRenumber(), BoundaryInfoTest::testSelectiveRenumber(), and libMesh::FroIO::write().

◆ n_boundary_ids() [2/3]

unsigned int libMesh::BoundaryInfo::n_boundary_ids ( const Elem *const  elem,
const unsigned short int  side 
) const
Returns
The number of boundary ids associated with the side side of element elem.

Definition at line 1754 of file boundary_info.C.

1756{
1757 std::vector<boundary_id_type> ids;
1758 this->boundary_ids(elem, side, ids);
1759 return cast_int<unsigned int>(ids.size());
1760}

References boundary_ids().

◆ n_boundary_ids() [3/3]

unsigned int libMesh::BoundaryInfo::n_boundary_ids ( const Node node) const
Returns
The number of boundary ids associated with Node node.

Definition at line 1401 of file boundary_info.C.

1402{
1403 auto pos = _boundary_node_id.equal_range(node);
1404 return cast_int<unsigned int>(std::distance(pos.first, pos.second));
1405}

References _boundary_node_id.

◆ n_edge_boundary_ids()

unsigned int libMesh::BoundaryInfo::n_edge_boundary_ids ( const Elem *const  elem,
const unsigned short int  edge 
) const
Returns
The number of boundary ids associated with the edge edge of element elem.
Note
Edge-based boundary IDs should only be used in 3D.

Definition at line 1469 of file boundary_info.C.

1471{
1472 std::vector<boundary_id_type> ids;
1473 this->edge_boundary_ids(elem, edge, ids);
1474 return cast_int<unsigned int>(ids.size());
1475}
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const

References edge_boundary_ids().

◆ n_edge_conds()

std::size_t libMesh::BoundaryInfo::n_edge_conds ( ) const
Returns
The number of edge-based boundary conditions. Edge-based boundary IDs should only be used in 3D.

This will be the correct global count even on a distributed mesh.

Definition at line 2666 of file boundary_info.C.

2667{
2668 // in serial we know the number of nodesets from the
2669 // size of the container
2670 if (_mesh->is_serial())
2671 return _boundary_edge_id.size();
2672
2673 // in parallel we need to sum the number of local nodesets
2674 parallel_object_only();
2675
2676 std::size_t n_edge_bcs=0;
2677
2678 for (const auto & pr : _boundary_edge_id)
2679 if (pr.first->processor_id() == this->processor_id())
2680 n_edge_bcs++;
2681
2682 this->comm().sum (n_edge_bcs);
2683
2684 return n_edge_bcs;
2685}

References _boundary_edge_id, _mesh, libMesh::ParallelObject::comm(), libMesh::MeshBase::is_serial(), libMesh::ParallelObject::processor_id(), and libMesh::Parallel::Communicator::sum().

Referenced by libMesh::ExodusII_IO_Helper::initialize(), libMesh::Nemesis_IO::prepare_to_write_nodal_data(), BoundaryInfoTest::testEdgeBoundaryConditions(), WriteEdgesetData::testWriteImpl(), libMesh::XdrIO::write(), libMesh::Nemesis_IO::write(), and libMesh::ExodusII_IO::write().

◆ n_nodeset_conds()

std::size_t libMesh::BoundaryInfo::n_nodeset_conds ( ) const
Returns
The number of node-based boundary conditions.

This will be the correct global count even on a distributed mesh.

Definition at line 2710 of file boundary_info.C.

2711{
2712 // in serial we know the number of nodesets from the
2713 // size of the container
2714 if (_mesh->is_serial())
2715 return _boundary_node_id.size();
2716
2717 // in parallel we need to sum the number of local nodesets
2718 parallel_object_only();
2719
2720 std::size_t n_nodesets=0;
2721
2722 for (const auto & pr : _boundary_node_id)
2723 if (pr.first->processor_id() == this->processor_id())
2724 n_nodesets++;
2725
2726 this->comm().sum (n_nodesets);
2727
2728 return n_nodesets;
2729}

References _boundary_node_id, _mesh, libMesh::ParallelObject::comm(), libMesh::MeshBase::is_serial(), libMesh::ParallelObject::processor_id(), and libMesh::Parallel::Communicator::sum().

Referenced by libMesh::XdrIO::write().

◆ n_processors()

processor_id_type libMesh::ParallelObject::n_processors ( ) const
inlineinherited
Returns
The number of processors in the group.

Definition at line 103 of file parallel_object.h.

104 {
105 processor_id_type returnval =
106 cast_int<processor_id_type>(_communicator.size());
107 libmesh_assert(returnval); // We never have an empty comm
108 return returnval;
109 }
processor_id_type size() const

References libMesh::ParallelObject::_communicator, libMesh::libmesh_assert(), and libMesh::Parallel::Communicator::size().

Referenced by libMesh::Partitioner::_find_global_index_by_pid_map(), _find_id_maps(), libMesh::DofMap::add_constraints_to_send_list(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::DistributedMesh::add_node(), libMesh::System::add_vector(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::Partitioner::build_graph(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::copy_nodes_and_elements(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::UnstructuredMesh::create_pid_mesh(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::DistributedMesh::DistributedMesh(), libMesh::EnsightIO::EnsightIO(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::MeshBase::get_info(), libMesh::StaticCondensation::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::DistributedMesh::insert_elem(), libMesh::NumericVector< T >::is_effectively_ghosted(), libMesh::NumericVector< T >::is_effectively_serial(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshBase::n_active_elem_on_proc(), libMesh::DofMap::n_dofs_per_processor(), libMesh::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::MeshBase::partition(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::CheckpointIO::read_connectivity(), libMesh::XdrIO::read_header(), libMesh::CheckpointIO::read_nodes(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::System::read_serialized_vector(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::Partitioner::repartition(), OverlappingFunctorTest::run_partitioner_test(), libMesh::DofMap::scatter_constraints(), libMesh::DistributedMesh::set_next_unique_id(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), WriteVecAndScalar::setupTests(), libMesh::RBEIMEvaluation::side_gather_bfs(), DistributedMeshTest::testRemoteElemError(), CheckpointIOTest::testSplitter(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

◆ n_raw_boundary_ids()

unsigned int libMesh::BoundaryInfo::n_raw_boundary_ids ( const Elem *const  elem,
const unsigned short int  side 
) const
Returns
The number of raw (excludes ancestors) boundary ids associated with the side side of element elem.

Definition at line 1763 of file boundary_info.C.

1765{
1766 std::vector<boundary_id_type> ids;
1767 this->raw_boundary_ids(elem, side, ids);
1768 return cast_int<unsigned int>(ids.size());
1769}
void raw_boundary_ids(const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const

References raw_boundary_ids().

◆ n_shellface_boundary_ids()

unsigned int libMesh::BoundaryInfo::n_shellface_boundary_ids ( const Elem *const  elem,
const unsigned short int  shellface 
) const
Returns
The number of boundary ids associated with the specified shell face of element elem.
Note
This is only relevant for shell elements.

Definition at line 1537 of file boundary_info.C.

1539{
1540 std::vector<boundary_id_type> ids;
1541 this->shellface_boundary_ids(elem, shellface, ids);
1542 return cast_int<unsigned int>(ids.size());
1543}
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const

References shellface_boundary_ids().

◆ n_shellface_conds()

std::size_t libMesh::BoundaryInfo::n_shellface_conds ( ) const
Returns
The number of shellface-based boundary conditions. This is only relevant on shell elements.

This will be the correct global count even on a distributed mesh.

Definition at line 2688 of file boundary_info.C.

2689{
2690 // in serial we know the number of nodesets from the
2691 // size of the container
2692 if (_mesh->is_serial())
2693 return _boundary_shellface_id.size();
2694
2695 // in parallel we need to sum the number of local nodesets
2696 parallel_object_only();
2697
2698 std::size_t n_shellface_bcs=0;
2699
2700 for (const auto & pr : _boundary_shellface_id)
2701 if (pr.first->processor_id() == this->processor_id())
2702 n_shellface_bcs++;
2703
2704 this->comm().sum (n_shellface_bcs);
2705
2706 return n_shellface_bcs;
2707}

References _boundary_shellface_id, _mesh, libMesh::ParallelObject::comm(), libMesh::MeshBase::is_serial(), libMesh::ParallelObject::processor_id(), and libMesh::Parallel::Communicator::sum().

Referenced by BoundaryInfoTest::testShellFaceConstraints(), and libMesh::XdrIO::write().

◆ nodeset_name()

std::string & libMesh::BoundaryInfo::nodeset_name ( boundary_id_type  id)

◆ operator!=()

bool libMesh::BoundaryInfo::operator!= ( const BoundaryInfo other_boundary_info) const
inline

Definition at line 88 of file boundary_info.h.

89 {
90 return !(*this == other_boundary_info);
91 }

◆ operator=()

BoundaryInfo & libMesh::BoundaryInfo::operator= ( const BoundaryInfo other_boundary_info)

Copy assignment operator.

Note
this will still reference the same MeshBase it was constructed with. Boundary data copied from other_boundary_info will refer to objects in this mesh which have the same DofObject::id() as the corresponding objects in the other mesh.

We're going to attempt to pull new pointers out of the mesh assigned to this boundary info.

This will only work if the mesh assigned to this BoundaryInfo is the same mesh object as other_boundary_info or was constructed in exactly the same way (or constructed as a copy, or a refined copy without renumbering, etc.).

Definition at line 111 of file boundary_info.C.

112{
113 // Overwrite any preexisting boundary info
114 this->clear();
115
126 // Copy node boundary info
127 for (const auto & [node, bid] : other_boundary_info._boundary_node_id)
128 _boundary_node_id.emplace(_mesh->node_ptr(node->id()), bid);
129
130 // Copy edge boundary info
131 for (const auto & [elem, id_pair] : other_boundary_info._boundary_edge_id)
132 _boundary_edge_id.emplace(_mesh->elem_ptr(elem->id()), id_pair);
133
134 // Copy shellface boundary info
135 for (const auto & [elem, id_pair] : other_boundary_info._boundary_shellface_id)
136 _boundary_shellface_id.emplace(_mesh->elem_ptr(elem->id()), id_pair);
137
138 // Copy side boundary info
139 for (const auto & [elem, id_pair] : other_boundary_info._boundary_side_id)
140 _boundary_side_id.emplace(_mesh->elem_ptr(elem->id()), id_pair);
141
142 _children_on_boundary = other_boundary_info._children_on_boundary;
143
144 _boundary_ids = other_boundary_info._boundary_ids;
145 _global_boundary_ids = other_boundary_info._global_boundary_ids;
146 _side_boundary_ids = other_boundary_info._side_boundary_ids;
147 _node_boundary_ids = other_boundary_info._node_boundary_ids;
148 _edge_boundary_ids = other_boundary_info._edge_boundary_ids;
149 _shellface_boundary_ids = other_boundary_info._shellface_boundary_ids;
150
151 _ss_id_to_name = other_boundary_info._ss_id_to_name;
152 _ns_id_to_name = other_boundary_info._ns_id_to_name;
153 _es_id_to_name = other_boundary_info._es_id_to_name;
154
155 return *this;
156}
void clear()
Clears the underlying data structures and restores the object to a pristine state with no data stored...

References _boundary_edge_id, _boundary_ids, _boundary_node_id, _boundary_shellface_id, _boundary_side_id, _children_on_boundary, _edge_boundary_ids, _es_id_to_name, _global_boundary_ids, _mesh, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, _ss_id_to_name, clear(), libMesh::MeshBase::elem_ptr(), and libMesh::MeshBase::node_ptr().

◆ operator==()

bool libMesh::BoundaryInfo::operator== ( const BoundaryInfo other_boundary_info) const

This tests for data equality via element ids.

Definition at line 159 of file boundary_info.C.

160{
161 for (const auto & [other_node, bid] : other_boundary_info._boundary_node_id)
162 {
163 const Node * node = this->_mesh->query_node_ptr(other_node->id());
164 if (!node)
165 return false;
166 if (!this->has_boundary_id(node, bid))
167 return false;
168 }
169 for (const auto & [node, bid] : this->_boundary_node_id)
170 {
171 const Node * other_node =
172 other_boundary_info._mesh->query_node_ptr(node->id());
173 if (!other_node)
174 return false;
175 if (!other_boundary_info.has_boundary_id(other_node, bid))
176 return false;
177 }
178
179 auto compare_edges = [&](const Elem * elem,
180 const Elem * other_elem,
181 unsigned short int edge)
182 {
183 if (!elem)
184 return false;
185 if (!other_elem)
186 return false;
187
188 std::vector<boundary_id_type> our_edges, other_edges;
189 this->edge_boundary_ids(elem, edge, our_edges);
190 other_boundary_info.edge_boundary_ids(other_elem, edge, other_edges);
191 if (our_edges.size() != other_edges.size())
192 return false;
193
194 std::sort(our_edges.begin(), our_edges.end());
195 std::sort(other_edges.begin(), other_edges.end());
196 for (auto i : index_range(our_edges))
197 if (our_edges[i] != other_edges[i])
198 return false;
199 return true;
200 };
201
202 for (const auto & [other_elem, edge_id_pair] : other_boundary_info._boundary_edge_id)
203 {
204 const Elem * elem = this->_mesh->query_elem_ptr(other_elem->id());
205 if (!compare_edges(elem, other_elem, edge_id_pair.first))
206 return false;
207 }
208
209 for (const auto & [elem, edge_id_pair] : this->_boundary_edge_id)
210 {
211 const Elem * other_elem = other_boundary_info._mesh->query_elem_ptr(elem->id());
212 if (!compare_edges(elem, other_elem, edge_id_pair.first))
213 return false;
214 }
215
216 auto compare_sides = [&](const Elem * elem,
217 const Elem * other_elem,
218 unsigned short int side)
219 {
220 if (!elem)
221 return false;
222 if (!other_elem)
223 return false;
224
225 std::vector<boundary_id_type> our_sides, other_sides;
226 this->boundary_ids(elem, side, our_sides);
227 other_boundary_info.boundary_ids(other_elem, side, other_sides);
228 if (our_sides.size() != other_sides.size())
229 return false;
230
231 std::sort(our_sides.begin(), our_sides.end());
232 std::sort(other_sides.begin(), other_sides.end());
233 for (auto i : index_range(our_sides))
234 if (our_sides[i] != other_sides[i])
235 return false;
236 return true;
237 };
238
239 for (const auto & [other_elem, side_id_pair] : other_boundary_info._boundary_side_id)
240 {
241 const Elem * elem = this->_mesh->query_elem_ptr(other_elem->id());
242 if (!compare_sides(elem, other_elem, side_id_pair.first))
243 return false;
244 }
245
246 for (const auto & [elem, side_id_pair] : this->_boundary_side_id)
247 {
248 const Elem * other_elem = other_boundary_info._mesh->query_elem_ptr(elem->id());
249 if (!compare_sides(elem, other_elem, side_id_pair.first))
250 return false;
251 }
252
253 auto compare_shellfaces = [&](const Elem * elem,
254 const Elem * other_elem,
255 unsigned short int shellface)
256 {
257 if (!elem)
258 return false;
259 if (!other_elem)
260 return false;
261
262 std::vector<boundary_id_type> our_shellfaces, other_shellfaces;
263 this->shellface_boundary_ids(elem, shellface, our_shellfaces);
264 other_boundary_info.shellface_boundary_ids(other_elem, shellface, other_shellfaces);
265 if (our_shellfaces.size() != other_shellfaces.size())
266 return false;
267
268 std::sort(our_shellfaces.begin(), our_shellfaces.end());
269 std::sort(other_shellfaces.begin(), other_shellfaces.end());
270 for (auto i : index_range(our_shellfaces))
271 if (our_shellfaces[i] != other_shellfaces[i])
272 return false;
273 return true;
274 };
275
276 for (const auto & [other_elem, shellface_id_pair] : other_boundary_info._boundary_shellface_id)
277 {
278 const Elem * elem = this->_mesh->query_elem_ptr(other_elem->id());
279 if (!compare_shellfaces(elem, other_elem, shellface_id_pair.first))
280 return false;
281 }
282
283 for (const auto & [elem, shellface_id_pair] : this->_boundary_shellface_id)
284 {
285 const Elem * other_elem = other_boundary_info._mesh->query_elem_ptr(elem->id());
286 if (!compare_shellfaces(elem, other_elem, shellface_id_pair.first))
287 return false;
288 }
289
290 if (_children_on_boundary != other_boundary_info._children_on_boundary)
291 return false;
292
293 auto compare_sets = [](const auto & set1, const auto & set2)
294 {
295 if (set1.size() != set2.size())
296 return false;
297 for (boundary_id_type bid : set1)
298 if (!set2.count(bid))
299 return false;
300
301 return true;
302 };
303
304 if (!compare_sets(_boundary_ids,
305 other_boundary_info._boundary_ids) ||
306 !compare_sets(_global_boundary_ids,
307 other_boundary_info._global_boundary_ids) ||
308 !compare_sets(_edge_boundary_ids,
309 other_boundary_info._edge_boundary_ids) ||
310 !compare_sets(_node_boundary_ids,
311 other_boundary_info._node_boundary_ids) ||
312 !compare_sets(_shellface_boundary_ids,
313 other_boundary_info._shellface_boundary_ids) ||
314 !compare_sets(_side_boundary_ids,
315 other_boundary_info._side_boundary_ids))
316 return false;
317
318 auto compare_maps = [](const auto & map1, const auto & map2)
319 {
320 if (map1.size() != map2.size())
321 return false;
322 for (const auto & pair : map1)
323 if (!map2.count(pair.first) ||
324 map2.at(pair.first) != pair.second)
325 return false;
326
327 return true;
328 };
329
330 if (!compare_maps(_ss_id_to_name,
331 other_boundary_info._ss_id_to_name) ||
332 !compare_maps(_ns_id_to_name,
333 other_boundary_info._ns_id_to_name) ||
334 !compare_maps(_es_id_to_name,
335 other_boundary_info._es_id_to_name))
336 return false;
337
338 return true;
339}
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0

References _boundary_edge_id, _boundary_ids, _boundary_node_id, _boundary_shellface_id, _boundary_side_id, _children_on_boundary, _edge_boundary_ids, _es_id_to_name, _global_boundary_ids, _mesh, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, _ss_id_to_name, boundary_ids(), edge_boundary_ids(), has_boundary_id(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::MeshBase::query_elem_ptr(), libMesh::MeshBase::query_node_ptr(), and shellface_boundary_ids().

◆ parallel_sync_node_ids()

void libMesh::BoundaryInfo::parallel_sync_node_ids ( )

Definition at line 2940 of file boundary_info.C.

2941{
2942 // we need BCs for ghost nodes.
2943 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2944 node_ids_requested;
2945
2946 // Determine what nodes we need to request
2947 for (const auto & node : _mesh->node_ptr_range())
2948 {
2949 const processor_id_type pid = node->processor_id();
2950 if (pid != this->processor_id())
2951 node_ids_requested[pid].push_back(node->id());
2952 }
2953
2954 typedef std::vector<boundary_id_type> datum_type;
2955
2956 // gather the node ID and boundary_id_type for the ghost nodes
2957 auto node_id_gather_functor =
2958 [this]
2960 const std::vector<dof_id_type> & ids,
2961 std::vector<datum_type> & data)
2962 {
2963 data.resize(ids.size());
2964 for (auto i : index_range(ids))
2965 {
2966 Node * node = _mesh->node_ptr(ids[i]);
2967 for (const auto & pr : as_range(_boundary_node_id.equal_range(node)))
2968 data[i].push_back(pr.second);
2969 }
2970 };
2971
2972 // update the _boundary_node_id on this processor
2973 auto node_id_action_functor =
2974 [this]
2976 const std::vector<dof_id_type> & ids,
2977 std::vector<datum_type> & data)
2978 {
2979 for (auto i : index_range(ids))
2980 {
2981 Node * node = _mesh->node_ptr(ids[i]);
2982 //clear boundary node
2983 _boundary_node_id.erase(node);
2984 // update boundary node
2985 for (const auto & pr : data[i])
2986 _boundary_node_id.insert(std::make_pair(node, pr));
2987 }
2988 };
2989
2990
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);
2995}

References _boundary_node_id, _mesh, libMesh::as_range(), libMesh::ParallelObject::comm(), libMesh::index_range(), libMesh::MeshBase::node_ptr(), libMesh::ParallelObject::processor_id(), and TIMPI::pull_parallel_vector_data().

◆ parallel_sync_side_ids()

void libMesh::BoundaryInfo::parallel_sync_side_ids ( )

Synchronize the boundary element side and node across processors.

This function is needed when boundary info is changed by adding or removing sides on the fly. Note: if the side of a ghost element is changed, then you would need to do do parallel push (see e.g., timpi/parallel_sync.h) and then sync.

Definition at line 2884 of file boundary_info.C.

2885{
2886 // we need BCs for ghost elements.
2887 std::unordered_map<processor_id_type, std::vector<dof_id_type>>
2888 elem_ids_requested;
2889
2890 // Determine what elements we need to request
2891 for (const auto & elem : _mesh->element_ptr_range())
2892 {
2893 const processor_id_type pid = elem->processor_id();
2894 if (pid != this->processor_id())
2895 elem_ids_requested[pid].push_back(elem->id());
2896 }
2897
2898 typedef std::vector<std::pair<unsigned short int, boundary_id_type>> datum_type;
2899
2900 // gather the element ID, side, and boundary_id_type for the ghost elements
2901 auto elem_id_gather_functor =
2902 [this]
2904 const std::vector<dof_id_type> & ids,
2905 std::vector<datum_type> & data)
2906 {
2907 data.resize(ids.size());
2908 for (auto i : index_range(ids))
2909 {
2910 Elem * elem = _mesh->elem_ptr(ids[i]);
2911 for (const auto & pr : as_range(_boundary_side_id.equal_range(elem)))
2912 data[i].push_back(std::make_pair(pr.second.first, pr.second.second));
2913 }
2914 };
2915 // update the _boundary_side_id on this processor
2916 auto elem_id_action_functor =
2917 [this]
2919 const std::vector<dof_id_type> & ids,
2920 std::vector<datum_type> & data)
2921 {
2922 for (auto i : index_range(ids))
2923 {
2924 Elem * elem = _mesh->elem_ptr(ids[i]);
2925 //clear boundary sides for this element
2926 _boundary_side_id.erase(elem);
2927 // update boundary sides for it
2928 for (const auto & [side_id, bndry_id] : data[i])
2929 _boundary_side_id.insert(std::make_pair(elem, std::make_pair(side_id, bndry_id)));
2930 }
2931 };
2932
2933
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);
2938}
const boundary_id_type side_id

References _boundary_side_id, _mesh, libMesh::as_range(), libMesh::ParallelObject::comm(), libMesh::MeshBase::elem_ptr(), libMesh::index_range(), libMesh::ParallelObject::processor_id(), TIMPI::pull_parallel_vector_data(), and side_id.

◆ print_info()

void libMesh::BoundaryInfo::print_info ( std::ostream &  out_stream = libMesh::out) const

Prints the boundary information data structure.

Definition at line 3143 of file boundary_info.C.

3144{
3145 // Print out the nodal BCs
3146 if (!_boundary_node_id.empty())
3147 {
3148 out_stream << "Nodal Boundary conditions:" << std::endl
3149 << "--------------------------" << std::endl
3150 << " (Node No., ID) " << std::endl;
3151
3152 for (const auto & [node, bndry_id] : _boundary_node_id)
3153 out_stream << " (" << node->id()
3154 << ", " << bndry_id
3155 << ")" << std::endl;
3156 }
3157
3158 // Print out the element edge BCs
3159 if (!_boundary_edge_id.empty())
3160 {
3161 out_stream << std::endl
3162 << "Edge Boundary conditions:" << std::endl
3163 << "-------------------------" << std::endl
3164 << " (Elem No., Edge No., ID) " << std::endl;
3165
3166 for (const auto & [elem, id_pair] : _boundary_edge_id)
3167 out_stream << " (" << elem->id()
3168 << ", " << id_pair.first
3169 << ", " << id_pair.second
3170 << ")" << std::endl;
3171 }
3172
3173 // Print out the element shellface BCs
3174 if (!_boundary_shellface_id.empty())
3175 {
3176 out_stream << std::endl
3177 << "Shell-face Boundary conditions:" << std::endl
3178 << "-------------------------" << std::endl
3179 << " (Elem No., Shell-face No., ID) " << std::endl;
3180
3181 for (const auto & [elem, id_pair] : _boundary_shellface_id)
3182 out_stream << " (" << elem->id()
3183 << ", " << id_pair.first
3184 << ", " << id_pair.second
3185 << ")" << std::endl;
3186 }
3187
3188 // Print out the element side BCs
3189 if (!_boundary_side_id.empty())
3190 {
3191 out_stream << std::endl
3192 << "Side Boundary conditions:" << std::endl
3193 << "-------------------------" << std::endl
3194 << " (Elem No., Side No., ID) " << std::endl;
3195
3196 for (const auto & [elem, id_pair] : _boundary_side_id)
3197 out_stream << " (" << elem->id()
3198 << ", " << id_pair.first
3199 << ", " << id_pair.second
3200 << ")" << std::endl;
3201 }
3202}

References _boundary_edge_id, _boundary_node_id, _boundary_shellface_id, and _boundary_side_id.

◆ print_summary()

void libMesh::BoundaryInfo::print_summary ( std::ostream &  out_stream = libMesh::out) const

Prints a summary of the boundary information.

Definition at line 3206 of file boundary_info.C.

3207{
3208 // Print out the nodal BCs
3209 if (!_boundary_node_id.empty())
3210 {
3211 out_stream << "Nodal Boundary conditions:" << std::endl
3212 << "--------------------------" << std::endl
3213 << " (ID, number of nodes) " << std::endl;
3214
3215 std::map<boundary_id_type, std::size_t> ID_counts;
3216
3217 for (const auto & pr : _boundary_node_id)
3218 ID_counts[pr.second]++;
3219
3220 for (const auto & [bndry_id, cnt] : ID_counts)
3221 out_stream << " (" << bndry_id
3222 << ", " << cnt
3223 << ")" << std::endl;
3224 }
3225
3226 // Print out the element edge BCs
3227 if (!_boundary_edge_id.empty())
3228 {
3229 out_stream << std::endl
3230 << "Edge Boundary conditions:" << std::endl
3231 << "-------------------------" << std::endl
3232 << " (ID, number of edges) " << std::endl;
3233
3234 std::map<boundary_id_type, std::size_t> ID_counts;
3235
3236 for (const auto & pr : _boundary_edge_id)
3237 ID_counts[pr.second.second]++;
3238
3239 for (const auto & [bndry_id, cnt] : ID_counts)
3240 out_stream << " (" << bndry_id
3241 << ", " << cnt
3242 << ")" << std::endl;
3243 }
3244
3245
3246 // Print out the element edge BCs
3247 if (!_boundary_shellface_id.empty())
3248 {
3249 out_stream << std::endl
3250 << "Shell-face Boundary conditions:" << std::endl
3251 << "-------------------------" << std::endl
3252 << " (ID, number of shellfaces) " << std::endl;
3253
3254 std::map<boundary_id_type, std::size_t> ID_counts;
3255
3256 for (const auto & pr : _boundary_shellface_id)
3257 ID_counts[pr.second.second]++;
3258
3259 for (const auto & [bndry_id, cnt] : ID_counts)
3260 out_stream << " (" << bndry_id
3261 << ", " << cnt
3262 << ")" << std::endl;
3263 }
3264
3265 // Print out the element side BCs
3266 if (!_boundary_side_id.empty())
3267 {
3268 out_stream << std::endl
3269 << "Side Boundary conditions:" << std::endl
3270 << "-------------------------" << std::endl
3271 << " (ID, number of sides) " << std::endl;
3272
3273 std::map<boundary_id_type, std::size_t> ID_counts;
3274
3275 for (const auto & pr : _boundary_side_id)
3276 ID_counts[pr.second.second]++;
3277
3278 for (const auto & [bndry_id, cnt] : ID_counts)
3279 out_stream << " (" << bndry_id
3280 << ", " << cnt
3281 << ")" << std::endl;
3282 }
3283}

References _boundary_edge_id, _boundary_node_id, _boundary_shellface_id, and _boundary_side_id.

Referenced by main().

◆ processor_id()

processor_id_type libMesh::ParallelObject::processor_id ( ) const
inlineinherited
Returns
The rank of this processor in the group.

Definition at line 114 of file parallel_object.h.

115 { return cast_int<processor_id_type>(_communicator.rank()); }
processor_id_type rank() const

References libMesh::ParallelObject::_communicator, and libMesh::Parallel::Communicator::rank().

Referenced by _find_id_maps(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), add_elements(), libMesh::DistributedMesh::add_node(), libMesh::MeshTools::Modification::all_tri(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::MeshFunction::check_found_elem(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::ExodusII_IO_Helper::close(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::compute_communication_map_parameters(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_node_communication_maps(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::ExodusII_IO_Helper::create(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DofMapBase::end_dof(), libMesh::DofMapBase::end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::find_dofs_to_send(), libMesh::UnstructuredMesh::find_neighbors(), libMesh::DofMapBase::first_dof(), libMesh::DofMapBase::first_old_dof(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::MeshBase::get_info(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), libMesh::DofMap::get_local_constraints(), libMesh::MeshBase::get_local_constraints(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::LaplaceMeshSmoother::init(), libMesh::SystemSubsetBySubdomain::init(), HeatSystem::init_data(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize_element_variables(), libMesh::ExodusII_IO_Helper::initialize_global_variables(), libMesh::ExodusII_IO_Helper::initialize_nodal_variables(), libMesh::DistributedMesh::insert_elem(), libMesh::MeshTools::Modification::interpolate_surface(), libMesh::SparsityPattern::Build::join(), libMesh::RBEvaluation::legacy_write_offline_data_to_files(), libMesh::RBSCMEvaluation::legacy_write_offline_data_to_files(), libMesh::TransientRBEvaluation::legacy_write_offline_data_to_files(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), main(), AugmentSparsityOnInterface::mesh_reinit(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), libMesh::MeshBase::n_active_local_elem(), n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::MeshBase::n_constraint_rows(), n_edge_conds(), libMesh::DofMapBase::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), n_nodeset_conds(), n_shellface_conds(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::DistributedMesh::own_node(), parallel_sync_node_ids(), parallel_sync_side_ids(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::DofMap::process_mesh_constraint_rows(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::XdrIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::NameBasedIO::read(), libMesh::EquationSystems::read(), libMesh::EquationSystems::read(), libMesh::ExodusII_IO_Helper::read_elem_num_map(), libMesh::ExodusII_IO_Helper::read_global_values(), libMesh::CheckpointIO::read_header(), libMesh::ExodusII_IO::read_header(), libMesh::System::read_header(), libMesh::XdrIO::read_header(), libMesh::DynaIO::read_mesh(), libMesh::ExodusII_IO_Helper::read_node_num_map(), libMesh::System::read_parallel_data(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::System::read_serialized_data(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::System::read_serialized_vectors(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), libMesh::DofMap::scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::DistributedMesh::set_next_unique_id(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::RBEIMEvaluation::side_gather_bfs(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), ExodusTest< elem_type >::test_read_gold(), ExodusTest< elem_type >::test_write(), ExodusC0PolyhedronTest::test_write_and_read_hexagonal_prism(), ExodusC0PolygonTest::test_write_and_read_pentagon(), MeshInputTest::testAbaqusRead(), MeshInputTest::testBadGmsh(), BoundaryInfoTest::testBoundaryIDs(), MeshInputTest::testCopyElementSolutionImpl(), MeshInputTest::testCopyElementVectorImpl(), MeshInputTest::testCopyNodalSolutionImpl(), DefaultCouplingTest::testCoupling(), PointNeighborCouplingTest::testCoupling(), MeshInputTest::testDynaFileMappings(), MeshInputTest::testDynaNoSplines(), MeshInputTest::testDynaReadElem(), MeshInputTest::testDynaReadPatch(), MeshInputTest::testExodusFileMappings(), MeshInputTest::testExodusIGASidesets(), MeshInputTest::testExodusWriteElementDataFromDiscontinuousNodalData(), MeshInputTest::testGmshBCIDOverlap(), MeshInputTest::testGoodGmsh(), MeshInputTest::testGoodSTL(), MeshInputTest::testGoodSTLBinary(), BoundaryInfoTest::testInternalBoundary(), MeshInputTest::testLowOrderEdgeBlocks(), BoundaryMeshSubdomainTest::testPerBoundarySubdomain(), SystemsTest::testProjectMatrix3D(), BoundaryInfoTest::testShellFaceConstraints(), MeshInputTest::testSingleElementImpl(), BoundaryMeshSubdomainTest::testSingleSubdomain(), WriteVecAndScalar::testSolution(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::NetGenMeshInterface::triangulate(), libMesh::Parallel::Packing< Elem * >::unpack(), libMesh::Parallel::Packing< Node * >::unpack(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::DTKAdapter::update_variable_values(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::XdrIO::write(), libMesh::NameBasedIO::write(), libMesh::CheckpointIO::write(), libMesh::EquationSystems::write(), libMesh::EquationSystems::write(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::ExodusII_IO::write_element_data_from_discontinuous_nodal_data(), libMesh::ExodusII_IO_Helper::write_element_values(), libMesh::ExodusII_IO_Helper::write_element_values_element_major(), libMesh::ExodusII_IO_Helper::write_elements(), libMesh::ExodusII_IO_Helper::write_elemset_data(), libMesh::ExodusII_IO_Helper::write_elemsets(), libMesh::ExodusII_IO::write_global_data(), libMesh::ExodusII_IO_Helper::write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), libMesh::ExodusII_IO_Helper::write_information_records(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::UCDIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_common(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::ExodusII_IO_Helper::write_nodeset_data(), libMesh::ExodusII_IO_Helper::write_nodesets(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), write_output_solvedata(), libMesh::System::write_parallel_data(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bc_names(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::System::write_serialized_data(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::System::write_serialized_vector(), libMesh::System::write_serialized_vectors(), libMesh::ExodusII_IO_Helper::write_sideset_data(), libMesh::ExodusII_IO_Helper::write_sidesets(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), libMesh::ExodusII_IO_Helper::write_timestep(), and libMesh::ExodusII_IO::write_timestep_discontinuous().

◆ raw_boundary_ids()

void libMesh::BoundaryInfo::raw_boundary_ids ( const Elem *const  elem,
const unsigned short int  side,
std::vector< boundary_id_type > &  vec_to_fill 
) const
Returns
The list of raw boundary ids associated with the side side of element elem.

These ids are "raw" because they exclude ids which are implicit, such as a child's inheritance of its ancestors' boundary id.

Definition at line 1773 of file boundary_info.C.

1776{
1777 libmesh_assert(elem);
1778
1779 // Only query BCs for sides that exist.
1780 libmesh_assert_less (side, elem->n_sides());
1781
1782 // Clear out any previous contents
1783 vec_to_fill.clear();
1784
1785 // Only level-0 elements store BCs.
1786 if (elem->parent() && !_children_on_boundary)
1787 return;
1788
1789 // Check each element in the range to see if its side matches the requested side.
1790 for (const auto & pr : as_range(_boundary_side_id.equal_range(elem)))
1791 if (pr.second.first == side)
1792 vec_to_fill.push_back(pr.second.second);
1793}

References _boundary_side_id, _children_on_boundary, libMesh::as_range(), libMesh::libmesh_assert(), libMesh::Elem::n_sides(), and libMesh::Elem::parent().

Referenced by copy_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), n_raw_boundary_ids(), and remove_side().

◆ raw_edge_boundary_ids()

void libMesh::BoundaryInfo::raw_edge_boundary_ids ( const Elem *const  elem,
const unsigned short int  edge,
std::vector< boundary_id_type > &  vec_to_fill 
) const
Returns
The list of raw boundary ids associated with the edge edge of element elem.

These ids are "raw" because they exclude ids which are implicit, such as a child's inheritance of its ancestors' boundary id.

Note
Edge-based boundary IDs should only be used in 3D.

Definition at line 1479 of file boundary_info.C.

1482{
1483 libmesh_assert(elem);
1484
1485 // Only query BCs for edges that exist.
1486 libmesh_assert_less (edge, elem->n_edges());
1487
1488 // Clear out any previous contents
1489 vec_to_fill.clear();
1490
1491 // Only level-0 elements store BCs.
1492 if (elem->parent())
1493 return;
1494
1495 // Check each element in the range to see if its edge matches the requested edge.
1496 for (const auto & pr : as_range(_boundary_edge_id.equal_range(elem)))
1497 if (pr.second.first == edge)
1498 vec_to_fill.push_back(pr.second.second);
1499}

References _boundary_edge_id, libMesh::as_range(), libMesh::libmesh_assert(), libMesh::Elem::n_edges(), and libMesh::Elem::parent().

Referenced by copy_boundary_ids(), and libMesh::MeshTools::libmesh_assert_valid_boundary_ids().

◆ raw_shellface_boundary_ids()

void libMesh::BoundaryInfo::raw_shellface_boundary_ids ( const Elem *const  elem,
const unsigned short int  shellface,
std::vector< boundary_id_type > &  vec_to_fill 
) const
Returns
The list of raw boundary ids associated with the specified shell face of element elem.

These ids are "raw" because they exclude ids which are implicit, such as a child's inheritance of its ancestors' boundary id.

Note
This is only relevant for shell elements.

Definition at line 1547 of file boundary_info.C.

1550{
1551 libmesh_assert(elem);
1552
1553 // Shells only have 2 faces
1554 libmesh_assert_less(shellface, 2);
1555
1556 // Clear out any previous contents
1557 vec_to_fill.clear();
1558
1559 // Only level-0 elements store BCs.
1560 if (elem->parent())
1561 return;
1562
1563 // Check each element in the range to see if its shellface matches the requested shellface.
1564 for (const auto & pr : as_range(_boundary_shellface_id.equal_range(elem)))
1565 if (pr.second.first == shellface)
1566 vec_to_fill.push_back(pr.second.second);
1567}

References _boundary_shellface_id, libMesh::as_range(), libMesh::libmesh_assert(), and libMesh::Elem::parent().

Referenced by copy_boundary_ids(), and libMesh::MeshTools::libmesh_assert_valid_boundary_ids().

◆ regenerate_id_sets()

void libMesh::BoundaryInfo::regenerate_id_sets ( )

Clears and regenerates the cached sets of ids.

This is in general necessary after use of remove_*() functions, which remove individual id associations (an O(1) process) without checking to see whether that is the last association with the id (an O(N) process).

Definition at line 364 of file boundary_info.C.

365{
366 const auto old_ss_id_to_name = _ss_id_to_name;
367 const auto old_ns_id_to_name = _ns_id_to_name;
368 const auto old_es_id_to_name = _es_id_to_name;
369
370 // Clear the old caches
371 _boundary_ids.clear();
372 _side_boundary_ids.clear();
373 _node_boundary_ids.clear();
374 _edge_boundary_ids.clear();
376 _ss_id_to_name.clear();
377 _ns_id_to_name.clear();
378 _es_id_to_name.clear();
379
380 // Loop over id maps to regenerate each set.
381 for (const auto & pr : _boundary_node_id)
382 {
383 const boundary_id_type id = pr.second;
384 _boundary_ids.insert(id);
385 _node_boundary_ids.insert(id);
386 if (const auto it = old_ns_id_to_name.find(id);
387 it != old_ns_id_to_name.end())
388 _ns_id_to_name.emplace(id, it->second);
389 }
390
391 for (const auto & pr : _boundary_edge_id)
392 {
393 const boundary_id_type id = pr.second.second;
394 _boundary_ids.insert(id);
395 _edge_boundary_ids.insert(id);
396 if (const auto it = old_es_id_to_name.find(id);
397 it != old_es_id_to_name.end())
398 _es_id_to_name.emplace(id, it->second);
399 }
400
401 for (const auto & pr : _boundary_side_id)
402 {
403 const boundary_id_type id = pr.second.second;
404 _boundary_ids.insert(id);
405 _side_boundary_ids.insert(id);
406 if (const auto it = old_ss_id_to_name.find(id);
407 it != old_ss_id_to_name.end())
408 _ss_id_to_name.emplace(id, it->second);
409 }
410
411 for (const auto & pr : _boundary_shellface_id)
412 {
413 const boundary_id_type id = pr.second.second;
414 _boundary_ids.insert(id);
415 _shellface_boundary_ids.insert(id);
416 }
417
418 // Handle global data
420 if (!_mesh->is_serial())
421 {
425 }
426
428}
void synchronize_global_id_set()
Synchronizes the boundary_ids set on each processor to determine global_boundary_ids.

References _boundary_edge_id, _boundary_ids, _boundary_node_id, _boundary_shellface_id, _boundary_side_id, libMesh::ParallelObject::_communicator, _edge_boundary_ids, _es_id_to_name, _mesh, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, _ss_id_to_name, libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::Parallel::Communicator::set_union(), and synchronize_global_id_set().

Referenced by libMesh::UnstructuredMesh::all_first_order(), clear_stitched_boundary_side_ids(), libMesh::MeshBase::complete_preparation(), libMesh::MeshTetInterface::delete_2D_hull_elements(), libMesh::DistributedMesh::delete_remote_elements(), main(), and libMesh::TetGenMeshInterface::pointset_convexhull().

◆ remove() [1/2]

void libMesh::BoundaryInfo::remove ( const Elem elem)

Removes the boundary conditions associated with element elem, if any exist.

Definition at line 1850 of file boundary_info.C.

1851{
1852 libmesh_assert(elem);
1853
1854 // Erase everything associated with elem
1855 _boundary_edge_id.erase (elem);
1856 _boundary_side_id.erase (elem);
1857 _boundary_shellface_id.erase (elem);
1858}

References _boundary_edge_id, _boundary_shellface_id, _boundary_side_id, and libMesh::libmesh_assert().

◆ remove() [2/2]

void libMesh::BoundaryInfo::remove ( const Node node)

◆ remove_edge() [1/2]

void libMesh::BoundaryInfo::remove_edge ( const Elem elem,
const unsigned short int  edge 
)

Removes all boundary conditions associated with edge edge of element elem, if any exist.

Definition at line 1862 of file boundary_info.C.

1864{
1865 libmesh_assert(elem);
1866
1867 // Only touch BCs for edges that exist.
1868 libmesh_assert_less (edge, elem->n_edges());
1869
1870 // Only level 0 elements are stored in BoundaryInfo.
1871 libmesh_assert_equal_to (elem->level(), 0);
1872
1873 // Erase (elem, edge, *) entries from map.
1874 erase_if(_boundary_edge_id, elem,
1875 [edge](decltype(_boundary_edge_id)::mapped_type & pr)
1876 {return pr.first == edge;});
1877}

References _boundary_edge_id, libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::n_edges().

Referenced by renumber_edge_id(), renumber_id(), and libMesh::Elem::swap2boundaryedges().

◆ remove_edge() [2/2]

void libMesh::BoundaryInfo::remove_edge ( const Elem elem,
const unsigned short int  edge,
const boundary_id_type  id 
)

Removes the boundary id id from edge edge of element elem, if it exists.

Definition at line 1881 of file boundary_info.C.

1884{
1885 libmesh_assert(elem);
1886
1887 // Only touch BCs for edges that exist.
1888 libmesh_assert_less (edge, elem->n_edges());
1889
1890 // Only level 0 elements are stored in BoundaryInfo.
1891 libmesh_assert_equal_to (elem->level(), 0);
1892
1893 // Erase (elem, edge, id) entries from map.
1894 erase_if(_boundary_edge_id, elem,
1895 [edge, id](decltype(_boundary_edge_id)::mapped_type & pr)
1896 {return pr.first == edge && pr.second == id;});
1897}

References _boundary_edge_id, libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::n_edges().

◆ remove_edge_id()

void libMesh::BoundaryInfo::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 boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.

Set the global parameter to true if this is being called for all processes in the object's communicator, in which case we will remove the id from the global boundary ID container

Definition at line 2031 of file boundary_info.C.

2032{
2033 // Erase id from ids containers
2034 _edge_boundary_ids.erase(id);
2035
2036 if (!_side_boundary_ids.count(id) &&
2037 !_shellface_boundary_ids.count(id) &&
2038 !_node_boundary_ids.count(id))
2039 _boundary_ids.erase(id);
2040
2041 _es_id_to_name.erase(id);
2042 if (global)
2043 {
2044 bool someone_has_it = _boundary_ids.count(id);
2045 this->comm().max(someone_has_it);
2046 if (!someone_has_it)
2047 _global_boundary_ids.erase(id);
2048 }
2049
2050 // Erase (*, *, id) entries from map.
2051 erase_if(_boundary_edge_id,
2052 [id](decltype(_boundary_edge_id)::mapped_type & pr)
2053 {return pr.second == id;});
2054}

References _boundary_edge_id, _boundary_ids, _edge_boundary_ids, _es_id_to_name, _global_boundary_ids, _node_boundary_ids, _shellface_boundary_ids, _side_boundary_ids, libMesh::ParallelObject::comm(), and libMesh::Parallel::Communicator::max().

Referenced by remove_id().

◆ remove_id()

void libMesh::BoundaryInfo::remove_id ( boundary_id_type  id,
bool  global = false 
)

Removes all entities (nodes, sides, edges, shellfaces) with boundary id id from their respective containers and erases any record of id's existence from the BoundaryInfo object.

That is, after calling remove_id(), id will no longer be in the sets returned by get_boundary_ids(), get_side_boundary_ids(), etc., and will not be in the bc_id_list vector returned by build_side_list(), etc.

Set the global parameter to true if this is being called for all processes in the object's communicator, in which case we will remove the id from the global boundary ID container

Definition at line 1989 of file boundary_info.C.

1990{
1991 // Pass global==false to the sub-methods here, so we can avoid
1992 // unnecessary communications
1993 this->remove_side_id(id, false);
1994 this->remove_edge_id(id, false);
1995 this->remove_shellface_id(id, false);
1996 this->remove_node_id(id, false);
1997
1998 if (global)
1999 _global_boundary_ids.erase(id);
2000}
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...
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...
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 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...

References _global_boundary_ids, remove_edge_id(), remove_node_id(), remove_shellface_id(), and remove_side_id().

Referenced by BoundaryInfoTest::testMesh(), and BoundaryInfoTest::testRenumber().

◆ remove_node()

void libMesh::BoundaryInfo::remove_node ( const Node node,
const boundary_id_type  id 
)

Removes boundary id id from node node, if it exists.

Definition at line 1837 of file boundary_info.C.

1839{
1840 libmesh_assert(node);
1841
1842 // Erase (node, id) entry from map.
1843 erase_if(_boundary_node_id, node,
1844 [id](decltype(_boundary_node_id)::mapped_type & val)
1845 {return val == id;});
1846}

References _boundary_node_id, and libMesh::libmesh_assert().

Referenced by clear_stitched_boundary_side_ids(), renumber_id(), and renumber_node_id().

◆ remove_node_id()

void libMesh::BoundaryInfo::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 boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.

Set the global parameter to true if this is being called for all processes in the object's communicator, in which case we will remove the id from the global boundary ID container

Definition at line 2084 of file boundary_info.C.

2085{
2086 // Erase id from ids containers
2087 _node_boundary_ids.erase(id);
2088
2089 if (!_side_boundary_ids.count(id) &&
2090 !_edge_boundary_ids.count(id) &&
2091 !_shellface_boundary_ids.count(id))
2092 _boundary_ids.erase(id);
2093
2094 _ns_id_to_name.erase(id);
2095 if (global)
2096 {
2097 bool someone_has_it = _boundary_ids.count(id);
2098 this->comm().max(someone_has_it);
2099 if (!someone_has_it)
2100 _global_boundary_ids.erase(id);
2101 }
2102
2103 // Erase (*, id) entries from map.
2104 erase_if(_boundary_node_id,
2105 [id](decltype(_boundary_node_id)::mapped_type & val)
2106 {return val == id;});
2107}

References _boundary_ids, _boundary_node_id, _edge_boundary_ids, _global_boundary_ids, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, libMesh::ParallelObject::comm(), and libMesh::Parallel::Communicator::max().

Referenced by remove_id(), and BoundaryInfoTest::testBuildNodeListFromSideList().

◆ remove_shellface() [1/2]

void libMesh::BoundaryInfo::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.

Definition at line 1900 of file boundary_info.C.

1902{
1903 libmesh_assert(elem);
1904
1905 // Only level 0 elements are stored in BoundaryInfo.
1906 libmesh_assert_equal_to (elem->level(), 0);
1907
1908 // Shells only have 2 faces
1909 libmesh_assert_less(shellface, 2);
1910
1911 // Erase (elem, shellface, *) entries from map.
1912 erase_if(_boundary_shellface_id, elem,
1913 [shellface](decltype(_boundary_shellface_id)::mapped_type & pr)
1914 {return pr.first == shellface;});
1915}

References _boundary_shellface_id, libMesh::Elem::level(), and libMesh::libmesh_assert().

Referenced by renumber_id(), and renumber_shellface_id().

◆ remove_shellface() [2/2]

void libMesh::BoundaryInfo::remove_shellface ( const Elem elem,
const unsigned short int  shellface,
const boundary_id_type  id 
)

Removes all boundary conditions associated with shell face shellface of element elem, if any exist.

Definition at line 1919 of file boundary_info.C.

1922{
1923 libmesh_assert(elem);
1924
1925 // Only level 0 elements are stored in BoundaryInfo.
1926 libmesh_assert_equal_to (elem->level(), 0);
1927
1928 // Shells only have 2 faces
1929 libmesh_assert_less(shellface, 2);
1930
1931 // Erase (elem, shellface, id) entries from map.
1932 erase_if(_boundary_shellface_id, elem,
1933 [shellface, id](decltype(_boundary_shellface_id)::mapped_type & pr)
1934 {return pr.first == shellface && pr.second == id;});
1935}

References _boundary_shellface_id, libMesh::Elem::level(), and libMesh::libmesh_assert().

◆ remove_shellface_id()

void libMesh::BoundaryInfo::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 shellface boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.

Set the global parameter to true if this is being called for all processes in the object's communicator, in which case we will remove the id from the global boundary ID container

Definition at line 2058 of file boundary_info.C.

2059{
2060 // Erase id from ids containers
2061 _shellface_boundary_ids.erase(id);
2062
2063 if (!_side_boundary_ids.count(id) &&
2064 !_edge_boundary_ids.count(id) &&
2065 !_node_boundary_ids.count(id))
2066 _boundary_ids.erase(id);
2067
2068 if (global)
2069 {
2070 bool someone_has_it = _boundary_ids.count(id);
2071 this->comm().max(someone_has_it);
2072 if (!someone_has_it)
2073 _global_boundary_ids.erase(id);
2074 }
2075
2076 // Erase (*, *, id) entries from map.
2077 erase_if(_boundary_shellface_id,
2078 [id](decltype(_boundary_shellface_id)::mapped_type & pr)
2079 {return pr.second == id;});
2080}

References _boundary_ids, _boundary_shellface_id, _edge_boundary_ids, _global_boundary_ids, _node_boundary_ids, _shellface_boundary_ids, _side_boundary_ids, libMesh::ParallelObject::comm(), and libMesh::Parallel::Communicator::max().

Referenced by remove_id().

◆ remove_side() [1/2]

void libMesh::BoundaryInfo::remove_side ( const Elem elem,
const unsigned short int  side 
)

Removes all boundary conditions associated with side side of element elem, if any exist.

Definition at line 1937 of file boundary_info.C.

1939{
1940 libmesh_assert(elem);
1941
1942 // Only touch BCs for sides that exist.
1943 libmesh_assert_less (side, elem->n_sides());
1944
1945 // Erase (elem, side, *) entries from map.
1946 erase_if(_boundary_side_id, elem,
1947 [side](decltype(_boundary_side_id)::mapped_type & pr)
1948 {return pr.first == side;});
1949}

References _boundary_side_id, libMesh::libmesh_assert(), and libMesh::Elem::n_sides().

Referenced by main(), renumber_id(), renumber_side_id(), libMesh::Elem::swap2boundarysides(), and BoundaryInfoTest::testBoundaryOnChildrenElementsRefineCoarsen().

◆ remove_side() [2/2]

void libMesh::BoundaryInfo::remove_side ( const Elem elem,
const unsigned short int  side,
const boundary_id_type  id 
)

Removes the boundary id id from side side of element elem, if it exists.

Definition at line 1953 of file boundary_info.C.

1956{
1957 libmesh_assert(elem);
1958
1959 // Only touch BCs for sides that exist.
1960 libmesh_assert_less (side, elem->n_sides());
1961
1962#ifdef LIBMESH_ENABLE_AMR
1963 // Here we have to stop and check if somebody tries to remove an ancestor's boundary ID
1964 // through a child
1965 if (elem->level())
1966 {
1967 std::vector<boundary_id_type> bd_ids;
1968 this->boundary_ids(elem,side,bd_ids);
1969 if(std::find(bd_ids.begin(), bd_ids.end(), id) != bd_ids.end())
1970 {
1971 std::vector<boundary_id_type> raw_bd_ids;
1972 this->raw_boundary_ids(elem, side, 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.");
1977 }
1978 }
1979#endif
1980
1981 // Erase (elem, side, id) entries from map.
1982 erase_if(_boundary_side_id, elem,
1983 [side, id](decltype(_boundary_side_id)::mapped_type & pr)
1984 {return pr.first == side && pr.second == id;});
1985}

References _boundary_side_id, boundary_ids(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::n_sides(), and raw_boundary_ids().

◆ remove_side_id()

void libMesh::BoundaryInfo::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 boundary ids, and removes it from the set of boundary ids if no other boundary type uses it.

Set the global parameter to true if this is being called for all processes in the object's communicator, in which case we will remove the id from the global boundary ID container

Definition at line 2004 of file boundary_info.C.

2005{
2006 // Erase id from ids containers
2007 _side_boundary_ids.erase(id);
2008
2009 if (!_edge_boundary_ids.count(id) &&
2010 !_shellface_boundary_ids.count(id) &&
2011 !_node_boundary_ids.count(id))
2012 _boundary_ids.erase(id);
2013
2014 _ss_id_to_name.erase(id);
2015 if (global)
2016 {
2017 bool someone_has_it = _boundary_ids.count(id);
2018 this->comm().max(someone_has_it);
2019 if (!someone_has_it)
2020 _global_boundary_ids.erase(id);
2021 }
2022
2023 // Erase (*, *, id) entries from map.
2024 erase_if(_boundary_side_id,
2025 [id](decltype(_boundary_side_id)::mapped_type & pr)
2026 {return pr.second == id;});
2027}

References _boundary_ids, _boundary_side_id, _edge_boundary_ids, _global_boundary_ids, _node_boundary_ids, _shellface_boundary_ids, _side_boundary_ids, _ss_id_to_name, libMesh::ParallelObject::comm(), and libMesh::Parallel::Communicator::max().

Referenced by remove_id(), and BoundaryInfoTest::testBuildSideListFromNodeList().

◆ renumber_edge_id()

void libMesh::BoundaryInfo::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.

Definition at line 2242 of file boundary_info.C.

2244{
2245 // If the IDs are the same, this is a no-op.
2246 if (old_id == new_id)
2247 return;
2248
2249 bool found_edge = false;
2250 for (auto & p : _boundary_edge_id)
2251 if (p.second.second == old_id)
2252 {
2253 // If we already have this id on this edge, we don't want to
2254 // create a duplicate in our multimap
2255 this->remove_edge(p.first, p.second.first, new_id);
2256 p.second.second = new_id;
2257 found_edge = true;
2258 }
2259 _edge_boundary_ids.erase(old_id);
2260
2261 if (found_edge)
2262 {
2263 _edge_boundary_ids.insert(new_id);
2264
2265 if (!_shellface_boundary_ids.count(old_id) &&
2266 !_side_boundary_ids.count(old_id) &&
2267 !_node_boundary_ids.count(old_id))
2268 {
2269 _boundary_ids.erase(old_id);
2270 _global_boundary_ids.erase(old_id);
2271 }
2272 _boundary_ids.insert(new_id);
2273 _global_boundary_ids.insert(new_id);
2274 }
2275
2276 renumber_name(_es_id_to_name, old_id, new_id);
2277
2279}
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.

References _boundary_edge_id, _boundary_ids, _edge_boundary_ids, _es_id_to_name, _global_boundary_ids, _node_boundary_ids, _shellface_boundary_ids, _side_boundary_ids, libmesh_assert_valid_multimaps(), and remove_edge().

Referenced by BoundaryInfoTest::testSelectiveRenumber().

◆ renumber_id()

void libMesh::BoundaryInfo::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 by boundary id new_id.

Definition at line 2111 of file boundary_info.C.

2113{
2114 if (old_id == new_id)
2115 {
2116 // If the IDs are the same, this is a no-op.
2117 return;
2118 }
2119
2120 bool found_node = false;
2121 for (auto & p : _boundary_node_id)
2122 if (p.second == old_id)
2123 {
2124 // If we already have this id on this node, we don't want to
2125 // create a duplicate in our multimap
2126 this->remove_node(p.first, new_id);
2127 p.second = new_id;
2128 found_node = true;
2129 }
2130 if (found_node)
2131 {
2132 _node_boundary_ids.erase(old_id);
2133 _node_boundary_ids.insert(new_id);
2134 }
2135
2136 bool found_edge = false;
2137 for (auto & p : _boundary_edge_id)
2138 if (p.second.second == old_id)
2139 {
2140 // If we already have this id on this edge, we don't want to
2141 // create a duplicate in our multimap
2142 this->remove_edge(p.first, p.second.first, new_id);
2143 p.second.second = new_id;
2144 found_edge = true;
2145 }
2146 if (found_edge)
2147 {
2148 _edge_boundary_ids.erase(old_id);
2149 _edge_boundary_ids.insert(new_id);
2150 }
2151
2152 bool found_shellface = false;
2153 for (auto & p : _boundary_shellface_id)
2154 if (p.second.second == old_id)
2155 {
2156 // If we already have this id on this shellface, we don't want
2157 // to create a duplicate in our multimap
2158 this->remove_shellface(p.first, p.second.first, new_id);
2159 p.second.second = new_id;
2160 found_shellface = true;
2161 }
2162 if (found_shellface)
2163 {
2164 _shellface_boundary_ids.erase(old_id);
2165 _shellface_boundary_ids.insert(new_id);
2166 }
2167
2168 bool found_side = false;
2169 for (auto & p : _boundary_side_id)
2170 if (p.second.second == old_id)
2171 {
2172 // If we already have this id on this side, we don't want to
2173 // create a duplicate in our multimap
2174 this->remove_side(p.first, p.second.first, new_id);
2175 p.second.second = new_id;
2176 found_side = true;
2177 }
2178 if (found_side)
2179 {
2180 _side_boundary_ids.erase(old_id);
2181 _side_boundary_ids.insert(new_id);
2182 }
2183
2184 if (found_node || found_edge || found_shellface || found_side)
2185 {
2186 _boundary_ids.erase(old_id);
2187 _boundary_ids.insert(new_id);
2188 _global_boundary_ids.erase(old_id);
2189 _global_boundary_ids.insert(new_id);
2190 }
2191
2192 renumber_name(_ss_id_to_name, old_id, new_id);
2193 renumber_name(_ns_id_to_name, old_id, new_id);
2194 renumber_name(_es_id_to_name, old_id, new_id);
2195
2197}
void remove_shellface(const Elem *elem, const unsigned short int shellface)
Removes all boundary conditions associated with shell face shellface of element elem,...
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.

References _boundary_edge_id, _boundary_ids, _boundary_node_id, _boundary_shellface_id, _boundary_side_id, _edge_boundary_ids, _es_id_to_name, _global_boundary_ids, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, _ss_id_to_name, libmesh_assert_valid_multimaps(), remove_edge(), remove_node(), remove_shellface(), and remove_side().

Referenced by libMesh::MeshTools::Modification::change_boundary_id(), and BoundaryInfoTest::testRenumber().

◆ renumber_node_id()

void libMesh::BoundaryInfo::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.

Definition at line 2322 of file boundary_info.C.

2324{
2325 // If the IDs are the same, this is a no-op.
2326 if (old_id == new_id)
2327 return;
2328
2329 bool found_node = false;
2330 for (auto & p : _boundary_node_id)
2331 if (p.second == old_id)
2332 {
2333 // If we already have this id on this node, we don't want to
2334 // create a duplicate in our multimap
2335 this->remove_node(p.first, new_id);
2336 p.second = new_id;
2337 found_node = true;
2338 }
2339 _node_boundary_ids.erase(old_id);
2340
2341 if (found_node)
2342 {
2343 _node_boundary_ids.insert(new_id);
2344
2345 if (!_shellface_boundary_ids.count(old_id) &&
2346 !_side_boundary_ids.count(old_id) &&
2347 !_edge_boundary_ids.count(old_id))
2348 {
2349 _boundary_ids.erase(old_id);
2350 _global_boundary_ids.erase(old_id);
2351 }
2352 _boundary_ids.insert(new_id);
2353 _global_boundary_ids.insert(new_id);
2354 }
2355
2356 renumber_name(_ns_id_to_name, old_id, new_id);
2357
2359}

References _boundary_ids, _boundary_node_id, _edge_boundary_ids, _global_boundary_ids, _node_boundary_ids, _ns_id_to_name, _shellface_boundary_ids, _side_boundary_ids, libmesh_assert_valid_multimaps(), and remove_node().

Referenced by BoundaryInfoTest::testSelectiveRenumber().

◆ renumber_shellface_id()

void libMesh::BoundaryInfo::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.

Definition at line 2283 of file boundary_info.C.

2285{
2286 // If the IDs are the same, this is a no-op.
2287 if (old_id == new_id)
2288 return;
2289
2290 bool found_shellface = false;
2291 for (auto & p : _boundary_shellface_id)
2292 if (p.second.second == old_id)
2293 {
2294 // If we already have this id on this shellface, we don't want
2295 // to create a duplicate in our multimap
2296 this->remove_shellface(p.first, p.second.first, new_id);
2297 p.second.second = new_id;
2298 found_shellface = true;
2299 }
2300 _shellface_boundary_ids.erase(old_id);
2301
2302 if (found_shellface)
2303 {
2304 _shellface_boundary_ids.insert(new_id);
2305
2306 if (!_edge_boundary_ids.count(old_id) &&
2307 !_side_boundary_ids.count(old_id) &&
2308 !_node_boundary_ids.count(old_id))
2309 {
2310 _boundary_ids.erase(old_id);
2311 _global_boundary_ids.erase(old_id);
2312 }
2313 _boundary_ids.insert(new_id);
2314 _global_boundary_ids.insert(new_id);
2315 }
2316
2318}

References _boundary_ids, _boundary_shellface_id, _edge_boundary_ids, _global_boundary_ids, _node_boundary_ids, _shellface_boundary_ids, _side_boundary_ids, libmesh_assert_valid_multimaps(), and remove_shellface().

◆ renumber_side_id()

void libMesh::BoundaryInfo::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.

Definition at line 2201 of file boundary_info.C.

2203{
2204 // If the IDs are the same, this is a no-op.
2205 if (old_id == new_id)
2206 return;
2207
2208 bool found_side = false;
2209 for (auto & p : _boundary_side_id)
2210 if (p.second.second == old_id)
2211 {
2212 // If we already have this id on this side, we don't want to
2213 // create a duplicate in our multimap
2214 this->remove_side(p.first, p.second.first, new_id);
2215 p.second.second = new_id;
2216 found_side = true;
2217 }
2218 _side_boundary_ids.erase(old_id);
2219
2220 if (found_side)
2221 {
2222 _side_boundary_ids.insert(new_id);
2223
2224 if (!_shellface_boundary_ids.count(old_id) &&
2225 !_edge_boundary_ids.count(old_id) &&
2226 !_node_boundary_ids.count(old_id))
2227 {
2228 _boundary_ids.erase(old_id);
2229 _global_boundary_ids.erase(old_id);
2230 }
2231 _boundary_ids.insert(new_id);
2232 _global_boundary_ids.insert(new_id);
2233 }
2234
2235 renumber_name(_ss_id_to_name, old_id, new_id);
2236
2238}

References _boundary_ids, _boundary_side_id, _edge_boundary_ids, _global_boundary_ids, _node_boundary_ids, _shellface_boundary_ids, _side_boundary_ids, _ss_id_to_name, libmesh_assert_valid_multimaps(), and remove_side().

Referenced by BoundaryInfoTest::testSelectiveRenumber().

◆ set_edgeset_name_map()

std::map< boundary_id_type, std::string > & libMesh::BoundaryInfo::set_edgeset_name_map ( )
inline
Returns
Writable/const reference to the edgeset name map.

Definition at line 913 of file boundary_info.h.

914 { return _es_id_to_name; }

References _es_id_to_name.

Referenced by libMesh::MeshTools::Generation::build_extrusion(), and libMesh::UnstructuredMesh::stitching_helper().

◆ set_mesh()

void libMesh::BoundaryInfo::set_mesh ( MeshBase m)
inlineprotected

Definition at line 70 of file boundary_info.h.

70{ _mesh = &m; }

References _mesh.

◆ set_nodeset_name_map()

std::map< boundary_id_type, std::string > & libMesh::BoundaryInfo::set_nodeset_name_map ( )
inline
Returns
A writable reference to the nodeset name map.

Definition at line 905 of file boundary_info.h.

906 { return _ns_id_to_name; }

References _ns_id_to_name.

Referenced by libMesh::MeshTools::Generation::build_extrusion(), libMesh::CheckpointIO::read_header(), and libMesh::UnstructuredMesh::stitching_helper().

◆ set_sideset_name_map()

std::map< boundary_id_type, std::string > & libMesh::BoundaryInfo::set_sideset_name_map ( )
inline
Returns
A writable reference to the sideset name map.

Definition at line 897 of file boundary_info.h.

898 { return _ss_id_to_name; }

References _ss_id_to_name.

Referenced by libMesh::MeshTools::Generation::build_extrusion(), libMesh::CheckpointIO::read_header(), and libMesh::UnstructuredMesh::stitching_helper().

◆ shellface_boundary_ids()

void libMesh::BoundaryInfo::shellface_boundary_ids ( const Elem *const  elem,
const unsigned short int  shellface,
std::vector< boundary_id_type > &  vec_to_fill 
) const
Returns
The list of boundary ids associated with the specified shell face of element elem.
Note
This is only relevant for shell elements.

Definition at line 1503 of file boundary_info.C.

1506{
1507 libmesh_assert(elem);
1508
1509 // Shells only have 2 faces
1510 libmesh_assert_less(shellface, 2);
1511
1512 // Clear out any previous contents
1513 vec_to_fill.clear();
1514
1515 // Only level-0 elements store BCs. If this is not a level-0
1516 // element get its level-0 parent and infer the BCs.
1517 const Elem * searched_elem = elem;
1518#ifdef LIBMESH_ENABLE_AMR
1519 if (elem->level() != 0)
1520 {
1521 while (searched_elem->parent() != nullptr)
1522 {
1523 const Elem * parent = searched_elem->parent();
1524 searched_elem = parent;
1525 }
1526 }
1527#endif
1528
1529 // Check each element in the range to see if its shellface matches the requested shellface.
1530 for (const auto & pr : as_range(_boundary_shellface_id.equal_range(searched_elem)))
1531 if (pr.second.first == shellface)
1532 vec_to_fill.push_back(pr.second.second);
1533}

References _boundary_shellface_id, libMesh::as_range(), libMesh::Elem::level(), libMesh::libmesh_assert(), and libMesh::Elem::parent().

Referenced by assemble_shell(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), n_shellface_boundary_ids(), operator==(), and libMesh::XdrIO::write_serialized_bcs_helper().

◆ side_boundary_ids()

void libMesh::BoundaryInfo::side_boundary_ids ( const Elem *const  elem,
std::vector< std::vector< boundary_id_type > > &  vec_to_fill 
) const
Returns
The list of boundary ids associated with any of the sides of element elem. Indexed by sides.

Definition at line 1581 of file boundary_info.C.

1583{
1584 libmesh_assert(elem);
1585
1586 // Clear out any previous contents
1587 vec_to_fill.clear();
1588 auto num_sides = elem->n_sides();
1589
1590 // No sides, no boundary ids
1591 if (!num_sides)
1592 return;
1593
1594 // We are going to gather boundary ids for each side
1595 vec_to_fill.resize(num_sides);
1596 // In most cases only level-0 elements store BCs.
1597 // In certain applications (such as time-dependent domains), however, children
1598 // need to store BCs too. This case is covered with the _children_on_boundary
1599 // flag.
1600 const Elem * searched_elem = elem;
1601
1602#ifdef LIBMESH_ENABLE_AMR
1603 if (elem->level() != 0)
1604 {
1605 // If we have children on the boundaries, we need to search for boundary IDs on the
1606 // child and its ancestors too if they share the side.
1608 {
1609 // Loop over ancestors to check if they have boundary ids on the same side
1610 std::vector<bool> search_on_side(elem->n_sides(), true);
1611 bool keep_searching = true;
1612 while (searched_elem && keep_searching)
1613 {
1614 for (const auto & pr : as_range(_boundary_side_id.equal_range(searched_elem)))
1615 {
1616 for (const auto side : make_range(elem->n_sides()))
1617 // Here we need to check if the boundary id already exists
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);
1622 }
1623
1624 const Elem * parent = searched_elem->parent();
1625 const auto child_index = parent ? parent->which_child_am_i(searched_elem) : libMesh::invalid_uint;
1626 for (const auto side : make_range(elem->n_sides()))
1627 // If the parent doesn't exist or if the child is not on the correct side of the
1628 // parent we are done checking the ancestors
1629 if (search_on_side[side] &&
1630 (!parent || parent->is_child_on_side(child_index, side) == false))
1631 search_on_side[side] = false;
1632
1633 searched_elem = parent;
1634 // if found what we needed on all sides, exit
1635 keep_searching = *std::max_element(search_on_side.begin(), search_on_side.end());
1636 }
1637
1638 return;
1639 }
1640
1641 // Children not on boundaries case.
1642 // It could be that a children is interior to the parent (search_on_side = false will handle that)
1643 // However, since no children on boundaries, we know that it's either the top parent or nothing
1644 std::vector<bool> search_on_side(elem->n_sides(), true);
1645 for (const auto side : make_range(elem->n_sides()))
1646 {
1647 // Reset the search level for each side
1648 const Elem * searched_elem_for_side = elem;
1649
1650 // If we don't have children on boundaries and we are on an external boundary,
1651 // we will just use the top parent. search_on_side[side] = true works
1652 if (elem->neighbor_ptr(side) == nullptr)
1653 continue;
1654 // Otherwise we loop over the ancestors and check if they have a different BC for us
1655 else
1656 while (searched_elem_for_side->parent() != nullptr)
1657 {
1658 const Elem * parent = searched_elem_for_side->parent();
1659 if (search_on_side[side] && parent->is_child_on_side(parent->which_child_am_i(searched_elem_for_side), side) == false)
1660 search_on_side[side] = false;
1661 searched_elem_for_side = parent;
1662 }
1663 }
1664 // Now search on the top parent, only if we need to (element is not deep inside the top parent)
1665 if (*std::max_element(search_on_side.begin(), search_on_side.end()))
1666 for (const auto & pr : as_range(_boundary_side_id.equal_range(elem->top_parent())))
1667 if (search_on_side[pr.second.first])
1668 vec_to_fill[pr.second.first].push_back(pr.second.second);
1669 return;
1670 }
1671#endif
1672
1673 // Check each element in the range to see if its side matches the requested side.
1674 for (const auto & pr : as_range(_boundary_side_id.equal_range(searched_elem)))
1675 vec_to_fill[pr.second.first].push_back(pr.second.second);
1676}

References _boundary_side_id, _children_on_boundary, libMesh::as_range(), libMesh::invalid_uint, libMesh::Elem::is_child_on_side(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::make_range(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::parent(), libMesh::Elem::top_parent(), and libMesh::Elem::which_child_am_i().

Referenced by BoundaryInfoTest::testBoundaryIDs(), and BoundaryInfoTest::testBoundaryOnChildrenBoundaryIDs().

◆ side_with_boundary_id()

unsigned int libMesh::BoundaryInfo::side_with_boundary_id ( const Elem *const  elem,
const boundary_id_type  boundary_id 
) const
Returns
A side of element elem whose associated boundary id is boundary_id if such a side exists, and invalid_uint otherwise.
Note
If multiple sides of elem have the same id, only the lowest numbered such side is returned.

Definition at line 2363 of file boundary_info.C.

2365{
2366 const Elem * searched_elem = elem;
2367
2368 // If we don't have a time-dependent domain, we can just go ahead and use the top parent
2369 // (since only those contain boundary conditions). Otherwise, we keep the element
2370 if (elem->level() != 0 && !_children_on_boundary)
2371 searched_elem = elem->top_parent();
2372
2373 // elem may have zero or multiple occurrences
2374 for (const auto & pr : as_range(_boundary_side_id.equal_range(searched_elem)))
2375 {
2376 // if this is true we found the requested boundary_id
2377 // of the element and want to return the side
2378 if (pr.second.second == boundary_id_in)
2379 {
2380 unsigned int side = pr.second.first;
2381
2382 // Here we branch out. If we don't allow time-dependent boundary domains,
2383 // we need to check if our parents are consistent.
2385 {
2386#ifdef LIBMESH_ENABLE_AMR
2387 // If we're on this external boundary then we share this
2388 // external boundary id
2389 if (elem->neighbor_ptr(side) == nullptr)
2390 return side;
2391
2392 // Internal boundary case
2393 const Elem * p = elem;
2394
2395 // If we're on an internal boundary then we need to be sure
2396 // it's the same internal boundary as our top_parent
2397 while (p != nullptr)
2398 {
2399 const Elem * parent = p->parent();
2400 if (parent && !parent->is_child_on_side(parent->which_child_am_i(p), side))
2401 break;
2402 p = parent;
2403 }
2404
2405 // We're on that side of our top_parent; return it
2406 if (!p)
2407 return side;
2408#else
2409 // do not forget to return the internal boundary when AMR is disabled
2410 return side;
2411#endif
2412 }
2413 // Otherwise we need to check if the child's ancestors have something on
2414 // the side of the child
2415 else
2416 return side;
2417 }
2418 }
2419
2420#ifdef LIBMESH_ENABLE_AMR
2421 // We might have instances (especially with moving boundary domains) when we
2422 // query the paren't boundary ID on a child. We only do this till we find the
2423 // the first side, for multiple sides see above.
2424 if (_children_on_boundary && elem->level() != 0)
2425 {
2426 for (auto side : make_range(elem->n_sides()))
2427 {
2428 const Elem * p = elem;
2429 while (p->parent() != nullptr)
2430 {
2431 const Elem * parent = p->parent();
2432
2433 // First we make sure the parent shares this side
2434 if (parent->is_child_on_side(parent->which_child_am_i(p), side))
2435 {
2436 // parent may have multiple boundary ids
2437 for (const auto & pr : as_range(_boundary_side_id.equal_range(parent)))
2438 // if this is true we found the requested boundary_id
2439 // of the element and want to return the side
2440 if (pr.second.first == side && pr.second.second == boundary_id_in)
2441 return side;
2442
2443 p = parent;
2444 }
2445 // If the parent is not on the same side, other ancestors won't be on the same side either
2446 else
2447 break;
2448 }
2449 }
2450 }
2451#endif
2452
2453 // if we get here, we found elem in the data structure but not
2454 // the requested boundary id, so return the default value
2455 return libMesh::invalid_uint;
2456}

References _boundary_side_id, _children_on_boundary, libMesh::as_range(), libMesh::invalid_uint, libMesh::Elem::is_child_on_side(), libMesh::Elem::level(), libMesh::make_range(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::parent(), libMesh::Elem::top_parent(), and libMesh::Elem::which_child_am_i().

Referenced by assemble_temperature_jump(), BoundaryInfoTest::testBoundaryOnChildrenBoundarySides(), and BoundaryInfoTest::testInternalBoundary().

◆ sides_with_boundary_id()

std::vector< unsigned int > libMesh::BoundaryInfo::sides_with_boundary_id ( const Elem *const  elem,
const boundary_id_type  boundary_id 
) const
Returns
All sides of element elem whose associated boundary id is boundary_id

Definition at line 2460 of file boundary_info.C.

2462{
2463 std::vector<unsigned int> returnval;
2464
2465 const Elem * searched_elem = elem;
2466 if (elem->level() != 0 && !_children_on_boundary)
2467 searched_elem = elem->top_parent();
2468
2469 // elem may have zero or multiple occurrences
2470 for (const auto & pr : as_range(_boundary_side_id.equal_range(searched_elem)))
2471 {
2472 // if this is true we found the requested boundary_id
2473 // of the element and want to return the side
2474 if (pr.second.second == boundary_id_in)
2475 {
2476 unsigned int side = pr.second.first;
2477
2478 // Here we branch out. If we don't allow time-dependent boundary domains,
2479 // we need to check if our parents are consistent.
2481 {
2482 // If we're on this external boundary then we share this
2483 // external boundary id
2484 if (elem->neighbor_ptr(side) == nullptr)
2485 {
2486 returnval.push_back(side);
2487 continue;
2488 }
2489
2490 // If we're on an internal boundary then we need to be sure
2491 // it's the same internal boundary as our top_parent
2492 const Elem * p = elem;
2493
2494#ifdef LIBMESH_ENABLE_AMR
2495
2496 while (p != nullptr)
2497 {
2498 const Elem * parent = p->parent();
2499 if (parent && !parent->is_child_on_side(parent->which_child_am_i(p), side))
2500 break;
2501 p = parent;
2502 }
2503#endif
2504 // We're on that side of our top_parent; return it
2505 if (!p)
2506 returnval.push_back(side);
2507 }
2508 // Otherwise we trust what we got and return the side
2509 else
2510 returnval.push_back(side);
2511 }
2512 }
2513
2514#ifdef LIBMESH_ENABLE_AMR
2515 // We might have instances (especially with moving boundary domains) when we
2516 // query the parent boundary ID on a child.
2517 if (_children_on_boundary && elem->level() != 0)
2518 {
2519 for (auto side : make_range(elem->n_sides()))
2520 {
2521 const Elem * p = elem;
2522 while (p->parent() != nullptr)
2523 {
2524 const Elem * parent = p->parent();
2525 // First we make sure the parent shares this side
2526 if (parent->is_child_on_side(parent->which_child_am_i(p), side))
2527 {
2528 // parent may have multiple boundary ids
2529 for (const auto & pr : as_range(_boundary_side_id.equal_range(parent)))
2530 {
2531 // if this is true we found the requested boundary_id
2532 // of the element and want to add the side to the vector. We
2533 // also need to check if the side is already in the vector. This might
2534 // happen if the child inherits the boundary from the parent.
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);
2538 }
2539 }
2540 // If the parent is not on the same side, other ancestors won't be on the same side either
2541 else
2542 break;
2543 p = parent;
2544 }
2545 }
2546 }
2547#endif
2548
2549 return returnval;
2550}

References _boundary_side_id, _children_on_boundary, libMesh::as_range(), libMesh::Elem::is_child_on_side(), libMesh::Elem::level(), libMesh::make_range(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor_ptr(), libMesh::Elem::parent(), libMesh::Elem::top_parent(), and libMesh::Elem::which_child_am_i().

Referenced by libMesh::PeriodicBoundaries::neighbor(), and BoundaryInfoTest::testBoundaryOnChildrenBoundarySides().

◆ sideset_name()

std::string & libMesh::BoundaryInfo::sideset_name ( boundary_id_type  id)

◆ sync() [1/3]

void libMesh::BoundaryInfo::sync ( const std::set< boundary_id_type > &  requested_boundary_ids,
UnstructuredMesh boundary_mesh 
)

Generates boundary_mesh data structures corresponding to the mesh data structures.

Allows the boundary_mesh to be used like any other mesh, except with interior_parent() values defined for algorithms which couple boundary and interior mesh information. Any pre-existing boundary_mesh data is cleared. Only boundary elements with the specified ids are extracted. Boundary IDs for the nodes on requested_boundary_ids will also be copied over to boundary_mesh. We do not currently copy edge boundary IDs over to boundary_mesh.

Definition at line 458 of file boundary_info.C.

460{
461 // Call the 3 argument version of this function with a dummy value for the third set.
462 std::set<subdomain_id_type> subdomains_relative_to;
463 subdomains_relative_to.insert(Elem::invalid_subdomain_id);
464
465 this->sync(requested_boundary_ids,
466 boundary_mesh,
467 subdomains_relative_to);
468}
void sync(UnstructuredMesh &boundary_mesh)
Generates boundary_mesh data structures corresponding to the mesh data structures.

References libMesh::Elem::invalid_subdomain_id, and sync().

◆ sync() [2/3]

void libMesh::BoundaryInfo::sync ( const std::set< boundary_id_type > &  requested_boundary_ids,
UnstructuredMesh boundary_mesh,
const std::set< subdomain_id_type > &  subdomains_relative_to 
)

Like the other sync() implementations, but specifically intended for building "boundary" meshes from internal sidesets.

In the case of an internal sideset, each side may belong to 2 higher-dimensional parent elements, and typically we do not want to add the same side to the boundary mesh twice. The std::set<subdomain_id_type> passed into this function specifies which subdomain the sides in question should relative to, so that they are only added once.

Deleting 0 elements seems weird, but it's better encapsulating than exposing a set_is_serial(false) capability that might be easily misused.

If the boundary_mesh is still serial, that means we can't parallelize it, so to make sure we can construct it in full on every processor we'll serialize the interior mesh.

We'll use a temporary MeshSerializer here, but as soon as we unserialize we'll be turning a bunch of interior_parent() links into dangling pointers, and it won't be easy to tell which. So we'll keep around a distributed copy for that case, and query it to fix up interior_parent() links as necessary.

We'll also need to make sure to unserialize the mesh before we prepare the boundary mesh for use, or the prepare_for_use() call on a refined boundary mesh will happily notice that it can find and restore some refined elements' interior_parent pointers, not knowing that those interior parents are about to go remote.

Re-create the boundary mesh.

Definition at line 472 of file boundary_info.C.

475{
476 LOG_SCOPE("sync()", "BoundaryInfo");
477
478 boundary_mesh.clear();
479
485 if (!_mesh->is_serial())
486 boundary_mesh.delete_remote_elements();
487
505 std::unique_ptr<MeshBase> mesh_copy;
506 if (boundary_mesh.is_serial() && !_mesh->is_serial())
507 mesh_copy = _mesh->clone();
508
509 auto serializer = std::make_unique<MeshSerializer>
510 (const_cast<MeshBase &>(*_mesh), boundary_mesh.is_serial());
511
516 boundary_mesh.set_n_partitions() = _mesh->n_partitions();
517
518 std::map<dof_id_type, dof_id_type> node_id_map;
519
520 this->_find_id_maps(requested_boundary_ids, 0, &node_id_map, 0, nullptr, subdomains_relative_to);
521
522 // Let's add all the boundary nodes we found to the boundary mesh
523 for (const auto & node : _mesh->node_ptr_range())
524 {
525 dof_id_type node_id = node->id();
526 if (node_id_map.count(node_id))
527 {
528 boundary_mesh.add_point(*node, node_id_map[node_id], node->processor_id());
529
530 // Copy over all the node's boundary IDs to boundary_mesh
531 std::vector<boundary_id_type> node_boundary_ids;
532 this->boundary_ids(node, node_boundary_ids);
533 for (const auto & node_bid : node_boundary_ids)
534 boundary_mesh.get_boundary_info().add_node(node_id_map[node_id], node_bid);
535 }
536 }
537
538 // Add the elements. When syncing a boundary mesh, we also store the
539 // parent side ids in addition to the interior_parent pointers,
540 // since this information is frequently needed on boundary meshes.
541 this->add_elements(requested_boundary_ids,
542 boundary_mesh,
543 subdomains_relative_to,
544 /*store_parent_side_ids=*/true);
545
546 // The new elements are currently using the interior mesh's nodes;
547 // we want them to use the boundary mesh's nodes instead.
548
549 // This side's Node pointers still point to the nodes of the original mesh.
550 // We need to re-point them to the boundary mesh's nodes! Since we copied *ALL* of
551 // the original mesh's nodes over, we should be guaranteed to have the same ordering.
552 for (auto & new_elem : boundary_mesh.element_ptr_range())
553 {
554 for (auto nn : new_elem->node_index_range())
555 {
556 // Get the correct node pointer, based on the id()
557 Node * new_node =
558 boundary_mesh.node_ptr(node_id_map[new_elem->node_id(nn)]);
559
560 // sanity check: be sure that the new Node exists and its
561 // global id really matches
562 libmesh_assert (new_node);
563 libmesh_assert_equal_to (new_node->id(),
564 node_id_map[new_elem->node_id(nn)]);
565
566 // Assign the new node pointer
567 new_elem->set_node(nn, new_node);
568 }
569 }
570
571 // The new elements might have interior parent pointers aimed at
572 // _mesh elements which are about to go remote, and we don't to
573 // leave those pointers dangling. Fix them up if needed.
574 if (mesh_copy.get())
575 {
576 for (auto & new_elem : boundary_mesh.element_ptr_range())
577 {
578 const dof_id_type interior_parent_id =
579 new_elem->interior_parent()->id();
580
581 if (!mesh_copy->query_elem_ptr(interior_parent_id))
582 new_elem->set_interior_parent
583 (const_cast<RemoteElem *>(remote_elem));
584 }
585 }
586
587 // Don't repartition this mesh; we want it to stay in sync with the
588 // interior partitioning.
589 boundary_mesh.partitioner().reset(nullptr);
590
591 // Deserialize the interior mesh before the boundary mesh
592 // prepare_for_use() can come to erroneous conclusions about which
593 // of its elements are semilocal
594 serializer.reset();
595
596 // Make boundary_mesh nodes and elements contiguous
597 boundary_mesh.prepare_for_use();
598
599 // and finally distribute element partitioning to the nodes
601}
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
unsigned int n_partitions() const
Definition mesh_base.h:1526
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.

References _find_id_maps(), _mesh, add_elements(), add_node(), libMesh::MeshBase::add_point(), boundary_ids(), libMesh::MeshBase::clear(), libMesh::MeshBase::clone(), libMesh::MeshBase::delete_remote_elements(), libMesh::MeshBase::get_boundary_info(), libMesh::DofObject::id(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::MeshBase::n_partitions(), libMesh::MeshBase::node_ptr(), libMesh::MeshBase::partitioner(), libMesh::MeshBase::prepare_for_use(), libMesh::remote_elem, libMesh::MeshBase::set_n_partitions(), and libMesh::Partitioner::set_node_processor_ids().

◆ sync() [3/3]

void libMesh::BoundaryInfo::sync ( UnstructuredMesh boundary_mesh)

Generates boundary_mesh data structures corresponding to the mesh data structures.

Allows the boundary_mesh to be used like any other mesh, except with interior_parent() values defined for algorithms which couple boundary and interior mesh information. Any pre-existing boundary_mesh data is cleared.

Definition at line 445 of file boundary_info.C.

446{
447 std::set<boundary_id_type> request_boundary_ids(_boundary_ids);
448 request_boundary_ids.insert(invalid_id);
449 if (!_mesh->is_serial())
450 this->comm().set_union(request_boundary_ids);
451
452 this->sync(request_boundary_ids,
453 boundary_mesh);
454}

References _boundary_ids, _mesh, libMesh::ParallelObject::comm(), invalid_id, libMesh::MeshBase::is_serial(), libMesh::Parallel::Communicator::set_union(), and sync().

Referenced by main(), sync(), and sync().

◆ synchronize_global_id_set()

void libMesh::BoundaryInfo::synchronize_global_id_set ( )

Synchronizes the boundary_ids set on each processor to determine global_boundary_ids.

This may be necessary after use of renumber_*() functions, which perform only local operations, if get_global_boundary_ids() is to be used without a full regenerate_id_sets() call first.

Definition at line 432 of file boundary_info.C.

433{
434 // Handle global data
437 if (!_mesh->is_serial())
439
441}

References _boundary_ids, libMesh::ParallelObject::_communicator, _global_boundary_ids, _mesh, libMesh::MeshBase::_preparation, libMesh::MeshBase::Preparation::has_boundary_id_sets, libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), and libMesh::Parallel::Communicator::set_union().

Referenced by regenerate_id_sets(), and BoundaryInfoTest::testSelectiveRenumber().

◆ transfer_boundary_ids_from_children()

void libMesh::BoundaryInfo::transfer_boundary_ids_from_children ( const Elem *const  parent)

Update parent's boundary id list so that this information is consistent with its children.

This is useful when _children_on_boundary = true, and is used when the element is about to get coarsened i.e., in MeshRefinement::_coarsen_elements()

Specifically, when we coarsen an element whose children have different boundary ids. In such scenarios, the parent will inherit the children's boundaries if at least 50% them own a boundary while sharing the side of the parent.

Definition at line 2596 of file boundary_info.C.

2597{
2598 // this is only needed when we allow boundary to be associated with children elements
2599 // also, we only transfer the parent's boundary ids when we are actually coarsen the child element
2600 if (!_children_on_boundary ||
2601 !(!parent->active() && parent->refinement_flag() == Elem::COARSEN_INACTIVE))
2602 return;
2603
2604 // We assume that edges can be divided ito two pieces, while triangles and
2605 // quads can be divided into four smaller areas. This is double because we'll need
2606 // to convert the ratio of the children with given boundary id to a double.
2607 const double number_of_sides_on_children = std::pow(2, parent->dim()-1);
2608
2609 // In this case the input argument elem is the parent element. We need to check all of its sides
2610 // to grab any potential boundary ids.
2611 for (unsigned int side_i = 0; side_i < parent->n_sides(); ++side_i)
2612 {
2613 // An temporary storage to count how many times the children's boundaries occur. the general
2614 // consensus is that if the boundary occurs more than once we propagate upon coarsening. Otherwise,
2615 // it will get deleted.
2616 std::map<unsigned short int, unsigned short int> boundary_counts;
2617
2618 for (const auto & child_i : make_range(parent->n_children()))
2619 {
2620 // We only need to check the children which share the side
2621 if (parent->is_child_on_side(child_i, side_i))
2622 {
2623 // Fetching the boundary tags on the child's side
2624 for (const auto & pr : as_range(_boundary_side_id.equal_range(parent->child_ptr(child_i))))
2625 {
2626 // Making sure we are on the same boundary
2627 if (pr.second.first == side_i)
2628 ++boundary_counts[pr.second.second];
2629 }
2630 }
2631 }
2632
2633 // This is where the decision is made. If 50% of the children have the tags,
2634 // we propagate them upwards upon coarsening. Otherwise, they are deleted.
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);
2638 }
2639
2640 for (const auto & child_i : make_range(parent->n_children()))
2641 this->remove(parent->child_ptr(child_i));
2642}
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
@ COARSEN_INACTIVE
Definition elem.h:1452

References _boundary_side_id, _children_on_boundary, libMesh::Elem::active(), add_side(), libMesh::as_range(), libMesh::Elem::child_ptr(), libMesh::Elem::COARSEN_INACTIVE, libMesh::Elem::dim(), libMesh::Elem::is_child_on_side(), libMesh::make_range(), libMesh::Elem::n_children(), libMesh::Elem::n_sides(), libMesh::Elem::refinement_flag(), and remove().

Friends And Related Symbol Documentation

◆ MeshBase

friend class MeshBase
friend

Definition at line 60 of file boundary_info.h.

Member Data Documentation

◆ _boundary_edge_id

std::multimap<const Elem *, std::pair<unsigned short int, boundary_id_type> > libMesh::BoundaryInfo::_boundary_edge_id
private

◆ _boundary_ids

std::set<boundary_id_type> libMesh::BoundaryInfo::_boundary_ids
private

A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.

See _side_boundary_ids, _edge_boundary_ids, _node_boundary_ids, and _shellface_boundary_ids for sets containing IDs for only sides, edges, nodes, and shell faces, respectively.

This only contains information related to this process's local and ghosted elements

Definition at line 1028 of file boundary_info.h.

Referenced by add_edge(), add_edge(), add_node(), add_node(), add_shellface(), add_shellface(), add_side(), add_side(), clear(), get_boundary_ids(), n_boundary_ids(), operator=(), operator==(), regenerate_id_sets(), remove_edge_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), renumber_side_id(), sync(), and synchronize_global_id_set().

◆ _boundary_node_id

std::multimap<const Node *, boundary_id_type> libMesh::BoundaryInfo::_boundary_node_id
private

◆ _boundary_shellface_id

std::multimap<const Elem *, std::pair<unsigned short int, boundary_id_type> > libMesh::BoundaryInfo::_boundary_shellface_id
private

◆ _boundary_side_id

std::multimap<const Elem *, std::pair<unsigned short int, boundary_id_type> > libMesh::BoundaryInfo::_boundary_side_id
private

◆ _children_on_boundary

bool libMesh::BoundaryInfo::_children_on_boundary
private

◆ _communicator

const Parallel::Communicator& libMesh::ParallelObject::_communicator
protectedinherited

◆ _edge_boundary_ids

std::set<boundary_id_type> libMesh::BoundaryInfo::_edge_boundary_ids
private

Set of user-specified boundary IDs for edges only.

This is only relevant in 3D.

Note
_boundary_ids is the union of this set, _side_boundary_ids, _node_boundary_ids, and _shellface_boundary_ids.

This only contains information related to this process's local and ghosted elements

Definition at line 1062 of file boundary_info.h.

Referenced by add_edge(), add_edge(), clear(), get_edge_boundary_ids(), operator=(), operator==(), regenerate_id_sets(), remove_edge_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), and renumber_side_id().

◆ _es_id_to_name

std::map<boundary_id_type, std::string> libMesh::BoundaryInfo::_es_id_to_name
private

This structure maintains the mapping of named edge sets for file formats (Exodus, Gmsh) that support this.

This data is global in nature, meaning it should be an aggregate of information across processors

Definition at line 1112 of file boundary_info.h.

Referenced by clear(), edgeset_name(), get_edgeset_name(), get_edgeset_name_map(), get_id_by_name(), operator=(), operator==(), regenerate_id_sets(), remove_edge_id(), renumber_edge_id(), renumber_id(), and set_edgeset_name_map().

◆ _global_boundary_ids

std::set<boundary_id_type> libMesh::BoundaryInfo::_global_boundary_ids
private

A collection of user-specified boundary ids for sides, edges, nodes, and shell faces.

See _side_boundary_ids, _edge_boundary_ids, _node_boundary_ids, and _shellface_boundary_ids for sets containing IDs for only sides, edges, nodes, and shell faces, respectively.

Unlike _boundary_ids, this member should contain boundary ids from across all processors after the mesh is prepared

Definition at line 1040 of file boundary_info.h.

Referenced by get_global_boundary_ids(), operator=(), operator==(), remove_edge_id(), remove_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), renumber_side_id(), and synchronize_global_id_set().

◆ _mesh

MeshBase* libMesh::BoundaryInfo::_mesh
private

◆ _node_boundary_ids

std::set<boundary_id_type> libMesh::BoundaryInfo::_node_boundary_ids
private

Set of user-specified boundary IDs for nodes only.

Note
_boundary_ids is the union of this set, _edge_boundary_ids, _side_boundary_ids, and _shellface_boundary_ids.

This only contains information related to this process's local and ghosted elements

Definition at line 1073 of file boundary_info.h.

Referenced by add_node(), add_node(), clear(), get_node_boundary_ids(), operator=(), operator==(), regenerate_id_sets(), remove_edge_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), and renumber_side_id().

◆ _ns_id_to_name

std::map<boundary_id_type, std::string> libMesh::BoundaryInfo::_ns_id_to_name
private

This structure maintains the mapping of named node sets for file formats (Exodus, Gmsh) that support this.

This data is global in nature, meaning it should be an aggregate of information across processors

Definition at line 1103 of file boundary_info.h.

Referenced by clear(), get_id_by_name(), get_nodeset_name(), get_nodeset_name_map(), nodeset_name(), operator=(), operator==(), regenerate_id_sets(), remove_node_id(), renumber_id(), renumber_node_id(), and set_nodeset_name_map().

◆ _shellface_boundary_ids

std::set<boundary_id_type> libMesh::BoundaryInfo::_shellface_boundary_ids
private

Set of user-specified boundary IDs for shellfaces only.

This is only relevant for shell elements.

Note
_boundary_ids is the union of this set, _side_boundary_ids, _edge_boundary_ids, and _node_boundary_ids.

This only contains information related to this process's local and ghosted elements

Definition at line 1085 of file boundary_info.h.

Referenced by add_shellface(), add_shellface(), clear(), get_shellface_boundary_ids(), operator=(), operator==(), regenerate_id_sets(), remove_edge_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), and renumber_side_id().

◆ _side_boundary_ids

std::set<boundary_id_type> libMesh::BoundaryInfo::_side_boundary_ids
private

Set of user-specified boundary IDs for sides only.

Note
_boundary_ids is the union of this set, _edge_boundary_ids, _node_boundary_ids, and _shellface_boundary_ids.

This only contains information related to this process's local and ghosted elements

Definition at line 1051 of file boundary_info.h.

Referenced by add_side(), add_side(), clear(), get_side_boundary_ids(), operator=(), operator==(), regenerate_id_sets(), remove_edge_id(), remove_node_id(), remove_shellface_id(), remove_side_id(), renumber_edge_id(), renumber_id(), renumber_node_id(), renumber_shellface_id(), and renumber_side_id().

◆ _ss_id_to_name

std::map<boundary_id_type, std::string> libMesh::BoundaryInfo::_ss_id_to_name
private

This structure maintains the mapping of named side sets for file formats (Exodus, Gmsh) that support this.

This data is global in nature, meaning it should be an aggregate of information across processors

Definition at line 1094 of file boundary_info.h.

Referenced by clear(), get_id_by_name(), get_sideset_name(), get_sideset_name_map(), operator=(), operator==(), regenerate_id_sets(), remove_side_id(), renumber_id(), renumber_side_id(), set_sideset_name_map(), and sideset_name().

◆ invalid_id

const boundary_id_type libMesh::BoundaryInfo::invalid_id = -123
static

The documentation for this class was generated from the following files: