Skip to content

Commit

Permalink
Merge pull request #28321 from lindsayad/auto-multi-pre-24690
Browse files Browse the repository at this point in the history
Automatically setup multiple preconditioners for Newton
  • Loading branch information
lindsayad authored Aug 12, 2024
2 parents 757fab8 + cd50458 commit 766e270
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 24 deletions.
5 changes: 5 additions & 0 deletions framework/include/problems/FEProblemBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2348,6 +2348,11 @@ class FEProblemBase : public SubProblem, public Restartable
virtual void setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid) override;
virtual void setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid) override;

/**
* @returns the nolinear system names in the problem
*/
const std::vector<NonlinearSystemName> & getNonlinearSystemNames() const { return _nl_sys_names; }

protected:
/// Create extra tagged vectors and matrices
void createTagVectors();
Expand Down
36 changes: 21 additions & 15 deletions framework/src/actions/CreateExecutionerAction.C
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,29 @@ CreateExecutionerAction::setupAutoPreconditioning()
const MooseEnum & solve_type = _moose_object_pars.get<MooseEnum>("solve_type");
if (((solve_type.find("NEWTON") != solve_type.items().end()) && (solve_type == "NEWTON")) ||
((solve_type.find("LINEAR") != solve_type.items().end()) && (solve_type == "LINEAR")))
{
// Action Parameters
InputParameters params = _action_factory.getValidParams("SetupPreconditionerAction");
params.set<std::string>("type") = "SMP";
for (const auto & nl_sys_name : _problem->getNonlinearSystemNames())
{
// Action Parameters
InputParameters params = _action_factory.getValidParams("SetupPreconditionerAction");
params.set<std::string>("type") = "SMP";

// Associate errors with "solve_type"
associateWithParameter(_moose_object_pars, "solve_type", params);
// Associate errors with "solve_type"
associateWithParameter(_moose_object_pars, "solve_type", params);

// Create the Action that will build the Preconditioner object
std::shared_ptr<Action> ptr =
_action_factory.create("SetupPreconditionerAction", "_moose_auto", params);
// Create the Action that will build the Preconditioner object
std::shared_ptr<Action> ptr = _action_factory.create(
"SetupPreconditionerAction",
MooseUtils::join(
std::vector<std::string>({"_moose_auto", static_cast<std::string>(nl_sys_name)}),
"_"),
params);

// Set 'full=true'
std::shared_ptr<MooseObjectAction> moa_ptr = std::static_pointer_cast<MooseObjectAction>(ptr);
InputParameters & mo_params = moa_ptr->getObjectParams();
mo_params.set<bool>("full") = true;
// Set 'full=true'
std::shared_ptr<MooseObjectAction> moa_ptr = std::static_pointer_cast<MooseObjectAction>(ptr);
InputParameters & mo_params = moa_ptr->getObjectParams();
mo_params.set<bool>("full") = true;
mo_params.set<NonlinearSystemName>("nl_sys") = nl_sys_name;

_awh.addActionBlock(ptr);
}
_awh.addActionBlock(ptr);
}
}
2 changes: 1 addition & 1 deletion framework/src/outputs/ConsoleUtils.C
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ outputExecutionInformation(const MooseApp & app, FEProblemBase & problem)
<< " MOOSE Preconditioner" +
(problem.numNonlinearSystems() > 1 ? (" " + std::to_string(i)) : "") + ": "
<< mpc->getParam<std::string>("_type");
if (mpc->name() == "_moose_auto")
if (mpc->name().find("_moose_auto") != std::string::npos)
oss << " (auto)";
oss << '\n';
}
Expand Down
9 changes: 1 addition & 8 deletions framework/src/preconditioners/MoosePreconditioner.C
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,5 @@ MoosePreconditioner::copyVarValues(MeshBase & mesh,
void
MoosePreconditioner::setCouplingMatrix(std::unique_ptr<CouplingMatrix> cm)
{
for (const auto i : make_range(_fe_problem.numNonlinearSystems()))
{
if (i == libMesh::cast_int<unsigned int>(_fe_problem.numNonlinearSystems() - 1))
// This is the last nonlinear system, so it's safe now to move the object
_fe_problem.setCouplingMatrix(std::move(cm), i);
else
_fe_problem.setCouplingMatrix(std::make_unique<CouplingMatrix>(*cm), i);
}
_fe_problem.setCouplingMatrix(std::move(cm), _nl_sys_num);
}
7 changes: 7 additions & 0 deletions framework/src/problems/FEProblemBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -5924,7 +5924,14 @@ FEProblemBase::init()

for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
for (const auto i : index_range(_nl))
{
mooseAssert(
_cm[i],
"Coupling matrix not set for system "
<< i
<< ". This should only happen if a preconditioner was not setup for this system");
_assembly[tid][i]->init(_cm[i].get());
}

if (_displaced_problem)
_displaced_problem->init();
Expand Down
96 changes: 96 additions & 0 deletions test/tests/misc/multiple-nl-systems/different-vars-per-system.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
[Mesh]
type = GeneratedMesh
dim = 1
nx = 20
[]

[Problem]
nl_sys_names = 'u v'
[]

[Variables]
[u]
solver_sys = 'u'
[]
[v]
solver_sys = 'v'
[]
[w]
solver_sys = 'u'
[]
[]

[Kernels]
[diff_u]
type = Diffusion
variable = u
[]
[diff_v]
type = Diffusion
variable = v
[]
[force]
type = CoupledForce
variable = v
v = u
[]
[diff_w]
type = Diffusion
variable = w
[]
[]

[BCs]
[left_u]
type = DirichletBC
variable = u
boundary = left
value = 0
[]
[right_u]
type = DirichletBC
variable = u
boundary = right
value = 1
[]
[left_v]
type = DirichletBC
variable = v
boundary = left
value = 0
[]
[right_v]
type = DirichletBC
variable = v
boundary = right
value = 1
[]
[left_w]
type = DirichletBC
variable = w
boundary = left
value = 0
[]
[right_w]
type = DirichletBC
variable = w
boundary = right
value = 1
[]
[]

[Executioner]
type = SteadySolve2
solve_type = 'NEWTON'
petsc_options = '-snes_monitor'
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
first_nl_sys_to_solve = 'u'
second_nl_sys_to_solve = 'v'
[]

[Outputs]
print_nonlinear_residuals = false
print_linear_residuals = false
exodus = true
[]
Binary file not shown.
17 changes: 17 additions & 0 deletions test/tests/misc/multiple-nl-systems/tests
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,21 @@
input = test.i
requirement = 'The system shall be able to perform a segregated solve using objects with hand-coded Jacobians and show perfect Jacobians for those objects.'
[]
[different_num_vars_per_system]
requirement = 'The software shall allow having a different number of variables in nonlinear systems within the same problem when the action of the Jacobian is provided by'
[newton]
type = Exodiff
input = different-vars-per-system.i
exodiff = different-vars-per-system_out.e
detail = 'an assembled matrix, or'
[]
[pjfnk]
type = Exodiff
input = different-vars-per-system.i
exodiff = different-vars-per-system_out.e
detail = 'a matrix-free approximation.'
prereq = 'different_num_vars_per_system/newton'
cli_args = 'Executioner/solve_type=PJFNK'
[]
[]
[]

0 comments on commit 766e270

Please sign in to comment.