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
16namespace 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
Dummy implementation for sequential index "distribution".
Definition: IndexDistribution.hpp:7
The basic container that stores a base matrix and a corresponding row/column feSpace.
Definition: MatrixBackend.hpp:24
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
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
Eigen::SparseMatrix< T, Orientation > BaseMatrix
The matrix type of the underlying base matrix.
Definition: MatrixBackend.hpp:27
BaseMatrix const & matrix() const
Return a reference to the data-matrix matrix.
Definition: MatrixBackend.hpp:47
typename BaseMatrix::Index size_type
The index/size - type.
Definition: MatrixBackend.hpp:33
typename BaseMatrix::Scalar value_type
The type of the elements of the DOFMatrix.
Definition: MatrixBackend.hpp:30
void finish()
Set the matrix entries from the triplet list and compress the matrix afterwards.
Definition: MatrixBackend.hpp:192
BaseMatrix & matrix()
Return a reference to the data-matrix matrix.
Definition: MatrixBackend.hpp:41
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
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
EigenSparseMatrix(DefaultIndexDistribution const &, DefaultIndexDistribution const &)
Constructor. Constructs new BaseMatrix.
Definition: MatrixBackend.hpp:37
void init(MatrixSize const &sizes)
Resize the matrix according to the pattern provided and set all entries to zero.
Definition: MatrixBackend.hpp:179
The basic container that stores a base vector and a corresponding basis.
Definition: VectorBackend.hpp:22
Definition: MatrixSize.hpp:12
std::size_t rows() const
Number of rows in the matrix.
Definition: MatrixSize.hpp:22
std::size_t cols() const
Number of columns in the matrix.
Definition: MatrixSize.hpp:28