DOFVectorBase.hpp 8.99 KB
Newer Older
1
2
#pragma once

3
#include <cmath>
4
#include <utility>
5

6
#include <dune/common/typetraits.hh>
7
#include <dune/functions/functionspacebases/sizeinfo.hh>
8

9
#include <amdis/DataTransfer.hpp>
10
#include <amdis/GridTransferManager.hpp>
11
#include <amdis/OperatorList.hpp>
12
#include <amdis/common/Math.hpp>
13
#include <amdis/common/TypeTraits.hpp>
14
15
16
#include <amdis/linearalgebra/DOFVectorInterface.hpp>
#include <amdis/typetree/MultiIndex.hpp>
#include <amdis/typetree/TreePath.hpp>
17
18
19

namespace AMDiS
{
20
21
  /// The container that stores a data-vector and a corresponding basis, should be
  /// derived from \ref DOFVectorBase.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  template <class GlobalBasis, class ValueType = double>
  class DOFVector;

  /// \brief Create a DOFVector from a basis.
  /**
   * This generator function accepts the basis as reference, temporary, or
   * shared_ptr. Internally the reference is wrapped into a non-destroying
   * shared_ptr and the temporary is moved into a new shared_ptr.
   *
   * The DataTransferOperation controls what is done during grid changes with the
   * DOFVector. The default is interpolation of the data to the new grid. See
   * \ref DataTransferOperation for more options.
   **/
  template <class ValueType = double, class GlobalBasis>
  DOFVector<Underlying_t<GlobalBasis>, ValueType>
  makeDOFVector(GlobalBasis&& basis, DataTransferOperation op = DataTransferOperation::INTERPOLATE)
  {
    return {FWD(basis), op};
  }


43
44
45
46
47
48
  /// \brief The basic container that stores a base vector and a corresponding basis
  /**
   * Basis implementation of DOFVector, i.e. a vector storing all the
   * assembled Operators indexed with DOF indices. The vector data is associated
   * to a global basis.
   *
49
   * \tparam GB  Basis of the vector
50
51
   * \tparam Backend  A linear algebra backend implementing the storage and operations.
   **/
52
  template <class GB, class Backend>
53
54
55
56
57
58
  class DOFVectorBase
      : public DOFVectorInterface
  {
    using Self = DOFVectorBase;

  public:
59
    /// The type of the functionspace basis associated to this vector
60
61
    using GlobalBasis = GB;
    using LocalView = typename GB::LocalView;
62
63
64

    using Element = typename LocalView::Element;
    using Geometry = typename Element::Geometry;
65
66

    /// The index/size - type
67
    using size_type  = typename GB::size_type;
68

69
70
71
    /// The type of the elements of the DOFVector
    using value_type = typename Backend::value_type;

72
    /// The type of the data vector used in the backend
73
    using BaseVector = typename Backend::BaseVector;
74
75

    /// The type of the vector filled on an element with local contributions
76
    using ElementVector = Dune::DynamicVector<value_type>;
77

78
79
80
81
82
83
    /// Defines an interface to transfer the data during grid adaption
    using DataTransfer = DataTransferInterface<Self>;

    /// A creator for a concrete data transfer object, depending on \ref DataTransferOperation
    using DataTransferFactory = AMDiS::DataTransferFactory<Self>;

84
  public:
85
86
87
88
    /// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
    DOFVectorBase(std::shared_ptr<GlobalBasis> basis, DataTransferOperation op)
      : basis_(basis)
      , dataTransfer_(DataTransferFactory::create(op, *basis_))
89
90
    {
      compress();
91
      attachToGridTransfer();
92
      operators_.init(*basis_);
93
    }
94

95
96
    /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves
    /// the basis into a new shared_ptr.
97
98
99
100
101
    template <class GB_>
    DOFVectorBase(GB_&& basis, DataTransferOperation op)
      : DOFVectorBase(Dune::wrap_or_move(FWD(basis)), op)
    {}

102
103
104
105
106
107
108
109
    /// Copy constructor
    DOFVectorBase(Self const& that)
      : basis_(that.basis_)
      , backend_(that.backend_)
      , elementVector_(that.elementVector_)
      , operators_(that.operators_)
      , dataTransfer_(that.dataTransfer_)
    {
110
      attachToGridTransfer();
111
112
113
114
115
116
117
118
119
120
    }

    /// Move constructor
    DOFVectorBase(Self&& that)
      : basis_(std::move(that.basis_))
      , backend_(std::move(that.backend_))
      , elementVector_(std::move(that.elementVector_))
      , operators_(std::move(that.operators_))
      , dataTransfer_(std::move(that.dataTransfer_))
    {
121
      attachToGridTransfer();
122
123
124
    }

    /// Destructor
125
    ~DOFVectorBase() override
126
    {
127
      detachFromGridTransfer();
128
    }
129
130
131
132

    /// Copy assignment operator
    Self& operator=(Self const& that)
    {
133
      detachFromGridTransfer();
134
      basis_ = that.basis_;
135
136
      backend_.resize(that.size());
      backend_ = that.backend_;
137
      dataTransfer_ = that.dataTransfer_;
138
      attachToGridTransfer();
139
140
141
142
143
144
145
      return *this;
    }

    /// Move assignment
    Self& operator=(Self&& that) = default;

    /// Sets each DOFVector to the scalar \p value.
146
    template <class Number,
147
      REQUIRES(Dune::IsNumber<Number>::value)>
148
    Self& operator=(Number value)
149
    {
150
      backend_.set(value);
151
152
153
      return *this;
    }

154
    /// Return the basis \ref basis_ associated to the vector
155
    std::shared_ptr<GlobalBasis const> basis() const
156
    {
157
      return basis_;
158
159
160
161
162
163
164
165
166
167
168
169
    }

    /// Return the data-vector
    BaseVector const& vector() const
    {
      return backend_.vector();
    }

    /// Return the data-vector
    BaseVector& vector()
    {
      return backend_.vector();
170
171
172
173
174
175
176
177
    }

    /// Return the size of the \ref basis
    size_type size() const
    {
      return basis_->dimension();
    }

178
    /// Resize the \ref vector to the size of the \ref basis
179
    void resize(Dune::Functions::SizeInfo<GB> const& s)
180
181
182
183
    {
      backend_.resize(size_type(s));
    }

184
    /// Resize the \ref vector to the size of the \ref basis and set to zero
185
    void compress() override
186
    {
187
      if (size_type(backend_.size()) != size()) {
188
        backend_.resize(size());
189
        backend_.set(0);
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
      }
    }

    /// Access the entry \p idx of the \ref vector with read-access.
    template <class Index>
    auto const& operator[](Index idx) const
    {
      size_type i = flatMultiIndex(idx);
      return backend_[i];
    }

    /// Access the entry \p idx of the \ref vector with write-access.
    template <class Index>
    auto& operator[](Index idx)
    {
      size_type i = flatMultiIndex(idx);
      return backend_[i];
    }

209
210
    /// Prepare the DOFVector for insertion of values, finish the insertion with
    /// \ref finish().
211
    void init(bool asmVector);
212

213
    /// Finish the insertion of values, see \ref init()
214
    void finish(bool asmVector);
215

216
    /// Insert a block of values into the matrix (add to existing values)
217
    void insert(LocalView const& localView, ElementVector const& elementVector);
218

219
    /// Associate a local operator with this DOFVector
220
221
    template <class ContextTag, class Expr, class TreePath = RootTreePath>
    void addOperator(ContextTag contextTag, Expr const& expr, TreePath path = {});
222

223
224
    /// Assemble the vector operators on the bound element.
    void assemble(LocalView const& localView);
225

226
    /// Assemble all vector operators added by \ref addOperator().
227
    void assemble();
228

229
    /// Return the associated DataTransfer object
230
    std::shared_ptr<DataTransfer const> dataTransfer() const
231
    {
232
      return dataTransfer_;
233
234
235
    }

    /// Return the associated DataTransfer object
236
    std::shared_ptr<DataTransfer> dataTransfer()
237
    {
238
      return dataTransfer_;
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    }

    /// Create a new DataTransfer object based on the operation type
    void setDataTransfer(DataTransferOperation op)
    {
      dataTransfer_ = DataTransferFactory::create(op, this->basis());
    }

    /// Assign the DataTransfer object
    void setDataTransfer(std::shared_ptr<DataTransfer> const& dataTransfer)
    {
      dataTransfer_ = dataTransfer;
    }

    /// Implementation of \ref DOFVectorInterface::preAdapt
254
    /// Redirects to a \ref DataTransfer object.
255
    void preAdapt(bool mightCoarsen) override
256
257
258
259
260
    {
      dataTransfer_->preAdapt(*this, mightCoarsen);
    }

    /// Implementation of \ref DOFVectorInterface::postAdapt
261
    /// Redirects to a \ref DataTransfer object.
262
    void postAdapt(bool refined) override
263
264
265
266
    {
      dataTransfer_->postAdapt(*this, refined);
    }

267
  private:
268
    // register this DOFVector and its basis to the DataTransfer
269
270
271
272
273
274
    void attachToGridTransfer()
    {
      GridTransferManager::attach(basis_->gridView().grid(), *this);
      GridTransferManager::attach(basis_->gridView().grid(), *basis_);
    }

275
    // deregister this DOFVector and its basis from the DataTransfer
276
277
278
279
280
281
    void detachFromGridTransfer()
    {
      GridTransferManager::detach(basis_->gridView().grid(), *basis_);
      GridTransferManager::detach(basis_->gridView().grid(), *this);
    }

282
283
  private:
    /// The finite element space / basis associated with the data vector
284
    std::shared_ptr<GlobalBasis> basis_;
285

286
    /// Data backend
287
    Backend backend_;
288
289
290
291

    /// Dense vector to store coefficients during \ref assemble()
    ElementVector elementVector_;

292
    /// List of operators associated to nodes, filled in \ref addOperator().
293
    VectorOperators<GlobalBasis,ElementVector> operators_;
294

295
296
    /// Data interpolation when the grid changes, set by default
    /// to \ref DataTransferOperation::INTERPOLATE.
297
    std::shared_ptr<DataTransfer> dataTransfer_;
298
299
300
  };

} // end namespace AMDiS
301
302

#include "DOFVectorBase.inc.hpp"