AMDiS  2.10
The Adaptive Multi-Dimensional Simulation Toolbox
VectorBackend.hpp
1 #pragma once
2 
3 #include <petscvec.h>
4 
5 #include <dune/common/ftraits.hh>
6 #include <dune/common/rangeutilities.hh>
7 #include <dune/common/shared_ptr.hh>
8 #include <dune/functions/common/multiindex.hh>
9 
10 #include <amdis/Output.hpp>
11 #include <amdis/algorithm/ForEach.hpp>
12 #include <amdis/algorithm/InnerProduct.hpp>
13 #include <amdis/algorithm/Transform.hpp>
14 #include <amdis/common/FakeContainer.hpp>
15 #include <amdis/operations/Assigner.hpp>
16 #include <amdis/typetree/MultiIndex.hpp>
17 
18 namespace AMDiS
19 {
21  template <class DofMap>
23  {
24  template <class A>
25  using AssignMode = std::conditional_t<std::is_same_v<A,Assigner::plus_assign>,
26  std::integral_constant<::InsertMode, ADD_VALUES>,
27  std::integral_constant<::InsertMode, INSERT_VALUES>>;
28 
29  public:
31  using BaseVector = ::Vec;
32 
34  using value_type = PetscScalar;
35 
37  using size_type = PetscInt;
38 
39  public:
41  explicit PetscVector(DofMap const& dofMap)
42  : dofMap_(dofMap)
43  {}
44 
47  : dofMap_(other.dofMap_)
48  {
49  swap(*this, other);
50  }
51 
53  PetscVector(PetscVector const& other)
54  : dofMap_(other.dofMap_)
55  , initialized_(other.initialized_)
56  {
57  if (other.initialized_) {
58  VecDuplicate(other.vector_, &vector_);
59  VecCopy(other.vector_, vector_);
60  }
61  }
62 
65  {
66  destroy();
67  }
68 
71  {
72  swap(*this, other);
73  return *this;
74  }
75 
78  {
79  return *this = PetscVector(other);
80  }
81 
83  BaseVector const& vector() const
84  {
85  return vector_;
86  }
87 
90  {
91  return vector_;
92  }
93 
95  std::size_t localSize() const
96  {
97  return dofMap_.localSize();
98  }
99 
101  std::size_t globalSize() const
102  {
103  return dofMap_.globalSize();
104  }
105 
107  // [[possibly collective]]
108  template <class Basis>
109  void init(Basis const&, bool clear)
110  {
111  Dune::Timer t;
112  if (initialized_)
113  destroy();
114 
115  // create the vector
116  create();
117  info(3, " create new vector needed {} seconds", t.elapsed());
118  t.reset();
119 
120  if (clear)
121  setZero();
122 
123  initialized_ = true;
124  }
125 
127  // [[collective]]
128  void finish()
129  {
130  Dune::Timer t;
131  VecAssemblyBegin(vector_);
132  VecAssemblyEnd(vector_);
133  info(3, " finish vector assembly needed {} seconds", t.elapsed());
134  }
135 
137  // [[collective]]
138  void synchronize()
139  {
140  Dune::Timer t;
141  VecGhostUpdateBegin(vector_, INSERT_VALUES, SCATTER_FORWARD);
142  VecGhostUpdateEnd(vector_, INSERT_VALUES, SCATTER_FORWARD);
143  info(3, " synchronize vector needed {} seconds", t.elapsed());
144  }
145 
147  // [[not collective]]
148  template <class MultiIndex>
149  PetscScalar at(MultiIndex const& idx) const
150  {
151  PetscScalar y = 0;
152  gather(std::array<MultiIndex,1>{idx}, &y);
153  return y;
154  }
155 
157  // [[not collective]]
158  template <class MultiIndex, class Assign>
159  void insert(MultiIndex const& dof, PetscScalar value, Assign)
160  {
161  assert(initialized_);
162  VecSetValue(vector_, dofMap_.global(flatMultiIndex(dof)), value, AssignMode<Assign>::value);
163  }
164 
166  // [[not collective]]
167  template <class IndexRange, class OutputIterator>
168  void gather(IndexRange const& localInd, OutputIterator buffer) const
169  {
170  forEach(localInd, [&buffer](auto&&, auto const& value) { *buffer = value; ++buffer; });
171  }
172 
174 
178  // [[not collective]]
179  template <class IndexRange, class LocalValues, class MaskRange, class Assign>
180  void scatter(IndexRange const& localInd, LocalValues const& localVal, MaskRange const& mask, Assign)
181  {
182  if constexpr(not std::is_same_v<typename LocalValues::value_type, PetscScalar>)
183  {
184  std::vector<PetscScalar> newLocalVal(localVal.begin(), localVal.end());
185  scatter(localInd, newLocalVal, mask, Assign{});
186  return;
187  }
188 
189  assert(initialized_);
190  assert(localInd.size() == localVal.size());
191 
192  // map local to global indices
193  std::vector<PetscInt> globalInd;
194  globalInd.reserve(localInd.size());
195 
196  auto ind_it = std::begin(localInd);
197  auto mask_it = std::begin(mask);
198  for (; ind_it != std::end(localInd); ++mask_it, ++ind_it)
199  globalInd.push_back(*mask_it ? dofMap_.global(flatMultiIndex(*ind_it)) : -1);
200 
201  if (!std::is_same_v<MaskRange, FakeContainer<bool,true>>)
202  VecSetOption(vector_, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
203 
204  VecSetValues(vector_, globalInd.size(), globalInd.data(), localVal.data(), AssignMode<Assign>::value);
205  VecSetOption(vector_, VEC_IGNORE_NEGATIVE_INDICES, PETSC_FALSE);
206  }
207 
209  // [[not collective]]
210  template <class IndexRange, class Func>
211  void forEach(IndexRange const& localInd, Func&& f) const
212  {
213  // Obtains the local ghosted representation of a parallel vector
214  Vec localGhostedVec = nullptr;
215  VecGhostGetLocalForm(vector_, &localGhostedVec);
216  assert(localGhostedVec != nullptr);
217 
218  // A pointer to a contiguous array that contains this processor's portion of the vector data.
219  PetscScalar* ptr;
220  VecGetArray(localGhostedVec, &ptr);
221 
222  for (auto const& dof : localInd)
223  {
224  size_type i = flatMultiIndex(dof);
225  if (dofMap_.owner(i)) {
226  // the index is a purely local entry
227  f(dof, ptr[dofMap_.dofToLocal(i)]);
228  }
229  else {
230  // ghost entries are stored at the end of the array
231  f(dof, ptr[dofMap_.localSize() + dofMap_.dofToGhost(i)]);
232  }
233  }
234 
235  VecRestoreArray(localGhostedVec, &ptr);
236  VecGhostRestoreLocalForm(vector_, &localGhostedVec);
237  }
238 
240  // [[not collective]]
241  template <class Func>
242  void forEachLocal(Func&& f) const
243  {
244  // A pointer to a contiguous array that contains this processor's portion of the vector data.
245  PetscScalar const* ptr;
246  VecGetArrayRead(vector_, &ptr);
247 
248  for (size_type i = 0; i < size_type(localSize()); ++i)
249  f(ptr[dofMap_.dofToLocal(i)]);
250 
251  VecRestoreArrayRead(vector_, &ptr);
252  }
253 
255  // [[mutable]]
256  // [[not collective]]
257  template <class Func>
258  void forEachLocal(Func&& f)
259  {
260  // A pointer to a contiguous array that contains this processor's portion of the vector data.
261  PetscScalar *ptr;
262  VecGetArray(vector_, &ptr);
263 
264  for (size_type i = 0; i < size_type(localSize()); ++i)
265  f(ptr[dofMap_.dofToLocal(i)]);
266 
267  VecRestoreArray(vector_, &ptr);
268  }
269 
271  // [[not collective]]
272  template <class Operation, class... VecIns>
273  static void transformLocal(PetscVector& vecOut, Operation op, VecIns const&... vecIn)
274  {
275  PetscScalar *ptrOut;
276  std::array<PetscScalar const*,sizeof...(VecIns)> ptrsIn{};
277 
278  // Obtain ptrs to internal local arrays
279  VecGetArray(vecOut.vector_, &ptrOut);
280  Ranges::forIndices<sizeof...(VecIns)>([&](auto ii) {
281  VecGetArrayRead(std::get<ii>(std::tie(vecIn...)).vector_, &ptrsIn[ii]);
282  });
283 
284  for (size_type i = 0; i < size_type(vecOut.localSize()); ++i) {
285  auto idx = vecOut.dofMap_.dofToLocal(i);
286  Ranges::applyIndices<sizeof...(VecIns)>([&](auto... ii) {
287  ptrOut[idx] = op(ptrsIn[ii][idx]...);
288  });
289  }
290 
291  // Restore array obtained with VecGetArray[Read]()
292  VecRestoreArray(vecOut.vector_, &ptrOut);
293  Ranges::forIndices<sizeof...(VecIns)>([&](auto ii) {
294  VecRestoreArrayRead(std::get<ii>(std::tie(vecIn...)).vector_, &ptrsIn[ii]);
295  });
296  }
297 
299  // [[not collective]]
300  template <class T, class BinOp1, class BinOp2>
301  static T innerProductLocal(PetscVector const& in1, PetscVector const& in2, T init, BinOp1 op1, BinOp2 op2)
302  {
303  PetscScalar const* ptr1;
304  PetscScalar const* ptr2;
305 
306  // Obtain ptrs to internal local arrays
307  VecGetArrayRead(in1.vector_, &ptr1);
308  VecGetArrayRead(in2.vector_, &ptr2);
309 
310  for (size_type i = 0; i < size_type(in1.localSize()); ++i) {
311  auto idx = in1.dofMap_.dofToLocal(i);
312  init = op1(std::move(init), op2(ptr1[idx], ptr2[idx]));
313  }
314 
315  // Restore array obtained with VecGetArrayRead()
316  VecRestoreArrayRead(in1.vector_, &ptr1);
317  VecRestoreArrayRead(in2.vector_, &ptr2);
318 
319  return init;
320  }
321 
323  // [[not collective]]
324  void set(PetscScalar value)
325  {
326  Vec localGhostedVec = nullptr;
327  VecGhostGetLocalForm(vector_, &localGhostedVec);
328  assert(localGhostedVec != nullptr);
329 
330  VecSet(localGhostedVec, value);
331  VecGhostRestoreLocalForm(vector_, &localGhostedVec);
332  }
333 
335  // [[not collective]]
336  void setZero()
337  {
338  Vec localGhostedVec = nullptr;
339  VecGhostGetLocalForm(vector_, &localGhostedVec);
340  assert(localGhostedVec != nullptr);
341 
342  VecZeroEntries(localGhostedVec);
343  VecGhostRestoreLocalForm(vector_, &localGhostedVec);
344  }
345 
346  friend void swap(PetscVector& lhs, PetscVector& rhs)
347  {
348  assert(&lhs.dofMap_ == &rhs.dofMap_);
349  std::swap(lhs.vector_, rhs.vector_);
350  std::swap(lhs.initialized_, rhs.initialized_);
351  }
352 
353  // An MPI Communicator or PETSC_COMM_SELF
354  MPI_Comm comm() const
355  {
356  return dofMap_.comm();
357  }
358 
359  private:
360  // Create a new Vector
361  void create()
362  {
363  VecCreateGhost(comm(),
364  dofMap_.localSize(), dofMap_.globalSize(), dofMap_.ghostSize(), dofMap_.ghostIndices().data(),
365  &vector_);
366  }
367 
368  // Destroy an old vector if created before
369  void destroy()
370  {
371  if (initialized_)
372  VecDestroy(&vector_);
373 
374  initialized_ = false;
375  }
376 
377  private:
378  // The local-to-global map
379  DofMap const& dofMap_;
380 
382  mutable Vec vector_ = nullptr;
383  bool initialized_ = false;
384  };
385 
386 
387  namespace Recursive
388  {
389  template <class DofMap>
390  struct ForEach<PetscVector<DofMap>>
391  {
392  template <class Vec, class UnaryFunction>
393  static void impl(Vec&& vec, UnaryFunction f)
394  {
395  vec.forEachLocal(f);
396  }
397  };
398 
399  template <class DofMap>
400  struct Transform<PetscVector<DofMap>>
401  {
402  template <class Operation, class... VecIns>
403  static void impl(PetscVector<DofMap>& vecOut, Operation op, VecIns const&... vecIn)
404  {
405  PetscVector<DofMap>::transformLocal(vecOut, op, vecIn...);
406  }
407  };
408 
409  template <class DofMap>
410  struct InnerProduct<PetscVector<DofMap>>
411  {
412  template <class T, class BinOp1, class BinOp2>
413  static T impl(PetscVector<DofMap> const& in1, PetscVector<DofMap> const& in2, T init, BinOp1 op1, BinOp2 op2)
414  {
415  return PetscVector<DofMap>::innerProductLocal(in1, in2, std::move(init), op1, op2);
416  }
417  };
418 
419  } // end namespace Recursive
420 } // end namespace AMDiS
void forEachLocal(Func &&f) const
Perform the f(value) on the local elements of this vector.
Definition: VectorBackend.hpp:242
constexpr bool MultiIndex
A multi-index type.
Definition: Concepts.hpp:149
BaseVector const & vector() const
Return the data-vector vector_.
Definition: VectorBackend.hpp:83
PetscVector(PetscVector &&other)
Move constructor.
Definition: VectorBackend.hpp:46
BaseVector & vector()
Return the data-vector vector_.
Definition: VectorBackend.hpp:89
PetscVector(PetscVector const &other)
Copy constructor.
Definition: VectorBackend.hpp:53
~PetscVector()
Destructor.
Definition: VectorBackend.hpp:64
void forEachLocal(Func &&f)
Perform the f(value) on the local elements of this vector.
Definition: VectorBackend.hpp:258
std::size_t globalSize() const
Return the number of entries in the global vector.
Definition: VectorBackend.hpp:101
Definition: ForEach.hpp:17
void forEach(IndexRange const &localInd, Func &&f) const
Apply the functor f to each vector entry to local index in localInd range.
Definition: VectorBackend.hpp:211
PetscScalar value_type
The type of the elements of the DOFVector.
Definition: VectorBackend.hpp:34
void insert(MultiIndex const &dof, PetscScalar value, Assign)
Access the entry i of the vector with write-access.
Definition: VectorBackend.hpp:159
Definition: AdaptBase.hpp:6
Definition: Transform.hpp:15
PetscVector & operator=(PetscVector &&other)
Move assignment operator.
Definition: VectorBackend.hpp:70
static void transformLocal(PetscVector &vecOut, Operation op, VecIns const &... vecIn)
Perform the valueOut = op(valueIn...) on the local elements of [vecOut] and [vecIn...].
Definition: VectorBackend.hpp:273
PetscVector & operator=(PetscVector const &other)
Copy assignment operator.
Definition: VectorBackend.hpp:77
General implementation of recursive inner-product.
Definition: InnerProduct.hpp:16
void setZero()
Zero all entries, including the ghost entries.
Definition: VectorBackend.hpp:336
void scatter(IndexRange const &localInd, LocalValues const &localVal, MaskRange const &mask, Assign)
Store all values given by localVal with indices localInd in the vector.
Definition: VectorBackend.hpp:180
std::size_t localSize() const
Return the number of entries in the local part of the vector.
Definition: VectorBackend.hpp:95
void gather(IndexRange const &localInd, OutputIterator buffer) const
Collect all values from this vector to indices given by localInd and store it into the output buffer...
Definition: VectorBackend.hpp:168
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:34
PetscInt size_type
The index/size - type.
Definition: VectorBackend.hpp:37
static T innerProductLocal(PetscVector const &in1, PetscVector const &in2, T init, BinOp1 op1, BinOp2 op2)
Perform the op1(init, op2(value1, value2)) on the local elements of [in1] and [in2].
Definition: VectorBackend.hpp:301
void synchronize()
Update the ghost regions with values from the owning process.
Definition: VectorBackend.hpp:138
::Vec BaseVector
The type of the base vector.
Definition: VectorBackend.hpp:31
void finish()
Finish assembly. Must be called before vector can be used in a KSP.
Definition: VectorBackend.hpp:128
void init(Basis const &, bool clear)
Resize the vector_ to the size s.
Definition: VectorBackend.hpp:109
PetscScalar at(MultiIndex const &idx) const
Access the entry i of the vector with read-only-access.
Definition: VectorBackend.hpp:149
PetscVector(DofMap const &dofMap)
Constructor. Constructs new BaseVector.
Definition: VectorBackend.hpp:41
The basic container that stores a base vector data.
Definition: VectorBackend.hpp:22