AnalyticGridFunction.hpp 7.2 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
10
#include <amdis/Operations.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
Praetorius, Simon's avatar
Praetorius, Simon committed
11
12
13

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

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

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

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

32
33
34
  private:
    using Geometry = typename LocalContext::Geometry;

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

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

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

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

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

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

71
72
73
74
75
76
77
78
79

  /// \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:**
80
   * - The functor `F` must fulfill the concept \ref Concepts::HasFunctorOrder
81
   **/
82
  template <class Sig, class LocalContext, class F,
83
    REQUIRES(Concepts::HasFunctorOrder<F,1>)>
84
85
  int order(AnalyticLocalFunction<Sig,LocalContext,F> const& lf)
  {
86
    return order(lf.fct(),1);
87
  }
88
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:**
   * - The functor `F` must fulfill the concept \ref Concepts::HasPartial
   **/
100
101
102
103
  template <class R, class D, class LocalContext, class F>
  auto derivative(AnalyticLocalFunction<R(D),LocalContext,F> const& lf)
  {
    static_assert(Concepts::HasPartial<F>,
104
      "No partial(...,_0) defined for Functor F of AnalyticLocalFunction.");
105
106
107
108
109
110
111
112
113

    auto df = partial(lf.fct(), index_<0>);

    using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
    using DerivativeSignature = typename Dune::Functions::DefaultDerivativeTraits<RawSignature>::Range(D);
    return AnalyticLocalFunction<DerivativeSignature,LocalContext,decltype(df)>{df};
  }


114
115
116
117
118
119
120
121
122
123
124
125
  /// \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>
   **/
126
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;
    using Range = std::decay_t<std::result_of_t<Function(Domain)>>;
Praetorius, Simon's avatar
Praetorius, Simon committed
133

134
135
    enum { hasDerivative = true };

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

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

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

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

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

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

  private:
    Function fct_;
    EntitySet entitySet_;
  };

174
175
176
177
178
179
180
181
182
183
184
  // 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
185

186
187
188
  /// \fn localFunction
  /// \brief Return the LocalFunction of the AnalyticGridFunction.
  /// \relates AnalyticGridfunction
189
190
191
192
193
194
  template <class F, class GV>
  auto localFunction(AnalyticGridFunction<F,GV> const& gf)
  {
    return gf.localFunction();
  }

195
  /// \fn derivative
196
  /// \brief Return a GridFunction representing the derivative of a functor.
197
198
199
200
201
202
  /**
   * \relates AnalyticGridfunction
   *
   * **Requirements:**
   * - Functor `F` must fulfill the concept \ref Concepts::HasPartial
   **/
203
204
205
206
  template <class F, class GV>
  auto derivative(AnalyticGridFunction<F,GV> const& gf)
  {
    static_assert(Concepts::HasPartial<F>,
Praetorius, Simon's avatar
Praetorius, Simon committed
207
      "No partial(...,_0) defined for Functor of AnalyticLocalFunction.");
208
209
210
211
212
213

    auto df = partial(gf.fct(), index_<0>);
    return AnalyticGridFunction<decltype(df), GV>{df, gf.entitySet().gridView()};
  }


214
215
#ifndef DOXYGEN
  // A pre-GridFunction that just stores the function
Praetorius, Simon's avatar
Praetorius, Simon committed
216
217
218
  template <class Function>
  struct AnalyticPreGridFunction
  {
219
220
221
222
223
224
225
226
227
228
229
    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
230
231
232
    Function fct_;
  };

233
  namespace Traits
Praetorius, Simon's avatar
Praetorius, Simon committed
234
235
236
237
  {
    template <class Functor>
    struct IsPreGridFunction<AnalyticPreGridFunction<Functor>>
      : std::true_type {};
238
  }
239
#endif
240

Praetorius, Simon's avatar
Praetorius, Simon committed
241

242
243
  /// \fn evalAtQP
  /// \brief Generator function for AnalyticGridFunction.
244
  /**
245
   * \relates AnalyticGridfunction
246
247
248
249
250
251
252
   * \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
253
254
  template <class Function,
    REQUIRES(Concepts::CallableDomain<Function>)>
255
  auto evalAtQP(Function const& f)
Praetorius, Simon's avatar
Praetorius, Simon committed
256
257
258
259
260
  {
    return AnalyticPreGridFunction<Function>{f};
  }

} // end namespace AMDiS