AnalyticGridFunction.hpp 7.71 KB
Newer Older
Praetorius, Simon's avatar
Praetorius, Simon committed
1
2
3
4
5
#pragma once

#include <type_traits>

#include <dune/common/std/optional.hh>
6
#include <dune/functions/common/signature.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
7
8
#include <dune/functions/gridfunctions/gridviewentityset.hh>

9
#include <amdis/Operations.hpp>
10
11
12
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
#include <amdis/gridfunctions/Order.hpp>
Praetorius, Simon's avatar
Praetorius, Simon committed
13
14
15

namespace AMDiS
{
16
#ifndef DOXYGEN
17
18
  template <class Signature, class LocalContext, class Function>
  class AnalyticLocalFunction;
19
#endif
Praetorius, Simon's avatar
Praetorius, Simon committed
20

21
22
  template <class R, class D, class LC, class Function>
  class AnalyticLocalFunction<R(D), LC, Function>
Praetorius, Simon's avatar
Praetorius, Simon committed
23
24
  {
  public:
25
26
    /// The LocalDomain this LocalFunction can be evaluated in
    using Domain = D;
Praetorius, Simon's avatar
Praetorius, Simon committed
27

28
29
    /// The range type of the LocalFunction
    using Range = R;
Praetorius, Simon's avatar
Praetorius, Simon committed
30

31
    /// This LocalFunction has its own \ref derivative() function
32
33
    enum { hasDerivative = true };

34
  private:
35
    using Geometry = typename LC::Geometry;
36

Praetorius, Simon's avatar
Praetorius, Simon committed
37
  public:
38
    /// \brief Constructor. stores the function `fct`.
39
    AnalyticLocalFunction(Function const& fct)
40
      : fct_{fct}
41
42
    {}

43
    /// \brief Create a geometry object from the element
44
    void bind(LC const& element)
45
46
47
    {
      geometry_.emplace(element.geometry());
    }
Praetorius, Simon's avatar
Praetorius, Simon committed
48

49
    /// \brief Releases the geometry object
50
    void unbind()
Praetorius, Simon's avatar
Praetorius, Simon committed
51
    {
52
53
      geometry_.reset();
    }
Praetorius, Simon's avatar
Praetorius, Simon committed
54

55
56
    /// \brief Evaluate the function in global coordinate by a local-to-global
    /// mapping of the local coordinates using the bound geometry object.
57
58
    Range operator()(Domain const& local) const
    {
59
      assert( bool(geometry_) );
60
61
62
63
64
65
66
67
68
69
70
71
72
      return fct_(geometry_.value().global(local));
    }

    Function const& fct() const
    {
      return fct_;
    }

  private:
    Function fct_;
    Dune::Std::optional<Geometry> geometry_;
  };

73
74
75
76
77
78
79
80
81

  /// \fn order
  /// \brief Return the polynomial order of the LocalFunction.
  /**
   * \relates AnalyticLocalFunction
   * The order is defined as the polynomial order of the functor `fct` and
   * requires a free function `order(fct,1)` to exists.
   *
   * **Requirements:**
82
   * - The functor `F` must fulfill the concept \ref Concepts::HasFunctorOrder
83
   **/
84
  template <class Sig, class LC, class F,
85
    REQUIRES(Concepts::HasFunctorOrder<F,1>)>
86
  int order(AnalyticLocalFunction<Sig,LC,F> const& lf)
87
  {
88
    return order(lf.fct(),1);
89
  }
90
91


92
93
94
95
96
97
98
99
  /// \fn derivative
  /// \brief Create an \ref AnalyticLocalFunction representing the derivative
  /// of the given AnalyticLocalFunction.
  /**
   * In order to differentiate the local function, the functor must be
   * differentiable, i.e. a free function `partial(fct,_0)` must exist.
   *
   * **Requirements:**
Praetorius, Simon's avatar
Praetorius, Simon committed
100
   * - The functor `F` must fulfill the concept \ref Concepts::HasDerivative
101
   **/
102
103
  template <class R, class D, class LC, class F, class Type>
  auto derivative(AnalyticLocalFunction<R(D),LC,F> const& lf, Type const& type)
104
  {
105
106
    static_assert(Concepts::HasDerivative<F,Type>,
      "No derivative(F,DerivativeType) defined for Functor F of AnalyticLocalFunction.");
107

108
    auto df = derivative(lf.fct(), type);
109
110

    using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
111
    using DerivativeSignature = typename DerivativeTraits<RawSignature,Type>::Range(D);
112
    return AnalyticLocalFunction<DerivativeSignature,LC,decltype(df)>{df};
113
114
  }

115
116
117
118
119
120
121
122
123
124
125
126
  /// \class AnalyticGridFunction
  /// \brief A Gridfunction that evaluates a function with global coordinates.
  /**
   * \ingroup GridFunctions
   * Implements a GridFunction that wraps a functor around global coordinates.
   *
   * \tparam Function The callable `f=f(x)` with `x in Domain == GlobalCoordinates`
   * \tparam GridView A GridView that models `Dune::GridViewConcept`.
   *
   * **Requirements:**
   * - Function models \ref Concepts::Callable<Domain>
   **/
127
128
129
130
131
132
  template <class Function, class GridView>
  class AnalyticGridFunction
  {
  public:
    using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>;
    using Domain = typename EntitySet::GlobalCoordinate;
133
    using Range = remove_cvref_t<std::result_of_t<Function(Domain)>>;
Praetorius, Simon's avatar
Praetorius, Simon committed
134

135
136
    enum { hasDerivative = true };

137
138
139
  private:
    using Element = typename EntitySet::Element;
    using LocalDomain = typename EntitySet::LocalCoordinate;
140
    using LocalFunction = AnalyticLocalFunction<Range(LocalDomain), Element, Function>;
Praetorius, Simon's avatar
Praetorius, Simon committed
141

142
  public:
Praetorius, Simon's avatar
Praetorius, Simon committed
143
    /// Constructor. Stores the function `fct` and creates an `EntitySet`.
Praetorius, Simon's avatar
Praetorius, Simon committed
144
    AnalyticGridFunction(Function const& fct, GridView const& gridView)
145
146
      : fct_{fct}
      , entitySet_{gridView}
Praetorius, Simon's avatar
Praetorius, Simon committed
147
148
    {}

Praetorius, Simon's avatar
Praetorius, Simon committed
149
    /// Return the evaluated functor at global coordinates
Praetorius, Simon's avatar
Praetorius, Simon committed
150
151
152
153
154
    Range operator()(Domain const& x) const
    {
      return fct_(x);
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
155
    /// Return the \ref AnalyticLocalFunction of the AnalyticGridFunction.
156
    LocalFunction makeLocalFunction() const
Praetorius, Simon's avatar
Praetorius, Simon committed
157
    {
158
      return {fct_};
Praetorius, Simon's avatar
Praetorius, Simon committed
159
160
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
161
    /// Returns \ref entitySet_
Praetorius, Simon's avatar
Praetorius, Simon committed
162
163
164
165
166
    EntitySet const& entitySet() const
    {
      return entitySet_;
    }

Praetorius, Simon's avatar
Praetorius, Simon committed
167
    /// Returns \ref fct_
Praetorius, Simon's avatar
Praetorius, Simon committed
168
169
170
171
172
173
174
    Function const& fct() const { return fct_; }

  private:
    Function fct_;
    EntitySet entitySet_;
  };

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

  namespace Concepts
  {
    namespace Definition
    {
      template <class F, int dow>
      constexpr bool CallableDow =
        Concepts::Callable<F, Dune::FieldVector<double, dow>>;
    }

    /// \brief Functor F is collable with GlobalCoordinates `F(Dune::FieldVector<double,DOW>)`
#ifndef WORLDDIM
    template <class F>
    constexpr bool CallableDomain =
      Definition::CallableDow<F, 1> || Definition::CallableDow<F, 2> || Definition::CallableDow<F, 3>;
#else
    template <class F>
    constexpr bool CallableDomain =
      Definition::CallableDow<F, WORLDDIM>;
#endif

Praetorius, Simon's avatar
Praetorius, Simon committed
196
197
198
    template <class F>
    using CallableDomain_t = bool_t<CallableDomain<F>>;

199
200
201
  } // end namespace Concepts


202
203
204
205
206
207
208
209
210
211
212
  // Creator for the AnalyticGridFunction
  template <class Function>
  struct GridFunctionCreator<Function, std::enable_if_t<Concepts::CallableDomain<Function>>>
  {
    template <class GridView>
    static auto create(Function const& fct, GridView const& gridView)
    {
      return AnalyticGridFunction<Function, GridView>{fct, gridView};
    }
  };

Praetorius, Simon's avatar
Praetorius, Simon committed
213

214
  /// \fn derivative
215
  /// \brief Return a GridFunction representing the derivative of a functor.
216
217
218
219
  /**
   * \relates AnalyticGridfunction
   *
   * **Requirements:**
220
   * - Functor `F` must fulfill the concept \ref Concepts::HasDerivative<Type>
221
   **/
222
223
  template <class F, class GV, class Type>
  auto derivative(AnalyticGridFunction<F,GV> const& gf, Type const& type)
224
  {
225
226
    static_assert(Concepts::HasDerivative<F,Type>,
      "No derivative(F,DerivativeType) defined for Functor of AnalyticLocalFunction.");
227

228
    auto df = derivative(gf.fct(), type);
229
230
231
232
    return AnalyticGridFunction<decltype(df), GV>{df, gf.entitySet().gridView()};
  }


233
234
#ifndef DOXYGEN
  // A pre-GridFunction that just stores the function
Praetorius, Simon's avatar
Praetorius, Simon committed
235
236
237
  template <class Function>
  struct AnalyticPreGridFunction
  {
238
239
240
241
242
243
244
245
246
247
248
    using Self = AnalyticPreGridFunction;

    struct Creator
    {
      template <class GridView>
      static auto create(Self const& self, GridView const& gridView)
      {
        return AnalyticGridFunction<Function, GridView>{self.fct_, gridView};
      }
    };

Praetorius, Simon's avatar
Praetorius, Simon committed
249
250
251
    Function fct_;
  };

252
  namespace Traits
Praetorius, Simon's avatar
Praetorius, Simon committed
253
254
255
256
  {
    template <class Functor>
    struct IsPreGridFunction<AnalyticPreGridFunction<Functor>>
      : std::true_type {};
257
  }
258
#endif
259

Praetorius, Simon's avatar
Praetorius, Simon committed
260

261
262
  /// \fn evalAtQP
  /// \brief Generator function for AnalyticGridFunction.
263
  /**
264
   * \relates AnalyticGridfunction
265
266
267
268
269
270
271
   * \ingroup GridFunctions
   * Evaluate a functor at global coordinates. See \ref AnalyticGridFunction.
   *
   * **Examples:**
   * - `evalAtQP([](Dune::FieldVector<double, 2> const& x) { return x[0]; })`
   * - `evalAtQP(Operation::TwoNorm{})`
   **/
Praetorius, Simon's avatar
Praetorius, Simon committed
272
273
  template <class Function,
    REQUIRES(Concepts::CallableDomain<Function>)>
274
  auto evalAtQP(Function const& f)
Praetorius, Simon's avatar
Praetorius, Simon committed
275
276
277
278
279
  {
    return AnalyticPreGridFunction<Function>{f};
  }

} // end namespace AMDiS