DUNE PDELab (git)

interpolate.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_FUNCTIONSPACEBASES_INTERPOLATE_HH
4#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_INTERPOLATE_HH
5
6#include <memory>
7#include <vector>
8
11#include <dune/common/referencehelper.hh>
12
13#include <dune/typetree/traversal.hh>
14
15#include <dune/functions/gridfunctions/gridviewfunction.hh>
16#include <dune/functions/common/functionconcepts.hh>
17
18#include <dune/functions/backends/concepts.hh>
19#include <dune/functions/backends/istlvectorbackend.hh>
20#include <dune/functions/functionspacebases/flatvectorview.hh>
21#include <dune/functions/functionspacebases/hierarchicnodetorangemap.hh>
22
23namespace Dune {
24namespace Functions {
25
26namespace Imp {
27
28struct AllTrueBitSetVector
29{
30 struct AllTrueBitSet
31 {
32 bool test(int) const { return true; }
33 } allTrue_;
34
35 operator bool() const
36 {
37 return true;
38 }
39
40 template<class I>
41 const AllTrueBitSetVector& operator[](const I&) const
42 {
43 return *this;
44 }
45
46 template<class SP>
47 void resize(const SP&) const
48 {}
49
50};
51
52
53
54// This helper function implements the restriction of some given function of type F.
55// The restriction is a simple callback that is applied to the values of the
56// function and the values of its derivative.
57template<class F, class Restriction>
58class ComponentFunction
59{
60public:
61
62 ComponentFunction(F f, Restriction restriction) :
63 f_(std::move(f)),
64 restriction_(std::move(restriction))
65 {}
66
67 template<class Domain>
68 auto operator()(const Domain& x) const
69 {
70 return restriction_(f_(x));
71 }
72
73 friend auto derivative(const ComponentFunction& cf)
74 {
75 // This provides support for capturing the derivative of the function by reference
76 // using forwardCapture for perfect forwarding capture. If the function caches its
77 // derivative, this saves a potentially costly copy.
78 auto&& df = derivative(Dune::resolveRef(cf.f_));
79 return [&, df=forwardCapture(std::forward<decltype(df)>(df))](auto&& x) {
80 return cf.restriction_(df.forward()(x));
81 };
82 }
83
84private:
85 F f_;
86 Restriction restriction_;
87};
88
89
90
91
92// This helper function implements caching of the derivative for local functions.
93// When using an algorithm that gets a LocalFunction and calls its derivative
94// on each element, this leads to a costly call of derivative(f). E.g. for a
95// DiscreteGlobalBasisFunction, this will allocate several buffer.
96// To avoid this, this helper function caches the derivative and hands
97// out the cached derivative by reference. To ensure that the handed out
98// derivative is appropriately bound, binding the function will automatically
99// bind the cached derivative.
100//
101// Notice that we cannot simply create the derivative in the constructor,
102// because this may throw for functions that do not implement the derivative.
103template<class F>
104class CachedDerivativeLocalFunction
105{
106 using Derivative = std::decay_t<decltype(derivative(Dune::resolveRef(std::declval<const F&>())))>;
107
108public:
109
110 CachedDerivativeLocalFunction(F f) :
111 f_(f)
112 {}
113
114 template<class Element>
115 void bind(const Element& element)
116 {
117 Dune::resolveRef(f_).bind(element);
118 if (derivative_)
119 derivative_.value().bind(element);
120 }
121
122 template<class X>
123 auto operator()(const X& x) const
124 {
125 return f_(x);
126 }
127
128 friend const Derivative& derivative(const CachedDerivativeLocalFunction& cdlf)
129 {
130 if (not cdlf.derivative_)
131 {
132 auto&& lf = Dune::resolveRef(cdlf.f_);
133 cdlf.derivative_ = derivative(lf);
134 if (lf.bound())
135 cdlf.derivative_.value().bind(lf.localContext());
136 }
137 return cdlf.derivative_.value();
138 }
139
140private:
141 F f_;
142 mutable std::optional<Derivative> derivative_;
143};
144
145
146
147template<class VectorBackend, class BitVectorBackend, class LocalFunction, class LocalView, class NodeToRangeEntry>
148void interpolateLocal(VectorBackend& vector, const BitVectorBackend& bitVector, const LocalFunction& localF, const LocalView& localView, const NodeToRangeEntry& nodeToRangeEntry)
149{
150 Dune::TypeTree::forEachLeafNode(localView.tree(), [&](auto&& node, auto&& treePath) {
151 using Node = std::decay_t<decltype(node)>;
152 using FiniteElement = typename Node::FiniteElement;
153 using FiniteElementRangeField = typename FiniteElement::Traits::LocalBasisType::Traits::RangeFieldType;
154
155 auto interpolationCoefficients = std::vector<FiniteElementRangeField>();
156 auto&& fe = node.finiteElement();
157 auto localF_RE = ComponentFunction(std::cref(localF), [&](auto&& y) { return nodeToRangeEntry(node, treePath, y); });
158
159 fe.localInterpolation().interpolate(localF_RE, interpolationCoefficients);
160 for (size_t i=0; i<fe.localBasis().size(); ++i)
161 {
162 auto multiIndex = localView.index(node.localIndex(i));
163 if ( bitVector[multiIndex] )
164 vector[multiIndex] = interpolationCoefficients[i];
165 }
166 });
167}
168
169
170struct HasDerivative
171{
172 template<class F>
173 auto require(F&& f) -> decltype(derivative(f));
174};
175
176} // namespace Imp
177
178
179
180
198template <class B, class C, class F, class BV, class NTRE>
199void interpolate(const B& basis, C&& coeff, const F& f, const BV& bv, const NTRE& nodeToRangeEntry)
200{
201 using GridView = typename B::GridView;
202 using Element = typename GridView::template Codim<0>::Entity;
203 using GlobalDomain = typename Element::Geometry::GlobalCoordinate;
204
205 static_assert(Dune::Functions::Concept::isCallable<F, GlobalDomain>(), "Function passed to interpolate does not model the Callable<GlobalCoordinate> concept");
206
207 auto&& gridView = basis.gridView();
208
209 // Small helper functions to wrap vectors using istlVectorBackend
210 // if they do not already satisfy the VectorBackend interface.
211 auto toVectorBackend = [&](auto& v) -> decltype(auto) {
212 if constexpr (models<Concept::VectorBackend<B>, decltype(v)>()) {
213 return v;
214 } else {
215 return istlVectorBackend(v);
216 }
217 };
218
219 auto toConstVectorBackend = [&](auto& v) -> decltype(auto) {
220 if constexpr (models<Concept::ConstVectorBackend<B>, decltype(v)>()) {
221 return v;
222 } else {
223 return istlVectorBackend(v);
224 }
225 };
226
227 auto&& bitVector = toConstVectorBackend(bv);
228 auto&& vector = toVectorBackend(coeff);
229 vector.resize(basis);
230
231 // Make a grid function supporting local evaluation out of f
232 auto gf = makeGridViewFunction(f, gridView);
233
234 // Obtain a local view of f
235 // To avoid costly reconstruction of the derivative on each element,
236 // we use the CachedDerivativeLocalFunction wrapper if the function
237 // is differentiable. This wrapper will handout
238 // a reference to a single cached derivative object.
239 auto localF = [&](){
240 if constexpr (models<Imp::HasDerivative, decltype(localFunction(gf))>())
241 return Imp::CachedDerivativeLocalFunction(localFunction(gf));
242 else
243 return localFunction(gf);
244 }();
245
246 auto localView = basis.localView();
247
248 for (const auto& e : elements(gridView))
249 {
250 localView.bind(e);
251 localF.bind(e);
252 Imp::interpolateLocal(vector, bitVector, localF, localView, nodeToRangeEntry);
253 }
254}
255
272template <class B, class C, class F, class BV>
273void interpolate(const B& basis, C&& coeff, const F& f, const BV& bitVector)
274{
275 interpolate(basis, coeff, f, bitVector, HierarchicNodeToRangeMap());
276}
277
292template <class B, class C, class F>
293void interpolate(const B& basis, C&& coeff, const F& f)
294{
295 interpolate (basis, coeff, f, Imp::AllTrueBitSetVector(), HierarchicNodeToRangeMap());
296}
297
298} // namespace Functions
299} // namespace Dune
300
301#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_INTERPOLATE_HH
Efficient implementation of a dynamic array of static arrays of booleans.
A few common exception classes.
constexpr T & resolveRef(T &gf) noexcept
Helper function to resolve std::reference_wrapper.
Definition: referencehelper.hh:47
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition: trigonometricfunction.hh:39
auto istlVectorBackend(Vector &v)
Return a vector backend wrapping non-const ISTL like containers.
Definition: istlvectorbackend.hh:346
void interpolate(const F &f, const GFS &gfs, XG &xg)
interpolation from a given grid function
Definition: interpolate.hh:177
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
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
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)