/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/timestepping/linear_solver/PETScKrylov.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/timestepping/linear_solver/PETScKrylov.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
PETScKrylov.hh
Go to the documentation of this file.
1#pragma once
2
3// external libraries
4#include <deal.II/base/config.h>
5
6#ifdef DEAL_II_WITH_PETSC
7
8#include <deal.II/lac/petsc_precondition.h>
9#include <deal.II/lac/petsc_solver.h>
10#include <deal.II/lac/solver_control.h>
11
12// standard library
13#include <stdexcept>
14
15// DiFfRG
17
18namespace DiFfRG
19{
20 namespace internal
21 {
34#ifdef DEAL_II_PETSC_WITH_HYPRE
35 using PETScDefaultPreconditioner = dealii::PETScWrappers::PreconditionBoomerAMG;
36#else
37 using PETScDefaultPreconditioner = dealii::PETScWrappers::PreconditionBlockJacobi;
38#endif
39
43 template <typename PreconditionerType> typename PreconditionerType::AdditionalData precondition_settings()
44 {
45 return typename PreconditionerType::AdditionalData();
46 }
47
48#ifdef DEAL_II_PETSC_WITH_HYPRE
67 template <>
68 inline dealii::PETScWrappers::PreconditionBoomerAMG::AdditionalData
69 precondition_settings<dealii::PETScWrappers::PreconditionBoomerAMG>()
70 {
71 using AMG = dealii::PETScWrappers::PreconditionBoomerAMG;
72 AMG::AdditionalData data;
73 data.relaxation_type_coarse = AMG::AdditionalData::RelaxationType::SORJacobi;
74 return data;
75 }
76#endif
77 } // namespace internal
78
97 template <typename SparseMatrixType, typename VectorType,
98 typename PreconditionerType = internal::PETScDefaultPreconditioner>
99 class PETScKrylov : public AbstractLinearSolver<SparseMatrixType, VectorType>
100 {
101 public:
102 static constexpr bool performs_factorization = false;
103
104 PETScKrylov() : matrix(nullptr) {}
105
106 void init(const SparseMatrixType &matrix)
107 {
108 this->matrix = &matrix;
109 // Rebuilding the preconditioner on every Jacobian is deliberate: IDA hands us a new
110 // Jacobian only when it has decided the old one is stale, so reusing a preconditioner
111 // across init() calls would be reusing it across exactly the changes it exists to track.
112 preconditioner.initialize(matrix, internal::precondition_settings<PreconditionerType>());
113 }
114
115 bool invert() { return false; }
116
117 int solve(const VectorType &src, VectorType &dst, const double tol)
118 {
119 if (!matrix) throw std::runtime_error("PETScKrylov::solve: matrix not initialized");
120
121 // Same iteration cap as the serial GMRES wrapper. src.size() is the *global* size for a
122 // PETSc vector, which is what we want here -- the cap should not depend on rank count.
123 dealii::SolverControl solver_control(std::max<std::size_t>(1000, src.size() / 10), tol);
124 dealii::PETScWrappers::SolverGMRES solver(solver_control);
125
126 try {
127 solver.solve(*matrix, dst, src, preconditioner);
128 } catch (std::exception &e) {
129 std::cerr << "PETSc GMRES linear solver failed: " << e.what() << std::endl;
130 throw;
131 }
132
133 return solver_control.last_step();
134 }
135
136 private:
137 const SparseMatrixType *matrix;
138 PreconditionerType preconditioner;
139 };
140} // namespace DiFfRG
141
142#endif // DEAL_II_WITH_PETSC
Definition complex_math.hh:10