AMDiS 2.10
The Adaptive Multi-Dimensional Simulation Toolbox
AverageInterpolator.hpp
1#pragma once
2
3#include <map>
4#include <vector>
5
6#include <amdis/common/FakeContainer.hpp>
7#include <amdis/common/FieldMatVec.hpp>
8#include <amdis/functions/EntitySet.hpp>
9#include <amdis/functions/HierarchicNodeToRangeMap.hpp>
10#include <amdis/functions/NodeIndices.hpp>
11#include <amdis/linearalgebra/Traits.hpp>
12#include <amdis/operations/Assigner.hpp>
13#include <amdis/typetree/Traversal.hpp>
14
15namespace AMDiS
16{
17 namespace tag
18 {
19 struct average {};
20 }
21
22 template <class Basis,
23 class TreePath = Dune::TypeTree::HybridTreePath<>>
25 {
26 template <class Coeff, class GridFct, class BitVector>
27 void operator()(Coeff& coeff, GridFct const& gf, BitVector const& bitVec) const
28 {
29 // storage for values computed during the interpolation
30 VectorType_t<typename Coeff::value_type, Coeff> coeff0(basis_);
31 VectorType_t<std::uint8_t, Coeff> counter(basis_);
32 using Counter = TYPEOF(counter);
33
34 // Obtain a local view of the gridFunction
35 auto lf = localFunction(gf);
36 auto localView = basis_.localView();
37
38 std::vector<typename Coeff::value_type> localCoeff;
39 std::vector<typename Counter::value_type> localOnes(localView.maxSize(), 1);
40
41 for (const auto& e : entitySet(basis_))
42 {
43 localView.bind(e);
44 lf.bind(e);
45
46 auto&& subTree = Dune::TypeTree::child(localView.tree(),treePath_);
47 Traversal::forEachLeafNode(subTree, [&](auto const& node, auto const& tp)
48 {
49 auto bitVecRange = mappedRangeView(Dune::range(node.size()), [&](std::size_t i) -> bool {
50 return bitVec[localView.index(node.localIndex(i))];
51 });
52
53 // check whether there is a local contribution
54 std::vector<bool> mask(bitVecRange.begin(), bitVecRange.end());
55 if (std::all_of(mask.begin(), mask.end(), [](bool m) { return !m; }))
56 return;
57
58 // compute local interpolation coefficients
59 node.finiteElement().localInterpolation().interpolate(HierarchicNodeWrapper{tp,lf}, localCoeff);
60
61 // assign local coefficients to global vector
62 coeff0.scatter(localView, node, localCoeff, mask, Assigner::plus_assign{});
63
64 localOnes.resize(node.size(), 1);
65 counter.scatter(localView, node, localOnes, mask, Assigner::plus_assign{});
66 });
67
68 lf.unbind();
69 }
70 coeff0.finish();
71 counter.finish();
72
73 // storage for values computed during the interpolation
74 std::map<typename Basis::MultiIndex, typename Coeff::value_type> coeffMap;
75 std::map<typename Basis::MultiIndex, std::uint8_t> counterMap;
76
77 std::vector<typename Coeff::value_type> localCoeffs;
78 std::vector<typename Counter::value_type> localCounter;
79
80 for (const auto& e : entitySet(basis_))
81 {
82 localView.bind(e);
83
84 auto&& node = Dune::TypeTree::child(localView.tree(),treePath_);
85 counter.gather(localView, node, localCounter);
86 coeff0.gather(localView, node, localCoeffs);
87
88 for (std::size_t i = 0; i < node.size(); ++i) {
89 if (localCounter[i] > 0) {
90 auto idx = localView.index(node.localIndex(i));
91 coeffMap[idx] = localCoeffs[i];
92 counterMap[idx] = localCounter[i];
93 }
94 }
95 }
96
97 assert(coeffMap.size() == counterMap.size());
98
99 // assign computed values to target vector
100 auto value_it = coeffMap.begin();
101 auto count_it = counterMap.begin();
102 for (; value_it != coeffMap.end(); ++value_it, ++count_it) {
103 assert(count_it->second > 0);
104 coeff.set(value_it->first, value_it->second/double(count_it->second));
105 }
106 coeff.finish();
107 }
108
109 template <class Coeff, class GridFct>
110 void operator()(Coeff& coeff, GridFct const& gf) const
111 {
112 (*this)(coeff, gf, FakeContainer<bool,true>{});
113 }
114
115 AverageInterpolator(Basis const& basis, TreePath treePath = {})
116 : basis_{basis}
117 , treePath_{treePath}
118 {}
119
120 Basis const& basis_;
121 TreePath treePath_ = {};
122 };
123
124
125 template <>
126 struct InterpolatorFactory<tag::average>
127 {
128 template <class Basis,
129 class TreePath = Dune::TypeTree::HybridTreePath<>>
130 static auto create(Basis const& basis, TreePath treePath = {})
131 {
132 return AverageInterpolator<Basis,TreePath>{basis, treePath};
133 }
134 };
135
136} // end namespace AMDiS
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:36
Definition: Assigner.hpp:17
Definition: AverageInterpolator.hpp:25
Definition: HierarchicNodeToRangeMap.hpp:42
Definition: SimpleInterpolator.hpp:80
Definition: AverageInterpolator.hpp:19