https://mooseframework.inl.gov
Classes | Functions
MooseMeshUtils Namespace Reference

Classes

struct  ElemSidePair
 

Functions

void mergeBoundaryIDsWithSameName (MeshBase &mesh)
 Merges the boundary IDs of boundaries that have the same names but different IDs. More...
 
void changeBoundaryId (MeshBase &mesh, const libMesh::boundary_id_type old_id, const libMesh::boundary_id_type new_id, bool delete_prev)
 Changes the old boundary ID to a new ID in the mesh. More...
 
void changeSubdomainId (MeshBase &mesh, const subdomain_id_type old_id, const subdomain_id_type new_id)
 Changes the old subdomain ID to a new ID in the mesh. More...
 
std::vector< BoundaryIDgetBoundaryIDs (const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
 Gets the boundary IDs with their names. More...
 
std::vector< BoundaryIDgetBoundaryIDs (const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown)
 Gets the boundary IDs with their names. More...
 
std::set< BoundaryIDgetBoundaryIDSet (const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown)
 Gets the boundary IDs into a set with their names. More...
 
BoundaryID getBoundaryID (const BoundaryName &boundary_name, const MeshBase &mesh)
 Gets the boundary ID associated with the given BoundaryName. More...
 
SubdomainID getSubdomainID (const SubdomainName &subdomain_name, const MeshBase &mesh)
 Gets the subdomain ID associated with the given SubdomainName. More...
 
std::vector< subdomain_id_typegetSubdomainIDs (const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
 Get the associated subdomainIDs for the subdomain names that are passed in. More...
 
std::set< subdomain_id_typegetSubdomainIDs (const libMesh::MeshBase &mesh, const std::set< SubdomainName > &subdomain_name)
 
Point meshCentroidCalculator (const MeshBase &mesh)
 Calculates the centroid of a MeshBase. More...
 
Point boundaryCentroidCalculator (const BoundaryName &boundary, MeshBase &mesh)
 Calculates the centroid of a boundary on a mesh. More...
 
RealVectorValue boundaryWeightedNormal (const BoundaryName &boundary, MeshBase &mesh)
 Calculates the side-volume weighted (side-vertex) average normal of a boundary on a mesh. More...
 
template<typename P , typename C >
void coordTransformFactor (const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
 Compute a coordinate transformation volume integration factor. More...
 
template<typename P , typename C >
computeDistanceToAxis (const P &point, const Point &origin, const RealVectorValue &direction)
 Computes the distance to a general axis. More...
 
Real computeMaxDistanceToAxis (const MeshBase &mesh, const Point &origin, const RealVectorValue &direction)
 Computes the maximum distance from all nodes of a mesh to a general axis. More...
 
template<typename P , typename C >
void coordTransformFactorRZGeneral (const P &point, const std::pair< Point, RealVectorValue > &axis, C &factor)
 Computes a coordinate transformation factor for a general axisymmetric axis. More...
 
void computeFiniteVolumeCoords (FaceInfo &fi, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
 
std::unordered_map< dof_id_type, dof_id_typegetExtraIDUniqueCombinationMap (const MeshBase &mesh, const std::set< SubdomainID > &block_ids, std::vector< ExtraElementIDName > extra_ids)
 Create a new set of element-wise IDs by finding unique combinations of existing extra ID values. More...
 
bool isCoPlanar (const std::vector< Point > &vec_pts, const Point plane_nvec, const Point fixed_pt)
 Decides whether all the Points of a vector of Points are in a plane that is defined by a normal vector and an inplane Point. More...
 
bool isCoPlanar (const std::vector< Point > &vec_pts, const Point plane_nvec)
 Decides whether all the Points of a vector of Points are in a plane with a given normal vector. More...
 
bool isCoPlanar (const std::vector< Point > &vec_pts)
 Decides whether all the Points of a vector of Points are coplanar. More...
 
SubdomainID getNextFreeSubdomainID (MeshBase &input_mesh)
 Checks input mesh and returns max(block ID) + 1, which represents a block ID that is not currently in use in the mesh. More...
 
BoundaryID getNextFreeBoundaryID (MeshBase &input_mesh)
 Checks input mesh and returns the largest boundary ID in the mesh plus one, which is a boundary ID in the mesh that is not currently in use. More...
 
bool hasSubdomainID (const MeshBase &input_mesh, const SubdomainID &id)
 Whether a particular subdomain ID exists in the mesh. More...
 
bool hasSubdomainName (const MeshBase &input_mesh, const SubdomainName &name)
 Whether a particular subdomain name exists in the mesh. More...
 
bool hasBoundaryID (const MeshBase &input_mesh, const BoundaryID id)
 Whether a particular boundary ID exists in the mesh. More...
 
bool hasBoundaryName (const MeshBase &input_mesh, const BoundaryName &name)
 Whether a particular boundary name exists in the mesh. More...
 
void makeOrderedNodeList (std::vector< std::pair< dof_id_type, dof_id_type >> &node_assm, std::vector< dof_id_type > &elem_id_list, std::vector< dof_id_type > &midpoint_node_list, std::vector< dof_id_type > &ordered_node_list, std::vector< dof_id_type > &ordered_elem_id_list)
 Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes based on connectivity. More...
 
void makeOrderedNodeList (std::vector< std::pair< dof_id_type, dof_id_type >> &node_assm, std::vector< dof_id_type > &elem_id_list, std::vector< dof_id_type > &ordered_node_list, std::vector< dof_id_type > &ordered_elem_id_list)
 Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes based on connectivity. More...
 
template<typename T , typename Q >
getIDFromName (const T &name)
 Converts a given name (BoundaryName or SubdomainName) that is known to only contain digits into a corresponding ID (BoundaryID or SubdomainID) and performs bounds checking to ensure that overflow doesn't happen. More...
 
void swapNodesInElem (Elem &elem, const unsigned int nd1, const unsigned int nd2)
 Swap two nodes within an element. More...
 
template<typename T >
void idSwapParametersProcessor (const std::string &class_name, const std::string &id_name, const std::vector< std::vector< T >> &id_swaps, std::vector< std::unordered_map< T, T >> &id_swap_pairs, const unsigned int row_index_shift=0)
 Reprocess the swap related input parameters to make pairs out of them to ease further processing. More...
 
void extraElemIntegerSwapParametersProcessor (const std::string &class_name, const unsigned int num_sections, const unsigned int num_integers, const std::vector< std::vector< std::vector< dof_id_type >>> &elem_integers_swaps, std::vector< std::unordered_map< dof_id_type, dof_id_type >> &elem_integers_swap_pairs)
 Reprocess the elem_integers_swaps into maps so they are easier to use. More...
 
std::unique_ptr< ReplicatedMesh > buildBoundaryMesh (const MeshBase &input_mesh, const boundary_id_type boundary_id)
 Build a lower-dimensional mesh from a boundary of an input mesh Note: The lower-dimensional mesh will only have one subdomain and one boundary. More...
 
std::unique_ptr< ReplicatedMesh > buildLoopBoundaryOf2DMesh (const MeshBase &input_mesh, const boundary_id_type boundary_id)
 Build a loop mesh of edges from the contiguous 2D boundary of 2D input mesh Note: The lower-dimensional mesh will only have one subdomain. More...
 
std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > buildBoundaryNodeToElemMap (const MeshBase &input_mesh, const boundary_id_type boundary_id)
 Build a map from the node ids to all element ids they are part of for the nodes on a particular nodeset. More...
 
std::set< dof_id_typegetBoundaryNodes (const MeshBase &mesh, const BoundaryID boundary_id)
 Get all the nodes on that particular boundary, whether a nodeset or a sideset. More...
 
void createSubdomainFromSidesets (MeshBase &mesh, std::vector< BoundaryName > boundary_names, const SubdomainID new_subdomain_id, const SubdomainName new_subdomain_name, const std::string type_name)
 Create a new subdomain by generating new side elements from a list of sidesets in a given mesh. More...
 
void convertBlockToMesh (MeshBase &source_mesh, MeshBase &target_mesh, const std::vector< SubdomainName > &target_blocks)
 Convert a list of blocks in a given mesh to a standalone new mesh. More...
 
void copyIntoMesh (MeshGenerator &mg, UnstructuredMesh &destination, const UnstructuredMesh &source, const bool avoid_merging_subdomains, const bool avoid_merging_boundaries, const Parallel::Communicator &communicator)
 Helper function for copying one mesh into another. More...
 
void buildPolyLineMesh (MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const std::vector< unsigned int > &nums_edges_between_points)
 Generates meshes from edges connecting a list of points. More...
 
void buildPolyLineMesh (MeshBase &mesh, const std::vector< Point > &points, const std::vector< Point > &mid_points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const std::vector< unsigned int > &nums_edges_between_points)
 Generates meshes from edges connecting a list of points, with optional midpoints to produce Edge3 elements so as to enable quadratic meshing. More...
 
void buildPolyLineMesh (MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const Real max_elem_size)
 Generates meshes from edges connecting a list of points. More...
 
void addExternalBoundary (MeshBase &mesh, const BoundaryID extern_bid, bool &has_external_bid)
 Adds a sideset for the external boundary of the mesh (e.g. More...
 
void mergeBoundaryIDsWithSameName (MeshBase &mesh)
 
void changeBoundaryId (MeshBase &mesh, const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
 
BoundaryID getBoundaryID (const BoundaryName &boundary_name, const MeshBase &mesh)
 
SubdomainID getSubdomainID (const SubdomainName &subdomain_name, const MeshBase &mesh)
 
void changeSubdomainId (MeshBase &mesh, const subdomain_id_type old_id, const subdomain_id_type new_id)
 
Point meshCentroidCalculator (const MeshBase &mesh)
 
Point boundaryCentroidCalculator (const BoundaryName &boundary, MeshBase &mesh)
 
RealVectorValue boundaryWeightedNormal (const BoundaryName &boundary, MeshBase &mesh)
 
Real computeMaxDistanceToAxis (const MeshBase &mesh, const Point &origin, const RealVectorValue &direction)
 
std::unordered_map< dof_id_type, dof_id_typegetExtraIDUniqueCombinationMap (const MeshBase &mesh, const std::set< SubdomainID > &block_ids, std::vector< ExtraElementIDName > extra_ids)
 
bool isCoPlanar (const std::vector< Point > &vec_pts, const Point plane_nvec, const Point fixed_pt)
 
bool isCoPlanar (const std::vector< Point > &vec_pts, const Point plane_nvec)
 
bool isCoPlanar (const std::vector< Point > &vec_pts)
 
SubdomainID getNextFreeSubdomainID (MeshBase &input_mesh)
 
BoundaryID getNextFreeBoundaryID (MeshBase &input_mesh)
 
bool hasSubdomainID (const MeshBase &input_mesh, const SubdomainID &id)
 
bool hasSubdomainName (const MeshBase &input_mesh, const SubdomainName &name)
 
bool hasBoundaryID (const MeshBase &input_mesh, const BoundaryID id)
 
bool hasBoundaryName (const MeshBase &input_mesh, const BoundaryName &name)
 
void swapNodesInElem (Elem &elem, const unsigned int nd1, const unsigned int nd2)
 
std::unique_ptr< ReplicatedMeshbuildBoundaryMesh (const MeshBase &input_mesh, const boundary_id_type boundary_id)
 
std::unique_ptr< ReplicatedMeshbuildLoopBoundaryOf2DMesh (const MeshBase &input_mesh, const boundary_id_type boundary_id)
 
std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > buildBoundaryNodeToElemMap (const MeshBase &input_mesh, const boundary_id_type boundary_id)
 
std::set< dof_id_typegetBoundaryNodes (const MeshBase &mesh, const BoundaryID boundary_id)
 
void createSubdomainFromSidesets (MeshBase &mesh, std::vector< BoundaryName > boundary_names, const SubdomainID new_subdomain_id, const SubdomainName new_subdomain_name, const std::string type_name)
 
void convertBlockToMesh (MeshBase &source_mesh, MeshBase &target_mesh, const std::vector< SubdomainName > &target_blocks)
 
void copyIntoMesh (MeshGenerator &mg, UnstructuredMesh &destination, const UnstructuredMesh &source, const bool avoid_merging_subdomains, const bool avoid_merging_boundaries, const Parallel::Communicator &communicator)
 
void buildPolyLineMesh (MeshBase &mesh, const std::vector< Point > &points, const std::vector< Point > &mid_points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const std::vector< unsigned int > &nums_edges_between_points)
 
void buildPolyLineMesh (MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const std::vector< unsigned int > &nums_edges_between_points)
 
void buildPolyLineMesh (MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const Real max_elem_size)
 
void addExternalBoundary (MeshBase &mesh, const BoundaryID extern_bid, bool &has_external_bid)
 

Function Documentation

◆ addExternalBoundary() [1/2]

void MooseMeshUtils::addExternalBoundary ( MeshBase &  mesh,
const BoundaryID  extern_bid,
bool &  has_external_bid 
)

Adds a sideset for the external boundary of the mesh (e.g.

all element sides with no neighbors)

Parameters
meshthe mesh to modify
extern_bidthe ID to assign to the external boundary
has_external_bidfalse if all elements of the mesh are internal (for example a sphere shell)

Referenced by XYTriangleBoundaryLayerGenerator::generate(), XYDelaunayGenerator::generate(), and SurfaceSubdomainsDelaunayRemesher::generate().

◆ addExternalBoundary() [2/2]

void MooseMeshUtils::addExternalBoundary ( MeshBase mesh,
const BoundaryID  extern_bid,
bool &  has_external_bid 
)

Definition at line 1549 of file MooseMeshUtils.C.

1550 {
1551  auto & binfo = mesh.get_boundary_info();
1552  for (const auto & elem : mesh.active_element_ptr_range())
1553  for (const auto & i_side : elem->side_index_range())
1554  if (elem->neighbor_ptr(i_side) == nullptr)
1555  {
1556  has_external_bid = true;
1557  binfo.add_side(elem, i_side, extern_bid);
1558  }
1559 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)

◆ boundaryCentroidCalculator() [1/2]

Point MooseMeshUtils::boundaryCentroidCalculator ( const BoundaryName &  boundary,
MeshBase &  mesh 
)

Calculates the centroid of a boundary on a mesh.

Parameters
boundaryboundary to compute the centroid of
meshinput mesh holding the boundary whose centroid needs to be calculated
Returns
a Point corresponding to the boundary centroid

Referenced by BSplineCurveGenerator::endPoint(), and BSplineCurveGenerator::startPoint().

◆ boundaryCentroidCalculator() [2/2]

Point MooseMeshUtils::boundaryCentroidCalculator ( const BoundaryName &  boundary,
MeshBase mesh 
)

Definition at line 297 of file MooseMeshUtils.C.

298 {
299  // Need boundaries to be synchronized
302  BoundaryInfo & mesh_boundary_info = mesh.get_boundary_info();
303  boundary_id_type boundary_id = mesh_boundary_info.get_id_by_name(boundary);
304  const auto side_list = mesh_boundary_info.build_side_list();
305 
306  // Initialize sums
307  Real volume_sum = 0;
308  Point volume_weighted_centroid_sum(0, 0, 0);
309 
310  for (const auto & [eid, side_i, bid] : side_list)
311  {
312  if (bid != boundary_id)
313  continue;
314 
315  // Get the side
316  const auto elem = mesh.elem_ptr(eid);
317  const auto side = elem->side_ptr(side_i);
318 
319  volume_sum += side->volume();
320  volume_weighted_centroid_sum += side->volume() * side->true_centroid();
321  }
322  // Sum across processes
323  mesh.comm().sum(volume_weighted_centroid_sum);
324  mesh.comm().sum(volume_sum);
325 
326  return volume_weighted_centroid_sum / volume_sum;
327 }
void synchronize_global_id_set()
MeshBase & mesh
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
Preparation preparation() const
boundary_id_type get_id_by_name(std::string_view name) const
int8_t boundary_id_type
virtual const Elem * elem_ptr(const dof_id_type i) const=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0

◆ boundaryWeightedNormal() [1/2]

RealVectorValue MooseMeshUtils::boundaryWeightedNormal ( const BoundaryName &  boundary,
MeshBase &  mesh 
)

Calculates the side-volume weighted (side-vertex) average normal of a boundary on a mesh.

Parameters
boundaryboundary to compute the weighted normal of
meshinput mesh holding the boundary whose averaged normal needs to be calculated
Returns
a Point corresponding to the boundary weighted normal

Referenced by BSplineCurveGenerator::endDirection(), and BSplineCurveGenerator::startDirection().

◆ boundaryWeightedNormal() [2/2]

RealVectorValue MooseMeshUtils::boundaryWeightedNormal ( const BoundaryName &  boundary,
MeshBase mesh 
)

Definition at line 330 of file MooseMeshUtils.C.

331 {
332  // Need boundaries to be synchronized
335  BoundaryInfo & mesh_boundary_info = mesh.get_boundary_info();
336  boundary_id_type boundary_id = mesh_boundary_info.get_id_by_name(boundary);
337  const auto side_list = mesh_boundary_info.build_side_list();
338 
339  // Initialize sums
340  Real volume_sum = 0;
341  RealVectorValue volume_weighted_normal_sum(0, 0, 0);
342 
343  for (const auto & [eid, side_i, bid] : side_list)
344  {
345  if (bid != boundary_id)
346  continue;
347 
348  // Get the side
349  const auto elem = mesh.elem_ptr(eid);
350  const auto side = elem->side_ptr(side_i);
351 
352  volume_sum += side->volume();
353  volume_weighted_normal_sum += side->volume() * elem->side_vertex_average_normal(side_i);
354  }
355  // Sum across processes
356  mesh.comm().sum(volume_weighted_normal_sum);
357  mesh.comm().sum(volume_sum);
358 
359  return volume_weighted_normal_sum / volume_sum;
360 }
void synchronize_global_id_set()
MeshBase & mesh
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
Preparation preparation() const
boundary_id_type get_id_by_name(std::string_view name) const
int8_t boundary_id_type
virtual const Elem * elem_ptr(const dof_id_type i) const=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0

◆ buildBoundaryMesh() [1/2]

std::unique_ptr<ReplicatedMesh> MooseMeshUtils::buildBoundaryMesh ( const MeshBase &  input_mesh,
const boundary_id_type  boundary_id 
)

Build a lower-dimensional mesh from a boundary of an input mesh Note: The lower-dimensional mesh will only have one subdomain and one boundary.

Error will be thrown if the mesh does not have the boundary. This function works only with replicated mesh, for similar functionality with distributed meshes, please refer to LowerDBlockFromSidesetGenerator generator.

Parameters
input_meshThe input mesh
boundary_idThe boundary id

◆ buildBoundaryMesh() [2/2]

std::unique_ptr<ReplicatedMesh> MooseMeshUtils::buildBoundaryMesh ( const MeshBase input_mesh,
const boundary_id_type  boundary_id 
)

Definition at line 697 of file MooseMeshUtils.C.

698 {
699  if (!input_mesh.is_serial())
700  ::mooseError("Input mesh should be serialized for extracting the boundary mesh.\nInput mesh:" +
701  input_mesh.get_info());
702  auto poly_mesh = std::make_unique<ReplicatedMesh>(input_mesh.comm());
703 
704  auto side_list = input_mesh.get_boundary_info().build_side_list();
705 
706  std::unordered_map<dof_id_type, dof_id_type> old_new_node_map;
707  for (const auto & [eid, side_i, bid] : side_list)
708  {
709  if (bid != boundary_id)
710  continue;
711 
712  // Get the side
713  const auto elem = input_mesh.elem_ptr(eid);
714  const auto side = elem->side_ptr(side_i);
715  auto side_elem = elem->build_side_ptr(side_i);
716  auto copy = side_elem->build(side_elem->type());
717 
718  for (const auto i : side_elem->node_index_range())
719  {
720  auto & n = side_elem->node_ref(i);
721 
722  if (old_new_node_map.count(n.id()))
723  copy->set_node(i, poly_mesh->node_ptr(old_new_node_map[n.id()]));
724  else
725  {
726  Node * node = poly_mesh->add_point(side_elem->point(i));
727  copy->set_node(i, node);
728  old_new_node_map[n.id()] = node->id();
729  }
730  }
731  poly_mesh->add_elem(copy.release());
732  }
733  poly_mesh->skip_partitioning(true);
734  poly_mesh->prepare_for_use();
735  if (poly_mesh->n_elem() == 0)
736  mooseError("The input mesh to extract the boundary from does not have a boundary with id ",
737  boundary_id,
738  ".\n",
739  input_mesh);
740 
741  return poly_mesh;
742 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
virtual bool is_serial() const
dof_id_type id() const
virtual const Elem * elem_ptr(const dof_id_type i) const=0
std::string get_info(const unsigned int verbosity=0, const bool global=true) const
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0

◆ buildBoundaryNodeToElemMap() [1/2]

std::unordered_map<dof_id_type, std::unordered_set<dof_id_type> > MooseMeshUtils::buildBoundaryNodeToElemMap ( const MeshBase &  input_mesh,
const boundary_id_type  boundary_id 
)

Build a map from the node ids to all element ids they are part of for the nodes on a particular nodeset.

Parameters
input_meshThe input mesh to get the map for
boundary_idThe boundary id of interest

◆ buildBoundaryNodeToElemMap() [2/2]

std::unordered_map<dof_id_type, std::unordered_set<dof_id_type> > MooseMeshUtils::buildBoundaryNodeToElemMap ( const MeshBase input_mesh,
const boundary_id_type  boundary_id 
)

Definition at line 960 of file MooseMeshUtils.C.

Referenced by buildLoopBoundaryOf2DMesh().

961 {
962  if (!input_mesh.is_serial())
963  ::mooseError(
964  "Input 2D mesh should be serialized for extracting the loop boundary mesh.\nInput mesh:" +
965  input_mesh.get_info());
966 
967  // Get all nodes on that boundary
968  // Boundary ID might be a sideset or a nodeset, get nodes regardless
969  const auto particular_node_ids = getBoundaryNodes(input_mesh, boundary_id);
970 
971  std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> nid_to_eids_map;
972  // Fill the map from looping over elements
973  for (const auto & elem :
974  as_range(input_mesh.active_elements_begin(), input_mesh.active_elements_end()))
975  {
976  for (const auto & nd : elem->node_ref_range())
977  {
978  // Only add the element id if the node is on the boundary
979  if (!particular_node_ids.count(nd.id()))
980  continue;
981 
982  auto & elem_ids = nid_to_eids_map[nd.id()];
983  elem_ids.insert(elem->id());
984  }
985  }
986  return nid_to_eids_map;
987 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::set< dof_id_type > getBoundaryNodes(const MeshBase &mesh, const BoundaryID boundary_id)
virtual bool is_serial() const
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::string get_info(const unsigned int verbosity=0, const bool global=true) const

◆ buildLoopBoundaryOf2DMesh() [1/2]

std::unique_ptr<ReplicatedMesh> MooseMeshUtils::buildLoopBoundaryOf2DMesh ( const MeshBase &  input_mesh,
const boundary_id_type  boundary_id 
)

Build a loop mesh of edges from the contiguous 2D boundary of 2D input mesh Note: The lower-dimensional mesh will only have one subdomain.

An error will be thrown if the mesh does not have the boundary. Note: currently, the boundary_id must be a nodeset!

Parameters
input_meshThe input mesh
boundary_idThe boundary id

Referenced by SurfaceSubdomainsDelaunayRemesher::General2DDelaunay().

◆ buildLoopBoundaryOf2DMesh() [2/2]

std::unique_ptr<ReplicatedMesh> MooseMeshUtils::buildLoopBoundaryOf2DMesh ( const MeshBase input_mesh,
const boundary_id_type  boundary_id 
)

Definition at line 745 of file MooseMeshUtils.C.

746 {
747  if (!input_mesh.is_serial())
748  ::mooseError(
749  "Input 2D mesh should be serialized for extracting the loop boundary mesh.\nInput mesh:" +
750  input_mesh.get_info());
751  auto edge_mesh = std::make_unique<ReplicatedMesh>(input_mesh.comm());
752  auto side_list = input_mesh.get_boundary_info().build_side_list();
753  std::set<BoundaryInfo::BCTuple> visited;
754  bool already_seen_this_side_tuple = false;
755  BoundaryInfo::BCTuple first_side_visited = {libMesh::invalid_uint, 0, 0};
756 
757  // Helps move elem to elem at a given node
758  const auto node_to_elem_map = buildBoundaryNodeToElemMap(input_mesh, boundary_id);
759  // Helps check if a node is part of a boundary
760  const auto & node_to_bids = input_mesh.get_boundary_info().get_nodeset_map();
761 
762  // Traverse from the first side (edge) in the side_list that matches the boundary_id
763  for (const auto & bside : side_list)
764  {
765  if (std::get<2>(bside) != boundary_id)
766  continue;
767 
768  // Check that we are not starting 'another' loop
769  if (bside != first_side_visited)
770  {
771  if (visited.size() && !visited.count(bside))
772  mooseWarning(
773  "Boundary " + std::to_string(boundary_id) +
774  " is not a (contiguous) loop. Boundary side: (" + Moose::stringify(bside) +
775  ") was not visited after a single pass around the boundary. Boundary sides visited: " +
776  Moose::stringify(visited));
777  else if (visited.empty())
778  first_side_visited = bside;
779  else
780  continue;
781  }
782 
783  // Form the element to be able to find the side
784  // These three variables will be updated while traversing the loop boundary
785  const Elem * elem = input_mesh.elem_ptr(std::get<0>(bside));
786  auto current_side = std::get<1>(bside);
787  auto side_elem = elem->build_side_ptr(current_side);
788 
789  // 3D elements should not be part of this boundary
790  if (elem->dim() != 2)
791  mooseError(
792  "Finding the loop boundary of a 2D mesh cannot be done with non-2D elements such as ",
793  *elem);
794 
795  // Start from node 0 of the side (on the boundary), set the next node as the other node
796  // one that side, and keep going from tht next node
797  bool looped_back = false;
798  const Node * starting_node = side_elem->node_ptr(0);
799  const auto new_mesh_starting_node = edge_mesh->add_point(side_elem->point(0));
800  Node * new_first_node = new_mesh_starting_node;
801  [[maybe_unused]] dof_id_type first_node_index = starting_node->id();
802  dof_id_type second_node_index = input_mesh.node_ptr(side_elem->node_id(1))->id();
803 
804  while (!looped_back && !already_seen_this_side_tuple)
805  {
806  if (MooseUtils::absoluteFuzzyEqual(input_mesh.point(second_node_index),
807  Point(*starting_node)))
808  looped_back = true;
809 
810  // Get the opposite node (the next node) and add it to the edge mesh
811  Node * new_second_node = looped_back
812  ? new_mesh_starting_node
813  : edge_mesh->add_point(input_mesh.point(second_node_index));
814 
815  // Add a copy of the edge side element to the mesh
816  side_elem = elem->build_side_ptr(current_side);
817  auto copy = side_elem->build(side_elem->type());
818  copy->set_node(0, new_first_node);
819  copy->set_node(1, new_second_node);
820  edge_mesh->add_elem(copy.release());
821 
822  // Make this side as 'visited'
823  std::tuple<dof_id_type, unsigned short int, boundary_id_type> bc_tuple = {
824  elem->id(), current_side, boundary_id};
825  const auto & visit_iter = visited.insert(bc_tuple);
826  if (!looped_back && !visit_iter.second)
827  already_seen_this_side_tuple = true;
828 
829  // Find the next element and side_elem
830  auto & connected_elems = libmesh_map_find(node_to_elem_map, second_node_index);
831  bool found_match = false;
832  const auto current_eid = elem->id();
833 
834  for (const auto eid : connected_elems)
835  {
836  mooseAssert(!found_match,
837  "We should only find one node on a connected element on this boundary");
838  if (eid != current_eid)
839  {
840  // Update the element (on the input mesh)
841  elem = input_mesh.elem_ptr(eid);
842 
843  // Find the side and the opposite node index in that side
844  for (const auto si : elem->side_index_range())
845  {
846  // Check that second node is on the side
847  const auto local_second_node_index =
848  elem->get_node_index(input_mesh.node_ptr(second_node_index));
849  // 2 sides should match this
850  if (elem->is_node_on_side(local_second_node_index, si))
851  {
852  // Only one side should be on the same boundary (node is connected to two elements)
853  // Form a bc_tuple and check the list of boundary sides
854  std::tuple<dof_id_type, unsigned short int, boundary_id_type> side_bc_tuple = {
855  elem->id(), si, boundary_id};
856 
857  if (std::find(side_list.begin(), side_list.end(), side_bc_tuple) == side_list.end())
858  continue;
859 
860  // We are on the right boundary, just need to get the other node
861  for (const auto local_side_node_id : elem->nodes_on_side(si))
862  {
863  const auto side_node_id = elem->node_id(local_side_node_id);
864 
865  // Skip current node (use global index to compare)
866  if (side_node_id == second_node_index)
867  continue;
868  mooseAssert(side_node_id != first_node_index,
869  "Somehow looped back in a single element");
870 
871  current_side = si;
872  second_node_index = side_node_id;
873  found_match = true;
874  break;
875  }
876  }
877  // No need to examine more sides
878  if (found_match)
879  break;
880  }
881 
882  // No need to examine more elements
883  if (found_match)
884  break;
885  }
886  // next node could be on the same element, just moving on to the next side
887  else if (connected_elems.size() == 1)
888  {
889  elem = input_mesh.elem_ptr(eid);
890  const auto local_second_node_index =
891  elem->get_node_index(input_mesh.node_ptr(second_node_index));
892 
893  // Move on to the next side
894  for (const auto si : elem->side_index_range())
895  if (si != current_side && elem->is_node_on_side(local_second_node_index, si))
896  {
897  // Check all nodes on that next side
898  for (const auto local_side_node_id : elem->nodes_on_side(si))
899  {
900  const auto side_node_id = elem->node_id(local_side_node_id);
901  // Skip current node
902  if (side_node_id == second_node_index)
903  continue;
904  mooseAssert((side_node_id != first_node_index) ||
905  (side_list.size() == elem->n_sides()),
906  "Somehow looped back in a single element");
907 
908  // Check all the boundaries the other node (on the edge side) is part of
909  const auto bids_range = node_to_bids.equal_range(input_mesh.node_ptr(side_node_id));
910 
911  for (auto iter = bids_range.first; iter != bids_range.second; iter++)
912  if (iter->second == boundary_id)
913  {
914  current_side = si;
915  second_node_index = side_node_id;
916  found_match = true;
917  }
918  }
919 
920  // no need to examine other sides
921  if (found_match)
922  break;
923  }
924  }
925  }
926 
927  // Set current node to opposite node of new element
928  // NOTE: do not use new_first_node or new_second_node to search in the input mesh!
929  new_first_node = new_second_node;
930  first_node_index = second_node_index;
931 
932  // Handle loop ending criterion
933  if (!found_match)
934  {
935  mooseWarning("Search for next element in loop boundary failed. Is boundary '" +
936  std::to_string(boundary_id) + "' of mesh ",
937  input_mesh,
938  " a loop boundary?");
939  break;
940  }
941  }
942  }
943 
944  if (already_seen_this_side_tuple)
945  mooseWarning("Boundary " + std::to_string(boundary_id) +
946  " seems to have cycles. A single-cycle loop should be used");
947 
948  edge_mesh->skip_partitioning(true);
949  edge_mesh->prepare_for_use();
950  if (edge_mesh->n_elem() == 0)
951  mooseError("The input mesh to extract the boundary from does not have a boundary with id ",
952  boundary_id,
953  "\n",
954  input_mesh);
955 
956  return edge_mesh;
957 }
std::tuple< dof_id_type, unsigned short int, boundary_id_type > BCTuple
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
const unsigned int invalid_uint
unsigned int get_node_index(const Node *node_ptr) const
IntRange< unsigned short > side_index_range() const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:345
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const=0
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
virtual bool is_serial() const
dof_id_type id() const
std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > buildBoundaryNodeToElemMap(const MeshBase &input_mesh, const boundary_id_type boundary_id)
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
virtual const Elem * elem_ptr(const dof_id_type i) const=0
virtual unsigned int n_sides() const=0
std::string get_info(const unsigned int verbosity=0, const bool global=true) const
virtual unsigned short dim() const=0
virtual const Point & point(const dof_id_type i) const=0
virtual const Node * node_ptr(const dof_id_type i) const=0
const std::multimap< const Node *, boundary_id_type > & get_nodeset_map() const
dof_id_type node_id(const unsigned int i) const
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const=0
uint8_t dof_id_type

◆ buildPolyLineMesh() [1/6]

void MooseMeshUtils::buildPolyLineMesh ( MeshBase &  mesh,
const std::vector< Point > &  points,
const bool  loop,
const BoundaryName &  start_boundary,
const BoundaryName &  end_boundary,
const std::vector< unsigned int > &  nums_edges_between_points 
)

Generates meshes from edges connecting a list of points.

Parameters
meshThe mesh to be built
pointsThe list of points defining the polyline
loopWhether the polyline is a closed loop
start_boundaryThe boundary name to assign to the start of the polyline (if not a loop)
end_boundaryThe boundary name to assign to the end of the polyline (if not a loop)
nums_edges_between_pointsThe numbers of edges to create between each pair of points (if only one number is given, it is used for all point pairs)

Referenced by BoundaryLayerUtils::buildBoundaryLayerRing(), SurfaceSubdomainsDelaunayRemesher::General2DDelaunay(), and PolyLineMeshGenerator::generate().

◆ buildPolyLineMesh() [2/6]

void MooseMeshUtils::buildPolyLineMesh ( MeshBase &  mesh,
const std::vector< Point > &  points,
const std::vector< Point > &  mid_points,
const bool  loop,
const BoundaryName &  start_boundary,
const BoundaryName &  end_boundary,
const std::vector< unsigned int > &  nums_edges_between_points 
)

Generates meshes from edges connecting a list of points, with optional midpoints to produce Edge3 elements so as to enable quadratic meshing.

If mid_points is empty, Edge2 elements are produced.

Parameters
meshThe mesh to be built
pointsThe list of points defining the polyline
mid_pointsThe optional list of midpoints corresponding to the segments for quadratic elements. if provided, it must contains exactly one midpoint per segment and nums_edges_between_points must be unity for every segment.
loopWhether the polyline is a closed loop
start_boundaryThe boundary name to assign to the start of the polyline (if not a loop)
end_boundaryThe boundary name to assign to the end of the polyline (if not a loop)
nums_edges_between_pointsThe numbers of edges to create between each pair of points (if only one number is given, it is used for all point pairs)

◆ buildPolyLineMesh() [3/6]

void MooseMeshUtils::buildPolyLineMesh ( MeshBase &  mesh,
const std::vector< Point > &  points,
const bool  loop,
const BoundaryName &  start_boundary,
const BoundaryName &  end_boundary,
const Real  max_elem_size 
)

Generates meshes from edges connecting a list of points.

Note that we do not support max_elem_size and quadratic mid points at the same time as we cannot pre-determine the number of mid points needed for quadratic elements when max_elem_size is specified.

Parameters
meshThe mesh to be built
pointsThe list of points defining the polyline
loopWhether the polyline is a closed loop
start_boundaryThe boundary name to assign to the start of the polyline (if not a loop)
end_boundaryThe boundary name to assign to the end of the polyline (if not a loop)
max_elem_sizeThe maximum element size for the mesh

◆ buildPolyLineMesh() [4/6]

void MooseMeshUtils::buildPolyLineMesh ( MeshBase mesh,
const std::vector< Point > &  points,
const std::vector< Point > &  mid_points,
const bool  loop,
const BoundaryName &  start_boundary,
const BoundaryName &  end_boundary,
const std::vector< unsigned int > &  nums_edges_between_points 
)

Definition at line 1403 of file MooseMeshUtils.C.

1410 {
1411  mooseAssert(nums_edges_between_points.size() == 1 ||
1412  nums_edges_between_points.size() == points.size() - 1 + loop,
1413  "nums_edges_between_points must be either a single value or have the same number of "
1414  "entries as segments defined by the points.");
1415  mooseAssert(
1416  mid_points.size() == 0 || mid_points.size() == points.size() - (loop ? 0 : 1),
1417  "mid_points must be either empty or have the consistent number of entries as points.");
1418  mooseAssert(
1419  mid_points.size() == 0 ||
1420  (nums_edges_between_points.size() == 1 && nums_edges_between_points.front() == 1) ||
1421  (nums_edges_between_points.size() == points.size() - 1 + loop &&
1422  std::all_of(nums_edges_between_points.begin(),
1423  nums_edges_between_points.end(),
1424  [](unsigned int n) { return n == 1; })),
1425  "mid_points can only be provided if each segment has exactly one edge.");
1426 
1427  const auto n_points = points.size();
1428  for (auto i : make_range(n_points))
1429  {
1430  const auto & num_edges_between_points =
1431  (nums_edges_between_points.size() == 1)
1432  ? nums_edges_between_points[0]
1433  : (i == nums_edges_between_points.size() ? 0 : nums_edges_between_points[i]);
1434 
1435  Point p = points[i];
1436  const auto pt_counter = (nums_edges_between_points.size() == 1)
1437  ? i
1438  : std::accumulate(nums_edges_between_points.begin(),
1439  nums_edges_between_points.begin() + i,
1440  0);
1441  mesh.add_point(
1442  p, nums_edges_between_points.size() == 1 ? (i * num_edges_between_points) : pt_counter);
1443 
1444  if (num_edges_between_points > 1)
1445  {
1446  if (!loop && (i + 1) == n_points)
1447  break;
1448 
1449  const auto ip1 = (i + 1) % n_points;
1450  const Point pvec = (points[ip1] - p) / num_edges_between_points;
1451 
1452  for (auto j : make_range(1u, num_edges_between_points))
1453  {
1454  p += pvec;
1455  mesh.add_point(
1456  p,
1457  (nums_edges_between_points.size() == 1 ? (i * num_edges_between_points) : pt_counter) +
1458  j);
1459  }
1460  }
1461  }
1462  // Add mid points if applicable. When mid points are provided, each segment has exactly one edge,
1463  // so the midpoint node ids follow the vertex node ids.
1464  for (const auto & i : make_range(mid_points.size()))
1465  mesh.add_point(mid_points[i], n_points + i);
1466 
1467  const auto n_segments = loop ? n_points : (n_points - 1);
1468  const auto n_elem =
1469  nums_edges_between_points.size() == 1
1470  ? n_segments * nums_edges_between_points[0]
1471  : std::accumulate(nums_edges_between_points.begin(), nums_edges_between_points.end(), 0);
1472  const auto max_nodes =
1473  (nums_edges_between_points.size() == 1 ? n_segments * nums_edges_between_points[0]
1474  : std::accumulate(nums_edges_between_points.begin(),
1475  nums_edges_between_points.end(),
1476  0)) +
1477  (loop ? 0 : 1);
1478  for (auto i : make_range(n_elem))
1479  {
1480  std::unique_ptr<Elem> elem;
1481  if (mid_points.size())
1482  {
1483  elem = std::make_unique<Edge3>();
1484  elem->set_node(2, mesh.node_ptr(n_points + i));
1485  }
1486  else
1487  elem = Elem::build(EDGE2);
1488  const auto ip1 = (i + 1) % max_nodes;
1489  elem->set_node(0, mesh.node_ptr(i));
1490  elem->set_node(1, mesh.node_ptr(ip1));
1491  elem->set_id() = i;
1492  mesh.add_elem(std::move(elem));
1493  }
1494 
1495  if (!loop)
1496  {
1498  std::vector<BoundaryName> bdy_names{start_boundary, end_boundary};
1499  std::vector<boundary_id_type> ids = MooseMeshUtils::getBoundaryIDs(mesh, bdy_names, true);
1500  bi.add_side(mesh.elem_ptr(0), 0, ids[0]);
1501  bi.add_side(mesh.elem_ptr(n_elem - 1), 1, ids[1]);
1502  }
1503  else
1504  mooseAssert(start_boundary.empty() && end_boundary.empty(),
1505  "Cannot assign start/end boundaries on a looped polyline.");
1506 
1508 }
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
virtual Elem * add_elem(Elem *e)=0
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
virtual const Elem * elem_ptr(const dof_id_type i) const=0
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
IntRange< T > make_range(T beg, T end)
virtual const Node * node_ptr(const dof_id_type i) const=0

◆ buildPolyLineMesh() [5/6]

void MooseMeshUtils::buildPolyLineMesh ( MeshBase mesh,
const std::vector< Point > &  points,
const bool  loop,
const BoundaryName &  start_boundary,
const BoundaryName &  end_boundary,
const std::vector< unsigned int > &  nums_edges_between_points 
)

Definition at line 1511 of file MooseMeshUtils.C.

1517 {
1519  mesh, points, {}, loop, start_boundary, end_boundary, nums_edges_between_points);
1520 }
void buildPolyLineMesh(MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const Real max_elem_size)

◆ buildPolyLineMesh() [6/6]

void MooseMeshUtils::buildPolyLineMesh ( MeshBase mesh,
const std::vector< Point > &  points,
const bool  loop,
const BoundaryName &  start_boundary,
const BoundaryName &  end_boundary,
const Real  max_elem_size 
)

Definition at line 1523 of file MooseMeshUtils.C.

Referenced by buildPolyLineMesh().

1529 {
1530  std::vector<unsigned int> nums_edges_between_points;
1531  const auto n_points = points.size();
1532  for (auto i : make_range(n_points))
1533  {
1534  if (!loop && (i + 1) == n_points)
1535  break;
1536 
1537  const auto ip1 = (i + 1) % n_points;
1538  const Real length = (points[ip1] - points[i]).norm();
1539  const unsigned int n_elems = std::max(
1540  static_cast<unsigned int>(std::ceil(length / max_elem_size)), static_cast<unsigned int>(1));
1541  nums_edges_between_points.push_back(n_elems);
1542  }
1543 
1545  mesh, points, {}, loop, start_boundary, end_boundary, nums_edges_between_points);
1546 }
void buildPolyLineMesh(MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const Real max_elem_size)
auto max(const L &left, const R &right)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm(const T &a)
IntRange< T > make_range(T beg, T end)

◆ changeBoundaryId() [1/2]

void MooseMeshUtils::changeBoundaryId ( MeshBase &  mesh,
const libMesh::boundary_id_type  old_id,
const libMesh::boundary_id_type  new_id,
bool  delete_prev 
)

Changes the old boundary ID to a new ID in the mesh.

Parameters
meshthe mesh
old_idthe old boundary id
new_idthe new boundary id
delete_prevwhether to delete the previous boundary id from the mesh

Referenced by MeshExtruderGenerator::changeID(), FillBetweenSidesetsGenerator::generate(), XYDelaunayGenerator::generate(), MooseMeshElementConversionUtils::transitionLayerGenerator(), and MeshTriangulationUtils::triangulateWithDelaunay().

◆ changeBoundaryId() [2/2]

void MooseMeshUtils::changeBoundaryId ( MeshBase mesh,
const boundary_id_type  old_id,
const boundary_id_type  new_id,
bool  delete_prev 
)

Definition at line 65 of file MooseMeshUtils.C.

69 {
70  // Get a reference to our BoundaryInfo object, we will use it several times below...
71  BoundaryInfo & boundary_info = mesh.get_boundary_info();
72 
73  // Container to catch ids passed back from BoundaryInfo
74  std::vector<boundary_id_type> old_ids;
75 
76  // Only level-0 elements store BCs. Loop over them.
77  for (auto & elem : as_range(mesh.level_elements_begin(0), mesh.level_elements_end(0)))
78  {
79  unsigned int n_sides = elem->n_sides();
80  for (const auto s : make_range(n_sides))
81  {
82  boundary_info.boundary_ids(elem, s, old_ids);
83  if (std::find(old_ids.begin(), old_ids.end(), old_id) != old_ids.end())
84  {
85  std::vector<boundary_id_type> new_ids(old_ids);
86  std::replace(new_ids.begin(), new_ids.end(), old_id, new_id);
87  if (delete_prev)
88  {
89  boundary_info.remove_side(elem, s);
90  boundary_info.add_side(elem, s, new_ids);
91  }
92  else
93  boundary_info.add_side(elem, s, new_ids);
94  }
95  }
96  }
97 
98  // Remove any remaining references to the old ID from the
99  // BoundaryInfo object. This prevents things like empty sidesets
100  // from showing up when printing information, etc.
101  if (delete_prev)
102  boundary_info.remove_id(old_id);
103 
104  // global information may now be out of sync
106 }
void remove_id(boundary_id_type id, bool global=false)
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
MeshBase & mesh
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
const BoundaryInfo & get_boundary_info() const
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
void remove_side(const Elem *elem, const unsigned short int side)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
IntRange< T > make_range(T beg, T end)
void unset_is_prepared()

◆ changeSubdomainId() [1/2]

void MooseMeshUtils::changeSubdomainId ( MeshBase &  mesh,
const subdomain_id_type  old_id,
const subdomain_id_type  new_id 
)

Changes the old subdomain ID to a new ID in the mesh.

Parameters
meshthe mesh
old_idthe old subdomain id
new_idthe new subdomain id

◆ changeSubdomainId() [2/2]

void MooseMeshUtils::changeSubdomainId ( MeshBase mesh,
const subdomain_id_type  old_id,
const subdomain_id_type  new_id 
)

Definition at line 269 of file MooseMeshUtils.C.

270 {
271  for (const auto & elem : mesh.element_ptr_range())
272  if (elem->subdomain_id() == old_id)
273  elem->subdomain_id() = new_id;
274 
275  // global cached information may now be out of sync
277 }
MeshBase & mesh
void unset_is_prepared()

◆ computeDistanceToAxis()

template<typename P , typename C >
C MooseMeshUtils::computeDistanceToAxis ( const P &  point,
const Point &  origin,
const RealVectorValue direction 
)

Computes the distance to a general axis.

Parameters
[in]pointPoint for which to compute distance from axis
[in]originAxis starting point
[in]directionAxis direction

Definition at line 205 of file MooseMeshUtils.h.

206 {
207  return (point - origin).cross(direction).norm();
208 }

◆ computeFiniteVolumeCoords()

void MooseMeshUtils::computeFiniteVolumeCoords ( FaceInfo fi,
const Moose::CoordinateSystemType  coord_type,
const unsigned int  rz_radial_coord = libMesh::invalid_uint 
)
inline

Definition at line 239 of file MooseMeshUtils.h.

242 {
243  coordTransformFactor(fi.faceCentroid(), fi.faceCoord(), coord_type, rz_radial_coord);
244 }
void coordTransformFactor(const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
Compute a coordinate transformation volume integration factor.
const Point & faceCentroid() const
Returns the coordinates of the face centroid.
Definition: FaceInfo.h:75
Real & faceCoord()
Sets/gets the coordinate transformation factor (for e.g.
Definition: FaceInfo.h:68

◆ computeMaxDistanceToAxis() [1/2]

Real MooseMeshUtils::computeMaxDistanceToAxis ( const MeshBase &  mesh,
const Point &  origin,
const RealVectorValue direction 
)

Computes the maximum distance from all nodes of a mesh to a general axis.

Parameters
[in]meshmesh to get the distance from
[in]originAxis starting point
[in]directionAxis direction

Referenced by AdvancedExtruderGenerator::generate().

◆ computeMaxDistanceToAxis() [2/2]

Real MooseMeshUtils::computeMaxDistanceToAxis ( const MeshBase mesh,
const Point origin,
const RealVectorValue direction 
)

Definition at line 363 of file MooseMeshUtils.C.

366 {
367  Real distance = 0;
368  mooseAssert(MooseUtils::absoluteFuzzyEqual(direction.norm_sq(), 1),
369  "Direction should be normalized");
370  for (const auto & node : mesh.node_ptr_range())
371  if (const auto dist_node = (*node - origin).cross(direction).norm(); dist_node > distance)
372  distance = dist_node;
373  mesh.comm().max(distance);
374  return distance;
375 }
MeshBase & mesh
const Parallel::Communicator & comm() const
Real distance(const Point &p)
auto norm_sq() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const

◆ convertBlockToMesh() [1/2]

void MooseMeshUtils::convertBlockToMesh ( MeshBase &  source_mesh,
MeshBase &  target_mesh,
const std::vector< SubdomainName > &  target_blocks 
)

Convert a list of blocks in a given mesh to a standalone new mesh.

Parameters
source_meshThe source mesh from which the blocks will be converted
target_meshThe target mesh to which the blocks will be converted
target_blocksThe names of the blocks to be converted to the target mesh

Referenced by Boundary2DDelaunayGenerator::General2DDelaunay(), SurfaceSubdomainsDelaunayRemesher::General2DDelaunay(), BlockToMeshConverterGenerator::generate(), SubdomainsFromPartitionerGenerator::generate(), Boundary2DDelaunayGenerator::generate(), and SurfaceSubdomainsDelaunayRemesher::generate().

◆ convertBlockToMesh() [2/2]

void MooseMeshUtils::convertBlockToMesh ( MeshBase source_mesh,
MeshBase target_mesh,
const std::vector< SubdomainName > &  target_blocks 
)

Definition at line 1164 of file MooseMeshUtils.C.

1167 {
1168  if (!source_mesh.is_replicated())
1169  mooseError("This generator does not support distributed meshes.");
1170 
1171  const auto target_block_ids = MooseMeshUtils::getSubdomainIDs(source_mesh, target_blocks);
1172 
1173  // Check that the block ids/names exist in the mesh
1174  std::set<SubdomainID> mesh_blocks;
1175  source_mesh.subdomain_ids(mesh_blocks);
1176 
1177  for (const auto i : index_range(target_block_ids))
1178  if (target_block_ids[i] == Moose::INVALID_BLOCK_ID || !mesh_blocks.count(target_block_ids[i]))
1179  {
1180  mooseException("The target_block '", target_blocks[i], "' was not found within the mesh.");
1181  }
1182 
1183  // know which nodes have already been inserted, by tracking the old mesh's node's ids'
1184  std::unordered_map<dof_id_type, dof_id_type> old_new_node_map;
1185 
1186  for (const auto target_block_id : target_block_ids)
1187  {
1188 
1189  for (auto elem : source_mesh.active_subdomain_elements_ptr_range(target_block_id))
1190  {
1191  if (elem->level() != 0)
1192  mooseError("Refined blocks are not supported by this generator. "
1193  "Can you re-organize mesh generators to refine after converting the block?");
1194 
1195  // make a deep copy so that mutiple meshes' destructors don't segfault at program termination
1196  auto copy = elem->build(elem->type());
1197 
1198  // Keep the subdomain id
1199  copy->subdomain_id() = elem->subdomain_id();
1200 
1201  // index of node in the copy element must be managed manually as there is no intelligent
1202  // insert method
1203  dof_id_type copy_n_index = 0;
1204 
1205  // correctly assign new copies of nodes, loop over nodes
1206  for (dof_id_type i : elem->node_index_range())
1207  {
1208  auto & n = elem->node_ref(i);
1209 
1210  if (old_new_node_map.count(n.id()))
1211  {
1212  // case where we have already inserted this particular point before
1213  // then we need to find the already-inserted one and hook it up right
1214  // to it's respective element
1215  copy->set_node(copy_n_index++, target_mesh.node_ptr(old_new_node_map[n.id()]));
1216  }
1217  else
1218  {
1219  // case where we've NEVER inserted this particular point before
1220  // add them both to the element and the mesh
1221 
1222  // Nodes' IDs are their indexes in the nodes' respective mesh
1223  // If we set them as invalid they are automatically assigned
1224  // Add to mesh, auto-assigning a new id.
1225  Node * node = target_mesh.add_point(elem->point(i));
1226 
1227  // Add to element copy (manually)
1228  copy->set_node(copy_n_index++, node);
1229 
1230  // remember the (old) ID
1231  old_new_node_map[n.id()] = node->id();
1232  }
1233  }
1234 
1235  // it is ok to release the copy element into the mesh because derived meshes class
1236  // (ReplicatedMesh, DistributedMesh) manage their own elements, will delete them
1237  target_mesh.add_elem(copy.release());
1238  }
1239  }
1240 
1241  // Move subdomain names
1242  for (const auto sbd_id : target_block_ids)
1243  target_mesh.subdomain_name(sbd_id) = source_mesh.subdomain_name(sbd_id);
1244 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
dof_id_type id() const
virtual Elem * add_elem(Elem *e)=0
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
std::string & subdomain_name(subdomain_id_type id)
virtual bool is_replicated() const
unsigned int level ElemType type std::set< subdomain_id_type > ss processor_id_type pid unsigned int level std::set< subdomain_id_type > virtual ss SimpleRange< element_iterator > active_subdomain_elements_ptr_range(subdomain_id_type sid)=0
virtual const Node * node_ptr(const dof_id_type i) const=0
auto index_range(const T &sizable)
uint8_t dof_id_type

◆ coordTransformFactor()

template<typename P , typename C >
void MooseMeshUtils::coordTransformFactor ( const P &  point,
C &  factor,
const Moose::CoordinateSystemType  coord_type,
const unsigned int  rz_radial_coord = libMesh::invalid_uint 
)

Compute a coordinate transformation volume integration factor.

Parameters
pointThe libMesh Point in space where we are evaluating the factor
factorThe output of this function. Would be 1 for cartesian coordinate systems, 2*pi*r for cylindrical coordinate systems, and 4*pi*r^2 for spherical coordinate systems
coord_typeThe coordinate system type, e.g. cartesian (COORD_XYZ), cylindrical (COORD_RZ), or spherical (COORD_RSPHERICAL)
rz_radial_coordThe index at which to index point for the radial coordinate when in a cylindrical coordinate system

Definition at line 171 of file MooseMeshUtils.h.

Referenced by computeFiniteVolumeCoords(), coordTransformFactor(), Moose::FV::greenGaussGradient(), and Moose::FV::loopOverElemFaceInfo().

175 {
176  switch (coord_type)
177  {
178  case Moose::COORD_XYZ:
179  factor = 1.0;
180  break;
181  case Moose::COORD_RZ:
182  {
183  mooseAssert(rz_radial_coord != libMesh::invalid_uint,
184  "Must pass in a valid rz radial coordinate");
185  factor = 2 * M_PI * point(rz_radial_coord);
186  break;
187  }
189  factor = 4 * M_PI * point(0) * point(0);
190  break;
191  default:
192  mooseError("Unknown coordinate system");
193  }
194 }
const unsigned int invalid_uint
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311

◆ coordTransformFactorRZGeneral()

template<typename P , typename C >
void MooseMeshUtils::coordTransformFactorRZGeneral ( const P &  point,
const std::pair< Point, RealVectorValue > &  axis,
C &  factor 
)

Computes a coordinate transformation factor for a general axisymmetric axis.

Parameters
[in]pointThe libMesh Point in space where we are evaluating the factor
[in]axisThe pair of values defining the general axisymmetric axis. Respectively, the values are the axis starting point and direction.
[out]factorThe coordinate transformation factor

Definition at line 231 of file MooseMeshUtils.h.

Referenced by coordTransformFactor().

234 {
235  factor = 2 * M_PI * computeDistanceToAxis<P, C>(point, axis.first, axis.second);
236 }

◆ copyIntoMesh() [1/2]

void MooseMeshUtils::copyIntoMesh ( MeshGenerator mg,
UnstructuredMesh &  destination,
const UnstructuredMesh &  source,
const bool  avoid_merging_subdomains,
const bool  avoid_merging_boundaries,
const Parallel::Communicator communicator 
)

Helper function for copying one mesh into another.

Parameters
mgThe mesh generator calling this function
destinationThe mesh to copy into
sourceThe mesh to copy from
avoid_merging_subdomainsIf true, subdomain IDs in the source mesh will be offset to avoid merging with subdomain IDs in the destination mesh
avoid_merging_boundariesIf true, boundary IDs in the source mesh will be offset to avoid merging with boundary IDs in the destination mesh
communicatorThe communicator for parallel operations

Referenced by CombinerGenerator::generate(), and XYZDelaunayGenerator::generate().

◆ copyIntoMesh() [2/2]

void MooseMeshUtils::copyIntoMesh ( MeshGenerator mg,
UnstructuredMesh destination,
const UnstructuredMesh source,
const bool  avoid_merging_subdomains,
const bool  avoid_merging_boundaries,
const Parallel::Communicator communicator 
)

Definition at line 1247 of file MooseMeshUtils.C.

1253 {
1254  dof_id_type node_delta = destination.max_node_id();
1255  dof_id_type elem_delta = destination.max_elem_id();
1256 
1257  unique_id_type unique_delta =
1258 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1259  destination.parallel_max_unique_id();
1260 #else
1261  0;
1262 #endif
1263 
1264  // Prevent overlaps by offsetting the subdomains in
1265  std::unordered_map<subdomain_id_type, subdomain_id_type> id_remapping;
1266  unsigned int block_offset = 0;
1267  if (avoid_merging_subdomains)
1268  {
1269  // Note: if performance becomes an issue, this is overkill for just getting the max node id
1270  std::set<subdomain_id_type> source_ids;
1271  std::set<subdomain_id_type> dest_ids;
1272 
1273  // We need source subdomain ids already cached; libMesh will
1274  // scream otherwise
1275  source.subdomain_ids(source_ids, true);
1276 
1277  // Our destination is non-const, so we can fix any missing caches
1278  if (!destination.preparation().has_cached_elem_data)
1279  destination.cache_elem_data();
1280 
1281  destination.subdomain_ids(dest_ids, true);
1282 
1283  mooseAssert(source_ids.size(), "Should have a subdomain");
1284  mooseAssert(dest_ids.size(), "Should have a subdomain");
1285  unsigned int max_dest_bid = *dest_ids.rbegin();
1286  unsigned int min_source_bid = *source_ids.begin();
1287  communicator.max(max_dest_bid);
1288  communicator.min(min_source_bid);
1289  block_offset = 1 + max_dest_bid - min_source_bid;
1290  for (const auto bid : source_ids)
1291  id_remapping[bid] = block_offset + bid;
1292  }
1293 
1294  // Copy mesh data over from the other mesh
1295  destination.copy_nodes_and_elements(source,
1296  // Skipping this should cause the neighbors
1297  // to simply be copied from the other mesh
1298  // (which makes sense and is way faster)
1299  /*skip_find_neighbors = */ true,
1300  elem_delta,
1301  node_delta,
1302  unique_delta,
1303  avoid_merging_subdomains ? &id_remapping : nullptr);
1304 
1305  // Get an offset to prevent overlaps / wild merging between boundaries
1306  BoundaryInfo & boundary = destination.get_boundary_info();
1307  const BoundaryInfo & other_boundary = source.get_boundary_info();
1308 
1309  unsigned int bid_offset = 0;
1310  if (avoid_merging_boundaries)
1311  {
1312  const auto boundary_ids = boundary.get_boundary_ids();
1313  const auto other_boundary_ids = other_boundary.get_boundary_ids();
1314  unsigned int max_dest_bid = boundary_ids.size() ? *boundary_ids.rbegin() : 0;
1315  unsigned int min_source_bid = other_boundary_ids.size() ? *other_boundary_ids.begin() : 0;
1316  communicator.max(max_dest_bid);
1317  communicator.min(min_source_bid);
1318  bid_offset = 1 + max_dest_bid - min_source_bid;
1319  }
1320 
1321  // Note: the code below originally came from ReplicatedMesh::stitch_mesh_helper()
1322  // in libMesh replicated_mesh.C around line 1203
1323 
1324  // Copy BoundaryInfo from other_mesh too. We do this via the
1325  // list APIs rather than element-by-element for speed.
1326  for (const auto & t : other_boundary.build_node_list())
1327  boundary.add_node(std::get<0>(t) + node_delta, bid_offset + std::get<1>(t));
1328 
1329  for (const auto & t : other_boundary.build_side_list())
1330  boundary.add_side(std::get<0>(t) + elem_delta, std::get<1>(t), bid_offset + std::get<2>(t));
1331 
1332  for (const auto & t : other_boundary.build_edge_list())
1333  boundary.add_edge(std::get<0>(t) + elem_delta, std::get<1>(t), bid_offset + std::get<2>(t));
1334 
1335  for (const auto & t : other_boundary.build_shellface_list())
1336  boundary.add_shellface(
1337  std::get<0>(t) + elem_delta, std::get<1>(t), bid_offset + std::get<2>(t));
1338 
1339  // Check for the case with two block ids sharing the same name
1340  if (avoid_merging_subdomains)
1341  {
1342  mooseAssert(mg.parameters().isParamDefined("avoid_merging_subdomains"),
1343  "Missing parameter in the mesh generator calling this function: "
1344  "avoid_merging_subdomains. Considering setting avoid_merging_subdomains to true.");
1345  for (const auto & [block_id, block_name] : destination.get_subdomain_name_map())
1346  for (const auto & [source_id, source_name] : source.get_subdomain_name_map())
1347  if (block_name == source_name)
1348  mg.paramWarning(
1349  "avoid_merging_subdomains",
1350  "Not merging subdomains is creating two subdomains with the same name '" +
1351  block_name + "' but different ids: " + std::to_string(source_id) + " & " +
1352  std::to_string(block_id + block_offset) +
1353  ".\n We recommend using a RenameBlockGenerator to prevent this as you "
1354  "will get errors reading the Exodus output later.");
1355  }
1356 
1357  for (const auto & [block_id, block_name] : source.get_subdomain_name_map())
1358  destination.set_subdomain_name_map().insert(
1359  std::make_pair<SubdomainID, SubdomainName>(block_id + block_offset, block_name));
1360 
1361  // Check for the case with two boundary ids sharing the same name
1362  if (avoid_merging_boundaries)
1363  {
1364  mooseAssert(mg.parameters().isParamDefined("avoid_merging_boundaries"),
1365  "Missing parameter in the mesh generator calling this function: "
1366  "avoid_merging_boundaries. Considering setting avoid_merging_boundaries to true.");
1367  for (const auto & [b_id, b_name] : other_boundary.get_sideset_name_map())
1368  for (const auto & [source_id, source_name] : boundary.get_sideset_name_map())
1369  if (b_name == source_name)
1370  mg.paramWarning(
1371  "avoid_merging_boundaries",
1372  "Not merging boundaries is creating two sidesets with the same name '" + b_name +
1373  "' but different ids: " + std::to_string(source_id) + " & " +
1374  std::to_string(b_id + bid_offset) +
1375  ".\n We recommend using a RenameBoundaryGenerator to prevent this as you "
1376  "will get errors reading the Exodus output later.");
1377  for (const auto & [b_id, b_name] : other_boundary.get_nodeset_name_map())
1378  for (const auto & [source_id, source_name] : boundary.get_nodeset_name_map())
1379  if (b_name == source_name)
1380  mg.paramWarning(
1381  "avoid_merging_boundaries",
1382  "Not merging boundaries is creating two nodesets with the same name '" + b_name +
1383  "' but different ids: " + std::to_string(source_id) + " & " +
1384  std::to_string(b_id + bid_offset) +
1385  ".\n We recommend using a RenameBoundaryGenerator to prevent this as you "
1386  "will get errors reading the Exodus output later.");
1387  }
1388 
1389  for (const auto & [nodeset_id, nodeset_name] : other_boundary.get_nodeset_name_map())
1390  boundary.set_nodeset_name_map().insert(
1391  std::make_pair<BoundaryID, BoundaryName>(nodeset_id + bid_offset, nodeset_name));
1392 
1393  for (const auto & [sideset_id, sideset_name] : other_boundary.get_sideset_name_map())
1394  boundary.set_sideset_name_map().insert(
1395  std::make_pair<BoundaryID, BoundaryName>(sideset_id + bid_offset, sideset_name));
1396 
1397  for (const auto & [edgeset_id, edgeset_name] : other_boundary.get_edgeset_name_map())
1398  boundary.set_edgeset_name_map().insert(
1399  std::make_pair<BoundaryID, BoundaryName>(edgeset_id + bid_offset, edgeset_name));
1400 }
bool isParamDefined(const std::string &name) const
Method returns true if the parameter is defined for any type.
std::vector< BCTuple > build_shellface_list() const
virtual unique_id_type parallel_max_unique_id() const=0
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
Preparation preparation() const
std::map< boundary_id_type, std::string > & set_sideset_name_map()
void add_node(const Node *node, const boundary_id_type id)
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
const std::map< boundary_id_type, std::string > & get_edgeset_name_map() const
virtual dof_id_type max_elem_id() const=0
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
std::vector< BCTuple > build_edge_list() const
std::map< subdomain_id_type, std::string > & set_subdomain_name_map()
const std::set< boundary_id_type > & get_boundary_ids() const
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
std::map< boundary_id_type, std::string > & set_nodeset_name_map()
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
virtual void copy_nodes_and_elements(const MeshBase &other_mesh, const bool skip_find_neighbors=false, dof_id_type element_id_offset=0, dof_id_type node_id_offset=0, unique_id_type unique_id_offset=0, std::unordered_map< subdomain_id_type, subdomain_id_type > *id_remapping=nullptr, const bool skip_preparation=false)
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const
void paramWarning(const std::string &param, Args... args) const
virtual dof_id_type max_node_id() const=0
uint8_t unique_id_type
uint8_t dof_id_type
std::map< boundary_id_type, std::string > & set_edgeset_name_map()
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)

◆ createSubdomainFromSidesets() [1/2]

void MooseMeshUtils::createSubdomainFromSidesets ( MeshBase &  mesh,
std::vector< BoundaryName >  boundary_names,
const SubdomainID  new_subdomain_id,
const SubdomainName  new_subdomain_name,
const std::string  type_name 
)

Create a new subdomain by generating new side elements from a list of sidesets in a given mesh.

Parameters
meshThe mesh to work on
boundary_namesThe names of the sidesets to be used to create the new subdomain
new_subdomain_idThe ID of the new subdomain to be created based on the sidesets
new_subdomain_nameThe name of the new subdomain to be created based on the sidesets
type_nameThe type of the mesh generator that is calling this method, used for error messages and debugging purposes.

Referenced by Boundary2DDelaunayGenerator::General2DDelaunay(), SurfaceSubdomainsDelaunayRemesher::General2DDelaunay(), LowerDBlockFromSidesetGenerator::generate(), and Boundary2DDelaunayGenerator::generate().

◆ createSubdomainFromSidesets() [2/2]

void MooseMeshUtils::createSubdomainFromSidesets ( MeshBase mesh,
std::vector< BoundaryName >  boundary_names,
const SubdomainID  new_subdomain_id,
const SubdomainName  new_subdomain_name,
const std::string  type_name 
)

Definition at line 1018 of file MooseMeshUtils.C.

1023 {
1024  // Generate a new block id if one isn't supplied.
1025  SubdomainID new_block_id = new_subdomain_id;
1026 
1027  // Make sure our boundary info and parallel counts are setup
1028  if (!mesh.is_prepared())
1029  {
1030  const bool allow_remote_element_removal = mesh.allow_remote_element_removal();
1031  // We want all of our boundary elements available, so avoid removing them if they haven't
1032  // already been so
1035  mesh.allow_remote_element_removal(allow_remote_element_removal);
1036  }
1037 
1038  // Check that the sidesets are present in the mesh
1039  for (const auto & sideset : boundary_names)
1041  mooseException("The sideset '", sideset, "' was not found within the mesh");
1042 
1043  auto sideset_ids = MooseMeshUtils::getBoundaryIDs(mesh, boundary_names, true);
1044  std::set<boundary_id_type> sidesets(sideset_ids.begin(), sideset_ids.end());
1045  auto side_list = mesh.get_boundary_info().build_side_list();
1046  if (!mesh.is_serial() && mesh.comm().size() > 1)
1047  {
1048  std::vector<Elem *> elements_to_send;
1049  unsigned short i_need_boundary_elems = 0;
1050  for (const auto & [elem_id, side, bc_id] : side_list)
1051  {
1052  libmesh_ignore(side);
1053  if (sidesets.count(bc_id))
1054  {
1055  // Whether we have this boundary information through our locally owned element or a ghosted
1056  // element, we'll need the boundary elements for parallel consistent addition
1057  i_need_boundary_elems = 1;
1058  auto * elem = mesh.elem_ptr(elem_id);
1059  if (elem->processor_id() == mesh.processor_id())
1060  elements_to_send.push_back(elem);
1061  }
1062  }
1063 
1064  std::set<const Elem *, libMesh::CompareElemIdsByLevel> connected_elements(
1065  elements_to_send.begin(), elements_to_send.end());
1066  std::set<const Node *> connected_nodes;
1067  reconnect_nodes(connected_elements, connected_nodes);
1068  std::set<dof_id_type> connected_node_ids;
1069  for (auto * nd : connected_nodes)
1070  connected_node_ids.insert(nd->id());
1071 
1072  std::vector<unsigned short> need_boundary_elems(mesh.comm().size());
1073  mesh.comm().allgather(i_need_boundary_elems, need_boundary_elems);
1074  std::unordered_map<processor_id_type, decltype(elements_to_send)> push_element_data;
1075  std::unordered_map<processor_id_type, decltype(connected_nodes)> push_node_data;
1076 
1077  for (const auto pid : index_range(mesh.comm()))
1078  // Don't need to send to self
1079  if (pid != mesh.processor_id() && need_boundary_elems[pid])
1080  {
1081  if (elements_to_send.size())
1082  push_element_data[pid] = elements_to_send;
1083  if (connected_nodes.size())
1084  push_node_data[pid] = connected_nodes;
1085  }
1086 
1087  auto node_action_functor = [](processor_id_type, const auto &)
1088  {
1089  // Node packing specialization already has unpacked node into mesh, so nothing to do
1090  };
1091  Parallel::push_parallel_packed_range(mesh.comm(), push_node_data, &mesh, node_action_functor);
1092  auto elem_action_functor = [](processor_id_type, const auto &)
1093  {
1094  // Elem packing specialization already has unpacked elem into mesh, so nothing to do
1095  };
1096  TIMPI::push_parallel_packed_range(mesh.comm(), push_element_data, &mesh, elem_action_functor);
1097 
1098  // now that we've gathered everything, we need to rebuild the side list
1099  side_list = mesh.get_boundary_info().build_side_list();
1100  }
1101 
1102  std::vector<std::pair<dof_id_type, ElemSidePair>> element_sides_on_boundary;
1103  dof_id_type counter = 0;
1104  for (const auto & [eid, side, bid] : side_list)
1105  if (sidesets.count(bid))
1106  {
1107  if (auto elem = mesh.query_elem_ptr(eid))
1108  {
1109  if (!elem->active())
1110  mooseError(
1111  "Only active, level 0 elements can be made interior parents of new level 0 lower-d "
1112  "elements. Make sure that ",
1113  type_name,
1114  "s are run before any refinement generators");
1115  element_sides_on_boundary.push_back(std::make_pair(counter, ElemSidePair(elem, side)));
1116  }
1117  ++counter;
1118  }
1119 
1120  dof_id_type max_elem_id = mesh.max_elem_id();
1121  unique_id_type max_unique_id = mesh.parallel_max_unique_id();
1122 
1123  // Making an important assumption that at least our boundary elements are the same on all
1124  // processes even in distributed mesh mode (this is reliant on the correct ghosting functors
1125  // existing on the mesh)
1126  for (auto & [i, elem_side] : element_sides_on_boundary)
1127  {
1128  Elem * elem = elem_side.elem;
1129 
1130  const auto side = elem_side.side;
1131 
1132  // Build a non-proxy element from this side.
1133  std::unique_ptr<Elem> side_elem(elem->build_side_ptr(side));
1134 
1135  // The side will be added with the same processor id as the parent.
1136  side_elem->processor_id() = elem->processor_id();
1137 
1138  // Add subdomain ID
1139  side_elem->subdomain_id() = new_block_id;
1140 
1141  // Also assign the side's interior parent, so it is always
1142  // easy to figure out the Elem we came from.
1143  side_elem->set_interior_parent(elem);
1144 
1145  // Add id
1146  side_elem->set_id(max_elem_id + i);
1147  side_elem->set_unique_id(max_unique_id + i);
1148 
1149  // Finally, add the lower-dimensional element to the mesh.
1150  mesh.add_elem(side_elem.release());
1151  };
1152 
1153  // Assign block name, if provided
1154  if (new_subdomain_name.size())
1155  mesh.subdomain_name(new_block_id) = new_subdomain_name;
1156 
1157  const bool skip_partitioning_old = mesh.skip_partitioning();
1158  mesh.skip_partitioning(true);
1160  mesh.skip_partitioning(skip_partitioning_old);
1161 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
bool is_prepared() const
virtual unique_id_type parallel_max_unique_id() const=0
bool hasBoundaryName(const MeshBase &input_mesh, const BoundaryName &name)
Whether a particular boundary name exists in the mesh.
void reconnect_nodes(connected_elem_set_type &connected_elements, connected_node_set_type &connected_nodes)
std::set< std::string > sideset
void skip_partitioning(bool skip)
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
MeshBase & mesh
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
processor_id_type size() const
uint8_t processor_id_type
void allow_remote_element_removal(bool allow)
virtual bool is_serial() const
void libmesh_ignore(const Args &...)
void push_parallel_packed_range(const Communicator &comm, MapToContainers &&data, Context *context, const ActionFunctor &act_on_data)
virtual Elem * add_elem(Elem *e)=0
virtual dof_id_type max_elem_id() const=0
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
std::string & subdomain_name(subdomain_id_type id)
virtual const Elem * elem_ptr(const dof_id_type i) const=0
virtual const Elem * query_elem_ptr(const dof_id_type i) const=0
processor_id_type processor_id() const
processor_id_type processor_id() const
uint8_t unique_id_type
auto index_range(const T &sizable)
uint8_t dof_id_type

◆ extraElemIntegerSwapParametersProcessor()

void MooseMeshUtils::extraElemIntegerSwapParametersProcessor ( const std::string &  class_name,
const unsigned int  num_sections,
const unsigned int  num_integers,
const std::vector< std::vector< std::vector< dof_id_type >>> &  elem_integers_swaps,
std::vector< std::unordered_map< dof_id_type, dof_id_type >> &  elem_integers_swap_pairs 
)

Reprocess the elem_integers_swaps into maps so they are easier to use.

Parameters
class_namename of the mesh generator class used for exception messages
num_sectionsnumber of sections in the mesh
num_integersnumber of extra element integers in the mesh
elem_integers_swapsvector of vectors of vectors of extra element ids to be swapped
elem_integers_swap_pairsvector of maps of the swapped pairs

Definition at line 665 of file MooseMeshUtils.C.

Referenced by AdvancedExtruderGenerator::AdvancedExtruderGenerator().

671 {
672  elem_integers_swap_pairs.reserve(num_sections * num_integers);
673  for (const auto i : make_range(num_integers))
674  {
675  const auto & elem_integer_swaps = elem_integers_swaps[i];
676  std::vector<std::unordered_map<dof_id_type, dof_id_type>> elem_integer_swap_pairs;
677  try
678  {
680  "elem_integers_swaps",
681  elem_integer_swaps,
682  elem_integer_swap_pairs,
683  i * num_sections);
684  }
685  catch (const MooseException & e)
686  {
687  throw MooseException(e.what());
688  }
689 
690  elem_integers_swap_pairs.insert(elem_integers_swap_pairs.end(),
691  elem_integer_swap_pairs.begin(),
692  elem_integer_swap_pairs.end());
693  }
694 }
virtual const char * what() const
Get out the error message.
void idSwapParametersProcessor(const std::string &class_name, const std::string &id_name, const std::vector< std::vector< T >> &id_swaps, std::vector< std::unordered_map< T, T >> &id_swap_pairs, const unsigned int row_index_shift=0)
Reprocess the swap related input parameters to make pairs out of them to ease further processing...
Provides a way for users to bail out of the current solve.
IntRange< T > make_range(T beg, T end)

◆ getBoundaryID() [1/2]

BoundaryID MooseMeshUtils::getBoundaryID ( const BoundaryName &  boundary_name,
const MeshBase &  mesh 
)

◆ getBoundaryID() [2/2]

BoundaryID MooseMeshUtils::getBoundaryID ( const BoundaryName &  boundary_name,
const MeshBase mesh 
)

Definition at line 236 of file MooseMeshUtils.C.

Referenced by hasBoundaryName().

237 {
239  if (boundary_name.empty())
240  return id;
241 
242  if (!MooseUtils::isDigits(boundary_name))
243  id = mesh.get_boundary_info().get_id_by_name(boundary_name);
244  else
245  id = getIDFromName<BoundaryName, BoundaryID>(boundary_name);
246 
247  return id;
248 }
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
boundary_id_type get_id_by_name(std::string_view name) const
boundary_id_type BoundaryID

◆ getBoundaryIDs() [1/2]

std::vector< boundary_id_type > MooseMeshUtils::getBoundaryIDs ( const libMesh::MeshBase mesh,
const std::vector< BoundaryName > &  boundary_name,
bool  generate_unknown,
const std::set< BoundaryID > &  mesh_boundary_ids 
)

Gets the boundary IDs with their names.

The ordering of the returned boundary ID vector matches the vector of the boundary names in boundary_name. When a boundary name is not available in the mesh, if generate_unknown is true a non-existant boundary ID will be returned, otherwise a BoundaryInfo::invalid_id will be returned.

If the conversion from a name to a number fails, that means that this must be a named boundary. We will look in the complete map for this sideset and create a new name/ID pair if requested.

If the conversion from a name to a number fails, that means that this must be a named boundary. We will look in the complete map for this sideset and create a new name/ID pair if requested.

Definition at line 118 of file MooseMeshUtils.C.

Referenced by BoundaryPreservedMarker::BoundaryPreservedMarker(), BoundaryLayerUtils::buildBoundaryLayerRing(), buildPolyLineMesh(), MeshExtruderGenerator::changeID(), SubProblem::checkBoundaryMatProps(), createSubdomainFromSidesets(), Boundary2DDelaunayGenerator::General2DDelaunay(), BoundaryLayerSubdomainGenerator::generate(), ExtraNodesetGenerator::generate(), SideSetsFromNormalsGenerator::generate(), BreakBoundaryOnSubdomainGenerator::generate(), RefineSidesetGenerator::generate(), SideSetsBetweenSubdomainsGenerator::generate(), FillBetweenSidesetsGenerator::generate(), SideSetsFromPointsGenerator::generate(), MeshDiagnosticsGenerator::generate(), XYTriangleBoundaryLayerGenerator::generate(), PolyLineMeshFollowingNodeSetGenerator::generate(), StackGenerator::generate(), AdvancedExtruderGenerator::generate(), ParsedGenerateNodeset::generate(), XYDelaunayGenerator::generate(), CircularBoundaryCorrectionGenerator::generate(), ElementDeletionGeneratorBase::generate(), ParsedGenerateSideset::generate(), SideSetsAroundSubdomainGenerator::generate(), PatternedMeshGenerator::generate(), BoundingBoxNodeSetGenerator::generate(), getBoundaryIDs(), MooseMesh::getBoundaryIDs(), getBoundaryIDSet(), NodeSetsGeneratorBase::setup(), SideSetsGeneratorBase::setup(), and MeshTriangulationUtils::triangulateWithDelaunay().

122 {
123  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
124  const std::map<BoundaryID, std::string> & sideset_map = boundary_info.get_sideset_name_map();
125  const std::map<BoundaryID, std::string> & nodeset_map = boundary_info.get_nodeset_name_map();
126 
127  BoundaryID max_boundary_local_id = 0;
128  /* It is required to generate a new ID for a given name. It is used often in mesh modifiers such
129  * as SideSetsBetweenSubdomains. Then we need to check the current boundary ids since they are
130  * changing during "mesh modify()", and figure out the right max boundary ID. Most of mesh
131  * modifiers are running in serial, and we won't involve a global communication.
132  */
133  if (generate_unknown)
134  {
137  max_boundary_local_id = bids.empty() ? 0 : *(bids.rbegin());
138  /* We should not hit this often */
139  if (!mesh.is_prepared() && !mesh.is_serial())
140  mesh.comm().max(max_boundary_local_id);
141  }
142 
143  BoundaryID max_boundary_id = mesh_boundary_ids.empty() ? 0 : *(mesh_boundary_ids.rbegin());
144 
145  max_boundary_id =
146  max_boundary_id > max_boundary_local_id ? max_boundary_id : max_boundary_local_id;
147 
148  std::vector<BoundaryID> ids(boundary_name.size());
149  for (const auto i : index_range(boundary_name))
150  {
151  if (boundary_name[i] == "ANY_BOUNDARY_ID")
152  {
153  ids.assign(mesh_boundary_ids.begin(), mesh_boundary_ids.end());
154  if (i)
155  mooseWarning("You passed \"ANY_BOUNDARY_ID\" in addition to other boundary_names. This "
156  "may be a logic error.");
157  break;
158  }
159 
160  if (boundary_name[i].empty() && !generate_unknown)
161  mooseError("Incoming boundary name is empty and we are not generating unknown boundary IDs. "
162  "This is invalid.");
163 
164  BoundaryID id;
165 
166  if (boundary_name[i].empty() || !MooseUtils::isDigits(boundary_name[i]))
167  {
173  if (generate_unknown &&
174  !MooseUtils::doesMapContainValue(sideset_map, std::string(boundary_name[i])) &&
175  !MooseUtils::doesMapContainValue(nodeset_map, std::string(boundary_name[i])))
176  id = ++max_boundary_id;
177  else
178  id = boundary_info.get_id_by_name(boundary_name[i]);
179  }
180  else
181  id = getIDFromName<BoundaryName, BoundaryID>(boundary_name[i]);
182 
183  ids[i] = id;
184  }
185 
186  return ids;
187 }
bool is_prepared() const
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:345
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
MeshBase & mesh
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
boundary_id_type get_id_by_name(std::string_view name) const
virtual bool is_serial() const
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const
boundary_id_type BoundaryID
const std::set< boundary_id_type > & get_boundary_ids() const
void max(const T &r, T &o, Request &req) const
const std::set< boundary_id_type > & get_global_boundary_ids() const
auto index_range(const T &sizable)

◆ getBoundaryIDs() [2/2]

std::vector< boundary_id_type > MooseMeshUtils::getBoundaryIDs ( const libMesh::MeshBase mesh,
const std::vector< BoundaryName > &  boundary_name,
bool  generate_unknown 
)

Gets the boundary IDs with their names.

The ordering of the returned boundary ID vector matches the vector of the boundary names in boundary_name. When a boundary name is not available in the mesh, if generate_unknown is true a non-existant boundary ID will be returned, otherwise a BoundaryInfo::invalid_id will be returned.

Definition at line 109 of file MooseMeshUtils.C.

112 {
113  return getBoundaryIDs(
114  mesh, boundary_name, generate_unknown, mesh.get_boundary_info().get_boundary_ids());
115 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
const std::set< boundary_id_type > & get_boundary_ids() const

◆ getBoundaryIDSet()

std::set< BoundaryID > MooseMeshUtils::getBoundaryIDSet ( const libMesh::MeshBase mesh,
const std::vector< BoundaryName > &  boundary_name,
bool  generate_unknown 
)

Gets the boundary IDs into a set with their names.

Because libMesh allows the same boundary to have multiple different boundary names, the size of the returned boundary ID set may be smaller than the size of the boundary name vector. When a boundary name is not available in the mesh, if generate_unknown is true a non-existant boundary ID will be returned, otherwise a BoundaryInfo::invalid_id will be returned.

Definition at line 190 of file MooseMeshUtils.C.

Referenced by DomainUserObject::DomainUserObject().

193 {
194  auto boundaries = getBoundaryIDs(mesh, boundary_name, generate_unknown);
195  return std::set<BoundaryID>(boundaries.begin(), boundaries.end());
196 }
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.

◆ getBoundaryNodes() [1/2]

std::set<dof_id_type> MooseMeshUtils::getBoundaryNodes ( const MeshBase &  mesh,
const BoundaryID  boundary_id 
)

Get all the nodes on that particular boundary, whether a nodeset or a sideset.

Note: if the mesh has both a nodeset and a sideset with the same ID, they will both be considered If this is undesirable, renumber one of them prior to calling this routine

Parameters
input_meshThe input mesh to get the map for
boundary_idThe boundary id of interest

◆ getBoundaryNodes() [2/2]

std::set<dof_id_type> MooseMeshUtils::getBoundaryNodes ( const MeshBase mesh,
const BoundaryID  boundary_id 
)

Definition at line 990 of file MooseMeshUtils.C.

Referenced by buildBoundaryNodeToElemMap().

991 {
992  std::set<dof_id_type> boundary_node_ids;
993  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
994 
995  // Get all nodes from the sideset with ID of boundary_id
996  const auto & bc_sides =
998  for (const auto & [elem_id, side, bc_id] : bc_sides)
999  {
1000  if (bc_id == boundary_id)
1001  {
1002  const auto elem = mesh.elem_ptr(elem_id);
1003  for (const auto ni : elem->nodes_on_side(side))
1004  boundary_node_ids.insert(elem->node_id(ni));
1005  }
1006  }
1007 
1008  // Get all nodes from nodeset with ID of boundary_id
1009  const auto & bc_nodes = boundary_info.build_node_list();
1010  for (const auto & [n_id, bc_id] : bc_nodes)
1011  if (bc_id == boundary_id)
1012  boundary_node_ids.insert(n_id);
1013 
1014  return boundary_node_ids;
1015 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
virtual const Elem * elem_ptr(const dof_id_type i) const=0
std::vector< NodeBCTuple > build_node_list(NodeBCTupleSortBy sort_by=NodeBCTupleSortBy::NODE_ID) const

◆ getExtraIDUniqueCombinationMap() [1/2]

std::unordered_map<dof_id_type, dof_id_type> MooseMeshUtils::getExtraIDUniqueCombinationMap ( const MeshBase &  mesh,
const std::set< SubdomainID > &  block_ids,
std::vector< ExtraElementIDName >  extra_ids 
)

Create a new set of element-wise IDs by finding unique combinations of existing extra ID values.

This function finds the unique combinations by recursively calling itself for extra ID inputs. In the recursive calling, the new unique combinations is determined by combining the extra ID value of current level and the unique combination determined in the previous level in recursion. In the lowest level of recursion, the base combination is set by the unique ID values of the corresponding extra ID.

Parameters
meshinput mesh
block_idsblock ids
extra_idsextra ids
Returns
map of element id to new extra id

Referenced by ExtraIDIntegralVectorPostprocessor::ExtraIDIntegralVectorPostprocessor(), UniqueExtraIDMeshGenerator::generate(), and getExtraIDUniqueCombinationMap().

◆ getExtraIDUniqueCombinationMap() [2/2]

std::unordered_map<dof_id_type, dof_id_type> MooseMeshUtils::getExtraIDUniqueCombinationMap ( const MeshBase mesh,
const std::set< SubdomainID > &  block_ids,
std::vector< ExtraElementIDName >  extra_ids 
)

Definition at line 378 of file MooseMeshUtils.C.

381 {
382  // check block restriction
383  const bool block_restricted = !block_ids.empty();
384  // get element id name of interest in recursive parsing algorithm
385  ExtraElementIDName id_name = extra_ids.back();
386  extra_ids.pop_back();
387  const auto id_index = mesh.get_elem_integer_index(id_name);
388 
389  // create base parsed id set
390  if (extra_ids.empty())
391  {
392  // get set of extra id values;
393  std::vector<dof_id_type> ids;
394  {
395  std::set<dof_id_type> ids_set;
396  for (const auto & elem : mesh.active_element_ptr_range())
397  {
398  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
399  continue;
400  const auto id = elem->get_extra_integer(id_index);
401  ids_set.insert(id);
402  }
403  mesh.comm().set_union(ids_set);
404  ids.assign(ids_set.begin(), ids_set.end());
405  }
406 
407  // determine new extra id values;
408  std::unordered_map<dof_id_type, dof_id_type> parsed_ids;
409  for (auto & elem : mesh.active_element_ptr_range())
410  {
411  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
412  continue;
413  parsed_ids[elem->id()] = std::distance(
414  ids.begin(), std::lower_bound(ids.begin(), ids.end(), elem->get_extra_integer(id_index)));
415  }
416  return parsed_ids;
417  }
418 
419  // if extra_ids is not empty, recursively call getExtraIDUniqueCombinationMap
420  const auto base_parsed_ids =
421  MooseMeshUtils::getExtraIDUniqueCombinationMap(mesh, block_ids, extra_ids);
422  // parsing extra ids based on ref_parsed_ids
423  std::vector<std::pair<dof_id_type, dof_id_type>> unique_ids;
424  {
425  std::set<std::pair<dof_id_type, dof_id_type>> unique_ids_set;
426  for (const auto & elem : mesh.active_element_ptr_range())
427  {
428  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
429  continue;
430  const dof_id_type id1 = libmesh_map_find(base_parsed_ids, elem->id());
431  const dof_id_type id2 = elem->get_extra_integer(id_index);
432  const std::pair<dof_id_type, dof_id_type> ids = std::make_pair(id1, id2);
433  unique_ids_set.insert(ids);
434  }
435  mesh.comm().set_union(unique_ids_set);
436  unique_ids.assign(unique_ids_set.begin(), unique_ids_set.end());
437  }
438 
439  std::unordered_map<dof_id_type, dof_id_type> parsed_ids;
440 
441  for (const auto & elem : mesh.active_element_ptr_range())
442  {
443  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
444  continue;
445  const dof_id_type id1 = libmesh_map_find(base_parsed_ids, elem->id());
446  const dof_id_type id2 = elem->get_extra_integer(id_index);
447  const dof_id_type new_id = std::distance(
448  unique_ids.begin(),
449  std::lower_bound(unique_ids.begin(), unique_ids.end(), std::make_pair(id1, id2)));
450  parsed_ids[elem->id()] = new_id;
451  }
452 
453  return parsed_ids;
454 }
std::unordered_map< dof_id_type, dof_id_type > getExtraIDUniqueCombinationMap(const MeshBase &mesh, const std::set< SubdomainID > &block_ids, std::vector< ExtraElementIDName > extra_ids)
Create a new set of element-wise IDs by finding unique combinations of existing extra ID values...
MeshBase & mesh
const Parallel::Communicator & comm() const
unsigned int get_elem_integer_index(std::string_view name) const
uint8_t dof_id_type
void set_union(T &data, const unsigned int root_id) const

◆ getIDFromName()

template<typename T , typename Q >
Q MooseMeshUtils::getIDFromName ( const T &  name)

Converts a given name (BoundaryName or SubdomainName) that is known to only contain digits into a corresponding ID (BoundaryID or SubdomainID) and performs bounds checking to ensure that overflow doesn't happen.

Parameters
nameName that is to be converted into an ID.
Returns
ID type corresponding to the type of name.

Definition at line 370 of file MooseMeshUtils.h.

371 {
372  if (!MooseUtils::isDigits(name))
373  mooseError(
374  "'name' ", name, " should only contain digits that can be converted to a numerical type.");
375  long long id = std::stoll(name);
376  Q id_Q = Q(id);
378  mooseError(MooseUtils::prettyCppType<T>(&name),
379  " ",
380  name,
381  " is not within the numeric limits of the expected ID type ",
382  MooseUtils::prettyCppType<Q>(&id_Q),
383  ".");
384 
385  return id_Q;
386 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
auto max(const L &left, const R &right)
auto min(const L &left, const R &right)

◆ getNextFreeBoundaryID() [1/2]

BoundaryID MooseMeshUtils::getNextFreeBoundaryID ( MeshBase &  input_mesh)

◆ getNextFreeBoundaryID() [2/2]

BoundaryID MooseMeshUtils::getNextFreeBoundaryID ( MeshBase input_mesh)

Definition at line 519 of file MooseMeshUtils.C.

520 {
521  if (!input_mesh.preparation().has_boundary_id_sets)
522  input_mesh.get_boundary_info().regenerate_id_sets();
523 
524  auto boundary_ids = input_mesh.get_boundary_info().get_boundary_ids();
525  if (boundary_ids.empty())
526  return 0;
527  return (*boundary_ids.rbegin() + 1);
528 }
const BoundaryInfo & get_boundary_info() const
Preparation preparation() const
const std::set< boundary_id_type > & get_boundary_ids() const

◆ getNextFreeSubdomainID() [1/2]

SubdomainID MooseMeshUtils::getNextFreeSubdomainID ( MeshBase &  input_mesh)

◆ getNextFreeSubdomainID() [2/2]

SubdomainID MooseMeshUtils::getNextFreeSubdomainID ( MeshBase input_mesh)

Definition at line 499 of file MooseMeshUtils.C.

500 {
501  // Call this to get most up to date block id information
502  input_mesh.cache_elem_data();
503 
504  std::set<SubdomainID> preexisting_subdomain_ids;
505  input_mesh.subdomain_ids(preexisting_subdomain_ids);
506  if (preexisting_subdomain_ids.empty())
507  return 0;
508  else
509  {
510  const auto highest_subdomain_id =
511  *std::max_element(preexisting_subdomain_ids.begin(), preexisting_subdomain_ids.end());
512  mooseAssert(highest_subdomain_id < std::numeric_limits<SubdomainID>::max(),
513  "A SubdomainID with max possible value was found");
514  return highest_subdomain_id + 1;
515  }
516 }
auto max(const L &left, const R &right)
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const

◆ getSubdomainID() [1/2]

SubdomainID MooseMeshUtils::getSubdomainID ( const SubdomainName &  subdomain_name,
const MeshBase &  mesh 
)

◆ getSubdomainID() [2/2]

SubdomainID MooseMeshUtils::getSubdomainID ( const SubdomainName &  subdomain_name,
const MeshBase mesh 
)

Definition at line 251 of file MooseMeshUtils.C.

Referenced by hasSubdomainName().

252 {
253  if (subdomain_name == "ANY_BLOCK_ID")
254  mooseError("getSubdomainID() does not work with \"ANY_BLOCK_ID\"");
255 
257  if (subdomain_name.empty())
258  return id;
259 
260  if (!MooseUtils::isDigits(subdomain_name))
261  id = mesh.get_id_by_name(subdomain_name);
262  else
263  id = getIDFromName<SubdomainName, SubdomainID>(subdomain_name);
264 
265  return id;
266 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
MeshBase & mesh
subdomain_id_type get_id_by_name(std::string_view name) const
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20

◆ getSubdomainIDs() [1/2]

std::vector< subdomain_id_type > MooseMeshUtils::getSubdomainIDs ( const libMesh::MeshBase mesh,
const std::vector< SubdomainName > &  subdomain_name 
)

Get the associated subdomainIDs for the subdomain names that are passed in.

Parameters
meshThe mesh
subdomain_nameThe names of the subdomains
Returns
The subdomain ids from the passed subdomain names.

Definition at line 199 of file MooseMeshUtils.C.

Referenced by FEProblemBase::checkProblemIntegrity(), convertBlockToMesh(), CoarsenBlockGenerator::generate(), BlockDeletionGenerator::generate(), BreakMeshByBlockGenerator::generate(), ParsedSubdomainGeneratorBase::generate(), RefineBlockGenerator::generate(), getSubdomainIDs(), MooseMesh::getSubdomainIDs(), BlockWeightedPartitioner::initialize(), LibmeshPartitioner::prepareBlocksForSubdomainPartitioner(), SurfaceMeshGeneratorBase::setup(), NodeSetsGeneratorBase::setup(), SideSetsGeneratorBase::setup(), SidesetAroundSubdomainUpdater::SidesetAroundSubdomainUpdater(), and MeshTriangulationUtils::triangulateWithDelaunay().

200 {
201  std::vector<subdomain_id_type> ids;
202 
203  // shortcut for "ANY_BLOCK_ID"
204  if (subdomain_names.size() == 1 && subdomain_names[0] == "ANY_BLOCK_ID")
205  {
206  // since get_mesh_subdomains() requires a prepared mesh, we need to check that here
207  mooseAssert(mesh.is_prepared(),
208  "getSubdomainIDs() should only be called on a prepared mesh if ANY_BLOCK_ID is "
209  "used to query all block IDs");
210  ids.assign(mesh.get_mesh_subdomains().begin(), mesh.get_mesh_subdomains().end());
211  return ids;
212  }
213 
214  // loop through subdomain names and get IDs (this preserves the order of subdomain_names)
215  ids.resize(subdomain_names.size());
216  for (auto i : index_range(subdomain_names))
217  {
218  if (subdomain_names[i] == "ANY_BLOCK_ID")
219  mooseError("getSubdomainIDs() accepts \"ANY_BLOCK_ID\" if and only if it is the only "
220  "subdomain name being queried.");
221  ids[i] = MooseMeshUtils::getSubdomainID(subdomain_names[i], mesh);
222  }
223 
224  return ids;
225 }
bool is_prepared() const
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
MeshBase & mesh
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
Gets the subdomain ID associated with the given SubdomainName.
const std::set< subdomain_id_type > & get_mesh_subdomains() const
auto index_range(const T &sizable)

◆ getSubdomainIDs() [2/2]

std::set< subdomain_id_type > MooseMeshUtils::getSubdomainIDs ( const libMesh::MeshBase mesh,
const std::set< SubdomainName > &  subdomain_name 
)

Definition at line 228 of file MooseMeshUtils.C.

229 {
230  const auto blk_ids = getSubdomainIDs(
231  mesh, std::vector<SubdomainName>(subdomain_names.begin(), subdomain_names.end()));
232  return {blk_ids.begin(), blk_ids.end()};
233 }
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.

◆ hasBoundaryID() [1/2]

bool MooseMeshUtils::hasBoundaryID ( const MeshBase &  input_mesh,
const BoundaryID  id 
)

Whether a particular boundary ID exists in the mesh.

Parameters
inputmesh over which to determine boundary IDs
boundaryID

Referenced by MooseMeshXYCuttingUtils::boundaryTriElemImprover(), AdvancedExtruderGenerator::generate(), and XYMeshLineCutter::generate().

◆ hasBoundaryID() [2/2]

bool MooseMeshUtils::hasBoundaryID ( const MeshBase input_mesh,
const BoundaryID  id 
)

Definition at line 552 of file MooseMeshUtils.C.

Referenced by hasBoundaryName().

553 {
554  const BoundaryInfo & boundary_info = input_mesh.get_boundary_info();
555  std::set<boundary_id_type> boundary_ids = boundary_info.get_boundary_ids();
556 
557  // On a distributed mesh we may have boundary IDs that only exist on
558  // other processors
559  if (!input_mesh.is_replicated())
560  input_mesh.comm().set_union(boundary_ids);
561 
562  return boundary_ids.count(id) && (id != Moose::INVALID_BOUNDARY_ID);
563 }
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
const std::set< boundary_id_type > & get_boundary_ids() const
virtual bool is_replicated() const
void set_union(T &data, const unsigned int root_id) const

◆ hasBoundaryName() [1/2]

bool MooseMeshUtils::hasBoundaryName ( const MeshBase &  input_mesh,
const BoundaryName &  name 
)

◆ hasBoundaryName() [2/2]

bool MooseMeshUtils::hasBoundaryName ( const MeshBase input_mesh,
const BoundaryName &  name 
)

Definition at line 566 of file MooseMeshUtils.C.

567 {
568  const auto id = getBoundaryID(name, input_mesh);
569  return hasBoundaryID(input_mesh, id);
570 }
bool hasBoundaryID(const MeshBase &input_mesh, const BoundaryID id)
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)

◆ hasSubdomainID() [1/2]

bool MooseMeshUtils::hasSubdomainID ( const MeshBase &  input_mesh,
const SubdomainID id 
)

◆ hasSubdomainID() [2/2]

bool MooseMeshUtils::hasSubdomainID ( const MeshBase input_mesh,
const SubdomainID id 
)

Definition at line 531 of file MooseMeshUtils.C.

Referenced by hasSubdomainName().

532 {
533  std::set<SubdomainID> mesh_blocks;
534  input_mesh.subdomain_ids(mesh_blocks);
535 
536  // On a distributed mesh we may have sideset IDs that only exist on
537  // other processors
538  if (!input_mesh.is_replicated())
539  input_mesh.comm().set_union(mesh_blocks);
540 
541  return mesh_blocks.count(id) && (id != Moose::INVALID_BLOCK_ID);
542 }
const Parallel::Communicator & comm() const
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
virtual bool is_replicated() const
void set_union(T &data, const unsigned int root_id) const

◆ hasSubdomainName() [1/2]

bool MooseMeshUtils::hasSubdomainName ( const MeshBase &  input_mesh,
const SubdomainName &  name 
)

◆ hasSubdomainName() [2/2]

bool MooseMeshUtils::hasSubdomainName ( const MeshBase input_mesh,
const SubdomainName &  name 
)

Definition at line 545 of file MooseMeshUtils.C.

546 {
547  const auto id = getSubdomainID(name, input_mesh);
548  return hasSubdomainID(input_mesh, id);
549 }
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)

◆ idSwapParametersProcessor()

template<typename T >
void MooseMeshUtils::idSwapParametersProcessor ( const std::string &  class_name,
const std::string &  id_name,
const std::vector< std::vector< T >> &  id_swaps,
std::vector< std::unordered_map< T, T >> &  id_swap_pairs,
const unsigned int  row_index_shift = 0 
)

Reprocess the swap related input parameters to make pairs out of them to ease further processing.

Parameters
class_namename of the mesh generator class used for exception messages
id_namename of the parameter to be swapped used for exception messages
id_swapsvector of vectors of the ids to be swapped
id_swap_pairsvector of maps of the swapped pairs
row_index_shiftshift to be applied to the row index in the exception messages (useful when this method is utilized to process a fraction of a long vector)

Definition at line 407 of file MooseMeshUtils.h.

Referenced by AdvancedExtruderGenerator::AdvancedExtruderGenerator(), and extraElemIntegerSwapParametersProcessor().

412 {
413  id_swap_pairs.resize(id_swaps.size());
414  for (const auto i : index_range(id_swaps))
415  {
416  const auto & swaps = id_swaps[i];
417  auto & swap_pairs = id_swap_pairs[i];
418 
419  if (swaps.size() % 2)
420  throw MooseException("Row ",
421  row_index_shift + i + 1,
422  " of ",
423  id_name,
424  " in ",
425  class_name,
426  " does not contain an even number of entries! Num entries: ",
427  swaps.size());
428 
429  swap_pairs.reserve(swaps.size() / 2);
430  for (unsigned int j = 0; j < swaps.size(); j += 2)
431  swap_pairs[swaps[j]] = swaps[j + 1];
432  }
433 }
Provides a way for users to bail out of the current solve.
auto index_range(const T &sizable)

◆ isCoPlanar() [1/6]

bool MooseMeshUtils::isCoPlanar ( const std::vector< Point > &  vec_pts,
const Point  plane_nvec,
const Point  fixed_pt 
)

Decides whether all the Points of a vector of Points are in a plane that is defined by a normal vector and an inplane Point.

Parameters
vec_ptsvector of points to be examined
plane_nvecnormal vector of the plane
fixed_pta Point in the plane
Returns
whether all the Points are in the given plane

Referenced by Positions::arePositionsCoplanar(), FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator(), and SurfaceMeshGeneratorBase::get2DElemNormal().

◆ isCoPlanar() [2/6]

bool MooseMeshUtils::isCoPlanar ( const std::vector< Point > &  vec_pts,
const Point  plane_nvec 
)

Decides whether all the Points of a vector of Points are in a plane with a given normal vector.

Parameters
vec_ptsvector of points to be examined
plane_nvecnormal vector of the plane
Returns
whether all the Points are in the same plane with the given normal vector

◆ isCoPlanar() [3/6]

bool MooseMeshUtils::isCoPlanar ( const std::vector< Point > &  vec_pts)

Decides whether all the Points of a vector of Points are coplanar.

Parameters
vec_ptsvector of points to be examined
Returns
whether all the Points are in a same plane

◆ isCoPlanar() [4/6]

bool MooseMeshUtils::isCoPlanar ( const std::vector< Point > &  vec_pts,
const Point  plane_nvec,
const Point  fixed_pt 
)

Definition at line 457 of file MooseMeshUtils.C.

458 {
459  for (const auto & pt : vec_pts)
460  if (!MooseUtils::absoluteFuzzyEqual((pt - fixed_pt) * plane_nvec, 0.0))
461  return false;
462  return true;
463 }

◆ isCoPlanar() [5/6]

bool MooseMeshUtils::isCoPlanar ( const std::vector< Point > &  vec_pts,
const Point  plane_nvec 
)

Definition at line 466 of file MooseMeshUtils.C.

467 {
468  return isCoPlanar(vec_pts, plane_nvec, vec_pts.front());
469 }
bool isCoPlanar(const std::vector< Point > &vec_pts)

◆ isCoPlanar() [6/6]

bool MooseMeshUtils::isCoPlanar ( const std::vector< Point > &  vec_pts)

Definition at line 472 of file MooseMeshUtils.C.

Referenced by isCoPlanar().

473 {
474  // Assuming that overlapped Points are allowed, the Points that are overlapped with vec_pts[0] are
475  // removed before further calculation.
476  std::vector<Point> vec_pts_nonzero{vec_pts[0]};
477  for (const auto i : index_range(vec_pts))
478  if (!MooseUtils::absoluteFuzzyEqual((vec_pts[i] - vec_pts[0]).norm(), 0.0))
479  vec_pts_nonzero.push_back(vec_pts[i]);
480  // 3 or fewer points are always coplanar
481  if (vec_pts_nonzero.size() <= 3)
482  return true;
483  else
484  {
485  for (const auto i : make_range(vec_pts_nonzero.size() - 1))
486  {
487  const Point tmp_pt = (vec_pts_nonzero[i] - vec_pts_nonzero[0])
488  .cross(vec_pts_nonzero[i + 1] - vec_pts_nonzero[0]);
489  // if the three points are not collinear, use cross product as the normal vector of the plane
490  if (!MooseUtils::absoluteFuzzyEqual(tmp_pt.norm(), 0.0))
491  return isCoPlanar(vec_pts_nonzero, tmp_pt.unit());
492  }
493  }
494  // If all the points are collinear, they are also coplanar
495  return true;
496 }
auto norm() const
bool isCoPlanar(const std::vector< Point > &vec_pts)
TypeVector< Real > unit() const
auto norm(const T &a)
IntRange< T > make_range(T beg, T end)
auto index_range(const T &sizable)

◆ makeOrderedNodeList() [1/2]

void MooseMeshUtils::makeOrderedNodeList ( std::vector< std::pair< dof_id_type, dof_id_type >> &  node_assm,
std::vector< dof_id_type > &  elem_id_list,
std::vector< dof_id_type > &  midpoint_node_list,
std::vector< dof_id_type > &  ordered_node_list,
std::vector< dof_id_type > &  ordered_elem_id_list 
)

Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes based on connectivity.

Parameters
node_assmvector of pairs of node ids that represent the sides
elem_id_listvector of element ids that represent the elements that contain the sides
midpoint_node_listvector of node ids that represent the midpoints of the sides for quadratic sides
ordered_node_listvector of node ids that represent the ordered nodes
ordered_elem_id_listvector of element corresponding to the ordered nodes

Definition at line 573 of file MooseMeshUtils.C.

Referenced by MooseMeshXYCuttingUtils::boundaryTriElemImprover(), FillBetweenPointVectorsTools::isClosedLoop(), and makeOrderedNodeList().

578 {
579  // a flag to indicate if the ordered_node_list has been reversed
580  bool is_flipped = false;
581  // Start from the first element, try to find a chain of nodes
582  mooseAssert(node_assm.size(), "Node list must not be empty");
583  ordered_node_list.push_back(node_assm.front().first);
584  if (midpoint_node_list.front() != DofObject::invalid_id)
585  ordered_node_list.push_back(midpoint_node_list.front());
586  ordered_node_list.push_back(node_assm.front().second);
587  ordered_elem_id_list.push_back(elem_id_list.front());
588  // Remove the element that has just been added to ordered_node_list
589  node_assm.erase(node_assm.begin());
590  midpoint_node_list.erase(midpoint_node_list.begin());
591  elem_id_list.erase(elem_id_list.begin());
592  const unsigned int node_assm_size_0 = node_assm.size();
593  for (unsigned int i = 0; i < node_assm_size_0; i++)
594  {
595  // Find nodes to expand the chain
596  dof_id_type end_node_id = ordered_node_list.back();
597  auto isMatch1 = [end_node_id](std::pair<dof_id_type, dof_id_type> old_id_pair)
598  { return old_id_pair.first == end_node_id; };
599  auto isMatch2 = [end_node_id](std::pair<dof_id_type, dof_id_type> old_id_pair)
600  { return old_id_pair.second == end_node_id; };
601  auto result = std::find_if(node_assm.begin(), node_assm.end(), isMatch1);
602  bool match_first;
603  if (result == node_assm.end())
604  {
605  match_first = false;
606  result = std::find_if(node_assm.begin(), node_assm.end(), isMatch2);
607  }
608  else
609  {
610  match_first = true;
611  }
612  // If found, add the node to boundary_ordered_node_list
613  if (result != node_assm.end())
614  {
615  const auto elem_index = std::distance(node_assm.begin(), result);
616  if (midpoint_node_list[elem_index] != DofObject::invalid_id)
617  ordered_node_list.push_back(midpoint_node_list[elem_index]);
618  ordered_node_list.push_back(match_first ? (*result).second : (*result).first);
619  node_assm.erase(result);
620  midpoint_node_list.erase(midpoint_node_list.begin() + elem_index);
621  ordered_elem_id_list.push_back(elem_id_list[elem_index]);
622  elem_id_list.erase(elem_id_list.begin() + elem_index);
623  }
624  // If there are still elements in node_assm and result ==
625  // node_assm.end(), this means the curve is not a loop, the
626  // ordered_node_list is flipped and try the other direction that has not
627  // been examined yet.
628  else
629  {
630  if (is_flipped)
631  // Flipped twice; this means the node list has at least two segments.
632  throw MooseException("The node list provided has more than one segments.");
633 
634  // mark the first flip event.
635  is_flipped = true;
636  std::reverse(ordered_node_list.begin(), ordered_node_list.end());
637  std::reverse(midpoint_node_list.begin(), midpoint_node_list.end());
638  std::reverse(ordered_elem_id_list.begin(), ordered_elem_id_list.end());
639  // As this iteration is wasted, set the iterator backward
640  i--;
641  }
642  }
643 }
Provides a way for users to bail out of the current solve.
uint8_t dof_id_type

◆ makeOrderedNodeList() [2/2]

void MooseMeshUtils::makeOrderedNodeList ( std::vector< std::pair< dof_id_type, dof_id_type >> &  node_assm,
std::vector< dof_id_type > &  elem_id_list,
std::vector< dof_id_type > &  ordered_node_list,
std::vector< dof_id_type > &  ordered_elem_id_list 
)

Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes based on connectivity.

Parameters
node_assmvector of pairs of node ids that represent the sides
elem_id_listvector of element ids that represent the elements that contain the sides
ordered_node_listvector of node ids that represent the ordered nodes
ordered_elem_id_listvector of element corresponding to the ordered nodes

Definition at line 646 of file MooseMeshUtils.C.

650 {
651  std::vector<dof_id_type> dummy_midpoint_node_list(node_assm.size(), DofObject::invalid_id);
653  node_assm, elem_id_list, dummy_midpoint_node_list, ordered_node_list, ordered_elem_id_list);
654 }
void makeOrderedNodeList(std::vector< std::pair< dof_id_type, dof_id_type >> &node_assm, std::vector< dof_id_type > &elem_id_list, std::vector< dof_id_type > &midpoint_node_list, std::vector< dof_id_type > &ordered_node_list, std::vector< dof_id_type > &ordered_elem_id_list)
Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes bas...

◆ mergeBoundaryIDsWithSameName() [1/2]

void MooseMeshUtils::mergeBoundaryIDsWithSameName ( MeshBase mesh)

Definition at line 38 of file MooseMeshUtils.C.

39 {
40  // We check if we have the same boundary name with different IDs. If we do, we assign the
41  // first ID to every occurrence.
42  const auto & side_bd_name_map = mesh.get_boundary_info().get_sideset_name_map();
43  const auto & node_bd_name_map = mesh.get_boundary_info().get_nodeset_name_map();
44  std::map<boundary_id_type, boundary_id_type> same_name_ids;
45 
46  auto populate_map = [](const std::map<boundary_id_type, std::string> & map,
47  std::map<boundary_id_type, boundary_id_type> & same_ids)
48  {
49  for (const auto & pair_outer : map)
50  for (const auto & pair_inner : map)
51  // The last condition is needed to make sure we only store one combination
52  if (pair_outer.second == pair_inner.second && pair_outer.first != pair_inner.first &&
53  same_ids.find(pair_inner.first) == same_ids.end())
54  same_ids[pair_outer.first] = pair_inner.first;
55  };
56 
57  populate_map(side_bd_name_map, same_name_ids);
58  populate_map(node_bd_name_map, same_name_ids);
59 
60  for (const auto & [id1, id2] : same_name_ids)
62 }
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
void renumber_id(boundary_id_type old_id, boundary_id_type new_id)
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const

◆ mergeBoundaryIDsWithSameName() [2/2]

void MooseMeshUtils::mergeBoundaryIDsWithSameName ( MeshBase &  mesh)

Merges the boundary IDs of boundaries that have the same names but different IDs.

Parameters
meshThe input mesh whose boundaries we will modify

Referenced by MeshRepairGenerator::generate(), and StitchMeshGenerator::generate().

◆ meshCentroidCalculator() [1/2]

Point MooseMeshUtils::meshCentroidCalculator ( const MeshBase &  mesh)

Calculates the centroid of a MeshBase.

Parameters
meshinput mesh whose centroid needs to be calculated
Returns
a Point corresponding to the mesh centroid

Referenced by Boundary2DDelaunayGenerator::General2DDelaunay(), SurfaceSubdomainsDelaunayRemesher::General2DDelaunay(), FillBetweenSidesetsGenerator::generate(), AdvancedExtruderGenerator::generate(), and MultiAppPositions::initialize().

◆ meshCentroidCalculator() [2/2]

Point MooseMeshUtils::meshCentroidCalculator ( const MeshBase mesh)

Definition at line 280 of file MooseMeshUtils.C.

281 {
282  Point centroid_pt = Point(0.0, 0.0, 0.0);
283  Real vol_tmp = 0.0;
284  for (const auto & elem : mesh.active_local_element_ptr_range())
285  {
286  Real elem_vol = elem->volume();
287  centroid_pt += (elem->true_centroid()) * elem_vol;
288  vol_tmp += elem_vol;
289  }
290  mesh.comm().sum(centroid_pt);
291  mesh.comm().sum(vol_tmp);
292  centroid_pt /= vol_tmp;
293  return centroid_pt;
294 }
MeshBase & mesh
const Parallel::Communicator & comm() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ swapNodesInElem() [1/2]

void MooseMeshUtils::swapNodesInElem ( Elem &  elem,
const unsigned int  nd1,
const unsigned int  nd2 
)

Swap two nodes within an element.

Parameters
elemelement whose nodes need to be swapped
nd1index of the first node to be swapped
nd2index of the second node to be swapped

Referenced by AdvancedExtruderGenerator::generate().

◆ swapNodesInElem() [2/2]

void MooseMeshUtils::swapNodesInElem ( Elem elem,
const unsigned int  nd1,
const unsigned int  nd2 
)

Definition at line 657 of file MooseMeshUtils.C.

658 {
659  Node * n_temp = elem.node_ptr(nd1);
660  elem.set_node(nd1, elem.node_ptr(nd2));
661  elem.set_node(nd2, n_temp);
662 }
virtual Node *& set_node(const unsigned int i)
const Node * node_ptr(const unsigned int i) const