LCOV - code coverage report
Current view: top level - include/utils - MooseMeshUtils.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 35 41 85.4 %
Date: 2025-09-03 20:01:23 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "libmesh/replicated_mesh.h"
      13             : #include "libmesh/boundary_info.h"
      14             : 
      15             : #include "MooseUtils.h"
      16             : #include "MooseTypes.h"
      17             : #include "FaceInfo.h"
      18             : 
      19             : namespace MooseMeshUtils
      20             : {
      21             : 
      22             : // Used to temporarily store information about which lower-dimensional
      23             : // sides to add and what subdomain id to use for the added sides.
      24             : struct ElemSidePair
      25             : {
      26       24507 :   ElemSidePair(Elem * elem_in, unsigned short int side_in) : elem(elem_in), side(side_in) {}
      27             : 
      28             :   Elem * elem;
      29             :   unsigned short int side;
      30             : };
      31             : 
      32             : /**
      33             :  * Merges the boundary IDs of boundaries that have the same names
      34             :  * but different IDs.
      35             :  * @param mesh The input mesh whose boundaries we will modify
      36             :  */
      37             : void mergeBoundaryIDsWithSameName(MeshBase & mesh);
      38             : 
      39             : /**
      40             :  * Changes the old boundary ID to a new ID in the mesh
      41             :  *
      42             :  * @param mesh the mesh
      43             :  * @param old_id the old boundary id
      44             :  * @param new_id the new boundary id
      45             :  * @param delete_prev whether to delete the previous boundary id from the mesh
      46             :  */
      47             : void changeBoundaryId(MeshBase & mesh,
      48             :                       const libMesh::boundary_id_type old_id,
      49             :                       const libMesh::boundary_id_type new_id,
      50             :                       bool delete_prev);
      51             : 
      52             : /**
      53             :  * Changes the old subdomain ID to a new ID in the mesh
      54             :  *
      55             :  * @param mesh the mesh
      56             :  * @param old_id the old subdomain id
      57             :  * @param new_id the new subdomain id
      58             :  */
      59             : void
      60             : changeSubdomainId(MeshBase & mesh, const subdomain_id_type old_id, const subdomain_id_type new_id);
      61             : 
      62             : /**
      63             :  * Gets the boundary IDs with their names.
      64             :  *
      65             :  * The ordering of the returned boundary ID vector matches the vector of the boundary
      66             :  * names in \p boundary_name.
      67             :  * When a boundary name is not available in the mesh, if \p generate_unknown is true
      68             :  * a non-existant boundary ID will be returned, otherwise a BoundaryInfo::invalid_id
      69             :  * will be returned.
      70             :  */
      71             : std::vector<BoundaryID> getBoundaryIDs(const libMesh::MeshBase & mesh,
      72             :                                        const std::vector<BoundaryName> & boundary_name,
      73             :                                        bool generate_unknown,
      74             :                                        const std::set<BoundaryID> & mesh_boundary_ids);
      75             : 
      76             : /**
      77             :  * Gets the boundary IDs with their names.
      78             :  *
      79             :  * The ordering of the returned boundary ID vector matches the vector of the boundary
      80             :  * names in \p boundary_name.
      81             :  * When a boundary name is not available in the mesh, if \p generate_unknown is true
      82             :  * a non-existant boundary ID will be returned, otherwise a BoundaryInfo::invalid_id
      83             :  * will be returned.
      84             :  */
      85             : std::vector<BoundaryID> getBoundaryIDs(const libMesh::MeshBase & mesh,
      86             :                                        const std::vector<BoundaryName> & boundary_name,
      87             :                                        bool generate_unknown);
      88             : 
      89             : /**
      90             :  * Gets the boundary IDs into a set with their names.
      91             :  *
      92             :  * Because libMesh allows the same boundary to have multiple different boundary names,
      93             :  * the size of the returned boundary ID set may be smaller than the size of the bounndary
      94             :  * name vector.
      95             :  * When a boundary name is not available in the mesh, if \p generate_unknown is true
      96             :  * a non-existant boundary ID will be returned, otherwise a BoundaryInfo::invalid_id
      97             :  * will be returned.
      98             :  */
      99             : std::set<BoundaryID> getBoundaryIDSet(const libMesh::MeshBase & mesh,
     100             :                                       const std::vector<BoundaryName> & boundary_name,
     101             :                                       bool generate_unknown);
     102             : 
     103             : /**
     104             :  * Gets the boundary ID associated with the given BoundaryName.
     105             :  *
     106             :  * This is needed because the BoundaryName can be either an ID or a name.
     107             :  * If it is a name, the mesh is queried for the ID associated with said name.
     108             :  */
     109             : BoundaryID getBoundaryID(const BoundaryName & boundary_name, const MeshBase & mesh);
     110             : 
     111             : /**
     112             :  * Gets the subdomain ID associated with the given SubdomainName.
     113             :  *
     114             :  * This is needed because the SubdomainName can be either an ID or a name.
     115             :  * If it is a name, the mesh is queried for the ID associated with said name.
     116             :  */
     117             : SubdomainID getSubdomainID(const SubdomainName & subdomain_name, const MeshBase & mesh);
     118             : 
     119             : /**
     120             :  * Get the associated subdomainIDs for the subdomain names that are passed in.
     121             :  *
     122             :  * @param mesh The mesh
     123             :  * @param subdomain_name The names of the subdomains
     124             :  * @return The subdomain ids from the passed subdomain names.
     125             :  */
     126             : std::vector<subdomain_id_type> getSubdomainIDs(const libMesh::MeshBase & mesh,
     127             :                                                const std::vector<SubdomainName> & subdomain_name);
     128             : std::set<subdomain_id_type> getSubdomainIDs(const libMesh::MeshBase & mesh,
     129             :                                             const std::set<SubdomainName> & subdomain_name);
     130             : 
     131             : /**
     132             :  * Calculates the centroid of a MeshBase.
     133             :  * @param mesh input mesh whose centroid needs to be calculated
     134             :  * @return a Point data containing the mesh centroid
     135             :  */
     136             : Point meshCentroidCalculator(const MeshBase & mesh);
     137             : 
     138             : /**
     139             :  * compute a coordinate transformation factor
     140             :  * @param point The libMesh \p Point in space where we are evaluating the factor
     141             :  * @param factor The output of this function. Would be 1 for cartesian coordinate systems, 2*pi*r
     142             :  * for cylindrical coordinate systems, and 4*pi*r^2 for spherical coordinate systems
     143             :  * @param coord_type The coordinate system type, e.g. cartesian (COORD_XYZ), cylindrical (COORD_RZ),
     144             :  * or spherical (COORD_RSPHERICAL)
     145             :  * @param rz_radial_coord The index at which to index \p point for the radial coordinate when in a
     146             :  * cylindrical coordinate system
     147             :  */
     148             : template <typename P, typename C>
     149             : void
     150  2153958618 : coordTransformFactor(const P & point,
     151             :                      C & factor,
     152             :                      const Moose::CoordinateSystemType coord_type,
     153             :                      const unsigned int rz_radial_coord = libMesh::invalid_uint)
     154             : {
     155  2153958618 :   switch (coord_type)
     156             :   {
     157  2150866174 :     case Moose::COORD_XYZ:
     158  2150866174 :       factor = 1.0;
     159  2150866174 :       break;
     160     3054338 :     case Moose::COORD_RZ:
     161             :     {
     162             :       mooseAssert(rz_radial_coord != libMesh::invalid_uint,
     163             :                   "Must pass in a valid rz radial coordinate");
     164     3054338 :       factor = 2 * M_PI * point(rz_radial_coord);
     165     3054338 :       break;
     166             :     }
     167       38106 :     case Moose::COORD_RSPHERICAL:
     168       38106 :       factor = 4 * M_PI * point(0) * point(0);
     169       38106 :       break;
     170           0 :     default:
     171           0 :       mooseError("Unknown coordinate system");
     172             :   }
     173  2153958618 : }
     174             : 
     175             : /**
     176             :  * Computes the distance to a general axis
     177             :  *
     178             :  * @param[in] point  Point for which to compute distance from axis
     179             :  * @param[in] origin  Axis starting point
     180             :  * @param[in] direction  Axis direction
     181             :  */
     182             : template <typename P, typename C>
     183             : C
     184     1212256 : computeDistanceToAxis(const P & point, const Point & origin, const RealVectorValue & direction)
     185             : {
     186     1212256 :   return (point - origin).cross(direction).norm();
     187             : }
     188             : 
     189             : /**
     190             :  * Computes a coordinate transformation factor for a general axisymmetric axis
     191             :  *
     192             :  * @param[in] point  The libMesh \p Point in space where we are evaluating the factor
     193             :  * @param[in] axis  The pair of values defining the general axisymmetric axis.
     194             :  *                  Respectively, the values are the axis starting point and direction.
     195             :  * @param[out] factor  The coordinate transformation factor
     196             :  */
     197             : template <typename P, typename C>
     198             : void
     199     1212256 : coordTransformFactorRZGeneral(const P & point,
     200             :                               const std::pair<Point, RealVectorValue> & axis,
     201             :                               C & factor)
     202             : {
     203     1212256 :   factor = 2 * M_PI * computeDistanceToAxis<P, C>(point, axis.first, axis.second);
     204     1212256 : }
     205             : 
     206             : inline void
     207             : computeFiniteVolumeCoords(FaceInfo & fi,
     208             :                           const Moose::CoordinateSystemType coord_type,
     209             :                           const unsigned int rz_radial_coord = libMesh::invalid_uint)
     210             : {
     211             :   coordTransformFactor(fi.faceCentroid(), fi.faceCoord(), coord_type, rz_radial_coord);
     212             : }
     213             : 
     214             : /**
     215             :  * Crate a new set of element-wise IDs by finding unique combinations of existing extra ID values
     216             :  *
     217             :  * This function finds the unique combinations by recursively calling itself for extra ID inputs. In
     218             :  * the recursive calling, the new unique combinations is determined by combining the extra ID value
     219             :  * of current level and the unique combination determined in the previous level in recursion. In the
     220             :  * lowest level of recursion, the base combination is set by the unique ID values of the
     221             :  * corresponding extra ID.
     222             :  *
     223             :  * @param mesh input mesh
     224             :  * @param block_ids block ids
     225             :  * @param extra_ids extra ids
     226             :  * @return map of element id to new extra id
     227             :  **/
     228             : std::unordered_map<dof_id_type, dof_id_type>
     229             : getExtraIDUniqueCombinationMap(const MeshBase & mesh,
     230             :                                const std::set<SubdomainID> & block_ids,
     231             :                                std::vector<ExtraElementIDName> extra_ids);
     232             : 
     233             : /**
     234             :  * Decides whether all the Points of a vector of Points are in a plane that is defined by a normal
     235             :  * vector and an inplane Point
     236             :  * @param vec_pts vector of points to be examined
     237             :  * @param plane_nvec normal vector of the plane
     238             :  * @param fixed_pt a Point in the plane
     239             :  * @return whether all the Points are in the given plane
     240             :  */
     241             : bool isCoPlanar(const std::vector<Point> vec_pts, const Point plane_nvec, const Point fixed_pt);
     242             : 
     243             : /**
     244             :  * Decides whether all the Points of a vector of Points are in a plane with a given normal vector
     245             :  * @param vec_pts vector of points to be examined
     246             :  * @param plane_nvec normal vector of the plane
     247             :  * @return whether all the Points are in the same plane with the given normal vector
     248             :  */
     249             : bool isCoPlanar(const std::vector<Point> vec_pts, const Point plane_nvec);
     250             : 
     251             : /**
     252             :  * Decides whether all the Points of a vector of Points are coplanar
     253             :  * @param vec_pts vector of points to be examined
     254             :  * @return whether all the Points are in a same plane
     255             :  */
     256             : bool isCoPlanar(const std::vector<Point> vec_pts);
     257             : 
     258             : /**
     259             :  * Checks input mesh and returns max(block ID) + 1, which represents
     260             :  * a block ID that is not currently in use in the mesh
     261             :  * @param input mesh over which to compute the next free block id
     262             :  */
     263             : SubdomainID getNextFreeSubdomainID(MeshBase & input_mesh);
     264             : 
     265             : /**
     266             :  * Checks input mesh and returns the largest boundary ID in the mesh plus one, which is
     267             :  * a boundary ID in the mesh that is not currently in use
     268             :  * @param input mesh over which to compute the next free boundary ID
     269             :  */
     270             : 
     271             : BoundaryID getNextFreeBoundaryID(MeshBase & input_mesh);
     272             : /**
     273             :  * Whether a particular subdomain ID exists in the mesh
     274             :  * @param input mesh over which to determine subdomain IDs
     275             :  * @param subdomain ID
     276             :  */
     277             : bool hasSubdomainID(const MeshBase & input_mesh, const SubdomainID & id);
     278             : 
     279             : /**
     280             :  * Whether a particular subdomain name exists in the mesh
     281             :  * @param input mesh over which to determine subdomain names
     282             :  * @param subdomain name
     283             :  */
     284             : bool hasSubdomainName(const MeshBase & input_mesh, const SubdomainName & name);
     285             : 
     286             : /**
     287             :  * Whether a particular boundary ID exists in the mesh
     288             :  * @param input mesh over which to determine boundary IDs
     289             :  * @param boundary ID
     290             :  */
     291             : bool hasBoundaryID(const MeshBase & input_mesh, const BoundaryID id);
     292             : 
     293             : /**
     294             :  * Whether a particular boundary name exists in the mesh
     295             :  * @param input mesh over which to determine boundary names
     296             :  * @param boundary name
     297             :  */
     298             : bool hasBoundaryName(const MeshBase & input_mesh, const BoundaryName & name);
     299             : 
     300             : /**
     301             :  * Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes
     302             :  * based on connectivity
     303             :  * @param node_assm vector of pairs of node ids that represent the sides
     304             :  * @param elem_id_list vector of element ids that represent the elements that contain the sides
     305             :  * @param midpoint_node_list vector of node ids that represent the midpoints of the sides for
     306             :  * quadratic sides
     307             :  * @param ordered_node_list vector of node ids that represent the ordered nodes
     308             :  * @param ordered_elem_id_list vector of element corresponding to the ordered nodes
     309             :  * */
     310             : void makeOrderedNodeList(std::vector<std::pair<dof_id_type, dof_id_type>> & node_assm,
     311             :                          std::vector<dof_id_type> & elem_id_list,
     312             :                          std::vector<dof_id_type> & midpoint_node_list,
     313             :                          std::vector<dof_id_type> & ordered_node_list,
     314             :                          std::vector<dof_id_type> & ordered_elem_id_list);
     315             : 
     316             : /**
     317             :  * Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes
     318             :  * based on connectivity
     319             :  * @param node_assm vector of pairs of node ids that represent the sides
     320             :  * @param elem_id_list vector of element ids that represent the elements that contain the sides
     321             :  * @param ordered_node_list vector of node ids that represent the ordered nodes
     322             :  * @param ordered_elem_id_list vector of element corresponding to the ordered nodes
     323             :  * */
     324             : void makeOrderedNodeList(std::vector<std::pair<dof_id_type, dof_id_type>> & node_assm,
     325             :                          std::vector<dof_id_type> & elem_id_list,
     326             :                          std::vector<dof_id_type> & ordered_node_list,
     327             :                          std::vector<dof_id_type> & ordered_elem_id_list);
     328             : 
     329             : /**
     330             :  * Converts a given name (BoundaryName or SubdomainName) that is known to only contain digits into a
     331             :  * corresponding ID (BoundaryID or SubdomainID) and performs bounds checking to ensure that overflow
     332             :  * doesn't happen.
     333             :  * @param name Name that is to be converted into an ID.
     334             :  * @return ID type corresponding to the type of name.
     335             :  */
     336             : template <typename T, typename Q>
     337             : Q
     338      527606 : getIDFromName(const T & name)
     339             : {
     340      527606 :   if (!MooseUtils::isDigits(name))
     341           0 :     mooseError(
     342             :         "'name' ", name, " should only contain digits that can be converted to a numerical type.");
     343      527606 :   long long id = std::stoll(name);
     344      527606 :   Q id_Q = Q(id);
     345      527606 :   if (id < std::numeric_limits<Q>::min() || id > std::numeric_limits<Q>::max())
     346           4 :     mooseError(MooseUtils::prettyCppType<T>(&name),
     347             :                " ",
     348             :                name,
     349             :                " is not within the numeric limits of the expected ID type ",
     350             :                MooseUtils::prettyCppType<Q>(&id_Q),
     351             :                ".");
     352             : 
     353      527602 :   return id_Q;
     354             : }
     355             : 
     356             : /**
     357             :  * Swap two nodes within an element
     358             :  * @param elem element whose nodes need to be swapped
     359             :  * @param nd1 index of the first node to be swapped
     360             :  * @param nd2 index of the second node to be swapped
     361             :  */
     362             : void swapNodesInElem(Elem & elem, const unsigned int nd1, const unsigned int nd2);
     363             : 
     364             : /**
     365             :  * Reprocess the swap related input parameters to make pairs out of them to ease further processing
     366             :  * @param class_name name of the mesh generator class used for exception messages
     367             :  * @param id_name name of the parameter to be swapped used for exception messages
     368             :  * @param id_swaps vector of vectors of the ids to be swapped
     369             :  * @param id_swap_pairs vector of maps of the swapped pairs
     370             :  * @param row_index_shift shift to be applied to the row index in the exception messages (useful
     371             :  * when this method is utilized to process a fraction of a long vector)
     372             :  */
     373             : template <typename T>
     374             : void
     375         508 : idSwapParametersProcessor(const std::string & class_name,
     376             :                           const std::string & id_name,
     377             :                           const std::vector<std::vector<T>> & id_swaps,
     378             :                           std::vector<std::unordered_map<T, T>> & id_swap_pairs,
     379             :                           const unsigned int row_index_shift = 0)
     380             : {
     381         508 :   id_swap_pairs.resize(id_swaps.size());
     382         970 :   for (const auto i : index_range(id_swaps))
     383             :   {
     384         462 :     const auto & swaps = id_swaps[i];
     385         462 :     auto & swap_pairs = id_swap_pairs[i];
     386             : 
     387         462 :     if (swaps.size() % 2)
     388           0 :       throw MooseException("Row ",
     389           0 :                            row_index_shift + i + 1,
     390             :                            " of ",
     391             :                            id_name,
     392             :                            " in ",
     393             :                            class_name,
     394             :                            " does not contain an even number of entries! Num entries: ",
     395           0 :                            swaps.size());
     396             : 
     397         462 :     swap_pairs.reserve(swaps.size() / 2);
     398        1255 :     for (unsigned int j = 0; j < swaps.size(); j += 2)
     399         793 :       swap_pairs[swaps[j]] = swaps[j + 1];
     400             :   }
     401         508 : }
     402             : 
     403             : /**
     404             :  * Reprocess the elem_integers_swaps into maps so they are easier to use
     405             :  * @param class_name name of the mesh generator class used for exception messages
     406             :  * @param num_sections number of sections in the mesh
     407             :  * @param num_integers number of extra element integers in the mesh
     408             :  * @param elem_integers_swaps vector of vectors of vectors of extra element ids to be swapped
     409             :  * @param elem_integers_swap_pairs vector of maps of the swapped pairs
     410             :  */
     411             : void extraElemIntegerSwapParametersProcessor(
     412             :     const std::string & class_name,
     413             :     const unsigned int num_sections,
     414             :     const unsigned int num_integers,
     415             :     const std::vector<std::vector<std::vector<dof_id_type>>> & elem_integers_swaps,
     416             :     std::vector<std::unordered_map<dof_id_type, dof_id_type>> & elem_integers_swap_pairs);
     417             : 
     418             : /**
     419             :  * Build a lower-dimensional mesh from a boundary of an input mesh
     420             :  * Note: The lower-dimensional mesh will only have one subdomain and one boundary.
     421             :  *       Error will be thrown if the mesh does not have the boundary.
     422             :  *       This function works only with replicated mesh, for similar functionality with
     423             :  *       distributed meshes, please refer to LowerDBlockFromSidesetGenerator generator.
     424             :  * @param input_mesh  The input mesh
     425             :  * @param boundary_id The boundary id
     426             :  */
     427             : std::unique_ptr<ReplicatedMesh> buildBoundaryMesh(const ReplicatedMesh & input_mesh,
     428             :                                                   const boundary_id_type boundary_id);
     429             : 
     430             : /**
     431             :  * Create a new subdomain by generating new side elements from a list of sidesets in a given mesh.
     432             :  * @param mesh The mesh to work on
     433             :  * @param boundary_names The names of the sidesets to be used to create the new subdomain
     434             :  * @param new_subdomain_id The ID of the new subdomain to be created based on the sidesets
     435             :  * @param new_subdomain_name The name of the new subdomain to be created based on the sidesets
     436             :  * @param type_name The type of the mesh generator that is calling this method, used for error
     437             :  *                  messages and debugging purposes.
     438             :  */
     439             : void createSubdomainFromSidesets(std::unique_ptr<MeshBase> & mesh,
     440             :                                  std::vector<BoundaryName> boundary_names,
     441             :                                  const SubdomainID new_subdomain_id,
     442             :                                  const SubdomainName new_subdomain_name,
     443             :                                  const std::string type_name);
     444             : 
     445             : /**
     446             :  * Convert a list of blocks in a given mesh to a standalone new mesh.
     447             :  * @param source_mesh The source mesh from which the blocks will be converted
     448             :  * @param target_mesh The target mesh to which the blocks will be converted
     449             :  * @param target_blocks The names of the blocks to be converted to the target mesh
     450             :  */
     451             : void convertBlockToMesh(std::unique_ptr<MeshBase> & source_mesh,
     452             :                         std::unique_ptr<MeshBase> & target_mesh,
     453             :                         const std::vector<SubdomainName> & target_blocks);
     454             : }

Generated by: LCOV version 1.14