DUNE PDELab (git)

discreteglobalbasisfunction.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_FUNCTIONS_GRIDFUNCTIONS_DISCRETEGLOBALBASISFUNCTIONS_HH
4#define DUNE_FUNCTIONS_GRIDFUNCTIONS_DISCRETEGLOBALBASISFUNCTIONS_HH
5
6#include <memory>
7#include <optional>
8
10
12
13#include <dune/typetree/treecontainer.hh>
14
15#include <dune/functions/functionspacebases/hierarchicnodetorangemap.hh>
16#include <dune/functions/functionspacebases/flatvectorview.hh>
17#include <dune/functions/gridfunctions/gridviewentityset.hh>
18#include <dune/functions/gridfunctions/gridfunction.hh>
19#include <dune/functions/backends/concepts.hh>
20#include <dune/functions/backends/istlvectorbackend.hh>
21
22namespace Dune {
23namespace Functions {
24
25
26namespace ImplDoc {
27
28template<typename B, typename V, typename NTRE>
29class DiscreteGlobalBasisFunctionBase
30{
31public:
32 using Basis = B;
33 using Vector = V;
34
35 // In order to make the cache work for proxy-references
36 // we have to use AutonomousValue<T> instead of std::decay_t<T>
37 using Coefficient = Dune::AutonomousValue<decltype(std::declval<Vector>()[std::declval<typename Basis::MultiIndex>()])>;
38
39 using GridView = typename Basis::GridView;
40 using EntitySet = GridViewEntitySet<GridView, 0>;
41 using Tree = typename Basis::LocalView::Tree;
42 using NodeToRangeEntry = NTRE;
43
44 using Domain = typename EntitySet::GlobalCoordinate;
45
46 using LocalDomain = typename EntitySet::LocalCoordinate;
47 using Element = typename EntitySet::Element;
48
49protected:
50
51 // This collects all data that is shared by all related
52 // global and local functions. This way we don't need to
53 // keep track of it individually.
54 struct Data
55 {
56 EntitySet entitySet;
57 std::shared_ptr<const Basis> basis;
58 std::shared_ptr<const Vector> coefficients;
59 std::shared_ptr<const NodeToRangeEntry> nodeToRangeEntry;
60 };
61
62public:
63 class LocalFunctionBase
64 {
65 using LocalView = typename Basis::LocalView;
66 using size_type = typename Tree::size_type;
67
68 public:
69 using Domain = LocalDomain;
70 using Element = typename EntitySet::Element;
71
72 protected:
73 LocalFunctionBase(const std::shared_ptr<const Data>& data)
74 : data_(data)
75 , localView_(data_->basis->localView())
76 {
77 localDoFs_.reserve(localView_.maxSize());
78 }
79
86 LocalFunctionBase(const LocalFunctionBase& other)
87 : data_(other.data_)
88 , localView_(other.localView_)
89 {
90 localDoFs_.reserve(localView_.maxSize());
91 if (bound())
92 localDoFs_ = other.localDoFs_;
93 }
94
102 LocalFunctionBase& operator=(const LocalFunctionBase& other)
103 {
104 data_ = other.data_;
105 localView_ = other.localView_;
106 if (bound())
107 localDoFs_ = other.localDoFs_;
108 return *this;
109 }
110
111 public:
118 void bind(const Element& element)
119 {
120 localView_.bind(element);
121 // Use cache of full local view size. For a subspace basis,
122 // this may be larger than the number of local DOFs in the
123 // tree. In this case only cache entries associated to local
124 // DOFs in the subspace are filled. Cache entries associated
125 // to local DOFs which are not contained in the subspace will
126 // not be touched.
127 //
128 // Alternatively one could use a cache that exactly fits
129 // the size of the tree. However, this would require to
130 // subtract an offset from localIndex(i) on each cache
131 // access in operator().
132 localDoFs_.resize(localView_.size());
133 const auto& dofs = *data_->coefficients;
134 for (size_type i = 0; i < localView_.tree().size(); ++i)
135 {
136 // For a subspace basis the index-within-tree i
137 // is not the same as the localIndex within the
138 // full local view.
139 size_t localIndex = localView_.tree().localIndex(i);
140 localDoFs_[localIndex] = dofs[localView_.index(localIndex)];
141 }
142 }
143
145 void unbind()
146 {
147 localView_.unbind();
148 }
149
151 bool bound() const
152 {
153 return localView_.bound();
154 }
155
157 const Element& localContext() const
158 {
159 return localView_.element();
160 }
161
162 protected:
163
164 template<class To, class From>
165 void assignWith(To& to, const From& from) const
166 {
167 auto from_flat = flatVectorView(from);
168 auto to_flat = flatVectorView(to);
169 assert(from_flat.size() == to_flat.size());
170 for (size_type i = 0; i < to_flat.size(); ++i)
171 to_flat[i] = from_flat[i];
172 }
173
174 template<class Node, class TreePath, class Range>
175 decltype(auto) nodeToRangeEntry(const Node& node, const TreePath& treePath, Range& y) const
176 {
177 return (*data_->nodeToRangeEntry)(node, treePath, y);
178 }
179
180 std::shared_ptr<const Data> data_;
181 LocalView localView_;
182 std::vector<Coefficient> localDoFs_;
183 };
184
185protected:
186 DiscreteGlobalBasisFunctionBase(const std::shared_ptr<const Data>& data)
187 : data_(data)
188 {
189 /* Nothing. */
190 }
191
192public:
193
195 const Basis& basis() const
196 {
197 return *data_->basis;
198 }
199
201 const Vector& dofs() const
202 {
203 return *data_->coefficients;
204 }
205
207 const NodeToRangeEntry& nodeToRangeEntry() const
208 {
209 return *data_->nodeToRangeEntry;
210 }
211
213 const EntitySet& entitySet() const
214 {
215 return data_->entitySet;
216 }
217
218protected:
219 std::shared_ptr<const Data> data_;
220};
221
222} // namespace ImplDoc
223
224
225
226template<typename DGBF>
227class DiscreteGlobalBasisFunctionDerivative;
228
272template<typename B, typename V,
273 typename NTRE = HierarchicNodeToRangeMap,
274 typename R = typename V::value_type>
276 : public ImplDoc::DiscreteGlobalBasisFunctionBase<B, V, NTRE>
277{
278 using Base = ImplDoc::DiscreteGlobalBasisFunctionBase<B, V, NTRE>;
279 using Data = typename Base::Data;
280
281public:
282 using Basis = typename Base::Basis;
283 using Vector = typename Base::Vector;
284
285 using Domain = typename Base::Domain;
286 using Range = R;
287
288 using Traits = Imp::GridFunctionTraits<Range(Domain), typename Base::EntitySet, DefaultDerivativeTraits, 16>;
289
290private:
291
292 template<class Node>
293 using LocalBasisRange = typename Node::FiniteElement::Traits::LocalBasisType::Traits::RangeType;
294 template<class Node>
295 using NodeData = typename std::vector<LocalBasisRange<Node>>;
296 using PerNodeEvaluationBuffer = typename TypeTree::TreeContainer<NodeData, typename Base::Tree>;
297
298public:
299 class LocalFunction
300 : public Base::LocalFunctionBase
301 {
302 using LocalBase = typename Base::LocalFunctionBase;
303 using size_type = typename Base::Tree::size_type;
304 using LocalBase::nodeToRangeEntry;
305
306 public:
307
308 using GlobalFunction = DiscreteGlobalBasisFunction;
309 using Domain = typename LocalBase::Domain;
310 using Range = GlobalFunction::Range;
311 using Element = typename LocalBase::Element;
312
314 LocalFunction(const DiscreteGlobalBasisFunction& globalFunction)
315 : LocalBase(globalFunction.data_)
316 , evaluationBuffer_(this->localView_.tree())
317 {
318 /* Nothing. */
319 }
320
330 Range operator()(const Domain& x) const
331 {
332 Range y;
333 istlVectorBackend(y) = 0;
334
335 TypeTree::forEachLeafNode(this->localView_.tree(), [&](auto&& node, auto&& treePath) {
336 const auto& fe = node.finiteElement();
337 const auto& localBasis = fe.localBasis();
338 auto& shapeFunctionValues = evaluationBuffer_[treePath];
339
340 localBasis.evaluateFunction(x, shapeFunctionValues);
341
342 // Compute linear combinations of basis function jacobian.
343 // Non-scalar coefficients of dimension coeffDim are handled by
344 // processing the coeffDim linear combinations independently
345 // and storing them as entries of an array.
346 using Value = LocalBasisRange< std::decay_t<decltype(node)> >;
347 static constexpr auto coeffDim = decltype(flatVectorView(this->localDoFs_[node.localIndex(0)]).size())::value;
348 auto values = std::array<Value, coeffDim>{};
349 istlVectorBackend(values) = 0;
350 for (size_type i = 0; i < localBasis.size(); ++i)
351 {
352 auto c = flatVectorView(this->localDoFs_[node.localIndex(i)]);
353 for (std::size_t j = 0; j < coeffDim; ++j)
354 values[j].axpy(c[j], shapeFunctionValues[i]);
355 }
356
357 // Assign computed values to node entry of range.
358 // Types are matched using the lexicographic ordering provided by flatVectorView.
359 LocalBase::assignWith(nodeToRangeEntry(node, treePath, y), values);
360 });
361
362 return y;
363 }
364
367 {
369 if (lf.bound())
370 dlf.bind(lf.localContext());
371 return dlf;
372 }
373
374 private:
375 mutable PerNodeEvaluationBuffer evaluationBuffer_;
376 };
377
379 template<class B_T, class V_T, class NTRE_T>
380 DiscreteGlobalBasisFunction(B_T && basis, V_T && coefficients, NTRE_T&& nodeToRangeEntry)
381 : Base(std::make_shared<Data>(Data{{basis.gridView()}, wrap_or_move(std::forward<B_T>(basis)), wrap_or_move(std::forward<V_T>(coefficients)), wrap_or_move(std::forward<NTRE_T>(nodeToRangeEntry))}))
382 {}
383
385 DiscreteGlobalBasisFunction(std::shared_ptr<const Basis> basis, std::shared_ptr<const V> coefficients, std::shared_ptr<const typename Base::NodeToRangeEntry> nodeToRangeEntry)
386 : Base(std::make_shared<Data>(Data{{basis->gridView()}, basis, coefficients, nodeToRangeEntry}))
387 {}
388
394 Range operator() (const Domain& x) const
395 {
396 HierarchicSearch search(this->data_->basis->gridView().grid(), this->data_->basis->gridView().indexSet());
397
398 const auto e = search.findEntity(x);
399 auto localThis = localFunction(*this);
400 localThis.bind(e);
401 return localThis(e.geometry().local(x));
402 }
403
406 {
408 }
409
418 friend LocalFunction localFunction(const DiscreteGlobalBasisFunction& t)
419 {
420 return LocalFunction(t);
421 }
422};
423
424
449template<typename R, typename B, typename V>
450auto makeDiscreteGlobalBasisFunction(B&& basis, V&& vector)
451{
452 using Basis = std::decay_t<B>;
453 using NTREM = HierarchicNodeToRangeMap;
454
455 // Small helper functions to wrap vectors using istlVectorBackend
456 // if they do not already satisfy the VectorBackend interface.
457 auto toConstVectorBackend = [&](auto&& v) -> decltype(auto) {
458 if constexpr (models<Concept::ConstVectorBackend<Basis>, decltype(v)>()) {
459 return std::forward<decltype(v)>(v);
460 } else {
461 return istlVectorBackend(v);
462 }
463 };
464
465 using Vector = std::decay_t<decltype(toConstVectorBackend(std::forward<V>(vector)))>;
467 std::forward<B>(basis),
468 toConstVectorBackend(std::forward<V>(vector)),
470}
471
472
487template<typename DGBF>
489 : public ImplDoc::DiscreteGlobalBasisFunctionBase<typename DGBF::Basis, typename DGBF::Vector, typename DGBF::NodeToRangeEntry>
490{
491 using Base = ImplDoc::DiscreteGlobalBasisFunctionBase<typename DGBF::Basis, typename DGBF::Vector, typename DGBF::NodeToRangeEntry>;
492 using Data = typename Base::Data;
493
494public:
495 using DiscreteGlobalBasisFunction = DGBF;
496
497 using Basis = typename Base::Basis;
498 using Vector = typename Base::Vector;
499
500 using Domain = typename Base::Domain;
502
503 using Traits = Imp::GridFunctionTraits<Range(Domain), typename Base::EntitySet, DefaultDerivativeTraits, 16>;
504
505private:
506
507 template<class Node>
508 using LocalBasisRange = typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType;
509 template<class Node>
510 using NodeData = typename std::vector< LocalBasisRange<Node> >;
511 using PerNodeEvaluationBuffer = typename TypeTree::TreeContainer<NodeData, typename Base::Tree>;
512
513public:
514
523 : public Base::LocalFunctionBase
524 {
525 using LocalBase = typename Base::LocalFunctionBase;
526 using size_type = typename Base::Tree::size_type;
527 using LocalBase::nodeToRangeEntry;
528
529 public:
531 using Domain = typename LocalBase::Domain;
532 using Range = GlobalFunction::Range;
533 using Element = typename LocalBase::Element;
534
536 LocalFunction(const GlobalFunction& globalFunction)
537 : LocalBase(globalFunction.data_)
538 , evaluationBuffer_(this->localView_.tree())
539 {
540 /* Nothing. */
541 }
542
549 void bind(const Element& element)
550 {
551 LocalBase::bind(element);
552 geometry_.emplace(element.geometry());
553 }
554
556 void unbind()
557 {
558 geometry_.reset();
559 LocalBase::unbind();
560 }
561
575 Range operator()(const Domain& x) const
576 {
577 Range y;
578 istlVectorBackend(y) = 0;
579
580 const auto& jacobianInverse = geometry_->jacobianInverse(x);
581
582 TypeTree::forEachLeafNode(this->localView_.tree(), [&](auto&& node, auto&& treePath) {
583 const auto& fe = node.finiteElement();
584 const auto& localBasis = fe.localBasis();
585 auto& shapeFunctionJacobians = evaluationBuffer_[treePath];
586
587 localBasis.evaluateJacobian(x, shapeFunctionJacobians);
588
589 // Compute linear combinations of basis function jacobian.
590 // Non-scalar coefficients of dimension coeffDim are handled by
591 // processing the coeffDim linear combinations independently
592 // and storing them as entries of an array.
593 using RefJacobian = LocalBasisRange< std::decay_t<decltype(node)> >;
594 static constexpr auto coeffDim = decltype(flatVectorView(this->localDoFs_[node.localIndex(0)]).size())::value;
595 auto refJacobians = std::array<RefJacobian, coeffDim>{};
596 istlVectorBackend(refJacobians) = 0;
597 for (size_type i = 0; i < localBasis.size(); ++i)
598 {
599 auto c = flatVectorView(this->localDoFs_[node.localIndex(i)]);
600 for (std::size_t j = 0; j < coeffDim; ++j)
601 refJacobians[j].axpy(c[j], shapeFunctionJacobians[i]);
602 }
603
604 // Transform Jacobians form local to global coordinates.
605 using Jacobian = decltype(refJacobians[0] * jacobianInverse);
606 auto jacobians = std::array<Jacobian, coeffDim>{};
607 std::transform(
608 refJacobians.begin(), refJacobians.end(), jacobians.begin(),
609 [&](const auto& refJacobian) { return refJacobian * jacobianInverse; });
610
611 // Assign computed Jacobians to node entry of range.
612 // Types are matched using the lexicographic ordering provided by flatVectorView.
613 LocalBase::assignWith(nodeToRangeEntry(node, treePath, y), jacobians);
614 });
615
616 return y;
617 }
618
620 friend typename Traits::LocalFunctionTraits::DerivativeInterface derivative(const LocalFunction&)
621 {
622 DUNE_THROW(NotImplemented, "derivative of derivative is not implemented");
623 }
624
625 private:
626 mutable PerNodeEvaluationBuffer evaluationBuffer_;
627 std::optional<typename Element::Geometry> geometry_;
628 };
629
636 DiscreteGlobalBasisFunctionDerivative(const std::shared_ptr<const Data>& data)
637 : Base(data)
638 {
639 /* Nothing. */
640 }
641
647 Range operator()(const Domain& x) const
648 {
649 HierarchicSearch search(this->data_->basis->gridView().grid(), this->data_->basis->gridView().indexSet());
650
651 const auto e = search.findEntity(x);
652 auto localThis = localFunction(*this);
653 localThis.bind(e);
654 return localThis(e.geometry().local(x));
655 }
656
657 friend typename Traits::DerivativeInterface derivative(const DiscreteGlobalBasisFunctionDerivative& f)
658 {
659 DUNE_THROW(NotImplemented, "derivative of derivative is not implemented");
660 }
661
664 {
665 return LocalFunction(f);
666 }
667};
668
669
670} // namespace Functions
671} // namespace Dune
672
673#endif // DUNE_FUNCTIONS_GRIDFUNCTIONS_DISCRETEGLOBALBASISFUNCTIONS_HH
local function evaluating the derivative in reference coordinates
Definition: discreteglobalbasisfunction.hh:524
Range operator()(const Domain &x) const
Evaluate this local-function in coordinates x in the bound element.
Definition: discreteglobalbasisfunction.hh:575
friend Traits::LocalFunctionTraits::DerivativeInterface derivative(const LocalFunction &)
Not implemented.
Definition: discreteglobalbasisfunction.hh:620
void unbind()
Unbind the local-function.
Definition: discreteglobalbasisfunction.hh:556
LocalFunction(const GlobalFunction &globalFunction)
Create a local function from the associated grid function.
Definition: discreteglobalbasisfunction.hh:536
void bind(const Element &element)
Bind LocalFunction to grid element.
Definition: discreteglobalbasisfunction.hh:549
Derivative of a DiscreteGlobalBasisFunction
Definition: discreteglobalbasisfunction.hh:490
Range operator()(const Domain &x) const
Evaluate the discrete grid-function derivative in global coordinates.
Definition: discreteglobalbasisfunction.hh:647
friend LocalFunction localFunction(const DiscreteGlobalBasisFunctionDerivative &f)
Construct local function from a DiscreteGlobalBasisFunctionDerivative
Definition: discreteglobalbasisfunction.hh:663
DiscreteGlobalBasisFunctionDerivative(const std::shared_ptr< const Data > &data)
create object from DiscreateGlobalBasisFunction data
Definition: discreteglobalbasisfunction.hh:636
A grid function induced by a global basis and a coefficient vector.
Definition: discreteglobalbasisfunction.hh:277
friend DiscreteGlobalBasisFunctionDerivative< DiscreteGlobalBasisFunction > derivative(const DiscreteGlobalBasisFunction &f)
Derivative of the DiscreteGlobalBasisFunction
Definition: discreteglobalbasisfunction.hh:405
DiscreteGlobalBasisFunction(B_T &&basis, V_T &&coefficients, NTRE_T &&nodeToRangeEntry)
Create a grid-function, by wrapping the arguments in std::shared_ptr.
Definition: discreteglobalbasisfunction.hh:380
DiscreteGlobalBasisFunction(std::shared_ptr< const Basis > basis, std::shared_ptr< const V > coefficients, std::shared_ptr< const typename Base::NodeToRangeEntry > nodeToRangeEntry)
Create a grid-function, by moving the arguments in std::shared_ptr.
Definition: discreteglobalbasisfunction.hh:385
friend LocalFunction localFunction(const DiscreteGlobalBasisFunction &t)
Construct local function from a DiscreteGlobalBasisFunction.
Definition: discreteglobalbasisfunction.hh:418
Range operator()(const Domain &x) const
Evaluate at a point given in world coordinates.
Definition: discreteglobalbasisfunction.hh:394
GridView::template Codim< codim >::Entity Element
Type of Elements contained in this EntitySet.
Definition: gridviewentityset.hh:32
Element::Geometry::LocalCoordinate LocalCoordinate
Type of local coordinates with respect to the Element.
Definition: gridviewentityset.hh:35
Search an IndexSet for an Entity containing a given point.
Definition: hierarchicsearch.hh:35
Entity findEntity(const FieldVector< ct, dimw > &global) const
Search the IndexSet of this HierarchicSearch for an Entity containing point global.
Definition: hierarchicsearch.hh:127
Default exception for dummy implementations.
Definition: exceptions.hh:263
Traits for type conversions and type information.
typename AutonomousValueType< T >::type AutonomousValue
Type free of internal references that T can be converted to.
Definition: typetraits.hh:588
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition: trigonometricfunction.hh:39
auto makeDiscreteGlobalBasisFunction(B &&basis, V &&vector)
Generate a DiscreteGlobalBasisFunction.
Definition: discreteglobalbasisfunction.hh:450
auto istlVectorBackend(Vector &v)
Return a vector backend wrapping non-const ISTL like containers.
Definition: istlvectorbackend.hh:346
constexpr auto treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:326
void forEachLeafNode(Tree &&tree, LeafFunc &&leafFunc)
Traverse tree and visit each leaf node.
Definition: traversal.hh:269
std::decay_t< decltype(makeTreeContainer(std::declval< const Tree & >(), std::declval< Detail::LeafToDefaultConstructibleValue< LeafToValue > >()))> TreeContainer
Alias to container type generated by makeTreeContainer for give tree type and when using LeafToValue ...
Definition: treecontainer.hh:306
Utility class for hierarchically searching for an Entity containing a given point.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
auto wrap_or_move(T &&t)
Capture R-value reference to shared_ptr.
Definition: shared_ptr.hh:96
STL namespace.
Default implementation for derivative traits.
Definition: defaultderivativetraits.hh:37
A simple node to range map using the nested tree indices.
Definition: hierarchicnodetorangemap.hh:30
Helper class to deduce the signature of a callable.
Definition: signature.hh:56
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)