LCOV - code coverage report
Current view: top level - src/meshgenerators - ParsedGenerateNodeset.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 47 49 95.9 %
Date: 2025-08-08 20:01:16 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       14479 : ParsedGenerateNodeset::validParams()
      26             : {
      27       14479 :   InputParameters params = NodeSetsGeneratorBase::validParams();
      28       14479 :   params += FunctionParserUtils<false>::validParams();
      29             : 
      30       14479 :   params.addRequiredParam<BoundaryName>("new_nodeset_name", "The name of the new nodeset");
      31             : 
      32       14479 :   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       14479 :   params.addParam<std::vector<std::string>>(
      36             :       "constant_names", {}, "Vector of constants used in the parsed function");
      37       14479 :   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             :   // This nodeset generator can only handle a single new nodeset name, not a vector of names
      43       14479 :   params.suppressParameter<std::vector<BoundaryName>>("new_nodeset");
      44             : 
      45       14479 :   params.addClassDescription("A MeshGenerator that adds nodes to a nodeset if the "
      46             :                              "node satisfies the `expression` expression.");
      47       14479 :   params.addParamNamesToGroup("expression constant_names constant_expressions",
      48             :                               "Parsed expression");
      49       14479 :   return params;
      50           0 : }
      51             : 
      52         109 : ParsedGenerateNodeset::ParsedGenerateNodeset(const InputParameters & parameters)
      53             :   : NodeSetsGeneratorBase(parameters),
      54             :     FunctionParserUtils<false>(parameters),
      55         109 :     _function(parameters.get<std::string>("expression"))
      56             : {
      57         109 :   _nodeset_names.push_back(getParam<BoundaryName>("new_nodeset_name"));
      58             : 
      59             :   // Create parsed function
      60         109 :   _func_F = std::make_shared<SymFunction>();
      61         214 :   parsedFunctionSetup(_func_F,
      62         109 :                       _function,
      63             :                       "x,y,z",
      64             :                       getParam<std::vector<std::string>>("constant_names"),
      65             :                       getParam<std::vector<std::string>>("constant_expressions"),
      66             :                       comm());
      67             : 
      68         105 :   _func_params.resize(3);
      69         105 : }
      70             : 
      71             : std::unique_ptr<MeshBase>
      72         105 : ParsedGenerateNodeset::generate()
      73             : {
      74         105 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      75         105 :   setup(*mesh);
      76             : 
      77          81 :   if (!mesh->is_replicated())
      78           0 :     mooseError("Not implemented for distributed meshes");
      79             : 
      80             :   // Get a reference to our BoundaryInfo object for later use
      81          81 :   BoundaryInfo & boundary_info = mesh->get_boundary_info();
      82             : 
      83             :   // Get a reference to the node to nodeset map
      84          81 :   const auto & nodeset_map = boundary_info.get_nodeset_map();
      85             : 
      86             :   // Get the BoundaryIDs from the mesh
      87             :   std::vector<boundary_id_type> nodeset_ids =
      88          81 :       MooseMeshUtils::getBoundaryIDs(*mesh, _nodeset_names, true);
      89             :   mooseAssert(nodeset_ids.size() == 1, "Length of nodeset_ids should be one");
      90             : 
      91             :   // Loop over nodes
      92       10521 :   for (const auto curr_node : as_range(mesh->active_nodes_begin(), mesh->active_nodes_end()))
      93             :   {
      94             :     // Get all nodesets the node is currently a part of
      95        5220 :     const auto & node_nodesets_iters = nodeset_map.equal_range(curr_node);
      96             : 
      97             :     // Copy into a vector to accommodate this developer's low skills
      98        5220 :     std::vector<BoundaryID> node_nodesets;
      99       12708 :     for (auto i = node_nodesets_iters.first; i != node_nodesets_iters.second; ++i)
     100        7488 :       node_nodesets.push_back(i->second);
     101             : 
     102             :     // Get all the elements the node is a part of
     103        5220 :     const auto & node_elems = _node_to_elem_map[curr_node->id()];
     104             : 
     105             :     // Check all the constraints specified in base class
     106        5220 :     if (!nodeSatisfiesRequirements(curr_node, node_nodesets, node_elems, *mesh))
     107        3816 :       continue;
     108             : 
     109             :     // Check expression
     110        1404 :     _func_params[0] = (*curr_node)(0);
     111        1404 :     _func_params[1] = (*curr_node)(1);
     112        1404 :     _func_params[2] = (*curr_node)(2);
     113        1404 :     if (evaluate(_func_F))
     114             :     {
     115        1008 :       if (_replace)
     116             :       {
     117         180 :         for (const auto nodeset_id : node_nodesets)
     118         108 :           boundary_info.remove_node(curr_node, nodeset_id);
     119             :       }
     120        1008 :       boundary_info.add_node(curr_node, nodeset_ids[0]);
     121             :     }
     122        5301 :   }
     123          81 :   boundary_info.nodeset_name(nodeset_ids[0]) = _nodeset_names[0];
     124             : 
     125             :   // TODO: consider if a new nodeset actually impacts preparedness
     126          81 :   mesh->set_isnt_prepared();
     127         162 :   return dynamic_pointer_cast<MeshBase>(mesh);
     128          81 : }

Generated by: LCOV version 1.14