From 0069f38f1431c61ff7060b8af084edea7e9c1414 Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Wed, 6 Nov 2024 09:31:51 -0700 Subject: [PATCH] Add support for multi-system at the Physics base class refs #8780 #29019 --- framework/include/physics/PhysicsBase.h | 28 ++++++++--- framework/src/physics/PhysicsBase.C | 67 +++++++++++++++++++++++-- framework/src/problems/FEProblemBase.C | 2 +- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/framework/include/physics/PhysicsBase.h b/framework/include/physics/PhysicsBase.h index 4bee0d914884..93213f0bd617 100644 --- a/framework/include/physics/PhysicsBase.h +++ b/framework/include/physics/PhysicsBase.h @@ -94,8 +94,8 @@ class PhysicsBase : public Action, public InputParametersChecksUtils & nonlinearVariableNames() const { return _nl_var_names; }; + /// Return the list of solver (nonlinear + linear) variables in this physics + const std::vector & solverVariableNames() const { return _solver_var_names; }; /// Return the list of aux variables in this physics const std::vector & auxVariableNames() const { return _aux_var_names; }; @@ -134,14 +134,23 @@ class PhysicsBase : public Action, public InputParametersChecksUtils & blocks) const; - /// System number for the system owning the variables - const unsigned int _sys_number; + /// System names for the system(s) owning the solver variables + std::vector _system_names; + + /// System numbers for the system(s) owning the solver variables + std::vector _system_numbers; /// Whether to output additional information const bool _verbose; @@ -224,8 +236,8 @@ class PhysicsBase : public Action, public InputParametersChecksUtils _nl_var_names; + /// Vector of the solver variables (nonlinear and linear) in the Physics + std::vector _solver_var_names; /// Vector of the aux variables in the Physics std::vector _aux_var_names; diff --git a/framework/src/physics/PhysicsBase.C b/framework/src/physics/PhysicsBase.C index bfd222af7f6d..ee6a179985f0 100644 --- a/framework/src/physics/PhysicsBase.C +++ b/framework/src/physics/PhysicsBase.C @@ -29,6 +29,13 @@ PhysicsBase::validParams() params.addParam( "transient", transient_options, "Whether the physics is to be solved as a transient"); + params.addParam>( + "system_name", + {"nl0"}, + "Name of the solver systems for the variables. If a single name is specified, " + "it is used for " + "all solver variables"); + MooseEnum pc_options("default none", "none"); params.addParam( "preconditioning", pc_options, "Which preconditioning to use for this Physics"); @@ -53,7 +60,7 @@ PhysicsBase::validParams() PhysicsBase::PhysicsBase(const InputParameters & parameters) : Action(parameters), InputParametersChecksUtils(this), - _sys_number(0), + _system_names(getParam>("system_name")), _verbose(getParam("verbose")), _preconditioning(getParam("preconditioning")), _blocks(getParam>("block")), @@ -143,7 +150,7 @@ PhysicsBase::act() // Exodus restart capabilities if (_current_task == "copy_vars_physics") { - copyVariablesFromMesh(nonlinearVariableNames(), true); + copyVariablesFromMesh(solverVariableNames(), true); if (_aux_var_names.size() > 0) copyVariablesFromMesh(auxVariableNames(), false); } @@ -244,6 +251,18 @@ PhysicsBase::initializePhysics() else _dim = _mesh->dimension(); + // Check that the systems exist in the Problem + // TODO: try to add the systems to the problem from here + const auto & problem_systems = getProblem().getNonlinearSystemNames(); + for (const auto & sys_name : _system_names) + if (std::find(problem_systems.begin(), problem_systems.end(), sys_name) == + problem_systems.end()) + mooseError("System '", sys_name, "' is not used in the problem"); + + // Cache system number as some routines prefer those + for (const auto & sys_name : _system_names) + _system_numbers.push_back(getProblem().solverSysNum(sys_name)); + // Forward physics verbosity to problem to output the setup if (_verbose) getProblem().setVerboseProblem(_verbose); @@ -257,6 +276,14 @@ PhysicsBase::checkIntegrityEarly() const { if (_is_transient == "true" && !getProblem().isTransient()) paramError("transient", "We cannot solve a physics as transient in a steady problem"); + + // Check that there is a system for each variable + if (_system_names.size() != 1 && _system_names.size() != _solver_var_names.size()) + paramError("system_name", + "There should be one system name per solver variable (potentially repeated), or a " + "single system name for all variables. Current you have '" + + std::to_string(_system_names.size()) + "' systems specified for '" + + std::to_string(_solver_var_names.size()) + "' solver variables."); } void @@ -265,14 +292,19 @@ PhysicsBase::copyVariablesFromMesh(const std::vector & variables_t { if (getParam("initialize_variables_from_mesh_file")) { - SystemBase & system = are_nonlinear ? getProblem().getNonlinearSystemBase(_sys_number) - : getProblem().systemBaseAuxiliary(); mooseInfoRepeated("Adding Exodus restart for " + std::to_string(variables_to_copy.size()) + " variables: " + Moose::stringify(variables_to_copy)); // TODO Check that the variable types and orders are actually supported for exodus restart - for (const auto & var_name : variables_to_copy) + for (const auto i : index_range(variables_to_copy)) + { + SystemBase & system = are_nonlinear + ? getProblem().getNonlinearSystemBase( + _system_numbers.size() == 1 ? _system_numbers[0] : i) + : getProblem().systemBaseAuxiliary(); + const auto & var_name = variables_to_copy[i]; system.addVariableToCopy( var_name, var_name, getParam("initial_from_file_timestep")); + } } } @@ -291,6 +323,31 @@ PhysicsBase::variableExists(const VariableName & var_name, bool error_if_aux) co return false; } +const SolverSystemName & +PhysicsBase::getSolverSystem(unsigned int variable_index) const +{ + mooseAssert(!_system_names.empty(), "We should have a solver system name"); + if (_system_names.size() == 1) + return _system_names[0]; + else + return _system_names[variable_index]; +} + +const SolverSystemName & +PhysicsBase::getSolverSystem(const VariableName & var_name) const +{ + mooseAssert(!_system_names.empty(), "We should have a solver system name"); + // No need to look if only one system + if (_system_names.size() == 1) + return _system_names[0]; + + // Find the variable in the list of variables + for (const auto variable_index : index_range(_solver_var_names)) + if (var_name == _solver_var_names[variable_index]) + return _system_names[variable_index]; + mooseError("Variable ", var_name, " was not found in list of variables"); +} + void PhysicsBase::checkRequiredTasks() const { diff --git a/framework/src/problems/FEProblemBase.C b/framework/src/problems/FEProblemBase.C index ab2324027043..84851558e0cf 100644 --- a/framework/src/problems/FEProblemBase.C +++ b/framework/src/problems/FEProblemBase.C @@ -5995,7 +5995,7 @@ FEProblemBase::init() _aux->dofMap().attach_extra_send_list_function(&extraSendList, _aux.get()); if (!_skip_nl_system_check && _solve && n_vars == 0) - mooseError("No variables specified in the FEProblemBase '", name(), "'."); + mooseError("No variables specified in nonlinear system '", nl->name(), "'."); } ghostGhostedBoundaries(); // We do this again right here in case new boundaries have been added