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"
42 "The order the block rows will be solved in. Put the name of variables here "
43 "to stand for solving that variable's block row. A variable may appear more "
44 "than once (to create cylces if you like).");
45 params.
addRequiredParam<std::vector<std::string>>(
"preconditioner",
"TODO: docstring");
47 params.
addParam<std::vector<std::string>>(
49 "The off diagonal row you want to add into the matrix, it will be associated "
50 "with an off diagonal column from the same position in off_diag_colum.");
51 params.
addParam<std::vector<std::string>>(
"off_diag_column",
52 "The off diagonal column you want to add into the "
53 "matrix, it will be associated with an off diagonal "
54 "row from the same position in off_diag_row.");
62 _nl(_fe_problem.getNonlinearSystemBase()),
63 _init_timer(registerTimedSection(
"init", 2)),
64 _apply_timer(registerTimedSection(
"apply", 1))
66 unsigned int num_systems =
_nl.
system().n_vars();
79 std::unique_ptr<CouplingMatrix> cm = libmesh_make_unique<CouplingMatrix>(n_vars);
86 for (
unsigned int i = 0; i < n_vars; i++)
90 std::vector<std::vector<unsigned int>> off_diag(n_vars);
91 for (
unsigned int i = 0; i < getParam<std::vector<std::string>>(
"off_diag_row").size(); i++)
97 (*cm)(row, column) = 1;
104 for (
unsigned int i = 0; i < n_vars; i++)
105 for (
unsigned int j = 0; j < n_vars; j++)
113 const std::vector<std::string> & pc_types = getParam<std::vector<std::string>>(
"preconditioner");
114 for (
unsigned int i = 0; i < num_systems; i++)
115 _pre_type[i] = Utility::string_to_enum<PreconditionerType>(pc_types[i]);
118 const std::vector<std::string> & solve_order = getParam<std::vector<std::string>>(
"solve_order");
120 for (
unsigned int i = 0; i < solve_order.size(); i++)
124 unsigned int n_vars =
_nl.
system().n_vars();
127 const std::vector<std::string> & odr = getParam<std::vector<std::string>>(
"off_diag_row");
128 const std::vector<std::string> & odc = getParam<std::vector<std::string>>(
"off_diag_column");
129 std::vector<std::vector<unsigned int>> off_diag(n_vars);
130 for (
unsigned int i = 0; i < odr.size(); i++)
132 unsigned int row =
_nl.
system().variable_number(odr[i]);
133 unsigned int column =
_nl.
system().variable_number(odc[i]);
134 off_diag[row].push_back(column);
137 for (
unsigned int var = 0; var < n_vars; var++)
143 mooseError(
"PBP must be used with JFNK solve type");
150 std::vector<unsigned int> off_diag,
151 PreconditionerType
type)
153 std::string var_name =
_nl.
system().variable_name(var);
155 LinearImplicitSystem & precond_system =
156 _fe_problem.
es().add_system<LinearImplicitSystem>(var_name +
"_system");
157 precond_system.assemble_before_solve =
false;
160 precond_system.add_variable(
161 var_name +
"_prec",
_nl.
system().variable(var).type(), active_subdomains);
167 for (
unsigned int i = 0; i < off_diag.size(); i++)
182 _is_initialized =
true;
184 const unsigned int num_systems =
_systems.size();
190 for (
unsigned int i = 0; i < num_systems; i++)
195 for (
unsigned int system_var = 0; system_var < num_systems; system_var++)
197 LinearImplicitSystem & u_system = *
_systems[system_var];
201 Preconditioner<Number>::build_preconditioner(MoosePreconditioner::_communicator);
205 Preconditioner<Number> * preconditioner =
_preconditioners[system_var].get();
206 preconditioner->set_matrix(*u_system.matrix);
207 preconditioner->set_type(
_pre_type[system_var]);
209 preconditioner->init();
216 const unsigned int num_systems =
_systems.size();
218 std::vector<JacobianBlock *> blocks;
221 for (
unsigned int system_var = 0; system_var < num_systems; system_var++)
223 LinearImplicitSystem & u_system = *
_systems[system_var];
227 blocks.push_back(block);
230 for (
unsigned int diag = 0; diag <
_off_diag[system_var].size(); diag++)
232 unsigned int coupled_var =
_off_diag[system_var][diag];
233 std::string coupled_name =
_nl.
system().variable_name(coupled_var);
237 blocks.push_back(block);
244 for (
auto & block : blocks)
253 const unsigned int num_systems =
_systems.size();
258 for (
unsigned int sys = 0; sys < num_systems; sys++)
266 LinearImplicitSystem & u_system = *
_systems[system_var];
270 mesh,
_nl.
system().number(), system_var,
x, u_system.number(), 0, *u_system.rhs);
274 for (
unsigned int diag = 0; diag <
_off_diag[system_var].size(); diag++)
276 unsigned int coupled_var =
_off_diag[system_var][diag];
277 LinearImplicitSystem & coupled_system = *
_systems[coupled_var];
278 SparseMatrix<Number> & off_diag = *
_off_diag_mats[system_var][diag];
279 NumericVector<Number> & rhs = *u_system.rhs;
286 off_diag.vector_mult_add(rhs, *coupled_system.solution);
300 for (
unsigned int system_var = 0; system_var < num_systems; system_var++)
302 LinearImplicitSystem & u_system = *
_systems[system_var];
305 mesh, u_system.number(), 0, *u_system.solution,
_nl.
system().number(), system_var, y);