https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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.
 
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.
 
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.
 
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.
 
std::vector< BoundaryIDgetBoundaryIDs (const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown)
 Gets the boundary IDs with their names.
 
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.
 
BoundaryID getBoundaryID (const BoundaryName &boundary_name, const MeshBase &mesh)
 Gets the boundary ID associated with the given BoundaryName.
 
SubdomainID getSubdomainID (const SubdomainName &subdomain_name, const MeshBase &mesh)
 Gets the subdomain ID associated with the given SubdomainName.
 
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.
 
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.
 
Point boundaryCentroidCalculator (const BoundaryName &boundary, MeshBase &mesh)
 Calculates the centroid of a boundary on a mesh.
 
RealVectorValue boundaryWeightedNormal (const BoundaryName &boundary, MeshBase &mesh)
 Calculates the side-volume weighted (side-vertex) average normal of a boundary on a mesh.
 
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.
 
template<typename P , typename C >
computeDistanceToAxis (const P &point, const Point &origin, const RealVectorValue &direction)
 Computes the distance to a general axis.
 
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.
 
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.
 
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_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.
 
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.
 
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.
 
bool isCoPlanar (const std::vector< Point > &vec_pts)
 Decides whether all the Points of a vector of Points are coplanar.
 
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.
 
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.
 
bool hasSubdomainID (const MeshBase &input_mesh, const SubdomainID &id)
 Whether a particular subdomain ID exists in the mesh.
 
bool hasSubdomainName (const MeshBase &input_mesh, const SubdomainName &name)
 Whether a particular subdomain name exists in the mesh.
 
bool hasBoundaryID (const MeshBase &input_mesh, const BoundaryID id)
 Whether a particular boundary ID exists in the mesh.
 
bool hasBoundaryName (const MeshBase &mesh, const BoundaryName &name)
 Whether a particular boundary name exists in the mesh.
 
bool hasBoundaryNameOrID (const MeshBase &mesh, const BoundaryName &name_or_id)
 Whether a particular boundary name or ID exists in the mesh.
 
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.
 
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.
 
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.
 
void swapNodesInElem (Elem &elem, const unsigned int nd1, const unsigned int nd2)
 Swap two nodes within an element.
 
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.
 
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.
 
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.
 
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.
 
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.
 
std::set< dof_id_type > getBoundaryNodes (const MeshBase &mesh, const BoundaryID boundary_id)
 Get all the nodes on that particular boundary, whether a nodeset or a sideset.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
void addExternalBoundary (MeshBase &mesh, const BoundaryID extern_bid, bool &has_external_bid)
 Adds a sideset for the external boundary of the mesh (e.g.
 
void mergeBoundaryIDsWithSameName (MeshBase &mesh)
 
void changeBoundaryId (MeshBase &mesh, const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
 
std::vector< boundary_id_typegetBoundaryIDs (const MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
 
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 &mesh, const BoundaryName &name)
 
bool hasBoundaryNameOrID (const MeshBase &mesh, const BoundaryName &name_or_id)
 
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)
 
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)
 
void swapNodesInElem (Elem &elem, const unsigned int nd1, const unsigned int nd2)
 
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)
 
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 SurfaceSubdomainsDelaunayRemesher::generate(), XYDelaunayGenerator::generate(), and XYTriangleBoundaryLayerGenerator::generate().

◆ addExternalBoundary() [2/2]

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

Definition at line 1562 of file MooseMeshUtils.C.

1563{
1564 auto & binfo = mesh.get_boundary_info();
1565 for (const auto & elem : mesh.active_element_ptr_range())
1566 for (const auto & i_side : elem->side_index_range())
1567 if (elem->neighbor_ptr(i_side) == nullptr)
1568 {
1569 has_external_bid = true;
1570 binfo.add_side(elem, i_side, extern_bid);
1571 }
1572}
for(PetscInt i=0;i< nvars;++i)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
const BoundaryInfo & get_boundary_info() const
MeshBase & mesh
if(subdm)

◆ 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 302 of file MooseMeshUtils.C.

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

◆ 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 335 of file MooseMeshUtils.C.

336{
337 // Need boundaries to be synchronized
338 if (!mesh.preparation().has_boundary_id_sets)
340 BoundaryInfo & mesh_boundary_info = mesh.get_boundary_info();
341 boundary_id_type boundary_id = mesh_boundary_info.get_id_by_name(boundary);
342 const auto side_list = mesh_boundary_info.build_side_list();
343
344 // Initialize sums
345 Real volume_sum = 0;
346 RealVectorValue volume_weighted_normal_sum(0, 0, 0);
347
348 for (const auto & [eid, side_i, bid] : side_list)
349 {
350 if (bid != boundary_id)
351 continue;
352
353 // Get the side
354 const auto elem = mesh.elem_ptr(eid);
355 const auto side = elem->side_ptr(side_i);
356
357 volume_sum += side->volume();
358 volume_weighted_normal_sum += side->volume() * elem->side_vertex_average_normal(side_i);
359 }
360 // Sum across processes
361 mesh.comm().sum(volume_weighted_normal_sum);
362 mesh.comm().sum(volume_sum);
363
364 return volume_weighted_normal_sum / volume_sum;
365}

◆ 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 710 of file MooseMeshUtils.C.

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

◆ 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

Referenced by buildLoopBoundaryOf2DMesh().

◆ 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 973 of file MooseMeshUtils.C.

974{
975 if (!input_mesh.is_serial())
977 "Input 2D mesh should be serialized for extracting the loop boundary mesh.\nInput mesh:" +
978 input_mesh.get_info());
979
980 // Get all nodes on that boundary
981 // Boundary ID might be a sideset or a nodeset, get nodes regardless
982 const auto particular_node_ids = getBoundaryNodes(input_mesh, boundary_id);
983
984 std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> nid_to_eids_map;
985 // Fill the map from looping over elements
986 for (const auto & elem :
987 as_range(input_mesh.active_elements_begin(), input_mesh.active_elements_end()))
988 {
989 for (const auto & nd : elem->node_ref_range())
990 {
991 // Only add the element id if the node is on the boundary
992 if (!particular_node_ids.count(nd.id()))
993 continue;
994
995 auto & elem_ids = nid_to_eids_map[nd.id()];
996 elem_ids.insert(elem->id());
997 }
998 }
999 return nid_to_eids_map;
1000}
std::set< dof_id_type > getBoundaryNodes(const MeshBase &mesh, const BoundaryID boundary_id)
Get all the nodes on that particular boundary, whether a nodeset or a sideset.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)

◆ 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 758 of file MooseMeshUtils.C.

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

1542{
1543 std::vector<unsigned int> nums_edges_between_points;
1544 const auto n_points = points.size();
1545 for (auto i : make_range(n_points))
1546 {
1547 if (!loop && (i + 1) == n_points)
1548 break;
1549
1550 const auto ip1 = (i + 1) % n_points;
1551 const Real length = (points[ip1] - points[i]).norm();
1552 const unsigned int n_elems = std::max(
1553 static_cast<unsigned int>(std::ceil(length / max_elem_size)), static_cast<unsigned int>(1));
1554 nums_edges_between_points.push_back(n_elems);
1555 }
1556
1557 buildPolyLineMesh(
1558 mesh, points, {}, loop, start_boundary, end_boundary, nums_edges_between_points);
1559}
IntRange< T > make_range(T beg, T end)

◆ 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 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(), buildPolyLineMesh(), buildPolyLineMesh(), SurfaceSubdomainsDelaunayRemesher::General2DDelaunay(), and PolyLineMeshGenerator::generate().

◆ buildPolyLineMesh() [4/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 1524 of file MooseMeshUtils.C.

1530{
1532 mesh, points, {}, loop, start_boundary, end_boundary, nums_edges_between_points);
1533}
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.

◆ buildPolyLineMesh() [5/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() [6/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 1416 of file MooseMeshUtils.C.

1423{
1424 mooseAssert(nums_edges_between_points.size() == 1 ||
1425 nums_edges_between_points.size() == points.size() - 1 + loop,
1426 "nums_edges_between_points must be either a single value or have the same number of "
1427 "entries as segments defined by the points.");
1428 mooseAssert(
1429 mid_points.size() == 0 || mid_points.size() == points.size() - (loop ? 0 : 1),
1430 "mid_points must be either empty or have the consistent number of entries as points.");
1431 mooseAssert(
1432 mid_points.size() == 0 ||
1433 (nums_edges_between_points.size() == 1 && nums_edges_between_points.front() == 1) ||
1434 (nums_edges_between_points.size() == points.size() - 1 + loop &&
1435 std::all_of(nums_edges_between_points.begin(),
1436 nums_edges_between_points.end(),
1437 [](unsigned int n) { return n == 1; })),
1438 "mid_points can only be provided if each segment has exactly one edge.");
1439
1440 const auto n_points = points.size();
1441 for (auto i : make_range(n_points))
1442 {
1443 const auto & num_edges_between_points =
1444 (nums_edges_between_points.size() == 1)
1445 ? nums_edges_between_points[0]
1446 : (i == nums_edges_between_points.size() ? 0 : nums_edges_between_points[i]);
1447
1448 Point p = points[i];
1449 const auto pt_counter = (nums_edges_between_points.size() == 1)
1450 ? i
1451 : std::accumulate(nums_edges_between_points.begin(),
1452 nums_edges_between_points.begin() + i,
1453 0);
1455 p, nums_edges_between_points.size() == 1 ? (i * num_edges_between_points) : pt_counter);
1456
1457 if (num_edges_between_points > 1)
1458 {
1459 if (!loop && (i + 1) == n_points)
1460 break;
1461
1462 const auto ip1 = (i + 1) % n_points;
1463 const Point pvec = (points[ip1] - p) / num_edges_between_points;
1464
1465 for (auto j : make_range(1u, num_edges_between_points))
1466 {
1467 p += pvec;
1469 p,
1470 (nums_edges_between_points.size() == 1 ? (i * num_edges_between_points) : pt_counter) +
1471 j);
1472 }
1473 }
1474 }
1475 // Add mid points if applicable. When mid points are provided, each segment has exactly one edge,
1476 // so the midpoint node ids follow the vertex node ids.
1477 for (const auto & i : make_range(mid_points.size()))
1478 mesh.add_point(mid_points[i], n_points + i);
1479
1480 const auto n_segments = loop ? n_points : (n_points - 1);
1481 const auto n_elem =
1482 nums_edges_between_points.size() == 1
1483 ? n_segments * nums_edges_between_points[0]
1484 : std::accumulate(nums_edges_between_points.begin(), nums_edges_between_points.end(), 0);
1485 const auto max_nodes =
1486 (nums_edges_between_points.size() == 1 ? n_segments * nums_edges_between_points[0]
1487 : std::accumulate(nums_edges_between_points.begin(),
1488 nums_edges_between_points.end(),
1489 0)) +
1490 (loop ? 0 : 1);
1491 for (auto i : make_range(n_elem))
1492 {
1493 std::unique_ptr<Elem> elem;
1494 if (mid_points.size())
1495 {
1496 elem = std::make_unique<Edge3>();
1497 elem->set_node(2, mesh.node_ptr(n_points + i));
1498 }
1499 else
1500 elem = Elem::build(EDGE2);
1501 const auto ip1 = (i + 1) % max_nodes;
1502 elem->set_node(0, mesh.node_ptr(i));
1503 elem->set_node(1, mesh.node_ptr(ip1));
1504 elem->set_id() = i;
1505 mesh.add_elem(std::move(elem));
1506 }
1507
1508 if (!loop)
1509 {
1511 std::vector<BoundaryName> bdy_names{start_boundary, end_boundary};
1512 std::vector<boundary_id_type> ids = MooseMeshUtils::getBoundaryIDs(mesh, bdy_names, true);
1513 bi.add_side(mesh.elem_ptr(0), 0, ids[0]);
1514 bi.add_side(mesh.elem_ptr(n_elem - 1), 1, ids[1]);
1515 }
1516 else
1517 mooseAssert(start_boundary.empty() && end_boundary.empty(),
1518 "Cannot assign start/end boundaries on a looped polyline.");
1519
1521}
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
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.
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)

◆ changeBoundaryId() [1/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 boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
void remove_id(boundary_id_type id, bool global=false)
void remove_side(const Elem *elem, const unsigned short int side)
void unset_is_prepared()

◆ changeBoundaryId() [2/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().

◆ 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 274 of file MooseMeshUtils.C.

275{
276 for (const auto & elem : mesh.element_ptr_range())
277 if (elem->subdomain_id() == old_id)
278 elem->subdomain_id() = new_id;
279
280 // global cached information may now be out of sync
282}

◆ 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 SubProblem &s, SubdomainID sub_id, const P &point, C &factor, SubdomainID neighbor_sub_id=libMesh::Elem::invalid_subdomain_id)
Computes a conversion multiplier for use when computing integraals for the current coordinate system ...
Definition Assembly.C:43
Real & faceCoord()
Sets/gets the coordinate transformation factor (for e.g.
Definition FaceInfo.h:68
const Point & faceCentroid() const
Returns the coordinates of the face centroid.
Definition FaceInfo.h:75

◆ 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 368 of file MooseMeshUtils.C.

371{
372 Real distance = 0;
373 mooseAssert(MooseUtils::absoluteFuzzyEqual(direction.norm_sq(), 1),
374 "Direction should be normalized");
375 for (const auto & node : mesh.node_ptr_range())
376 if (const auto dist_node = (*node - origin).cross(direction).norm(); dist_node > distance)
377 distance = dist_node;
378 mesh.comm().max(distance);
379 return distance;
380}
void max(const T &r, T &o, Request &req) const
auto norm_sq() const
Real distance(const Point &p)

◆ 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(), Boundary2DDelaunayGenerator::generate(), SubdomainsFromPartitionerGenerator::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 1177 of file MooseMeshUtils.C.

1180{
1181 if (!source_mesh.is_replicated())
1182 mooseError("This generator does not support distributed meshes.");
1183
1184 const auto target_block_ids = MooseMeshUtils::getSubdomainIDs(source_mesh, target_blocks);
1185
1186 // Check that the block ids/names exist in the mesh
1187 std::set<SubdomainID> mesh_blocks;
1188 source_mesh.subdomain_ids(mesh_blocks);
1189
1190 for (const auto i : index_range(target_block_ids))
1191 if (target_block_ids[i] == Moose::INVALID_BLOCK_ID || !mesh_blocks.count(target_block_ids[i]))
1192 {
1193 mooseException("The target_block '", target_blocks[i], "' was not found within the mesh.");
1194 }
1195
1196 // know which nodes have already been inserted, by tracking the old mesh's node's ids'
1197 std::unordered_map<dof_id_type, dof_id_type> old_new_node_map;
1198
1199 for (const auto target_block_id : target_block_ids)
1200 {
1201
1202 for (auto elem : source_mesh.active_subdomain_elements_ptr_range(target_block_id))
1203 {
1204 if (elem->level() != 0)
1205 mooseError("Refined blocks are not supported by this generator. "
1206 "Can you re-organize mesh generators to refine after converting the block?");
1207
1208 // make a deep copy so that mutiple meshes' destructors don't segfault at program termination
1209 auto copy = elem->build(elem->type());
1210
1211 // Keep the subdomain id
1212 copy->subdomain_id() = elem->subdomain_id();
1213
1214 // index of node in the copy element must be managed manually as there is no intelligent
1215 // insert method
1216 dof_id_type copy_n_index = 0;
1217
1218 // correctly assign new copies of nodes, loop over nodes
1219 for (dof_id_type i : elem->node_index_range())
1220 {
1221 auto & n = elem->node_ref(i);
1222
1223 if (old_new_node_map.count(n.id()))
1224 {
1225 // case where we have already inserted this particular point before
1226 // then we need to find the already-inserted one and hook it up right
1227 // to it's respective element
1228 copy->set_node(copy_n_index++, target_mesh.node_ptr(old_new_node_map[n.id()]));
1229 }
1230 else
1231 {
1232 // case where we've NEVER inserted this particular point before
1233 // add them both to the element and the mesh
1234
1235 // Nodes' IDs are their indexes in the nodes' respective mesh
1236 // If we set them as invalid they are automatically assigned
1237 // Add to mesh, auto-assigning a new id.
1238 Node * node = target_mesh.add_point(elem->point(i));
1239
1240 // Add to element copy (manually)
1241 copy->set_node(copy_n_index++, node);
1242
1243 // remember the (old) ID
1244 old_new_node_map[n.id()] = node->id();
1245 }
1246 }
1247
1248 // it is ok to release the copy element into the mesh because derived meshes class
1249 // (ReplicatedMesh, DistributedMesh) manage their own elements, will delete them
1250 target_mesh.add_elem(copy.release());
1251 }
1252 }
1253
1254 // Move subdomain names
1255 for (const auto sbd_id : target_block_ids)
1256 target_mesh.set_subdomain_name(sbd_id, source_mesh.subdomain_name(sbd_id));
1257}
unsigned int count
Definition MortarUtils.C:53
virtual bool is_replicated() const
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
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.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
auto index_range(const T &sizable)

◆ 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.

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}
@ COORD_RZ
Definition MooseTypes.h:866
@ COORD_RSPHERICAL
Definition MooseTypes.h:867
@ COORD_XYZ
Definition MooseTypes.h:865

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

◆ 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.

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

Referenced by coordTransformFactor().

◆ 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 1260 of file MooseMeshUtils.C.

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

◆ 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(), Boundary2DDelaunayGenerator::generate(), and LowerDBlockFromSidesetGenerator::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 1031 of file MooseMeshUtils.C.

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

◆ extraElemIntegerSwapParametersProcessor() [1/2]

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

Referenced by AdvancedExtruderGenerator::AdvancedExtruderGenerator().

◆ extraElemIntegerSwapParametersProcessor() [2/2]

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 
)

Definition at line 678 of file MooseMeshUtils.C.

684{
685 elem_integers_swap_pairs.reserve(num_sections * num_integers);
686 for (const auto i : make_range(num_integers))
687 {
688 const auto & elem_integer_swaps = elem_integers_swaps[i];
689 std::vector<std::unordered_map<dof_id_type, dof_id_type>> elem_integer_swap_pairs;
690 try
691 {
693 "elem_integers_swaps",
694 elem_integer_swaps,
695 elem_integer_swap_pairs,
696 i * num_sections);
697 }
698 catch (const MooseException & e)
699 {
700 throw MooseException(e.what());
701 }
702
703 elem_integers_swap_pairs.insert(elem_integers_swap_pairs.end(),
704 elem_integer_swap_pairs.begin(),
705 elem_integer_swap_pairs.end());
706 }
707}
Provides a way for users to bail out of the current solve.
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.

◆ 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 241 of file MooseMeshUtils.C.

242{
244 if (boundary_name.empty())
245 return id;
246
247 if (!MooseUtils::isDigits(boundary_name))
248 id = mesh.get_boundary_info().get_id_by_name(boundary_name);
249 else
250 id = getIDFromName<BoundaryName, BoundaryID>(boundary_name);
251
252 return id;
253}
const BoundaryID INVALID_BOUNDARY_ID
Definition MooseTypes.C:22

◆ getBoundaryIDs() [1/3]

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}

◆ getBoundaryIDs() [2/3]

std::vector< BoundaryID > 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.

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

◆ getBoundaryIDs() [3/3]

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

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.

122{
123 libmesh_parallel_only(mesh.comm());
124
125 const BoundaryInfo & boundary_info = mesh.get_boundary_info();
126 const std::map<BoundaryID, std::string> & sideset_map = boundary_info.get_sideset_name_map();
127 const std::map<BoundaryID, std::string> & nodeset_map = boundary_info.get_nodeset_name_map();
128
129 BoundaryID current_max_boundary_id = 0;
130 /* It is required to generate a new ID for a given name. It is used often in mesh modifiers such
131 * as SideSetsBetweenSubdomains. Then we need to check the current boundary ids since they are
132 * changing during "mesh modify()", and figure out the right max boundary ID. Most of mesh
133 * modifiers are running in serial, and we won't involve a global communication.
134 */
135 if (generate_unknown)
136 {
137 bool has_boundary_id_sets = mesh.preparation().has_boundary_id_sets;
138 mesh.comm().min(has_boundary_id_sets);
139
140 const auto & bids = has_boundary_id_sets ? boundary_info.get_global_boundary_ids()
141 : boundary_info.get_boundary_ids();
142 current_max_boundary_id = bids.empty() ? 0 : *(bids.rbegin());
143
144 if (!has_boundary_id_sets)
145 mesh.comm().max(current_max_boundary_id);
146 }
147
148 BoundaryID max_boundary_id = mesh_boundary_ids.empty() ? 0 : *(mesh_boundary_ids.rbegin());
149
150 max_boundary_id =
151 max_boundary_id > current_max_boundary_id ? max_boundary_id : current_max_boundary_id;
152
153 std::vector<BoundaryID> ids(boundary_name.size());
154 for (const auto i : index_range(boundary_name))
155 {
156 if (boundary_name[i] == "ANY_BOUNDARY_ID")
157 {
158 ids.assign(mesh_boundary_ids.begin(), mesh_boundary_ids.end());
159 if (i)
160 mooseWarning("You passed \"ANY_BOUNDARY_ID\" in addition to other boundary_names. This "
161 "may be a logic error.");
162 break;
163 }
164
165 if (boundary_name[i].empty() && !generate_unknown)
166 mooseError("Incoming boundary name is empty and we are not generating unknown boundary IDs. "
167 "This is invalid.");
168
169 BoundaryID id;
170
171 if (boundary_name[i].empty() || !MooseUtils::isDigits(boundary_name[i]))
172 {
178 if (generate_unknown &&
179 !MooseUtils::doesMapContainValue(sideset_map, std::string(boundary_name[i])) &&
180 !MooseUtils::doesMapContainValue(nodeset_map, std::string(boundary_name[i])))
181 id = ++max_boundary_id;
182 else
183 id = boundary_info.get_id_by_name(boundary_name[i]);
184 }
185 else
186 id = getIDFromName<BoundaryName, BoundaryID>(boundary_name[i]);
187
188 ids[i] = id;
189 }
190
191 return ids;
192}
void min(const T &r, T &o, Request &req) const
const std::set< boundary_id_type > & get_global_boundary_ids() const
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const
const std::map< boundary_id_type, std::string > & get_sideset_name_map() 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 195 of file MooseMeshUtils.C.

198{
199 auto boundaries = getBoundaryIDs(mesh, boundary_name, generate_unknown);
200 return std::set<BoundaryID>(boundaries.begin(), boundaries.end());
201}

Referenced by DomainUserObject::DomainUserObject().

◆ 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

Referenced by buildBoundaryNodeToElemMap().

◆ getBoundaryNodes() [2/2]

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

Definition at line 1003 of file MooseMeshUtils.C.

1004{
1005 std::set<dof_id_type> boundary_node_ids;
1006 const BoundaryInfo & boundary_info = mesh.get_boundary_info();
1007
1008 // Get all nodes from the sideset with ID of boundary_id
1009 const auto & bc_sides =
1010 boundary_info.build_side_list(libMesh::BoundaryInfo::BCTupleSortBy::BOUNDARY_ID);
1011 for (const auto & [elem_id, side, bc_id] : bc_sides)
1012 {
1013 if (bc_id == boundary_id)
1014 {
1015 const auto elem = mesh.elem_ptr(elem_id);
1016 for (const auto ni : elem->nodes_on_side(side))
1017 boundary_node_ids.insert(elem->node_id(ni));
1018 }
1019 }
1020
1021 // Get all nodes from nodeset with ID of boundary_id
1022 const auto & bc_nodes = boundary_info.build_node_list();
1023 for (const auto & [n_id, bc_id] : bc_nodes)
1024 if (bc_id == boundary_id)
1025 boundary_node_ids.insert(n_id);
1026
1027 return boundary_node_ids;
1028}
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 383 of file MooseMeshUtils.C.

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

◆ 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 383 of file MooseMeshUtils.h.

384{
385 if (!MooseUtils::isDigits(name))
387 "'name' ", name, " should only contain digits that can be converted to a numerical type.");
388 long long id = std::stoll(name);
389 Q id_Q = Q(id);
390 if (id < std::numeric_limits<Q>::min() || id > std::numeric_limits<Q>::max())
391 mooseError(MooseUtils::prettyCppType<T>(&name),
392 " ",
393 name,
394 " is not within the numeric limits of the expected ID type ",
395 MooseUtils::prettyCppType<Q>(&id_Q),
396 ".");
397
398 return id_Q;
399}

◆ getNextFreeBoundaryID() [1/2]

BoundaryID MooseMeshUtils::getNextFreeBoundaryID ( MeshBase &  input_mesh)

◆ getNextFreeBoundaryID() [2/2]

BoundaryID MooseMeshUtils::getNextFreeBoundaryID ( MeshBase input_mesh)

Definition at line 524 of file MooseMeshUtils.C.

525{
526 if (!input_mesh.preparation().has_boundary_id_sets)
528
529 auto boundary_ids = input_mesh.get_boundary_info().get_boundary_ids();
530 if (boundary_ids.empty())
531 return 0;
532 return (*boundary_ids.rbegin() + 1);
533}

◆ getNextFreeSubdomainID() [1/2]

SubdomainID MooseMeshUtils::getNextFreeSubdomainID ( MeshBase &  input_mesh)

◆ getNextFreeSubdomainID() [2/2]

SubdomainID MooseMeshUtils::getNextFreeSubdomainID ( MeshBase input_mesh)

Definition at line 504 of file MooseMeshUtils.C.

505{
506 // Call this to get most up to date block id information
507 input_mesh.cache_elem_data();
508
509 std::set<SubdomainID> preexisting_subdomain_ids;
510 input_mesh.subdomain_ids(preexisting_subdomain_ids);
511 if (preexisting_subdomain_ids.empty())
512 return 0;
513 else
514 {
515 const auto highest_subdomain_id =
516 *std::max_element(preexisting_subdomain_ids.begin(), preexisting_subdomain_ids.end());
517 mooseAssert(highest_subdomain_id < std::numeric_limits<SubdomainID>::max(),
518 "A SubdomainID with max possible value was found");
519 return highest_subdomain_id + 1;
520 }
521}

◆ 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 256 of file MooseMeshUtils.C.

257{
258 if (subdomain_name == "ANY_BLOCK_ID")
259 mooseError("getSubdomainID() does not work with \"ANY_BLOCK_ID\"");
260
262 if (subdomain_name.empty())
263 return id;
264
265 if (!MooseUtils::isDigits(subdomain_name))
266 id = mesh.get_id_by_name(subdomain_name);
267 else
268 id = getIDFromName<SubdomainName, SubdomainID>(subdomain_name);
269
270 return id;
271}
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::set< subdomain_id_type > MooseMeshUtils::getSubdomainIDs ( const libMesh::MeshBase mesh,
const std::set< SubdomainName > &  subdomain_name 
)

Definition at line 233 of file MooseMeshUtils.C.

234{
235 const auto blk_ids = getSubdomainIDs(
236 mesh, std::vector<SubdomainName>(subdomain_names.begin(), subdomain_names.end()));
237 return {blk_ids.begin(), blk_ids.end()};
238}

◆ getSubdomainIDs() [2/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 204 of file MooseMeshUtils.C.

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

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

◆ 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(), XYMeshLineCutter::generate(), and hasBoundaryNameOrID().

◆ hasBoundaryID() [2/2]

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

Definition at line 557 of file MooseMeshUtils.C.

558{
559 const BoundaryInfo & boundary_info = input_mesh.get_boundary_info();
560 std::set<boundary_id_type> boundary_ids = boundary_info.get_boundary_ids();
561
562 // On a distributed mesh we may have boundary IDs that only exist on
563 // other processors
564 if (!input_mesh.is_replicated())
565 input_mesh.comm().set_union(boundary_ids);
566
567 return boundary_ids.count(id) && (id != Moose::INVALID_BOUNDARY_ID);
568}

◆ hasBoundaryName() [1/2]

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

Whether a particular boundary name exists in the mesh.

This returns true if name is non-empty and is a name (not ID) that exists.

Parameters
meshmesh over which to determine boundary names
nameboundary name

◆ hasBoundaryName() [2/2]

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

Definition at line 571 of file MooseMeshUtils.C.

572{
573 const BoundaryInfo & boundary_info = mesh.get_boundary_info();
574 const BoundaryID id = boundary_info.get_id_by_name(name);
575 return id != Moose::INVALID_BOUNDARY_ID;
576}

◆ hasBoundaryNameOrID() [1/2]

bool MooseMeshUtils::hasBoundaryNameOrID ( const MeshBase &  mesh,
const BoundaryName &  name_or_id 
)

◆ hasBoundaryNameOrID() [2/2]

bool MooseMeshUtils::hasBoundaryNameOrID ( const MeshBase mesh,
const BoundaryName &  name_or_id 
)

Definition at line 579 of file MooseMeshUtils.C.

580{
581 const auto id = getBoundaryID(name_or_id, mesh);
582 return hasBoundaryID(mesh, id);
583}
bool hasBoundaryID(const MeshBase &input_mesh, const BoundaryID id)
Whether a particular boundary ID exists in the mesh.
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
Gets the boundary ID associated with the given BoundaryName.

◆ 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 536 of file MooseMeshUtils.C.

537{
538 std::set<SubdomainID> mesh_blocks;
539 input_mesh.subdomain_ids(mesh_blocks);
540
541 // On a distributed mesh we may have sideset IDs that only exist on
542 // other processors
543 if (!input_mesh.is_replicated())
544 input_mesh.comm().set_union(mesh_blocks);
545
546 return mesh_blocks.count(id) && (id != Moose::INVALID_BLOCK_ID);
547}

◆ 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 550 of file MooseMeshUtils.C.

551{
552 const auto id = getSubdomainID(name, input_mesh);
553 return hasSubdomainID(input_mesh, id);
554}
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh.

◆ 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 420 of file MooseMeshUtils.h.

425{
426 id_swap_pairs.resize(id_swaps.size());
427 for (const auto i : index_range(id_swaps))
428 {
429 const auto & swaps = id_swaps[i];
430 auto & swap_pairs = id_swap_pairs[i];
431
432 if (swaps.size() % 2)
433 throw MooseException("Row ",
434 row_index_shift + i + 1,
435 " of ",
436 id_name,
437 " in ",
438 class_name,
439 " does not contain an even number of entries! Num entries: ",
440 swaps.size());
441
442 swap_pairs.reserve(swaps.size() / 2);
443 for (unsigned int j = 0; j < swaps.size(); j += 2)
444 swap_pairs[swaps[j]] = swaps[j + 1];
445 }
446}

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

◆ isCoPlanar() [1/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() [2/6]

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

Definition at line 477 of file MooseMeshUtils.C.

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

◆ isCoPlanar() [3/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() [4/6]

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

Definition at line 471 of file MooseMeshUtils.C.

472{
473 return isCoPlanar(vec_pts, plane_nvec, vec_pts.front());
474}
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 vecto...

◆ isCoPlanar() [5/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(), SurfaceMeshGeneratorBase::get2DElemNormal(), isCoPlanar(), and isCoPlanar().

◆ isCoPlanar() [6/6]

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

Definition at line 462 of file MooseMeshUtils.C.

463{
464 for (const auto & pt : vec_pts)
465 if (!MooseUtils::absoluteFuzzyEqual((pt - fixed_pt) * plane_nvec, 0.0))
466 return false;
467 return true;
468}

◆ makeOrderedNodeList() [1/4]

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

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

◆ makeOrderedNodeList() [2/4]

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 
)

Definition at line 586 of file MooseMeshUtils.C.

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

◆ makeOrderedNodeList() [3/4]

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

◆ makeOrderedNodeList() [4/4]

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 
)

Definition at line 659 of file MooseMeshUtils.C.

663{
664 std::vector<dof_id_type> dummy_midpoint_node_list(node_assm.size(), DofObject::invalid_id);
666 node_assm, elem_id_list, dummy_midpoint_node_list, ordered_node_list, ordered_elem_id_list);
667}
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)

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().

◆ mergeBoundaryIDsWithSameName() [2/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)
61 mesh.get_boundary_info().renumber_id(id2, id1);
62}

◆ 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(), AdvancedExtruderGenerator::generate(), FillBetweenSidesetsGenerator::generate(), and MultiAppPositions::initialize().

◆ meshCentroidCalculator() [2/2]

Point MooseMeshUtils::meshCentroidCalculator ( const MeshBase mesh)

Definition at line 285 of file MooseMeshUtils.C.

286{
287 Point centroid_pt = Point(0.0, 0.0, 0.0);
288 Real vol_tmp = 0.0;
289 for (const auto & elem : mesh.active_local_element_ptr_range())
290 {
291 Real elem_vol = elem->volume();
292 centroid_pt += (elem->true_centroid()) * elem_vol;
293 vol_tmp += elem_vol;
294 }
295 mesh.comm().sum(centroid_pt);
296 mesh.comm().sum(vol_tmp);
297 centroid_pt /= vol_tmp;
298 return centroid_pt;
299}

◆ 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 670 of file MooseMeshUtils.C.

671{
672 Node * n_temp = elem.node_ptr(nd1);
673 elem.set_node(nd1, elem.node_ptr(nd2));
674 elem.set_node(nd2, n_temp);
675}
virtual Node *& set_node(const unsigned int i)
const Node * node_ptr(const unsigned int i) const