LCOV - code coverage report
Current view: top level - src/meshgenerators - NodeSetsGeneratorBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 126 130 96.9 %
Date: 2026-05-29 20:35:17 Functions: 9 9 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             : #include "NodeSetsGeneratorBase.h"
      11             : #include "Parser.h"
      12             : #include "InputParameters.h"
      13             : #include "MooseMeshUtils.h"
      14             : 
      15             : #include "libmesh/mesh_generation.h"
      16             : #include "libmesh/mesh.h"
      17             : #include "libmesh/elem.h"
      18             : 
      19             : InputParameters
      20        3284 : NodeSetsGeneratorBase::validParams()
      21             : {
      22        3284 :   InputParameters params = MeshGenerator::validParams();
      23       13136 :   params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
      24       13136 :   params.addRequiredParam<std::vector<BoundaryName>>("new_nodeset",
      25             :                                                      "The list of nodeset names to create.");
      26             : 
      27        9852 :   params.addParam<bool>("replace",
      28        6568 :                         false,
      29             :                         "If true, replace the old nodesets. If false, the current nodesets (if "
      30             :                         "any) will be preserved.");
      31             : 
      32       13136 :   params.addParam<std::vector<BoundaryName>>(
      33             :       "included_nodesets",
      34             :       "A set of nodeset names or ids whose nodes will be included in the new nodesets.  A node "
      35             :       "is only added if it also belongs to one of these nodesets.");
      36       13136 :   params.addParam<std::vector<BoundaryName>>(
      37             :       "excluded_nodesets",
      38             :       "A set of nodeset names or ids whose nodes will be excluded from the new nodesets.  A node "
      39             :       "is only added if does not belong to any of these nodesets.");
      40       13136 :   params.addParam<std::vector<SubdomainName>>(
      41             :       "included_subdomains",
      42             :       "A set of subdomain names or ids whose nodes will be included in the new nodesets. A node "
      43             :       "is only added if the subdomain id of the corresponding element is in this set.");
      44       13136 :   params.addParam<std::vector<SubdomainName>>(
      45             :       "excluded_subdomains",
      46             :       "A set of subdomain names or ids whose nodes will be excluded in the new nodesets. A node "
      47             :       "is only added if the subdomain id of the corresponding element is not in this set.");
      48             : 
      49        9852 :   params.addParam<bool>(
      50             :       "include_only_external_nodes",
      51        6568 :       false,
      52             :       "Whether to only include external nodes when considering nodes to add to the nodeset");
      53             : 
      54             :   // Nodeset restriction param group
      55        9852 :   params.addParamNamesToGroup("included_nodesets excluded_nodesets included_subdomains "
      56             :                               "include_only_external_nodes",
      57             :                               "Nodeset restrictions");
      58             : 
      59        3284 :   return params;
      60           0 : }
      61             : 
      62         113 : NodeSetsGeneratorBase::NodeSetsGeneratorBase(const InputParameters & parameters)
      63             :   : MeshGenerator(parameters),
      64         113 :     _input(getMesh("input")),
      65         113 :     _nodeset_names(std::vector<BoundaryName>()),
      66         226 :     _replace(getParam<bool>("replace")),
      67         226 :     _check_included_nodesets(isParamValid("included_nodesets")),
      68         226 :     _check_excluded_nodesets(isParamValid("excluded_nodesets")),
      69         226 :     _check_included_subdomains(isParamValid("included_subdomains")),
      70         226 :     _check_excluded_subdomains(isParamValid("excluded_subdomains")),
      71         113 :     _included_nodeset_ids(std::vector<boundary_id_type>()),
      72         113 :     _excluded_nodeset_ids(std::vector<boundary_id_type>()),
      73         113 :     _included_subdomain_ids(std::vector<subdomain_id_type>()),
      74         113 :     _excluded_subdomain_ids(std::vector<subdomain_id_type>()),
      75         452 :     _include_only_external_nodes(getParam<bool>("include_only_external_nodes"))
      76             : {
      77         339 :   if (isParamValid("new_nodeset"))
      78           0 :     _nodeset_names = getParam<std::vector<BoundaryName>>("new_nodeset");
      79         113 : }
      80             : 
      81             : void
      82         110 : NodeSetsGeneratorBase::setup(MeshBase & mesh)
      83             : {
      84             :   // We'll need cached subdomain_ids later
      85         110 :   if (!mesh.preparation().has_cached_elem_data)
      86         110 :     mesh.cache_elem_data();
      87             : 
      88             :   // Parameter checks and filling vector of ids (used instead of names for efficiency)
      89         110 :   if (_check_included_nodesets)
      90             :   {
      91          50 :     const auto & included_nodesets = getParam<std::vector<BoundaryName>>("included_nodesets");
      92          47 :     for (const auto & nodeset_name : _nodeset_names)
      93          25 :       if (std::find(included_nodesets.begin(), included_nodesets.end(), nodeset_name) !=
      94          50 :           included_nodesets.end())
      95           6 :         paramError(
      96             :             "new_nodeset",
      97             :             "A nodeset cannot be both the new nodeset and be included in the list of included "
      98             :             "nodesets. If you are trying to restrict an existing nodeset, you must use a "
      99             :             "different name for 'new_nodeset', delete the old nodeset, and then rename the "
     100             :             "new nodeset to the old nodeset.");
     101             : 
     102          22 :     _included_nodeset_ids = MooseMeshUtils::getBoundaryIDs(mesh, included_nodesets, false);
     103             : 
     104             :     // Check that the included nodeset ids/names exist in the mesh
     105          41 :     for (const auto i : index_range(_included_nodeset_ids))
     106          22 :       if (_included_nodeset_ids[i] == Moose::INVALID_BOUNDARY_ID)
     107           6 :         paramError("included_nodesets",
     108             :                    "The nodeset '",
     109           3 :                    included_nodesets[i],
     110             :                    "' was not found within the mesh");
     111             :   }
     112             : 
     113         104 :   if (_check_excluded_nodesets)
     114             :   {
     115          34 :     const auto & excluded_nodesets = getParam<std::vector<BoundaryName>>("excluded_nodesets");
     116          31 :     for (const auto & nodeset_name : _nodeset_names)
     117          17 :       if (std::find(excluded_nodesets.begin(), excluded_nodesets.end(), nodeset_name) !=
     118          34 :           excluded_nodesets.end())
     119           6 :         paramError(
     120             :             "new_nodeset",
     121             :             "A nodeset cannot be both the new nodeset and be excluded in the list of excluded "
     122             :             "nodesets.");
     123          14 :     _excluded_nodeset_ids = MooseMeshUtils::getBoundaryIDs(mesh, excluded_nodesets, false);
     124             : 
     125             :     // Check that the excluded nodeset ids/names exist in the mesh
     126          25 :     for (const auto i : index_range(_excluded_nodeset_ids))
     127          14 :       if (_excluded_nodeset_ids[i] == Moose::INVALID_BOUNDARY_ID)
     128           6 :         paramError("excluded_nodesets",
     129             :                    "The nodeset '",
     130           3 :                    excluded_nodesets[i],
     131             :                    "' was not found within the mesh");
     132             : 
     133          11 :     if (_check_included_nodesets)
     134             :     {
     135             :       // Check that included and excluded nodeset lists do not overlap
     136           3 :       for (const auto & nodeset_id : _included_nodeset_ids)
     137           3 :         if (std::find(_excluded_nodeset_ids.begin(), _excluded_nodeset_ids.end(), nodeset_id) !=
     138           6 :             _excluded_nodeset_ids.end())
     139           6 :           paramError("excluded_nodesets",
     140             :                      "'included_nodesets' and 'excluded_nodesets' lists should not overlap");
     141             :     }
     142             :   }
     143             : 
     144             :   // Get the subdomain ids from the names
     145          95 :   if (_check_included_subdomains)
     146             :   {
     147             :     // check that the subdomains exist in the mesh
     148         102 :     const auto subdomains = getParam<std::vector<SubdomainName>>("included_subdomains");
     149          99 :     for (const auto & name : subdomains)
     150          51 :       if (!MooseMeshUtils::hasSubdomainName(mesh, name))
     151           6 :         paramError("included_subdomains", "The block '", name, "' was not found in the mesh");
     152             : 
     153          48 :     _included_subdomain_ids = MooseMeshUtils::getSubdomainIDs(mesh, subdomains);
     154          48 :   }
     155             : 
     156          92 :   if (_check_excluded_subdomains)
     157             :   {
     158             :     // check that the subdomains exist in the mesh
     159          16 :     const auto subdomains = getParam<std::vector<SubdomainName>>("excluded_subdomains");
     160          16 :     for (const auto & name : subdomains)
     161           8 :       if (!MooseMeshUtils::hasSubdomainName(mesh, name))
     162           0 :         paramError("excluded_subdomains", "The block '", name, "' was not found in the mesh");
     163             : 
     164           8 :     _excluded_subdomain_ids = MooseMeshUtils::getSubdomainIDs(mesh, subdomains);
     165             : 
     166           8 :     if (_check_included_subdomains)
     167             :     {
     168             :       // Check that included and excluded nodeset lists do not overlap
     169          16 :       for (const auto & subdomain_id : _included_subdomain_ids)
     170           8 :         if (std::find(_excluded_subdomain_ids.begin(),
     171             :                       _excluded_subdomain_ids.end(),
     172          16 :                       subdomain_id) != _excluded_subdomain_ids.end())
     173           0 :           paramError("excluded_subdomains",
     174             :                      "'included_subdomains' and 'excluded_subdomains' lists should not overlap");
     175             :     }
     176           8 :   }
     177             : 
     178             :   // Build the node to element map, which is usually provided by a MooseMesh but in the mesh
     179             :   // generation process we are working with a MeshBase
     180        2364 :   for (const auto & elem : mesh.active_element_ptr_range())
     181       19232 :     for (unsigned int n = 0; n < elem->n_nodes(); n++)
     182       17052 :       _node_to_elem_map[elem->node_id(n)].push_back(elem->id());
     183          92 : }
     184             : 
     185             : bool
     186         288 : NodeSetsGeneratorBase::nodeOnMeshExteriorBoundary(const Node * node,
     187             :                                                   const std::vector<dof_id_type> & node_elems,
     188             :                                                   const MeshBase & mesh) const
     189             : {
     190             :   // Loop on the elements and check whether the node is part of a side with no neighbor (exterior)
     191         416 :   for (const auto elem_id : node_elems)
     192             :   {
     193         400 :     const auto elem = mesh.elem_ptr(elem_id);
     194        1616 :     for (const auto side_i : make_range(elem->n_sides()))
     195             :     {
     196             :       // Node is part of the side
     197        1488 :       if (elem->side_ptr(side_i)->get_node_index(node) != libMesh::invalid_uint)
     198             :       {
     199             :         // No neighbor on that side
     200         736 :         if (!elem->neighbor_ptr(side_i))
     201         272 :           return true;
     202             :       }
     203             :     }
     204             :   }
     205          16 :   return false;
     206             : }
     207             : 
     208             : bool
     209        3072 : NodeSetsGeneratorBase::nodeElementsInIncludedSubdomains(const std::vector<dof_id_type> node_elems,
     210             :                                                         const MeshBase & mesh) const
     211             : {
     212       10192 :   for (const auto elem_id : node_elems)
     213             :   {
     214        8040 :     subdomain_id_type curr_subdomain = mesh.elem_ptr(elem_id)->subdomain_id();
     215        8040 :     if (std ::find(_included_subdomain_ids.begin(),
     216             :                    _included_subdomain_ids.end(),
     217       16080 :                    curr_subdomain) != _included_subdomain_ids.end())
     218         920 :       return true;
     219             :   }
     220        2152 :   return false;
     221             : }
     222             : 
     223             : bool
     224         216 : NodeSetsGeneratorBase::nodeElementsInExcludedSubdomains(const std::vector<dof_id_type> node_elems,
     225             :                                                         const MeshBase & mesh) const
     226             : {
     227         856 :   for (const auto elem_id : node_elems)
     228             :   {
     229         712 :     subdomain_id_type curr_subdomain = mesh.elem_ptr(elem_id)->subdomain_id();
     230         712 :     if (std ::find(_excluded_subdomain_ids.begin(),
     231             :                    _excluded_subdomain_ids.end(),
     232        1424 :                    curr_subdomain) != _excluded_subdomain_ids.end())
     233          72 :       return true;
     234             :   }
     235         144 :   return false;
     236             : }
     237             : 
     238             : bool
     239        1280 : NodeSetsGeneratorBase::nodeInIncludedNodesets(const std::vector<BoundaryID> & node_nodesets) const
     240             : {
     241        3072 :   for (const auto bid : node_nodesets)
     242        1984 :     if (std::find(_included_nodeset_ids.begin(), _included_nodeset_ids.end(), bid) !=
     243        3968 :         _included_nodeset_ids.end())
     244         192 :       return true;
     245        1088 :   return false;
     246             : }
     247             : 
     248             : bool
     249         128 : NodeSetsGeneratorBase::nodeInExcludedNodesets(const std::vector<BoundaryID> & node_nodesets) const
     250             : {
     251         256 :   for (const auto bid : node_nodesets)
     252         192 :     if (std::find(_excluded_nodeset_ids.begin(), _excluded_nodeset_ids.end(), bid) !=
     253         384 :         _excluded_nodeset_ids.end())
     254          64 :       return true;
     255          64 :   return false;
     256             : }
     257             : 
     258             : bool
     259        5120 : NodeSetsGeneratorBase::nodeSatisfiesRequirements(const Node * node,
     260             :                                                  const std::vector<BoundaryID> & node_nodesets,
     261             :                                                  const std::vector<dof_id_type> & node_elems,
     262             :                                                  const MeshBase & mesh) const
     263             : {
     264             :   // Skip if side has neighbor and we only want external nodes
     265        5120 :   if (_include_only_external_nodes && !nodeOnMeshExteriorBoundary(node, node_elems, mesh))
     266          16 :     return false;
     267             : 
     268             :   // Skip if none of the elements owning the node are in the list of accepted subdomains
     269        5104 :   if (_check_included_subdomains && !nodeElementsInIncludedSubdomains(node_elems, mesh))
     270        2152 :     return false;
     271             : 
     272             :   // Skip if a element owning the node is in the list of excluded subdomains
     273             :   // Note: if a node is on the interface of included subdomains and excluded subdomains,
     274             :   //       it will pass the above check but return false here, i.e. subdomain excluding will
     275             :   //       win if both subdomain including and excluding are true.
     276        2952 :   if (_check_excluded_subdomains && nodeElementsInExcludedSubdomains(node_elems, mesh))
     277          72 :     return false;
     278             : 
     279             :   // Skip if side is not part of included nodesets
     280        2880 :   if (_check_included_nodesets && !nodeInIncludedNodesets(node_nodesets))
     281        1088 :     return false;
     282             : 
     283             :   // Skip if side is part of excluded nodesets
     284        1792 :   if (_check_excluded_nodesets && nodeInExcludedNodesets(node_nodesets))
     285          64 :     return false;
     286             : 
     287        1728 :   return true;
     288             : }

Generated by: LCOV version 1.14