https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PhysicsBase.C
Go to the documentation of this file.
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#include "PhysicsBase.h"
11#include "MooseUtils.h"
12#include "FEProblemBase.h"
13
14#include "NonlinearSystemBase.h"
15#include "AuxiliarySystem.h"
16#include "BlockRestrictable.h"
17#include "ActionComponent.h"
20#include "MooseVariableScalar.h"
21#include "LinearSystem.h"
22
25{
27 params.addClassDescription("Creates all the objects necessary to solve a particular physics");
28
29 params.addParam<std::vector<SubdomainName>>(
30 "block", {}, "Blocks (subdomains) that this Physics is active on.");
31
32 MooseEnum transient_options("true false same_as_problem", "same_as_problem");
33 params.addParam<MooseEnum>(
34 "transient", transient_options, "Whether the physics is to be solved as a transient");
35
36 params.addParam<bool>("verbose", false, "Flag to facilitate debugging a Physics");
37
38 // Numerical solve parameters
39 params.addParam<std::vector<SolverSystemName>>(
40 "system_names",
41 {"nl0"},
42 "Name of the solver system(s) for the variables. If a single name is specified, "
43 "that system is used for all solver variables.");
44 MooseEnum pc_options("default defer", "defer");
45 params.addParam<MooseEnum>("preconditioning",
46 pc_options,
47 "Which preconditioning to use/add for this Physics, or whether to "
48 "defer to the Preconditioning block, or another Physics");
49
50 // Restart parameters
51 params.addParam<bool>("initialize_variables_from_mesh_file",
52 false,
53 "Determines if the variables that are added by the action are initialized"
54 "from the mesh file (only for Exodus format)");
55 params.addParam<std::string>(
56 "initial_from_file_timestep",
57 "LATEST",
58 "Gives the time step number (or \"LATEST\") for which to read the Exodus solution");
59 params.addParamNamesToGroup("initialize_variables_from_mesh_file initial_from_file_timestep",
60 "Restart from Exodus");
61
62 // Options to turn off tasks
63 params.addParam<bool>("dont_create_solver_variables",
64 false,
65 "Whether to skip the 'add_variable'/'add_variables_physics' task(s)");
66 params.addParam<bool>(
67 "dont_create_ics", false, "Whether to skip the 'add_ic'/'add_fv_ic/add_ics_physics' task(s)");
68 params.addParam<bool>(
69 "dont_create_kernels", false, "Whether to skip the 'add_kernel' task for each kernel type");
70 params.addParam<bool>("dont_create_bcs",
71 false,
72 "Whether to skip the 'add_bc' task for each boundary condition type");
73 params.addParam<bool>("dont_create_functions", false, "Whether to skip the 'add_function' task");
74 params.addParam<bool>(
75 "dont_create_aux_variables", false, "Whether to skip the 'add_aux_variable' task");
76 params.addParam<bool>(
77 "dont_create_aux_kernels", false, "Whether to skip the 'add_aux_kernel' task");
78 params.addParam<bool>(
79 "dont_create_materials",
80 false,
81 "Whether to skip the 'add_material'/'add_materials_physics' task(s) for each material type");
82 params.addParam<bool>(
83 "dont_create_user_objects",
84 false,
85 "Whether to skip the 'add_user_object' task. This does not apply to UserObject derived "
86 "classes being created on a different task (for example: postprocessors, VPPs, correctors)");
87 params.addParam<bool>(
88 "dont_create_correctors", false, "Whether to skip the 'add_correctors' task");
89 params.addParam<bool>(
90 "dont_create_postprocessors", false, "Whether to skip the 'add_postprocessors' task");
91 params.addParam<bool>("dont_create_vectorpostprocessors",
92 false,
93 "Whether to skip the 'add_vectorpostprocessors' task");
95 "dont_create_solver_variables dont_create_ics dont_create_kernels dont_create_bcs "
96 "dont_create_functions dont_create_aux_variables dont_create_aux_kernels "
97 "dont_create_materials dont_create_user_objects dont_create_correctors "
98 "dont_create_postprocessors dont_create_vectorpostprocessors",
99 "Reduce Physics object creation");
100
101 params.addParamNamesToGroup("active inactive", "Advanced");
102 params.addParamNamesToGroup("preconditioning system_names", "Numerical scheme");
103 return params;
104}
105
107 : Action(parameters),
109 _system_names(getParam<std::vector<SolverSystemName>>("system_names")),
110 _verbose(getParam<bool>("verbose")),
111 _preconditioning(getParam<MooseEnum>("preconditioning")),
112 _blocks(getParam<std::vector<SubdomainName>>("block")),
113 _is_transient(getParam<MooseEnum>("transient"))
114{
115 checkSecondParamSetOnlyIfFirstOneTrue("initialize_variables_from_mesh_file",
116 "initial_from_file_timestep");
118 addRequiredPhysicsTask("init_physics");
119 addRequiredPhysicsTask("copy_vars_physics");
120 addRequiredPhysicsTask("check_integrity_early_physics");
121}
122
123void
125{
126 mooseDoOnce(checkRequiredTasks());
127
128 // Lets a derived Physics class implement additional tasks
130
131 // Initialization and variables
132 if (_current_task == "init_physics")
134 else if ((_current_task == "add_variable" || _current_task == "add_variables_physics") &&
135 !getParam<bool>("dont_create_solver_variables"))
137 else if ((_current_task == "add_ic" || _current_task == "add_fv_ic" ||
138 _current_task == "add_ics_physics") &&
139 !getParam<bool>("dont_create_ics"))
141
142 // Kernels
143 else if (_current_task == "add_interpolation_method_physics" &&
144 !getParam<bool>("dont_create_kernels"))
146 else if (_current_task == "add_kernel" && !getParam<bool>("dont_create_kernels"))
147 addFEKernels();
148 else if (_current_task == "add_nodal_kernel" && !getParam<bool>("dont_create_kernels"))
150 else if ((_current_task == "add_fv_kernel" || _current_task == "add_linear_fv_kernel") &&
151 !getParam<bool>("dont_create_kernels"))
152 addFVKernels();
153 else if (_current_task == "add_dirac_kernel" && !getParam<bool>("dont_create_kernels"))
155 else if (_current_task == "add_dg_kernel" && !getParam<bool>("dont_create_kernels"))
156 addDGKernels();
157 else if (_current_task == "add_scalar_kernel" && !getParam<bool>("dont_create_kernels"))
159 else if (_current_task == "add_interface_kernel" && !getParam<bool>("dont_create_kernels"))
161 else if (_current_task == "add_fv_ik" && !getParam<bool>("dont_create_kernels"))
163
164 // Boundary conditions
165 else if (_current_task == "add_bc" && !getParam<bool>("dont_create_bcs"))
166 addFEBCs();
167 else if (_current_task == "add_nodal_bc" && !getParam<bool>("dont_create_bcs"))
168 addNodalBCs();
169 else if ((_current_task == "add_fv_bc" || _current_task == "add_linear_fv_bc") &&
170 !getParam<bool>("dont_create_bcs"))
171 addFVBCs();
172 else if (_current_task == "add_periodic_bc" && !getParam<bool>("dont_create_bcs"))
174
175 // Auxiliary quantities
176 else if (_current_task == "add_function" && !getParam<bool>("dont_create_functions"))
177 addFunctions();
178 else if (_current_task == "add_aux_variable" && !getParam<bool>("dont_create_aux_variables"))
180 else if (_current_task == "add_aux_kernel" && !getParam<bool>("dont_create_aux_kernels"))
182 else if ((_current_task == "add_material" || _current_task == "add_materials_physics") &&
183 !getParam<bool>("dont_create_materials"))
184 addMaterials();
185 else if (_current_task == "add_functor_material" && !getParam<bool>("dont_create_materials"))
187
188 // Multiapp
189 else if (_current_task == "add_multi_app")
190 addMultiApps();
191 else if (_current_task == "add_transfer")
192 addTransfers();
193
194 // User objects and output
195 else if (_current_task == "add_user_object" && !getParam<bool>("dont_create_user_objects"))
197 else if (_current_task == "add_corrector" && !getParam<bool>("dont_create_correctors"))
199 else if (_current_task == "add_postprocessor" && !getParam<bool>("dont_create_postprocessors"))
201 else if (_current_task == "add_vector_postprocessor" &&
202 !getParam<bool>("dont_create_vectorpostprocessors"))
204 else if (_current_task == "add_reporter")
205 addReporters();
206 else if (_current_task == "add_output")
207 addOutputs();
208
209 // Equation solver-related tasks
210 else if (_current_task == "add_preconditioning")
212 else if (_current_task == "add_executioner")
214 else if (_current_task == "add_executor")
215 addExecutors();
216
217 // Checks
218 else if (_current_task == "check_integrity_early_physics")
220 else if (_current_task == "check_integrity")
222
223 // Exodus restart capabilities
224 if (_current_task == "copy_vars_physics")
225 {
227 if (_aux_var_names.size() > 0)
229 }
230}
231
232void
233PhysicsBase::addUserObject(const std::string & uo_type,
234 const std::string & uo_name,
235 InputParameters & params)
236{
237 mooseAssert(
238 [&]()
239 {
240 const auto supplied = getSuppliedUserObjects();
241 return std::find(supplied.begin(), supplied.end(), uo_name) != supplied.end();
242 }(),
243 "The UserObject '" + uo_name + "' added by Physics '" + name() +
244 "' was not declared in getSuppliedUserObjects(). Declare it there so its construction "
245 "order can be resolved.");
246 getProblem().addUserObject(uo_type, uo_name, params);
247}
248
249void
251{
252 if (getParam<bool>("initialize_variables_from_mesh_file"))
254
255 checkSecondParamSetOnlyIfFirstOneTrue("initialize_variables_from_mesh_file",
256 "initial_from_file_timestep");
257}
258
259bool
261{
262 mooseAssert(_problem, "We don't have a problem yet");
263 if (_is_transient == "true")
264 return true;
265 else if (_is_transient == "false")
266 return false;
267 else
268 return getProblem().isTransient();
269}
270
271unsigned int
273{
274 mooseAssert(_mesh, "We dont have a mesh yet");
275 mooseAssert(_dim < 4, "Dimension has not been set yet");
276 return _dim;
277}
278
279std::set<SubdomainID>
280PhysicsBase::getSubdomainIDs(const std::set<SubdomainName> & blocks) const
281{
282 const bool not_block_restricted =
283 (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end()) ||
285 mooseAssert(_mesh, "Should have a mesh");
286 // use a set for simplicity. Note that subdomain names are unique, except maybe the empty one,
287 // which cannot be specified by the user to the Physics.
288 // MooseMesh::getSubdomainIDs cannot deal with the 'ANY_BLOCK_ID' name
289 std::set<SubdomainID> block_ids_set =
290 not_block_restricted ? _mesh->meshSubdomains() : _mesh->getSubdomainIDs(blocks);
291 return block_ids_set;
292}
293
294std::vector<std::string>
295PhysicsBase::getSubdomainNamesAndIDs(const std::set<SubdomainID> & blocks) const
296{
297 mooseAssert(_mesh, "Should have a mesh");
298 std::vector<std::string> sub_names_ids;
299 sub_names_ids.reserve(blocks.size());
300 for (const auto bid : blocks)
301 {
302 const auto bname = _mesh->getSubdomainName(bid);
303 sub_names_ids.push_back((bname.empty() ? "(unnamed)" : bname) + " (" + std::to_string(bid) +
304 ")");
305 }
306 return sub_names_ids;
307}
308
309void
310PhysicsBase::addBlocks(const std::vector<SubdomainName> & blocks)
311{
312 if (blocks.size())
313 {
314 _blocks.insert(_blocks.end(), blocks.begin(), blocks.end());
315 _dim = _mesh->getBlocksMaxDimension(_blocks);
316 }
317}
318
319void
320PhysicsBase::addBlocksById(const std::vector<SubdomainID> & block_ids)
321{
322 if (block_ids.size())
323 {
324 for (const auto bid : block_ids)
325 _blocks.push_back(_mesh->getSubdomainName(bid));
326 _dim = _mesh->getBlocksMaxDimension(_blocks);
327 }
328}
329
330void
332{
333 for (const auto & block : component.blocks())
334 _blocks.push_back(block);
335}
336
337void
343
344const ActionComponent &
345PhysicsBase::getActionComponent(const ComponentName & comp_name) const
346{
347 return _awh.getAction<ActionComponent>(comp_name);
348}
349
350void
352{
353 // Annoying edge case. We cannot use ANY_BLOCK_ID for kernels and variables since errors got
354 // added downstream for using it, we cannot leave it empty as that sets all objects to not live
355 // on any block
356 if (isParamSetByUser("block") && _blocks.empty())
357 paramError("block",
358 "Empty block restriction is not supported. Comment out the Physics if you are "
359 "trying to disable it.");
360
361 // Components should have added their blocks already.
362 if (_blocks.empty())
363 _blocks.push_back("ANY_BLOCK_ID");
364
365 mooseAssert(_mesh, "We should have a mesh to find the dimension");
366 if (_blocks.size())
367 _dim = _mesh->getBlocksMaxDimension(_blocks);
368 else
369 _dim = _mesh->dimension();
370
371 // Forward physics verbosity to problem to output the setup
372 if (_verbose)
374
375 // If the derived physics need additional initialization very early on
377
378 // Check that the systems exist in the Problem
379 // TODO: try to add the systems to the problem from here instead
380 // NOTE: this must be performed after the "Additional" initialization because the list
381 // of systems might have been adjusted once the dimension of the Physics is known
382 const auto & problem_nl_systems = getProblem().getNonlinearSystemNames();
383 const auto & problem_lin_systems = getProblem().getLinearSystemNames();
384 for (const auto & sys_name : _system_names)
385 if (std::find(problem_nl_systems.begin(), problem_nl_systems.end(), sys_name) ==
386 problem_nl_systems.end() &&
387 std::find(problem_lin_systems.begin(), problem_lin_systems.end(), sys_name) ==
388 problem_lin_systems.end() &&
389 solverVariableNames().size())
390 mooseError("System '", sys_name, "' is not found in the Problem");
391
392 // Cache system number as it makes some logic easier
393 for (const auto & sys_name : _system_names)
394 _system_numbers.push_back(getProblem().solverSysNum(sys_name));
395}
396
397void
399{
400 if (_is_transient == "true" && !getProblem().isTransient())
401 paramError("transient", "We cannot solve a physics as transient in a steady problem");
402
403 // Check that there is a system for each variable
404 if (_system_names.size() != 1 && _system_names.size() != _solver_var_names.size())
405 paramError("system_names",
406 "There should be one system name per solver variable (potentially repeated), or a "
407 "single system name for all variables. Currently you have '" +
408 std::to_string(_system_names.size()) + "' systems specified for '" +
409 std::to_string(_solver_var_names.size()) + "' solver variables.");
410
411 // Check that each variable is present in the expected system
412 unsigned int var_i = 0;
413 for (const auto & var_name : _solver_var_names)
414 {
415 const auto & sys_name = _system_names.size() == 1 ? _system_names[0] : _system_names[var_i++];
416 if (!_problem->getSolverSystem(_problem->solverSysNum(sys_name)).hasVariable(var_name) &&
417 !_problem->getSolverSystem(_problem->solverSysNum(sys_name)).hasScalarVariable(var_name))
418 paramError("system_names",
419 "We expected system '" + sys_name + "' to contain variable '" + var_name +
420 "' but it did not. Make sure the system names closely match the ordering of "
421 "the variables in the Physics.");
422 }
423}
424
425void
426PhysicsBase::copyVariablesFromMesh(const std::vector<VariableName> & variables_to_copy,
427 bool are_solver_var)
428{
429 if (getParam<bool>("initialize_variables_from_mesh_file"))
430 {
431 mooseInfoRepeated("Adding Exodus restart for " + std::to_string(variables_to_copy.size()) +
432 " variables: " + Moose::stringify(variables_to_copy));
433 // TODO Check that the variable types and orders are actually supported for exodus restart
434 for (const auto i : index_range(variables_to_copy))
435 {
436 SystemBase & system = are_solver_var ? getProblem().getSystemBase(_system_numbers.size() == 1
437 ? _system_numbers[0]
438 : _system_numbers[i])
440 const auto & var_name = variables_to_copy[i];
441 system.addVariableToCopy(
442 var_name, var_name, getParam<std::string>("initial_from_file_timestep"));
443 }
444 }
445}
446
447bool
448PhysicsBase::variableExists(const VariableName & var_name, bool error_if_aux) const
449{
450 if (error_if_aux && _problem->getAuxiliarySystem().hasVariable(var_name))
451 mooseError("Variable '",
452 var_name,
453 "' is supposed to be nonlinear for physics '",
454 name(),
455 "' but it is already defined as auxiliary");
456 else
457 return _problem->hasVariable(var_name);
458}
459
460bool
461PhysicsBase::solverVariableExists(const VariableName & var_name) const
462{
463 return _problem->hasSolverVariable(var_name);
464}
465
466const SolverSystemName &
467PhysicsBase::getSolverSystem(unsigned int variable_index) const
468{
469 mooseAssert(!_system_names.empty(), "We should have a solver system name");
470 if (_system_names.size() == 1)
471 return _system_names[0];
472 else
473 // We trust that the system names and the variable names match one-to-one as it is enforced by
474 // the checkIntegrityEarly() routine.
475 return _system_names[variable_index];
476}
477
478const SolverSystemName &
479PhysicsBase::getSolverSystem(const VariableName & var_name) const
480{
481 mooseAssert(!_system_names.empty(), "We should have a solver system name");
482 // No need to look if only one system for the Physics
483 if (_system_names.size() == 1)
484 return _system_names[0];
485
486 // We trust that the system names and the variable names match one-to-one as it is enforced by
487 // the checkIntegrityEarly() routine.
488 for (const auto variable_index : index_range(_solver_var_names))
489 if (var_name == _solver_var_names[variable_index])
490 return _system_names[variable_index];
491 mooseError("Variable '", var_name, "' was not found within the Physics solver variables.");
492}
493
494void
496{
497 const auto registered_tasks = _action_factory.getTasksByAction(type());
498
499 // Check for missing tasks
500 for (const auto & required_task : _required_tasks)
501 if (!registered_tasks.count(required_task))
502 mooseWarning("Task '" + required_task +
503 "' has been declared as required by a Physics parent class of derived class '" +
504 type() +
505 "' but this task is not registered to the derived class. Registered tasks for "
506 "this Physics are: " +
507 Moose::stringify(registered_tasks));
508}
509
510void
511PhysicsBase::assignBlocks(InputParameters & params, const std::vector<SubdomainName> & blocks) const
512{
513 // We only set the blocks if we don't have `ANY_BLOCK_ID` defined because the subproblem
514 // (through the mesh) errors out if we use this keyword during the addVariable/Kernel
515 // functions
516 if (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") == blocks.end())
517 params.set<std::vector<SubdomainName>>("block") = blocks;
518 if (blocks.empty())
519 mooseInfoRepeated("Empty block restriction assigned to an object created by Physics '" +
520 name() + "'.\n Did you mean to do this?");
521}
522
523bool
524PhysicsBase::checkBlockRestrictionIdentical(const std::string & object_name,
525 const std::vector<SubdomainName> & blocks,
526 bool error_if_not_identical) const
527{
528 // If identical, we can return fast
529 if (_blocks == blocks)
530 return true;
531 // If one is block restricted to anywhere and the other is block restricted to anywhere manually
532 if ((std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end() &&
534 (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end() &&
536 return true;
537
538 // Copy, sort and unique is the only way to check that they are actually the same
539 auto copy_blocks = _blocks;
540 auto copy_blocks_other = blocks;
541 std::sort(copy_blocks.begin(), copy_blocks.end());
542 copy_blocks.erase(unique(copy_blocks.begin(), copy_blocks.end()), copy_blocks.end());
543 std::sort(copy_blocks_other.begin(), copy_blocks_other.end());
544 copy_blocks_other.erase(unique(copy_blocks_other.begin(), copy_blocks_other.end()),
545 copy_blocks_other.end());
546
547 if (copy_blocks == copy_blocks_other)
548 return true;
549 std::vector<SubdomainName> diff;
550 std::set_difference(copy_blocks.begin(),
551 copy_blocks.end(),
552 copy_blocks_other.begin(),
553 copy_blocks_other.end(),
554 std::inserter(diff, diff.begin()));
555 if (error_if_not_identical)
556 mooseError("Physics '",
557 name(),
558 "' and object '",
559 object_name,
560 "' have different block restrictions.\nPhysics: ",
562 "\nObject: ",
564 "\nDifference: ",
565 Moose::stringify(diff));
566 else
567 return false;
568}
569
570bool
571PhysicsBase::hasBlocks(const std::vector<SubdomainName> & blocks) const
572{
573 mooseAssert(_blocks.size(), "hasBlocks called before blocks were initialized");
574 return std::all_of(blocks.begin(),
575 blocks.end(),
576 [this](const SubdomainName & block)
577 { return std::find(_blocks.begin(), _blocks.end(), block) != _blocks.end(); });
578}
579
580bool
581PhysicsBase::allMeshBlocks(const std::vector<SubdomainName> & blocks) const
582{
583 mooseAssert(_mesh, "The mesh should exist already");
584 // Try to return faster without examining every single block
585 if (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end())
586 return true;
587 else if (blocks.size() != _mesh->meshSubdomains().size())
588 return false;
589
590 for (const auto mesh_block : _mesh->meshSubdomains())
591 {
592 const auto & subdomain_name = _mesh->getSubdomainName(mesh_block);
593 // Check subdomain name
594 if (!subdomain_name.empty() &&
595 std::find(blocks.begin(), blocks.end(), subdomain_name) == blocks.end())
596 return false;
597 // no subdomain name, check the IDs being used as names instead
598 else if (std::find(blocks.begin(), blocks.end(), std::to_string(mesh_block)) == blocks.end())
599 return false;
600 }
601 return true;
602}
603
604bool
605PhysicsBase::allMeshBlocks(const std::set<SubdomainName> & blocks) const
606{
607 std::vector<SubdomainName> blocks_vec(blocks.begin(), blocks.end());
608 return allMeshBlocks(blocks_vec);
609}
610
611void
613 const std::vector<std::pair<MooseEnumItem, std::string>> & petsc_pair_options)
614{
615 Moose::PetscSupport::PetscOptions & po = _problem->getPetscOptions();
616 for (const auto solver_sys_num : _system_numbers)
618 petsc_pair_options,
619 _problem->mesh().dimension(),
620 _problem->getSolverSystem(solver_sys_num).prefix(),
621 *this,
622 po);
623}
624
625bool
626PhysicsBase::isVariableFV(const VariableName & var_name) const
627{
628 const auto var = &_problem->getVariable(0, var_name);
629 return var->isFV();
630}
631
632bool
633PhysicsBase::isVariableScalar(const VariableName & var_name) const
634{
635 return _problem->hasScalarVariable(var_name);
636}
637
638bool
639PhysicsBase::shouldCreateVariable(const VariableName & var_name,
640 const std::vector<SubdomainName> & blocks,
641 const bool error_if_aux)
642{
643 if (!variableExists(var_name, error_if_aux))
644 return true;
645 // check block restriction
646 auto & var = _problem->getVariable(0, var_name);
647 const bool not_block_restricted =
648 (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end()) ||
650 if (!var.blockRestricted() || (!not_block_restricted && var.hasBlocks(blocks)))
651 return false;
652
653 // This is an edge case, which might warrant a warning
654 if (allMeshBlocks(var.blocks()) && not_block_restricted)
655 return false;
656 else
657 mooseError("Variable '" + var_name + "' already exists with subdomain restriction '" +
658 Moose::stringify(var.blocks()) + "' which does not include the subdomains '" +
659 Moose::stringify(blocks) + "', required for this Physics.");
660}
661
662bool
663PhysicsBase::shouldCreateIC(const VariableName & var_name,
664 const std::vector<SubdomainName> & blocks,
665 const bool ic_is_default_ic,
666 const bool error_if_already_defined) const
667{
668 // Handle recover
669 if (ic_is_default_ic && (_app.isRestarting() || _app.isRecovering()))
670 return false;
671 // do not set initial conditions if we are loading fields from the mesh file
672 if (getParam<bool>("initialize_variables_from_mesh_file"))
673 return false;
674 // Different type of ICs, not block restrictable
675 mooseAssert(!isVariableScalar(var_name), "shouldCreateIC not implemented for scalar variables");
676
677 // Process the desired block restriction into a set of subdomain IDs
678 std::set<SubdomainName> blocks_set(blocks.begin(), blocks.end());
679 const auto blocks_ids_set = getSubdomainIDs(blocks_set);
680
681 // Check whether there are any ICs for this variable already in the problem
682 std::set<SubdomainID> blocks_ids_covered;
683 bool has_all_blocks;
684 if (isVariableFV(var_name))
685 {
686 has_all_blocks = _problem->getFVInitialConditionWarehouse().hasObjectsForVariableAndBlocks(
687 var_name, blocks_ids_set, blocks_ids_covered, /*tid =*/0);
688 // FV variables can be initialized by non-FV ICs
689 std::set<SubdomainID> blocks_ids_covered_fe;
690 const bool has_all_blocks_from_feics =
691 _problem->getInitialConditionWarehouse().hasObjectsForVariableAndBlocks(
692 var_name, blocks_ids_set, blocks_ids_covered_fe, /*tid =*/0);
693 // Note we are missing the case with complete but split coverage
694 has_all_blocks = has_all_blocks || has_all_blocks_from_feics;
695 blocks_ids_covered.insert(blocks_ids_covered_fe.begin(), blocks_ids_covered_fe.end());
696 }
697 else
698 has_all_blocks = _problem->getInitialConditionWarehouse().hasObjectsForVariableAndBlocks(
699 var_name, blocks_ids_set, blocks_ids_covered, /*tid =*/0);
700
701 const bool has_some_blocks = !blocks_ids_covered.empty();
702 if (!has_some_blocks)
703 return true;
704
705 if (has_all_blocks)
706 {
707 if (error_if_already_defined)
708 mooseError("ICs for variable '" + var_name + "' have already been defined for blocks '" +
709 Moose::stringify(blocks) + "'.");
710 else
711 return false;
712 }
713
714 // Partial overlap between Physics is not implemented.
715 mooseError("There is a partial overlap between the subdomains covered by pre-existing initial "
716 "conditions (ICs), defined on blocks (ids): " +
717 Moose::stringify(getSubdomainNamesAndIDs(blocks_ids_covered)) +
718 "\n and a newly created IC for variable '" + var_name +
719 "', to be defined on blocks: " + Moose::stringify(blocks) +
720 ".\nWe should be creating the Physics' IC only for non-covered blocks. This is not "
721 "implemented at this time.");
722}
723
724bool
725PhysicsBase::shouldCreateTimeDerivative(const VariableName & var_name,
726 const std::vector<SubdomainName> & blocks,
727 const bool error_if_already_defined) const
728{
729 // Follow the transient setting of the Physics
730 if (!isTransient())
731 return false;
732
733 // Variable is either nonlinear (FV/FE), nodal nonlinear (field of ODEs), linear, or scalar.
734 // The warehouses hosting the time kernels are different for each of these types
735 // Different type of time derivatives, not block restrictable
736 mooseAssert(!isVariableScalar(var_name),
737 "shouldCreateTimeDerivative not implemented for scalar variables");
738 mooseAssert(!_problem->hasAuxiliaryVariable(var_name),
739 "Should not be called with auxiliary variables");
740
741 // Get solver system type
742 const auto var = &_problem->getVariable(0, var_name);
743 const auto var_id = var->number();
744 const auto sys_num = var->sys().number();
745 const auto time_vector_tag =
746 (sys_num < _problem->numNonlinearSystems())
747 ? var->sys().timeVectorTag()
748 // this is not quite correct. Many kernels can contribute to RHS time vector on paper
749 : dynamic_cast<LinearSystem *>(&var->sys())->rightHandSideTimeVectorTag();
750
751 // We just use the warehouse, it should cover every time derivative object type
752 bool all_blocks_covered = true;
753 std::set<SubdomainID> blocks_ids_covered;
754 // we examine subdomain by subdomain, because mutiple kernels could be covering every block in
755 // the 'blocks' parameter
756 for (const auto & block : blocks)
757 {
758 std::vector<MooseObject *> time_kernels;
759 if (block != "ANY_BLOCK_ID")
760 {
761 const auto bid = _mesh->getSubdomainID(block);
762 _problem->theWarehouse()
763 .query()
764 .template condition<AttribSysNum>(sys_num)
765 .template condition<AttribVar>(var_id)
766 .template condition<AttribSubdomains>(bid)
767 // we use the time tag as a proxy for time derivatives
768 .template condition<AttribVectorTags>(time_vector_tag)
769 .queryInto(time_kernels);
770 }
771 else
772 _problem->theWarehouse()
773 .query()
774 .template condition<AttribSysNum>(sys_num)
775 .template condition<AttribVar>(var_id)
776 // we use the time tag as a proxy for time derivatives
777 .template condition<AttribVectorTags>(time_vector_tag)
778 .queryInto(time_kernels);
779
780 if (time_kernels.size())
781 {
782 if (block == "ANY_BLOCK_ID")
783 {
784 for (const auto & time_kernel : time_kernels)
785 if (const auto blk = dynamic_cast<BlockRestrictable *>(time_kernel))
786 blocks_ids_covered.insert(blk->blockIDs().begin(), blk->blockIDs().end());
787 }
788 else
789 blocks_ids_covered.insert(_mesh->getSubdomainID(block));
790 }
791 else
792 all_blocks_covered = false;
793 }
794
795 // From the set of covered blocks, see if the blocks we needed are found
796 if (all_blocks_covered)
797 {
798 std::set<SubdomainName> blocks_set(blocks.begin(), blocks.end());
799 const auto blocks_ids = getSubdomainIDs(blocks_set);
800 if (blocks_ids != blocks_ids_covered)
801 all_blocks_covered = false;
802 }
803 const bool has_some_blocks = !blocks_ids_covered.empty();
804 if (!has_some_blocks)
805 return true;
806 if (all_blocks_covered)
807 {
808 if (error_if_already_defined)
809 mooseError("A time kernel for variable '" + var_name +
810 "' has already been defined on blocks '" + Moose::stringify(blocks) + "'.");
811 else
812 return false;
813 }
814
815 // Partial overlap between Physics is not implemented.
816 mooseError("There is a partial overlap between the subdomains covered by pre-existing time "
817 "derivative kernel(s), defined on blocks (ids): " +
818 Moose::stringify(getSubdomainNamesAndIDs(blocks_ids_covered)) +
819 "\nand a newly created time derivative kernel for variable " + var_name +
820 ", to be defined on blocks: " + Moose::stringify(blocks) +
821 ".\nWe should be creating the Physics' time derivative only for non-covered "
822 "blocks. This is not implemented at this time.");
823}
824
825void
826PhysicsBase::reportPotentiallyMissedParameters(const std::vector<std::string> & param_names,
827 const std::string & object_type,
828 const std::string & object_name) const
829{
830 std::vector<std::string> defaults_unused;
831 std::vector<std::string> user_values_unused;
832 for (const auto & param : param_names)
833 {
834 if (isParamSetByUser(param))
835 user_values_unused.push_back(param);
836 else if (isParamValid(param))
837 defaults_unused.push_back(param);
838 }
839 const std::string object_name_string =
840 object_name.empty() ? "" : ("and name '" + object_name + "' ");
841
842 if (defaults_unused.size() && _verbose)
843 mooseInfoRepeated("Defaults for parameters '" + Moose::stringify(defaults_unused) +
844 "' for object of type '" + object_type + "' " + object_name_string +
845 "were not used because the object was not created by this Physics.");
846 if (user_values_unused.size())
847 {
850 "User-specifed values for parameters '" + Moose::stringify(user_values_unused) +
851 "' for object of type '" + object_type + "' " + object_name_string +
852 "were not used because the corresponding object was not created by this Physics.");
853 else if (_app.unusedFlagIsError())
854 mooseError("User-specified values for parameters '" + Moose::stringify(user_values_unused) +
855 "' for object of type '" + object_type + "' " + object_name_string +
856 "were not used because the corresponding object was not created by this Physics.");
857 }
858}
void mooseInfoRepeated(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
Definition MooseError.h:409
char ** blocks
Base class for components that are defined using an action.
const std::vector< SubdomainName > & blocks() const
Returns the subdomains for the component mesh, if any.
std::set< std::string > getTasksByAction(const std::string &action) const
const T & getAction(const std::string &name) const
Retrieve an action with its name and the desired type.
Base class for actions.
Definition Action.h:38
std::shared_ptr< MooseMesh > & _mesh
Definition Action.h:174
static InputParameters validParams()
Definition Action.C:26
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
bool addRelationshipManagers(Moose::RelationshipManagerType when_type, const InputParameters &moose_object_pars)
Method to add a relationship manager for the objects being added to the system.
Definition Action.C:148
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
Definition Action.h:178
const std::string & _current_task
The current action (even though we have separate instances for each action)
Definition Action.h:172
ActionWarehouse & _awh
Reference to ActionWarehouse where we store object build by actions.
Definition Action.h:169
An interface that restricts an object to subdomains via the 'blocks' input parameter.
virtual std::vector< std::shared_ptr< UserObject > > addUserObject(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
virtual const SystemBase & systemBaseAuxiliary() const override
Return the auxiliary system object as a base class reference.
void setVerboseProblem(bool verbose)
Make the problem be verbose.
unsigned int solverSysNum(const SolverSystemName &solver_sys_name) const override
const std::vector< LinearSystemName > & getLinearSystemNames() const
const std::vector< NonlinearSystemName > & getNonlinearSystemNames() const
virtual bool isTransient() const override
virtual const SystemBase & getSystemBase(const unsigned int sys_num) const
Get constant reference to a system in this problem.
Utility class to help check parameters.
void checkSecondParamSetOnlyIfFirstOneTrue(const std::string &param1, const std::string &param2) const
Check that a parameter is set only if the first one is set to true.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
Linear system to be solved.
bool unusedFlagIsError() const
Returns whether the flag for unused parameters is set to throw an error.
Definition MooseApp.h:1120
void setExodusFileRestart(bool flag)
Set the flag to indicate whether or not we need to use a separate Exodus reader to read the mesh BEFO...
Definition MooseApp.h:430
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition MooseApp.C:1675
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition MooseApp.C:1669
bool unusedFlagIsWarning() const
Returns whether the flag for unused parameters is set to throw a warning only.
Definition MooseApp.h:1117
const std::string & type() const
Get the type of this class.
Definition MooseBase.h:93
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition MooseBase.h:205
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
A struct for storing the various types of petsc options and values.
ActionFactory & _action_factory
Builds Actions.
Base class to help creating an entire physics.
Definition PhysicsBase.h:31
bool solverVariableExists(const VariableName &var_name) const
Check whether a variable already exists and is a solver variable.
const std::vector< VariableName > & auxVariableNames() const
Return the list of aux variables in this physics.
unsigned int _dim
Dimension of the physics, which we expect for now to be the dimension of the mesh NOTE: this is not k...
virtual void addFVBCs()
virtual void addReporters()
virtual void addCorrectors()
void addPetscPairsToPetscOptions(const std::vector< std::pair< MooseEnumItem, std::string > > &petsc_pair_options)
Process the given petsc option pairs into the system solver settings.
static InputParameters validParams()
Definition PhysicsBase.C:24
virtual void checkIntegrity() const
Additional checks performed near the end of the setup phase.
virtual void addFunctions()
virtual void actOnAdditionalTasks()
Routine to add additional setup work on additional registered tasks to a Physics.
Definition PhysicsBase.h:49
virtual void addExecutors()
virtual void addFVInterpolationMethods()
virtual void addMultiApps()
std::set< std::string > _required_tasks
Manually keeps track of the tasks required by each physics as tasks cannot be inherited.
virtual void addExecutioner()
void addBlocksById(const std::vector< SubdomainID > &block_ids)
virtual FEProblemBase & getProblem()
Get the problem for this physics Useful to add objects to the simulation.
void addBlocks(const std::vector< SubdomainName > &blocks)
Add new blocks to the Physics.
std::vector< SolverSystemName > _system_names
System names for the system(s) owning the solver variables.
std::vector< VariableName > _solver_var_names
Vector of the solver variables (nonlinear and linear) in the Physics.
void addUserObject(const std::string &uo_type, const std::string &uo_name, InputParameters &params)
Add a UserObject supplied by this Physics to the problem.
std::vector< unsigned int > _system_numbers
System numbers for the system(s) owning the solver variables.
bool shouldCreateIC(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool ic_is_default_ic, const bool error_if_already_defined) const
Returns whether this Physics should create the variable.
bool checkBlockRestrictionIdentical(const std::string &object_name, const std::vector< SubdomainName > &blocks, const bool error_if_not_identical=true) const
Check if an external object has the same block restriction.
virtual void addTransfers()
virtual void addOutputs()
bool allMeshBlocks(const std::vector< SubdomainName > &blocks) const
Check if a vector contains all the mesh blocks.
virtual void addInitialConditions()
virtual void addFEBCs()
bool shouldCreateTimeDerivative(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_already_defined) const
Returns whether this Physics should create the variable.
virtual void addFVInterfaceKernels()
std::set< SubdomainID > getSubdomainIDs(const std::set< SubdomainName > &blocks) const
Get the set of subdomain ids for the incoming vector of subdomain names.
virtual void addAuxiliaryKernels()
virtual void addNodalKernels()
void initializePhysics()
Process some parameters that require the problem to be created. Executed on init_physics.
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
Set the blocks parameter to the input parameters of an object this Physics will create.
unsigned int dimension() const
Return the maximum dimension of the blocks the Physics is active on.
virtual void checkIntegrityEarly() const
Additional checks performed once the executioner / executor has been created.
void reportPotentiallyMissedParameters(const std::vector< std::string > &param_names, const std::string &object_type, const std::string &object_name="") const
When this is called, we are knowingly not using the value of these parameters.
const std::vector< VariableName > & solverVariableNames() const
Return the list of solver (nonlinear + linear) variables in this physics.
virtual void addScalarKernels()
void copyVariablesFromMesh(const std::vector< VariableName > &variables_to_copy, bool are_nonlinear=true)
Copy nonlinear or aux variables from the mesh file.
virtual void addComponent(const ActionComponent &component)
Most basic way of adding a component: simply adding the blocks to the block restriction of the Physic...
void prepareCopyVariablesFromMesh() const
Tell the app if we want to use Exodus restart.
std::vector< std::string > getSubdomainNamesAndIDs(const std::set< SubdomainID > &blocks) const
Get the vector of subdomain names and ids for the incoming set of subdomain IDs.
virtual void addPostprocessors()
virtual void addUserObjects()
virtual void addDiracKernels()
virtual void initializePhysicsAdditional()
Additional initialization work that should happen very early, as soon as the problem is created.
virtual void act() override final
Forwards from the action tasks to the implemented addXYZ() in the derived classes If you need more th...
bool variableExists(const VariableName &var_name, bool error_if_aux) const
Check whether a variable already exists.
virtual void addVectorPostprocessors()
virtual void addAuxiliaryVariables()
virtual void addPreconditioning()
MooseEnum _is_transient
Whether the physics is to be solved as a transient.
bool hasBlocks(const std::vector< SubdomainName > &blocks) const
Whether the Physics is defined on those blocks.
std::vector< VariableName > _aux_var_names
Vector of the aux variables in the Physics.
virtual std::vector< UserObjectName > getSuppliedUserObjects() const
Return the names of the UserObjects this Physics adds to the problem.
const SolverSystemName & getSolverSystem(unsigned int variable_index) const
Get the solver system for this variable index.
PhysicsBase(const InputParameters &parameters)
virtual void addFunctorMaterials()
bool shouldCreateVariable(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_aux)
Returns whether this Physics should create the variable.
const ActionComponent & getActionComponent(const ComponentName &comp_name) const
Get a component with the requested name.
virtual InputParameters getAdditionalRMParams() const
Provide additional parameters for the relationship managers.
Definition PhysicsBase.h:38
bool isVariableScalar(const VariableName &var_name) const
Whether the variable is a scalar variable (global single scalar, not a field)
virtual void addMaterials()
bool isVariableFV(const VariableName &var_name) const
Whether the variable is a finite volume variable.
virtual void addInterfaceKernels()
virtual void addFVKernels()
bool isTransient() const
Return whether the Physics is solved using a transient.
std::vector< SubdomainName > _blocks
Keep track of the subdomains the Physics is defined on.
const std::vector< SubdomainName > & blocks() const
Return the blocks this physics is defined on.
Definition PhysicsBase.h:60
virtual void addNodalBCs()
const bool _verbose
Whether to output additional information.
virtual void addFEKernels()
virtual void addRelationshipManagers(Moose::RelationshipManagerType input_rm_type) override
Method to add a relationship manager for the objects being added to the system.
virtual void addSolverVariables()
The default implementation of these routines will do nothing as we do not expect all Physics to be de...
void checkRequiredTasks() const
Check the list of required tasks for missing tasks.
virtual void addDGKernels()
void addRequiredPhysicsTask(const std::string &task)
Add a new required task for all physics deriving from this class NOTE: This does not register the tas...
virtual void addPeriodicBCs()
void mooseWarning(Args &&... args) const
Base class for a system (of equations)
Definition SystemBase.h:87
virtual void addVariableToCopy(const std::string &dest_name, const std::string &source_name, const std::string &timestep)
Add info about variable that will be copied.
void addPetscPairsToPetscOptions(const std::vector< std::pair< MooseEnumItem, std::string > > &petsc_pair_options, const unsigned int mesh_dimension, std::string prefix, const ParallelParamObject &param_object, PetscOptions &petsc_options)
Populate name and value pairs in a given PetscOptions object using vectors of input arguments.
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64
RelationshipManagerType
Main types of Relationship Managers.