DOFVectorBase.hpp 6.43 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
14
15
#include <amdis/linearalgebra/DOFVectorInterface.hpp>
#include <amdis/typetree/MultiIndex.hpp>
#include <amdis/typetree/TreePath.hpp>
16
17
18
19

namespace AMDiS
{
  /// The basic container that stores a base vector and a corresponding basis
20
  template <class BasisType, class Backend>
21
22
23
24
25
26
  class DOFVectorBase
      : public DOFVectorInterface
  {
    using Self = DOFVectorBase;

  public:
27
    /// The type of the functionspace basis associated to this vector
28
    using Basis = BasisType;
29
30
31
32
    using LocalView = typename Basis::LocalView;

    using Element = typename LocalView::Element;
    using Geometry = typename Element::Geometry;
33
34
35
36

    /// The index/size - type
    using size_type  = typename BasisType::size_type;

37
38
39
    /// The type of the elements of the DOFVector
    using value_type = typename Backend::value_type;

40
    /// The type of the data vector used in the backend
41
    using BaseVector = typename Backend::BaseVector;
42
    using ElementVector = Dune::DynamicVector<double>;
43

44
45
46
47
48
49
    /// 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>;

50
  public:
51
    /// Constructor. Constructs new BaseVector.
52
    DOFVectorBase(BasisType const& basis, DataTransferOperation op = NO_OPERATION)
53
      : basis_(&basis)
54
      , dataTransfer_(DataTransferFactory::create(op, basis))
55
56
    {
      compress();
57
      GridTransferManager::attach(*this);
58
      operators_.init(basis);
59
    }
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    /// Copy constructor
    DOFVectorBase(Self const& that)
      : basis_(that.basis_)
      , backend_(that.backend_)
      , elementVector_(that.elementVector_)
      , operators_(that.operators_)
      , dataTransfer_(that.dataTransfer_)
    {
      GridTransferManager::attach(*this);
    }

    /// 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_))
    {
      GridTransferManager::attach(*this);
    }

    /// Destructor
84
    ~DOFVectorBase() override
85
86
87
    {
      GridTransferManager::detach(*this);
    }
88
89
90
91

    /// Copy assignment operator
    Self& operator=(Self const& that)
    {
92
      GridTransferManager::detach(*this);
93
      basis_ = that.basis_;
94
95
      backend_.resize(that.size());
      backend_ = that.backend_;
96
97
      dataTransfer_ = that.dataTransfer_;
      GridTransferManager::attach(*this);
98
99
100
101
102
103
104
      return *this;
    }

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

    /// Sets each DOFVector to the scalar \p value.
105
106
107
    template <class Number,
      std::enable_if_t<Dune::IsNumber<Number>::value, int> = 0>
    Self& operator=(Number value)
108
    {
109
      backend_.set(value);
110
111
112
      return *this;
    }

113
    /// Return the basis \ref basis_ associated to the vector
114
115
    Basis const& basis() const
    {
116
117
118
119
120
121
122
123
124
125
126
127
128
      return *basis_;
    }

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

    /// Return the data-vector
    BaseVector& vector()
    {
      return backend_.vector();
129
130
131
132
133
134
135
136
    }

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

137
138
139
140
141
    void resize(Dune::Functions::SizeInfo<Basis> const& s)
    {
      backend_.resize(size_type(s));
    }

142
    /// Resize the \ref vector to the size of the \ref basis and set to zero
143
    void compress() override
144
    {
145
      if (size_type(backend_.size()) != size()) {
146
        backend_.resize(size());
147
        backend_.set(0);
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
      }
    }

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

167
    void init(bool asmVector);
168

169
    void finish(bool asmVector);
170

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

174
175
176
    /// Associate a local operator with this DOFVector
    template <class ContextTag, class Operator, class TreePath = RootTreePath>
    void addOperator(ContextTag contextTag, Operator const& preOp, TreePath path = {});
177

178
179
    /// Assemble the vector operators on the bound element.
    void assemble(LocalView const& localView);
180

181
182
    /// Assemble all vector operators
    void assemble();
183

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
    /// Return the associated DataTransfer object
    DataTransfer const& dataTransfer() const
    {
      return *dataTransfer_;
    }

    /// Return the associated DataTransfer object
    DataTransfer& dataTransfer()
    {
      return *dataTransfer_;
    }

    /// 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
209
    void preAdapt(bool mightCoarsen) override
210
211
212
213
214
    {
      dataTransfer_->preAdapt(*this, mightCoarsen);
    }

    /// Implementation of \ref DOFVectorInterface::postAdapt
215
    void postAdapt(bool refined) override
216
217
218
219
    {
      dataTransfer_->postAdapt(*this, refined);
    }

220
221
222
  private:
    /// The finite element space / basis associated with the data vector
    Basis const* basis_;
223

224
    /// Data backend
225
    Backend backend_;
226
227
228
229
230
231

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

    /// List of operators associated to nodes
    VectorOperators<Basis> operators_;
232
233
234

    /// Data interpolation when the grid changes
    std::shared_ptr<DataTransfer> dataTransfer_;
235
236
237
  };

} // end namespace AMDiS
238
239

#include "DOFVectorBase.inc.hpp"