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

Generated by: LCOV version 1.14