https://mooseframework.inl.gov
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 
28 using namespace libMesh;
29 
30 template <typename Base>
33 {
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 
48 template <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"))
54 {
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
103 }
104 
105 template <typename Base>
106 void
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 
122 {
124 }
125 
128 {
129  std::shared_ptr<Split> top_split = _nl.getSplit(_decomposition_split);
130  top_split->setup(_nl, _nl.prefix());
131 }
132 
133 void
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  }
154  createMooseDM(&dm);
155  LibmeshPetscCall(SNESSetDM(snes, dm));
156  LibmeshPetscCall(DMDestroy(&dm));
157 }
158 
159 const DofMapBase &
161 {
162  return _nl.dofMap();
163 }
164 
165 const System &
167 {
168  return _nl.system();
169 }
170 
171 std::string
173 {
174  return _nl.prefix();
175 }
176 
177 KSP
179 {
180  KSP ksp;
181  auto snes = _nl.getSNES();
182  LibmeshPetscCall(SNESGetKSP(snes, &ksp));
183  return ksp;
184 }
185 
FieldSplitPreconditionerTempl(const InputParameters &parameters)
virtual const libMesh::System & system() const override
NonlinearSystemBase & _nl
The nonlinear system this FSP is associated with (convenience reference)
static InputParameters validParams()
Constructor.
virtual SNES getSNES()=0
virtual void setupDM() override
setup the data management data structure that manages the field split
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:333
unsigned int number() const
Get variable number coming from libMesh.
FieldSplitPreconditioner(const InputParameters &parameters)
PetscErrorCode PetscOptionItems *PetscErrorCode DM dm
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver()=0
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
InputParameters validParams()
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...
Base class for MOOSE preconditioners.
virtual unsigned int nVariables() const
Get the number of variables in this system.
Definition: SystemBase.C:883
SolverPackage default_solver_package()
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:1155
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.
unsigned int n_vars
virtual const libMesh::DofMapBase & dofMap() const override
Implements a preconditioner designed to map onto PETSc&#39;s PCFieldSplit.
std::shared_ptr< Split > getSplit(const std::string &name)
Retrieves a split by name.
virtual std::string prefix() const override
std::string _decomposition_split
The decomposition split.
void createMooseDM(DM *dm)
creates the MOOSE data management object
static InputParameters validParams()
std::string prefix() const
Definition: SystemBase.C:1705
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...
registerMooseObjectAliased("MooseApp", FieldSplitPreconditioner, "FSP")
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...
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:90
PetscErrorCode DMMooseRegisterAll()
void useFieldSplitPreconditioner(FieldSplitPreconditionerBase *fsp)
If called with a non-null object true this system will use a field split preconditioner matrix...
auto index_range(const T &sizable)
virtual libMesh::System & system() override
Get the reference to the libMesh system.