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 : }