BlockMTLVector.hpp 5.24 KB
Newer Older
1
2
#pragma once

3
4
5
#include <array>
#include <type_traits>

6
7
#include <boost/numeric/mtl/utility/irange.hpp>

8
9
10
#include <amdis/common/Mpl.hpp>
#include <amdis/linear_algebra/LinearAlgebraBase.hpp>
#include <amdis/linear_algebra/mtl/MTLDenseVector.hpp>
11

12
13
14
namespace AMDiS
{
  /// A simple block-vector class
15
  template <class MTLVector, std::size_t N>
16
  class BlockMTLVector
17
      : public std::array<MTLVector, N>
18
19
20
21
  {
  public:
    /// The type of the blocks
    using BaseVector = MTLVector;
22

23
24
    /// The index/size - type
    using size_type  = typename MTLVector::size_type;
25

26
27
28
    /// The type of the elements of the MTLVector
    using value_type = typename MTLVector::value_type;
  };
29
30


31
32
  namespace Impl
  {
33
    /// Specialization of Impl::BaseVector from \file LinearAlgebraBase.hpp
34
    template <class MTLVector, std::size_t N>
35
36
37
38
39
    struct BaseVector<BlockMTLVector<MTLVector, N>>
    {
      using type = MTLVector;
    };
  }
40

41
42

  /// Return the number of overall rows of a BlockMTLVector
43
44
  template <class MTLVector, std::size_t N>
  inline std::size_t num_rows(BlockMTLVector<MTLVector, N> const& vec)
45
  {
46
47
    std::size_t nRows = 0;
    forEach(range_<0, N>, [&](const auto _i) {
48
49
50
51
52
53
      nRows += num_rows(std::get<_i>(vec));
    });
    return nRows;
  }

  /// Return the number of overall columns of a BlockMTLVector
54
55
  template <class MTLVector, std::size_t N>
  inline std::size_t num_cols(BlockMTLVector<MTLVector, N> const& vec)
56
57
58
59
60
  {
    return 1;
  }

  /// Return the size, i.e. rows*columns of a BlockMTLVector
61
62
  template <class MTLVector, std::size_t N>
  inline std::size_t size(BlockMTLVector<MTLVector, N> const& vec)
63
64
65
66
67
  {
    return num_rows(vec);
  }

  /// Nullify a BlockMTLVector, i.e. nullify each block.
68
  template <class MTLVector, std::size_t N>
69
  inline void set_to_zero(BlockMTLVector<MTLVector, N>& vec)
70
  {
71
    forEach(range_<0, N>, [&](const auto _i) {
72
      set_to_zero(std::get<_i>(vec));
73
74
    });
  }
75
76


77
  /// A wrapper, that creates a contiguos vector corresponding to a block-vector
78
  /// and copy the value on construction and eventually back on destruction, if
79
  /// required.
80
81
  template <class BlockVector, class Vector, class NonConstBlockVector>
  class BlockVectorWrapper;
82

83
  // specialization for BlockMTLVector
84
  template <class BlockVector, class Vector, class MTLVector, std::size_t N>
85
86
87
  class BlockVectorWrapper<BlockVector, Vector, BlockMTLVector<MTLVector, N>>
  {
    static_assert( std::is_same< std::remove_const_t<BlockVector>, BlockMTLVector<MTLVector, N> >::value,
88
                   "This specialization is for BlockMTLVectors only.");
89

90
  public:
91
92
    explicit BlockVectorWrapper(BlockVector& blockVector,
                                bool copyBack = !std::is_const<BlockVector>::value)
93
      : blockVector(blockVector)
94
      , vector_(num_rows(blockVector))
95
96
97
98
      , copyBack(copyBack)
    {
      assignTo();
    }
99

100
101
102
    ~BlockVectorWrapper()
    {
      if (copyBack)
103
        assignFrom(bool_<!std::is_const<BlockVector>::value>);
104
    }
105

106
107
    /// Return a reference to the block-vector
    BlockVector const&  getBlockVector() const  { return blockVector; }
108

109
    /// Return a reference to the contiguose-vector
110
111
    Vector&       vector()       { return vector_; }
    Vector const& vector() const { return vector_; }
112
113
114
115
116

  private:
    /// copy from block-vector to vector
    void assignTo()
    {
117
118
119
      std::size_t start = 0;
      for (std::size_t r = 0; r < N; ++r) {
        std::size_t finish = start + num_rows(blockVector[r]);
120
        mtl::irange range(start, finish);
121

122
        vector_[range] = blockVector[r];
123
        start = finish;
124
125
      }
    }
126

127
    /// do not copy vector to block-vector since this is const
128
    template <bool Copy>
129
    std::enable_if_t<!Copy> assignFrom(bool_t<Copy>) { /* Do nothing */ }
130

131
    /// copy from vector to block-vector
132
    template <bool Copy>
133
    std::enable_if_t<Copy> assignFrom(bool_t<Copy>)
134
    {
135
136
137
      std::size_t start = 0;
      for (std::size_t r = 0; r < N; ++r) {
        std::size_t finish = start + num_rows(blockVector[r]);
138
        mtl::irange range(start, finish);
139

140
        blockVector[r] = vector_[range];
141
        start = finish;
142
143
      }
    }
144

145
146
  private:
    BlockVector& blockVector;
147
    Vector vector_;
148

149
    /// Copy data back to block-vector on destruction
150
151
    bool copyBack;
  };
152
153


154
155
156
157
  // Specialization for non-block-vectors
  template <class BlockVector, class Vector>
  class BlockVectorWrapper<BlockVector, Vector, Vector>
  {
158
    static_assert( std::is_same< std::remove_const_t<BlockVector>, Vector >::value,
159
160
                   "This specialization is for contiguose vectors only.");
  public:
161
    explicit BlockVectorWrapper(BlockVector& vector, bool = false)
162
      : vector_(vector)
163
    {}
164

165
    /// Return a reference to the vector
166
167
168
    BlockVector const& getBlockVector() const { return vector_; }
    BlockVector&       vector()            { return vector_; }
    BlockVector const& vector()      const { return vector_; }
169

170
  private:
171
    BlockVector& vector_;
172
  };
173

174
175
176
  template <class BlockVector, class Vector>
  using BlockVectorWrapper_t
    = BlockVectorWrapper<BlockVector, Vector, std::remove_const_t<BlockVector>>;
177

178

179
  template <class BlockVector, class Vector = MTLDenseVector<typename BlockVector::value_type>>
180
  auto blockWrapper(BlockVector& bvec)
181
  {
182
    return BlockVectorWrapper_t<BlockVector, Vector>{bvec};
183
  }
184

185
186

} // end namespace AMDiS