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