DOFVectorView.hpp 10.3 KB
Newer Older
1 2
#pragma once

3 4 5 6
#include <vector>

#include <dune/common/std/optional.hh>
#include <dune/functions/common/defaultderivativetraits.hh>
7
#include <dune/functions/common/treedata.hh>
8
#include <dune/functions/functionspacebases/defaultnodetorangemap.hh>
Praetorius, Simon's avatar
Praetorius, Simon committed
9
#include <dune/functions/functionspacebases/flatvectorview.hh>
10 11 12
#include <dune/functions/gridfunctions/gridviewentityset.hh>
#include <dune/typetree/childextraction.hh>

13 14
#include <amdis/GridFunctions.hpp>
#include <amdis/utility/FiniteElementType.hpp>
15

16 17
namespace AMDiS
{
18 19 20 21 22
  /**
    * \addtogroup GridFunctions
    * @{
    **/

23
  template <class GlobalBasisType, class RangeType, class TreePathType>
Praetorius, Simon's avatar
Praetorius, Simon committed
24
  class DOFVectorConstView
25 26
  {
  public:
27
    using GlobalBasis = GlobalBasisType;
28 29 30
    using TreePath = TreePathType;

    using Tree = typename GlobalBasis::LocalView::Tree;
31 32
    using SubTree = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>;
    using NodeToRangeEntry = Dune::Functions::DefaultNodeToRangeMap<SubTree>;
33 34

    using GridView = typename GlobalBasis::GridView;
35
    using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>;
36 37

    using Domain = typename EntitySet::GlobalCoordinate;
38
    using Range = RangeType_t<SubTree>;
39 40
    static_assert(std::is_arithmetic<RangeType>::value, "");
    // Don't know how to determine Range with non-trivial RangeType
41

42 43
    using RawSignature = typename Dune::Functions::SignatureTraits<Range(Domain)>::RawSignature;
    using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>;
44 45
    using DerivativeRange = typename DerivativeTraits::Range;

46 47
    using LocalDomain = typename EntitySet::LocalCoordinate;
    using Element = typename EntitySet::Element;
48 49
    using Geometry = typename Element::Geometry;

50
    enum { hasDerivative = false };
Praetorius, Simon's avatar
Praetorius, Simon committed
51

52 53
  public: // a local view on the gradients

54
    /// A LocalFunction representing the derivative of the DOFVector
55 56 57 58 59 60
    class GradientLocalFunction
    {
    public:
      using Domain = LocalDomain;
      using Range = DerivativeRange;

61 62
      enum { hasDerivative = false };

63
    private:
Praetorius, Simon's avatar
Praetorius, Simon committed
64
      using LocalView = typename GlobalBasis::LocalView;
65 66 67 68 69 70 71 72 73 74

      template <class LeafNode>
      using LocalBasisJacobian = typename LeafNode::FiniteElement::Traits::LocalBasisType::Traits::JacobianType;

      template <class Node>
      using NodeData = typename std::vector<LocalBasisJacobian<Node>>;

      using ReferenceGradientContainer = Dune::Functions::TreeData<SubTree, NodeData, true>;

    public:
Praetorius, Simon's avatar
Praetorius, Simon committed
75
      GradientLocalFunction(DOFVectorConstView const& globalFunction)
76
        : globalFunction_(&globalFunction)
Praetorius, Simon's avatar
Praetorius, Simon committed
77 78
        , localView_(globalFunction_->basis().localView())
        , subTree_(&Dune::TypeTree::child(localView_.tree(), globalFunction_->treePath()))
79 80 81 82 83 84
      {
        referenceGradientContainer_.init(*subTree_);
      }

      void bind(Element const& element)
      {
Praetorius, Simon's avatar
Praetorius, Simon committed
85
        localView_.bind(element);
86 87 88 89 90 91
        geometry_.emplace(element.geometry());
        bound_ = true;
      }

      void unbind()
      {
Praetorius, Simon's avatar
Praetorius, Simon committed
92
        localView_.unbind();
93 94 95 96 97 98 99
        geometry_.reset();
        bound_ = false;
      }

      /// Evaluate Gradient at bound element in local coordinates
      Range operator()(Domain const& x) const;

100 101 102
      friend int order(GradientLocalFunction const& self)
      {
        assert( self.bound_ );
103
        return std::max(0, polynomialDegree(*self.subTree_)-1);
104 105
      }

106 107 108 109
      /// Return the bound element
      Element const& localContext() const
      {
        assert( bound_ );
Praetorius, Simon's avatar
Praetorius, Simon committed
110
        return localView_.element();
111 112 113
      }

    private:
Praetorius, Simon's avatar
Praetorius, Simon committed
114
      DOFVectorConstView const* globalFunction_;
Praetorius, Simon's avatar
Praetorius, Simon committed
115
      LocalView localView_;
116 117 118 119 120 121 122 123 124 125

      SubTree const* subTree_;
      mutable ReferenceGradientContainer referenceGradientContainer_;

      Dune::Std::optional<Geometry> geometry_;
      bool bound_ = false;
    };


  public: // a local view on the values
126

127
    /// A LocalFunction, i.e., an element local view on the DOFVector
128 129 130
    class LocalFunction
    {
    public:
Praetorius, Simon's avatar
Praetorius, Simon committed
131 132
      using Domain = typename DOFVectorConstView::LocalDomain;
      using Range = typename DOFVectorConstView::Range;
133

134 135
      enum { hasDerivative = true };

136
    private:
Praetorius, Simon's avatar
Praetorius, Simon committed
137
      using LocalView = typename GlobalBasis::LocalView;
138 139

      template <class LeafNode>
140 141
      using LocalBasisRange = RangeType_t<LeafNode>;
        // = typename LeafNode::FiniteElement::Traits::LocalBasisType::Traits::RangeType;
142 143 144 145 146 147 148

      template <class Node>
      using NodeData = typename std::vector<LocalBasisRange<Node>>;

      using ShapeFunctionValueContainer = Dune::Functions::TreeData<SubTree, NodeData, true>;

    public:
Praetorius, Simon's avatar
Praetorius, Simon committed
149
      LocalFunction(DOFVectorConstView const& globalFunction)
150
        : globalFunction_(&globalFunction)
Praetorius, Simon's avatar
Praetorius, Simon committed
151 152
        , localView_(globalFunction_->basis().localView())
        , subTree_(&Dune::TypeTree::child(localView_.tree(), globalFunction_->treePath()))
153
      {
154
        shapeFunctionValueContainer_.init(*subTree_);
155 156 157 158
      }

      void bind(Element const& element)
      {
Praetorius, Simon's avatar
Praetorius, Simon committed
159
        localView_.bind(element);
160 161 162 163 164
        bound_ = true;
      }

      void unbind()
      {
Praetorius, Simon's avatar
Praetorius, Simon committed
165
        localView_.unbind();
166 167 168
        bound_ = false;
      }

169
      /// Evaluate LocalFunction at bound element in local coordinates
170 171
      Range operator()(Domain const& x) const;

172
      /// \brief Create a LocalFunction representing the gradient. \relates GradientLocalFunction
173 174
      friend GradientLocalFunction derivative(LocalFunction const& localFunction)
      {
175
        static_assert(isValidRange<DerivativeTraits>(),"Derivative of DOFVector not defined.");
176 177 178
        return GradientLocalFunction{*localFunction.globalFunction_};
      }

179 180 181
      friend int order(LocalFunction const& self)
      {
        assert( self.bound_ );
182
        return polynomialDegree(*self.subTree_);
183 184
      }

185
      /// Return the bound element
186 187
      Element const& localContext() const
      {
188
        assert( bound_ );
Praetorius, Simon's avatar
Praetorius, Simon committed
189
        return localView_.element();
190 191 192
      }

    private:
Praetorius, Simon's avatar
Praetorius, Simon committed
193
      DOFVectorConstView const* globalFunction_;
Praetorius, Simon's avatar
Praetorius, Simon committed
194
      LocalView localView_;
195
      SubTree const* subTree_;
196 197 198 199 200 201

      mutable ShapeFunctionValueContainer shapeFunctionValueContainer_;

      bool bound_ = false;
    };

202

203
  public:
204
    /// Constructor. Stores a pointer to the dofVector and a copy of the treePath.
205
    DOFVectorConstView(DOFVector<GlobalBasis,RangeType> const& dofVector, TreePath const& treePath)
206
      : dofVector_(&dofVector)
207
      , treePath_(treePath)
208 209
      , entitySet_(dofVector.basis().gridView())
      , nodeToRangeEntry_(Dune::Functions::makeDefaultNodeToRangeMap(dofVector.basis(), treePath))
210 211
    {}

212
    /// Evaluate the view on this DOFVector in global coordinates
213 214 215 216 217 218
    Range operator()(Domain const& x) const
    {
      error_exit("Not implemented.");
      return Range(0);
    }

219
    /// \brief Create a local function for this view on the DOFVector. \relates LocalFunction
Praetorius, Simon's avatar
Praetorius, Simon committed
220
    friend LocalFunction localFunction(DOFVectorConstView const& self)
221
    {
222 223 224
      return LocalFunction{self};
    }

225 226 227 228 229 230
    EntitySet const& entitySet() const
    {
      return entitySet_;
    }

  public:
231 232 233
    /// Return global basis
    GlobalBasis const& basis() const
    {
234
      return dofVector_->basis();
235 236 237 238 239 240 241 242 243
    }

    /// Return treePath associated with this view
    TreePath const& treePath() const
    {
      return treePath_;
    }

    /// Return const coefficient vector
244
    DOFVector<GlobalBasis,RangeType> const& coefficients() const
245 246 247 248 249
    {
      return *dofVector_;
    }

  protected:
250
    DOFVector<GlobalBasis,RangeType> const* dofVector_;
251 252 253 254 255 256 257 258
    TreePath const treePath_;

    EntitySet entitySet_;
    NodeToRangeEntry nodeToRangeEntry_;
  };


  // A mutable version of DOFVectorView
259
  template <class GlobalBasisType, class RangeType, class TreePathType>
Praetorius, Simon's avatar
Praetorius, Simon committed
260
  class DOFVectorMutableView
261
      : public DOFVectorConstView<GlobalBasisType, RangeType, TreePathType>
262
  {
263
    using Super = DOFVectorConstView<GlobalBasisType, RangeType, TreePathType>;
264

265
    using GlobalBasis = GlobalBasisType;
266 267 268 269
    using TreePath = TreePathType;

  public:
    /// Constructor. Stores a pointer to the mutable `dofvector`.
270
    DOFVectorMutableView(DOFVector<GlobalBasis,RangeType>& dofVector, TreePath const& treePath)
Praetorius, Simon's avatar
Praetorius, Simon committed
271
      : Super(dofVector, treePath)
272 273 274 275
      , mutableDofVector_(&dofVector)
    {}

  public:
Praetorius, Simon's avatar
Praetorius, Simon committed
276 277
    /// Interpolation of GridFunction to DOFVector
    template <class Expr>
Praetorius, Simon's avatar
Praetorius, Simon committed
278
    DOFVectorMutableView& interpolate(Expr&& expr)
279
    {
Praetorius, Simon's avatar
Praetorius, Simon committed
280 281
      auto const& basis = Super::basis();
      auto const& treePath = Super::treePath();
282

283
      auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), basis.gridView());
284

285
      DOFVector<GlobalBasis,RangeType> tmp(*mutableDofVector_);
286
      Dune::Functions::interpolate(basis, treePath, tmp, std::forward<decltype(gridFct)>(gridFct));
287

288
      // move data from temporary vector into stored DOFVector
289
      mutableDofVector_->vector() = std::move(tmp.vector());
290 291
      return *this;
    }
292

293 294 295 296 297 298 299
    template <class Expr>
    DOFVectorMutableView& operator<<(Expr&& expr)
    {
      return interpolate(expr);
    }


300
    /// Return the mutable DOFVector
301
    DOFVector<GlobalBasis,RangeType>& coefficients() { return *mutableDofVector_; }
302

303
    /// Return the const DOFVector
Praetorius, Simon's avatar
Praetorius, Simon committed
304
    using Super::coefficients;
305

306
  protected:
307
    DOFVector<GlobalBasis,RangeType>* mutableDofVector_;
308 309
  };

310 311
  /** @} **/

312

313
#ifndef DOXYGEN
314
  // A Generator for a const \ref DOFVectorView.
315 316
  template <class GlobalBasis, class RangeType, class TreePath>
  auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType> const& dofVector, TreePath const& treePath)
317
  {
318
    return DOFVectorConstView<GlobalBasis, RangeType, TreePath>{dofVector, treePath};
319 320 321
  }

  // A Generator for a mutable \ref DOFVectorView.
322 323
  template <class GlobalBasis, class RangeType, class TreePath>
  auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType>& dofVector, TreePath const& treePath)
324
  {
325
    return DOFVectorMutableView<GlobalBasis, RangeType, TreePath>{dofVector, treePath};
326 327 328 329
  }


  // A Generator for a const \ref DOFVectorView.
330 331
  template <class GlobalBasis, class RangeType>
  auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType> const& dofVector)
332 333
  {
    auto treePath = Dune::TypeTree::hybridTreePath();
334
    return DOFVectorConstView<GlobalBasis, RangeType, decltype(treePath)>{dofVector, treePath};
335 336 337
  }

  // A Generator for a mutable \ref DOFVectorView.
338 339
  template <class GlobalBasis, class RangeType>
  auto makeDOFVectorView(DOFVector<GlobalBasis, RangeType>& dofVector)
340 341
  {
    auto treePath = Dune::TypeTree::hybridTreePath();
342
    return DOFVectorMutableView<GlobalBasis, RangeType, decltype(treePath)>{dofVector, treePath};
343
  }
344
#endif
345

346 347 348
} // end namespace AMDiS

#include "DOFVectorView.inc.hpp"