analyticgridfunction.hh 6.15 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_CURVED_SURFACE_GRID_ANALYTIC_GRIDFUNCTION_HH
#define DUNE_CURVED_SURFACE_GRID_ANALYTIC_GRIDFUNCTION_HH

namespace Dune
{
  //! A set of entities of given `codim` of a `Grid`
  /**
   * \tparam G      The grid type
   * \tparam codim  Codimension of the entities to define the set of.
   *
   * \note This entityset just defines types
   **/
  template< class G, int codim >
  class GridEntitySet
  {
  public:
    //! Type of the grid
    using Grid = G;

    //! Type of Elements contained in this EntitySet
    using Element = typename Grid::template Codim<codim>::Entity;

    //! Type of local coordinates with respect to the Element
    using LocalCoordinate = typename Element::Geometry::LocalCoordinate;

    //! Type of global coordinates with respect to the Element
    using GlobalCoordinate = typename Element::Geometry::GlobalCoordinate;
  };


  //! LocalFunction associated to the \ref AnalyticGridFunction
  /**
   * \tparam LocalContext  Context this localFunction can be bound to, e.g. a grid element
   * \tparam F             Type of a function that can be evaluated in global coordinates.
   **/
  template< class LocalContext, class F >
  class LocalAnalyticGridFunction;

  //! Generator for \ref LocalAnalyticGridFunction
  /**
   * \param  ff            Function that can be evaluated at global coordinates of the \ref LocalContext
   * \tparam LocalContext  Context this localFunction can be bound to, e.g. a grid element
   **/
  template< class LocalContext, class FF >
  auto localAnalyticGridFunction (FF&& ff)
  {
    using F = std::decay_t<FF>;
    return LocalAnalyticGridFunction<LocalContext, F>{std::forward<FF>(ff)};
  }


  template< class LC, class Functor >
  class LocalAnalyticGridFunction
  {
  public:
    using LocalContext = LC;
    using Geometry = typename LocalContext::Geometry;

    using Domain = typename Geometry::GlobalCoordinate;
    using LocalDomain = typename Geometry::LocalCoordinate;
    using Range = std::result_of_t<Functor(Domain)>;
    using Signature = Range(LocalDomain);

  public:
    //! Constructor. Stores the functor f by value
    template< class FF,
      disableCopyMove<LocalAnalyticGridFunction, FF> = 0>
    LocalAnalyticGridFunction (FF&& f)
      : f_(std::forward<FF>(f))
    {}

    //! bind the LocalFunction to the local context
    /**
     * Stores the localContext and its geometry in a cache variable
     **/
    void bind (const LocalContext& localContext)
    {
      localContext_.emplace(localContext);
      geometry_.emplace(localContext.geometry());
    }

    //! unbind the localContext from the localFunction
    /**
     * Reset the geometry
     **/
    void unbind ()
    {
      geometry_.reset();
      localContext_.reset();
    }

    //! evaluate the stored function in local coordinates
    /**
     * Transform the local coordinates to global coordinates first,
     * then evalute the stored functor.
     **/
    Range operator() (const LocalDomain& x) const
    {
      assert(!!geometry_);
      return f_(geometry_->global(x));
    }

    //! return the bound localContext.
    const LocalContext& localContext () const
    {
      assert(!!localContext_);
      return *localContext_;
    }

    //! obtain the functor
    const Functor& f () const
    {
      return f_;
    }

  private:
    Functor f_;

    // some caches
    Std::optional<LocalContext> localContext_;
    Std::optional<Geometry> geometry_;
  };

  //! Derivative of a \ref LocalAnalyticGridFunction
  /**
   * Participates in overload resolution only if the functor `F` is differentiable
   **/
  template< class LC, class F >
  auto derivative (const LocalAnalyticGridFunction<LC,F>& t)
    -> decltype(localAnalyticGridFunction<LC>(derivative(t.f())))
  {
    return localAnalyticGridFunction<LC>(derivative(t.f()));
  }


  //! GridFunction associated to the mapping F
  /**
   * \tparam Grid       The grid type with elements the corresponding LocalFunction can be bound to
   * \tparam F          Type of a function that can be evaluated in global coordinates.
   **/
  template< class Grid, class F >
  class AnalyticGridFunction;

  //! Generator for \ref AnalyticGridFunction
  /**
   * \param  ff    Function that can be evaluated at global coordinates of the \ref Grid
   * \tparam Grid  The grid type with elements the corresponding LocalFunction can be bound to
   **/
  template< class Grid, class FF >
  auto analyticGridFunction (FF&& ff)
  {
    using F = std::decay_t<FF>;
    return AnalyticGridFunction<Grid, F>{std::forward<FF>(ff)};
  }


  template< class GridType, class Functor >
  class AnalyticGridFunction
  {
  public:
    using Grid = GridType;
    using EntitySet = GridEntitySet<Grid,0>;

    using Domain = typename EntitySet::GlobalCoordinate;
    using Range = std::result_of_t<Functor(Domain)>;
    using Signature = Range(Domain);

  public:
    //! Constructor. Stores the functor f by value
    template< class FF,
      disableCopyMove<AnalyticGridFunction, FF> = 0>
    AnalyticGridFunction (FF&& f)
      : f_(std::forward<FF>(f))
    {}

    //! evaluate the stored function in global coordinates
    Range operator() (const Domain& x) const
    {
      return f_(x);
    }

    //! construct the \ref LocalAnalyticGridFunction
    using LocalFunction = LocalAnalyticGridFunction<typename EntitySet::Element, Functor>;
    friend LocalFunction localFunction (const AnalyticGridFunction& t)
    {
      return LocalFunction(t.f_);
    }

    //! obtain the stored \ref GridEntitySet
    const EntitySet& entitySet () const
    {
      return entitySet_;
    }

    //! obtain the functor
    const Functor& f () const
    {
      return f_;
    }

  private:
    Functor f_;
    EntitySet entitySet_;
  };

  //! Derivative of an \ref AnalyticGridFunction
  /**
   * Participates in overload resolution only if the functor `F` is differentiable
   **/
  template< class Grid, class F >
  auto derivative (const AnalyticGridFunction<Grid,F>& t)
    -> decltype(analyticGridFunction<Grid>(derivative(t.f())))
  {
    return analyticGridFunction<Grid>(derivative(t.f()));
  }

} // end namespace Dune

#endif // DUNE_CURVED_SURFACE_GRID_ANALYTIC_GRIDFUNCTION_HH