LCOV - code coverage report
Current view: top level - src/meshgenerators - ParsedGenerateNodeset.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 6f668f Lines: 50 52 96.2 %
Date: 2025-09-22 20:01:15 Functions: 3 3 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 "ParsedGenerateNodeset.h"
      11             : #include "Conversion.h"
      12             : #include "MooseMeshUtils.h"
      13             : #include "CastUniquePointer.h"
      14             : 
      15             : #include "libmesh/fparser_ad.hh"
      16             : #include "libmesh/distributed_mesh.h"
      17             : #include "libmesh/elem.h"
      18             : #include "libmesh/fe_base.h"
      19             : 
      20             : #include <typeinfo>
      21             : 
      22             : registerMooseObject("MooseApp", ParsedGenerateNodeset);
      23             : 
      24             : InputParameters
      25       15003 : ParsedGenerateNodeset::validParams()
      26             : {
      27       15003 :   InputParameters params = NodeSetsGeneratorBase::validParams();
      28       15003 :   params += FunctionParserUtils<false>::validParams();
      29             : 
      30       60012 :   params.addRequiredParam<BoundaryName>("new_nodeset_name", "The name of the new nodeset");
      31             : 
      32       60012 :   params.addRequiredParam<std::string>("expression",
      33             :                                        "Function expression describing the geometric constraints "
      34             :                                        "that the node must meet to be included in the nodeset");
      35       60012 :   params.addParam<std::vector<std::string>>(
      36             :       "constant_names", {}, "Vector of constants used in the parsed function");
      37       60012 :   params.addParam<std::vector<std::string>>(
      38             :       "constant_expressions",
      39             :       {},
      40             :       "Vector of values for the constants in constant_names (can be an FParser expression)");
      41             : 
      42       45009 :   params.addParam<bool>(
      43             :       "allow_distributed_meshes",
      44       30006 :       false,
      45             :       "Can be used to avoid erroring on distributed meshes, when it is known to be safe. For "
      46             :       "example, when only using a parsed expression to select nodes.");
      47             : 
      48             :   // This nodeset generator can only handle a single new nodeset name, not a vector of names
      49       30006 :   params.suppressParameter<std::vector<BoundaryName>>("new_nodeset");
      50             : 
      51       30006 :   params.addClassDescription("A MeshGenerator that adds nodes to a nodeset if the "
      52             :                              "node satisfies the `expression` expression.");
      53       60012 :   params.addParamNamesToGroup("expression constant_names constant_expressions",
      54             :                               "Parsed expression");
      55       45009 :   params.addParamNamesToGroup("allow_distributed_meshes", "Advanced");
      56       15003 :   return params;
      57           0 : }
      58             : 
      59         131 : ParsedGenerateNodeset::ParsedGenerateNodeset(const InputParameters & parameters)
      60             :   : NodeSetsGeneratorBase(parameters),
      61             :     FunctionParserUtils<false>(parameters),
      62         131 :     _function(parameters.get<std::string>("expression"))
      63             : {
      64         262 :   _nodeset_names.push_back(getParam<BoundaryName>("new_nodeset_name"));
      65             : 
      66             :   // Create parsed function
      67         131 :   _func_F = std::make_shared<SymFunction>();
      68         905 :   parsedFunctionSetup(_func_F,
      69         131 :                       _function,
      70             :                       "x,y,z",
      71             :                       getParam<std::vector<std::string>>("constant_names"),
      72             :                       getParam<std::vector<std::string>>("constant_expressions"),
      73             :                       comm());
      74             : 
      75         127 :   _func_params.resize(3);
      76         127 : }
      77             : 
      78             : std::unique_ptr<MeshBase>
      79         127 : ParsedGenerateNodeset::generate()
      80             : {
      81         127 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      82         127 :   setup(*mesh);
      83             : 
      84         309 :   if (!getParam<bool>("allow_distributed_meshes") && !mesh->is_replicated())
      85           0 :     mooseError("Not implemented for distributed meshes");
      86             : 
      87             :   // Get a reference to our BoundaryInfo object for later use
      88         103 :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
      89             : 
      90             :   // Get a reference to the node to nodeset map
      91         103 :   const auto & nodeset_map = boundary_info.get_nodeset_map();
      92             : 
      93             :   // Get the BoundaryIDs from the mesh
      94             :   std::vector<boundary_id_type> nodeset_ids =
      95         103 :       MooseMeshUtils::getBoundaryIDs(*mesh, _nodeset_names, true);
      96             :   mooseAssert(nodeset_ids.size() == 1, "Length of nodeset_ids should be one");
      97             : 
      98             :   // Loop over nodes
      99        5853 :   for (const auto curr_node : as_range(mesh->active_nodes_begin(), mesh->active_nodes_end()))
     100             :   {
     101             :     // Get all nodesets the node is currently a part of
     102        5750 :     const auto & node_nodesets_iters = nodeset_map.equal_range(curr_node);
     103             : 
     104             :     // Copy into a vector to accommodate this developer's low skills
     105        5750 :     std::vector<BoundaryID> node_nodesets;
     106       13705 :     for (auto i = node_nodesets_iters.first; i != node_nodesets_iters.second; ++i)
     107        7955 :       node_nodesets.push_back(i->second);
     108             : 
     109             :     // Get all the elements the node is a part of
     110        5750 :     const auto & node_elems = _node_to_elem_map[curr_node->id()];
     111             : 
     112             :     // Check all the constraints specified in base class
     113        5750 :     if (!nodeSatisfiesRequirements(curr_node, node_nodesets, node_elems, *mesh))
     114        3816 :       continue;
     115             : 
     116             :     // Check expression
     117        1934 :     _func_params[0] = (*curr_node)(0);
     118        1934 :     _func_params[1] = (*curr_node)(1);
     119        1934 :     _func_params[2] = (*curr_node)(2);
     120        5802 :     if (evaluate(_func_F))
     121             :     {
     122        1116 :       if (_replace)
     123             :       {
     124         180 :         for (const auto nodeset_id : node_nodesets)
     125         108 :           boundary_info.remove_node(curr_node, nodeset_id);
     126             :       }
     127        1116 :       boundary_info.add_node(curr_node, nodeset_ids[0]);
     128             :     }
     129        5853 :   }
     130         103 :   boundary_info.nodeset_name(nodeset_ids[0]) = _nodeset_names[0];
     131             : 
     132             :   // TODO: consider if a new nodeset actually impacts preparedness
     133         103 :   mesh->set_isnt_prepared();
     134         206 :   return dynamic_pointer_cast<MeshBase>(mesh);
     135         103 : }

Generated by: LCOV version 1.14