LCOV - code coverage report
Current view: top level - src/meshgenerators - NodeSetsGeneratorBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 102 104 98.1 %
Date: 2025-07-17 01:28:37 Functions: 8 8 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       14445 : NodeSetsGeneratorBase::validParams()
      21             : {
      22       14445 :   InputParameters params = MeshGenerator::validParams();
      23       14445 :   params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
      24       14445 :   params.addRequiredParam<std::vector<BoundaryName>>("new_nodeset",
      25             :                                                      "The list of nodeset names to create.");
      26             : 
      27       43335 :   params.addParam<bool>("replace",
      28       28890 :                         false,
      29             :                         "If true, replace the old nodesets. If false, the current nodesets (if "
      30             :                         "any) will be preserved.");
      31             : 
      32       14445 :   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       14445 :   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       14445 :   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             : 
      45       43335 :   params.addParam<bool>(
      46             :       "include_only_external_nodes",
      47       28890 :       false,
      48             :       "Whether to only include external nodes when considering nodes to add to the nodeset");
      49             : 
      50             :   // Nodeset restriction param group
      51       14445 :   params.addParamNamesToGroup("included_nodesets excluded_nodesets included_subdomains "
      52             :                               "include_only_external_nodes",
      53             :                               "Nodeset restrictions");
      54             : 
      55       14445 :   return params;
      56           0 : }
      57             : 
      58          92 : NodeSetsGeneratorBase::NodeSetsGeneratorBase(const InputParameters & parameters)
      59             :   : MeshGenerator(parameters),
      60          92 :     _input(getMesh("input")),
      61          92 :     _nodeset_names(std::vector<BoundaryName>()),
      62          92 :     _replace(getParam<bool>("replace")),
      63          92 :     _check_included_nodesets(isParamValid("included_nodesets")),
      64          92 :     _check_excluded_nodesets(isParamValid("excluded_nodesets")),
      65          92 :     _check_included_subdomains(isParamValid("included_subdomains")),
      66          92 :     _included_nodeset_ids(std::vector<boundary_id_type>()),
      67          92 :     _excluded_nodeset_ids(std::vector<boundary_id_type>()),
      68          92 :     _included_subdomain_ids(std::vector<subdomain_id_type>()),
      69         184 :     _include_only_external_nodes(getParam<bool>("include_only_external_nodes"))
      70             : {
      71          92 :   if (isParamValid("new_nodeset"))
      72           0 :     _nodeset_names = getParam<std::vector<BoundaryName>>("new_nodeset");
      73          92 : }
      74             : 
      75             : void
      76          88 : NodeSetsGeneratorBase::setup(MeshBase & mesh)
      77             : {
      78             :   // Parameter checks and filling vector of ids (used instead of names for efficiency)
      79          88 :   if (_check_included_nodesets)
      80             :   {
      81          28 :     const auto & included_nodesets = getParam<std::vector<BoundaryName>>("included_nodesets");
      82          52 :     for (const auto & nodeset_name : _nodeset_names)
      83          28 :       if (std::find(included_nodesets.begin(), included_nodesets.end(), nodeset_name) !=
      84          56 :           included_nodesets.end())
      85           4 :         paramError(
      86             :             "new_nodeset",
      87             :             "A nodeset cannot be both the new nodeset and be included in the list of included "
      88             :             "nodesets. If you are trying to restrict an existing nodeset, you must use a "
      89             :             "different name for 'new_nodeset', delete the old nodeset, and then rename the "
      90             :             "new nodeset to the old nodeset.");
      91             : 
      92          24 :     _included_nodeset_ids = MooseMeshUtils::getBoundaryIDs(mesh, included_nodesets, false);
      93             : 
      94             :     // Check that the included nodeset ids/names exist in the mesh
      95          44 :     for (const auto i : index_range(_included_nodeset_ids))
      96          24 :       if (_included_nodeset_ids[i] == Moose::INVALID_BOUNDARY_ID)
      97           4 :         paramError("included_nodesets",
      98             :                    "The nodeset '",
      99           4 :                    included_nodesets[i],
     100             :                    "' was not found within the mesh");
     101             :   }
     102             : 
     103          80 :   if (_check_excluded_nodesets)
     104             :   {
     105          20 :     const auto & excluded_nodesets = getParam<std::vector<BoundaryName>>("excluded_nodesets");
     106          36 :     for (const auto & nodeset_name : _nodeset_names)
     107          20 :       if (std::find(excluded_nodesets.begin(), excluded_nodesets.end(), nodeset_name) !=
     108          40 :           excluded_nodesets.end())
     109           4 :         paramError(
     110             :             "new_nodeset",
     111             :             "A nodeset cannot be both the new nodeset and be excluded in the list of excluded "
     112             :             "nodesets.");
     113          16 :     _excluded_nodeset_ids = MooseMeshUtils::getBoundaryIDs(mesh, excluded_nodesets, false);
     114             : 
     115             :     // Check that the excluded nodeset ids/names exist in the mesh
     116          28 :     for (const auto i : index_range(_excluded_nodeset_ids))
     117          16 :       if (_excluded_nodeset_ids[i] == Moose::INVALID_BOUNDARY_ID)
     118           4 :         paramError("excluded_nodesets",
     119             :                    "The nodeset '",
     120           4 :                    excluded_nodesets[i],
     121             :                    "' was not found within the mesh");
     122             : 
     123          12 :     if (_check_included_nodesets)
     124             :     {
     125             :       // Check that included and excluded nodeset lists do not overlap
     126           4 :       for (const auto & nodeset_id : _included_nodeset_ids)
     127           4 :         if (std::find(_excluded_nodeset_ids.begin(), _excluded_nodeset_ids.end(), nodeset_id) !=
     128           8 :             _excluded_nodeset_ids.end())
     129           4 :           paramError("excluded_nodesets",
     130             :                      "'included_nodesets' and 'excluded_nodesets' lists should not overlap");
     131             :     }
     132             :   }
     133             : 
     134             :   // Get the subdomain ids from the names
     135          68 :   if (_check_included_subdomains)
     136             :   {
     137             :     // check that the subdomains exist in the mesh
     138          44 :     const auto subdomains = getParam<std::vector<SubdomainName>>("included_subdomains");
     139          84 :     for (const auto & name : subdomains)
     140          44 :       if (!MooseMeshUtils::hasSubdomainName(mesh, name))
     141           4 :         paramError("included_subdomains", "The block '", name, "' was not found in the mesh");
     142             : 
     143          40 :     _included_subdomain_ids = MooseMeshUtils::getSubdomainIDs(mesh, subdomains);
     144          40 :   }
     145             : 
     146             :   // Build the node to element map, which is usually provided by a MooseMesh but in the mesh
     147             :   // generation process we are working with a MeshBase
     148        3712 :   for (const auto & elem : mesh.active_element_ptr_range())
     149       16416 :     for (unsigned int n = 0; n < elem->n_nodes(); n++)
     150       14656 :       _node_to_elem_map[elem->node_id(n)].push_back(elem->id());
     151          64 : }
     152             : 
     153             : bool
     154         288 : NodeSetsGeneratorBase::nodeOnMeshExteriorBoundary(const Node * node,
     155             :                                                   const std::vector<dof_id_type> & node_elems,
     156             :                                                   const MeshBase & mesh) const
     157             : {
     158             :   // Loop on the elements and check whether the node is part of a side with no neighbor (exterior)
     159         416 :   for (const auto elem_id : node_elems)
     160             :   {
     161         400 :     const auto elem = mesh.elem_ptr(elem_id);
     162        1616 :     for (const auto side_i : make_range(elem->n_sides()))
     163             :     {
     164             :       // Node is part of the side
     165        1488 :       if (elem->side_ptr(side_i)->get_node_index(node) != libMesh::invalid_uint)
     166             :       {
     167             :         // No neighbor on that side
     168         736 :         if (!elem->neighbor_ptr(side_i))
     169         272 :           return true;
     170             :       }
     171             :     }
     172             :   }
     173          16 :   return false;
     174             : }
     175             : 
     176             : bool
     177        2688 : NodeSetsGeneratorBase::nodeElementsInIncludedSubdomains(const std::vector<dof_id_type> node_elems,
     178             :                                                         const MeshBase & mesh) const
     179             : {
     180        9168 :   for (const auto elem_id : node_elems)
     181             :   {
     182        7184 :     subdomain_id_type curr_subdomain = mesh.elem_ptr(elem_id)->subdomain_id();
     183        7184 :     if (std ::find(_included_subdomain_ids.begin(),
     184             :                    _included_subdomain_ids.end(),
     185       14368 :                    curr_subdomain) != _included_subdomain_ids.end())
     186         704 :       return true;
     187             :   }
     188        1984 :   return false;
     189             : }
     190             : 
     191             : bool
     192        1280 : NodeSetsGeneratorBase::nodeInIncludedNodesets(const std::vector<BoundaryID> & node_nodesets) const
     193             : {
     194        3072 :   for (const auto bid : node_nodesets)
     195        1984 :     if (std::find(_included_nodeset_ids.begin(), _included_nodeset_ids.end(), bid) !=
     196        3968 :         _included_nodeset_ids.end())
     197         192 :       return true;
     198        1088 :   return false;
     199             : }
     200             : 
     201             : bool
     202         128 : NodeSetsGeneratorBase::nodeInExcludedNodesets(const std::vector<BoundaryID> & node_nodesets) const
     203             : {
     204         256 :   for (const auto bid : node_nodesets)
     205         192 :     if (std::find(_excluded_nodeset_ids.begin(), _excluded_nodeset_ids.end(), bid) !=
     206         384 :         _excluded_nodeset_ids.end())
     207          64 :       return true;
     208          64 :   return false;
     209             : }
     210             : 
     211             : bool
     212        4256 : NodeSetsGeneratorBase::nodeSatisfiesRequirements(const Node * node,
     213             :                                                  const std::vector<BoundaryID> & node_nodesets,
     214             :                                                  const std::vector<dof_id_type> & node_elems,
     215             :                                                  const MeshBase & mesh) const
     216             : {
     217             :   // Skip if side has neighbor and we only want external nodes
     218        4256 :   if (_include_only_external_nodes && !nodeOnMeshExteriorBoundary(node, node_elems, mesh))
     219          16 :     return false;
     220             : 
     221             :   // Skip if none of the elements owning the node are in the list of accepted subdomains
     222        4240 :   if (_check_included_subdomains && !nodeElementsInIncludedSubdomains(node_elems, mesh))
     223        1984 :     return false;
     224             : 
     225             :   // Skip if side is not part of included nodesets
     226        2256 :   if (_check_included_nodesets && !nodeInIncludedNodesets(node_nodesets))
     227        1088 :     return false;
     228             : 
     229             :   // Skip if side is part of excluded nodesets
     230        1168 :   if (_check_excluded_nodesets && nodeInExcludedNodesets(node_nodesets))
     231          64 :     return false;
     232             : 
     233        1104 :   return true;
     234             : }

Generated by: LCOV version 1.14