AMDiS  0.3
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 #include <dune/functions/functionspacebases/sizeinfo.hh>
15 
16 #include <amdis/Output.hpp>
17 #include <amdis/algorithm/ForEach.hpp>
18 #include <amdis/algorithm/InnerProduct.hpp>
19 #include <amdis/algorithm/Transform.hpp>
20 #include <amdis/common/Concepts.hpp>
21 #include <amdis/common/ConceptsBase.hpp>
22 #include <amdis/common/FakeContainer.hpp>
23 #include <amdis/common/TypeTraits.hpp>
24 #include <amdis/functions/NodeIndices.hpp>
25 #include <amdis/operations/Assigner.hpp>
26 #include <amdis/typetree/MultiIndex.hpp>
27 
28 namespace AMDiS
29 {
31 
38  template <class T, template <class> class VectorImpl>
40  {
41  using Self = VectorFacade;
42  using Impl = VectorImpl<T>;
43 
44  private:
45  // States the vector can be in. Is changed on various insertion or gathering methods.
46  enum class VectorState
47  {
48  unknown = 0,
49  synchronized = 1,
50  insert_values = 2,
51  add_values = 3
52  };
53 
54  template <class A>
55  using VectorStateOf_t = std::conditional_t<std::is_same_v<A,Assigner::plus_assign>,
56  std::integral_constant<VectorState, VectorState::add_values>,
57  std::integral_constant<VectorState, VectorState::insert_values>>;
58 
59  public:
60  using size_type = typename Impl::size_type;
61  using value_type = typename Impl::value_type;
62 
65  template <class GlobalBasis,
66  class = std::void_t<decltype(std::declval<GlobalBasis>().dimension())> >
67  VectorFacade(GlobalBasis const& basis)
68  : impl_(basis)
69  {
70  resizeZero(sizeInfo(basis));
71  }
72 
74  Impl const& impl() const { return impl_; }
75  Impl& impl() { return impl_; }
76 
77 
78  template <class V>
79  using HasLocalSize = decltype(std::declval<V>().localSize());
80 
81  template <class V>
82  using HasGlobalSize = decltype(std::declval<V>().globalSize());
83 
85  std::size_t localSize() const
86  {
87  if constexpr (Dune::Std::is_detected<HasLocalSize,Impl>::value)
88  return impl_.localSize();
89  else
90  return impl_.size();
91  }
92 
94  std::size_t globalSize() const
95  {
96  if constexpr (Dune::Std::is_detected<HasGlobalSize,Impl>::value)
97  return impl_.globalSize();
98  else
99  return impl_.size();
100  }
101 
103  template <class SizeInfo>
104  void resize(SizeInfo const& sizeInfo)
105  {
106  init(sizeInfo, false);
107  }
108 
110  template <class SizeInfo>
111  void resizeZero(SizeInfo const& sizeInfo)
112  {
113  init(sizeInfo, true);
114  }
115 
118  template <class SizeInfo>
119  void init(SizeInfo const& sizeInfo, bool clear)
120  {
121  impl_.init(sizeInfo, clear);
122  state_ = clear ? VectorState::synchronized : VectorState::unknown;
123  }
124 
126  void finish()
127  {
128  impl_.finish();
129  state_ = VectorState::unknown;
130  }
131 
133 
143  template <class Index, class Assign = Assigner::plus_assign,
144  REQUIRES(Concepts::MultiIndex<Index>)>
145  void insert(Index const& idx, typename Impl::value_type const& value, Assign assign = {})
146  {
147  test_exit_dbg(state_ == VectorStateOf_t<Assign>::value ||
148  state_ == VectorState::unknown ||
149  state_ == VectorState::synchronized,
150  "Vector in invalid state {} for insertion by {}.", to_string(state_), Dune::className<Assign>());
151 
152  impl_.insert(idx, value, assign);
153 
154  // set the state to insert_values or add_values
155  state_ = VectorStateOf_t<Assign>::value;
156  }
157 
159  template <class Index,
160  REQUIRES(Concepts::MultiIndex<Index>)>
161  void set(Index const& idx, typename Impl::value_type const& value)
162  {
163  insert(idx, value, Assigner::assign{});
164  }
165 
167  template <class Index,
168  REQUIRES(Concepts::MultiIndex<Index>)>
169  void add(Index const& idx, typename Impl::value_type const& value)
170  {
171  insert(idx, value, Assigner::plus_assign{});
172  }
173 
175  template <class Index,
176  REQUIRES(Concepts::MultiIndex<Index>)>
177  typename Impl::value_type get(Index const& idx) const
178  {
179  const_cast<Self*>(this)->synchronize();
180  return impl_.at(idx);
181  }
182 
183 
186 
198  template <class LocalView, class Node, class Buffer,
199  REQUIRES(Concepts::LocalView<LocalView>),
200  REQUIRES(Concepts::BasisNode<Node>)>
201  void gather(LocalView const& localView, Node const& node, Buffer& buffer) const
202  {
203  test_exit(state_ == VectorState::unknown ||
204  state_ == VectorState::synchronized,
205  "Vector in invalid state {} for gather operations.", to_string(state_));
206 
207  const_cast<Self*>(this)->synchronize();
208 
209  buffer.resize(node.size());
210  impl_.gather(nodeIndices(localView, node), buffer.begin());
211  }
212 
213  // [[expects: localView is bound to an element]]
214  template <class LocalView, class Buffer,
215  REQUIRES(Concepts::LocalView<LocalView>)>
216  void gather(LocalView const& localView, Buffer& buffer) const
217  {
218  gather(localView, localView.tree(), buffer);
219  }
220 
222 
241  template <class LocalView, class Node, class NodeVector, class MaskRange, class Assign,
242  REQUIRES(Concepts::LocalView<LocalView>),
243  REQUIRES(Concepts::BasisNode<Node>)>
244  void scatter(LocalView const& localView, Node const& node, NodeVector const& localVector,
245  MaskRange const& mask, Assign assign)
246  {
247  test_exit(state_ == VectorStateOf_t<Assign>::value ||
248  state_ == VectorState::unknown ||
249  state_ == VectorState::synchronized,
250  "Vector in invalid state {} for insertion by {}.", to_string(state_), Dune::className<Assign>());
251 
252  assert(localVector.size() == node.size());
253 
254  // create a range of DOF indices on the node
255  impl_.scatter(nodeIndices(localView, node), localVector, mask, assign);
256 
257  // set the state to insert_values or add_values
258  state_ = VectorStateOf_t<Assign>::value;
259  }
260 
262  // [[expects: localView is bound to an element]]
263  // [[expects: node is in localView.tree()]]
264  template <class LocalView, class Node, class NodeVector, class Assign,
265  REQUIRES(Concepts::LocalView<LocalView>),
266  REQUIRES(Concepts::BasisNode<Node>)>
267  void scatter(LocalView const& localView, Node const& node, NodeVector const& localVector, Assign assign)
268  {
269  scatter(localView, node, localVector, FakeContainer<bool,true>{}, assign);
270  }
271 
273  // [[expects: localView is bound to an element]]
274  template <class LocalView, class LocalVector, class Assign,
275  REQUIRES(Concepts::LocalView<LocalView>)>
276  void scatter(LocalView const& localView, LocalVector const& localVector, Assign assign)
277  {
278  scatter(localView, localView.tree(), localVector, assign);
279  }
280 
282 
288  template <class LocalInd, class Func>
289  void forEach(LocalInd const& localInd, Func&& func)
290  {
291  synchronize();
292  impl_.forEach(localInd, FWD(func));
293  }
294 
296 
302  template <class LocalInd, class Func>
303  void forEach(LocalInd const& localInd, Func&& func) const
304  {
305  const_cast<Self*>(this)->synchronize();
306  impl_.forEach(localInd, FWD(func));
307  }
308 
309  private:
310  // synchronizes ghost values. Does not touch owned values
311  void synchronize()
312  {
313  if (state_ != VectorState::synchronized)
314  impl_.synchronize();
315 
316  state_ = VectorState::synchronized;
317  }
318 
319  // print the vector state to string for debugging purposes
320  static std::string to_string(VectorState state)
321  {
322  switch (state) {
323  case VectorState::synchronized: return "synchronized";
324  case VectorState::insert_values: return "insert_values";
325  case VectorState::add_values: return "add_values";
326  default: return "unknown";
327  }
328  }
329 
330  private:
332  Impl impl_;
333 
336  VectorState state_ = VectorState::unknown;
337  };
338 
339 
340  namespace Recursive
341  {
342  template <class T, template <class> class Impl>
344  {
345  template <class Vec, class UnaryFunction>
346  static void impl (Vec&& vec, UnaryFunction f)
347  {
348  // NOTE: maybe needs synchronization
349  Recursive::forEach(vec.impl(), f);
350  }
351  };
352 
353  template <class T, template <class> class Impl>
355  {
356  template <class Operation, class... Ts>
357  static void impl (VectorFacade<T,Impl>& vecOut, Operation op, VectorFacade<Ts,Impl> const&... vecIn)
358  {
359  // NOTE: maybe needs synchronization
360  Recursive::transform(vecOut.impl(), op, vecIn.impl()...);
361  }
362  };
363 
364  template <class S, template <class> class Impl>
366  {
367  template <class In1, class In2, class T, class BinOp1, class BinOp2>
368  static T impl (In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
369  {
370  // NOTE: maybe needs synchronization
371  return Recursive::innerProduct(in1.impl(), in2.impl(), std::move(init), op1, op2);
372  }
373  };
374 
375  } // end namespace Recursive
376 
377 
378  namespace Impl
379  {
380  template <class T, class Facade>
381  struct VectorTypeImpl;
382 
383  template <class T, class S, template <class> class Impl>
384  struct VectorTypeImpl<T,VectorFacade<S,Impl>>
385  {
386  using type = VectorFacade<T,Impl>;
387  };
388 
389  } // end namespace Impl
390 
392  template <class T, class Facade>
393  using VectorType_t = typename Impl::VectorTypeImpl<T,Facade>::type;
394 
395 } // end namespace AMDiS
std::size_t localSize() const
Return the number of entries in the local part of the vector.
Definition: VectorFacade.hpp:85
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:201
void finish()
Finish the insertion of values, see init()
Definition: VectorFacade.hpp:126
The basic container that stores a base vector and a corresponding basis.
Definition: VectorFacade.hpp:39
std::size_t globalSize() const
Return the number of entries in the global vector.
Definition: VectorFacade.hpp:94
Definition: Assigner.hpp:16
Global basis defined on a pre-basis.
Definition: GlobalBasis.hpp:50
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:244
void forEach(LocalInd const &localInd, Func &&func)
Apply func to each value at given indices localInd.
Definition: VectorFacade.hpp:289
VectorFacade(GlobalBasis const &basis)
Definition: VectorFacade.hpp:67
Definition: AdaptBase.hpp:6
constexpr bool LocalView
A Dune::Functions::LocalView type.
Definition: Concepts.hpp:182
The restriction of a finite element basis to a single element.
Definition: LocalView.hpp:20
Tree const & tree() const
Return the local ansatz tree associated to the bound entity.
Definition: LocalView.hpp:129
void add(Index const &idx, typename Impl::value_type const &value)
See insert for assignment operation Assigner::plus_assign.
Definition: VectorFacade.hpp:169
void forEach(LocalInd const &localInd, Func &&func) const
Apply func to each value at given indices localInd.
Definition: VectorFacade.hpp:303
void resize(SizeInfo const &sizeInfo)
Resize the vector to the size of the basis.
Definition: VectorFacade.hpp:104
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:34
void init(SizeInfo const &sizeInfo, bool clear)
Definition: VectorFacade.hpp:119
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:145
void resizeZero(SizeInfo const &sizeInfo)
Resize the vector to the size of the basis and set to zero.
Definition: VectorFacade.hpp:111
Impl const & impl() const
Return the underlying linear algebra backend.
Definition: VectorFacade.hpp:74
void scatter(LocalView const &localView, Node const &node, NodeVector const &localVector, Assign assign)
Call scatter with MaskRange set to FakeContainer.
Definition: VectorFacade.hpp:267
constexpr bool GlobalBasis
A Dune::Functions::GlobalBasis type.
Definition: Concepts.hpp:190
void scatter(LocalView const &localView, LocalVector const &localVector, Assign assign)
Call scatter with Node given by the tree of the localView.
Definition: VectorFacade.hpp:276
Definition: Assigner.hpp:7