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
27namespace 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())> >
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
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:36
Global basis defined on a pre-basis.
Definition: GlobalBasis.hpp:48
IndexDist const & indexDistribution() const
Return the index distribution.
Definition: GlobalBasis.hpp:148
The restriction of a finite element basis to a single element.
Definition: LocalView.hpp:16
The basic container that stores a base vector and a corresponding basis.
Definition: VectorFacade.hpp:39
void gather(std::vector< Index > const &indices, Buffer &buffer)
Call gather the values associated to the indices into the buffer.
Definition: VectorFacade.hpp:223
void scatter(LocalView const &localView, Node const &node, NodeVector const &localVector, Assign assign)
Call scatter with MaskRange set to FakeContainer.
Definition: VectorFacade.hpp:281
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 forEach(LocalInd const &localInd, Func &&func) const
Apply func to each value at given indices localInd.
Definition: VectorFacade.hpp:328
void add(Index const &idx, typename Impl::value_type const &value)
See insert for assignment operation Assigner::plus_assign.
Definition: VectorFacade.hpp:168
void finish()
Finish the insertion of values, see init()
Definition: VectorFacade.hpp:125
void init(Basis const &basis, bool clear)
Definition: VectorFacade.hpp:118
VectorFacade(GlobalBasis const &basis)
Definition: VectorFacade.hpp:66
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 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 forEach(LocalInd const &localInd, Func &&func)
Apply func to each value at given indices localInd.
Definition: VectorFacade.hpp:314
void set(Index const &idx, typename Impl::value_type const &value)
See insert for assignment operation Assigner::assign.
Definition: VectorFacade.hpp:160
std::size_t globalSize() const
Return the number of entries in the global vector.
Definition: VectorFacade.hpp:93
void resize(Basis const &basis)
Resize the vector to the size of the basis.
Definition: VectorFacade.hpp:103
Impl::value_type get(Index const &idx) const
Return the value of the vector at the local index idx.
Definition: VectorFacade.hpp:176
std::size_t localSize() const
Return the number of entries in the local part of the vector.
Definition: VectorFacade.hpp:84
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 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 resizeZero(Basis const &basis)
Resize the vector to the size of the basis and set to zero.
Definition: VectorFacade.hpp:110
Impl const & impl() const
Return the underlying linear algebra backend.
Definition: VectorFacade.hpp:73
constexpr bool GlobalBasis
A Dune::Functions::GlobalBasis type.
Definition: Concepts.hpp:189
constexpr bool LocalView
A Dune::Functions::LocalView type.
Definition: Concepts.hpp:181
Definition: Assigner.hpp:8
Definition: Assigner.hpp:17
Definition: ForEach.hpp:39
General implementation of recursive inner-product.
Definition: InnerProduct.hpp:58
Definition: Transform.hpp:35