AMDiS  2.10
The Adaptive Multi-Dimensional Simulation Toolbox
VectorFacade.hpp
1 #pragma once
2 
3 #include <string>
4 #include <type_traits>
5 #include <utility>
6 
7 #include <dune/common/classname.hh>
8 #include <dune/common/deprecated.hh>
9 #include <dune/common/hybridutilities.hh>
10 #include <dune/common/rangeutilities.hh>
11 #include <dune/common/shared_ptr.hh>
12 #include <dune/common/std/type_traits.hh>
13 #include <dune/functions/functionspacebases/concepts.hh>
14 
15 #include <amdis/Output.hpp>
16 #include <amdis/algorithm/ForEach.hpp>
17 #include <amdis/algorithm/InnerProduct.hpp>
18 #include <amdis/algorithm/Transform.hpp>
19 #include <amdis/common/Concepts.hpp>
20 #include <amdis/common/ConceptsBase.hpp>
21 #include <amdis/common/FakeContainer.hpp>
22 #include <amdis/common/TypeTraits.hpp>
23 #include <amdis/functions/NodeIndices.hpp>
24 #include <amdis/operations/Assigner.hpp>
25 #include <amdis/typetree/MultiIndex.hpp>
26 
27 namespace AMDiS
28 {
30 
37  template <class T, template <class> class VectorImpl>
39  {
40  using Self = VectorFacade;
41  using Impl = VectorImpl<T>;
42 
43  private:
44  // States the vector can be in. Is changed on various insertion or gathering methods.
45  enum class VectorState
46  {
47  unknown = 0,
48  synchronized = 1,
49  insert_values = 2,
50  add_values = 3
51  };
52 
53  template <class A>
54  using VectorStateOf_t = std::conditional_t<std::is_same_v<A,Assigner::plus_assign>,
55  std::integral_constant<VectorState, VectorState::add_values>,
56  std::integral_constant<VectorState, VectorState::insert_values>>;
57 
58  public:
59  using size_type = typename Impl::size_type;
60  using value_type = typename Impl::value_type;
61 
64  template <class GlobalBasis,
65  class = std::void_t<decltype(std::declval<GlobalBasis>().indexDistribution())> >
66  VectorFacade(GlobalBasis const& basis)
67  : impl_(basis.indexDistribution())
68  {
69  resizeZero(basis);
70  }
71 
73  Impl const& impl() const { return impl_; }
74  Impl& impl() { return impl_; }
75 
76 
77  template <class V>
78  using HasLocalSize = decltype(std::declval<V>().localSize());
79 
80  template <class V>
81  using HasGlobalSize = decltype(std::declval<V>().globalSize());
82 
84  std::size_t localSize() const
85  {
86  if constexpr (Dune::Std::is_detected<HasLocalSize,Impl>::value)
87  return impl_.localSize();
88  else
89  return impl_.size();
90  }
91 
93  std::size_t globalSize() const
94  {
95  if constexpr (Dune::Std::is_detected<HasGlobalSize,Impl>::value)
96  return impl_.globalSize();
97  else
98  return impl_.size();
99  }
100 
102  template <class Basis>
103  void resize(Basis const& basis)
104  {
105  init(basis, false);
106  }
107 
109  template <class Basis>
110  void resizeZero(Basis const& basis)
111  {
112  init(basis, true);
113  }
114 
117  template <class Basis>
118  void init(Basis const& basis, bool clear)
119  {
120  impl_.init(basis, clear);
121  state_ = clear ? VectorState::synchronized : VectorState::unknown;
122  }
123 
125  void finish()
126  {
127  impl_.finish();
128  state_ = VectorState::unknown;
129  }
130 
132 
142  template <class Index, class Assign = Assigner::plus_assign,
143  REQUIRES(Concepts::MultiIndex<Index>)>
144  void insert(Index const& idx, typename Impl::value_type const& value, Assign assign = {})
145  {
146  test_exit_dbg(state_ == VectorStateOf_t<Assign>::value ||
147  state_ == VectorState::unknown ||
148  state_ == VectorState::synchronized,
149  "Vector in invalid state {} for insertion by {}.", to_string(state_), Dune::className<Assign>());
150 
151  impl_.insert(idx, value, assign);
152 
153  // set the state to insert_values or add_values
154  state_ = VectorStateOf_t<Assign>::value;
155  }
156 
158  template <class Index,
159  REQUIRES(Concepts::MultiIndex<Index>)>
160  void set(Index const& idx, typename Impl::value_type const& value)
161  {
162  insert(idx, value, Assigner::assign{});
163  }
164 
166  template <class Index,
167  REQUIRES(Concepts::MultiIndex<Index>)>
168  void add(Index const& idx, typename Impl::value_type const& value)
169  {
170  insert(idx, value, Assigner::plus_assign{});
171  }
172 
174  template <class Index,
175  REQUIRES(Concepts::MultiIndex<Index>)>
176  typename Impl::value_type get(Index const& idx) const
177  {
178  const_cast<Self*>(this)->synchronize();
179  return impl_.at(idx);
180  }
181 
182 
185 
197  template <class LocalView, class Node, class Buffer,
198  REQUIRES(Concepts::LocalView<LocalView>),
199  REQUIRES(Concepts::BasisNode<Node>)>
200  void gather(LocalView const& localView, Node const& node, Buffer& buffer) const
201  {
202  test_exit(state_ == VectorState::unknown ||
203  state_ == VectorState::synchronized,
204  "Vector in invalid state {} for gather operations.", to_string(state_));
205 
206  const_cast<Self*>(this)->synchronize();
207 
208  buffer.resize(node.size());
209  impl_.gather(nodeIndices(localView, node), buffer.begin());
210  }
211 
212  // [[expects: localView is bound to an element]]
213  template <class LocalView, class Buffer,
214  REQUIRES(Concepts::LocalView<LocalView>)>
215  void gather(LocalView const& localView, Buffer& buffer) const
216  {
217  gather(localView, localView.tree(), buffer);
218  }
219 
221  template <class Index, class Buffer,
222  REQUIRES(Concepts::MultiIndex<Index>)>
223  void gather(std::vector<Index> const& indices, Buffer& buffer)
224  {
225  test_exit(state_ == VectorState::unknown ||
226  state_ == VectorState::synchronized,
227  "Vector in invalid state {} for gather operations.", to_string(state_));
228 
229  const_cast<Self*>(this)->synchronize();
230 
231  buffer.resize(indices.size());
232  impl_.gather(indices, buffer.begin());
233  }
234 
236 
255  template <class LocalView, class Node, class NodeVector, class MaskRange, class Assign,
256  REQUIRES(Concepts::LocalView<LocalView>),
257  REQUIRES(Concepts::BasisNode<Node>)>
258  void scatter(LocalView const& localView, Node const& node, NodeVector const& localVector,
259  MaskRange const& mask, Assign assign)
260  {
261  test_exit(state_ == VectorStateOf_t<Assign>::value ||
262  state_ == VectorState::unknown ||
263  state_ == VectorState::synchronized,
264  "Vector in invalid state {} for insertion by {}.", to_string(state_), Dune::className<Assign>());
265 
266  assert(localVector.size() == node.size());
267 
268  // create a range of DOF indices on the node
269  impl_.scatter(nodeIndices(localView, node), localVector, mask, assign);
270 
271  // set the state to insert_values or add_values
272  state_ = VectorStateOf_t<Assign>::value;
273  }
274 
276  // [[expects: localView is bound to an element]]
277  // [[expects: node is in localView.tree()]]
278  template <class LocalView, class Node, class NodeVector, class Assign,
279  REQUIRES(Concepts::LocalView<LocalView>),
280  REQUIRES(Concepts::BasisNode<Node>)>
281  void scatter(LocalView const& localView, Node const& node, NodeVector const& localVector, Assign assign)
282  {
283  scatter(localView, node, localVector, FakeContainer<bool,true>{}, assign);
284  }
285 
287  // [[expects: localView is bound to an element]]
288  template <class LocalView, class LocalVector, class Assign,
289  REQUIRES(Concepts::LocalView<LocalView>)>
290  void scatter(LocalView const& localView, LocalVector const& localVector, Assign assign)
291  {
292  scatter(localView, localView.tree(), localVector, assign);
293  }
294 
296  template <class Index, class Buffer,
297  REQUIRES(Concepts::MultiIndex<Index>)>
298  void scatter(std::vector<Index> const& indices, Buffer const& values)
299  {
300  impl_.scatter(indices, values, FakeContainer<bool,true>{}, Assigner::assign{});
301 
302  // set the state to insert_values or add_values
303  state_ = VectorStateOf_t<Assigner::assign>::value;
304  }
305 
307 
313  template <class LocalInd, class Func>
314  void forEach(LocalInd const& localInd, Func&& func)
315  {
316  synchronize();
317  impl_.forEach(localInd, FWD(func));
318  }
319 
321 
327  template <class LocalInd, class Func>
328  void forEach(LocalInd const& localInd, Func&& func) const
329  {
330  const_cast<Self*>(this)->synchronize();
331  impl_.forEach(localInd, FWD(func));
332  }
333 
334  private:
335  // synchronizes ghost values. Does not touch owned values
336  void synchronize()
337  {
338  if (state_ != VectorState::synchronized)
339  impl_.synchronize();
340 
341  state_ = VectorState::synchronized;
342  }
343 
344  // print the vector state to string for debugging purposes
345  static std::string to_string(VectorState state)
346  {
347  switch (state) {
348  case VectorState::synchronized: return "synchronized";
349  case VectorState::insert_values: return "insert_values";
350  case VectorState::add_values: return "add_values";
351  default: return "unknown";
352  }
353  }
354 
355  private:
357  Impl impl_;
358 
361  VectorState state_ = VectorState::unknown;
362  };
363 
364 
365  namespace Recursive
366  {
367  template <class T, template <class> class Impl>
369  {
370  template <class Vec, class UnaryFunction>
371  static void impl (Vec&& vec, UnaryFunction f)
372  {
373  // NOTE: maybe needs synchronization
374  Recursive::forEach(vec.impl(), f);
375  }
376  };
377 
378  template <class T, template <class> class Impl>
380  {
381  template <class Operation, class... Ts>
382  static void impl (VectorFacade<T,Impl>& vecOut, Operation op, VectorFacade<Ts,Impl> const&... vecIn)
383  {
384  // NOTE: maybe needs synchronization
385  Recursive::transform(vecOut.impl(), op, vecIn.impl()...);
386  }
387  };
388 
389  template <class S, template <class> class Impl>
391  {
392  template <class In1, class In2, class T, class BinOp1, class BinOp2>
393  static T impl (In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
394  {
395  // NOTE: maybe needs synchronization
396  return Recursive::innerProduct(in1.impl(), in2.impl(), std::move(init), op1, op2);
397  }
398  };
399 
400  } // end namespace Recursive
401 
402 
403  namespace Impl
404  {
405  template <class T, class Facade>
406  struct VectorTypeImpl;
407 
408  template <class T, class S, template <class> class Impl>
409  struct VectorTypeImpl<T,VectorFacade<S,Impl>>
410  {
411  using type = VectorFacade<T,Impl>;
412  };
413 
414  } // end namespace Impl
415 
417  template <class T, class Facade>
418  using VectorType_t = typename Impl::VectorTypeImpl<T,Facade>::type;
419 
420 } // end namespace AMDiS
std::size_t localSize() const
Return the number of entries in the local part of the vector.
Definition: VectorFacade.hpp:84
void gather(LocalView const &localView, Node const &node, Buffer &buffer) const
Extract values from the vector referring to the given local indices and store it into a buffer...
Definition: VectorFacade.hpp:200
void finish()
Finish the insertion of values, see init()
Definition: VectorFacade.hpp:125
The basic container that stores a base vector and a corresponding basis.
Definition: VectorFacade.hpp:38
std::size_t globalSize() const
Return the number of entries in the global vector.
Definition: VectorFacade.hpp:93
Definition: Assigner.hpp:16
Global basis defined on a pre-basis.
Definition: GlobalBasis.hpp:44
Definition: ForEach.hpp:17
void scatter(LocalView const &localView, Node const &node, NodeVector const &localVector, MaskRange const &mask, Assign assign)
Insert a block of values into the vector (add or overwrite to existing values)
Definition: VectorFacade.hpp:258
void forEach(LocalInd const &localInd, Func &&func)
Apply func to each value at given indices localInd.
Definition: VectorFacade.hpp:314
VectorFacade(GlobalBasis const &basis)
Definition: VectorFacade.hpp:66
Definition: AdaptBase.hpp:6
constexpr bool LocalView
A Dune::Functions::LocalView type.
Definition: Concepts.hpp:181
Definition: Transform.hpp:15
The restriction of a finite element basis to a single element.
Definition: LocalView.hpp:14
General implementation of recursive inner-product.
Definition: InnerProduct.hpp:16
void init(Basis const &basis, bool clear)
Definition: VectorFacade.hpp:118
void add(Index const &idx, typename Impl::value_type const &value)
See insert for assignment operation Assigner::plus_assign.
Definition: VectorFacade.hpp:168
void forEach(LocalInd const &localInd, Func &&func) const
Apply func to each value at given indices localInd.
Definition: VectorFacade.hpp:328
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:34
void insert(Index const &idx, typename Impl::value_type const &value, Assign assign={})
Insert a single value into the matrix (add or overwrite to existing value)
Definition: VectorFacade.hpp:144
void resize(Basis const &basis)
Resize the vector to the size of the basis.
Definition: VectorFacade.hpp:103
IndexDist const & indexDistribution() const
Return the index distribution.
Definition: GlobalBasis.hpp:148
Impl const & impl() const
Return the underlying linear algebra backend.
Definition: VectorFacade.hpp:73
void resizeZero(Basis const &basis)
Resize the vector to the size of the basis and set to zero.
Definition: VectorFacade.hpp:110
void scatter(LocalView const &localView, Node const &node, NodeVector const &localVector, Assign assign)
Call scatter with MaskRange set to FakeContainer.
Definition: VectorFacade.hpp:281
constexpr bool GlobalBasis
A Dune::Functions::GlobalBasis type.
Definition: Concepts.hpp:189
void scatter(LocalView const &localView, LocalVector const &localVector, Assign assign)
Call scatter with Node given by the tree of the localView.
Definition: VectorFacade.hpp:290
void scatter(std::vector< Index > const &indices, Buffer const &values)
Call scatter the values associated to the indices into the vector.
Definition: VectorFacade.hpp:298
void gather(std::vector< Index > const &indices, Buffer &buffer)
Call gather the values associated to the indices into the buffer.
Definition: VectorFacade.hpp:223
Definition: Assigner.hpp:7