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 "BlockRestrictable.h"
12 :
13 : #include "FEProblem.h"
14 : #include "Material.h"
15 : #include "MooseMesh.h"
16 : #include "MooseVariableFE.h"
17 : #include "SystemBase.h"
18 : #include "Conversion.h"
19 :
20 : InputParameters
21 12058446 : BlockRestrictable::validParams()
22 : {
23 : // Create InputParameters object that will be appended to the parameters for the inheriting object
24 12058446 : InputParameters params = emptyInputParameters();
25 :
26 : // Add the user-facing 'block' input parameter
27 36175338 : params.addParam<std::vector<SubdomainName>>(
28 : "block", "The list of blocks (ids or names) that this object will be applied");
29 :
30 : // A parameter for disabling error message for objects restrictable by boundary and block,
31 : // if the parameter is valid it was already set so don't do anything
32 12058446 : if (!params.have_parameter<bool>("_dual_restrictable"))
33 36175338 : params.addPrivateParam<bool>("_dual_restrictable", false);
34 :
35 : // Return the parameters
36 12058446 : return params;
37 0 : }
38 :
39 : // Standard constructor
40 497417 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object, bool initialize /*=true*/)
41 994834 : : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
42 994834 : _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
43 1492251 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
44 : : NULL),
45 994834 : _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
46 : : NULL),
47 497417 : _boundary_ids(_empty_boundary_ids),
48 1989668 : _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
49 497417 : _blk_name(moose_object->name()),
50 497417 : _blk_dim(libMesh::invalid_uint),
51 1339769 : _moose_object(moose_object)
52 : {
53 497417 : if (initialize)
54 497417 : initializeBlockRestrictable(_moose_object);
55 497413 : }
56 :
57 : // Dual restricted constructor
58 0 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object,
59 0 : const std::set<BoundaryID> & boundary_ids)
60 0 : : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
61 0 : _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
62 0 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
63 : : NULL),
64 0 : _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
65 : : NULL),
66 0 : _boundary_ids(boundary_ids),
67 0 : _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
68 0 : _blk_name(moose_object->name()),
69 0 : _blk_dim(libMesh::invalid_uint),
70 0 : _moose_object(moose_object)
71 : {
72 0 : initializeBlockRestrictable(_moose_object);
73 0 : }
74 :
75 : void
76 497417 : BlockRestrictable::initializeBlockRestrictable(const MooseObject * moose_object)
77 : {
78 : // If the mesh pointer is not defined, but FEProblemBase is, get it from there
79 497417 : if (_blk_feproblem != NULL && _blk_mesh == NULL)
80 497417 : _blk_mesh = &_blk_feproblem->mesh();
81 :
82 : // Check that the mesh pointer was defined, it is required for this class to operate
83 497417 : if (_blk_mesh == NULL)
84 0 : mooseError("The input parameters must contain a pointer to FEProblem via '_fe_problem' or a "
85 : "pointer to the MooseMesh via '_mesh'");
86 :
87 : // Populate the MaterialData pointer
88 497417 : if (_blk_feproblem != NULL)
89 : {
90 : #ifdef MOOSE_KOKKOS_ENABLED
91 344935 : if (_moose_object->isKokkosObject({}))
92 2523 : _blk_material_data = &_blk_feproblem->getKokkosMaterialData(Moose::BLOCK_MATERIAL_DATA);
93 : else
94 : #endif
95 494894 : _blk_material_data = &_blk_feproblem->getMaterialData(Moose::BLOCK_MATERIAL_DATA, _blk_tid);
96 : }
97 :
98 : // The 'block' input is defined
99 1492251 : if (moose_object->isParamValid("block"))
100 : {
101 : // Extract the blocks from the input
102 153680 : _blocks = moose_object->getParam<std::vector<SubdomainName>>("block");
103 :
104 : // Store the IDs in a set, handling ANY_BLOCK_ID if supplied
105 76840 : if (std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end())
106 4525 : _blk_ids.insert(Moose::ANY_BLOCK_ID);
107 : else
108 : {
109 : // Get the IDs from the supplied names
110 72315 : _vec_ids = _blk_mesh->getSubdomainIDs(_blocks);
111 72315 : _blk_ids.insert(_vec_ids.begin(), _vec_ids.end());
112 : }
113 : }
114 :
115 : // When 'blocks' is not set and there is a "variable", use the blocks from the variable
116 1261731 : else if (moose_object->isParamValid("variable"))
117 : {
118 411126 : std::string variable_name = moose_object->parameters().getMooseType("variable");
119 205563 : if (!variable_name.empty())
120 178076 : _blk_ids = _blk_feproblem
121 356152 : ->getVariable(_blk_tid,
122 : variable_name,
123 : Moose::VarKindType::VAR_ANY,
124 : Moose::VarFieldType::VAR_FIELD_ANY)
125 178076 : .activeSubdomains();
126 205563 : }
127 :
128 : // Produce error if the object is not allowed to be both block and boundary restricted
129 497417 : if (!_blk_dual_restrictable && !_boundary_ids.empty() && !_boundary_ids.empty())
130 0 : if (!_boundary_ids.empty() && _boundary_ids.find(Moose::ANY_BOUNDARY_ID) == _boundary_ids.end())
131 0 : moose_object->paramError("block",
132 : "Attempted to restrict the object '",
133 0 : _blk_name,
134 : "' to a block, but the object is already restricted by boundary");
135 :
136 : // If no blocks were defined above, specify that it is valid on all blocks
137 1328573 : if (_blk_ids.empty() && !moose_object->isParamValid("boundary"))
138 : {
139 399098 : _blk_ids.insert(Moose::ANY_BLOCK_ID);
140 798196 : _blocks = {"ANY_BLOCK_ID"};
141 : }
142 :
143 : // If this object is block restricted, check that defined blocks exist on the mesh
144 497417 : if (_blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end())
145 : {
146 93794 : const std::set<SubdomainID> & valid_ids = _blk_mesh->meshSubdomains();
147 93794 : std::vector<SubdomainID> diff;
148 :
149 93794 : std::set_difference(_blk_ids.begin(),
150 : _blk_ids.end(),
151 : valid_ids.begin(),
152 : valid_ids.end(),
153 : std::back_inserter(diff));
154 :
155 93794 : if (!diff.empty())
156 : {
157 4 : std::ostringstream msg;
158 4 : auto sep = " ";
159 4 : msg << "the following blocks (ids) do not exist on the mesh:";
160 8 : for (const auto & id : diff)
161 : {
162 4 : if (_blk_name.size() > 0)
163 : {
164 : auto & name =
165 4 : _blocks.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) - _vec_ids.begin());
166 4 : if (std::to_string(id) != name)
167 0 : msg << sep << name << " (" << id << ")";
168 : else
169 4 : msg << sep << id;
170 : }
171 : else
172 0 : msg << sep << id;
173 4 : sep = ", ";
174 : }
175 4 : std::vector<SubdomainID> valid_ids_vec(valid_ids.begin(), valid_ids.end());
176 4 : auto valid_names = _blk_mesh->getSubdomainNames(valid_ids_vec);
177 16 : msg << "\nBlocks names (resp. ids) that do exist: " << Moose::stringify(valid_names) << " ("
178 24 : << Moose::stringify(valid_ids) << ")";
179 8 : moose_object->paramError("block", msg.str());
180 0 : }
181 93790 : }
182 :
183 : // Get the mesh dimension for the blocks
184 497413 : if (blockRestricted())
185 93790 : _blk_dim = _blk_mesh->getBlocksMaxDimension(_blocks);
186 : else
187 403623 : _blk_dim = _blk_mesh->dimension();
188 :
189 : #ifdef MOOSE_KOKKOS_ENABLED
190 344933 : if (moose_object->isKokkosObject({}))
191 2523 : initializeKokkosBlockRestrictable(_blk_mesh->getKokkosMesh());
192 : #endif
193 896511 : }
194 :
195 : bool
196 2089368 : BlockRestrictable::blockRestricted() const
197 : {
198 2089368 : return _blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end();
199 : }
200 :
201 : const std::vector<SubdomainName> &
202 28969 : BlockRestrictable::blocks() const
203 : {
204 28969 : return _blocks;
205 : }
206 :
207 : const std::set<SubdomainID> &
208 7630344 : BlockRestrictable::blockIDs() const
209 : {
210 7630344 : if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
211 5616195 : return _blk_mesh->meshSubdomains();
212 : else
213 2014149 : return _blk_ids;
214 : }
215 :
216 : unsigned int
217 26 : BlockRestrictable::numBlocks() const
218 : {
219 26 : return (unsigned int)_blk_ids.size();
220 : }
221 :
222 : bool
223 8 : BlockRestrictable::hasBlocks(const SubdomainName & name) const
224 : {
225 : // Create a vector and utilize the getSubdomainIDs function, which
226 : // handles the ANY_BLOCK_ID (getSubdomainID does not)
227 8 : std::vector<SubdomainName> names(1);
228 8 : names[0] = name;
229 16 : return hasBlocks(_blk_mesh->getSubdomainIDs(names));
230 8 : }
231 :
232 : bool
233 8 : BlockRestrictable::hasBlocks(const std::vector<SubdomainName> & names) const
234 : {
235 8 : return hasBlocks(_blk_mesh->getSubdomainIDs(names));
236 : }
237 :
238 : bool
239 0 : BlockRestrictable::hasBlocks(const std::set<SubdomainName> & names) const
240 : {
241 0 : return hasBlocks(_blk_mesh->getSubdomainIDs(names));
242 : }
243 :
244 : bool
245 641741829 : BlockRestrictable::hasBlocks(const SubdomainID id) const
246 : {
247 641741829 : if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
248 541283547 : return true;
249 : else
250 100458282 : return _blk_ids.find(id) != _blk_ids.end();
251 : }
252 :
253 : bool
254 24 : BlockRestrictable::hasBlocks(const std::vector<SubdomainID> & ids) const
255 : {
256 24 : std::set<SubdomainID> ids_set(ids.begin(), ids.end());
257 48 : return hasBlocks(ids_set);
258 24 : }
259 :
260 : bool
261 2379 : BlockRestrictable::hasBlocks(const std::set<SubdomainID> & ids) const
262 : {
263 2379 : if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
264 1062 : return true;
265 : else
266 1317 : return std::includes(_blk_ids.begin(), _blk_ids.end(), ids.begin(), ids.end());
267 : }
268 :
269 : bool
270 1156412 : BlockRestrictable::isBlockSubset(const std::set<SubdomainID> & ids) const
271 : {
272 : // An empty input is assumed to be ANY_BLOCK_ID
273 1156412 : if (ids.empty() || ids.find(Moose::ANY_BLOCK_ID) != ids.end())
274 1089225 : return true;
275 :
276 67187 : if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
277 1488 : return std::includes(ids.begin(),
278 : ids.end(),
279 1488 : _blk_mesh->meshSubdomains().begin(),
280 2976 : _blk_mesh->meshSubdomains().end());
281 : else
282 65699 : return std::includes(ids.begin(), ids.end(), _blk_ids.begin(), _blk_ids.end());
283 : }
284 :
285 : bool
286 0 : BlockRestrictable::isBlockSubset(const std::vector<SubdomainID> & ids) const
287 : {
288 0 : std::set<SubdomainID> ids_set(ids.begin(), ids.end());
289 0 : return isBlockSubset(ids_set);
290 0 : }
291 :
292 : const std::set<SubdomainID> &
293 579315 : BlockRestrictable::meshBlockIDs() const
294 : {
295 579315 : return _blk_mesh->meshSubdomains();
296 : }
297 :
298 : bool
299 15687 : BlockRestrictable::hasBlockMaterialPropertyHelper(const std::string & prop_name)
300 : {
301 :
302 : // Reference to MaterialWarehouse for testing and retrieving block ids
303 15687 : const MaterialWarehouse & warehouse = _blk_feproblem->getMaterialWarehouse();
304 :
305 : // Complete set of ids that this object is active
306 15687 : const std::set<SubdomainID> & ids = blockRestricted() ? blockIDs() : meshBlockIDs();
307 :
308 : // Loop over each id for this object
309 16513 : for (const auto & id : ids)
310 : {
311 : // Storage of material properties that have been DECLARED on this id
312 15765 : std::set<std::string> declared_props;
313 :
314 : // If block materials exist, populated the set of properties that were declared
315 15765 : if (warehouse.hasActiveBlockObjects(id))
316 : {
317 15047 : const std::vector<std::shared_ptr<MaterialBase>> & mats = warehouse.getActiveBlockObjects(id);
318 122464 : for (const auto & mat : mats)
319 : {
320 107417 : const std::set<std::string> & mat_props = mat->getSuppliedItems();
321 107417 : declared_props.insert(mat_props.begin(), mat_props.end());
322 : }
323 : }
324 :
325 : // If the supplied property is not in the list of properties on the current id, return false
326 15765 : if (declared_props.find(prop_name) == declared_props.end())
327 14939 : return false;
328 15765 : }
329 :
330 : // If you get here the supplied property is defined on all blocks
331 748 : return true;
332 : }
333 :
334 : Moose::CoordinateSystemType
335 0 : BlockRestrictable::getBlockCoordSystem()
336 : {
337 0 : if (!_blk_mesh)
338 0 : mooseError("No mesh available in BlockRestrictable::checkCoordSystem()");
339 0 : if (!_blk_feproblem)
340 0 : mooseError("No problem available in BlockRestrictable::checkCoordSystem()");
341 :
342 0 : const auto & subdomains = blockRestricted() ? blockIDs() : meshBlockIDs();
343 :
344 0 : if (subdomains.empty())
345 0 : mooseError("No subdomains found in the problem.");
346 :
347 : // make sure all subdomains are using the same coordinate system
348 0 : auto coord_system = _blk_feproblem->getCoordSystem(*subdomains.begin());
349 0 : for (auto subdomain : subdomains)
350 0 : if (_blk_feproblem->getCoordSystem(subdomain) != coord_system)
351 0 : mooseError("This object requires all subdomains to have the same coordinate system.");
352 :
353 0 : return coord_system;
354 : }
355 :
356 : void
357 1158198 : BlockRestrictable::checkVariable(const MooseVariableFieldBase & variable) const
358 : {
359 : // a variable defined on all internal sides does not need this check because
360 : // it can be coupled with other variables in DG kernels
361 1168106 : if (!_blk_mesh->interiorLowerDBlocks().empty() &&
362 9908 : variable.activeOnSubdomains(_blk_mesh->interiorLowerDBlocks()))
363 3120 : return;
364 :
365 1155078 : if (!isBlockSubset(variable.activeSubdomains()))
366 : {
367 128 : std::string var_ids = Moose::stringify(variable.activeSubdomains(), ", ");
368 96 : std::string obj_ids = Moose::stringify(blockRestricted() ? _blk_ids : meshBlockIDs(), ", ");
369 32 : mooseError("The 'block' parameter of the object '",
370 32 : _blk_name,
371 : "' must be a subset of the 'block' parameter of the variable '",
372 32 : variable.name(),
373 : "':\n Object '",
374 32 : _blk_name,
375 : "': ",
376 : obj_ids,
377 : "\n Variable '",
378 32 : variable.name(),
379 : "': ",
380 : var_ids);
381 0 : }
382 : }
383 :
384 : unsigned int
385 0 : BlockRestrictable::blocksMaxDimension() const
386 : {
387 : mooseAssert(_blk_dim != libMesh::invalid_uint, "Block restriction not initialized");
388 0 : return _blk_dim;
389 : }
|