DerivativeGridFunction.hpp 5.96 KB
Newer Older
1
2
3
4
#pragma once

#include <type_traits>

5
#include <dune/grid/utility/hierarchicsearch.hh>
6

7
8
9
10
#include <amdis/common/Concepts.hpp>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/gridfunctions/Derivative.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
Praetorius, Simon's avatar
Praetorius, Simon committed
11

12
13
namespace AMDiS
{
14
15
16
17
18
19
20
21
22
23
24
  namespace Impl
  {
    template <class LF, class Sig>
    struct CheckFunctorConcept
    {
      static_assert(Concepts::Functor<LF, Sig>, "Derivative of LocalFunction can not be called as a functor.");
    };

    template <class Traits>
    struct CheckValidRange
    {
25
      static_assert(!std::is_same_v<typename Traits::Range, Dune::Functions::InvalidRange>, "Invalid Range.");
26
27
28
    };
  }

29
  /// \class DerivativeGridFunction
30
31
  /// \brief A Gridfunction that returns the derivative when calling localFunction.
  /**
Praetorius, Simon's avatar
Praetorius, Simon committed
32
   * \ingroup GridFunctions
33
   * Wraps the GridFunction so that \ref localFunction returns a LocalFunction
34
35
36
   * representing the derivative of the LocalFunction of the GridFunction.
   *
   * \tparam GridFunction The GridFunction that is wrapped.
37
   * \tparam The type of derivative, i.e. one of tag::gradient, tag::partial{i}, or tag::divergence
38
39
   *
   * **Requirements:**
40
41
   * - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction
   *   has a derivative.
42
   **/
43
  template <class GridFunction, class Type>
44
45
  class DerivativeGridFunction
  {
46
47
48
    using GridFctRange = typename GridFunction::Range;
    using GridFctDomain = typename GridFunction::Domain;
    using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature;
49
50

    using Traits = DerivativeTraits<RawSignature, Type>;
51
    using LocalFunction = TYPEOF( derivativeOf(localFunction(std::declval<GridFunction>()), std::declval<Type>()) ) ;
52
53
54
55

    using LocalFctRange = typename Traits::Range;
    using LocalFctDomain = typename GridFunction::EntitySet::LocalCoordinate;

Praetorius, Simon's avatar
Praetorius, Simon committed
56
57
    CHECK_CONCEPT(Impl::CheckValidRange<Traits>);
    CHECK_CONCEPT(Impl::CheckFunctorConcept<LocalFunction, LocalFctRange(LocalFctDomain)>);
58

59
60
    enum { hasDerivative = false };

61
  public:
62
    /// The Range of the derivative of the GridFunction
63
    using Range = typename Traits::Range;
64

65
    /// The domain of the GridFunction
66
    using Domain = GridFctDomain;
67

68
69
    /// The EntitySet of the GridFunction
    using EntitySet = typename GridFunction::EntitySet;
70
71

  public:
72
    /// Constructor. Stores a copy of gridFct.
73
    explicit DerivativeGridFunction(GridFunction const& gridFct, Type const& type)
74
      : gridFct_{gridFct}
75
76
      , type_{type}
    {}
77

78
    /// Evaluate derivative in global coordinates. NOTE: expensive
79
80
    Range operator()(Domain const& x) const
    {
81
82
83
84
85
86
87
88
89
90
      auto gv = entitySet().gridView();

      using GridView = decltype(gv);
      using Grid = typename GridView::Grid;
      using IS = typename GridView::IndexSet;

      Dune::HierarchicSearch<Grid,IS> hsearch{gv.grid(), gv.indexSet()};

      auto element = hsearch.findEntity(x);
      auto geometry = element.geometry();
91
      auto localFct = makeLocalFunction();
92
93
      localFct.bind(element);
      return localFct(geometry.local(x));
94
95
    }

96
    /// Return the derivative-localFunction of the GridFunction.
97
    LocalFunction makeLocalFunction() const
98
    {
99
      return derivativeOf(localFunction(gridFct_), type_);
Praetorius, Simon's avatar
Praetorius, Simon committed
100
101
    }

102
    /// Return the \ref EntitySet of the \ref GridFunction.
103
104
105
106
107
108
    EntitySet const& entitySet() const
    {
      return gridFct_.entitySet();
    }

  private:
109
    GridFunction gridFct_;
110
    Type type_;
111
112
  };

113

114
  /// \fn derivativeOf
115
116
117
118
  /// \brief Create a GridFunction representing the derivative of the given
  /// Gridfunction.
  /**
   * A GridFunction can be differentiated if the corresponding LocalFunction
119
   * provides a free function `derivativeOf()`
120
121
122
   *
   * **Requirements:**
   * - The type `GridFct` models the concept of a GridFunction
123
   * - The `GridFct` has no own `derivativeOf()` function, i.e. it holds
124
125
126
   *   `GridFct::hasDerivative == false`.
   * - The localFunction of the `GridFct` models `Concepts::HasDerivative`.
   **/
127
128
  template <class GridFct, class Type,
            class LocalFct = decltype( localFunction(std::declval<GridFct>()) ),
129
    REQUIRES(not GridFct::hasDerivative)>
130
  auto derivativeOf(GridFct const& gridFct, Type const& type)
131
  {
132
    static_assert(Concepts::HasDerivative<LocalFct,Type>,
133
      "derivativeOf(LocalFunction,type) not defined!");
134
    return DerivativeGridFunction<GridFct,Type>{gridFct, type};
135
136
  }

137

138
#ifndef DOXYGEN
139
  template <class Expr, class Type>
140
141
  struct DerivativePreGridFunction
  {
142
143
144
145
146
147
148
    using Self = DerivativePreGridFunction;

    struct Creator
    {
      template <class GridView>
      static auto create(Self const& self, GridView const& gridView)
      {
149
        return derivativeOf(makeGridFunction(self.expr_, gridView), self.type_);
150
151
152
153
      }
    };

    Expr expr_;
154
    Type type_ = {};
155
156
157
158
  };

  namespace Traits
  {
159
160
    template <class Expr,class Type>
    struct IsPreGridFunction<DerivativePreGridFunction<Expr,Type>>
161
162
      : std::true_type {};
  }
163
#endif
164
165


166
  /// \fn gradientOf
167
168
  /// \brief Generator function for DerivativeGridFunction expressions.
  /// \relates DerivativeGridFunction
169
  /**
Praetorius, Simon's avatar
Praetorius, Simon committed
170
   * \ingroup GridFunctions
171
   * Generates a Gridfunction representing the gradient of a GridFunction.
172
   * See \ref DerivativeGridFunction.
173
174
   *
   * **Examples:**
175
176
   * - `gradientOf(prob.solution(_0))`
   * - `gradientOf(X(0) + X(1) + prob.solution(_0))`
177
   **/
178
  template <class Expr>
179
  auto gradientOf(Expr const& expr)
180
  {
181
182
183
184
185
    return DerivativePreGridFunction<Expr, tag::gradient>{expr};
  }

  /// Generates a Gridfunction representing the divergence of a vector-valued GridFunction.
  template <class Expr>
186
  auto divergenceOf(Expr const& expr)
187
188
189
190
191
192
  {
    return DerivativePreGridFunction<Expr, tag::divergence>{expr};
  }

  /// Generates a Gridfunction representing the partial derivative of a GridFunction.
  template <class Expr>
193
  auto partialDerivativeOf(Expr const& expr, std::size_t i)
194
195
  {
    return DerivativePreGridFunction<Expr, tag::partial>{expr, tag::partial{i}};
196
197
  }

198
199
200
  /** @} **/

} // end namespace AMDiS