AMDiS 2.11-git
The Adaptive Multi-Dimensional Simulation Toolbox
 
Loading...
Searching...
No Matches
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/typetraits.hh>
13#include <dune/common/std/type_traits.hh>
14#include <dune/functions/functionspacebases/concepts.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
28namespace AMDiS
29{
30 // States the vector can be in. Is changed on various insertion or gathering methods.
31 enum class VectorState
32 {
33 unknown = 0,
34 synchronized = 1,
35 insert_values = 2,
36 add_values = 3
37 };
38
40
47 template <class T, template <class> class VectorImpl>
49 {
50 using Self = VectorFacade;
51 using Impl = VectorImpl<T>;
52
53 private:
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>().indexDistribution())> >
68 : impl_(basis.indexDistribution())
69 {
70 resizeZero(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 Basis>
104 void resize(Basis const& basis)
105 {
106 init(basis, false);
107 }
108
110 template <class Basis>
111 void resizeZero(Basis const& basis)
112 {
113 init(basis, true);
114 }
115
118 template <class Basis>
119 void init(Basis const& basis, bool clear)
120 {
121 impl_.init(basis, 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 template <class Index, class Buffer,
223 REQUIRES(Concepts::MultiIndex<Index>)>
224 void gather(std::vector<Index> const& indices, Buffer& buffer)
225 {
226 test_exit(state_ == VectorState::unknown ||
227 state_ == VectorState::synchronized,
228 "Vector in invalid state {} for gather operations.", to_string(state_));
229
230 const_cast<Self*>(this)->synchronize();
231
232 buffer.resize(indices.size());
233 impl_.gather(indices, buffer.begin());
234 }
235
237
256 template <class LocalView, class Node, class NodeVector, class MaskRange, class Assign,
257 REQUIRES(Concepts::LocalView<LocalView>),
258 REQUIRES(Concepts::BasisNode<Node>)>
259 void scatter(LocalView const& localView, Node const& node, NodeVector const& localVector,
260 MaskRange const& mask, Assign assign)
261 {
262 test_exit(state_ == VectorStateOf_t<Assign>::value ||
263 state_ == VectorState::unknown ||
264 state_ == VectorState::synchronized,
265 "Vector in invalid state {} for insertion by {}.", to_string(state_), Dune::className<Assign>());
266
267 assert(localVector.size() == node.size());
268
269 // create a range of DOF indices on the node
270 impl_.scatter(nodeIndices(localView, node), localVector, mask, assign);
271
272 // set the state to insert_values or add_values
273 state_ = VectorStateOf_t<Assign>::value;
274 }
275
277 // [[expects: localView is bound to an element]]
278 // [[expects: node is in localView.tree()]]
279 template <class LocalView, class Node, class NodeVector, class Assign,
280 REQUIRES(Concepts::LocalView<LocalView>),
281 REQUIRES(Concepts::BasisNode<Node>)>
282 void scatter(LocalView const& localView, Node const& node, NodeVector const& localVector, Assign assign)
283 {
284 scatter(localView, node, localVector, FakeContainer<bool,true>{}, assign);
285 }
286
288 // [[expects: localView is bound to an element]]
289 template <class LocalView, class LocalVector, class Assign,
290 REQUIRES(Concepts::LocalView<LocalView>)>
291 void scatter(LocalView const& localView, LocalVector const& localVector, Assign assign)
292 {
293 scatter(localView, localView.tree(), localVector, assign);
294 }
295
297 template <class Index, class Buffer,
298 REQUIRES(Concepts::MultiIndex<Index>)>
299 void scatter(std::vector<Index> const& indices, Buffer const& values)
300 {
301 impl_.scatter(indices, values, FakeContainer<bool,true>{}, Assigner::assign{});
302
303 // set the state to insert_values or add_values
304 state_ = VectorStateOf_t<Assigner::assign>::value;
305 }
306
307
310
312 template <class S,
313 std::enable_if_t<Dune::IsNumber<S>::value, int> = 0>
314 Self& axpy (const S& alpha, const Self& x)
315 {
316 impl_.axpy(alpha, x.impl_);
317 return *this;
318 }
319
321 template <class S,
322 std::enable_if_t<Dune::IsNumber<S>::value, int> = 0>
323 Self& aypx (const S& alpha, const Self& x)
324 {
325 impl_.aypx(alpha, x.impl_);
326 return *this;
327 }
328
330 template <class S,
331 std::enable_if_t<Dune::IsNumber<S>::value, int> = 0>
332 Self& operator= (const S& alpha)
333 {
334 impl_.set(alpha);
335 return *this;
336 }
337
340 {
341 return this->axpy(1.0, x);
342 }
343
346 {
347 return this->axpy(-1.0, x);
348 }
349
351 template <class S,
352 std::enable_if_t<Dune::IsNumber<S>::value, int> = 0>
353 Self& operator*= (const S& alpha)
354 {
355 impl_.scale(alpha);
356 return *this;
357 }
358
360 template <class S,
361 std::enable_if_t<Dune::IsNumber<S>::value, int> = 0>
362 Self& operator/= (const S& alpha)
363 {
364 impl_.scale(S(1)/alpha);
365 return *this;
366 }
367
369
370
372
378 template <class LocalInd, class Func>
379 void forEach(LocalInd const& localInd, Func&& func)
380 {
381 synchronize();
382 impl_.forEach(localInd, FWD(func));
383 }
384
386
392 template <class LocalInd, class Func>
393 void forEach(LocalInd const& localInd, Func&& func) const
394 {
395 const_cast<Self*>(this)->synchronize();
396 impl_.forEach(localInd, FWD(func));
397 }
398
400
403 VectorState state () const
404 {
405 return state_;
406 }
407
408 private:
409 // synchronizes ghost values. Does not touch owned values
410 void synchronize()
411 {
412 if (state_ != VectorState::synchronized)
413 impl_.synchronize();
414
415 state_ = VectorState::synchronized;
416 }
417
418 // print the vector state to string for debugging purposes
419 static std::string to_string(VectorState state)
420 {
421 switch (state) {
422 case VectorState::synchronized: return "synchronized";
423 case VectorState::insert_values: return "insert_values";
424 case VectorState::add_values: return "add_values";
425 default: return "unknown";
426 }
427 }
428
429 private:
431 Impl impl_;
432
435 VectorState state_ = VectorState::unknown;
436 };
437
438
439 namespace Recursive
440 {
441 template <class T, template <class> class Impl>
442 struct ForEach<VectorFacade<T,Impl>>
443 {
444 template <class Vec, class UnaryFunction>
445 static void impl (Vec&& vec, UnaryFunction f)
446 {
447 // NOTE: maybe needs synchronization
448 Recursive::forEach(vec.impl(), f);
449 }
450 };
451
452 template <class T, template <class> class Impl>
453 struct Transform<VectorFacade<T,Impl>>
454 {
455 template <class Operation, class... Ts>
456 static void impl (VectorFacade<T,Impl>& vecOut, Operation op, VectorFacade<Ts,Impl> const&... vecIn)
457 {
458 // NOTE: maybe needs synchronization
459 Recursive::transform(vecOut.impl(), op, vecIn.impl()...);
460 }
461 };
462
463 template <class S, template <class> class Impl>
464 struct InnerProduct<VectorFacade<S,Impl>>
465 {
466 template <class In1, class In2, class T, class BinOp1, class BinOp2>
467 static T impl (In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
468 {
469 // NOTE: maybe needs synchronization
470 return Recursive::innerProduct(in1.impl(), in2.impl(), std::move(init), op1, op2);
471 }
472 };
473
474 } // end namespace Recursive
475
476
477 namespace Impl
478 {
479 template <class T, class Facade>
480 struct VectorTypeImpl;
481
482 template <class T, class S, template <class> class Impl>
483 struct VectorTypeImpl<T,VectorFacade<S,Impl>>
484 {
485 using type = VectorFacade<T,Impl>;
486 };
487
488 } // end namespace Impl
489
491 template <class T, class Facade>
492 using VectorType_t = typename Impl::VectorTypeImpl<T,Facade>::type;
493
494} // 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:47
IndexDist const & indexDistribution() const
Return the index distribution.
Definition GlobalBasis.hpp:138
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:49
void gather(std::vector< Index > const &indices, Buffer &buffer)
Call gather the values associated to the indices into the buffer.
Definition VectorFacade.hpp:224
void scatter(LocalView const &localView, Node const &node, NodeVector const &localVector, Assign assign)
Call scatter with MaskRange set to FakeContainer.
Definition VectorFacade.hpp:282
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
Self & aypx(const S &alpha, const Self &x)
Implements *this = alpha * (*this) + x.
Definition VectorFacade.hpp:323
Self & operator-=(const Self &x)
return *this -= x
Definition VectorFacade.hpp:345
void forEach(LocalInd const &localInd, Func &&func) const
Apply func to each value at given indices localInd.
Definition VectorFacade.hpp:393
Self & operator/=(const S &alpha)
scale all entries by the factor 1.0/alpha
Definition VectorFacade.hpp:362
void add(Index const &idx, typename Impl::value_type const &value)
See insert for assignment operation Assigner::plus_assign.
Definition VectorFacade.hpp:169
void finish()
Finish the insertion of values, see init()
Definition VectorFacade.hpp:126
Self & operator=(const S &alpha)
Set all entries to alpha.
Definition VectorFacade.hpp:332
void init(Basis const &basis, bool clear)
Definition VectorFacade.hpp:119
VectorFacade(GlobalBasis const &basis)
Definition VectorFacade.hpp:67
void scatter(LocalView const &localView, LocalVector const &localVector, Assign assign)
Call scatter with Node given by the tree of the localView.
Definition VectorFacade.hpp:291
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 forEach(LocalInd const &localInd, Func &&func)
Apply func to each value at given indices localInd.
Definition VectorFacade.hpp:379
void set(Index const &idx, typename Impl::value_type const &value)
See insert for assignment operation Assigner::assign.
Definition VectorFacade.hpp:161
Self & operator*=(const S &alpha)
scale all entries by the factor alpha
Definition VectorFacade.hpp:353
Self & axpy(const S &alpha, const Self &x)
Implements *this = *this + alpha * x.
Definition VectorFacade.hpp:314
std::size_t globalSize() const
Return the number of entries in the global vector.
Definition VectorFacade.hpp:94
void resize(Basis const &basis)
Resize the vector to the size of the basis.
Definition VectorFacade.hpp:104
Impl::value_type get(Index const &idx) const
Return the value of the vector at the local index idx.
Definition VectorFacade.hpp:177
std::size_t localSize() const
Return the number of entries in the local part of the vector.
Definition VectorFacade.hpp:85
VectorState state() const
Return the internal state of the vector.
Definition VectorFacade.hpp:403
Self & operator+=(const Self &x)
return *this += x
Definition VectorFacade.hpp:339
void scatter(std::vector< Index > const &indices, Buffer const &values)
Call scatter the values associated to the indices into the vector.
Definition VectorFacade.hpp:299
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:259
void resizeZero(Basis const &basis)
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
Definition Assigner.hpp:8
Definition Assigner.hpp:17