Dune-Functions 2.11
Loading...
Searching...
No Matches
interpolate.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_INTERPOLATE_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_INTERPOLATE_HH
9
10#include <memory>
11#include <vector>
12
13#include <dune/common/exceptions.hh>
14#include <dune/common/bitsetvector.hh>
15#include <dune/common/referencehelper.hh>
16
17#include <dune/common/typetree/traversal.hh>
18
21
26
27namespace Dune {
28namespace Functions {
29
30namespace Imp {
31
32struct AllTrueBitSetVector
33{
34 struct AllTrueBitSet
35 {
36 bool test(int) const { return true; }
37 } allTrue_;
38
39 operator bool() const
40 {
41 return true;
42 }
43
44 template<class I>
45 const AllTrueBitSetVector& operator[](const I&) const
46 {
47 return *this;
48 }
49
50 template<class SP>
51 void resize(const SP&) const
52 {}
53
54};
55
56
57
58// This helper function implements the restriction of some given function of type F.
59// The restriction is a simple callback that is applied to the values of the
60// function and the values of its derivative.
61template<class F, class Restriction>
62class ComponentFunction
63{
64public:
65
66 ComponentFunction(F f, Restriction restriction) :
67 f_(std::move(f)),
68 restriction_(std::move(restriction))
69 {}
70
71 template<class Domain>
72 auto operator()(const Domain& x) const
73 {
74 return restriction_(f_(x));
75 }
76
77 friend auto derivative(const ComponentFunction& cf)
78 {
79 // This provides support for capturing the derivative of the function by reference
80 // using forwardCapture for perfect forwarding capture. If the function caches its
81 // derivative, this saves a potentially costly copy.
82 auto&& df = derivative(Dune::resolveRef(cf.f_));
83 return [&, df=forwardCapture(std::forward<decltype(df)>(df))](auto&& x) {
84 return cf.restriction_(df.forward()(x));
85 };
86 }
87
88private:
89 F f_;
90 Restriction restriction_;
91};
92
93
94
95
96// This helper function implements caching of the derivative for local functions.
97// When using an algorithm that gets a LocalFunction and calls its derivative
98// on each element, this leads to a costly call of derivative(f). E.g. for a
99// DiscreteGlobalBasisFunction, this will allocate several buffer.
100// To avoid this, this helper function caches the derivative and hands
101// out the cached derivative by reference. To ensure that the handed out
102// derivative is appropriately bound, binding the function will automatically
103// bind the cached derivative.
104//
105// Notice that we cannot simply create the derivative in the constructor,
106// because this may throw for functions that do not implement the derivative.
107template<class F>
108class CachedDerivativeLocalFunction
109{
110 using Derivative = std::decay_t<decltype(derivative(Dune::resolveRef(std::declval<const F&>())))>;
111
112public:
113
114 CachedDerivativeLocalFunction(F f) :
115 f_(f)
116 {}
117
118 template<class Element>
119 void bind(const Element& element)
120 {
121 Dune::resolveRef(f_).bind(element);
122 if (derivative_)
123 derivative_.value().bind(element);
124 }
125
126 template<class X>
127 auto operator()(const X& x) const
128 {
129 return f_(x);
130 }
131
132 friend const Derivative& derivative(const CachedDerivativeLocalFunction& cdlf)
133 {
134 if (not cdlf.derivative_)
135 {
136 auto&& lf = Dune::resolveRef(cdlf.f_);
137 cdlf.derivative_ = derivative(lf);
138 if (lf.bound())
139 cdlf.derivative_.value().bind(lf.localContext());
140 }
141 return cdlf.derivative_.value();
142 }
143
144private:
145 F f_;
146 mutable std::optional<Derivative> derivative_;
147};
148
149
150
151template<class VectorBackend, class BitVectorBackend, class LocalFunction, class LocalView, class NodeToRangeEntry>
152void interpolateLocal(VectorBackend& vector, const BitVectorBackend& bitVector, const LocalFunction& localF, const LocalView& localView, const NodeToRangeEntry& nodeToRangeEntry)
153{
154 Dune::TypeTree::forEachLeafNode(localView.tree(), [&](auto&& node, auto&& treePath) {
155 if (node.empty())
156 return;
157 using Node = std::decay_t<decltype(node)>;
158 using FiniteElement = typename Node::FiniteElement;
159 using FiniteElementRangeField = typename FiniteElement::Traits::LocalBasisType::Traits::RangeFieldType;
160
161 auto interpolationCoefficients = std::vector<FiniteElementRangeField>();
162 auto&& fe = node.finiteElement();
163 auto localF_RE = ComponentFunction(std::cref(localF), [&](auto&& y) { return nodeToRangeEntry(node, treePath, y); });
164
165 fe.localInterpolation().interpolate(localF_RE, interpolationCoefficients);
166 for (size_t i=0; i<fe.localBasis().size(); ++i)
167 {
168 auto multiIndex = localView.index(node.localIndex(i));
169 if ( bitVector[multiIndex] )
170 vector[multiIndex] = interpolationCoefficients[i];
171 }
172 });
173}
174
175
176struct HasDerivative
177{
178 template<class F>
179 auto require(F&& f) -> decltype(derivative(f));
180};
181
182} // namespace Imp
183
184
185
186
204template <class B, class C, class F, class BV, class NTRE>
205void interpolate(const B& basis, C&& coeff, const F& f, const BV& bv, const NTRE& nodeToRangeEntry)
206{
207 using GridView = typename B::GridView;
208 using Element = typename GridView::template Codim<0>::Entity;
209 using GlobalDomain = typename Element::Geometry::GlobalCoordinate;
210
211 static_assert(Dune::Functions::Concept::isCallable<F, GlobalDomain>(), "Function passed to interpolate does not model the Callable<GlobalCoordinate> concept");
212
213 auto&& gridView = basis.gridView();
214
215 // Small helper functions to wrap vectors using istlVectorBackend
216 // if they do not already satisfy the VectorBackend interface.
217 auto toVectorBackend = [&](auto& v) -> decltype(auto) {
218 if constexpr (models<Concept::VectorBackend<B>, decltype(v)>()) {
219 return v;
220 } else {
221 return istlVectorBackend(v);
222 }
223 };
224
225 auto toConstVectorBackend = [&](auto& v) -> decltype(auto) {
226 if constexpr (models<Concept::ConstVectorBackend<B>, decltype(v)>()) {
227 return v;
228 } else {
229 return istlVectorBackend(v);
230 }
231 };
232
233 auto&& bitVector = toConstVectorBackend(bv);
234 auto&& vector = toVectorBackend(coeff);
235 vector.resize(basis);
236
237 // Make a grid function supporting local evaluation out of f
238 auto gf = makeGridViewFunction(f, gridView);
239
240 // Obtain a local view of f
241 // To avoid costly reconstruction of the derivative on each element,
242 // we use the CachedDerivativeLocalFunction wrapper if the function
243 // is differentiable. This wrapper will handout
244 // a reference to a single cached derivative object.
245 auto localF = [&](){
246 if constexpr (models<Imp::HasDerivative, decltype(localFunction(gf))>())
247 return Imp::CachedDerivativeLocalFunction(localFunction(gf));
248 else
249 return localFunction(gf);
250 }();
251
252 auto localView = basis.localView();
253
254 for (const auto& e : elements(gridView))
255 {
256 localView.bind(e);
257 localF.bind(e);
258 Imp::interpolateLocal(vector, bitVector, localF, localView, nodeToRangeEntry);
259 }
260}
261
278template <class B, class C, class F, class BV>
279void interpolate(const B& basis, C&& coeff, const F& f, const BV& bitVector)
280{
281 interpolate(basis, coeff, f, bitVector, HierarchicNodeToRangeMap());
282}
283
298template <class B, class C, class F>
299void interpolate(const B& basis, C&& coeff, const F& f)
300{
301 interpolate (basis, coeff, f, Imp::AllTrueBitSetVector(), HierarchicNodeToRangeMap());
302}
303
304} // namespace Functions
305} // namespace Dune
306
307#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_INTERPOLATE_HH
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition trigonometricfunction.hh:43
auto istlVectorBackend(Vector &v)
Return a vector backend wrapping non-const ISTL like containers.
Definition istlvectorbackend.hh:350
static constexpr auto isCallable()
Check if f is callable with given argument list.
Definition functionconcepts.hh:51
Definition monomialset.hh:19
Definition monomialset.hh:19
void interpolate(const B &basis, C &&coeff, const F &f, const BV &bv, const NTRE &nodeToRangeEntry)
Interpolate given function in discrete function space.
Definition interpolate.hh:205
std::decay_t< F > makeGridViewFunction(F &&f, const GridView &gridView)
Construct a function modeling GridViewFunction from function and grid view.
Definition gridviewfunction.hh:72
auto forwardCapture(T &&t)
Create a capture object for perfect forwarding.
Definition utility.hh:380
A simple node to range map using the nested tree indices.
Definition hierarchicnodetorangemap.hh:34