SystemMatrix.hpp 6.99 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
#pragma once

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

#include <boost/numeric/mtl/matrix/dense2D.hpp>
#include <boost/numeric/mtl/matrix/compressed2D.hpp>

11
12
13
14
15
#include <amdis/Output.hpp>
#include <amdis/common/TupleUtility.hpp>
#include <amdis/common/Utility.hpp>
#include <amdis/linear_algebra/mtl/BlockMTLMatrix.hpp>
#include <amdis/linear_algebra/mtl/DOFMatrix.hpp>
16
17

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

namespace AMDiS
{
22
  /// \cond HIDDEN_SYMBOLS
23
24
25
26
27
28
  namespace Impl
  {
    // DOFMatrices = std::tuple< std::tuple< DOFMatrix<RowFeSpace, ColFeSpace, ValueType>... >... >
    template <class DOFMatrices>
    struct BuildDOFMatrices
    {
29
      template <std::size_t R>
30
      using DOFMatrixRow = std::tuple_element_t<R, DOFMatrices>;
31

32
      template <std::size_t R, std::size_t C>
33
      using DOFMatrixRowCol = std::tuple_element_t<C, DOFMatrixRow<R>>;
34

35
      // add arg to repeated constructor argument list
36
      template <std::size_t... R, class RowFeSpaces, class ColFeSpaces, class MultiMatrix>
37
38
      static DOFMatrices make(Indices<R...>,
                              RowFeSpaces&& rowFeSpaces,
39
40
41
42
                              ColFeSpaces&& colFeSpace,
                              MultiMatrix&& multiMatrix)
      {
        return DOFMatrices{make_row(
43
          index_<R>,
44
45
46
          MakeSeq_t<std::tuple_size<std::decay_t<ColFeSpaces>>::value>(),
          std::get<R>(std::forward<RowFeSpaces>(rowFeSpaces)),
          std::forward<ColFeSpaces>(colFeSpace),
47
          std::forward<MultiMatrix>(multiMatrix)
48
49
          )...};
      }
50

51
52
      template <std::size_t R, std::size_t... C, class RowFeSpace, class ColFeSpaces, class MultiMatrix>
      static DOFMatrixRow<R> make_row(index_t<R>,
53
54
                                      Indices<C...>,
                                      RowFeSpace&& rowFeSpace,
55
56
57
58
                                      ColFeSpaces&& colFeSpace,
                                      MultiMatrix&& multiMatrix)
      {
        return DOFMatrixRow<R>{DOFMatrixRowCol<R,C>(
59
60
          std::forward<RowFeSpace>(rowFeSpace),
          std::get<C>(std::forward<ColFeSpaces>(colFeSpace)),
61
          "matrix[" + std::to_string(R) + "][" + std::to_string(C) + "]",
62
          multiMatrix(index_<R>, index_<C>)
63
64
65
          )...};
      }
    };
66

67
    // construction method to construct a tuple of tuples of DOFMatrices
68
    template <class DOFMatrices, class RowFeSpaces, class ColFeSpaces, class MultiMatrix>
69
    DOFMatrices buildDOFMatrices(RowFeSpaces&& rowFeSpaces,
70
71
72
73
74
75
76
77
78
                                  ColFeSpaces&& colFeSpace,
                                  MultiMatrix&& multiMatrix)
    {
        return BuildDOFMatrices<DOFMatrices>::make(
            MakeSeq_t<std::tuple_size<std::decay_t<RowFeSpaces>>::value>(), // traverse rows first
            std::forward<RowFeSpaces>(rowFeSpaces),
            std::forward<ColFeSpaces>(colFeSpace),
            std::forward<MultiMatrix>(multiMatrix));
    }
79

80
  } // end namespace Impl
81
  /// \endcond
82
83


84
  /// \brief Container that repesents multiple data-matrices.
85
86
87
  /**
    *  Represents a fixed-size matrix of \ref mtl::compressed2D + a tuple of corresponding
    *  feSpaces. This (R,C)'th matrix combined with the (R,C)'th FeSpace
88
    *  builds a \ref DOFMatrix and can be return by the \ref operator().
89
90
91
92
93
94
95
96
97
98
99
    **/
  template <class FeSpaces, class ValueType = double>
  class SystemMatrix
  {
    template <class RowFeSpace>
    struct MultiMatrixRowGenerator
    {
      template <class ColFeSpace>
      using DOFMatrixGenerator = DOFMatrix<RowFeSpace, ColFeSpace, ValueType>;
      using DOFMatrices  = MakeTuple_t<DOFMatrixGenerator, FeSpaces>;
    };
100

101
102
    template <class RowFeSpace>
    using DOFMatrixGenerator = typename MultiMatrixRowGenerator<RowFeSpace>::DOFMatrices;
103

104
  public:
105
    /// The number of blocks per row/column
106
    static constexpr std::size_t nComponent = std::tuple_size<FeSpaces>::value;
107
    AMDIS_STATIC_ASSERT( nComponent > 0 );
108

109
110
    /// The type of the matrix in each block
    using BaseMatrix = mtl::compressed2D<ValueType>;
111

112
113
    /// The type of the matrix of DOFMatrices
    using DOFMatrices = MakeTuple_t<DOFMatrixGenerator, FeSpaces>;
114

115
116
    /// The type of the matrix of base-matrices
    using MultiMatrix = BlockMTLMatrix<BaseMatrix, nComponent, nComponent>;
117
118


119
    /// Constructor that constructs new base-matrices
120
    explicit SystemMatrix(FeSpaces const& feSpaces)
121
      : feSpaces(feSpaces)
122
      , matrix()
123
      , dofmatrices(Impl::buildDOFMatrices<DOFMatrices>(feSpaces, feSpaces, matrix))
124
    {}
125

126

127
    /// Return the number of blocks per row
128
    static constexpr std::size_t N()
129
130
131
    {
      return std::tuple_size<FeSpaces>::value;
    }
132

133
    /// Return the number of blocks per column
134
    static constexpr std::size_t M()
135
136
137
    {
      return std::tuple_size<FeSpaces>::value;
    }
138

139
    /// Return the (R,C)'th underlaying base matrix
140
141
    template <std::size_t R, std::size_t C>
    auto& getMatrix(const index_t<R> _r = {}, const index_t<C> _c = {})
142
143
    {
      static_assert(R < N() && C < M(), "Indices out of range [0,N)x[0,M)");
144
      return matrix(_r, _c);
145
    }
146

147
    /// Return the (R,C)'th underlaying base matrix
148
149
    template <std::size_t R, std::size_t C>
    auto const& getMatrix(const index_t<R> _r = {}, const index_t<C> _c = {}) const
150
151
    {
      static_assert(R < N() && C < M(), "Indices out of range [0,N)x[0,M)");
152
      return matrix(_r, _c);
153
    }
154

155
156
157
    /// Return the underlying multi matrix
    MultiMatrix&        getMatrix()       { return matrix; }
    MultiMatrix const&  getMatrix() const { return matrix; }
158

159
    /// Return the I'th row finite element space
160
161
    template <std::size_t I = 0>
    auto& getRowFeSpace(const index_t<I> = {}) const
162
163
164
165
    {
      static_assert(I < N(), "Index out of range [0,N)");
      return std::get<I>(feSpaces);
    }
166

167
    /// Return the I'th column finite element space
168
169
    template <std::size_t I = 0>
    auto const& getColFeSpace(const index_t<I> = {}) const
170
171
172
173
    {
      static_assert(I < M(), "Index out of range [0,M)");
      return std::get<I>(feSpaces);
    }
174

175
    /// Return the (R,C)'th DOFMatrix
176
177
    template <std::size_t R = 0, std::size_t C = 0>
    auto& operator()(const index_t<R> = {}, const index_t<C> = {})
178
179
180
181
    {
      static_assert(R < N() && C < M(), "Indices out of range [0,N)x[0,M)");
      return std::get<C>(std::get<R>(dofmatrices));
    }
182

183
    /// Return the (R,C)'th DOFMatrix
184
185
    template <std::size_t R = 0, std::size_t C = 0>
    auto const& operator()(const index_t<R> = {}, const index_t<C> = {}) const
186
187
188
189
    {
      static_assert(R < N() && C < M(), "Indices out of range [0,N)x[0,M)");
      return std::get<C>(std::get<R>(dofmatrices));
    }
190

191
  private:
192
193
    /// a tuple of feSpaces for rows and columns of the matrix
    FeSpaces const& feSpaces;
194

195
196
    /// a tuple of data-matrices
    MultiMatrix matrix;
197

198
199
    /// a tuple of DOFMatrices
    DOFMatrices dofmatrices;
200
201
  };

202
203
204
205
// #ifndef AMDIS_NO_EXTERN_SYSTEMMATRIX
//     // explicit instantiation in SystemMatrix.cpp
//     extern template class SystemMatrix<typename TestTraits<2,1,2>::FeSpaces>;
// #endif
206

207
} // end namespace AMDiS