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

#include <type_traits>

#include <dune/functions/common/defaultderivativetraits.hh>
6
#include <dune/grid/utility/hierarchicsearch.hh>
7

8
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
Praetorius, Simon's avatar
Praetorius, Simon committed
9

10
11
12
namespace AMDiS
{
  /**
Praetorius, Simon's avatar
Praetorius, Simon committed
13
    * \addtogroup GridFunctions
14
15
16
    * @{
    **/

17
18
19
20
21
22
23
24
25
26
27
  /// \brief A Gridfunction that returns the derivative when calling localFunction.
  /**
   * Wrapps the GridFunction so that \ref localFunction returns a LocalFunction
   * representing the derivative of the LocalFunction of the GridFunction.
   *
   * \tparam GridFunction The GridFunction that is wrapped.
   *
   * **Requirements:**
   * - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction has a derivative.
   **/
  template <class GridFunction>
28
29
  class DerivativeGridFunction
  {
30
31
32
    using GridFctRange = typename GridFunction::Range;
    using GridFctDomain = typename GridFunction::Domain;
    using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature;
33
    using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>;
34
    using LocalFunction = std::decay_t<decltype(derivative(localFunction(std::declval<GridFunction>())))>;
35

36
37
    enum { hasDerivative = false };

38
  public:
39
    /// The Range of the derivative of the GridFunction
40
41
    using Range = typename DerivativeTraits::Range;

42
    /// The domain of the GridFunction
43
    using Domain = GridFctDomain;
44

45
46
    /// The EntitySet of the GridFunction
    using EntitySet = typename GridFunction::EntitySet;
47
48

  public:
49
50
    /// Constructor. Stores a copy of gridFct.
    explicit DerivativeGridFunction(GridFunction const& gridFct)
51
      : gridFct_{gridFct}
52
53
54
    {
      static_assert(isValidRange<DerivativeTraits>(), "Derivative of GridFunction not defined");
    }
55

56
    /// Evaluate derivative in global coordinates. NOTE: expensive
57
58
    Range operator()(Domain const& x) const
    {
59
60
61
62
63
64
65
66
67
68
69
70
71
      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();
      auto localFct = derivative(localFunction(gridFct_));
      localFct.bind(element);
      return localFct(geometry.local(x));
72
73
    }

74
    /// Return the derivative-localFunction of the GridFunction.
75
    friend LocalFunction localFunction(DerivativeGridFunction const& gf)
76
    {
77
      return derivative(localFunction(gf.gridFct_));
Praetorius, Simon's avatar
Praetorius, Simon committed
78
79
    }

80
    /// Return the \ref EntitySet of the \ref GridFunction.
81
82
83
84
85
86
    EntitySet const& entitySet() const
    {
      return gridFct_.entitySet();
    }

  private:
87
    GridFunction gridFct_;
88
89
  };

90

91
#ifndef DOXYGEN
Praetorius, Simon's avatar
Praetorius, Simon committed
92
  template <class GridFct,
93
            class LocalFct = decltype(localFunction(std::declval<GridFct>())),
94
    REQUIRES(not GridFct::hasDerivative)>
Praetorius, Simon's avatar
Praetorius, Simon committed
95
  auto derivative(GridFct const& gridFct)
96
  {
97
    static_assert(Concepts::HasDerivative<LocalFct>, "derivative(LocalFunction) not defined!");
Praetorius, Simon's avatar
Praetorius, Simon committed
98
    return DerivativeGridFunction<GridFct>{gridFct};
99
100
  }

101
102
103
104

  template <class Expr>
  struct DerivativePreGridFunction
  {
105
106
107
108
109
110
111
112
113
114
115
116
    using Self = DerivativePreGridFunction;

    struct Creator
    {
      template <class GridView>
      static auto create(Self const& self, GridView const& gridView)
      {
        return derivative(makeGridFunction(self.expr_, gridView));
      }
    };

    Expr expr_;
117
118
119
120
121
122
123
124
  };

  namespace Traits
  {
    template <class Expr>
    struct IsPreGridFunction<DerivativePreGridFunction<Expr>>
      : std::true_type {};
  }
125
#endif
126
127


128
129
130
131
132
133
134
135
  /// \brief Generator function for DerivativeGridFunction expressions. \relates DerivativeGridFunction
  /**
   * Generates a derivative of a GridFunction. See \ref DerivativeGridFunction.
   *
   * **Examples:**
   * - `gradientAtQP(prob.getSolution(_0))`
   * - `gradientAtQP(X(0) + X(1) + prob.getSolution(_0))`
   **/
136
137
138
139
140
141
  template <class Expr>
  auto gradientAtQP(Expr const& expr)
  {
    return DerivativePreGridFunction<Expr>{expr};
  }

142
143
144
  /** @} **/

} // end namespace AMDiS