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 14445 : ParsedGenerateNodeset::validParams() 26 : { 27 14445 : InputParameters params = NodeSetsGeneratorBase::validParams(); 28 14445 : params += FunctionParserUtils<false>::validParams(); 29 : 30 14445 : params.addRequiredParam<BoundaryName>("new_nodeset_name", "The name of the new nodeset"); 31 : 32 14445 : 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 14445 : params.addParam<std::vector<std::string>>( 36 : "constant_names", {}, "Vector of constants used in the parsed function"); 37 14445 : 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 14445 : params.suppressParameter<std::vector<BoundaryName>>("new_nodeset"); 44 : 45 14445 : params.addClassDescription("A MeshGenerator that adds nodes to a nodeset if the " 46 : "node satisfies the `expression` expression."); 47 14445 : params.addParamNamesToGroup("expression constant_names constant_expressions", 48 : "Parsed expression"); 49 14445 : return params; 50 0 : } 51 : 52 92 : ParsedGenerateNodeset::ParsedGenerateNodeset(const InputParameters & parameters) 53 : : NodeSetsGeneratorBase(parameters), 54 : FunctionParserUtils<false>(parameters), 55 92 : _function(parameters.get<std::string>("expression")) 56 : { 57 92 : _nodeset_names.push_back(getParam<BoundaryName>("new_nodeset_name")); 58 : 59 : // Create parsed function 60 92 : _func_F = std::make_shared<SymFunction>(); 61 180 : parsedFunctionSetup(_func_F, 62 92 : _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 88 : _func_params.resize(3); 69 88 : } 70 : 71 : std::unique_ptr<MeshBase> 72 88 : ParsedGenerateNodeset::generate() 73 : { 74 88 : std::unique_ptr<MeshBase> mesh = std::move(_input); 75 88 : setup(*mesh); 76 : 77 64 : 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 64 : BoundaryInfo & boundary_info = mesh->get_boundary_info(); 82 : 83 : // Get a reference to the node to nodeset map 84 64 : 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 64 : 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 8576 : 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 4256 : 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 4256 : std::vector<BoundaryID> node_nodesets; 99 10272 : for (auto i = node_nodesets_iters.first; i != node_nodesets_iters.second; ++i) 100 6016 : node_nodesets.push_back(i->second); 101 : 102 : // Get all the elements the node is a part of 103 4256 : const auto & node_elems = _node_to_elem_map[curr_node->id()]; 104 : 105 : // Check all the constraints specified in base class 106 4256 : if (!nodeSatisfiesRequirements(curr_node, node_nodesets, node_elems, *mesh)) 107 3152 : continue; 108 : 109 : // Check expression 110 1104 : _func_params[0] = (*curr_node)(0); 111 1104 : _func_params[1] = (*curr_node)(1); 112 1104 : _func_params[2] = (*curr_node)(2); 113 1104 : if (evaluate(_func_F)) 114 : { 115 752 : if (_replace) 116 : { 117 160 : for (const auto nodeset_id : node_nodesets) 118 96 : boundary_info.remove_node(curr_node, nodeset_id); 119 : } 120 752 : boundary_info.add_node(curr_node, nodeset_ids[0]); 121 : } 122 4320 : } 123 64 : boundary_info.nodeset_name(nodeset_ids[0]) = _nodeset_names[0]; 124 : 125 : // TODO: consider if a new nodeset actually impacts preparedness 126 64 : mesh->set_isnt_prepared(); 127 128 : return dynamic_pointer_cast<MeshBase>(mesh); 128 64 : }