20#include "libmesh/libmesh_common.h"
21#include "libmesh/equation_systems.h"
22#include "libmesh/nonlinear_implicit_system.h"
23#include "libmesh/nonlinear_solver.h"
24#include "libmesh/linear_implicit_system.h"
25#include "libmesh/transient_system.h"
26#include "libmesh/numeric_vector.h"
27#include "libmesh/sparse_matrix.h"
28#include "libmesh/string_to_enum.h"
29#include "libmesh/coupling_matrix.h"
40 params.
addClassDescription(
"Physics-based preconditioner (PBP) allows individual physics to have "
41 "their own preconditioner.");
45 "The order the block rows will be solved in. Put the name of variables here "
46 "to stand for solving that variable's block row. A variable may appear more "
47 "than once (to create cylces if you like).");
48 params.
addRequiredParam<std::vector<std::string>>(
"preconditioner",
"TODO: docstring");
56 _nl(_fe_problem.getNonlinearSystemBase(_nl_sys_num))
58 const auto & libmesh_system =
_nl.
system();
71 std::unique_ptr<CouplingMatrix> cm = std::make_unique<CouplingMatrix>(
n_vars);
73 bool full = getParam<bool>(
"full");
78 for (
unsigned int i = 0; i <
n_vars; i++)
82 for (
const auto & off_diag : getParam<NonlinearVariableName, NonlinearVariableName>(
83 "off_diag_row",
"off_diag_column"))
85 const auto row = libmesh_system.variable_number(off_diag.first);
86 const auto column = libmesh_system.variable_number(off_diag.second);
87 (*cm)(row, column) = 1;
94 for (
unsigned int i = 0; i <
n_vars; i++)
95 for (
unsigned int j = 0; j <
n_vars; j++)
103 const std::vector<std::string> & pc_types = getParam<std::vector<std::string>>(
"preconditioner");
104 for (
unsigned int i = 0; i < num_systems; i++)
105 _pre_type[i] = Utility::string_to_enum<PreconditionerType>(pc_types[i]);
108 const std::vector<std::string> & solve_order = getParam<std::vector<std::string>>(
"solve_order");
117 std::vector<std::vector<unsigned int>> off_diag(
n_vars);
120 const std::vector<NonlinearVariableName> & odr =
121 getParam<std::vector<NonlinearVariableName>>(
"off_diag_row");
122 const std::vector<NonlinearVariableName> & odc =
123 getParam<std::vector<NonlinearVariableName>>(
"off_diag_column");
129 off_diag[row].push_back(column);
133 for (
unsigned int var = 0; var <
n_vars; var++)
139 mooseError(
"PBP must be used with JFNK solve type");
146 std::vector<unsigned int> off_diag,
175 TIME_SECTION(
"init", 2,
"Initializing PhysicsBasedPreconditioner");
180 const unsigned int num_systems =
_systems.size();
186 for (
unsigned int i = 0; i < num_systems; i++)
191 for (
unsigned int system_var = 0; system_var < num_systems; system_var++)
205 preconditioner->
init();
212 const unsigned int num_systems =
_systems.size();
214 std::vector<JacobianBlock *>
blocks;
217 for (
unsigned int system_var = 0; system_var < num_systems; system_var++)
229 unsigned int coupled_var =
_off_diag[system_var][diag];
241 for (
auto & block :
blocks)
248 TIME_SECTION(
"apply", 1,
"Applying PhysicsBasedPreconditioner");
250 const unsigned int num_systems =
_systems.size();
255 for (
unsigned int sys = 0; sys < num_systems; sys++)
273 unsigned int coupled_var =
_off_diag[system_var][diag];
302 for (
unsigned int system_var = 0; system_var < num_systems; system_var++)
registerMooseObjectAliased("MooseApp", PhysicsBasedPreconditioner, "PBP")
virtual libMesh::EquationSystems & es() override
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
virtual MooseMesh & mesh() override
virtual void computeJacobianBlocks(std::vector< JacobianBlock * > &blocks, const unsigned int nl_sys_num)
Computes several Jacobian blocks simultaneously, summing their contributions into smaller preconditio...
Helper class for holding the preconditioning blocks to fill.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Base class for MOOSE preconditioners.
FEProblemBase & _fe_problem
Subproblem this preconditioner is part of.
static void copyVarValues(MeshBase &mesh, const unsigned int from_system, const unsigned int from_var, const NumericVector< Number > &from_vector, const unsigned int to_system, const unsigned int to_var, NumericVector< Number > &to_vector)
Helper function for copying values associated with variables in vectors from two different systems.
void setCouplingMatrix(std::unique_ptr< libMesh::CouplingMatrix > cm)
Setup the coupling matrix on the finite element problem.
static InputParameters validParams()
virtual void attachPreconditioner(libMesh::Preconditioner< Number > *preconditioner)=0
Attach a customized preconditioner that requires physics knowledge.
virtual libMesh::System & system() override
Get the reference to the libMesh system.
Implements a segregated solve preconditioner.
virtual void setup()
This is called every time the "operator might have changed".
std::vector< unsigned int > _solve_order
Holds the order the blocks are solved for.
virtual void clear()
Release all memory and clear data structures.
static InputParameters validParams()
Constructor.
virtual ~PhysicsBasedPreconditioner()
std::vector< std::vector< libMesh::SparseMatrix< Number > * > > _off_diag_mats
Holds pointers to the off-diagonal matrices.
NonlinearSystemBase & _nl
The nonlinear system this PBP is associated with (convenience reference)
virtual void apply(const NumericVector< Number > &x, NumericVector< Number > &y)
Computes the preconditioned vector "y" based on input "x".
std::vector< libMesh::LinearImplicitSystem * > _systems
List of linear system that build up the preconditioner.
std::vector< std::unique_ptr< libMesh::Preconditioner< Number > > > _preconditioners
Holds one Preconditioner object per small system to solve.
PhysicsBasedPreconditioner(const InputParameters ¶ms)
std::vector< libMesh::PreconditionerType > _pre_type
Which preconditioner to use for each solve.
std::vector< std::vector< unsigned int > > _off_diag
Holds which off diagonal blocks to compute.
void addSystem(unsigned int var, std::vector< unsigned int > off_diag, libMesh::PreconditionerType type=libMesh::AMG_PRECOND)
Add a diagonal system + possibly off-diagonals ones as well, also specifying type of preconditioning.
virtual void init()
Initialize data structures if not done so already.
virtual unsigned int nVariables() const
Get the number of variables in this system.
unsigned int number() const
Gets the number of this system.
virtual const std::set< SubdomainID > * getVariableBlocks(unsigned int var_number)
Get the block where a variable of this system is defined.
virtual System & add_system(std::string_view system_type, std::string_view name)
NumericVector< Number > * rhs
const SparseMatrix< Number > & get_system_matrix() const
virtual void scale(const T factor)=0
const Parallel::Communicator & _communicator
void set_type(const PreconditionerType pct)
void set_matrix(SparseMatrix< Number > &mat)
PreconditionerType type() const
static std::unique_ptr< Preconditioner< T > > build_preconditioner(const libMesh::Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
void vector_mult_add(NumericVector< T > &dest, const NumericVector< T > &arg) const
SparseMatrix< Number > & add_matrix(std::string_view mat_name, ParallelType type=PARALLEL, MatrixBuildType mat_build_type=MatrixBuildType::AUTOMATIC)
const Variable & variable(unsigned int var) const
bool assemble_before_solve
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
std::unique_ptr< NumericVector< Number > > solution
const std::string & variable_name(const unsigned int i) const
unsigned int variable_number(std::string_view var) const
unsigned int n_vars() const
unsigned int number() const
const FEType & type() const
@ ST_JFNK
Jacobian-Free Newton Krylov.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
auto index_range(const T &sizable)