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 5452440 : BoundaryRestrictable::validParams()
18 : {
19 :
20 : // Create instance of InputParameters
21 5452440 : InputParameters params = emptyInputParameters();
22 :
23 : // Create user-facing 'boundary' input for restricting inheriting object to boundaries
24 5452440 : 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 5452440 : if (!params.isParamValid("_dual_restrictable"))
30 5452440 : params.addPrivateParam<bool>("_dual_restrictable", false);
31 :
32 5452440 : return params;
33 0 : }
34 :
35 : // Standard constructor
36 192939 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object, bool nodal)
37 385878 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
38 192939 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
39 : : NULL),
40 192939 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
41 : : NULL),
42 192939 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
43 192939 : _block_ids(_empty_block_ids),
44 192939 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
45 192939 : _bnd_material_data(_bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
46 192939 : _bnd_nodal(nodal),
47 578817 : _moose_object(*moose_object)
48 : {
49 192939 : initializeBoundaryRestrictable();
50 192934 : }
51 :
52 : // Dual restricted constructor
53 36106 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object,
54 : const std::set<SubdomainID> & block_ids,
55 36106 : bool nodal)
56 72212 : : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
57 36106 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
58 : : NULL),
59 36106 : _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
60 : : NULL),
61 36106 : _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
62 36106 : _block_ids(block_ids),
63 36106 : _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
64 36106 : _bnd_material_data(_bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
65 36106 : _bnd_nodal(nodal),
66 108318 : _moose_object(*moose_object)
67 : {
68 36106 : initializeBoundaryRestrictable();
69 36102 : }
70 :
71 : void
72 229045 : BoundaryRestrictable::initializeBoundaryRestrictable()
73 : {
74 : // The name and id of the object
75 229045 : const std::string & name = _moose_object.getParam<std::string>("_object_name");
76 :
77 : // If the mesh pointer is not defined, but FEProblemBase is, get it from there
78 229045 : if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
79 229045 : _bnd_mesh = &_bnd_feproblem->mesh();
80 :
81 : // Check that the mesh pointer was defined, it is required for this class to operate
82 229045 : if (_bnd_mesh == NULL)
83 0 : mooseError("The input parameters must contain a pointer to FEProblemBase via '_fe_problem' or "
84 : "a pointer to the MooseMesh via '_mesh'");
85 :
86 : // If the user supplies boundary IDs
87 229045 : if (_moose_object.isParamValid("boundary"))
88 : {
89 : // Extract the blocks from the input
90 108613 : _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
91 :
92 : // Get the IDs from the supplied names
93 108613 : _vec_ids = _bnd_mesh->getBoundaryIDs(_boundary_names, true);
94 :
95 : // Store the IDs, handling ANY_BOUNDARY_ID if supplied
96 108613 : if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
97 217226 : _boundary_names.end())
98 67 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
99 : else
100 108546 : _bnd_ids.insert(_vec_ids.begin(), _vec_ids.end());
101 : }
102 :
103 : // Produce error if the object is not allowed to be both block and boundary restricted
104 229045 : if (!_bnd_dual_restrictable && !_bnd_ids.empty() && !_block_ids.empty())
105 4 : if (!_block_ids.empty() && _block_ids.find(Moose::ANY_BLOCK_ID) == _block_ids.end())
106 4 : _moose_object.paramError("boundary",
107 : "Attempted to restrict the object '",
108 : name,
109 : "' to a boundary, but the object is already restricted by block(s)");
110 :
111 : // Store ANY_BOUNDARY_ID if empty
112 229041 : if (_bnd_ids.empty())
113 : {
114 120432 : _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
115 240864 : _boundary_names = {"ANY_BOUNDARY_ID"};
116 : }
117 :
118 : // If this object is block restricted, check that defined blocks exist on the mesh
119 229041 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
120 : {
121 : const std::set<BoundaryID> * valid_ids;
122 108542 : const char * message_ptr = nullptr;
123 :
124 108542 : if (_bnd_nodal)
125 : {
126 80552 : valid_ids = &_bnd_mesh->meshNodesetIds();
127 80552 : message_ptr = "node sets";
128 : }
129 : else
130 : {
131 27990 : valid_ids = &_bnd_mesh->meshSidesetIds();
132 27990 : message_ptr = "side sets";
133 : }
134 :
135 108542 : std::vector<BoundaryID> diff;
136 :
137 108542 : std::set_difference(_bnd_ids.begin(),
138 : _bnd_ids.end(),
139 : valid_ids->begin(),
140 : valid_ids->end(),
141 : std::back_inserter(diff));
142 :
143 108542 : if (!diff.empty())
144 : {
145 9 : std::ostringstream msg;
146 9 : auto sep = " ";
147 9 : msg << "the following " << message_ptr << " (ids) do not exist on the mesh:";
148 19 : for (const auto & id : diff)
149 : {
150 10 : if (_boundary_names.size() > 0)
151 : {
152 10 : auto & name = _boundary_names.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) -
153 10 : _vec_ids.begin());
154 10 : if (std::to_string(id) != name)
155 6 : msg << sep << name << " (" << id << ")";
156 : else
157 4 : msg << sep << id;
158 : }
159 : else
160 0 : msg << sep << id;
161 10 : sep = ", ";
162 : }
163 9 : if (!_bnd_nodal)
164 : // Diagnostic message
165 : msg << "\n\nMOOSE distinguishes between \"node sets\" and \"side sets\" depending on "
166 : "whether \nyou are using \"Nodal\" or \"Integrated\" BCs respectively. Node sets "
167 : "corresponding \nto your side sets are constructed for you by default.\n\n"
168 : "Try setting \"Mesh/construct_side_list_from_node_list=true\" if you see this "
169 : "error.\n"
170 5 : "Note: If you are running with adaptivity you should prefer using side sets.";
171 :
172 12 : _moose_object.paramError("boundary", msg.str());
173 1 : }
174 108534 : }
175 349464 : }
176 :
177 216297 : BoundaryRestrictable::~BoundaryRestrictable() {}
178 :
179 : const std::set<BoundaryID> &
180 772509 : BoundaryRestrictable::boundaryIDs() const
181 : {
182 772509 : return _bnd_ids;
183 : }
184 :
185 : const std::vector<BoundaryName> &
186 12992 : BoundaryRestrictable::boundaryNames() const
187 : {
188 12992 : return _boundary_names;
189 : }
190 :
191 : unsigned int
192 192 : BoundaryRestrictable::numBoundaryIDs() const
193 : {
194 192 : return (unsigned int)_bnd_ids.size();
195 : }
196 :
197 : bool
198 1058803 : BoundaryRestrictable::boundaryRestricted() const
199 : {
200 1058803 : return BoundaryRestrictable::restricted(_bnd_ids);
201 : }
202 :
203 : bool
204 1271318 : BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
205 : {
206 1271318 : return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
207 : }
208 :
209 : bool
210 8 : BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
211 : {
212 : // Create a vector and utilize the getBoundaryIDs function, which
213 : // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
214 16 : return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
215 8 : }
216 :
217 : bool
218 8 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
219 : {
220 8 : return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
221 : }
222 :
223 : bool
224 180522 : BoundaryRestrictable::hasBoundary(const BoundaryID & id) const
225 : {
226 180522 : if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
227 0 : return true;
228 : else
229 180522 : return _bnd_ids.find(id) != _bnd_ids.end();
230 : }
231 :
232 : bool
233 24 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
234 : {
235 24 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
236 48 : return hasBoundary(ids_set, type);
237 24 : }
238 :
239 : bool
240 282 : BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
241 : {
242 : // An empty input is assumed to be ANY_BOUNDARY_ID
243 282 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
244 242 : return true;
245 :
246 : // All supplied IDs must match those of the object
247 40 : else if (type == ALL)
248 : {
249 40 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
250 0 : return true;
251 : else
252 40 : return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
253 : }
254 : // Any of the supplied IDs must match those of the object
255 : else
256 : {
257 : // Loop through the supplied ids
258 0 : for (const auto & id : ids)
259 : {
260 : // Test the current supplied id
261 0 : bool test = hasBoundary(id);
262 :
263 : // If the id exists in the stored ids, then return true, otherwise
264 0 : if (test)
265 0 : return true;
266 : }
267 0 : return false;
268 : }
269 : }
270 :
271 : bool
272 4 : BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
273 : {
274 : // An empty input is assumed to be ANY_BOUNDARY_ID
275 4 : if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
276 0 : return true;
277 :
278 4 : if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
279 0 : return std::includes(ids.begin(),
280 : ids.end(),
281 0 : _bnd_mesh->meshBoundaryIds().begin(),
282 0 : _bnd_mesh->meshBoundaryIds().end());
283 : else
284 4 : return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
285 : }
286 :
287 : bool
288 0 : BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
289 : {
290 0 : std::set<BoundaryID> ids_set(ids.begin(), ids.end());
291 0 : return isBoundarySubset(ids_set);
292 0 : }
293 :
294 : const std::set<BoundaryID> &
295 0 : BoundaryRestrictable::meshBoundaryIDs() const
296 : {
297 0 : return _bnd_mesh->getBoundaryIDs();
298 : }
299 :
300 : bool
301 25 : BoundaryRestrictable::hasBoundaryMaterialPropertyHelper(const std::string & prop_name) const
302 : {
303 : // Reference to MaterialWarehouse for testing and retrieving boundary ids
304 25 : const MaterialWarehouse & warehouse = _bnd_feproblem->getMaterialWarehouse();
305 :
306 : // Complete set of BoundaryIDs that this object is defined
307 : const std::set<BoundaryID> & ids =
308 25 : hasBoundary(Moose::ANY_BOUNDARY_ID) ? meshBoundaryIDs() : boundaryIDs();
309 :
310 : // Loop over each BoundaryID for this object
311 42 : for (const auto & id : ids)
312 : {
313 : // Storage of material properties that have been DECLARED on this BoundaryID
314 25 : std::set<std::string> declared_props;
315 :
316 : // If boundary materials exist, populated the set of properties that were declared
317 25 : if (warehouse.hasActiveBoundaryObjects(id))
318 : {
319 : const std::vector<std::shared_ptr<MaterialBase>> & mats =
320 25 : warehouse.getActiveBoundaryObjects(id);
321 50 : for (const auto & mat : mats)
322 : {
323 25 : const std::set<std::string> & mat_props = mat->getSuppliedItems();
324 25 : declared_props.insert(mat_props.begin(), mat_props.end());
325 : }
326 : }
327 :
328 : // If the supplied property is not in the list of properties on the current id, return false
329 25 : if (declared_props.find(prop_name) == declared_props.end())
330 8 : return false;
331 25 : }
332 :
333 : // If you get here the supplied property is defined on all boundaries
334 17 : return true;
335 : }
|