https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FieldSplitPreconditioner.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 "libmesh/petsc_macro.h"
12
13// MOOSE includes
14#include "FEProblem.h"
15#include "MooseEnum.h"
16#include "MooseVariableFE.h"
17#include "NonlinearSystem.h"
18#include "PetscSupport.h"
19#include "MoosePreconditioner.h"
21#include "Split.h"
22#include "PetscDMMoose.h"
23
24#include "libmesh/libmesh_common.h"
25#include "libmesh/petsc_nonlinear_solver.h"
26#include "libmesh/coupling_matrix.h"
27
28using namespace libMesh;
29
30template <typename Base>
33{
34 InputParameters params = Base::validParams();
35 params.addClassDescription("Preconditioner designed to map onto PETSc's PCFieldSplit.");
36
37 params.addRequiredParam<std::string>(
38 "topsplit", "Entrance to splits, the top split will specify how splits will go.");
39 // We should use full coupling Jacobian matrix by default
40 params.addParam<bool>("full",
41 true,
42 "Set to true if you want the full set of couplings between variables "
43 "simply for convenience so you don't have to set every off_diag_row "
44 "and off_diag_column combination.");
45 return params;
46}
47
48template <typename Base>
50 const InputParameters & parameters)
51 : Base(parameters),
52 _nl(this->_fe_problem.getNonlinearSystemBase(this->_nl_sys_num)),
53 _decomposition_split(this->template getParam<std::string>("topsplit"))
56 mooseError("The field split preconditioner can only be used with PETSc");
57
58 // number of variables
59 unsigned int n_vars = _nl.nVariables();
60 // if we want to construct a full Jacobian?
61 // it is recommended to have a full Jacobian for using
62 // the fieldSplit preconditioner
63 bool full = this->template getParam<bool>("full");
64
65 // how variables couple
66 std::unique_ptr<CouplingMatrix> cm = std::make_unique<CouplingMatrix>(n_vars);
67 if (!full)
68 {
69 if (this->isParamValid("off_diag_row") && this->isParamValid("off_diag_column"))
70 {
71
72 const auto off_diag_rows =
73 this->template getParam<std::vector<NonlinearVariableName>>("off_diag_row");
74 const auto off_diag_columns =
75 this->template getParam<std::vector<NonlinearVariableName>>("off_diag_column");
76
77 // put 1s on diagonal
78 for (unsigned int i = 0; i < n_vars; i++)
79 (*cm)(i, i) = 1;
80
81 // off-diagonal entries
82 std::vector<std::vector<unsigned int>> off_diag(n_vars);
83 if (off_diag_rows.size() * off_diag_columns.size() != 0 &&
84 off_diag_rows.size() == off_diag_columns.size())
85 for (const auto i : index_range(off_diag_rows))
86 {
87 unsigned int row = _nl.getVariable(0, off_diag_rows[i]).number();
88 unsigned int column = _nl.getVariable(0, off_diag_columns[i]).number();
89 (*cm)(row, column) = 1;
90 }
91 }
92 }
93 else
94 {
95 for (unsigned int i = 0; i < n_vars; i++)
96 for (unsigned int j = 0; j < n_vars; j++)
97 (*cm)(i, j) = 1; // full coupling
98 }
99 this->setCouplingMatrix(std::move(cm));
100
101 // turn on a flag
102 _nl.useFieldSplitPreconditioner(this);
103}
104
105template <typename Base>
106void
108{
109 LibmeshPetscCallA(
110 _nl.comm().get(),
111 DMCreateMoose(_nl.comm().get(), _nl, dofMap(), system(), _decomposition_split, dm));
112 LibmeshPetscCallA(_nl.comm().get(),
113 PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix().c_str()));
114 LibmeshPetscCall(DMSetFromOptions(*dm));
115 LibmeshPetscCall(DMSetUp(*dm));
116}
117
119
125
128{
129 std::shared_ptr<Split> top_split = _nl.getSplit(_decomposition_split);
130 top_split->setup(_nl, _nl.prefix());
131}
132
133void
135{
136 PetscBool ismoose;
137 DM dm = LIBMESH_PETSC_NULLPTR;
138
139 // Initialize the part of the DM package that's packaged with Moose; in the PETSc source tree this
140 // call would be in DMInitializePackage()
141 LibmeshPetscCall(DMMooseRegisterAll());
142 // Create and set up the DM that will consume the split options and deal with block matrices.
143 auto * const petsc_solver =
144 libMesh::cast_ptr<PetscNonlinearSolver<Number> *>(_nl.nonlinearSolver());
145 SNES snes = petsc_solver->snes(prefix().c_str());
146 // if there exists a DMMoose object, not to recreate a new one
147 LibmeshPetscCall(SNESGetDM(snes, &dm));
148 if (dm)
149 {
150 LibmeshPetscCall(PetscObjectTypeCompare((PetscObject)dm, DMMOOSE, &ismoose));
151 if (ismoose)
152 return;
153 }
155 LibmeshPetscCall(SNESSetDM(snes, dm));
156 LibmeshPetscCall(DMDestroy(&dm));
157}
158
159const DofMapBase &
161{
162 return _nl.dofMap();
163}
164
165const System &
167{
168 return _nl.system();
169}
170
171std::string
173{
174 return _nl.prefix();
175}
176
177KSP
179{
180 KSP ksp;
181 auto snes = _nl.getSNES();
182 LibmeshPetscCall(SNESGetKSP(snes, &ksp));
183 return ksp;
184}
185
registerMooseObjectAliased("MooseApp", FieldSplitPreconditioner, "FSP")
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
PetscErrorCode PetscOptionItems *PetscErrorCode DM dm
PetscErrorCode DMCreateMoose(MPI_Comm comm, NonlinearSystemBase &nl, const libMesh::DofMapBase &dof_map, const libMesh::System &system, const std::string &dm_name, DM *dm)
Create a MOOSE DM.
PetscErrorCode DMMooseRegisterAll()
unsigned int n_vars
Implements a preconditioner designed to map onto PETSc's PCFieldSplit.
FieldSplitPreconditionerTempl(const InputParameters &parameters)
static InputParameters validParams()
Constructor.
NonlinearSystemBase & _nl
The nonlinear system this FSP is associated with (convenience reference)
void createMooseDM(DM *dm)
creates the MOOSE data management object
virtual void setupDM() override
setup the data management data structure that manages the field split
virtual const libMesh::System & system() const override
virtual std::string prefix() const override
static InputParameters validParams()
virtual const libMesh::DofMapBase & dofMap() const override
FieldSplitPreconditioner(const InputParameters &parameters)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
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.
Base class for MOOSE preconditioners.
virtual SNES getSNES()=0
std::shared_ptr< Split > getSplit(const std::string &name)
Retrieves a split by name.
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver()=0
virtual libMesh::System & system() override
Get the reference to the libMesh system.
std::string prefix() const
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
auto index_range(const T &sizable)
SolverPackage default_solver_package()