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 : // MOOSE includes
11 : #include "BoundaryRestrictable.h"
12 : #include "Material.h"
13 : #include "MooseMesh.h"
14 : #include "MooseObject.h"
15 :
16 : InputParameters
17 1520725 : BoundaryRestrictable::validParams()
18 : {
19 :
20 : // Create instance of InputParameters
21 1520725 : InputParameters params = emptyInputParameters();
22 :
23 : // Create user-facing 'boundary' input for restricting inheriting object to boundaries
24 6082900 : params.addParam<std::vector<BoundaryName>>(
25 : "boundary", "The list of boundaries (ids or names) from the mesh where this object applies");
26 :
27 : // A parameter for disabling error message for objects restrictable by boundary and block,
28 : // if the parameter is valid it was already set so don't do anything
29 3041450 : if (!params.isParamValid("_dual_restrictable"))
30 4562175 : params.addPrivateParam<bool>("_dual_restrictable", false);
31 :
32 1520725 : return params;
33 0 : }
34 :
35 : // Standard constructor
36 202824 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object, bool nodal)
37 202824 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
38 608472 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
39 : : NULL),
40 405648 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
41 : : NULL),
42 405648 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
43 202824 : _block_ids(_empty_block_ids),
44 811296 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
45 357155 : _bnd_material_data(
46 : #ifdef MOOSE_KOKKOS_ENABLED
47 154331 : moose_object->isKokkosObject()
48 5227 : ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
49 : :
50 : #endif
51 197597 : _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
52 202824 : _bnd_nodal(nodal),
53 762803 : _moose_object(*moose_object)
54 : {
55 202824 : initializeBoundaryRestrictable();
56 202828 : }
57 :
58 : // Dual restricted constructor
59 40750 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object,
60 : const std::set<SubdomainID> & block_ids,
61 40750 : bool nodal)
62 40750 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
63 122250 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
64 : : NULL),
65 81500 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
66 : : NULL),
67 81500 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
68 40750 : _block_ids(block_ids),
69 163000 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
70 72124 : _bnd_material_data(
71 : #ifdef MOOSE_KOKKOS_ENABLED
72 31374 : moose_object->isKokkosObject()
73 3023 : ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
74 : :
75 : #endif
76 37727 : _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
77 40750 : _bnd_nodal(nodal),
78 153624 : _moose_object(*moose_object)
79 : {
80 40750 : initializeBoundaryRestrictable();
81 40747 : }
82 :
83 : void
84 243574 : BoundaryRestrictable::initializeBoundaryRestrictable()
85 : {
86 : // The name and id of the object
87 243574 : const std::string & name = _moose_object.name();
88 :
89 : // If the mesh pointer is not defined, but FEProblemBase is, get it from there
90 243574 : if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
91 243574 : _bnd_mesh = &_bnd_feproblem->mesh();
92 :
93 : // Check that the mesh pointer was defined, it is required for this class to operate
94 243574 : if (_bnd_mesh == NULL)
95 0 : mooseError("The input parameters must contain a pointer to FEProblemBase via '_fe_problem' or "
96 : "a pointer to the MooseMesh via '_mesh'");
97 :
98 : // If the user supplies boundary IDs
99 730722 : if (_moose_object.isParamValid("boundary"))
100 : {
101 : // Extract the blocks from the input
102 222604 : _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
103 :
104 : // Get the IDs from the supplied names
105 111302 : _vec_ids = _bnd_mesh->getBoundaryIDs(_boundary_names, true);
106 :
107 : // Store the IDs, handling ANY_BOUNDARY_ID if supplied
108 111302 : if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
109 222604 : _boundary_names.end())
110 64 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
111 : else
112 111238 : _bnd_ids.insert(_vec_ids.begin(), _vec_ids.end());
113 : }
114 :
115 : // Produce error if the object is not allowed to be both block and boundary restricted
116 243574 : if (!_bnd_dual_restrictable && !_bnd_ids.empty() && !_block_ids.empty())
117 3 : if (!_block_ids.empty() && _block_ids.find(Moose::ANY_BLOCK_ID) == _block_ids.end())
118 6 : _moose_object.paramError("boundary",
119 : "Attempted to restrict the object '",
120 : name,
121 : "' to a boundary, but the object is already restricted by block(s)");
122 :
123 : // Store ANY_BOUNDARY_ID if empty
124 243571 : if (_bnd_ids.empty())
125 : {
126 132272 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
127 264544 : _boundary_names = {"ANY_BOUNDARY_ID"};
128 : }
129 :
130 : // If this object is block restricted, check that defined blocks exist on the mesh
131 243571 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
132 : {
133 : const std::set<BoundaryID> * valid_ids;
134 111235 : const char * message_ptr = nullptr;
135 :
136 111235 : if (_bnd_nodal)
137 : {
138 83482 : valid_ids = &_bnd_mesh->meshNodesetIds();
139 83482 : message_ptr = "node sets";
140 : }
141 : else
142 : {
143 27753 : valid_ids = &_bnd_mesh->meshSidesetIds();
144 27753 : message_ptr = "side sets";
145 : }
146 :
147 111235 : std::vector<BoundaryID> diff;
148 :
149 111235 : std::set_difference(_bnd_ids.begin(),
150 : _bnd_ids.end(),
151 : valid_ids->begin(),
152 : valid_ids->end(),
153 : std::back_inserter(diff));
154 :
155 111235 : if (!diff.empty())
156 : {
157 8 : std::ostringstream msg;
158 8 : auto sep = " ";
159 8 : msg << "the following " << message_ptr << " (ids) do not exist on the mesh:";
160 18 : for (const auto & id : diff)
161 : {
162 10 : if (_boundary_names.size() > 0)
163 : {
164 10 : auto & name = _boundary_names.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) -
165 10 : _vec_ids.begin());
166 10 : if (std::to_string(id) != name)
167 7 : msg << sep << name << " (" << id << ")";
168 : else
169 3 : msg << sep << id;
170 : }
171 : else
172 0 : msg << sep << id;
173 10 : sep = ", ";
174 : }
175 :
176 : const auto & other_ids =
177 8 : _bnd_nodal ? _bnd_mesh->meshSidesetIds() : _bnd_mesh->meshNodesetIds();
178 8 : std::vector<BoundaryID> other_boundary_ids;
179 8 : std::set_intersection(diff.begin(),
180 : diff.end(),
181 : other_ids.begin(),
182 : other_ids.end(),
183 : std::back_inserter(other_boundary_ids));
184 8 : if (!other_boundary_ids.empty())
185 : {
186 3 : msg << "\n\nThe following boundary ";
187 3 : if (other_boundary_ids.size() == 1)
188 3 : msg << "id exists";
189 : else
190 0 : msg << "ids exist";
191 3 : if (other_boundary_ids.size() == 1)
192 3 : msg << " as " << (_bnd_nodal ? "a side set" : "a node set")
193 3 : << " but is being requested as " << (_bnd_nodal ? "a node set" : "a side set") << ":";
194 : else
195 0 : msg << " as " << (_bnd_nodal ? "side sets" : "node sets")
196 0 : << " but are being requested as " << (_bnd_nodal ? "node sets" : "side sets") << ":";
197 :
198 3 : sep = " ";
199 6 : for (const auto id : other_boundary_ids)
200 : {
201 3 : msg << sep << id;
202 3 : sep = ", ";
203 : }
204 :
205 3 : if (!_bnd_nodal)
206 : msg << "\n\nTry setting Mesh/construct_side_list_from_node_list=true if you want side "
207 3 : "sets constructed from node sets.";
208 : }
209 :
210 20 : _moose_object.paramError("boundary", msg.str());
211 4 : }
212 111229 : }
213 :
214 : #ifdef MOOSE_KOKKOS_ENABLED
215 185697 : if (_moose_object.isKokkosObject())
216 8250 : _bnd_feproblem->addKokkosMeshInitializationHook(
217 16500 : std::bind(&BoundaryRestrictable::initializeKokkosBoundaryRestrictable, this));
218 : #endif
219 375835 : }
220 :
221 583707 : BoundaryRestrictable::~BoundaryRestrictable() {}
222 :
223 : const std::set<BoundaryID> &
224 795778 : BoundaryRestrictable::boundaryIDs() const
225 : {
226 795778 : return _bnd_ids;
227 : }
228 :
229 : const std::vector<BoundaryName> &
230 13051 : BoundaryRestrictable::boundaryNames() const
231 : {
232 13051 : return _boundary_names;
233 : }
234 :
235 : unsigned int
236 192 : BoundaryRestrictable::numBoundaryIDs() const
237 : {
238 192 : return (unsigned int)_bnd_ids.size();
239 : }
240 :
241 : bool
242 1173356 : BoundaryRestrictable::boundaryRestricted() const
243 : {
244 1173356 : return BoundaryRestrictable::restricted(_bnd_ids);
245 : }
246 :
247 : bool
248 1397231 : BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
249 : {
250 1397231 : return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
251 : }
252 :
253 : bool
254 6 : BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
255 : {
256 : // Create a vector and utilize the getBoundaryIDs function, which
257 : // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
258 18 : return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
259 6 : }
260 :
261 : bool
262 6 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
263 : {
264 6 : return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
265 : }
266 :
267 : bool
268 174867 : BoundaryRestrictable::hasBoundary(const BoundaryID & id) const
269 : {
270 174867 : if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
271 0 : return true;
272 : else
273 174867 : return _bnd_ids.find(id) != _bnd_ids.end();
274 : }
275 :
276 : bool
277 18 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
278 : {
279 18 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
280 36 : return hasBoundary(ids_set, type);
281 18 : }
282 :
283 : bool
284 270 : BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
285 : {
286 : // An empty input is assumed to be ANY_BOUNDARY_ID
287 270 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
288 240 : return true;
289 :
290 : // All supplied IDs must match those of the object
291 30 : else if (type == ALL)
292 : {
293 30 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
294 0 : return true;
295 : else
296 30 : return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
297 : }
298 : // Any of the supplied IDs must match those of the object
299 : else
300 : {
301 : // Loop through the supplied ids
302 0 : for (const auto & id : ids)
303 : {
304 : // Test the current supplied id
305 0 : bool test = hasBoundary(id);
306 :
307 : // If the id exists in the stored ids, then return true, otherwise
308 0 : if (test)
309 0 : return true;
310 : }
311 0 : return false;
312 : }
313 : }
314 :
315 : bool
316 3 : BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
317 : {
318 : // An empty input is assumed to be ANY_BOUNDARY_ID
319 3 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
320 0 : return true;
321 :
322 3 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
323 0 : return std::includes(ids.begin(),
324 : ids.end(),
325 0 : _bnd_mesh->meshBoundaryIds().begin(),
326 0 : _bnd_mesh->meshBoundaryIds().end());
327 : else
328 3 : return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
329 : }
330 :
331 : bool
332 0 : BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
333 : {
334 0 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
335 0 : return isBoundarySubset(ids_set);
336 0 : }
337 :
338 : const std::set<BoundaryID> &
339 2992 : BoundaryRestrictable::meshBoundaryIDs() const
340 : {
341 2992 : return _bnd_mesh->getBoundaryIDs();
342 : }
343 :
344 : bool
345 22 : BoundaryRestrictable::hasBoundaryMaterialPropertyHelper(const std::string & prop_name) const
346 : {
347 : // Reference to MaterialWarehouse for testing and retrieving boundary ids
348 22 : const MaterialWarehouse & warehouse = _bnd_feproblem->getMaterialWarehouse();
349 :
350 : // Complete set of BoundaryIDs that this object is defined
351 : const std::set<BoundaryID> & ids =
352 22 : hasBoundary(Moose::ANY_BOUNDARY_ID) ? meshBoundaryIDs() : boundaryIDs();
353 :
354 : // Loop over each BoundaryID for this object
355 38 : for (const auto & id : ids)
356 : {
357 : // Storage of material properties that have been DECLARED on this BoundaryID
358 22 : std::set<std::string> declared_props;
359 :
360 : // If boundary materials exist, populated the set of properties that were declared
361 22 : if (warehouse.hasActiveBoundaryObjects(id))
362 : {
363 : const std::vector<std::shared_ptr<MaterialBase>> & mats =
364 22 : warehouse.getActiveBoundaryObjects(id);
365 44 : for (const auto & mat : mats)
366 : {
367 22 : const std::set<std::string> & mat_props = mat->getSuppliedItems();
368 22 : declared_props.insert(mat_props.begin(), mat_props.end());
369 : }
370 : }
371 :
372 : // If the supplied property is not in the list of properties on the current id, return false
373 22 : if (declared_props.find(prop_name) == declared_props.end())
374 6 : return false;
375 22 : }
376 :
377 : // If you get here the supplied property is defined on all boundaries
378 16 : return true;
379 : }
|