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 1520132 : BoundaryRestrictable::validParams()
18 : {
19 :
20 : // Create instance of InputParameters
21 1520132 : InputParameters params = emptyInputParameters();
22 :
23 : // Create user-facing 'boundary' input for restricting inheriting object to boundaries
24 6080528 : 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 3040264 : if (!params.isParamValid("_dual_restrictable"))
30 4560396 : params.addPrivateParam<bool>("_dual_restrictable", false);
31 :
32 1520132 : return params;
33 0 : }
34 :
35 : // Standard constructor
36 202076 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object, bool nodal)
37 202076 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
38 606228 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
39 : : NULL),
40 404152 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
41 : : NULL),
42 404152 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
43 202076 : _block_ids(_empty_block_ids),
44 808304 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
45 355918 : _bnd_material_data(
46 : #ifdef MOOSE_KOKKOS_ENABLED
47 153842 : moose_object->isKokkosObject()
48 5227 : ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
49 : :
50 : #endif
51 196849 : _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
52 202076 : _bnd_nodal(nodal),
53 760070 : _moose_object(*moose_object)
54 : {
55 202076 : initializeBoundaryRestrictable();
56 202080 : }
57 :
58 : // Dual restricted constructor
59 40567 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object,
60 : const std::set<SubdomainID> & block_ids,
61 40567 : bool nodal)
62 40567 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
63 121701 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
64 : : NULL),
65 81134 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
66 : : NULL),
67 81134 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
68 40567 : _block_ids(block_ids),
69 162268 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
70 71941 : _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 37544 : _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
77 40567 : _bnd_nodal(nodal),
78 153075 : _moose_object(*moose_object)
79 : {
80 40567 : initializeBoundaryRestrictable();
81 40564 : }
82 :
83 : void
84 242643 : BoundaryRestrictable::initializeBoundaryRestrictable()
85 : {
86 : // The name and id of the object
87 242643 : const std::string & name = _moose_object.name();
88 :
89 : // If the mesh pointer is not defined, but FEProblemBase is, get it from there
90 242643 : if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
91 242643 : _bnd_mesh = &_bnd_feproblem->mesh();
92 :
93 : // Check that the mesh pointer was defined, it is required for this class to operate
94 242643 : 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 727929 : if (_moose_object.isParamValid("boundary"))
100 : {
101 : // Extract the blocks from the input
102 221466 : _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
103 :
104 : // Get the IDs from the supplied names
105 110733 : _vec_ids = _bnd_mesh->getBoundaryIDs(_boundary_names, true);
106 :
107 : // Store the IDs, handling ANY_BOUNDARY_ID if supplied
108 110733 : if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
109 221466 : _boundary_names.end())
110 64 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
111 : else
112 110669 : _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 242643 : 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 242640 : if (_bnd_ids.empty())
125 : {
126 131910 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
127 263820 : _boundary_names = {"ANY_BOUNDARY_ID"};
128 : }
129 :
130 : // If this object is block restricted, check that defined blocks exist on the mesh
131 242640 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
132 : {
133 : const std::set<BoundaryID> * valid_ids;
134 110666 : const char * message_ptr = nullptr;
135 :
136 110666 : if (_bnd_nodal)
137 : {
138 83160 : valid_ids = &_bnd_mesh->meshNodesetIds();
139 83160 : message_ptr = "node sets";
140 : }
141 : else
142 : {
143 27506 : valid_ids = &_bnd_mesh->meshSidesetIds();
144 27506 : message_ptr = "side sets";
145 : }
146 :
147 110666 : std::vector<BoundaryID> diff;
148 :
149 110666 : 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 110666 : 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 8 : if (!_bnd_nodal)
176 : // Diagnostic message
177 : msg << "\n\nMOOSE distinguishes between \"node sets\" and \"side sets\" depending on "
178 : "whether\nyou are using \"Nodal\" or \"Integrated\" BCs respectively. Node sets "
179 : "corresponding\nto your side sets are constructed for you by default.\n\n"
180 : "Try setting \"Mesh/construct_side_list_from_node_list=true\" if you see this "
181 : "error.\n"
182 5 : "Note: If you are running with adaptivity you should prefer using side sets.";
183 :
184 20 : _moose_object.paramError("boundary", msg.str());
185 2 : }
186 110660 : }
187 :
188 : #ifdef MOOSE_KOKKOS_ENABLED
189 185208 : if (_moose_object.isKokkosObject())
190 8250 : _bnd_feproblem->addKokkosMeshInitializationHook(
191 16500 : std::bind(&BoundaryRestrictable::initializeKokkosBoundaryRestrictable, this));
192 : #endif
193 374542 : }
194 :
195 582744 : BoundaryRestrictable::~BoundaryRestrictable() {}
196 :
197 : const std::set<BoundaryID> &
198 792615 : BoundaryRestrictable::boundaryIDs() const
199 : {
200 792615 : return _bnd_ids;
201 : }
202 :
203 : const std::vector<BoundaryName> &
204 13051 : BoundaryRestrictable::boundaryNames() const
205 : {
206 13051 : return _boundary_names;
207 : }
208 :
209 : unsigned int
210 192 : BoundaryRestrictable::numBoundaryIDs() const
211 : {
212 192 : return (unsigned int)_bnd_ids.size();
213 : }
214 :
215 : bool
216 1170246 : BoundaryRestrictable::boundaryRestricted() const
217 : {
218 1170246 : return BoundaryRestrictable::restricted(_bnd_ids);
219 : }
220 :
221 : bool
222 1393396 : BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
223 : {
224 1393396 : return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
225 : }
226 :
227 : bool
228 6 : BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
229 : {
230 : // Create a vector and utilize the getBoundaryIDs function, which
231 : // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
232 18 : return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
233 6 : }
234 :
235 : bool
236 6 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
237 : {
238 6 : return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
239 : }
240 :
241 : bool
242 174831 : BoundaryRestrictable::hasBoundary(const BoundaryID & id) const
243 : {
244 174831 : if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
245 0 : return true;
246 : else
247 174831 : return _bnd_ids.find(id) != _bnd_ids.end();
248 : }
249 :
250 : bool
251 18 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
252 : {
253 18 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
254 36 : return hasBoundary(ids_set, type);
255 18 : }
256 :
257 : bool
258 270 : BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
259 : {
260 : // An empty input is assumed to be ANY_BOUNDARY_ID
261 270 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
262 240 : return true;
263 :
264 : // All supplied IDs must match those of the object
265 30 : else if (type == ALL)
266 : {
267 30 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
268 0 : return true;
269 : else
270 30 : return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
271 : }
272 : // Any of the supplied IDs must match those of the object
273 : else
274 : {
275 : // Loop through the supplied ids
276 0 : for (const auto & id : ids)
277 : {
278 : // Test the current supplied id
279 0 : bool test = hasBoundary(id);
280 :
281 : // If the id exists in the stored ids, then return true, otherwise
282 0 : if (test)
283 0 : return true;
284 : }
285 0 : return false;
286 : }
287 : }
288 :
289 : bool
290 3 : BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
291 : {
292 : // An empty input is assumed to be ANY_BOUNDARY_ID
293 3 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
294 0 : return true;
295 :
296 3 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
297 0 : return std::includes(ids.begin(),
298 : ids.end(),
299 0 : _bnd_mesh->meshBoundaryIds().begin(),
300 0 : _bnd_mesh->meshBoundaryIds().end());
301 : else
302 3 : return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
303 : }
304 :
305 : bool
306 0 : BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
307 : {
308 0 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
309 0 : return isBoundarySubset(ids_set);
310 0 : }
311 :
312 : const std::set<BoundaryID> &
313 2992 : BoundaryRestrictable::meshBoundaryIDs() const
314 : {
315 2992 : return _bnd_mesh->getBoundaryIDs();
316 : }
317 :
318 : bool
319 22 : BoundaryRestrictable::hasBoundaryMaterialPropertyHelper(const std::string & prop_name) const
320 : {
321 : // Reference to MaterialWarehouse for testing and retrieving boundary ids
322 22 : const MaterialWarehouse & warehouse = _bnd_feproblem->getMaterialWarehouse();
323 :
324 : // Complete set of BoundaryIDs that this object is defined
325 : const std::set<BoundaryID> & ids =
326 22 : hasBoundary(Moose::ANY_BOUNDARY_ID) ? meshBoundaryIDs() : boundaryIDs();
327 :
328 : // Loop over each BoundaryID for this object
329 38 : for (const auto & id : ids)
330 : {
331 : // Storage of material properties that have been DECLARED on this BoundaryID
332 22 : std::set<std::string> declared_props;
333 :
334 : // If boundary materials exist, populated the set of properties that were declared
335 22 : if (warehouse.hasActiveBoundaryObjects(id))
336 : {
337 : const std::vector<std::shared_ptr<MaterialBase>> & mats =
338 22 : warehouse.getActiveBoundaryObjects(id);
339 44 : for (const auto & mat : mats)
340 : {
341 22 : const std::set<std::string> & mat_props = mat->getSuppliedItems();
342 22 : declared_props.insert(mat_props.begin(), mat_props.end());
343 : }
344 : }
345 :
346 : // If the supplied property is not in the list of properties on the current id, return false
347 22 : if (declared_props.find(prop_name) == declared_props.end())
348 6 : return false;
349 22 : }
350 :
351 : // If you get here the supplied property is defined on all boundaries
352 16 : return true;
353 : }
|