ThunderEgg  1.0.0
PCShellCreator.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) 2020-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_PCSHELLCREATOR_H
22 #define THUNDEREGG_PETSC_PCSHELLCREATOR_H
23 
29 #include <petscpc.h>
30 namespace ThunderEgg::PETSc {
36 template<int D>
38 {
39 private:
43  std::shared_ptr<const Operator<D>> op;
47  Mat A;
48  std::function<Vector<D>()> getNewVector;
56  PCShellCreator(const Operator<D>& op, Mat A, const std::function<Vector<D>()>& vector_allocator)
57  : op(op.clone())
58  , A(A)
59  , getNewVector(vector_allocator)
60  {}
61  PCShellCreator(const PCShellCreator&) = delete;
62  PCShellCreator& operator=(const PCShellCreator&) = delete;
63  PCShellCreator(PCShellCreator&&) noexcept = delete;
64  PCShellCreator& operator=(PCShellCreator&&) noexcept = delete;
68  ~PCShellCreator() { MatDestroy(&A); }
77  static int applyPC(PC A, Vec x, Vec b)
78  {
79  PCShellCreator<D>* psc = nullptr;
80  PCShellGetContext(A, (void**)&psc);
81 
82  Vector<D> te_x = psc->getNewVector();
83  Vector<D> te_b = psc->getNewVector();
84 
85  // petsc vectors don't have gost padding for patchs, so this is neccesary
86  const double* x_view;
87  VecGetArrayRead(x, &x_view);
88  int index = 0;
89  for (int p_index = 0; p_index < te_x.getNumLocalPatches(); p_index++) {
90  for (int c = 0; c < te_x.getNumComponents(); c++) {
91  ComponentView<double, D> ld = te_x.getComponentView(c, p_index);
92  Loop::Nested<D>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D>& coord) {
93  ld[coord] = x_view[index];
94  index++;
95  });
96  }
97  }
98 
99  VecRestoreArrayRead(x, &x_view);
100 
101  psc->op->apply(te_x, te_b);
102 
103  double* b_view;
104  VecGetArray(b, &b_view);
105  index = 0;
106  for (int p_index = 0; p_index < te_b.getNumLocalPatches(); p_index++) {
107  for (int c = 0; c < te_x.getNumComponents(); c++) {
108  ComponentView<const double, D> ld = te_b.getComponentView(c, p_index);
109  Loop::Nested<D>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D>& coord) {
110  b_view[index] = ld[coord];
111  index++;
112  });
113  }
114  }
115  VecRestoreArray(b, &b_view);
116 
117  return 0;
118  }
125  static int destroyPC(PC A)
126  {
127  PCShellCreator<D>* psc = nullptr;
128  PCShellGetContext(A, (void**)&psc);
129  delete psc;
130  return 0;
131  }
132 
133 public:
142  static PC GetNewPCShell(const Operator<D>& prec,
143  const Operator<D>& op,
144  const std::function<Vector<D>()>& vector_allocator)
145  {
146  Mat A = MatShellCreator<D>::GetNewMatShell(op, vector_allocator);
147  PCShellCreator<D>* psc = new PCShellCreator(prec, A, vector_allocator);
148  PC P;
149  PCCreate(MPI_COMM_WORLD, &P);
150  PCSetType(P, PCSHELL);
151  PCShellSetContext(P, psc);
152  PCShellSetApply(P, applyPC);
153  PCShellSetDestroy(P, destroyPC);
154  PCSetOperators(P, A, A);
155  return P;
156  }
157 };
158 } // namespace ThunderEgg::PETSc
159 #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
A collection of wrappers for operating with PETSc.
Definition: KSPSolver.h:35
ThunderEgg::Operator::clone
virtual Operator< D > * clone() const =0
Clone this operator.
ThunderEgg::ComponentView< double, D >
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::PETSc::PCShellCreator
Wraps an Operator for use as a PETSc PC.
Definition: PCShellCreator.h:37
ThunderEgg::Operator
Base class for operators.
Definition: Operator.h:37
ThunderEgg::Vector
Vector class for use in thunderegg.
Definition: Vector.h:42
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