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