AMDiS  0.1
The Adaptive Multi-Dimensional Simulation Toolbox
DiscreteLocalFunction.inc.hpp
1 #pragma once
2 
3 #include <amdis/Output.hpp>
4 #include <amdis/common/DerivativeTraits.hpp>
5 #include <amdis/common/FieldMatVec.hpp>
6 #include <amdis/common/Math.hpp>
7 #include <amdis/functions/NodeIndices.hpp>
8 #include <amdis/functions/Order.hpp>
9 #include <amdis/typetree/FiniteElementType.hpp>
10 #include <amdis/utility/LocalToGlobalAdapter.hpp>
11 
12 #include <dune/common/ftraits.hh>
13 
14 namespace AMDiS {
15 namespace Impl {
16 
17 // specialization of Coeff has gather method
18 template <class Coeff, class LocalView, class LocalCoeff,
19  class = decltype(std::declval<Coeff>().gather(std::declval<LocalView>(), std::declval<LocalCoeff&>()))>
20 void gather(Coeff const& coeff, LocalView const& localView, LocalCoeff& localCoeff, Dune::PriorityTag<2>)
21 {
22  coeff.gather(localView, localCoeff);
23 }
24 
25 // fallback implementation
26 template <class Coeff, class LocalView, class LocalCoeff>
27 void gather(Coeff const& coeff, LocalView const& localView, LocalCoeff& localCoeff, Dune::PriorityTag<1>)
28 {
29  localCoeff.resize(localView.size());
30  auto it = localCoeff.begin();
31  for (auto const& idx : nodeIndices(localView))
32  *it++ = coeff[idx];
33 }
34 
35 } // end namespace Impl
36 
37 
38 template <class Coeff, class GB, class TP>
39 class DiscreteFunction<Coeff const,GB,TP>::LocalFunction
40 {
41 public:
42  using Domain = typename EntitySet::LocalCoordinate;
43  using Range = typename DiscreteFunction::Range;
44 
45  enum { hasDerivative = true };
46 
47 private:
48  using LocalView = typename GlobalBasis::LocalView;
49  using Element = typename EntitySet::Element;
50  using Geometry = typename Element::Geometry;
51 
52 public:
54  LocalFunction(DiscreteFunction const& globalFunction)
55  : globalFunction_(globalFunction)
56  , localView_(globalFunction_.basis().localView())
57  , subTreeCache_(&Dune::TypeTree::child(localView_.treeCache(), globalFunction_.treePath()))
58  {}
59 
62  : globalFunction_(other.globalFunction_)
63  , localView_(globalFunction_.basis().localView())
64  , subTreeCache_(&Dune::TypeTree::child(localView_.treeCache(), globalFunction_.treePath()))
65  {}
66 
68  void bind(Element const& element)
69  {
70  localView_.bind(element);
71  Impl::gather(globalFunction_.coefficients(), localView_, localCoefficients_, Dune::PriorityTag<4>{});
72  bound_ = true;
73  }
74 
76  void unbind()
77  {
78  localView_.unbind();
79  bound_ = false;
80  }
81 
83  Range operator()(Domain const& x) const
84  {
85  assert( bound_ );
86  Range y(0);
87 
88  auto&& nodeToRangeEntry = globalFunction_.nodeToRangeEntry_;
89  for_each_leaf_node(*subTreeCache_, [&,this](auto const& node, auto const& tp)
90  {
91  auto const& shapeFunctionValues = node.localBasisValuesAt(x);
92  std::size_t size = node.finiteElement().size();
93 
94  // Get range entry associated to this node
95  auto re = Dune::Functions::flatVectorView(nodeToRangeEntry(node, tp, y));
96 
97  for (std::size_t i = 0; i < size; ++i) {
98  // Get coefficient associated to i-th shape function
99  auto c = Dune::Functions::flatVectorView(localCoefficients_[node.localIndex(i)]);
100 
101  // Get value of i-th shape function
102  auto v = Dune::Functions::flatVectorView(shapeFunctionValues[i]);
103 
104  std::size_t dimC = c.size();
105  std::size_t dimV = v.size();
106  assert(dimC*dimV == std::size_t(re.size()));
107  for(std::size_t j = 0; j < dimC; ++j) {
108  auto&& c_j = c[j];
109  for(std::size_t k = 0; k < dimV; ++k)
110  re[j*dimV + k] += c_j*v[k];
111  }
112  }
113  });
114 
115  return y;
116  }
117 
120  {
121  return GradientLocalFunction{globalFunction_, type};
122  }
123 
124  DivergenceLocalFunction makeDerivative(tag::divergence type) const
125  {
126  return DivergenceLocalFunction{globalFunction_, type};
127  }
128 
129  PartialLocalFunction makeDerivative(tag::partial type) const
130  {
131  return PartialLocalFunction{globalFunction_, type};
132  }
133 
135  auto order() const
136  -> decltype(AMDiS::order(std::declval<SubTree>()))
137  {
138  assert( bound_ );
139  return AMDiS::order(*subTreeCache_);
140  }
141 
143  Element const& localContext() const
144  {
145  assert( bound_ );
146  return localView_.element();
147  }
148 
149 private:
150  DiscreteFunction globalFunction_;
151  LocalView localView_;
152  SubTreeCache const* subTreeCache_;
153 
154  std::vector<ValueType> localCoefficients_;
155  bool bound_ = false;
156 };
157 
158 
159 template <class Coeff, class GB, class TP>
160  template <class Type>
162 {
163  using R = typename DiscreteFunction::Range;
164  using D = typename DiscreteFunction::Domain;
165  using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
167 
168 public:
169  using Domain = typename EntitySet::LocalCoordinate;
170  using Range = typename Traits::Range;
171 
172  enum { hasDerivative = false };
173 
174 private:
175  using LocalView = typename GlobalBasis::LocalView;
176  using Element = typename EntitySet::Element;
177  using Geometry = typename Element::Geometry;
178 
179 public:
181  DerivativeLocalFunctionBase(DiscreteFunction const& globalFunction, Type const& type)
182  : globalFunction_(globalFunction)
183  , type_(type)
184  , localView_(globalFunction_.basis().localView())
185  , subTreeCache_(&Dune::TypeTree::child(localView_.treeCache(), globalFunction_.treePath()))
186  {}
187 
190  : globalFunction_(other.globalFunction_)
191  , type_(other.type_)
192  , localView_(globalFunction_.basis().localView())
193  , subTreeCache_(&Dune::TypeTree::child(localView_.treeCache(), globalFunction_.treePath()))
194  {}
195 
196  void bind(Element const& element)
197  {
198  localView_.bind(element);
199  geometry_.emplace(element.geometry());
200 
201  Impl::gather(globalFunction_.coefficients(), localView_, localCoefficients_, Dune::PriorityTag<4>{});
202  bound_ = true;
203  }
204 
205  void unbind()
206  {
207  localView_.unbind();
208  geometry_.reset();
209  bound_ = false;
210  }
211 
212  auto order() const
213  -> decltype(AMDiS::order(std::declval<SubTree>()))
214  {
215  assert( bound_ );
216  return std::max(0, AMDiS::order(*subTreeCache_)-1);
217  }
218 
220  Element const& localContext() const
221  {
222  assert( bound_ );
223  return localView_.element();
224  }
225 
226  Geometry const& geometry() const
227  {
228  assert( bound_ );
229  return geometry_.value();
230  }
231 
232  LocalView const& localView() const
233  {
234  return localView_;
235  }
236 
237 protected:
238  DiscreteFunction globalFunction_;
239  Type type_;
240  LocalView localView_;
241  SubTreeCache const* subTreeCache_;
242  std::optional<Geometry> geometry_;
243  std::vector<ValueType> localCoefficients_;
244  bool bound_ = false;
245 };
246 
247 
248 template <class Coeff, class GB, class TP>
249 class DiscreteFunction<Coeff const,GB,TP>::GradientLocalFunction
250  : public DerivativeLocalFunctionBase<tag::gradient>
251 {
253 public:
254  using Range = typename Super::Range;
255  using Domain = typename Super::Domain;
256 
257  // adopt constructor from base class
259 
261  Range operator()(Domain const& x) const
262  {
263  assert( this->bound_ );
264  Range dy(0);
265 
266  auto&& nodeToRangeEntry = this->globalFunction_.nodeToRangeEntry_;
267  for_each_leaf_node(*this->subTreeCache_, [&](auto const& node, auto const& tp)
268  {
269  LocalToGlobalBasisAdapter localBasis(node, this->geometry());
270  auto const& gradients = localBasis.gradientsAt(x);
271 
272  // Get range entry associated to this node
273  auto re = Dune::Functions::flatVectorView(nodeToRangeEntry(node, tp, dy));
274 
275  for (std::size_t i = 0; i < localBasis.size(); ++i) {
276  // Get coefficient associated to i-th shape function
277  auto c = Dune::Functions::flatVectorView(this->localCoefficients_[node.localIndex(i)]);
278 
279  // Get value of i-th transformed reference gradient
280  auto grad = Dune::Functions::flatVectorView(gradients[i]);
281 
282  std::size_t dimC = c.size();
283  std::size_t dimV = grad.size();
284  assert(dimC*dimV == std::size_t(re.size()));
285  for(std::size_t j = 0; j < dimC; ++j) {
286  auto&& c_j = c[j];
287  for(std::size_t k = 0; k < dimV; ++k)
288  re[j*dimV + k] += c_j*grad[k];
289  }
290  }
291  });
292 
293  return dy;
294  }
295 
296  using Super::localCoefficients_;
297 };
298 
299 
300 template <class Coeff, class GB, class TP>
301 class DiscreteFunction<Coeff const,GB,TP>::DivergenceLocalFunction
302  : public DerivativeLocalFunctionBase<tag::divergence>
303 {
305 
306 public:
307  using Range = typename Super::Range;
308  using Domain = typename Super::Domain;
309 
310  // adopt constructor from base class
312 
314  Range operator()(Domain const& x) const
315  {
316  return evaluate_node(x, bool_t<SubTree::isPower && SubTree::degree() == GridView::dimensionworld>{});
317  }
318 
319 private:
320  Range evaluate_node(Domain const& x, std::false_type) const
321  {
322  error_exit("Cannot calculate divergence(node) where node is not a power node.");
323  return Range(0);
324  }
325 
326  Range evaluate_node(Domain const& x, std::true_type) const
327  {
328  static_assert(static_size_v<Range> == 1, "Implemented for scalar coefficients only.");
329 
330  assert( this->bound_ );
331  Range dy(0);
332 
333  auto&& node = *this->subTreeCache_;
334 
335  LocalToGlobalBasisAdapter localBasis(node.child(0), this->geometry());
336  auto const& gradients = localBasis.gradientsAt(x);
337 
338  auto re = Dune::Functions::flatVectorView(dy);
339  assert(int(re.size()) == 1);
340  for (std::size_t i = 0; i < localBasis.size(); ++i) {
341  auto grad = Dune::Functions::flatVectorView(gradients[i]);
342 
343  assert(int(grad.size()) == GridView::dimensionworld);
344  for (std::size_t j = 0; j < GridView::dimensionworld; ++j)
345  re[0] += localCoefficients_[node.child(j).localIndex(i)] * grad[j];
346  }
347 
348  return dy;
349  }
350 
351  using Super::localCoefficients_;
352 };
353 
354 
355 template <class Coeff, class GB, class TP>
356 class DiscreteFunction<Coeff const,GB,TP>::PartialLocalFunction
357  : public DerivativeLocalFunctionBase<tag::partial>
358 {
360 
361 public:
362  using Range = typename Super::Range;
363  using Domain = typename Super::Domain;
364 
366 
368  Range operator()(Domain const& x) const
369  {
370  assert( this->bound_ );
371  Range dy(0);
372 
373  std::size_t comp = this->type_.comp;
374 
375  auto&& nodeToRangeEntry = this->globalFunction_.nodeToRangeEntry_;
376  for_each_leaf_node(*this->subTreeCache_, [&](auto const& node, auto const& tp)
377  {
378  LocalToGlobalBasisAdapter localBasis(node, this->geometry());
379  auto const& partial = localBasis.partialsAt(x, comp);
380 
381  // Get range entry associated to this node
382  auto re = Dune::Functions::flatVectorView(nodeToRangeEntry(node, tp, dy));
383 
384  for (std::size_t i = 0; i < localBasis.size(); ++i) {
385  // Get coefficient associated to i-th shape function
386  auto c = Dune::Functions::flatVectorView(this->localCoefficients_[node.localIndex(i)]);
387 
388  // Get value of i-th transformed reference partial_derivative
389  auto d_comp = Dune::Functions::flatVectorView(partial[i]);
390 
391  std::size_t dimC = c.size();
392  std::size_t dimV = d_comp.size();
393  assert(dimC*dimV == std::size_t(re.size()));
394  for(std::size_t j = 0; j < dimC; ++j) {
395  auto&& c_j = c[j];
396  for(std::size_t k = 0; k < dimV; ++k)
397  re[j*dimV + k] += c_j*d_comp[k];
398  }
399  }
400  });
401 
402  return dy;
403  }
404 
405  using Super::localCoefficients_;
406 };
407 
408 
409 } // end namespace AMDiS
void for_each_leaf_node(Tree &&tree, LeafFunc &&leafFunc)
Traverse tree and visit each leaf node.
Definition: Traversal.hpp:127
Definition: DiscreteLocalFunction.inc.hpp:161
DerivativeLocalFunctionBase(DerivativeLocalFunctionBase const &other)
Copy constructor.
Definition: DiscreteLocalFunction.inc.hpp:189
Range operator()(Domain const &x) const
Evaluate LocalFunction at bound element in local coordinates.
Definition: DiscreteLocalFunction.inc.hpp:83
GradientLocalFunction makeDerivative(tag::gradient type) const
Create a LocalFunction representing the gradient.
Definition: DiscreteLocalFunction.inc.hpp:119
Range operator()(Domain const &x) const
Evaluate Gradient at bound element in local coordinates.
Definition: DiscreteLocalFunction.inc.hpp:261
Convert a simple (scalar) local basis into a global basis.
Definition: LocalToGlobalAdapter.hpp:64
Definition: AdaptiveGrid.hpp:373
Definition: DerivativeTraits.hpp:21
void error_exit(std::string const &str, Args &&... args)
print a message and exit
Definition: Output.hpp:142
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:70
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
constexpr bool LocalView
A Dune::Functions::LocalView type.
Definition: Concepts.hpp:182
A mutable view on the subspace of a DOFVector,.
Definition: DiscreteFunction.hpp:33
Definition: DerivativeTraits.hpp:20
std::size_t size() const
Return the number of local basis functions.
Definition: LocalToGlobalAdapter.hpp:96
Definition: DerivativeTraits.hpp:19
auto order(F const &f) -> decltype(&F::operator(), f.order())
polynomial order of functions
Definition: Order.hpp:11
auto const & partialsAt(typename Traits::DomainLocal const &x, std::size_t comp) const
Definition: LocalToGlobalAdapter.hpp:176
Definition: DiscreteLocalFunction.inc.hpp:356
DerivativeLocalFunctionBase(DiscreteFunction const &globalFunction, Type const &type)
Constructor. Stores a copy of the DiscreteFunction.
Definition: DiscreteLocalFunction.inc.hpp:181
void bind(Element const &element)
Bind the LocalView to the element.
Definition: DiscreteLocalFunction.inc.hpp:68
LocalFunction(DiscreteFunction const &globalFunction)
Constructor. Stores a copy of the DiscreteFunction.
Definition: DiscreteLocalFunction.inc.hpp:54
Range operator()(Domain const &x) const
Evaluate divergence at bound element in local coordinates.
Definition: DiscreteLocalFunction.inc.hpp:314
Element const & localContext() const
Return the bound element.
Definition: DiscreteLocalFunction.inc.hpp:220
LocalFunction(LocalFunction const &other)
Copy constructor.
Definition: DiscreteLocalFunction.inc.hpp:61
Definition: DerivativeTraits.hpp:28
void unbind()
Unbind the LocalView from the element.
Definition: DiscreteLocalFunction.inc.hpp:76
auto order() const -> decltype(AMDiS::order(std::declval< SubTree >()))
The polynomial degree of the LocalFunctions basis-functions.
Definition: DiscreteLocalFunction.inc.hpp:135
std::integral_constant< bool, B > bool_t
A wrapper for bool types.
Definition: Logical.hpp:12
Element const & localContext() const
Return the bound element.
Definition: DiscreteLocalFunction.inc.hpp:143
Range operator()(Domain const &x) const
Evaluate partial derivative at bound element in local coordinates.
Definition: DiscreteLocalFunction.inc.hpp:368
auto nodeIndices(LocalView const &localView, Node const &node)
Returns a range over (flat) DOF indices on a node, given by the localView.
Definition: NodeIndices.hpp:13
Definition: DiscreteLocalFunction.inc.hpp:39
Definition: DiscreteLocalFunction.inc.hpp:249
Definition: DiscreteLocalFunction.inc.hpp:301
auto const & gradientsAt(typename Traits::DomainLocal const &x) const
Definition: LocalToGlobalAdapter.hpp:147