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

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

#include <dune/amdis/Basic.hpp>
#include <dune/amdis/Log.hpp>
#include <dune/amdis/Loops.hpp>

12
#include <dune/amdis/linear_algebra/mtl/BlockMTLVector.hpp>
13
14
15
16
17
18
19
#include <dune/amdis/linear_algebra/mtl/DOFVector.hpp>

// for explicit instantiation
#include <dune/amdis/ProblemStatBase.hpp>

namespace AMDiS
{
20
  /// \cond HIDDEN_SYMBOLS
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  namespace Impl
  {
    // DOFVectors = std::tuple< DOFVector<FeSpace, ValueType>... >
    template <class DOFVectors>
    struct BuildDOFVectors
    {
      template <size_t I>
      using DOFVectorIdx = std::tuple_element_t<I, DOFVectors>;
      
      template <size_t... I, class FeSpaces, class MultiVector>
      static DOFVectors make(Seq<I...>, 
                              FeSpaces&& feSpaces, 
                              std::vector<std::string> const& names,
                              MultiVector&& multiVector)
      {
        return DOFVectors{DOFVectorIdx<I>(
          std::get<I>(std::forward<FeSpaces>(feSpaces)),
          names[I],
          multiVector[I] 
          )...};
      }
    };
        
44
    // construction method to construct a tuple of DOFVectors
45
46
47
48
49
    template <class DOFVectors, class FeSpaces, class MultiVector>
    DOFVectors build_dofvectors(FeSpaces&& feSpaces, 
                                    std::vector<std::string> const& names,
                                    MultiVector&& multiVector)
    {
50
51
52
53
54
      return BuildDOFVectors<DOFVectors>::make(
          MakeSeq_t<std::tuple_size<std::decay_t<FeSpaces>>::value>(),
          std::forward<FeSpaces>(feSpaces),
          names,
          std::forward<MultiVector>(multiVector));
55
56
57
    }
    
  } // end namespace Impl
58
  /// \endcond
59
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 
    *  builds a \ref DOFVector  and can be return by the \ref operator().
66
67
68
69
70
71
72
73
74
75
    **/
  template <class FeSpaces, class ValueType = double>
  class SystemVector
  {
    using Self = SystemVector;
    
    template <class FeSpace>
    using DOFVectorGenerator = DOFVector<FeSpace, ValueType>;
    
  public:
76
    /// The number of blocks
77
78
79
    static constexpr size_t nComponents = std::tuple_size<FeSpaces>::value;
    AMDIS_STATIC_ASSERT( nComponents > 0 );
    
80
    /// The type of the block-vector
81
82
    using BaseVector = typename DOFVectorGenerator<std::tuple_element_t<0, FeSpaces>>::BaseVector;
    using MultiVector = BlockMTLVector<BaseVector, nComponents>;
83
    
84
    /// The type of the vector of DOFVectors
85
86
87
88
89
90
91
92
93
94
95
96
97
    using DOFVectors  = MakeTuple_t<DOFVectorGenerator, FeSpaces>;
    
    /// Constructor that constructs new base-vectors
    SystemVector(FeSpaces const& feSpaces, std::vector<std::string> const& names)
      : feSpaces(feSpaces)
      , names(names)
      , vector{}
      , dofvectors(Impl::build_dofvectors<DOFVectors>(feSpaces, names, vector))
    {
      compress();
    }
    

98
    /// Return the number of blocks
99
100
101
102
103
    static constexpr size_t size()
    {
      return std::tuple_size<FeSpaces>::value;
    }

104
    /// Return the number of blocks
105
106
107
108
109
    int count() const
    {
      return int(size());
    }
    
110
    /// Return a shared pointer to the I'th underlaying base vector
111
    template <size_t I>
112
    auto& getVector(const index_<I> = {})
113
114
115
116
117
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return vector[I];
    }
    
118
    /// Return a shared pointer to the I'th underlaying base vector
119
    template <size_t I>
120
    auto const& getVector(const index_<I> = {}) const
121
122
123
124
125
126
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return vector[I];
    }
    
    /// Return the underlying multi vector
127
128
    MultiVector&        getVector()       { return vector; }
    MultiVector const&  getVector() const { return vector; }
129
130
131
    
    /// Return the I'th finite element space
    template <size_t I = 0>
132
    auto const& getFeSpace(const index_<I> = {}) const
133
134
135
136
137
138
139
140
141
142
143
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(feSpaces);
    }
    
    /// Return the name of the i'th DOFVector
    std::string getName(size_t i) const
    {
        return names[i];
    }
    
144
    /// Return the I'th DOFVector
145
146
147
148
149
150
151
    template <size_t I>
    auto& operator[](const index_<I>)
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
    
152
    /// Return the I'th DOFVector
153
154
155
156
157
158
159
    template <size_t I>
    auto const& operator[](const index_<I>) const
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
    
160
    /// Return the I'th DOFVector
161
    template <size_t I>
162
    auto& getDOFVector(const index_<I> = {})
163
164
165
166
167
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
    
168
    /// Return the I'th DOFVector
169
    template <size_t I>
170
    auto const& getDOFVector(const index_<I> = {}) const
171
172
173
174
175
176
177
    {
      static_assert(I < size(), "Index out of range [0,SIZE)" );
      return std::get<I>(dofvectors);
    }
    
    /// Resize the I'th \ref vector to the sizes of the I'th \ref feSpaces.
    template <size_t I = 0>
178
    void compress(const index_<I> = {})
179
180
181
182
183
184
185
186
187
188
189
190
    {
      std::get<I>(dofvectors).compress();
    }
    
    /// Resize the \ref vectors to the sizes of the \ref feSpaces.
    void compress()
    {
      For<0, size()>::loop([this](const auto I) {
        std::get<I>(dofvectors).compress();
      });
    }
    
191
    /// Copy the Systemvector \p that element-wise
192
193
194
195
196
197
198
    void copy(Self const& that)
    {
      For<0, size()>::loop([this, &that](const auto I) {
        std::get<I>(dofvectors).copy(that[I]);
      });
    }
    
199
    /// Scale each DOFVector by the factor \p s.
200
201
202
203
204
205
206
207
208
209
    template <class Scalar>
    std::enable_if_t< std::is_arithmetic<Scalar>::value, Self&>
    operator*=(Scalar s)
    {
      For<0, size()>::loop([this, s](const auto I) {
        vector[I] *= s;
      });
      return *this;
    }
    
210
    /// Sets each DOFVector to the scalar \p s.
211
212
213
214
215
216
217
218
219
220
221
    template <class Scalar>
    std::enable_if_t< std::is_arithmetic<Scalar>::value, Self&>
    operator=(Scalar s)
    {
      For<0, size()>::loop([this, s](const auto I) {
        vector[I] = s;
      });
      return *this;
    }
      
  private:
222
223
224
225
    /// a tuple of feSpaces
    FeSpaces const& feSpaces;	
    
    /// The names of the DOFVectors
226
227
    std::vector<std::string> names;
    
228
229
230
231
232
    /// a tuple of base vectors, i.e. mtl::dense_vectors
    MultiVector vector;
    
    /// a tuple of dofvectors referencing \ref vector
    DOFVectors dofvectors;
233
  };
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  
  
  /// Construct a systemvector from given feSpace-tuple and names-vector
  template <class FeSpacesType, class ValueType = double>
  SystemVector<FeSpacesType, ValueType>
  make_systemvector(FeSpacesType const& feSpaces, std::vector<std::string> names)
  {
    return {feSpaces, names};
  }
  
  /// 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>
  make_systemvector(FeSpaces const& feSpaces, std::string base_name)
  {
    std::vector<std::string> names;
    for (size_t i = 0; i < std::tuple_size<FeSpaces>::value; ++i)
      names.push_back(base_name + "_" + std::to_string(i));
    return {feSpaces, names};
  }
255
256
257
258
259
260
261
262
    
  
#ifndef AMDIS_NO_EXTERN_SYSTEMVECTOR
    // explicit instantiation in SystemVector.cpp
    extern template class SystemVector<typename ProblemStatTraits<2,2,1,2>::FeSpaces>;
#endif

} // end namespace AMDiS