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 3331972 : BlockRestrictable::validParams()
22 : {
23 : // Create InputParameters object that will be appended to the parameters for the inheriting object
24 3331972 : InputParameters params = emptyInputParameters();
25 :
26 : // Add the user-facing 'block' input parameter
27 9995916 : 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 3331972 : if (!params.have_parameter<bool>("_dual_restrictable"))
33 9995916 : params.addPrivateParam<bool>("_dual_restrictable", false);
34 :
35 : // Return the parameters
36 3331972 : return params;
37 0 : }
38 :
39 : // Standard constructor
40 471696 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object, bool initialize /*=true*/)
41 943392 : : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
42 943392 : _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
43 1415088 : ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
44 : : NULL),
45 943392 : _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
46 : : NULL),
47 471696 : _boundary_ids(_empty_boundary_ids),
48 1886784 : _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
49 471696 : _blk_name(moose_object->name()),
50 471696 : _blk_dim(libMesh::invalid_uint),
51 1305576 : _moose_object(moose_object)
52 : {
53 471696 : if (initialize)
54 471696 : initializeBlockRestrictable(_moose_object);
55 471693 : }
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 471696 : BlockRestrictable::initializeBlockRestrictable(const MooseObject * moose_object)
77 : {
78 : // If the mesh pointer is not defined, but FEProblemBase is, get it from there
79 471696 : if (_blk_feproblem != NULL && _blk_mesh == NULL)
80 471696 : _blk_mesh = &_blk_feproblem->mesh();
81 :
82 : // Check that the mesh pointer was defined, it is required for this class to operate
83 471696 : 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 471696 : if (_blk_feproblem != NULL)
89 : {
90 : #ifdef MOOSE_KOKKOS_ENABLED
91 362184 : if (_moose_object->isKokkosObject())
92 7872 : _blk_material_data = &_blk_feproblem->getKokkosMaterialData(Moose::BLOCK_MATERIAL_DATA);
93 : else
94 : #endif
95 463824 : _blk_material_data = &_blk_feproblem->getMaterialData(Moose::BLOCK_MATERIAL_DATA, _blk_tid);
96 : }
97 :
98 : // The 'block' input is defined
99 1415088 : if (moose_object->isParamValid("block"))
100 : {
101 : // Extract the blocks from the input
102 144726 : _blocks = moose_object->getParam<std::vector<SubdomainName>>("block");
103 :
104 : // Store the IDs in a set, handling ANY_BLOCK_ID if supplied
105 72363 : if (std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end())
106 4275 : _blk_ids.insert(Moose::ANY_BLOCK_ID);
107 : else
108 : {
109 : // Get the IDs from the supplied names
110 68088 : _vec_ids = _blk_mesh->getSubdomainIDs(_blocks);
111 68088 : _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 1197999 : else if (moose_object->isParamValid("variable"))
117 : {
118 389692 : std::string variable_name = moose_object->parameters().getMooseType("variable");
119 194846 : if (!variable_name.empty())
120 167811 : _blk_ids = _blk_feproblem
121 335622 : ->getVariable(_blk_tid,
122 : variable_name,
123 : Moose::VarKindType::VAR_ANY,
124 : Moose::VarFieldType::VAR_FIELD_ANY)
125 167811 : .activeSubdomains();
126 194846 : }
127 :
128 : // Produce error if the object is not allowed to be both block and boundary restricted
129 471696 : 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 1260846 : if (_blk_ids.empty() && !moose_object->isParamValid("boundary"))
138 : {
139 379285 : _blk_ids.insert(Moose::ANY_BLOCK_ID);
140 758570 : _blocks = {"ANY_BLOCK_ID"};
141 : }
142 :
143 : // If this object is block restricted, check that defined blocks exist on the mesh
144 471696 : if (_blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end())
145 : {
146 88136 : const std::set<SubdomainID> & valid_ids = _blk_mesh->meshSubdomains();
147 88136 : std::vector<SubdomainID> diff;
148 :
149 88136 : 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 88136 : if (!diff.empty())
156 : {
157 3 : std::ostringstream msg;
158 3 : auto sep = " ";
159 3 : msg << "the following blocks (ids) do not exist on the mesh:";
160 6 : for (const auto & id : diff)
161 : {
162 3 : if (_blk_name.size() > 0)
163 : {
164 : auto & name =
165 3 : _blocks.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) - _vec_ids.begin());
166 3 : if (std::to_string(id) != name)
167 0 : msg << sep << name << " (" << id << ")";
168 : else
169 3 : msg << sep << id;
170 : }
171 : else
172 0 : msg << sep << id;
173 3 : sep = ", ";
174 : }
175 3 : std::vector<SubdomainID> valid_ids_vec(valid_ids.begin(), valid_ids.end());
176 3 : auto valid_names = _blk_mesh->getSubdomainNames(valid_ids_vec);
177 12 : msg << "\nBlocks names (resp. ids) that do exist: " << Moose::stringify(valid_names) << " ("
178 18 : << Moose::stringify(valid_ids) << ")";
179 6 : moose_object->paramError("block", msg.str());
180 0 : }
181 88133 : }
182 :
183 : // Get the mesh dimension for the blocks
184 471693 : if (blockRestricted())
185 88133 : _blk_dim = _blk_mesh->getBlocksMaxDimension(_blocks);
186 : else
187 383560 : _blk_dim = _blk_mesh->dimension();
188 :
189 : #ifdef MOOSE_KOKKOS_ENABLED
190 362182 : if (moose_object->isKokkosObject())
191 7872 : _blk_feproblem->addKokkosMeshInitializationHook(
192 15744 : std::bind(&BlockRestrictable::initializeKokkosBlockRestrictable, this));
193 : #endif
194 850978 : }
195 :
196 : bool
197 1654892 : BlockRestrictable::blockRestricted() const
198 : {
199 1654892 : return _blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end();
200 : }
201 :
202 : const std::vector<SubdomainName> &
203 27814 : BlockRestrictable::blocks() const
204 : {
205 27814 : return _blocks;
206 : }
207 :
208 : const std::set<SubdomainID> &
209 6841494 : BlockRestrictable::blockIDs() const
210 : {
211 6841494 : if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
212 5492192 : return _blk_mesh->meshSubdomains();
213 : else
214 1349302 : return _blk_ids;
215 : }
216 :
217 : unsigned int
218 24 : BlockRestrictable::numBlocks() const
219 : {
220 24 : return (unsigned int)_blk_ids.size();
221 : }
222 :
223 : bool
224 6 : BlockRestrictable::hasBlocks(const SubdomainName & name) const
225 : {
226 : // Create a vector and utilize the getSubdomainIDs function, which
227 : // handles the ANY_BLOCK_ID (getSubdomainID does not)
228 6 : std::vector<SubdomainName> names(1);
229 6 : names[0] = name;
230 12 : return hasBlocks(_blk_mesh->getSubdomainIDs(names));
231 6 : }
232 :
233 : bool
234 6 : BlockRestrictable::hasBlocks(const std::vector<SubdomainName> & names) const
235 : {
236 6 : return hasBlocks(_blk_mesh->getSubdomainIDs(names));
237 : }
238 :
239 : bool
240 0 : BlockRestrictable::hasBlocks(const std::set<SubdomainName> & names) const
241 : {
242 0 : return hasBlocks(_blk_mesh->getSubdomainIDs(names));
243 : }
244 :
245 : bool
246 853836636 : BlockRestrictable::hasBlocks(const SubdomainID id) const
247 : {
248 853836636 : if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
249 785502701 : return true;
250 : else
251 68333935 : return _blk_ids.find(id) != _blk_ids.end();
252 : }
253 :
254 : bool
255 18 : BlockRestrictable::hasBlocks(const std::vector<SubdomainID> & ids) const
256 : {
257 18 : std::set<SubdomainID> ids_set(ids.begin(), ids.end());
258 36 : return hasBlocks(ids_set);
259 18 : }
260 :
261 : bool
262 2076 : BlockRestrictable::hasBlocks(const std::set<SubdomainID> & ids) const
263 : {
264 2076 : if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
265 933 : return true;
266 : else
267 1143 : return std::includes(_blk_ids.begin(), _blk_ids.end(), ids.begin(), ids.end());
268 : }
269 :
270 : bool
271 844394 : BlockRestrictable::isBlockSubset(const std::set<SubdomainID> & ids) const
272 : {
273 : // An empty input is assumed to be ANY_BLOCK_ID
274 844394 : if (ids.empty() || ids.find(Moose::ANY_BLOCK_ID) != ids.end())
275 806053 : return true;
276 :
277 38341 : if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
278 1287 : return std::includes(ids.begin(),
279 : ids.end(),
280 1287 : _blk_mesh->meshSubdomains().begin(),
281 2574 : _blk_mesh->meshSubdomains().end());
282 : else
283 37054 : return std::includes(ids.begin(), ids.end(), _blk_ids.begin(), _blk_ids.end());
284 : }
285 :
286 : bool
287 0 : BlockRestrictable::isBlockSubset(const std::vector<SubdomainID> & ids) const
288 : {
289 0 : std::set<SubdomainID> ids_set(ids.begin(), ids.end());
290 0 : return isBlockSubset(ids_set);
291 0 : }
292 :
293 : const std::set<SubdomainID> &
294 442428 : BlockRestrictable::meshBlockIDs() const
295 : {
296 442428 : return _blk_mesh->meshSubdomains();
297 : }
298 :
299 : bool
300 14651 : BlockRestrictable::hasBlockMaterialPropertyHelper(const std::string & prop_name)
301 : {
302 :
303 : // Reference to MaterialWarehouse for testing and retrieving block ids
304 14651 : const MaterialWarehouse & warehouse = _blk_feproblem->getMaterialWarehouse();
305 :
306 : // Complete set of ids that this object is active
307 14651 : const std::set<SubdomainID> & ids = blockRestricted() ? blockIDs() : meshBlockIDs();
308 :
309 : // Loop over each id for this object
310 15467 : for (const auto & id : ids)
311 : {
312 : // Storage of material properties that have been DECLARED on this id
313 14721 : std::set<std::string> declared_props;
314 :
315 : // If block materials exist, populated the set of properties that were declared
316 14721 : if (warehouse.hasActiveBlockObjects(id))
317 : {
318 14060 : const std::vector<std::shared_ptr<MaterialBase>> & mats = warehouse.getActiveBlockObjects(id);
319 113411 : for (const auto & mat : mats)
320 : {
321 99351 : const std::set<std::string> & mat_props = mat->getSuppliedItems();
322 99351 : declared_props.insert(mat_props.begin(), mat_props.end());
323 : }
324 : }
325 :
326 : // If the supplied property is not in the list of properties on the current id, return false
327 14721 : if (declared_props.find(prop_name) == declared_props.end())
328 13905 : return false;
329 14721 : }
330 :
331 : // If you get here the supplied property is defined on all blocks
332 746 : return true;
333 : }
334 :
335 : Moose::CoordinateSystemType
336 0 : BlockRestrictable::getBlockCoordSystem()
337 : {
338 0 : if (!_blk_mesh)
339 0 : mooseError("No mesh available in BlockRestrictable::checkCoordSystem()");
340 0 : if (!_blk_feproblem)
341 0 : mooseError("No problem available in BlockRestrictable::checkCoordSystem()");
342 :
343 0 : const auto & subdomains = blockRestricted() ? blockIDs() : meshBlockIDs();
344 :
345 0 : if (subdomains.empty())
346 0 : mooseError("No subdomains found in the problem.");
347 :
348 : // make sure all subdomains are using the same coordinate system
349 0 : auto coord_system = _blk_feproblem->getCoordSystem(*subdomains.begin());
350 0 : for (auto subdomain : subdomains)
351 0 : if (_blk_feproblem->getCoordSystem(subdomain) != coord_system)
352 0 : mooseError("This object requires all subdomains to have the same coordinate system.");
353 :
354 0 : return coord_system;
355 : }
356 :
357 : void
358 844308 : BlockRestrictable::checkVariable(const MooseVariableFieldBase & variable) const
359 : {
360 : // a variable defined on all internal sides does not need this check because
361 : // it can be coupled with other variables in DG kernels
362 849892 : if (!_blk_mesh->interiorLowerDBlocks().empty() &&
363 5584 : variable.activeOnSubdomains(_blk_mesh->interiorLowerDBlocks()))
364 1152 : return;
365 :
366 843156 : if (!isBlockSubset(variable.activeSubdomains()))
367 : {
368 96 : std::string var_ids = Moose::stringify(variable.activeSubdomains(), ", ");
369 72 : std::string obj_ids = Moose::stringify(blockRestricted() ? _blk_ids : meshBlockIDs(), ", ");
370 24 : mooseError("The 'block' parameter of the object '",
371 24 : _blk_name,
372 : "' must be a subset of the 'block' parameter of the variable '",
373 24 : variable.name(),
374 : "':\n Object '",
375 24 : _blk_name,
376 : "': ",
377 : obj_ids,
378 : "\n Variable '",
379 24 : variable.name(),
380 : "': ",
381 : var_ids);
382 0 : }
383 : }
384 :
385 : unsigned int
386 0 : BlockRestrictable::blocksMaxDimension() const
387 : {
388 : mooseAssert(_blk_dim != libMesh::invalid_uint, "Block restriction not initialized");
389 0 : return _blk_dim;
390 : }
|