ThunderEgg  1.0.0
KSPSolver.h
Go to the documentation of this file.
1 /***************************************************************************
2  * ThunderEgg, a library for solvers on adaptively refined block-structured
3  * Cartesian grids.
4  *
5  * Copyright (c) 2021 Scott Aiton
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  ***************************************************************************/
20 
21 #ifndef THUNDEREGG_PETSC_KSPSOLVER_H
22 #define THUNDEREGG_PETSC_KSPSOLVER_H
23 
32 #include <petscksp.h>
33 #include <petscmat.h>
34 
35 namespace ThunderEgg::PETSc {
39 template<int D>
40 class KSPSolver : public Iterative::Solver<D>
41 {
42 private:
46  KSPType type = KSPGMRES;
53  Vec getPetscVecWithoutGhost(const Vector<D>& vec) const
54  {
55  Vec petsc_vec;
56  VecCreateMPI(vec.getCommunicator().getMPIComm(),
57  vec.getNumLocalCells() * vec.getNumComponents(),
58  PETSC_DETERMINE,
59  &petsc_vec);
60  return petsc_vec;
61  }
68  void copyToPetscVec(const Vector<D>& vec, Vec petsc_vec) const
69  {
70  double* petsc_vec_view;
71  size_t curr_index = 0;
72  VecGetArray(petsc_vec, &petsc_vec_view);
73  for (int i = 0; i < vec.getNumLocalPatches(); i++) {
74  for (int c = 0; c < vec.getNumComponents(); c++) {
76  nested_loop<D>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D>& coord) {
77  petsc_vec_view[curr_index] = ld[coord];
78  curr_index++;
79  });
80  }
81  }
82  VecRestoreArray(petsc_vec, &petsc_vec_view);
83  }
90  void copyToVec(Vec petsc_vec, Vector<D>& vec) const
91  {
92  const double* petsc_vec_view;
93  size_t curr_index = 0;
94  VecGetArrayRead(petsc_vec, &petsc_vec_view);
95  for (int i = 0; i < vec.getNumLocalPatches(); i++) {
96  for (int c = 0; c < vec.getNumComponents(); c++) {
98  nested_loop<D>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D>& coord) {
99  ld[coord] = petsc_vec_view[curr_index];
100  curr_index++;
101  });
102  }
103  }
104  VecRestoreArrayRead(petsc_vec, &petsc_vec_view);
105  }
112  void destroyPetscVec(const Vector<D>& vec, Vec petsc_vec) const { VecDestroy(&petsc_vec); }
113  static int MonitorResidual(KSP ksp, PetscInt n, PetscReal rnorm, std::ostream* os)
114  {
115  char buf[100];
116  sprintf(buf, "%5d %16.8e\n", n, rnorm);
117  (*os) << std::string(buf);
118  return 0;
119  }
120 
121 public:
129  explicit KSPSolver() {}
130 
131  KSPSolver<D>* clone() const override { return new KSPSolver<D>(*this); }
132 
133  void setType(KSPType new_type) { type = new_type; }
134  int solve(const Operator<D>& A,
135  Vector<D>& x,
136  const Vector<D>& b,
137  const Operator<D>* Mr = nullptr,
138  bool output = false,
139  std::ostream& os = std::cout) const override
140  {
141  Mat A_PETSC = MatShellCreator<D>::GetNewMatShell(A, [&]() { return x.getZeroClone(); });
142 
143  PC Mr_PETSC = nullptr;
144  if (Mr != nullptr) {
145  Mr_PETSC = PCShellCreator<D>::GetNewPCShell(*Mr, A, [&]() { return x.getZeroClone(); });
146  }
147  Vec x_PETSC = getPetscVecWithoutGhost(x);
148  copyToPetscVec(x, x_PETSC);
149 
150  Vec b_PETSC = getPetscVecWithoutGhost(x);
151  copyToPetscVec(b, b_PETSC);
152 
153  KSP ksp;
154  KSPCreate(PETSC_COMM_WORLD, &ksp);
155  KSPSetType(ksp, type);
156  KSPSetOperators(ksp, A_PETSC, A_PETSC);
157 
158  if (Mr != nullptr) {
159  KSPSetPC(ksp, Mr_PETSC);
160  // KSPSetPCSide(ksp, PC_RIGHT);
161  }
162 
163  if (output) {
164  KSPMonitorSet(
165  ksp, (PetscErrorCode(*)(KSP, PetscInt, PetscReal, void*)) & MonitorResidual, &os, nullptr);
166  }
167 
168  KSPSolve(ksp, b_PETSC, x_PETSC);
169 
170  int iterations;
171  KSPGetIterationNumber(ksp, &iterations);
172 
173  const char* converged_reason;
174  KSPGetConvergedReasonString(ksp, &converged_reason);
175  os << converged_reason << std::endl;
176 
177  KSPDestroy(&ksp);
178  VecDestroy(&x_PETSC);
179  VecDestroy(&b_PETSC);
180  PCDestroy(&Mr_PETSC);
181  MatDestroy(&A_PETSC);
182  return iterations;
183  }
184 };
185 } // namespace ThunderEgg::PETSc
186 #endif
ThunderEgg::Vector::getComponentView
ComponentView< double, D > getComponentView(int component_index, int patch_local_index)
Get the ComponentView for the specified patch and component.
Definition: Vector.h:336
ThunderEgg::PETSc::KSPSolver::solve
int solve(const Operator< D > &A, Vector< D > &x, const Vector< D > &b, const Operator< D > *Mr=nullptr, bool output=false, std::ostream &os=std::cout) const override
Perform an iterative solve.
Definition: KSPSolver.h:134
PCShellCreator.h
PCShellCreator class.
ThunderEgg::PETSc::KSPSolver::KSPSolver
KSPSolver()
Construct a new MatWrapper object.
Definition: KSPSolver.h:129
ThunderEgg::PETSc
A collection of wrappers for operating with PETSc.
Definition: KSPSolver.h:35
ThunderEgg::PETSc::KSPSolver::clone
KSPSolver< D > * clone() const override
Clone this solver.
Definition: KSPSolver.h:131
ThunderEgg::Vector::getCommunicator
const Communicator & getCommunicator() const
get the MPI Comm that this vector uses
Definition: Vector.h:311
ThunderEgg::ComponentView
Array for acessing data of a patch. It supports variable striding.
Definition: ComponentView.h:38
Solver.h
Solver class.
ThunderEgg::Vector::getNumLocalCells
int getNumLocalCells() const
Get the number of local cells int he vector (excluding ghost cells)
Definition: Vector.h:322
ThunderEgg::View::getEnd
const std::array< int, D > & getEnd() const
Get the coordinate of the last element.
Definition: View.h:211
ThunderEgg::PETSc::MatShellCreator::GetNewMatShell
static Mat GetNewMatShell(const Operator< D > &op, const std::function< Vector< D >()> &vector_allocator)
Get a new MatShell for use with PETSc.
Definition: MatShellCreator.h:132
ThunderEgg::PETSc::PCShellCreator::GetNewPCShell
static PC GetNewPCShell(const Operator< D > &prec, const Operator< D > &op, const std::function< Vector< D >()> &vector_allocator)
Construct a new PCShell object.
Definition: PCShellCreator.h:142
ThunderEgg::Operator
Base class for operators.
Definition: Operator.h:37
ThunderEgg::Iterative::Solver
Abstract interface for Iterative solvers.
Definition: Solver.h:39
ThunderEgg::Vector
Vector class for use in thunderegg.
Definition: Vector.h:42
ThunderEgg::PETSc::KSPSolver
Wraps a PETSc KSP solver for use use as a Solver.
Definition: KSPSolver.h:40
ThunderEgg::Vector::getZeroClone
Vector< D > getZeroClone() const
Get a vector of the same length initialized to zero.
Definition: Vector.h:601
ThunderEgg::Vector::getNumLocalPatches
int getNumLocalPatches() const
Get the number of local patches.
Definition: Vector.h:316
MatShellCreator.h
MatShellCreator class.
ThunderEgg::View::getStart
const std::array< int, D > & getStart() const
Get the coordinate of the first element.
Definition: View.h:207