SystemVector.hpp 10.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
#pragma once

#include <vector>
#include <string>
#include <memory>
#include <tuple>

#include <dune/istl/multitypeblockvector.hh>

10
11
12
13
#include <amdis/Output.hpp>
#include <amdis/common/Loops.hpp>
#include <amdis/common/TupleUtility.hpp>
#include <amdis/common/Utility.hpp>
14

15
#include <amdis/linear_algebra/istl/DOFVector.hpp>
16
17

// for explicit instantiation
18
#include <amdis/ProblemStatTraits.hpp>
19
20
21

namespace AMDiS
{
22

23
24
25
26
27
28
  namespace Impl
  {
    // DOFVectors = std::tuple< DOFVector<FeSpace, ValueType>... >
    template <class DOFVectors>
    struct BuildDOFVectors
    {
29
      template <std::size_t I>
30
      using DOFVectorIdx = std::tuple_element_t<I, DOFVectors>;
31

32
      template <std::size_t... I, class FeSpaces, class MultiVector>
33
34
      static DOFVectors make(Indices<I...>,
                              FeSpaces&& feSpaces,
35
36
37
38
39
40
                              std::vector<std::string> const& names,
                              MultiVector&& multiVector)
      {
        return DOFVectors{DOFVectorIdx<I>(
          std::get<I>(std::forward<FeSpaces>(feSpaces)),
          names[I],
41
          std::get<I>(std::forward<MultiVector>(multiVector))
42
43
44
          )...};
      }
    };
45

46
    template <class DOFVectors, class FeSpaces, class MultiVector>
47
    DOFVectors buildDOFVectors(FeSpaces&& feSpaces,
48
49
50
51
52
53
54
55
56
                                    std::vector<std::string> const& names,
                                    MultiVector&& multiVector)
    {
        return BuildDOFVectors<DOFVectors>::make(
            MakeSeq_t<std::tuple_size<std::decay_t<FeSpaces>>::value>(),
            std::forward<FeSpaces>(feSpaces),
            names,
            std::forward<MultiVector>(multiVector));
    }
57

58
  } // end namespace Impl
59
60


61
  /// \brief Container that repesents multiple data-Vectors of different value types.
62
63
64
  /**
    *  Represents a \ref Dune::MultiTypeBlockVector + a tuple of corresponding
    *  feSpaces. This I'th \ref Dune::BlockVector compbined with the I'th FeSpace
65
    *  builds a \ref DOFVector  and can be return by the \ref operator[].
66
    *
67
68
    *  By default, the ValueTypes are all \ref Dune::FieldVector of 1 double entry.
    **/
69
  template <class FeSpaces,
70
71
72
73
            class ValueTypes = Repeat_t<std::tuple_size<FeSpaces>::value, Dune::FieldVector<double,1>> >
  class SystemVector
  {
    using Self = SystemVector;
74

75
76
  public:
    template <class T> using BlockVectorGenerator = Dune::BlockVector<T, std::allocator<T>>;
77

78
79
    using BaseVectors = MakeTuple_t<BlockVectorGenerator, ValueTypes>;
    using MultiVector = ExpandTuple_t<Dune::MultiTypeBlockVector, BaseVectors>;
80

81
    using DOFVectors  = MakeTuple2_t<DOFVector, FeSpaces, ValueTypes>;
82

83
    static constexpr std::size_t nComponents = std::tuple_size<FeSpaces>::value;
84

85
86
    AMDIS_STATIC_ASSERT( nComponents > 0 );
    AMDIS_STATIC_ASSERT( nComponents == std::tuple_size<ValueTypes>::value );
87

88
89
90
91
92
    /// Constructor that constructs new base-vectors
    SystemVector(FeSpaces const& feSpaces, std::vector<std::string> const& names)
      : feSpaces(feSpaces)
      , names(names)
      , vector{}
93
      , dofvectors(Impl::buildDOFVectors<DOFVectors>(feSpaces, names, vector))
94
95
96
    {
      compress();
    }
97

98
99

    /// Return the number of vector entries
100
    static constexpr std::size_t size()
101
102
103
104
105
106
107
108
109
    {
      return std::tuple_size<FeSpaces>::value;
    }

    /// Return number of elements
    int count() const
    {
      return int(size());
    }
110

111
    /// Return a shared pointer to the i'th underlaying base vector
112
113
    template <std::size_t I>
    auto& getVector(const index_t<I> = {})
114
115
116
117
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(vector);
    }
118

119
    /// Return a shared pointer to the i'th underlaying base vector
120
121
    template <std::size_t I>
    auto const& getVector(const index_t<I> = {}) const
122
123
124
125
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(vector);
    }
126

127
128
129
130
131
    /// Return the underlying multi vector
    MultiVector& getVector()
    {
      return vector;
    }
132

133
134
135
136
    MultiVector const& getVector() const
    {
      return vector;
    }
137

138
    /// Return the I'th finite element space
139
140
    template <std::size_t I = 0>
    auto const& getFeSpace(const index_t<I> = {}) const
141
142
143
144
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(feSpaces);
    }
145

146
    /// Return the name of the i'th DOFVector
147
    std::string getName(std::size_t i) const
148
149
150
    {
        return names[i];
    }
151

152
153
    template <std::size_t I>
    auto& operator[](const index_t<I>)
154
155
156
157
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
158

159
160
    template <std::size_t I>
    auto const& operator[](const index_t<I>) const
161
162
163
164
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
165

166
167
    template <std::size_t I>
    auto& getDOFVector(const index_t<I> = {})
168
169
170
171
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
172

173
174
    template <std::size_t I>
    auto const& getDOFVector(const index_t<I> = {}) const
175
176
177
178
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
179

180
    /// Resize the I'th \ref vector to the sizes of the I'th \ref feSpaces.
181
182
    template <std::size_t I = 0>
    void compress(const index_t<I> = {})
183
184
185
    {
      std::get<I>(dofvectors).compress();
    }
186

187
188
189
    /// Resize the \ref vectors to the sizes of the \ref feSpaces.
    void compress()
    {
190
      forEach(range_<0, size()>, [this](const auto I) {
191
192
193
        std::get<I>(dofvectors).compress();
      });
    }
194

195
196
    void copy(Self const& that)
    {
197
      forEach(range_<0, size()>, [this, &that](const auto I) {
198
199
200
        std::get<I>(dofvectors).copy(that[I]);
      });
    }
201

202
203
204
205
    template <class Scalar>
    std::enable_if_t< std::is_arithmetic<Scalar>::value, Self&>
    operator*=(Scalar s)
    {
206
      forEach(range_<0, size()>, [this, s](const auto I) {
207
208
209
210
        std::get<I>(vector) *= s;
      });
      return *this;
    }
211

212
213
214
215
    template <class Scalar>
    std::enable_if_t< std::is_arithmetic<Scalar>::value, Self&>
    operator=(Scalar s)
    {
216
      forEach(range_<0, size()>, [this, s](const auto I) {
217
218
219
220
        std::get<I>(vector) = s;
      });
      return *this;
    }
221

222
223
224
  private:
    FeSpaces const& feSpaces;	///< a tuple of feSpaces
    std::vector<std::string> names;
225

226
227
228
    MultiVector vector;		///< a tuple of data-vectors
    DOFVectors	dofvectors;	///< a tuple of dofvectors referencing \ref vector
  };
229
230


231
  // specialization for the case of only 1 component.
232

233
234
235
236
  template <class FeSpace, class ValueType>
  class SystemVector<std::tuple<FeSpace>, std::tuple<ValueType>>
  {
    using Self = SystemVector;
237

238
239
240
  public:
    using MultiVector = Dune::BlockVector<ValueType>;
    using DOFVectors  = DOFVector<FeSpace, ValueType>;
241

242
    static constexpr std::size_t nComponent = 1;
243

244
245
246
247
248
249
250
    /// Constructor that constructs new base-vectors
    template <class FeSpaces>
    SystemVector(FeSpaces const& feSpaces, std::vector<std::string> const& names)
      : dofvector(std::get<0>(feSpaces), names.front())
    {
      compress();
    }
251

252
253

    /// Return the number of vector entries
254
    static constexpr std::size_t size()
255
256
257
258
259
260
261
262
263
    {
      return 1;
    }

    /// Return number of elements
    int count() const
    {
      return 1;
    }
264

265
    /// Return a shared pointer to the i'th underlaying base vector
266
267
    template <std::size_t I = 0>
    MultiVector& getVector(const index_t<I> = {})
268
269
270
271
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector.getVector();
    }
272

273
    /// Return a shared pointer to the i'th underlaying base vector
274
275
    template <std::size_t I = 0>
    MultiVector const& getVector(const index_t<I> = {}) const
276
277
278
279
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector.getVector();
    }
280

281
282
283
284
285
    /// Return the underlying multi vector
    MultiVector& getVector()
    {
      return dofvector.getVector();
    }
286

287
288
289
290
    MultiVector const& getVector() const
    {
      return dofvector.getVector();
    }
291

292
    /// Return the I'th finite element space
293
294
    template <std::size_t I = 0>
    auto const& getFeSpace(const index_t<I> = {}) const
295
296
297
298
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector.getFeSpace();
    }
299

300
    /// Return the name of the i'th DOFVector
301
    std::string getName(std::size_t i = 0) const
302
    {
303
      test_exit(i == 0, "Index out of range [0,1)");
304
305
      return dofvector.getName();
    }
306

307
308
    template <std::size_t I>
    auto& operator[](const index_t<I>)
309
310
311
312
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector;
    }
313

314
315
    template <std::size_t I>
    auto const& operator[](const index_t<I>) const
316
317
318
319
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector;
    }
320

321
322
    template <std::size_t I>
    auto& getDOFVector(const index_t<I> = {})
323
324
325
326
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector;
    }
327

328
329
    template <std::size_t I>
    auto const& getDOFVector(const index_t<I> = {}) const
330
331
332
333
    {
      static_assert(I == 0, "Index out of range [0,1)");
      return dofvector;
    }
334

335
    /// Resize the I'th \ref vector to the sizes of the I'th \ref feSpaces.
336
337
    template <std::size_t I = 0>
    void compress(const index_t<I> = {})
338
339
340
341
    {
      static_assert(I == 0, "Index out of range [0,1)");
      dofvector.compress();
    }
342

343
344
345
346
347
    /// Resize the \ref vectors to the sizes of the \ref feSpaces.
    void compress()
    {
      dofvector.compress();
    }
348

349
350
    void copy(Self const& that)
    {
351
      dofvector.copy(that[_0]);
352
    }
353

354
355
356
357
358
359
360
    template <class Scalar>
    std::enable_if_t< std::is_arithmetic<Scalar>::value, Self&>
    operator*=(Scalar s)
    {
      dofvector.getVector() *= s;
      return *this;
    }
361

362
363
364
365
366
367
368
    template <class Scalar>
    std::enable_if_t< std::is_arithmetic<Scalar>::value, Self&>
    operator=(Scalar s)
    {
      dofvector.getVector() = s;
      return *this;
    }
369

370
371
372
  private:
    DOFVectors      dofvector;  ///< a tuple of sofvectors referencing \ref vector
  };
373
374
375
376




377
378
#ifndef AMDIS_NO_EXTERN_SYSTEMVECTOR
    // explicit instantiation in SystemVector.cpp
379
380
    extern template class SystemVector<typename TestTraits<2,1>::FeSpaces>;
    extern template class SystemVector<typename TestTraits<2,1,2>::FeSpaces>;
381
382
383
#endif

} // end namespace AMDiS