DOFMatrix.hpp 3.74 KB
Newer Older
1 2
#pragma once

3
#include <list>
4
#include <memory>
5 6
#include <string>
#include <vector>
7 8 9 10 11 12

#include <boost/numeric/mtl/matrix/compressed2D.hpp>
#include <boost/numeric/mtl/matrix/inserter.hpp>
#include <boost/numeric/mtl/utility/property_map.hpp>
#include <boost/numeric/mtl/utility/range_wrapper.hpp>

13
#include <amdis/Output.hpp>
14 15
#include <amdis/linearalgebra/Common.hpp>
#include <amdis/linearalgebra/DOFMatrixBase.hpp>
16 17 18

namespace AMDiS
{
19
  /// \brief The basic container that stores a base matrix
20 21
  template <class ValueType>
  class MtlMatrix
22
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
23
  public:
24
    /// The matrix type of the underlying base matrix
25
    using BaseMatrix = mtl::compressed2D<ValueType>;
26

27
    /// The type of the elements of the DOFMatrix
28
    using value_type = ValueType;
29

30 31 32
    /// The index/size - type
    using size_type = typename BaseMatrix::size_type;

33
    /// The type of the inserter used when filling the matrix. NOTE: need not be public
34
    using Inserter = mtl::mat::inserter<BaseMatrix, mtl::operations::update_plus<value_type>>;
35

36 37
  public:
    /// Constructor. Constructs new BaseMatrix.
38
    MtlMatrix() = default;
39

40
    /// Return a reference to the data-matrix \ref matrix
41
    BaseMatrix& matrix()
42
    {
43
      assert( !inserter_ );
44
      return matrix_;
45
    }
46

47
    /// Return a reference to the data-matrix \ref matrix
48
    BaseMatrix const& matrix() const
49
    {
50
      assert( !inserter_ );
51
      return matrix_;
52
    }
53

54

55
    /// \brief Returns an update-proxy of the inserter, to inserte/update a value at
56
    /// position (\p r, \p c) in the matrix. Need an insertionMode inserter, that can
57
    /// be created by \ref init and must be closed by \ref finish after insertion.
58
    void insert(size_type r, size_type c, value_type const& value)
59
    {
60
      test_exit_dbg(inserter_, "Inserter not initilized!");
61
      test_exit_dbg(r < num_rows(matrix_) && c < num_cols(matrix_),
62
          "Indices out of range [0,{})x[0,{})", num_rows(matrix_), num_cols(matrix_));
63
      (*inserter_)[r][c] += value;
64 65
    }

66

67
    /// Create inserter. Assumes that no inserter is currently active on this matrix.
68 69 70
    template <class RowBasis, class ColBasis>
    void init(RowBasis const& rowBasis, ColBasis const& colBasis,
              bool prepareForInsertion)
71
    {
72
      test_exit(!inserter_, "Matrix already in insertion mode!");
73

74
      calculateSlotSize();
75
      matrix_.change_dim(rowBasis.dimension(), colBasis.dimension());
76
      if (prepareForInsertion) {
77 78
        set_to_zero(matrix_);
        inserter_ = new Inserter(matrix_, slotSize_);
79
      }
80 81
    }

82
    /// Delete inserter -> finish insertion. Must be called in order to fill the
83
    /// final construction of the matrix.
84 85
    void finish()
    {
86
      delete inserter_;
87
      inserter_ = nullptr;
88
    }
89

90
    /// Return the number of nonzeros in the matrix
91
    std::size_t nnz() const
92
    {
93
      return matrix_.nnz();
94
    }
95

96 97 98
  protected:
    // Estimates the slot-size used in the inserter to reserve enough space per row.
    void calculateSlotSize()
99
    {
100
      slotSize_ = 0;
101

102 103
      if (num_rows(matrix_) != 0)
        slotSize_ = int(double(matrix_.nnz()) / num_rows(matrix_) * 1.2);
104 105
      if (slotSize_ < MIN_NNZ_PER_ROW)
        slotSize_ = MIN_NNZ_PER_ROW;
106
    }
107

108
  private:
109
    /// The minimal number of nonzeros per row
110
    static constexpr int MIN_NNZ_PER_ROW = 50;
111

112
    /// The data-matrix (can hold a new BaseMatrix or a pointer to external data
113
    BaseMatrix matrix_;
114

115
    /// A pointer to the inserter. Created in \ref init and destroyed in \ref finish
116
    Inserter* inserter_ = nullptr;
117

118
    /// The size of the slots used to insert values per row
119
    int slotSize_ = MIN_NNZ_PER_ROW;
120 121
  };

122 123 124
  template <class RowBasisType, class ColBasisType, class ValueType = double>
  using DOFMatrix = DOFMatrixBase<RowBasisType, ColBasisType, MtlMatrix<ValueType>>;

125
} // end namespace AMDiS