AMDiS 2.10
The Adaptive Multi-Dimensional Simulation Toolbox
LocalAverageInterpolator.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 local_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 std::map<typename Basis::MultiIndex, typename Coeff::value_type> values;
31 std::map<typename Basis::MultiIndex, std::uint8_t> counter;
32
33 std::vector<typename Coeff::value_type> localCoeff;
34
35 // Obtain a local view of the gridFunction
36 auto lf = localFunction(gf);
37 auto localView = basis_.localView();
38 for (const auto& e : entitySet(basis_))
39 {
40 localView.bind(e);
41 lf.bind(e);
42
43 auto&& subTree = Dune::TypeTree::child(localView.tree(),treePath_);
44 Traversal::forEachLeafNode(subTree, [&](auto const& node, auto const& tp)
45 {
46 // check whether there is a local contribution
47 bool any = false;
48 for (std::size_t i = 0; i < node.size(); ++i) {
49 auto idx = localView.index(node.localIndex(i));
50 if(bitVec[idx]) {
51 any = true;
52 break;
53 }
54 }
55
56 if (!any)
57 return;
58
59 // compute local interpolation coefficients
60 node.finiteElement().localInterpolation().interpolate(HierarchicNodeWrapper{tp,lf}, localCoeff);
61
62 // assign relevant local coefficients to temporary storage
63 for (std::size_t i = 0; i < node.size(); ++i) {
64 auto idx = localView.index(node.localIndex(i));
65 if (bitVec[idx]) {
66 counter[idx]++;
67 values[idx] += localCoeff[i];
68 }
69 }
70 });
71
72 lf.unbind();
73 }
74
75 assert(values.size() == counter.size());
76
77 // assign computed values to target vector
78 auto value_it = values.begin();
79 auto count_it = counter.begin();
80 for (; value_it != values.end(); ++value_it, ++count_it) {
81 coeff.set(value_it->first, value_it->second/double(count_it->second));
82 }
83 coeff.finish();
84 }
85
86 template <class Coeff, class GridFct>
87 void operator()(Coeff& coeff, GridFct const& gf) const
88 {
89 (*this)(coeff, gf, FakeContainer<bool,true>{});
90 }
91
92 LocalAverageInterpolator(Basis const& basis, TreePath treePath = {})
93 : basis_{basis}
94 , treePath_{treePath}
95 {}
96
97 Basis const& basis_;
98 TreePath treePath_ = {};
99 };
100
101
102 template <>
103 struct InterpolatorFactory<tag::local_average>
104 {
105 template <class Basis,
106 class TreePath = Dune::TypeTree::HybridTreePath<>>
107 static auto create(Basis const& basis, TreePath treePath = {})
108 {
109 return LocalAverageInterpolator<Basis,TreePath>{basis, treePath};
110 }
111 };
112
113} // end namespace AMDiS
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:36
Definition: HierarchicNodeToRangeMap.hpp:42
Definition: SimpleInterpolator.hpp:80
Definition: LocalAverageInterpolator.hpp:25
Definition: LocalAverageInterpolator.hpp:19