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