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