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 3284 : NodeSetsGeneratorBase::validParams()
21 : {
22 3284 : InputParameters params = MeshGenerator::validParams();
23 13136 : params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
24 13136 : params.addRequiredParam<std::vector<BoundaryName>>("new_nodeset",
25 : "The list of nodeset names to create.");
26 :
27 9852 : params.addParam<bool>("replace",
28 6568 : false,
29 : "If true, replace the old nodesets. If false, the current nodesets (if "
30 : "any) will be preserved.");
31 :
32 13136 : 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 13136 : 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 13136 : 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 13136 : params.addParam<std::vector<SubdomainName>>(
45 : "excluded_subdomains",
46 : "A set of subdomain names or ids whose nodes will be excluded in the new nodesets. A node "
47 : "is only added if the subdomain id of the corresponding element is not in this set.");
48 :
49 9852 : params.addParam<bool>(
50 : "include_only_external_nodes",
51 6568 : false,
52 : "Whether to only include external nodes when considering nodes to add to the nodeset");
53 :
54 : // Nodeset restriction param group
55 9852 : params.addParamNamesToGroup("included_nodesets excluded_nodesets included_subdomains "
56 : "include_only_external_nodes",
57 : "Nodeset restrictions");
58 :
59 3284 : return params;
60 0 : }
61 :
62 113 : NodeSetsGeneratorBase::NodeSetsGeneratorBase(const InputParameters & parameters)
63 : : MeshGenerator(parameters),
64 113 : _input(getMesh("input")),
65 113 : _nodeset_names(std::vector<BoundaryName>()),
66 226 : _replace(getParam<bool>("replace")),
67 226 : _check_included_nodesets(isParamValid("included_nodesets")),
68 226 : _check_excluded_nodesets(isParamValid("excluded_nodesets")),
69 226 : _check_included_subdomains(isParamValid("included_subdomains")),
70 226 : _check_excluded_subdomains(isParamValid("excluded_subdomains")),
71 113 : _included_nodeset_ids(std::vector<boundary_id_type>()),
72 113 : _excluded_nodeset_ids(std::vector<boundary_id_type>()),
73 113 : _included_subdomain_ids(std::vector<subdomain_id_type>()),
74 113 : _excluded_subdomain_ids(std::vector<subdomain_id_type>()),
75 452 : _include_only_external_nodes(getParam<bool>("include_only_external_nodes"))
76 : {
77 339 : if (isParamValid("new_nodeset"))
78 0 : _nodeset_names = getParam<std::vector<BoundaryName>>("new_nodeset");
79 113 : }
80 :
81 : void
82 110 : NodeSetsGeneratorBase::setup(MeshBase & mesh)
83 : {
84 : // We'll need cached subdomain_ids later
85 110 : if (!mesh.preparation().has_cached_elem_data)
86 110 : mesh.cache_elem_data();
87 :
88 : // Parameter checks and filling vector of ids (used instead of names for efficiency)
89 110 : if (_check_included_nodesets)
90 : {
91 50 : const auto & included_nodesets = getParam<std::vector<BoundaryName>>("included_nodesets");
92 47 : for (const auto & nodeset_name : _nodeset_names)
93 25 : if (std::find(included_nodesets.begin(), included_nodesets.end(), nodeset_name) !=
94 50 : included_nodesets.end())
95 6 : paramError(
96 : "new_nodeset",
97 : "A nodeset cannot be both the new nodeset and be included in the list of included "
98 : "nodesets. If you are trying to restrict an existing nodeset, you must use a "
99 : "different name for 'new_nodeset', delete the old nodeset, and then rename the "
100 : "new nodeset to the old nodeset.");
101 :
102 22 : _included_nodeset_ids = MooseMeshUtils::getBoundaryIDs(mesh, included_nodesets, false);
103 :
104 : // Check that the included nodeset ids/names exist in the mesh
105 41 : for (const auto i : index_range(_included_nodeset_ids))
106 22 : if (_included_nodeset_ids[i] == Moose::INVALID_BOUNDARY_ID)
107 6 : paramError("included_nodesets",
108 : "The nodeset '",
109 3 : included_nodesets[i],
110 : "' was not found within the mesh");
111 : }
112 :
113 104 : if (_check_excluded_nodesets)
114 : {
115 34 : const auto & excluded_nodesets = getParam<std::vector<BoundaryName>>("excluded_nodesets");
116 31 : for (const auto & nodeset_name : _nodeset_names)
117 17 : if (std::find(excluded_nodesets.begin(), excluded_nodesets.end(), nodeset_name) !=
118 34 : excluded_nodesets.end())
119 6 : paramError(
120 : "new_nodeset",
121 : "A nodeset cannot be both the new nodeset and be excluded in the list of excluded "
122 : "nodesets.");
123 14 : _excluded_nodeset_ids = MooseMeshUtils::getBoundaryIDs(mesh, excluded_nodesets, false);
124 :
125 : // Check that the excluded nodeset ids/names exist in the mesh
126 25 : for (const auto i : index_range(_excluded_nodeset_ids))
127 14 : if (_excluded_nodeset_ids[i] == Moose::INVALID_BOUNDARY_ID)
128 6 : paramError("excluded_nodesets",
129 : "The nodeset '",
130 3 : excluded_nodesets[i],
131 : "' was not found within the mesh");
132 :
133 11 : if (_check_included_nodesets)
134 : {
135 : // Check that included and excluded nodeset lists do not overlap
136 3 : for (const auto & nodeset_id : _included_nodeset_ids)
137 3 : if (std::find(_excluded_nodeset_ids.begin(), _excluded_nodeset_ids.end(), nodeset_id) !=
138 6 : _excluded_nodeset_ids.end())
139 6 : paramError("excluded_nodesets",
140 : "'included_nodesets' and 'excluded_nodesets' lists should not overlap");
141 : }
142 : }
143 :
144 : // Get the subdomain ids from the names
145 95 : if (_check_included_subdomains)
146 : {
147 : // check that the subdomains exist in the mesh
148 102 : const auto subdomains = getParam<std::vector<SubdomainName>>("included_subdomains");
149 99 : for (const auto & name : subdomains)
150 51 : if (!MooseMeshUtils::hasSubdomainName(mesh, name))
151 6 : paramError("included_subdomains", "The block '", name, "' was not found in the mesh");
152 :
153 48 : _included_subdomain_ids = MooseMeshUtils::getSubdomainIDs(mesh, subdomains);
154 48 : }
155 :
156 92 : if (_check_excluded_subdomains)
157 : {
158 : // check that the subdomains exist in the mesh
159 16 : const auto subdomains = getParam<std::vector<SubdomainName>>("excluded_subdomains");
160 16 : for (const auto & name : subdomains)
161 8 : if (!MooseMeshUtils::hasSubdomainName(mesh, name))
162 0 : paramError("excluded_subdomains", "The block '", name, "' was not found in the mesh");
163 :
164 8 : _excluded_subdomain_ids = MooseMeshUtils::getSubdomainIDs(mesh, subdomains);
165 :
166 8 : if (_check_included_subdomains)
167 : {
168 : // Check that included and excluded nodeset lists do not overlap
169 16 : for (const auto & subdomain_id : _included_subdomain_ids)
170 8 : if (std::find(_excluded_subdomain_ids.begin(),
171 : _excluded_subdomain_ids.end(),
172 16 : subdomain_id) != _excluded_subdomain_ids.end())
173 0 : paramError("excluded_subdomains",
174 : "'included_subdomains' and 'excluded_subdomains' lists should not overlap");
175 : }
176 8 : }
177 :
178 : // Build the node to element map, which is usually provided by a MooseMesh but in the mesh
179 : // generation process we are working with a MeshBase
180 2364 : for (const auto & elem : mesh.active_element_ptr_range())
181 19232 : for (unsigned int n = 0; n < elem->n_nodes(); n++)
182 17052 : _node_to_elem_map[elem->node_id(n)].push_back(elem->id());
183 92 : }
184 :
185 : bool
186 288 : NodeSetsGeneratorBase::nodeOnMeshExteriorBoundary(const Node * node,
187 : const std::vector<dof_id_type> & node_elems,
188 : const MeshBase & mesh) const
189 : {
190 : // Loop on the elements and check whether the node is part of a side with no neighbor (exterior)
191 416 : for (const auto elem_id : node_elems)
192 : {
193 400 : const auto elem = mesh.elem_ptr(elem_id);
194 1616 : for (const auto side_i : make_range(elem->n_sides()))
195 : {
196 : // Node is part of the side
197 1488 : if (elem->side_ptr(side_i)->get_node_index(node) != libMesh::invalid_uint)
198 : {
199 : // No neighbor on that side
200 736 : if (!elem->neighbor_ptr(side_i))
201 272 : return true;
202 : }
203 : }
204 : }
205 16 : return false;
206 : }
207 :
208 : bool
209 3072 : NodeSetsGeneratorBase::nodeElementsInIncludedSubdomains(const std::vector<dof_id_type> node_elems,
210 : const MeshBase & mesh) const
211 : {
212 10192 : for (const auto elem_id : node_elems)
213 : {
214 8040 : subdomain_id_type curr_subdomain = mesh.elem_ptr(elem_id)->subdomain_id();
215 8040 : if (std ::find(_included_subdomain_ids.begin(),
216 : _included_subdomain_ids.end(),
217 16080 : curr_subdomain) != _included_subdomain_ids.end())
218 920 : return true;
219 : }
220 2152 : return false;
221 : }
222 :
223 : bool
224 216 : NodeSetsGeneratorBase::nodeElementsInExcludedSubdomains(const std::vector<dof_id_type> node_elems,
225 : const MeshBase & mesh) const
226 : {
227 856 : for (const auto elem_id : node_elems)
228 : {
229 712 : subdomain_id_type curr_subdomain = mesh.elem_ptr(elem_id)->subdomain_id();
230 712 : if (std ::find(_excluded_subdomain_ids.begin(),
231 : _excluded_subdomain_ids.end(),
232 1424 : curr_subdomain) != _excluded_subdomain_ids.end())
233 72 : return true;
234 : }
235 144 : return false;
236 : }
237 :
238 : bool
239 1280 : NodeSetsGeneratorBase::nodeInIncludedNodesets(const std::vector<BoundaryID> & node_nodesets) const
240 : {
241 3072 : for (const auto bid : node_nodesets)
242 1984 : if (std::find(_included_nodeset_ids.begin(), _included_nodeset_ids.end(), bid) !=
243 3968 : _included_nodeset_ids.end())
244 192 : return true;
245 1088 : return false;
246 : }
247 :
248 : bool
249 128 : NodeSetsGeneratorBase::nodeInExcludedNodesets(const std::vector<BoundaryID> & node_nodesets) const
250 : {
251 256 : for (const auto bid : node_nodesets)
252 192 : if (std::find(_excluded_nodeset_ids.begin(), _excluded_nodeset_ids.end(), bid) !=
253 384 : _excluded_nodeset_ids.end())
254 64 : return true;
255 64 : return false;
256 : }
257 :
258 : bool
259 5120 : NodeSetsGeneratorBase::nodeSatisfiesRequirements(const Node * node,
260 : const std::vector<BoundaryID> & node_nodesets,
261 : const std::vector<dof_id_type> & node_elems,
262 : const MeshBase & mesh) const
263 : {
264 : // Skip if side has neighbor and we only want external nodes
265 5120 : if (_include_only_external_nodes && !nodeOnMeshExteriorBoundary(node, node_elems, mesh))
266 16 : return false;
267 :
268 : // Skip if none of the elements owning the node are in the list of accepted subdomains
269 5104 : if (_check_included_subdomains && !nodeElementsInIncludedSubdomains(node_elems, mesh))
270 2152 : return false;
271 :
272 : // Skip if a element owning the node is in the list of excluded subdomains
273 : // Note: if a node is on the interface of included subdomains and excluded subdomains,
274 : // it will pass the above check but return false here, i.e. subdomain excluding will
275 : // win if both subdomain including and excluding are true.
276 2952 : if (_check_excluded_subdomains && nodeElementsInExcludedSubdomains(node_elems, mesh))
277 72 : return false;
278 :
279 : // Skip if side is not part of included nodesets
280 2880 : if (_check_included_nodesets && !nodeInIncludedNodesets(node_nodesets))
281 1088 : return false;
282 :
283 : // Skip if side is part of excluded nodesets
284 1792 : if (_check_excluded_nodesets && nodeInExcludedNodesets(node_nodesets))
285 64 : return false;
286 :
287 1728 : return true;
288 : }
|