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 5964014 : BoundaryRestrictable::validParams()
18 : {
19 :
20 : // Create instance of InputParameters
21 5964014 : InputParameters params = emptyInputParameters();
22 :
23 : // Create user-facing 'boundary' input for restricting inheriting object to boundaries
24 23856056 : 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 11928028 : if (!params.isParamValid("_dual_restrictable"))
30 17892042 : params.addPrivateParam<bool>("_dual_restrictable", false);
31 :
32 5964014 : return params;
33 0 : }
34 :
35 : // Standard constructor
36 212426 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object, bool nodal)
37 212426 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
38 637278 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
39 : : NULL),
40 424852 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
41 : : NULL),
42 424852 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
43 212426 : _block_ids(_empty_block_ids),
44 849704 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
45 358252 : _bnd_material_data(
46 : #ifdef MOOSE_KOKKOS_ENABLED
47 145826 : moose_object->isKokkosObject({})
48 1674 : ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
49 : :
50 : #endif
51 210752 : _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
52 212426 : _bnd_nodal(nodal),
53 783104 : _moose_object(*moose_object)
54 : {
55 212426 : initializeBoundaryRestrictable();
56 212428 : }
57 :
58 : // Dual restricted constructor
59 41950 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object,
60 : const std::set<SubdomainID> & block_ids,
61 41950 : bool nodal)
62 41950 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
63 125850 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
64 : : NULL),
65 83900 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
66 : : NULL),
67 83900 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
68 41950 : _block_ids(block_ids),
69 167800 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
70 70972 : _bnd_material_data(
71 : #ifdef MOOSE_KOKKOS_ENABLED
72 29022 : moose_object->isKokkosObject({})
73 952 : ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
74 : :
75 : #endif
76 40998 : _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
77 41950 : _bnd_nodal(nodal),
78 154872 : _moose_object(*moose_object)
79 : {
80 41950 : initializeBoundaryRestrictable();
81 41946 : }
82 :
83 : void
84 254376 : BoundaryRestrictable::initializeBoundaryRestrictable()
85 : {
86 : // The name and id of the object
87 254376 : const std::string & name = _moose_object.name();
88 :
89 : // If the mesh pointer is not defined, but FEProblemBase is, get it from there
90 254376 : if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
91 254376 : _bnd_mesh = &_bnd_feproblem->mesh();
92 :
93 : // Check that the mesh pointer was defined, it is required for this class to operate
94 254376 : 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 763128 : if (_moose_object.isParamValid("boundary"))
100 : {
101 : // Extract the blocks from the input
102 240394 : _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
103 :
104 : // Get the IDs from the supplied names
105 120197 : _vec_ids = _bnd_mesh->getBoundaryIDs(_boundary_names, true);
106 :
107 : // Store the IDs, handling ANY_BOUNDARY_ID if supplied
108 120197 : if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
109 240394 : _boundary_names.end())
110 71 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
111 : else
112 120126 : _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 254376 : if (!_bnd_dual_restrictable && !_bnd_ids.empty() && !_block_ids.empty())
117 4 : if (!_block_ids.empty() && _block_ids.find(Moose::ANY_BLOCK_ID) == _block_ids.end())
118 8 : _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 254372 : if (_bnd_ids.empty())
125 : {
126 134179 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
127 268358 : _boundary_names = {"ANY_BOUNDARY_ID"};
128 : }
129 :
130 : // If this object is block restricted, check that defined blocks exist on the mesh
131 254372 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
132 : {
133 : const std::set<BoundaryID> * valid_ids;
134 120122 : const char * message_ptr = nullptr;
135 :
136 120122 : if (_bnd_nodal)
137 : {
138 89083 : valid_ids = &_bnd_mesh->meshNodesetIds();
139 89083 : message_ptr = "node sets";
140 : }
141 : else
142 : {
143 31039 : valid_ids = &_bnd_mesh->meshSidesetIds();
144 31039 : message_ptr = "side sets";
145 : }
146 :
147 120122 : std::vector<BoundaryID> diff;
148 :
149 120122 : 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 120122 : if (!diff.empty())
156 : {
157 10 : std::ostringstream msg;
158 10 : auto sep = " ";
159 10 : msg << "the following " << message_ptr << " (ids) do not exist on the mesh:";
160 22 : for (const auto & id : diff)
161 : {
162 12 : if (_boundary_names.size() > 0)
163 : {
164 12 : auto & name = _boundary_names.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) -
165 12 : _vec_ids.begin());
166 12 : if (std::to_string(id) != name)
167 8 : msg << sep << name << " (" << id << ")";
168 : else
169 4 : msg << sep << id;
170 : }
171 : else
172 0 : msg << sep << id;
173 12 : sep = ", ";
174 : }
175 10 : 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 6 : "Note: If you are running with adaptivity you should prefer using side sets.";
183 :
184 24 : _moose_object.paramError("boundary", msg.str());
185 2 : }
186 120114 : }
187 :
188 : #ifdef MOOSE_KOKKOS_ENABLED
189 174840 : if (_moose_object.isKokkosObject({}))
190 2626 : initializeKokkosBoundaryRestrictable(_bnd_mesh);
191 : #endif
192 388541 : }
193 :
194 376084 : BoundaryRestrictable::~BoundaryRestrictable() {}
195 :
196 : const std::set<BoundaryID> &
197 860941 : BoundaryRestrictable::boundaryIDs() const
198 : {
199 860941 : return _bnd_ids;
200 : }
201 :
202 : const std::vector<BoundaryName> &
203 14070 : BoundaryRestrictable::boundaryNames() const
204 : {
205 14070 : return _boundary_names;
206 : }
207 :
208 : unsigned int
209 208 : BoundaryRestrictable::numBoundaryIDs() const
210 : {
211 208 : return (unsigned int)_bnd_ids.size();
212 : }
213 :
214 : bool
215 1201866 : BoundaryRestrictable::boundaryRestricted() const
216 : {
217 1201866 : return BoundaryRestrictable::restricted(_bnd_ids);
218 : }
219 :
220 : bool
221 1436362 : BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
222 : {
223 1436362 : return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
224 : }
225 :
226 : bool
227 8 : BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
228 : {
229 : // Create a vector and utilize the getBoundaryIDs function, which
230 : // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
231 24 : return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
232 8 : }
233 :
234 : bool
235 8 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
236 : {
237 8 : return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
238 : }
239 :
240 : bool
241 197406 : BoundaryRestrictable::hasBoundary(const BoundaryID & id) const
242 : {
243 197406 : if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
244 0 : return true;
245 : else
246 197406 : return _bnd_ids.find(id) != _bnd_ids.end();
247 : }
248 :
249 : bool
250 24 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
251 : {
252 24 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
253 48 : return hasBoundary(ids_set, type);
254 24 : }
255 :
256 : bool
257 300 : BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
258 : {
259 : // An empty input is assumed to be ANY_BOUNDARY_ID
260 300 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
261 260 : return true;
262 :
263 : // All supplied IDs must match those of the object
264 40 : else if (type == ALL)
265 : {
266 40 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
267 0 : return true;
268 : else
269 40 : return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
270 : }
271 : // Any of the supplied IDs must match those of the object
272 : else
273 : {
274 : // Loop through the supplied ids
275 0 : for (const auto & id : ids)
276 : {
277 : // Test the current supplied id
278 0 : bool test = hasBoundary(id);
279 :
280 : // If the id exists in the stored ids, then return true, otherwise
281 0 : if (test)
282 0 : return true;
283 : }
284 0 : return false;
285 : }
286 : }
287 :
288 : bool
289 4 : BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
290 : {
291 : // An empty input is assumed to be ANY_BOUNDARY_ID
292 4 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
293 0 : return true;
294 :
295 4 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
296 0 : return std::includes(ids.begin(),
297 : ids.end(),
298 0 : _bnd_mesh->meshBoundaryIds().begin(),
299 0 : _bnd_mesh->meshBoundaryIds().end());
300 : else
301 4 : return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
302 : }
303 :
304 : bool
305 0 : BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
306 : {
307 0 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
308 0 : return isBoundarySubset(ids_set);
309 0 : }
310 :
311 : const std::set<BoundaryID> &
312 808 : BoundaryRestrictable::meshBoundaryIDs() const
313 : {
314 808 : return _bnd_mesh->getBoundaryIDs();
315 : }
316 :
317 : bool
318 26 : BoundaryRestrictable::hasBoundaryMaterialPropertyHelper(const std::string & prop_name) const
319 : {
320 : // Reference to MaterialWarehouse for testing and retrieving boundary ids
321 26 : const MaterialWarehouse & warehouse = _bnd_feproblem->getMaterialWarehouse();
322 :
323 : // Complete set of BoundaryIDs that this object is defined
324 : const std::set<BoundaryID> & ids =
325 26 : hasBoundary(Moose::ANY_BOUNDARY_ID) ? meshBoundaryIDs() : boundaryIDs();
326 :
327 : // Loop over each BoundaryID for this object
328 44 : for (const auto & id : ids)
329 : {
330 : // Storage of material properties that have been DECLARED on this BoundaryID
331 26 : std::set<std::string> declared_props;
332 :
333 : // If boundary materials exist, populated the set of properties that were declared
334 26 : if (warehouse.hasActiveBoundaryObjects(id))
335 : {
336 : const std::vector<std::shared_ptr<MaterialBase>> & mats =
337 26 : warehouse.getActiveBoundaryObjects(id);
338 52 : for (const auto & mat : mats)
339 : {
340 26 : const std::set<std::string> & mat_props = mat->getSuppliedItems();
341 26 : declared_props.insert(mat_props.begin(), mat_props.end());
342 : }
343 : }
344 :
345 : // If the supplied property is not in the list of properties on the current id, return false
346 26 : if (declared_props.find(prop_name) == declared_props.end())
347 8 : return false;
348 26 : }
349 :
350 : // If you get here the supplied property is defined on all boundaries
351 18 : return true;
352 : }
|