AMDiS  2.10
The Adaptive Multi-Dimensional Simulation Toolbox
MatrixBackend.hpp
1 #pragma once
2 
3 #include <list>
4 #include <memory>
5 #include <string>
6 #include <vector>
7 
8 #include <Eigen/SparseCore>
9 
10 #include <dune/common/timer.hh>
11 
12 #include <amdis/Output.hpp>
13 #include <amdis/linearalgebra/eigen/MatrixSize.hpp>
14 #include <amdis/linearalgebra/eigen/VectorBackend.hpp>
15 
16 namespace AMDiS
17 {
18  class DefaultIndexDistribution;
19 
22  template <class T, int Orientation = Eigen::RowMajor>
24  {
25  public:
27  using BaseMatrix = Eigen::SparseMatrix<T, Orientation>;
28 
30  using value_type = typename BaseMatrix::Scalar;
31 
33  using size_type = typename BaseMatrix::Index;
34 
35  public:
38  {}
39 
42  {
43  return matrix_;
44  }
45 
47  BaseMatrix const& matrix() const
48  {
49  return matrix_;
50  }
51 
52 
56  void insert(size_type r, size_type c, value_type const& value)
57  {
58  test_exit_dbg(r < matrix_.rows() && c < matrix_.cols(),
59  "Indices out of range [0,{})x[0,{})", matrix_.rows(), matrix_.cols());
60  tripletList_.emplace_back(r, c, value);
61  }
62 
63  template <class Ind, class LocalMat>
64  void scatter(Ind const& idx, LocalMat const& mat)
65  {
66  scatter(idx, idx, mat);
67  }
68 
69  template <class RowInd, class ColInd, class LocalMat>
70  void scatter(RowInd const& rows, ColInd const& cols, LocalMat const& mat)
71  {
72  //tripletList_.reserve(tripletList_.size() + rows.size()*cols.size());
73  for (size_type i = 0; i < size_type(rows.size()); ++i)
74  for (size_type j = 0; j < size_type(cols.size()); ++j)
75  tripletList_.emplace_back(rows[i], cols[j], mat[i][j]);
76  }
77 
79  template <class RowInd, class ColInd>
80  void zeroRows(RowInd const& rowInd, ColInd const& colInd, bool diag)
81  {
82  if constexpr(Orientation == Eigen::RowMajor) {
83  // loop over the matrix rows
84  auto rowIt = rowInd.begin();
85  auto rowEnd = rowInd.end();
86  auto colIt = colInd.begin();
87  for (; rowIt != rowEnd; ++rowIt, ++colIt) {
88  for (typename BaseMatrix::InnerIterator it(matrix_, *rowIt); it; ++it)
89  it.valueRef() = (diag && *colIt == it.col() ? T(1) : T(0));
90  }
91  } else {
92  error_exit("EigenMatrix::zeroRows with row and col indices is only implemented for RowMajor matrices.");
93  }
94  }
95 
96  template <class RowInd>
97  void zeroRows(RowInd const& rowInd, bool diag)
98  {
99  if constexpr(Orientation == Eigen::ColMajor) {
100  std::vector<bool> rowBitVec(matrix_.rows());
101  for (std::size_t i = 0; i < rowInd.size(); ++i)
102  rowBitVec[rowInd[i]] = true;
103 
104  // loop over the matrix columns
105  for (size_type c = 0; c < matrix_.outerSize(); ++c) {
106  for (typename BaseMatrix::InnerIterator it(matrix_, c); it; ++it) {
107  if (rowBitVec[it.row()])
108  it.valueRef() = (diag && it.row() == it.col() ? T(1) : T(0));
109  }
110  }
111  } else if constexpr(Orientation == Eigen::RowMajor) {
112  // loop over the matrix rows
113  for (size_type r : rowInd) {
114  for (typename BaseMatrix::InnerIterator it(matrix_, r); it; ++it)
115  it.valueRef() = (diag && it.row() == it.col() ? T(1) : T(0));
116  }
117  }
118  }
119 
121  template <class RowInd, class ColInd>
122  void zeroRowsColumnsImpl(RowInd const& rowInd, ColInd const& colInd, bool diag, EigenVector<T> const* x = nullptr, EigenVector<T>* b = nullptr)
123  {
124  static_assert(Orientation == Eigen::RowMajor, "Only implemented for RowMajor matrices.");
125  assert(rowInd.size() == colInd.size());
126 
127  std::vector<bool> colBitVec(matrix_.cols());
128  for (std::size_t i = 0; i < rowInd.size(); ++i) {
129  colBitVec[colInd[i]] = true;
130  }
131 
132  // eliminate rows
133  zeroRows(rowInd,false);
134 
135  // eliminate columns
136  for (size_type r = 0; r < matrix_.outerSize(); ++r) {
137  for (typename BaseMatrix::InnerIterator it(matrix_, r); it; ++it) {
138  if (colBitVec[it.col()]) {
139  if (diag && x && b)
140  b->vector()[r] -= it.value() * x->vector()[it.col()];
141  it.valueRef() = 0;
142  }
143  }
144  }
145 
146  // set diagonal entry
147  if (diag) {
148  for (std::size_t i = 0; i < rowInd.size(); ++i)
149  matrix_.coeffRef(rowInd[i],colInd[i]) = 1;
150  if (!matrix_.isCompressed())
151  matrix_.makeCompressed();
152  }
153  }
154  template <class RowInd>
155  void zeroRowsColumns(RowInd const& rowInd, bool diag)
156  {
157  zeroRowsColumnsImpl(rowInd,rowInd,diag,nullptr,nullptr);
158  }
159 
160  template <class RowInd>
161  void zeroRowsColumns(RowInd const& rowInd, bool diag, EigenVector<T> const& x, EigenVector<T> & b)
162  {
163  zeroRowsColumnsImpl(rowInd,rowInd,diag,&x,&b);
164  }
165 
166  template <class RowInd, class ColInd>
167  void zeroRowsColumns(RowInd const& rowInd, ColInd const& colInd, bool diag)
168  {
169  zeroRowsColumnsImpl(rowInd,colInd,diag,nullptr,nullptr);
170  }
171 
172  template <class RowInd, class ColInd>
173  void zeroRowsColumns(RowInd const& rowInd, ColInd const& colInd, bool diag, EigenVector<T> const& x, EigenVector<T> & b)
174  {
175  zeroRowsColumnsImpl(rowInd,colInd,diag,&x,&b);
176  }
177 
179  void init(MatrixSize const& sizes)
180  {
181  matrix_.resize(sizes.rows(), sizes.cols());
182  matrix_.setZero();
183  }
184 
186  void init()
187  {
188  matrix_.setZero();
189  }
190 
192  void finish()
193  {
194  matrix_.setFromTriplets(tripletList_.begin(), tripletList_.end());
195  matrix_.makeCompressed();
196 
197  tripletList_.clear(); // NOTE: this does not free the memory
198  }
199 
201  std::size_t nnz() const
202  {
203  return matrix_.nonZeros();
204  }
205 
206  private:
208  BaseMatrix matrix_;
209 
211  std::vector<Eigen::Triplet<value_type, Eigen::Index>> tripletList_;
212  };
213 
214 } // end namespace AMDiS
void init(MatrixSize const &sizes)
Resize the matrix according to the pattern provided and set all entries to zero.
Definition: MatrixBackend.hpp:179
void init()
Set all matrix entries to zero while keeping the size unchanged.
Definition: MatrixBackend.hpp:186
std::size_t nnz() const
Return the number of nonzeros in the matrix.
Definition: MatrixBackend.hpp:201
std::size_t cols() const
Number of columns in the matrix.
Definition: MatrixSize.hpp:28
typename BaseMatrix::Index size_type
The index/size - type.
Definition: MatrixBackend.hpp:33
std::size_t rows() const
Number of rows in the matrix.
Definition: MatrixSize.hpp:22
Definition: AdaptBase.hpp:6
The basic container that stores a base vector and a corresponding basis.
Definition: VectorBackend.hpp:20
void zeroRowsColumnsImpl(RowInd const &rowInd, ColInd const &colInd, bool diag, EigenVector< T > const *x=nullptr, EigenVector< T > *b=nullptr)
Set all entries of the specified rows and columns to zero and the diagonal element to diag ...
Definition: MatrixBackend.hpp:122
The basic container that stores a base matrix and a corresponding row/column feSpace.
Definition: MatrixBackend.hpp:23
BaseMatrix & matrix()
Return a reference to the data-matrix matrix.
Definition: MatrixBackend.hpp:41
BaseMatrix const & matrix() const
Return a reference to the data-matrix matrix.
Definition: MatrixBackend.hpp:47
void finish()
Set the matrix entries from the triplet list and compress the matrix afterwards.
Definition: MatrixBackend.hpp:192
typename BaseMatrix::Scalar value_type
The type of the elements of the DOFMatrix.
Definition: MatrixBackend.hpp:30
Dummy implementation for sequential index "distribution".
Definition: IndexDistribution.hpp:6
void insert(size_type r, size_type c, value_type const &value)
Returns an update-proxy of the inserter, to insert/update a value at position (r, c) in the matrix...
Definition: MatrixBackend.hpp:56
Definition: MatrixSize.hpp:11
EigenSparseMatrix(DefaultIndexDistribution const &, DefaultIndexDistribution const &)
Constructor. Constructs new BaseMatrix.
Definition: MatrixBackend.hpp:37
Eigen::SparseMatrix< T, Orientation > BaseMatrix
The matrix type of the underlying base matrix.
Definition: MatrixBackend.hpp:27
void zeroRows(RowInd const &rowInd, ColInd const &colInd, bool diag)
Set all entries of the specified rows to zero and the diagonal element to diag
Definition: MatrixBackend.hpp:80