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

Generated by: LCOV version 1.14