DOFVectorBase.hpp 9.19 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/FlatVector.hpp>
13
#include <amdis/common/Math.hpp>
14
#include <amdis/common/TypeTraits.hpp>
15
16
17
#include <amdis/linearalgebra/DOFVectorInterface.hpp>
#include <amdis/typetree/MultiIndex.hpp>
#include <amdis/typetree/TreePath.hpp>
18
19
20

namespace AMDiS
{
21
22
  /// The container that stores a data-vector and a corresponding basis, should be
  /// derived from \ref DOFVectorBase.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  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};
  }


44
45
46
47
48
49
  /// \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.
   *
50
   * \tparam GB  Basis of the vector
51
52
   * \tparam Backend  A linear algebra backend implementing the storage and operations.
   **/
53
  template <class GB, class Backend>
54
55
56
57
58
59
  class DOFVectorBase
      : public DOFVectorInterface
  {
    using Self = DOFVectorBase;

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

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

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

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

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

    /// The type of the vector filled on an element with local contributions
77
    using ElementVector = FlatVector<value_type>;
78

79
80
81
82
83
84
    /// 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>;

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

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

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

    /// 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_))
    {
122
      attachToGridTransfer();
123
124
125
    }

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

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

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

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

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

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

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

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

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

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

    /// 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];
    }

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

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

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

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

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

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

230
231
232
233
234
235
    /// Write DOFVector to file
    void backup(std::string const& filename);

    /// Read backup data from file
    void restore(std::string const& filename);

236
    /// Return the associated DataTransfer object
237
    std::shared_ptr<DataTransfer const> dataTransfer() const
238
    {
239
      return dataTransfer_;
240
241
242
    }

    /// Return the associated DataTransfer object
243
    std::shared_ptr<DataTransfer> dataTransfer()
244
    {
245
      return dataTransfer_;
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
    }

    /// 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
261
    /// Redirects to a \ref DataTransfer object.
262
    void preAdapt(bool mightCoarsen) override
263
264
265
266
267
    {
      dataTransfer_->preAdapt(*this, mightCoarsen);
    }

    /// Implementation of \ref DOFVectorInterface::postAdapt
268
    /// Redirects to a \ref DataTransfer object.
269
    void postAdapt(bool refined) override
270
271
272
273
    {
      dataTransfer_->postAdapt(*this, refined);
    }

274
  private:
275
    // register this DOFVector and its basis to the DataTransfer
276
277
278
279
280
281
    void attachToGridTransfer()
    {
      GridTransferManager::attach(basis_->gridView().grid(), *this);
      GridTransferManager::attach(basis_->gridView().grid(), *basis_);
    }

282
    // deregister this DOFVector and its basis from the DataTransfer
283
284
285
286
287
288
    void detachFromGridTransfer()
    {
      GridTransferManager::detach(basis_->gridView().grid(), *basis_);
      GridTransferManager::detach(basis_->gridView().grid(), *this);
    }

289
290
  private:
    /// The finite element space / basis associated with the data vector
291
    std::shared_ptr<GlobalBasis> basis_;
292

293
    /// Data backend
294
    Backend backend_;
295
296
297
298

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

299
    /// List of operators associated to nodes, filled in \ref addOperator().
300
    VectorOperators<GlobalBasis,ElementVector> operators_;
301

302
303
    /// Data interpolation when the grid changes, set by default
    /// to \ref DataTransferOperation::INTERPOLATE.
304
    std::shared_ptr<DataTransfer> dataTransfer_;
305
306
307
  };

} // end namespace AMDiS
308
309

#include "DOFVectorBase.inc.hpp"