DiscreteFunction.hpp 9.04 KB
Newer Older
1
2
#pragma once

3
#include <optional>
4
5
6
7
8
9
10
11
#include <vector>

#include <dune/functions/common/defaultderivativetraits.hh>
#include <dune/functions/functionspacebases/defaultnodetorangemap.hh>
#include <dune/functions/functionspacebases/flatvectorview.hh>
#include <dune/functions/gridfunctions/gridviewentityset.hh>
#include <dune/typetree/childextraction.hh>

Praetorius, Simon's avatar
Praetorius, Simon committed
12
#include <amdis/common/Tags.hpp>
13
#include <amdis/typetree/FiniteElementType.hpp>
14
#include <amdis/typetree/RangeType.hpp>
15
#include <amdis/typetree/TreePath.hpp>
16
17
18

namespace AMDiS
{
19
  /// \class DiscreteFunction
20
21
  /// \brief A view on a subspace of a \ref DOFVector
  /**
22
23
  * \ingroup GridFunctions
  *
Praetorius, Simon's avatar
Praetorius, Simon committed
24
25
26
  * \tparam Coeff     Const or mutable coefficient type of the DOFVector
  * \tparam GB        Thy type of the global basis
  * \tparam TreePath  A realization of \ref Dune::TypeTree::HybridTreePath
27
28
  *
  * **Requirements:**
29
  * - GB models \ref Concepts::GlobalBasis
30
  **/
31
  template <class Coeff, class GB, class TreePath>
32
33
  class DiscreteFunction;

34

Praetorius, Simon's avatar
Praetorius, Simon committed
35
36
37
38
  /// A mutable view on the subspace of a DOFVector, \relates DiscreteFunction
  template <class Coeff, class GB, class TreePath>
  class DiscreteFunction
      : public DiscreteFunction<Coeff const,GB,TreePath>
39
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
40
41
42
43
44
45
    using Self = DiscreteFunction<Coeff,GB,TreePath>;
    using Super = DiscreteFunction<Coeff const,GB,TreePath>;

    using Coefficients = Coeff;
    using GlobalBasis = GB;
    using ValueType = typename Coeff::value_type;
46

Praetorius, Simon's avatar
Praetorius, Simon committed
47
48
  public:
    /// Constructor. Stores a pointer to the mutable `dofvector`.
49
50
51
    template <class... Path>
    DiscreteFunction(Coefficients& dofVector, GlobalBasis const& basis, Path... path)
      : Super(dofVector, basis, path...)
Praetorius, Simon's avatar
Praetorius, Simon committed
52
53
54
      , mutableCoeff_(&dofVector)
    {}

55
56
57
58
59
60
61
62
    /// Construct a DiscreteFunction directly from a DOFVector
    template <class DV, class... Path,
      class Coeff_ = TYPEOF(std::declval<DV>().coefficients()),
      class GB_    = TYPEOF(*std::declval<DV>().basis())>
    DiscreteFunction(DV&& dofVector, Path... path)
      : DiscreteFunction(dofVector.coefficients(), *dofVector.basis(), path...)
    {}

Praetorius, Simon's avatar
Praetorius, Simon committed
63
64
65
66
67
68
  public:
    /// \brief Interpolation of GridFunction to DOFVector, assuming that there is no
    /// reference to this DOFVector in the expression.
    /**
     * **Example:**
     * ```
69
     * auto v = valueOf(prob.solutionVector(),0);
Praetorius, Simon's avatar
Praetorius, Simon committed
70
71
72
73
74
     * v.interpolate_noalias([](auto const& x) { return x[0]; });
     * ```
     **/
    template <class Expr, class Tag = tag::average>
    void interpolate_noalias(Expr&& expr, Tag strategy = {});
75

Praetorius, Simon's avatar
Praetorius, Simon committed
76
77
78
79
    /// \brief Interpolation of GridFunction to DOFVector
    /**
     * **Example:**
     * ```
80
     * auto v = valueOf(prob.solutionVector(),0);
Praetorius, Simon's avatar
Praetorius, Simon committed
81
82
83
     * v.interpolate(v + [](auto const& x) { return x[0]; });
     * ```
     * Allows to have a reference to the DOFVector in the expression, e.g. as
84
     * \ref DiscreteFunction or \ref gradientOf() of a DiscreteFunction.
Praetorius, Simon's avatar
Praetorius, Simon committed
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
     **/
    template <class Expr, class Tag = tag::average>
    void interpolate(Expr&& expr, Tag strategy = {});

    /// \brief Interpolation of GridFunction to DOFVector, alias to \ref interpolate()
    template <class Expr>
    Self& operator<<(Expr&& expr)
    {
      interpolate(FWD(expr));
      return *this;
    }

    /// \brief interpolate `(*this) + expr` to DOFVector
    template <class Expr>
    Self& operator+=(Expr&& expr)
    {
      interpolate((*this) + expr);
      return *this;
    }

    /// \brief interpolate `(*this) - expr` to DOFVector
    template <class Expr>
    Self& operator-=(Expr&& expr)
    {
      interpolate((*this) - expr);
      return *this;
    }

    /// Return the mutable DOFVector
Praetorius, Simon's avatar
Praetorius, Simon committed
114
115
116
117
    Coefficients& coefficients()
    {
      return *mutableCoeff_;
    }
Praetorius, Simon's avatar
Praetorius, Simon committed
118
119
120
121

    /// Return the const DOFVector
    using Super::coefficients;

122
123
    template <class... Indices>
    auto child(Indices... ii)
Praetorius, Simon's avatar
Praetorius, Simon committed
124
    {
125
126
      auto tp = cat(this->treePath_, makeTreePath(ii...));
      return DiscreteFunction<Coeff, GB, TYPEOF(makeTreePath(tp))>{*mutableCoeff_, this->basis(), tp};
Praetorius, Simon's avatar
Praetorius, Simon committed
127
128
129
130
131
132
133
    }

    using Super::child;

  protected:
    Coefficients* mutableCoeff_;
  };
134
135

  /// A Const DiscreteFunction
Praetorius, Simon's avatar
Praetorius, Simon committed
136
137
  template <class Coeff, class GB, class TreePath>
  class DiscreteFunction<Coeff const,GB,TreePath>
138
  {
139
  private:
Praetorius, Simon's avatar
Praetorius, Simon committed
140
    using Coefficients = std::remove_const_t<Coeff>;
141
    using GlobalBasis = GB;
Praetorius, Simon's avatar
Praetorius, Simon committed
142
    using ValueType = typename Coefficients::value_type;
143
144
145
146
147
148

    using Tree = typename GlobalBasis::LocalView::Tree;
    using SubTree = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>;
    using NodeToRangeEntry = Dune::Functions::DefaultNodeToRangeMap<SubTree>;
    using GridView = typename GlobalBasis::GridView;

149
  public:
150
151
152
    /// Set of entities the DiscreteFunction is defined on
    using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>;

153
    /// Global coordinates of the EntitySet
154
155
    using Domain = typename EntitySet::GlobalCoordinate;

156
    /// Range type of this DiscreteFunction
Praetorius, Simon's avatar
Praetorius, Simon committed
157
    using Range = RangeType_t<SubTree,ValueType>;
158

159
160
    /// \brief This GridFunction has no derivative function, it can be created
    /// by \ref DiscreteGridFunction.
161
162
    enum { hasDerivative = false };

163
164
  public:
    /// A LocalFunction representing the derivative of the DOFVector on a bound element
165
166
167
    template <class Type>
    class DerivativeLocalFunctionBase;

168
    class GradientLocalFunction;
169
170
    class PartialLocalFunction;
    class DivergenceLocalFunction;
171

172
    /// A LocalFunction representing the value the DOFVector on a bound element
173
    class LocalFunction;
174
175
176

  public:
    /// Constructor. Stores a pointer to the dofVector and a copy of the treePath.
177
178
    template <class... Path>
    DiscreteFunction(Coefficients const& coefficients, GlobalBasis const& basis, Path... path)
Praetorius, Simon's avatar
Praetorius, Simon committed
179
180
      : coefficients_(&coefficients)
      , basis_(&basis)
181
      , treePath_(makeTreePath(path...))
Praetorius, Simon's avatar
Praetorius, Simon committed
182
      , entitySet_(basis_->gridView())
Praetorius, Simon's avatar
Praetorius, Simon committed
183
      , nodeToRangeEntry_(Dune::Functions::makeDefaultNodeToRangeMap(*basis_, treePath_))
184
185
    {}

186
187
188
189
190
191
192
193
194
    /// Construct a DiscreteFunction directly from a DOFVector
    template <class DV, class... Path,
      class Coeff_ = TYPEOF(std::declval<DV>().coefficients()),
      class GB_    = TYPEOF(*std::declval<DV>().basis())>
    DiscreteFunction(DV const& dofVector, Path... path)
      : DiscreteFunction(dofVector.coefficients(), *dofVector.basis(), path...)
    {}


195
    /// \brief Evaluate DiscreteFunction in global coordinates. NOTE: expensive
196
197
198
    Range operator()(Domain const& x) const;

    /// \brief Create a local function for this view on the DOFVector. \relates LocalFunction
199
    LocalFunction makeLocalFunction() const
200
    {
201
      return LocalFunction{*this};
202
203
    }

204
    /// \brief Return a \ref Dune::Functions::GridViewEntitySet
205
206
207
208
209
    EntitySet const& entitySet() const
    {
      return entitySet_;
    }

210
    /// \brief Return global basis bound to the DOFVector
Praetorius, Simon's avatar
Praetorius, Simon committed
211
    GlobalBasis const& basis() const
212
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
213
      return *basis_;
214
215
    }

216
    /// \brief Return treePath associated with this discrete function
217
218
219
220
221
    TreePath const& treePath() const
    {
      return treePath_;
    }

222
    /// \brief Return const coefficient vector
Praetorius, Simon's avatar
Praetorius, Simon committed
223
    Coefficients const& coefficients() const
224
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
225
      return *coefficients_;
226
227
    }

228
229
    template <class... Indices>
    auto child(Indices... ii) const
230
    {
231
232
      auto tp = cat(this->treePath_, makeTreePath(ii...));
      return DiscreteFunction<Coeff const, GB, TYPEOF(makeTreePath(tp))>{*coefficients_, *basis_, tp};
233
234
    }

235
  protected:
Praetorius, Simon's avatar
Praetorius, Simon committed
236
237
    Coefficients const* coefficients_;
    GlobalBasis const* basis_;
238
    TreePath treePath_;
239
240
241
242
    EntitySet entitySet_;
    NodeToRangeEntry nodeToRangeEntry_;
  };

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  // deduction guides

  template <class Coeff, class GB, class... Path,
    class TP = TYPEOF(makeTreePath(std::declval<Path>()...)),
    REQUIRES(Concepts::GlobalBasis<GB>)>
  DiscreteFunction(Coeff&, GB const&, Path...)
    -> DiscreteFunction<Coeff,GB,TP>;

  template <class DV, class... Path,
    class Coeff = decltype(std::declval<DV>().coefficients()),
    class GB    = decltype(*std::declval<DV>().basis()),
    class TP    = TYPEOF(makeTreePath(std::declval<Path>()...))>
  DiscreteFunction(DV&, Path...)
    -> DiscreteFunction<std::remove_reference_t<Coeff>,std::decay_t<GB>,TP>;

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

  // grid functions representing the DOFVector
  // -----------------------------------------

  /// A Generator for the childs of a mutable \ref DiscreteFunction
  template <class Coeff, class GB, class... Path, class... Indices>
  auto valueOf(DiscreteFunction<Coeff,GB,Path...>& df, Indices... ii)
  {
    return df.child(ii...);
  }

  /// A Generator for the childs of a const \ref DiscreteFunction
  template <class Coeff, class GB, class... Path, class... Indices>
  auto valueOf(DiscreteFunction<Coeff,GB,Path...> const& df, Indices... ii)
  {
    return df.child(ii...);
  }

  /// A Generator to transform a DOFVector into a \ref DiscreteFunction
  template <class DV, class... Indices,
    class = decltype(std::declval<DV>().coefficients()),
    class = decltype(std::declval<DV>().basis())>
  auto valueOf(DV& dofVec, Indices... ii)
  {
    return DiscreteFunction{dofVec.coefficients(), *dofVec.basis(), makeTreePath(ii...)};
  }

285
286
} // end namespace AMDiS

287
#include "DiscreteLocalFunction.inc.hpp"
288
#include "DiscreteFunction.inc.hpp"