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

Classes

struct  ElemSidePair
 

Functions

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

Function Documentation

◆ addExternalBoundary() [1/2]

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

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

all element sides with no neighbors)

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

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

◆ addExternalBoundary() [2/2]

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

Definition at line 1557 of file MooseMeshUtils.C.

1558 {
1559  auto & binfo = mesh.get_boundary_info();
1560  for (const auto & elem : mesh.active_element_ptr_range())
1561  for (const auto & i_side : elem->side_index_range())
1562  if (elem->neighbor_ptr(i_side) == nullptr)
1563  {
1564  has_external_bid = true;
1565  binfo.add_side(elem, i_side, extern_bid);
1566  }
1567 }
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)

◆ boundaryCentroidCalculator() [1/2]

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

Calculates the centroid of a boundary on a mesh.

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

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

◆ boundaryCentroidCalculator() [2/2]

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

Definition at line 297 of file MooseMeshUtils.C.

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

◆ boundaryWeightedNormal() [1/2]

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

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

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

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

◆ boundaryWeightedNormal() [2/2]

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

Definition at line 330 of file MooseMeshUtils.C.

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

◆ buildBoundaryMesh() [1/2]

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

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

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

Parameters
input_meshThe input mesh
boundary_idThe boundary id

◆ buildBoundaryMesh() [2/2]

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

Definition at line 705 of file MooseMeshUtils.C.

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

◆ buildBoundaryNodeToElemMap() [1/2]

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

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

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

◆ buildBoundaryNodeToElemMap() [2/2]

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

Definition at line 968 of file MooseMeshUtils.C.

Referenced by buildLoopBoundaryOf2DMesh().

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

◆ buildLoopBoundaryOf2DMesh() [1/2]

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

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

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

Parameters
input_meshThe input mesh
boundary_idThe boundary id

Referenced by SurfaceSubdomainsDelaunayRemesher::General2DDelaunay().

◆ buildLoopBoundaryOf2DMesh() [2/2]

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

Definition at line 753 of file MooseMeshUtils.C.

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

◆ buildPolyLineMesh() [1/6]

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

Generates meshes from edges connecting a list of points.

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

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

◆ buildPolyLineMesh() [2/6]

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

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

If mid_points is empty, Edge2 elements are produced.

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

◆ buildPolyLineMesh() [3/6]

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

Generates meshes from edges connecting a list of points.

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

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

◆ buildPolyLineMesh() [4/6]

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

Definition at line 1411 of file MooseMeshUtils.C.

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

◆ buildPolyLineMesh() [5/6]

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

Definition at line 1519 of file MooseMeshUtils.C.

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

◆ buildPolyLineMesh() [6/6]

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

Definition at line 1531 of file MooseMeshUtils.C.

Referenced by buildPolyLineMesh().

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

◆ changeBoundaryId() [1/2]

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

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

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

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

◆ changeBoundaryId() [2/2]

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

Definition at line 65 of file MooseMeshUtils.C.

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

◆ changeSubdomainId() [1/2]

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

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

Parameters
meshthe mesh
old_idthe old subdomain id
new_idthe new subdomain id

◆ changeSubdomainId() [2/2]

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

Definition at line 269 of file MooseMeshUtils.C.

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

◆ computeDistanceToAxis()

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

Computes the distance to a general axis.

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

Definition at line 205 of file MooseMeshUtils.h.

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

◆ computeFiniteVolumeCoords()

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

Definition at line 239 of file MooseMeshUtils.h.

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

◆ computeMaxDistanceToAxis() [1/2]

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

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

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

Referenced by AdvancedExtruderGenerator::generate().

◆ computeMaxDistanceToAxis() [2/2]

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

Definition at line 363 of file MooseMeshUtils.C.

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

◆ convertBlockToMesh() [1/2]

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

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

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

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

◆ convertBlockToMesh() [2/2]

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

Definition at line 1172 of file MooseMeshUtils.C.

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

◆ coordTransformFactor()

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

Compute a coordinate transformation volume integration factor.

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

Definition at line 171 of file MooseMeshUtils.h.

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

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

◆ coordTransformFactorRZGeneral()

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

Computes a coordinate transformation factor for a general axisymmetric axis.

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

Definition at line 231 of file MooseMeshUtils.h.

Referenced by coordTransformFactor().

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

◆ copyIntoMesh() [1/2]

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

Helper function for copying one mesh into another.

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

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

◆ copyIntoMesh() [2/2]

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

Definition at line 1255 of file MooseMeshUtils.C.

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

◆ createSubdomainFromSidesets() [1/2]

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

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

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

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

◆ createSubdomainFromSidesets() [2/2]

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

Definition at line 1026 of file MooseMeshUtils.C.

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

◆ extraElemIntegerSwapParametersProcessor()

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

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

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

Definition at line 673 of file MooseMeshUtils.C.

Referenced by AdvancedExtruderGenerator::AdvancedExtruderGenerator().

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

◆ getBoundaryID() [1/2]

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

◆ getBoundaryID() [2/2]

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

Definition at line 236 of file MooseMeshUtils.C.

Referenced by hasBoundaryNameOrID().

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

◆ getBoundaryIDs() [1/2]

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

Gets the boundary IDs with their names.

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

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

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

Definition at line 118 of file MooseMeshUtils.C.

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

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

◆ getBoundaryIDs() [2/2]

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

Gets the boundary IDs with their names.

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

Definition at line 109 of file MooseMeshUtils.C.

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

◆ getBoundaryIDSet()

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

Gets the boundary IDs into a set with their names.

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

Definition at line 190 of file MooseMeshUtils.C.

Referenced by DomainUserObject::DomainUserObject().

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

◆ getBoundaryNodes() [1/2]

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

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

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

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

◆ getBoundaryNodes() [2/2]

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

Definition at line 998 of file MooseMeshUtils.C.

Referenced by buildBoundaryNodeToElemMap().

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

◆ getExtraIDUniqueCombinationMap() [1/2]

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

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

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

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

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

◆ getExtraIDUniqueCombinationMap() [2/2]

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

Definition at line 378 of file MooseMeshUtils.C.

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

◆ getIDFromName()

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

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

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

Definition at line 383 of file MooseMeshUtils.h.

384 {
385  if (!MooseUtils::isDigits(name))
386  mooseError(
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);
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 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
auto max(const L &left, const R &right)
auto min(const L &left, const R &right)

◆ getNextFreeBoundaryID() [1/2]

BoundaryID MooseMeshUtils::getNextFreeBoundaryID ( MeshBase &  input_mesh)

◆ getNextFreeBoundaryID() [2/2]

BoundaryID MooseMeshUtils::getNextFreeBoundaryID ( MeshBase input_mesh)

Definition at line 519 of file MooseMeshUtils.C.

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

◆ getNextFreeSubdomainID() [1/2]

SubdomainID MooseMeshUtils::getNextFreeSubdomainID ( MeshBase &  input_mesh)

◆ getNextFreeSubdomainID() [2/2]

SubdomainID MooseMeshUtils::getNextFreeSubdomainID ( MeshBase input_mesh)

Definition at line 499 of file MooseMeshUtils.C.

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

◆ getSubdomainID() [1/2]

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

◆ getSubdomainID() [2/2]

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

Definition at line 251 of file MooseMeshUtils.C.

Referenced by hasSubdomainName().

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

◆ getSubdomainIDs() [1/2]

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

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

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

Definition at line 199 of file MooseMeshUtils.C.

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

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

◆ getSubdomainIDs() [2/2]

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

Definition at line 228 of file MooseMeshUtils.C.

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

◆ hasBoundaryID() [1/2]

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

Whether a particular boundary ID exists in the mesh.

Parameters
inputmesh over which to determine boundary IDs
boundaryID

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

◆ hasBoundaryID() [2/2]

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

Definition at line 552 of file MooseMeshUtils.C.

Referenced by hasBoundaryNameOrID().

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

◆ hasBoundaryName() [1/2]

bool MooseMeshUtils::hasBoundaryName ( const MeshBase &  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 566 of file MooseMeshUtils.C.

567 {
568  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
569  const BoundaryID id = boundary_info.get_id_by_name(name);
570  return id != Moose::INVALID_BOUNDARY_ID;
571 }
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
MeshBase & mesh
const BoundaryInfo & get_boundary_info() const
boundary_id_type get_id_by_name(std::string_view name) const
boundary_id_type BoundaryID

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

575 {
576  const auto id = getBoundaryID(name_or_id, mesh);
577  return hasBoundaryID(mesh, id);
578 }
bool hasBoundaryID(const MeshBase &input_mesh, const BoundaryID id)
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)

◆ hasSubdomainID() [1/2]

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

◆ hasSubdomainID() [2/2]

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

Definition at line 531 of file MooseMeshUtils.C.

Referenced by hasSubdomainName().

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

◆ hasSubdomainName() [1/2]

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

◆ hasSubdomainName() [2/2]

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

Definition at line 545 of file MooseMeshUtils.C.

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

◆ idSwapParametersProcessor()

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

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

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

Definition at line 420 of file MooseMeshUtils.h.

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

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 }
Provides a way for users to bail out of the current solve.
auto index_range(const T &sizable)

◆ isCoPlanar() [1/6]

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

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

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

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

◆ isCoPlanar() [2/6]

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

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

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

◆ isCoPlanar() [3/6]

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

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

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

◆ isCoPlanar() [4/6]

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

Definition at line 457 of file MooseMeshUtils.C.

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

◆ isCoPlanar() [5/6]

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

Definition at line 466 of file MooseMeshUtils.C.

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

◆ isCoPlanar() [6/6]

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

Definition at line 472 of file MooseMeshUtils.C.

Referenced by isCoPlanar().

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

◆ makeOrderedNodeList() [1/2]

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

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

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

Definition at line 581 of file MooseMeshUtils.C.

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

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

◆ makeOrderedNodeList() [2/2]

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

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

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

Definition at line 654 of file MooseMeshUtils.C.

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

◆ mergeBoundaryIDsWithSameName() [1/2]

void MooseMeshUtils::mergeBoundaryIDsWithSameName ( MeshBase mesh)

Definition at line 38 of file MooseMeshUtils.C.

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

◆ mergeBoundaryIDsWithSameName() [2/2]

void MooseMeshUtils::mergeBoundaryIDsWithSameName ( MeshBase &  mesh)

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

Parameters
meshThe input mesh whose boundaries we will modify

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

◆ meshCentroidCalculator() [1/2]

Point MooseMeshUtils::meshCentroidCalculator ( const MeshBase &  mesh)

Calculates the centroid of a MeshBase.

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

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

◆ meshCentroidCalculator() [2/2]

Point MooseMeshUtils::meshCentroidCalculator ( const MeshBase mesh)

Definition at line 280 of file MooseMeshUtils.C.

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

◆ swapNodesInElem() [1/2]

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

Swap two nodes within an element.

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

Referenced by AdvancedExtruderGenerator::generate().

◆ swapNodesInElem() [2/2]

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

Definition at line 665 of file MooseMeshUtils.C.

666 {
667  Node * n_temp = elem.node_ptr(nd1);
668  elem.set_node(nd1, elem.node_ptr(nd2));
669  elem.set_node(nd2, n_temp);
670 }
virtual Node *& set_node(const unsigned int i)
const Node * node_ptr(const unsigned int i) const