AMDiS  2.10
The Adaptive Multi-Dimensional Simulation Toolbox
SimpleDataTransfer.hpp
1 #pragma once
2 
3 #include <map>
4 #include <optional>
5 #include <vector>
6 
7 #include <amdis/DataTransfer.hpp>
8 #include <amdis/functions/EntitySet.hpp>
9 #include <amdis/gridfunctions/CoarsenedGridFunction.hpp>
10 #include <amdis/gridfunctions/DiscreteFunction.hpp>
11 
12 #include <dune/grid/common/capabilities.hh>
13 
14 namespace AMDiS {
15 
22 namespace tag {
23 
26  : datatransfer
27  {};
28 
29 } // end namespace tag
30 
31 
32 template <class Basis, class Container>
34 {
35  using CoefficientVector = std::vector<typename Container::value_type>;
36  using EntityId = typename Basis::GridView::Grid::LocalIdSet::IdType;
37  using PersistentStorage = std::map<EntityId, CoefficientVector>;
38  using Domain = typename Basis::GridView::template Codim<0>::Entity::Geometry::LocalCoordinate;
39 
40 private:
41  PersistentStorage persistentStorage_;
42 
43 public:
45  {
46  static_assert(Dune::Capabilities::hasSingleGeometryType<typename Basis::GridView::Grid>::v);
47  }
48 
50  void preAdapt(Basis const& basis, Container const& coeff, bool mightCoarsen)
51  {
52  CoefficientVector interpolationCoeff;
53  auto localView = basis.localView();
54  auto interpol = [&](auto const& lf, auto& localCoeff) {
55  localCoeff.resize(localView.size());
56  Traversal::forEachLeafNode(localView.tree(), [&](auto const& node, auto const& tp)
57  {
58  auto lf_at_tp = HierarchicNodeWrapper{tp,lf};
59  node.finiteElement().localInterpolation().interpolate(lf_at_tp, interpolationCoeff);
60  assert(node.size() == interpolationCoeff.size());
61  for (std::size_t i = 0; i < node.size(); ++i)
62  localCoeff[node.localIndex(i)] = interpolationCoeff[i];
63  });
64  };
65 
66  DiscreteFunction coeffFct{coeff, basis};
67  CoarsenedGridFunction c_gf{basis.gridView(), coeffFct};
68  auto c_lf = localFunction(c_gf);
69  auto const& idSet = basis.gridView().grid().localIdSet();
70  for (auto const& e : entitySet(basis))
71  {
72  localView.bind(e);
73 
74  // store the coefficients on the current element
75  coeff.gather(localView, persistentStorage_[idSet.id(e)]);
76 
77  // if the element might be coarsened, extract also interpolated coefficients on
78  // coarser elements
79  if (e.mightVanish()) {
80  auto father = e;
81  while (father.hasFather()) {
82  father = father.father();
83  auto [it,inserted] = persistentStorage_.try_emplace(idSet.id(father));
84  if (inserted) {
85  c_lf.bind(father);
86  interpol(c_lf, it->second);
87  }
88 
89  if (!inserted || !father.mightVanish())
90  break;
91  }
92  }
93  }
94  }
95 
96 
98  void adapt(Basis const& basis, Container& coeff)
99  {
100  coeff.init(basis, false);
101  auto localView = basis.localView();
102 
103  CoefficientVector interpolationCoeff;
104  auto interpol = [&](auto const& local, auto const& localCoeff) {
105  Traversal::forEachLeafNode(localView.tree(), [&](auto const& node, auto const& tp)
106  {
107  auto const& localFE = node.finiteElement();
108  auto const& localBasis = localFE.localBasis();
109  auto const& localInterpolation = localFE.localInterpolation();
110 
111  using LocalBasis = TYPEOF(localBasis);
112  using RangeType = typename LocalBasis::Traits::RangeType;
113  std::vector<RangeType> shapeValues;
114  localInterpolation.interpolate([&](auto const& x) {
115  localBasis.evaluateFunction(local(x), shapeValues);
116  auto range = localCoeff[node.localIndex(0)] * shapeValues[0];
117  assert(node.size() == shapeValues.size());
118  for (std::size_t i = 1; i < shapeValues.size(); ++i)
119  range.axpy(localCoeff[node.localIndex(i)], shapeValues[i]);
120  return range;
121  }, interpolationCoeff);
122  coeff.scatter(localView, node, interpolationCoeff, Assigner::assign{});
123  });
124  };
125 
126  auto const& idSet = basis.gridView().grid().localIdSet();
127  for (const auto& e : entitySet(basis))
128  {
129  localView.bind(e);
130  if (e.isNew()) {
131  // interpolate from coarser elements to the fine element
132  auto father = e;
133  std::function<Domain(Domain const&)> local = [](Domain const& x) { return x; };
134  [[maybe_unused]] bool found = false;
135  while (father.hasFather()) {
136  // store the coordinate transform
137  local = [local, geo=father.geometryInFather()](Domain const& x) {
138  return geo.global(local(x));
139  };
140  father = father.father();
141 
142  // if coarse element is found, interpolate to fine element
143  auto it = persistentStorage_.find(idSet.id(father));
144  if (it != persistentStorage_.end()) {
145  interpol(local, it->second);
146  found = true;
147  break;
148  }
149  }
150  assert(found);
151  } else {
152  // just extract the stored coefficients
153  auto it = persistentStorage_.find(idSet.id(e));
154  test_exit(it != persistentStorage_.end(),
155  "Element should be in persistent storage but isn't.");
156  coeff.scatter(localView, it->second, Assigner::assign{});
157  }
158  }
159 
160  coeff.finish();
161  }
162 
164  void postAdapt(Container& coeff)
165  {
166  persistentStorage_.clear();
167  };
168 };
169 
171 template <>
172 struct DataTransferFactory<tag::simple_datatransfer>
173 {
174  template <class Basis, class T, template <class> class Impl,
175  REQUIRES(Concepts::GlobalBasis<Basis>)>
176  static DataTransfer<Basis,VectorFacade<T,Impl>> create(Basis const&, VectorFacade<T,Impl> const&)
177  {
179  }
180 };
181 
183 
184 } // end namespace AMDiS
void preAdapt(Basis const &basis, Container const &coeff, bool mightCoarsen)
Create a persistent storage of the coefficients.
Definition: SimpleDataTransfer.hpp:50
The basic container that stores a base vector and a corresponding basis.
Definition: VectorFacade.hpp:38
Base tag type for all data transfer tags.
Definition: DataTransfer.hpp:121
Definition: AdaptBase.hpp:6
Definition: SimpleDataTransfer.hpp:33
void adapt(Basis const &basis, Container &coeff)
Transfer the content of the coefficients to the new basis.
Definition: SimpleDataTransfer.hpp:98
A mutable view on the subspace of a DOFVector,.
Definition: DOFVector.hpp:24
Tag that referrs to the SimpleDataTransfer.
Definition: SimpleDataTransfer.hpp:25
The base class for data transfer classes.
Definition: DataTransfer.hpp:66
Definition: DataTransfer.hpp:132
void postAdapt(Container &coeff)
Is called after the preAdapt step of the grid.
Definition: SimpleDataTransfer.hpp:164
A grid function defining data on a coarser entity level than it can be bound to.
Definition: CoarsenedGridFunction.hpp:27
Definition: HierarchicNodeToRangeMap.hpp:41
Definition: Assigner.hpp:7