AMDiS  0.3
The Adaptive Multi-Dimensional Simulation Toolbox
DiscreteLocalFunction.inc.hpp
1 #pragma once
2 
3 #include <amdis/Output.hpp>
4 #include <amdis/algorithm/ForEach.hpp>
5 #include <amdis/common/DerivativeTraits.hpp>
6 #include <amdis/common/FieldMatVec.hpp>
7 #include <amdis/common/Index.hpp>
8 #include <amdis/common/Math.hpp>
9 #include <amdis/functions/HierarchicNodeToRangeMap.hpp>
10 #include <amdis/functions/NodeIndices.hpp>
11 #include <amdis/functions/Order.hpp>
12 #include <amdis/typetree/FiniteElementType.hpp>
13 #include <amdis/utility/LocalToGlobalAdapter.hpp>
14 
15 #include <dune/common/ftraits.hh>
16 
17 namespace AMDiS {
18 namespace Impl {
19 
20 // specialization for containers with gather method
21 template <class Coeff, class LV, class LC>
22 auto gather(Coeff const& coeff, LV const& localView, LC& localCoeff, Dune::PriorityTag<2>)
23  -> std::void_t<decltype(coeff.gather(localView, localCoeff))>
24 {
25  coeff.gather(localView, localCoeff);
26 }
27 
28 // implementation for containers with multi-index access
29 template <class Coeff, class LV, class LC,
30  class MI = typename LV::MultiIndex>
31 auto gather(Coeff const& coeff, LV const& localView, LC& localCoeff, Dune::PriorityTag<1>)
32  -> std::void_t<decltype(coeff[std::declval<MI>()])>
33 {
34  localCoeff.resize(localView.size());
35  auto it = localCoeff.begin();
36  for (auto const& idx : nodeIndices(localView))
37  *it++ = coeff[idx];
38 }
39 
40 // fallback implementation
41 template <class Coeff, class LV, class LC>
42 auto gather(Coeff const& coeff, LV const& localView, LC& localCoeff, Dune::PriorityTag<0>)
43  -> std::void_t<decltype(coeff[index_<0>])>
44 {
45  auto backend = Dune::Functions::istlVectorBackend(coeff);
46  localCoeff.resize(localView.size());
47  auto it = localCoeff.begin();
48  for (auto const& idx : nodeIndices(localView))
49  *it++ = backend[idx];
50 }
51 
52 } // end namespace Impl
53 
54 
55 template <class C, class GB, class TP, class R>
56  template <class Type>
57 class DiscreteFunction<C const,GB,TP,R>::LocalFunction
58 {
59  using DomainType = typename DiscreteFunction::Domain;
60  using RangeType = typename DiscreteFunction::Range;
61 
62  template <class T>
63  using DerivativeRange = typename DerivativeTraits<RangeType(DomainType), T>::Range;
64 
65 public:
66  using Domain = typename EntitySet::LocalCoordinate;
67  using Range = DerivativeRange<Type>;
68 
69  enum { hasDerivative = std::is_same<Type, tag::value>::value };
70 
71 private:
72  using LocalView = typename GlobalBasis::LocalView;
73  using Element = typename EntitySet::Element;
74  using Geometry = typename Element::Geometry;
76 
77 public:
79  template <class LV>
80  LocalFunction(std::shared_ptr<LV> localView, TP const& treePath, C const& coefficients, Type type)
81  : localView_(std::move(localView))
82  , treePath_(treePath)
83  , coefficients_(coefficients)
84  , type_(type)
85  {}
86 
88  void bind(Element const& element)
89  {
90  localView_->bind(element);
91  geometry_.emplace(element.geometry());
92  Impl::gather(coefficients_, *localView_, localCoefficients_, Dune::PriorityTag<4>{});
93  bound_ = true;
94  }
95 
97  void unbind()
98  {
99  localView_->unbind();
100  geometry_.reset();
101  bound_ = false;
102  }
103 
105  Range operator() (const Domain& local) const
106  {
107  assert(bound_);
108  if constexpr (std::is_same_v<Type, tag::value>)
109  return evaluateFunction(local);
110  else if constexpr (std::is_same_v<Type, tag::gradient>)
111  return evaluateJacobian(local);
112  else if constexpr (std::is_same_v<Type, tag::partial>)
113  return evaluatePartialDerivative(local);
114  else if constexpr (std::is_same_v<Type, tag::divergence>) {
115  static constexpr bool isVectorNode
116  = SubTree::isPower && int(SubTree::degree()) == GridView::dimensionworld;
117  static_assert(isVectorNode);
118  if constexpr (isVectorNode)
119  return evaluateDivergence(local);
120  }
121 
122  return Range{};
123  }
124 
126  template <class DerType>
128  {
129  static_assert(std::is_same_v<Type, tag::value>);
130  return {localView_, treePath_, coefficients_, type};
131  }
132 
134  auto order() const
135  -> decltype(AMDiS::order(std::declval<SubTree>()))
136  {
137  assert(bound_);
138  return AMDiS::order(subTree());
139  }
140 
142  Element const& localContext() const
143  {
144  assert(bound_);
145  return localView_->element();
146  }
147 
148 private:
149 
150  template <class LocalCoordinate>
151  auto evaluateFunction (const LocalCoordinate& local) const;
152 
153  template <class LocalCoordinate>
154  auto evaluateJacobian (const LocalCoordinate& local) const;
155 
156  template <class LocalCoordinate>
157  auto evaluateDivergence (const LocalCoordinate& local) const;
158 
159  template <class LocalCoordinate>
160  auto evaluatePartialDerivative (const LocalCoordinate& local) const;
161 
162  // get the geometry of the bound element, that is constructed in the bind() method
163  Geometry const& geometry() const
164  {
165  assert(bound_);
166  return *geometry_;
167  }
168 
169  // return the sub-tree of the basis-tree associated to the tree-path
170  SubTree const& subTree() const
171  {
172  return Dune::TypeTree::child(localView_->tree(), treePath_);
173  }
174 
175  // return the sub-tree of the basis-tree-cache associated to the tree-path
176  // NOTE: this is only return in case the local-view does provide a treeCache() function
177  template <class LV,
178  class = decltype(std::declval<LV>().treeCache())>
179  auto const& subTreeCache(Dune::PriorityTag<1>) const
180  {
181  return Dune::TypeTree::child(localView_->treeCache(), treePath_);
182  }
183 
184  // construct a new tree-cache that stores a reference to the sub-tree
185  template <class>
186  auto subTreeCache(Dune::PriorityTag<0>) const
187  {
188  return makeNodeCache(subTree());
189  }
190 
191  decltype(auto) subTreeCache() const
192  {
193  return subTreeCache<LocalView>(Dune::PriorityTag<2>());
194  }
195 
196 private:
197  std::shared_ptr<LocalView> localView_;
198  TP treePath_;
199  Coefficients const& coefficients_;
200  Type type_;
201  NodeToRangeMap nodeToRangeMap_;
202 
203  std::optional<Geometry> geometry_;
204  std::vector<Coefficient> localCoefficients_;
205  bool bound_ = false;
206 };
207 
208 
209 template <class C, class GB, class TP, class R>
210  template <class Type>
211  template <class LocalCoordinate>
213 ::evaluateFunction(LocalCoordinate const& local) const
214 {
215  Range y;
216  Recursive::forEach(y, [](auto& v) { v = 0; });
217 
218  Traversal::forEachLeafNode(this->subTreeCache(), [&](auto const& node, auto const& tp)
219  {
220  auto const& shapeFunctionValues = node.localBasisValuesAt(local);
221  std::size_t size = node.finiteElement().size();
222 
223  // Get range entry associated to this node
224  auto re = Dune::Functions::flatVectorView(nodeToRangeMap_(node, tp, y));
225 
226  for (std::size_t i = 0; i < size; ++i) {
227  // Get coefficient associated to i-th shape function
228  auto c = Dune::Functions::flatVectorView(localCoefficients_[node.localIndex(i)]);
229 
230  // Get value of i-th shape function
231  auto v = Dune::Functions::flatVectorView(shapeFunctionValues[i]);
232 
233  std::size_t dimC = c.size();
234  std::size_t dimV = v.size();
235  assert(dimC*dimV == std::size_t(re.size()));
236  for(std::size_t j = 0; j < dimC; ++j) {
237  auto&& c_j = c[j];
238  for(std::size_t k = 0; k < dimV; ++k)
239  re[j*dimV + k] += c_j*v[k];
240  }
241  }
242  });
243 
244  return y;
245 }
246 
247 
248 template <class C, class GB, class TP, class R>
249  template <class Type>
250  template <class LocalCoordinate>
252 ::evaluateJacobian(LocalCoordinate const& local) const
253 {
254  Range dy;
255  Recursive::forEach(dy, [](auto& v) { v = 0; });
256 
257  Traversal::forEachLeafNode(this->subTreeCache(), [&](auto const& node, auto const& tp)
258  {
259  LocalToGlobalBasisAdapter localBasis(node, this->geometry());
260  auto const& gradients = localBasis.gradientsAt(local);
261 
262  // Get range entry associated to this node
263  auto re = Dune::Functions::flatVectorView(nodeToRangeMap_(node, tp, dy));
264 
265  for (std::size_t i = 0; i < localBasis.size(); ++i) {
266  // Get coefficient associated to i-th shape function
267  auto c = Dune::Functions::flatVectorView(localCoefficients_[node.localIndex(i)]);
268 
269  // Get value of i-th transformed reference gradient
270  auto grad = Dune::Functions::flatVectorView(gradients[i]);
271 
272  std::size_t dimC = c.size();
273  std::size_t dimV = grad.size();
274  assert(dimC*dimV == std::size_t(re.size()));
275  for(std::size_t j = 0; j < dimC; ++j) {
276  auto&& c_j = c[j];
277  for(std::size_t k = 0; k < dimV; ++k)
278  re[j*dimV + k] += c_j*grad[k];
279  }
280  }
281  });
282 
283  return dy;
284 }
285 
286 
287 template <class C, class GB, class TP, class R>
288  template <class Type>
289  template <class LocalCoordinate>
291 ::evaluateDivergence(LocalCoordinate const& local) const
292 {
293  static_assert(static_size_v<Range> == 1, "Divergence implemented for scalar coefficients only.");
294 
295  Range dy;
296  Recursive::forEach(dy, [](auto& v) { v = 0; });
297 
298  auto&& node = this->subTreeCache();
299 
300  LocalToGlobalBasisAdapter localBasis(node.child(0), this->geometry());
301  auto const& gradients = localBasis.gradientsAt(local);
302 
303  auto re = Dune::Functions::flatVectorView(dy);
304  assert(int(re.size()) == 1);
305  for (std::size_t i = 0; i < localBasis.size(); ++i) {
306  auto grad = Dune::Functions::flatVectorView(gradients[i]);
307 
308  assert(int(grad.size()) == GridView::dimensionworld);
309  for (std::size_t j = 0; j < GridView::dimensionworld; ++j)
310  re[0] += localCoefficients_[node.child(j).localIndex(i)] * grad[j];
311  }
312 
313  return dy;
314 }
315 
316 
317 template <class C, class GB, class TP, class R>
318  template <class Type>
319  template <class LocalCoordinate>
321 ::evaluatePartialDerivative(LocalCoordinate const& local) const
322 {
323  std::size_t comp = this->type_.comp;
324 
325  Range dy;
326  Recursive::forEach(dy, [](auto& v) { v = 0; });
327 
328  Traversal::forEachLeafNode(this->subTreeCache(), [&](auto const& node, auto const& tp)
329  {
330  LocalToGlobalBasisAdapter localBasis(node, this->geometry());
331  auto const& partial = localBasis.partialsAt(local, comp);
332 
333  // Get range entry associated to this node
334  auto re = Dune::Functions::flatVectorView(nodeToRangeMap_(node, tp, dy));
335 
336  for (std::size_t i = 0; i < localBasis.size(); ++i) {
337  // Get coefficient associated to i-th shape function
338  auto c = Dune::Functions::flatVectorView(localCoefficients_[node.localIndex(i)]);
339 
340  // Get value of i-th transformed reference partial_derivative
341  auto d_comp = Dune::Functions::flatVectorView(partial[i]);
342 
343  std::size_t dimC = c.size();
344  std::size_t dimV = d_comp.size();
345  assert(dimC*dimV == std::size_t(re.size()));
346  for(std::size_t j = 0; j < dimC; ++j) {
347  auto&& c_j = c[j];
348  for(std::size_t k = 0; k < dimV; ++k)
349  re[j*dimV + k] += c_j*d_comp[k];
350  }
351  }
352  });
353 
354  return dy;
355 }
356 
357 
358 } // end namespace AMDiS
LocalFunction(std::shared_ptr< LV > localView, TP const &treePath, C const &coefficients, Type type)
Constructor. Stores a copy of the DiscreteFunction.
Definition: DiscreteLocalFunction.inc.hpp:80
constexpr bool MultiIndex
A multi-index type.
Definition: Concepts.hpp:150
Convert a simple (scalar) local basis into a global basis.
Definition: LocalToGlobalAdapter.hpp:64
Definition: FieldMatVec.hpp:12
AMDiS::LocalView< Self > LocalView
Type of the local view on the restriction of the basis to a single element.
Definition: GlobalBasis.hpp:67
Definition: AdaptBase.hpp:6
A mutable view on the subspace of a DOFVector,.
Definition: DiscreteFunction.hpp:36
std::size_t size() const
Return the number of local basis functions.
Definition: LocalToGlobalAdapter.hpp:96
A simple node to range map using the nested tree indices.
Definition: HierarchicNodeToRangeMap.hpp:23
auto const & partialsAt(typename Traits::DomainLocal const &x, std::size_t comp) const
Definition: LocalToGlobalAdapter.hpp:176
LocalFunction< DerType > makeDerivative(DerType type) const
Create a LocalFunction representing the derivative.
Definition: DiscreteLocalFunction.inc.hpp:127
void bind(Element const &element)
Bind the LocalView to the element.
Definition: DiscreteLocalFunction.inc.hpp:88
Definition: DerivativeTraits.hpp:29
void unbind()
Unbind the LocalView from the element.
Definition: DiscreteLocalFunction.inc.hpp:97
auto order() const -> decltype(AMDiS::order(std::declval< SubTree >()))
The polynomial degree of the LocalFunctions basis-functions.
Definition: DiscreteLocalFunction.inc.hpp:134
Element const & localContext() const
Return the bound element.
Definition: DiscreteLocalFunction.inc.hpp:142
Definition: DiscreteLocalFunction.inc.hpp:57
auto const & gradientsAt(typename Traits::DomainLocal const &x) const
Definition: LocalToGlobalAdapter.hpp:147