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 
15 namespace 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
Definition: Assigner.hpp:16
Definition: AdaptBase.hpp:6
Definition: SimpleInterpolator.hpp:80
Definition: AverageInterpolator.hpp:19
A container-like data-structure not storing anything and with empty implementations in many container...
Definition: FakeContainer.hpp:34
Definition: AverageInterpolator.hpp:24
Definition: HierarchicNodeToRangeMap.hpp:41