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