ThunderEgg  1.0.0
MatShellCreator.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_MATSHELLCREATOR_H
22 #define THUNDEREGG_PETSC_MATSHELLCREATOR_H
23 
28 #include <ThunderEgg/Operator.h>
29 #include <petscmat.h>
30 namespace ThunderEgg::PETSc {
36 template<int D>
38 {
39 private:
43  std::shared_ptr<const Operator<D>> op;
44 
48  std::function<Vector<D>()> getNewVector;
49 
55  explicit MatShellCreator(const Operator<D>& op,
56  const std::function<Vector<D>()>& vector_allocator)
57  : op(op.clone())
58  , getNewVector(vector_allocator)
59  {}
68  static int applyMat(Mat A, Vec x, Vec b)
69  {
70  MatShellCreator<D>* msc = nullptr;
71  MatShellGetContext(A, &msc);
72 
73  Vector<D> te_x = msc->getNewVector();
74  Vector<D> te_b = msc->getNewVector();
75 
76  // petsc vectors don't have gost padding for patchs, so this is neccesary
77  const double* x_view;
78  VecGetArrayRead(x, &x_view);
79  int index = 0;
80  for (int p_index = 0; p_index < te_x.getNumLocalPatches(); p_index++) {
81  for (int c = 0; c < te_x.getNumComponents(); c++) {
82  ComponentView<double, D> ld = te_x.getComponentView(c, p_index);
83  Loop::Nested<D>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D>& coord) {
84  ld[coord] = x_view[index];
85  index++;
86  });
87  }
88  }
89 
90  VecRestoreArrayRead(x, &x_view);
91 
92  msc->op->apply(te_x, te_b);
93 
94  double* b_view;
95  VecGetArray(b, &b_view);
96  index = 0;
97  for (int p_index = 0; p_index < te_b.getNumLocalPatches(); p_index++) {
98  for (int c = 0; c < te_b.getNumComponents(); c++) {
99  const ComponentView<const double, D> ld = te_b.getComponentView(c, p_index);
100  Loop::Nested<D>(ld.getStart(), ld.getEnd(), [&](const std::array<int, D>& coord) {
101  b_view[index] = ld[coord];
102  index++;
103  });
104  }
105  }
106  VecRestoreArray(b, &b_view);
107 
108  return 0;
109  }
116  static int destroyMat(Mat A)
117  {
118  MatShellCreator<D>* msc = nullptr;
119  MatShellGetContext(A, &msc);
120  delete msc;
121  return 0;
122  }
123 
124 public:
132  static Mat GetNewMatShell(const Operator<D>& op,
133  const std::function<Vector<D>()>& vector_allocator)
134  {
135  MatShellCreator<D>* msc = new MatShellCreator(op, vector_allocator);
136  Vector<D> vec = vector_allocator();
137  int m = vec.getNumLocalCells() * vec.getNumComponents();
138  Mat A;
139  MatCreateShell(MPI_COMM_WORLD, m, m, PETSC_DETERMINE, PETSC_DETERMINE, msc, &A);
140  MatShellSetOperation(A, MATOP_MULT, (void (*)(void))applyMat);
141  MatShellSetOperation(A, MATOP_DESTROY, (void (*)(void))destroyMat);
142  return A;
143  }
144 };
145 } // namespace ThunderEgg::PETSc
146 #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.
Operator.h
Operator class.
ThunderEgg::ComponentView< double, D >
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::Operator
Base class for operators.
Definition: Operator.h:37
ThunderEgg::Vector
Vector class for use in thunderegg.
Definition: Vector.h:42
ThunderEgg::PETSc::MatShellCreator
Wraps an Operator for use as a PETSc Mat.
Definition: MatShellCreator.h:37
ThunderEgg::Vector::getNumLocalPatches
int getNumLocalPatches() const
Get the number of local patches.
Definition: Vector.h:316
ThunderEgg::View::getStart
const std::array< int, D > & getStart() const
Get the coordinate of the first element.
Definition: View.h:207