Loading [MathJax]/extensions/tex2jax.js
https://mooseframework.inl.gov
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
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  return params;
100 }
101 
103  : Action(parameters),
105  _system_names(getParam<std::vector<SolverSystemName>>("system_names")),
106  _verbose(getParam<bool>("verbose")),
107  _preconditioning(getParam<MooseEnum>("preconditioning")),
108  _blocks(getParam<std::vector<SubdomainName>>("block")),
109  _is_transient(getParam<MooseEnum>("transient"))
110 {
111  checkSecondParamSetOnlyIfFirstOneTrue("initialize_variables_from_mesh_file",
112  "initial_from_file_timestep");
114  addRequiredPhysicsTask("init_physics");
115  addRequiredPhysicsTask("copy_vars_physics");
116  addRequiredPhysicsTask("check_integrity_early_physics");
117 }
118 
119 void
121 {
122  mooseDoOnce(checkRequiredTasks());
123 
124  // Lets a derived Physics class implement additional tasks
126 
127  // Initialization and variables
128  if (_current_task == "init_physics")
130  else if (_current_task == "add_variable" && !getParam<bool>("dont_create_solver_variables"))
132  else if (_current_task == "add_ic" && !getParam<bool>("dont_create_ics"))
134 
135  // Kernels
136  else if (_current_task == "add_kernel" && !getParam<bool>("dont_create_kernels"))
137  addFEKernels();
138  else if (_current_task == "add_nodal_kernel" && !getParam<bool>("dont_create_kernels"))
139  addNodalKernels();
140  else if ((_current_task == "add_fv_kernel" || _current_task == "add_linear_fv_kernel") &&
141  !getParam<bool>("dont_create_kernels"))
142  addFVKernels();
143  else if (_current_task == "add_dirac_kernel" && !getParam<bool>("dont_create_kernels"))
144  addDiracKernels();
145  else if (_current_task == "add_dg_kernel" && !getParam<bool>("dont_create_kernels"))
146  addDGKernels();
147  else if (_current_task == "add_scalar_kernel" && !getParam<bool>("dont_create_kernels"))
149  else if (_current_task == "add_interface_kernel" && !getParam<bool>("dont_create_kernels"))
151  else if (_current_task == "add_fv_ik" && !getParam<bool>("dont_create_kernels"))
153 
154  // Boundary conditions
155  else if (_current_task == "add_bc" && !getParam<bool>("dont_create_bcs"))
156  addFEBCs();
157  else if (_current_task == "add_nodal_bc" && !getParam<bool>("dont_create_bcs"))
158  addNodalBCs();
159  else if ((_current_task == "add_fv_bc" || _current_task == "add_linear_fv_bc") &&
160  !getParam<bool>("dont_create_bcs"))
161  addFVBCs();
162  else if (_current_task == "add_periodic_bc" && !getParam<bool>("dont_create_bcs"))
163  addPeriodicBCs();
164 
165  // Auxiliary quantities
166  else if (_current_task == "add_function" && !getParam<bool>("dont_create_functions"))
167  addFunctions();
168  else if (_current_task == "add_aux_variable" && !getParam<bool>("dont_create_aux_variables"))
170  else if (_current_task == "add_aux_kernel" && !getParam<bool>("dont_create_aux_kernels"))
172  else if (_current_task == "add_material" && !getParam<bool>("dont_create_materials"))
173  addMaterials();
174  else if (_current_task == "add_functor_material" && !getParam<bool>("dont_create_materials"))
176 
177  // Multiapp
178  else if (_current_task == "add_multi_app")
179  addMultiApps();
180  else if (_current_task == "add_transfer")
181  addTransfers();
182 
183  // User objects and output
184  else if (_current_task == "add_user_object" && !getParam<bool>("dont_create_user_objects"))
185  addUserObjects();
186  else if (_current_task == "add_corrector" && !getParam<bool>("dont_create_correctors"))
187  addCorrectors();
188  else if (_current_task == "add_postprocessor" && !getParam<bool>("dont_create_postprocessors"))
190  else if (_current_task == "add_vector_postprocessor" &&
191  !getParam<bool>("dont_create_vectorpostprocessors"))
193  else if (_current_task == "add_reporter")
194  addReporters();
195  else if (_current_task == "add_output")
196  addOutputs();
197 
198  // Equation solver-related tasks
199  else if (_current_task == "add_preconditioning")
201  else if (_current_task == "add_executioner")
202  addExecutioner();
203  else if (_current_task == "add_executor")
204  addExecutors();
205 
206  // Checks
207  else if (_current_task == "check_integrity_early_physics")
209  else if (_current_task == "check_integrity")
210  checkIntegrity();
211 
212  // Exodus restart capabilities
213  if (_current_task == "copy_vars_physics")
214  {
216  if (_aux_var_names.size() > 0)
218  }
219 }
220 
221 void
223 {
224  if (getParam<bool>("initialize_variables_from_mesh_file"))
226 
227  checkSecondParamSetOnlyIfFirstOneTrue("initialize_variables_from_mesh_file",
228  "initial_from_file_timestep");
229 }
230 
231 bool
233 {
234  mooseAssert(_problem, "We don't have a problem yet");
235  if (_is_transient == "true")
236  return true;
237  else if (_is_transient == "false")
238  return false;
239  else
240  return getProblem().isTransient();
241 }
242 
243 unsigned int
245 {
246  mooseAssert(_mesh, "We dont have a mesh yet");
247  mooseAssert(_dim < 4, "Dimension has not been set yet");
248  return _dim;
249 }
250 
251 std::set<SubdomainID>
252 PhysicsBase::getSubdomainIDs(const std::set<SubdomainName> & blocks) const
253 {
254  const bool not_block_restricted =
255  (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end()) ||
257  mooseAssert(_mesh, "Should have a mesh");
258  // use a set for simplicity. Note that subdomain names are unique, except maybe the empty one,
259  // which cannot be specified by the user to the Physics.
260  // MooseMesh::getSubdomainIDs cannot deal with the 'ANY_BLOCK_ID' name
261  std::set<SubdomainID> block_ids_set =
262  not_block_restricted ? _mesh->meshSubdomains() : _mesh->getSubdomainIDs(blocks);
263  return block_ids_set;
264 }
265 
266 std::vector<std::string>
267 PhysicsBase::getSubdomainNamesAndIDs(const std::set<SubdomainID> & blocks) const
268 {
269  mooseAssert(_mesh, "Should have a mesh");
270  std::vector<std::string> sub_names_ids;
271  sub_names_ids.reserve(blocks.size());
272  for (const auto bid : blocks)
273  {
274  const auto bname = _mesh->getSubdomainName(bid);
275  sub_names_ids.push_back((bname.empty() ? "(unnamed)" : bname) + " (" + std::to_string(bid) +
276  ")");
277  }
278  return sub_names_ids;
279 }
280 
281 void
282 PhysicsBase::addBlocks(const std::vector<SubdomainName> & blocks)
283 {
284  if (blocks.size())
285  {
286  _blocks.insert(_blocks.end(), blocks.begin(), blocks.end());
287  _dim = _mesh->getBlocksMaxDimension(_blocks);
288  }
289 }
290 
291 void
292 PhysicsBase::addBlocksById(const std::vector<SubdomainID> & block_ids)
293 {
294  if (block_ids.size())
295  {
296  for (const auto bid : block_ids)
297  _blocks.push_back(_mesh->getSubdomainName(bid));
298  _dim = _mesh->getBlocksMaxDimension(_blocks);
299  }
300 }
301 
302 void
304 {
305  for (const auto & block : component.blocks())
306  _blocks.push_back(block);
307 }
308 
309 void
311 {
313  Action::addRelationshipManagers(input_rm_type, params);
314 }
315 
316 const ActionComponent &
317 PhysicsBase::getActionComponent(const ComponentName & comp_name) const
318 {
319  return _awh.getAction<ActionComponent>(comp_name);
320 }
321 
322 void
324 {
325  // Annoying edge case. We cannot use ANY_BLOCK_ID for kernels and variables since errors got
326  // added downstream for using it, we cannot leave it empty as that sets all objects to not live
327  // on any block
328  if (isParamSetByUser("block") && _blocks.empty())
329  paramError("block",
330  "Empty block restriction is not supported. Comment out the Physics if you are "
331  "trying to disable it.");
332 
333  // Components should have added their blocks already.
334  if (_blocks.empty())
335  _blocks.push_back("ANY_BLOCK_ID");
336 
337  mooseAssert(_mesh, "We should have a mesh to find the dimension");
338  if (_blocks.size())
339  _dim = _mesh->getBlocksMaxDimension(_blocks);
340  else
341  _dim = _mesh->dimension();
342 
343  // Forward physics verbosity to problem to output the setup
344  if (_verbose)
346 
347  // If the derived physics need additional initialization very early on
349 
350  // Check that the systems exist in the Problem
351  // TODO: try to add the systems to the problem from here instead
352  // NOTE: this must be performed after the "Additional" initialization because the list
353  // of systems might have been adjusted once the dimension of the Physics is known
354  const auto & problem_nl_systems = getProblem().getNonlinearSystemNames();
355  const auto & problem_lin_systems = getProblem().getLinearSystemNames();
356  for (const auto & sys_name : _system_names)
357  if (std::find(problem_nl_systems.begin(), problem_nl_systems.end(), sys_name) ==
358  problem_nl_systems.end() &&
359  std::find(problem_lin_systems.begin(), problem_lin_systems.end(), sys_name) ==
360  problem_lin_systems.end() &&
361  solverVariableNames().size())
362  mooseError("System '", sys_name, "' is not found in the Problem");
363 
364  // Cache system number as it makes some logic easier
365  for (const auto & sys_name : _system_names)
366  _system_numbers.push_back(getProblem().solverSysNum(sys_name));
367 }
368 
369 void
371 {
372  if (_is_transient == "true" && !getProblem().isTransient())
373  paramError("transient", "We cannot solve a physics as transient in a steady problem");
374 
375  // Check that there is a system for each variable
376  if (_system_names.size() != 1 && _system_names.size() != _solver_var_names.size())
377  paramError("system_names",
378  "There should be one system name per solver variable (potentially repeated), or a "
379  "single system name for all variables. Current you have '" +
380  std::to_string(_system_names.size()) + "' systems specified for '" +
381  std::to_string(_solver_var_names.size()) + "' solver variables.");
382 
383  // Check that each variable is present in the expected system
384  unsigned int var_i = 0;
385  for (const auto & var_name : _solver_var_names)
386  {
387  const auto & sys_name = _system_names.size() == 1 ? _system_names[0] : _system_names[var_i++];
388  if (!_problem->getSolverSystem(_problem->solverSysNum(sys_name)).hasVariable(var_name) &&
389  !_problem->getSolverSystem(_problem->solverSysNum(sys_name)).hasScalarVariable(var_name))
390  paramError("system_names",
391  "We expected system '" + sys_name + "' to contain variable '" + var_name +
392  "' but it did not. Make sure the system names closely match the ordering of "
393  "the variables in the Physics.");
394  }
395 }
396 
397 void
398 PhysicsBase::copyVariablesFromMesh(const std::vector<VariableName> & variables_to_copy,
399  bool are_nonlinear)
400 {
401  if (getParam<bool>("initialize_variables_from_mesh_file"))
402  {
403  mooseInfoRepeated("Adding Exodus restart for " + std::to_string(variables_to_copy.size()) +
404  " variables: " + Moose::stringify(variables_to_copy));
405  // TODO Check that the variable types and orders are actually supported for exodus restart
406  for (const auto i : index_range(variables_to_copy))
407  {
408  SystemBase & system =
409  are_nonlinear ? getProblem().getNonlinearSystemBase(
410  _system_numbers.size() == 1 ? _system_numbers[0] : _system_numbers[i])
412  const auto & var_name = variables_to_copy[i];
413  system.addVariableToCopy(
414  var_name, var_name, getParam<std::string>("initial_from_file_timestep"));
415  }
416  }
417 }
418 
419 bool
420 PhysicsBase::variableExists(const VariableName & var_name, bool error_if_aux) const
421 {
422  if (error_if_aux && _problem->getAuxiliarySystem().hasVariable(var_name))
423  mooseError("Variable '",
424  var_name,
425  "' is supposed to be nonlinear for physics '",
426  name(),
427  "' but it is already defined as auxiliary");
428  else
429  return _problem->hasVariable(var_name);
430 }
431 
432 bool
433 PhysicsBase::solverVariableExists(const VariableName & var_name) const
434 {
435  return _problem->hasSolverVariable(var_name);
436 }
437 
438 const SolverSystemName &
439 PhysicsBase::getSolverSystem(unsigned int variable_index) const
440 {
441  mooseAssert(!_system_names.empty(), "We should have a solver system name");
442  if (_system_names.size() == 1)
443  return _system_names[0];
444  else
445  // We trust that the system names and the variable names match one-to-one as it is enforced by
446  // the checkIntegrityEarly() routine.
447  return _system_names[variable_index];
448 }
449 
450 const SolverSystemName &
451 PhysicsBase::getSolverSystem(const VariableName & var_name) const
452 {
453  mooseAssert(!_system_names.empty(), "We should have a solver system name");
454  // No need to look if only one system for the Physics
455  if (_system_names.size() == 1)
456  return _system_names[0];
457 
458  // We trust that the system names and the variable names match one-to-one as it is enforced by
459  // the checkIntegrityEarly() routine.
460  for (const auto variable_index : index_range(_solver_var_names))
461  if (var_name == _solver_var_names[variable_index])
462  return _system_names[variable_index];
463  mooseError("Variable '", var_name, "' was not found within the Physics solver variables.");
464 }
465 
466 void
468 {
469  const auto registered_tasks = _action_factory.getTasksByAction(type());
470 
471  // Check for missing tasks
472  for (const auto & required_task : _required_tasks)
473  if (!registered_tasks.count(required_task))
474  mooseWarning("Task '" + required_task +
475  "' has been declared as required by a Physics parent class of derived class '" +
476  type() +
477  "' but this task is not registered to the derived class. Registered tasks for "
478  "this Physics are: " +
479  Moose::stringify(registered_tasks));
480 }
481 
482 void
483 PhysicsBase::assignBlocks(InputParameters & params, const std::vector<SubdomainName> & blocks) const
484 {
485  // We only set the blocks if we don't have `ANY_BLOCK_ID` defined because the subproblem
486  // (through the mesh) errors out if we use this keyword during the addVariable/Kernel
487  // functions
488  if (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") == blocks.end())
489  params.set<std::vector<SubdomainName>>("block") = blocks;
490  if (blocks.empty())
491  mooseInfoRepeated("Empty block restriction assigned to an object created by Physics '" +
492  name() + "'.\n Did you mean to do this?");
493 }
494 
495 bool
496 PhysicsBase::checkBlockRestrictionIdentical(const std::string & object_name,
497  const std::vector<SubdomainName> & blocks,
498  bool error_if_not_identical) const
499 {
500  // If identical, we can return fast
501  if (_blocks == blocks)
502  return true;
503  // If one is block restricted to anywhere and the other is block restricted to anywhere manually
504  if ((std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end() &&
505  allMeshBlocks(blocks)) ||
506  (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end() &&
508  return true;
509 
510  // Copy, sort and unique is the only way to check that they are actually the same
511  auto copy_blocks = _blocks;
512  auto copy_blocks_other = blocks;
513  std::sort(copy_blocks.begin(), copy_blocks.end());
514  copy_blocks.erase(unique(copy_blocks.begin(), copy_blocks.end()), copy_blocks.end());
515  std::sort(copy_blocks_other.begin(), copy_blocks_other.end());
516  copy_blocks_other.erase(unique(copy_blocks_other.begin(), copy_blocks_other.end()),
517  copy_blocks_other.end());
518 
519  if (copy_blocks == copy_blocks_other)
520  return true;
521  std::vector<SubdomainName> diff;
522  std::set_difference(copy_blocks.begin(),
523  copy_blocks.end(),
524  copy_blocks_other.begin(),
525  copy_blocks_other.end(),
526  std::inserter(diff, diff.begin()));
527  if (error_if_not_identical)
528  mooseError("Physics '",
529  name(),
530  "' and object '",
531  object_name,
532  "' have different block restrictions.\nPhysics: ",
534  "\nObject: ",
536  "\nDifference: ",
537  Moose::stringify(diff));
538  else
539  return false;
540 }
541 
542 bool
543 PhysicsBase::allMeshBlocks(const std::vector<SubdomainName> & blocks) const
544 {
545  mooseAssert(_mesh, "The mesh should exist already");
546  // Try to return faster without examining every single block
547  if (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end())
548  return true;
549  else if (blocks.size() != _mesh->meshSubdomains().size())
550  return false;
551 
552  for (const auto mesh_block : _mesh->meshSubdomains())
553  {
554  const auto & subdomain_name = _mesh->getSubdomainName(mesh_block);
555  // Check subdomain name
556  if (!subdomain_name.empty() &&
557  std::find(blocks.begin(), blocks.end(), subdomain_name) == blocks.end())
558  return false;
559  // no subdomain name, check the IDs being used as names instead
560  else if (std::find(blocks.begin(), blocks.end(), std::to_string(mesh_block)) == blocks.end())
561  return false;
562  }
563  return true;
564 }
565 
566 bool
567 PhysicsBase::allMeshBlocks(const std::set<SubdomainName> & blocks) const
568 {
569  std::vector<SubdomainName> blocks_vec(blocks.begin(), blocks.end());
570  return allMeshBlocks(blocks_vec);
571 }
572 
573 void
575  const std::vector<std::pair<MooseEnumItem, std::string>> & petsc_pair_options)
576 {
577  Moose::PetscSupport::PetscOptions & po = _problem->getPetscOptions();
578  for (const auto solver_sys_num : _system_numbers)
580  petsc_pair_options,
581  _problem->mesh().dimension(),
582  _problem->getSolverSystem(solver_sys_num).prefix(),
583  *this,
584  po);
585 }
586 
587 bool
588 PhysicsBase::isVariableFV(const VariableName & var_name) const
589 {
590  const auto var = &_problem->getVariable(0, var_name);
591  return var->isFV();
592 }
593 
594 bool
595 PhysicsBase::isVariableScalar(const VariableName & var_name) const
596 {
597  return _problem->hasScalarVariable(var_name);
598 }
599 
600 bool
601 PhysicsBase::shouldCreateVariable(const VariableName & var_name,
602  const std::vector<SubdomainName> & blocks,
603  const bool error_if_aux)
604 {
605  if (!variableExists(var_name, error_if_aux))
606  return true;
607  // check block restriction
608  auto & var = _problem->getVariable(0, var_name);
609  const bool not_block_restricted =
610  (std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end()) ||
612  if (!var.blockRestricted() || (!not_block_restricted && var.hasBlocks(blocks)))
613  return false;
614 
615  // This is an edge case, which might warrant a warning
616  if (allMeshBlocks(var.blocks()) && not_block_restricted)
617  return false;
618  else
619  mooseError("Variable '" + var_name + "' already exists with subdomain restriction '" +
620  Moose::stringify(var.blocks()) + "' which does not include the subdomains '" +
621  Moose::stringify(blocks) + "', required for this Physics.");
622 }
623 
624 bool
625 PhysicsBase::shouldCreateIC(const VariableName & var_name,
626  const std::vector<SubdomainName> & blocks,
627  const bool ic_is_default_ic,
628  const bool error_if_already_defined) const
629 {
630  // Handle recover
631  if (ic_is_default_ic && (_app.isRestarting() || _app.isRecovering()))
632  return false;
633  // do not set initial conditions if we are loading fields from the mesh file
634  if (getParam<bool>("initialize_variables_from_mesh_file"))
635  return false;
636  // Different type of ICs, not block restrictable
637  mooseAssert(!isVariableScalar(var_name), "shouldCreateIC not implemented for scalar variables");
638 
639  // Process the desired block restriction into a set of subdomain IDs
640  std::set<SubdomainName> blocks_set(blocks.begin(), blocks.end());
641  const auto blocks_ids_set = getSubdomainIDs(blocks_set);
642 
643  // Check whether there are any ICs for this variable already in the problem
644  std::set<SubdomainID> blocks_ids_covered;
645  bool has_all_blocks;
646  if (isVariableFV(var_name))
647  has_all_blocks = _problem->getFVInitialConditionWarehouse().hasObjectsForVariableAndBlocks(
648  var_name, blocks_ids_set, blocks_ids_covered, /*tid =*/0);
649  else
650  has_all_blocks = _problem->getInitialConditionWarehouse().hasObjectsForVariableAndBlocks(
651  var_name, blocks_ids_set, blocks_ids_covered, /*tid =*/0);
652 
653  const bool has_some_blocks = !blocks_ids_covered.empty();
654  if (!has_some_blocks)
655  return true;
656 
657  if (has_all_blocks)
658  {
659  if (error_if_already_defined)
660  mooseError("ICs for variable '" + var_name + "' have already been defined for blocks '" +
661  Moose::stringify(blocks) + "'.");
662  else
663  return false;
664  }
665 
666  // Partial overlap between Physics is not implemented.
667  mooseError("There is a partial overlap between the subdomains covered by pre-existing initial "
668  "conditions (ICs), defined on blocks (ids): " +
669  Moose::stringify(getSubdomainNamesAndIDs(blocks_ids_covered)) +
670  "\n and a newly created IC for variable " + var_name +
671  ", to be defined on blocks: " + Moose::stringify(blocks) +
672  ".\nWe should be creating the Physics' IC only for non-covered blocks. This is not "
673  "implemented at this time.");
674 }
675 
676 bool
677 PhysicsBase::shouldCreateTimeDerivative(const VariableName & var_name,
678  const std::vector<SubdomainName> & blocks,
679  const bool error_if_already_defined) const
680 {
681  // Follow the transient setting of the Physics
682  if (!isTransient())
683  return false;
684 
685  // Variable is either nonlinear (FV/FE), nodal nonlinear (field of ODEs), linear, or scalar.
686  // The warehouses hosting the time kernels are different for each of these types
687  // Different type of time derivatives, not block restrictable
688  mooseAssert(!isVariableScalar(var_name),
689  "shouldCreateTimeDerivative not implemented for scalar variables");
690  mooseAssert(!_problem->hasAuxiliaryVariable(var_name),
691  "Should not be called with auxiliary variables");
692 
693  // Get solver system type
694  const auto var = &_problem->getVariable(0, var_name);
695  const auto var_id = var->number();
696  const auto sys_num = var->sys().number();
697  const auto time_vector_tag =
698  (sys_num < _problem->numNonlinearSystems())
699  ? var->sys().timeVectorTag()
700  // this is not quite correct. Many kernels can contribute to RHS time vector on paper
701  : dynamic_cast<LinearSystem *>(&var->sys())->rightHandSideTimeVectorTag();
702 
703  // We just use the warehouse, it should cover every time derivative object type
704  bool all_blocks_covered = true;
705  std::set<SubdomainID> blocks_ids_covered;
706  // we examine subdomain by subdomain, because mutiple kernels could be covering every block in
707  // the 'blocks' parameter
708  for (const auto & block : blocks)
709  {
710  std::vector<MooseObject *> time_kernels;
711  if (block != "ANY_BLOCK_ID")
712  {
713  const auto bid = _mesh->getSubdomainID(block);
714  _problem->theWarehouse()
715  .query()
716  .template condition<AttribSysNum>(sys_num)
717  .template condition<AttribVar>(var_id)
718  .template condition<AttribSubdomains>(bid)
719  // we use the time tag as a proxy for time derivatives
720  .template condition<AttribVectorTags>(time_vector_tag)
721  .queryInto(time_kernels);
722  }
723  else
724  _problem->theWarehouse()
725  .query()
726  .template condition<AttribSysNum>(sys_num)
727  .template condition<AttribVar>(var_id)
728  // we use the time tag as a proxy for time derivatives
729  .template condition<AttribVectorTags>(time_vector_tag)
730  .queryInto(time_kernels);
731 
732  if (time_kernels.size())
733  {
734  if (block == "ANY_BLOCK_ID")
735  {
736  for (const auto & time_kernel : time_kernels)
737  if (const auto blk = dynamic_cast<BlockRestrictable *>(time_kernel))
738  blocks_ids_covered.insert(blk->blockIDs().begin(), blk->blockIDs().end());
739  }
740  else
741  blocks_ids_covered.insert(_mesh->getSubdomainID(block));
742  }
743  else
744  all_blocks_covered = false;
745  }
746 
747  // From the set of covered blocks, see if the blocks we needed are found
748  if (all_blocks_covered)
749  {
750  std::set<SubdomainName> blocks_set(blocks.begin(), blocks.end());
751  const auto blocks_ids = getSubdomainIDs(blocks_set);
752  if (blocks_ids != blocks_ids_covered)
753  all_blocks_covered = false;
754  }
755  const bool has_some_blocks = !blocks_ids_covered.empty();
756  if (!has_some_blocks)
757  return true;
758  if (all_blocks_covered)
759  {
760  if (error_if_already_defined)
761  mooseError("A time kernel for variable '" + var_name +
762  "' has already been defined on blocks '" + Moose::stringify(blocks) + "'.");
763  else
764  return false;
765  }
766 
767  // Partial overlap between Physics is not implemented.
768  mooseError("There is a partial overlap between the subdomains covered by pre-existing time "
769  "derivative kernel(s), defined on blocks (ids): " +
770  Moose::stringify(getSubdomainNamesAndIDs(blocks_ids_covered)) +
771  "\nand a newly created time derivative kernel for variable " + var_name +
772  ", to be defined on blocks: " + Moose::stringify(blocks) +
773  ".\nWe should be creating the Physics' time derivative only for non-covered "
774  "blocks. This is not implemented at this time.");
775 }
776 
777 void
778 PhysicsBase::reportPotentiallyMissedParameters(const std::vector<std::string> & param_names,
779  const std::string & object_type) const
780 {
781  std::vector<std::string> defaults_unused;
782  std::vector<std::string> user_values_unused;
783  for (const auto & param : param_names)
784  {
785  if (isParamSetByUser(param))
786  user_values_unused.push_back(param);
787  else if (isParamValid(param))
788  defaults_unused.push_back(param);
789  }
790  if (defaults_unused.size() && _verbose)
791  mooseInfoRepeated("Defaults for parameters '" + Moose::stringify(defaults_unused) +
792  "' for object of type '" + object_type +
793  "' were not used because the object was not created by this Physics.");
794  if (user_values_unused.size())
795  {
797  mooseWarning(
798  "User-specifed values for parameters '" + Moose::stringify(user_values_unused) +
799  "' for object of type '" + object_type +
800  "' were not used because the corresponding object was not created by this Physics.");
801  else if (_app.unusedFlagIsError())
802  mooseError(
803  "User-specified values for parameters '" + Moose::stringify(user_values_unused) +
804  "' for object of type '" + object_type +
805  "' were not used because the corresponding object was not created by this Physics.");
806  }
807 }
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:120
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:483
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:601
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:323
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:574
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:370
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:1147
bool solverVariableExists(const VariableName &var_name) const
Check whether a variable already exists and is a solver variable.
Definition: PhysicsBase.C:433
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:625
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:677
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:1737
bool allMeshBlocks(const std::vector< SubdomainName > &blocks) const
Check if a vector contains all the mesh blocks.
Definition: PhysicsBase.C:543
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:244
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:282
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:439
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:1125
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:457
bool isVariableScalar(const VariableName &var_name) const
Whether the variable is a scalar variable (global single scalar, not a field)
Definition: PhysicsBase.C:595
PhysicsBase(const InputParameters &parameters)
Definition: PhysicsBase.C:102
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:398
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:588
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:267
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
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
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:420
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:496
virtual void addFVKernels()
Definition: PhysicsBase.h:284
static InputParameters validParams()
Definition: PhysicsBase.C:24
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:252
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:303
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:310
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:684
bool unusedFlagIsWarning() const
Returns whether the flag for unused parameters is set to throw a warning only.
Definition: MooseApp.h:1122
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:292
void prepareCopyVariablesFromMesh() const
Tell the app if we want to use Exodus restart.
Definition: PhysicsBase.C:222
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:778
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:317
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:1731
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:232
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:467