SystemVector.hpp 7.63 KB
Newer Older
1
2
#pragma once

3
#include <algorithm>
4
#include <memory>
5
#include <string>
6
#include <tuple>
7
#include <vector>
8

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

15
16
#include <amdis/linear_algebra/mtl/BlockMTLVector.hpp>
#include <amdis/linear_algebra/mtl/DOFVector.hpp>
17
18

// for explicit instantiation
19
#include <amdis/ProblemStatTraits.hpp>
20
21
22
23
24
25
26
27
28

namespace AMDiS
{
  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
          multiVector[I]
42
43
44
          )...};
      }
    };
45

46
    // construction method to construct a tuple of DOFVectors
47
    template <class DOFVectors, class FeSpaces, class MultiVector>
48
    DOFVectors buildDOFVectors(FeSpaces&& feSpaces,
49
50
51
                                    std::vector<std::string> const& names,
                                    MultiVector&& multiVector)
    {
52
53
54
55
56
      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

59
  } // end namespace Impl
60
61


62
  /// \brief Container that repesents multiple data-Vectors of different value types.
63
64
65
  /**
    *  Represents a std::array of \ref mtl::dense_vector + a tuple of corresponding
    *  feSpaces. This I'th matrix combined with the I'th FeSpace
66
    *  builds a \ref DOFVector  and can be return by the \ref operator().
67
68
69
70
71
    **/
  template <class FeSpaces, class ValueType = double>
  class SystemVector
  {
    using Self = SystemVector;
72

73
74
    template <class FeSpace>
    using DOFVectorGenerator = DOFVector<FeSpace, ValueType>;
75

76
  public:
77
    /// The number of blocks
78
    static constexpr std::size_t nComponents = std::tuple_size<FeSpaces>::value;
79
    AMDIS_STATIC_ASSERT( nComponents > 0 );
80

81
    /// The type of the block-vector
82
83
    using BaseVector = typename DOFVectorGenerator<std::tuple_element_t<0, FeSpaces>>::BaseVector;
    using MultiVector = BlockMTLVector<BaseVector, nComponents>;
84

85
    /// The type of the vector of DOFVectors
86
    using DOFVectors  = MakeTuple_t<DOFVectorGenerator, FeSpaces>;
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 blocks
100
    static constexpr std::size_t size()
101
102
103
104
    {
      return std::tuple_size<FeSpaces>::value;
    }

105
    /// Return the number of blocks
106
107
108
109
    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 vector[I];
    }
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 vector[I];
    }
126

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

131
    /// Return the I'th finite element space
132
133
    template <std::size_t I = 0>
    auto const& getFeSpace(const index_t<I> = {}) const
134
135
136
137
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(feSpaces);
    }
138

139
    /// Return the name of the i'th DOFVector
140
    std::string getName(std::size_t i) const
141
142
143
    {
        return names[i];
    }
144

145
    /// Return the I'th DOFVector
146
147
    template <std::size_t I>
    auto& operator[](const index_t<I>)
148
149
150
151
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
152

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

161
    /// Return the I'th DOFVector
162
163
    template <std::size_t I>
    auto& getDOFVector(const index_t<I> = {})
164
165
166
167
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
168

169
    /// Return the I'th DOFVector
170
171
    template <std::size_t I>
    auto const& getDOFVector(const index_t<I> = {}) const
172
173
174
175
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
176

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

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

192
    /// Copy the Systemvector \p that element-wise
193
194
    void copy(Self const& that)
    {
195
      forEach(range_<0, size()>, [this, &that](const auto I) {
196
197
198
        std::get<I>(dofvectors).copy(that[I]);
      });
    }
199

200
    /// Scale each DOFVector by the factor \p s.
201
    template <class Scalar>
202
    std::enable_if_t< Concepts::Arithmetic<Scalar>, Self&>
203
204
    operator*=(Scalar s)
    {
205
      forEach(range_<0, size()>, [this, s](const auto I) {
206
207
208
209
        vector[I] *= s;
      });
      return *this;
    }
210

211
    /// Sets each DOFVector to the scalar \p s.
212
    template <class Scalar>
213
    std::enable_if_t< Concepts::Arithmetic<Scalar>, Self&>
214
215
    operator=(Scalar s)
    {
216
      forEach(range_<0, size()>, [this, s](const auto I) {
217
218
219
220
        vector[I] = s;
      });
      return *this;
    }
221

222
  private:
223
    /// a tuple of feSpaces
224
225
    FeSpaces const& feSpaces;

226
    /// The names of the DOFVectors
227
    std::vector<std::string> names;
228

229
230
    /// a tuple of base vectors, i.e. mtl::dense_vectors
    MultiVector vector;
231

232
233
    /// a tuple of dofvectors referencing \ref vector
    DOFVectors dofvectors;
234
  };
235
236


237
238
239
  /// Construct a systemvector from given feSpace-tuple and names-vector
  template <class FeSpacesType, class ValueType = double>
  SystemVector<FeSpacesType, ValueType>
240
  makeSystemVector(FeSpacesType const& feSpaces, std::vector<std::string> names)
241
242
243
  {
    return {feSpaces, names};
  }
244

245
246
247
248
  /// Construct a systemvector from given feSpace-tuple. Create vector of names
  /// from base_name, i.e. {base_name_0, base_name_1, ...}
  template <class FeSpaces, class ValueType = double>
  SystemVector<FeSpaces, ValueType>
249
  makeSystemVector(FeSpaces const& feSpaces, std::string base_name)
250
251
  {
    std::vector<std::string> names;
252
    for (std::size_t i = 0; i < std::tuple_size<FeSpaces>::value; ++i)
253
254
255
      names.push_back(base_name + "_" + std::to_string(i));
    return {feSpaces, names};
  }
256
257


258
259
260
261
// #ifndef AMDIS_NO_EXTERN_SYSTEMVECTOR
//     // explicit instantiation in SystemVector.cpp
//     extern template class SystemVector<typename TestTraits<2,1,2>::FeSpaces>;
// #endif
262
263

} // end namespace AMDiS