Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
SparseLU_SupernodalMatrix.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2012 Désiré Nuentsa-Wakam <[email protected]>
5// Copyright (C) 2012 Gael Guennebaud <[email protected]>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11#ifndef EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
12#define EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18namespace internal {
19
30/* TODO
31 * InnerIterator as for sparsematrix
32 * SuperInnerIterator to iterate through all supernodes
33 * Function for triangular solve
34 */
35template <typename Scalar_, typename StorageIndex_>
36class MappedSuperNodalMatrix {
37 public:
38 typedef Scalar_ Scalar;
39 typedef StorageIndex_ StorageIndex;
40 typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;
41 typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
42
43 public:
44 MappedSuperNodalMatrix() {}
45 MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
46 IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
47 setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
48 }
49
50 ~MappedSuperNodalMatrix() {}
57 void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
58 IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
59 m_row = m;
60 m_col = n;
61 m_nzval = nzval.data();
62 m_nzval_colptr = nzval_colptr.data();
63 m_rowind = rowind.data();
64 m_rowind_colptr = rowind_colptr.data();
65 m_nsuper = col_to_sup(n);
66 m_col_to_sup = col_to_sup.data();
67 m_sup_to_col = sup_to_col.data();
68 }
69
73 Index rows() const { return m_row; }
74
78 Index cols() const { return m_col; }
79
85 Scalar* valuePtr() { return m_nzval; }
86
87 const Scalar* valuePtr() const { return m_nzval; }
91 StorageIndex* colIndexPtr() { return m_nzval_colptr; }
92
93 const StorageIndex* colIndexPtr() const { return m_nzval_colptr; }
94
98 StorageIndex* rowIndex() { return m_rowind; }
99
100 const StorageIndex* rowIndex() const { return m_rowind; }
101
105 StorageIndex* rowIndexPtr() { return m_rowind_colptr; }
106
107 const StorageIndex* rowIndexPtr() const { return m_rowind_colptr; }
108
112 StorageIndex* colToSup() { return m_col_to_sup; }
113
114 const StorageIndex* colToSup() const { return m_col_to_sup; }
118 StorageIndex* supToCol() { return m_sup_to_col; }
119
120 const StorageIndex* supToCol() const { return m_sup_to_col; }
121
125 Index nsuper() const { return m_nsuper; }
126
127 class InnerIterator;
128 template <typename Dest>
129 void solveInPlace(MatrixBase<Dest>& X) const;
130 template <bool Conjugate, typename Dest>
131 void solveTransposedInPlace(MatrixBase<Dest>& X) const;
132
133 protected:
134 Index m_row; // Number of rows
135 Index m_col; // Number of columns
136 Index m_nsuper; // Number of supernodes
137 Scalar* m_nzval; // array of nonzero values packed by column
138 StorageIndex* m_nzval_colptr; // nzval_colptr[j] Stores the location in nzval[] which starts column j
139 StorageIndex* m_rowind; // Array of compressed row indices of rectangular supernodes
140 StorageIndex* m_rowind_colptr; // rowind_colptr[j] stores the location in rowind[] which starts column j
141 StorageIndex* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
142 StorageIndex* m_sup_to_col; // sup_to_col[s] points to the starting column of the s-th supernode
143
144 private:
145};
146
151template <typename Scalar, typename StorageIndex>
152class MappedSuperNodalMatrix<Scalar, StorageIndex>::InnerIterator {
153 public:
154 InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
155 : m_matrix(mat),
156 m_outer(outer),
157 m_supno(mat.colToSup()[outer]),
158 m_idval(mat.colIndexPtr()[outer]),
159 m_startidval(m_idval),
160 m_endidval(mat.colIndexPtr()[outer + 1]),
161 m_idrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]]),
162 m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]] + 1]) {}
163 inline InnerIterator& operator++() {
164 m_idval++;
165 m_idrow++;
166 return *this;
167 }
168 inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
169
170 inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
171
172 inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
173 inline Index row() const { return index(); }
174 inline Index col() const { return m_outer; }
175
176 inline Index supIndex() const { return m_supno; }
177
178 inline operator bool() const {
179 return ((m_idval < m_endidval) && (m_idval >= m_startidval) && (m_idrow < m_endidrow));
180 }
181
182 protected:
183 const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
184 const Index m_outer; // Current column
185 const Index m_supno; // Current SuperNode number
186 Index m_idval; // Index to browse the values in the current column
187 const Index m_startidval; // Start of the column value
188 const Index m_endidval; // End of the column value
189 Index m_idrow; // Index to browse the row indices
190 Index m_endidrow; // End index of row indices of the current column
191};
192
197template <typename Scalar, typename Index_>
198template <typename Dest>
199void MappedSuperNodalMatrix<Scalar, Index_>::solveInPlace(MatrixBase<Dest>& X) const {
200 /* Explicit type conversion as the Index type of MatrixBase<Dest> may be wider than Index */
201 // eigen_assert(X.rows() <= NumTraits<Index>::highest());
202 // eigen_assert(X.cols() <= NumTraits<Index>::highest());
203 Index n = int(X.rows());
204 Index nrhs = Index(X.cols());
205 const Scalar* Lval = valuePtr(); // Nonzero values
206 Matrix<Scalar, Dynamic, Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
207 work.setZero();
208 for (Index k = 0; k <= nsuper(); k++) {
209 Index fsupc = supToCol()[k]; // First column of the current supernode
210 Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
211 Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
212 Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
213 Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
214 Index irow; // Current index row
215
216 if (nsupc == 1) {
217 for (Index j = 0; j < nrhs; j++) {
218 InnerIterator it(*this, fsupc);
219 ++it; // Skip the diagonal element
220 for (; it; ++it) {
221 irow = it.row();
222 X(irow, j) -= X(fsupc, j) * it.value();
223 }
224 }
225 } else {
226 // The supernode has more than one column
227 Index luptr = colIndexPtr()[fsupc];
228 Index lda = colIndexPtr()[fsupc + 1] - luptr;
229
230 // Triangular solve
231 Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr]), nsupc, nsupc,
232 OuterStride<>(lda));
233 typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
234 U = A.template triangularView<UnitLower>().solve(U);
235 // Matrix-vector product
236 new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr + nsupc]), nrow,
237 nsupc, OuterStride<>(lda));
238 work.topRows(nrow).noalias() = A * U;
239
240 // Begin Scatter
241 for (Index j = 0; j < nrhs; j++) {
242 Index iptr = istart + nsupc;
243 for (Index i = 0; i < nrow; i++) {
244 irow = rowIndex()[iptr];
245 X(irow, j) -= work(i, j); // Scatter operation
246 work(i, j) = Scalar(0);
247 iptr++;
248 }
249 }
250 }
251 }
252}
253
254template <typename Scalar, typename Index_>
255template <bool Conjugate, typename Dest>
256void MappedSuperNodalMatrix<Scalar, Index_>::solveTransposedInPlace(MatrixBase<Dest>& X) const {
257 using numext::conj;
258 Index n = int(X.rows());
259 Index nrhs = Index(X.cols());
260 const Scalar* Lval = valuePtr(); // Nonzero values
261 Matrix<Scalar, Dynamic, Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
262 work.setZero();
263 for (Index k = nsuper(); k >= 0; k--) {
264 Index fsupc = supToCol()[k]; // First column of the current supernode
265 Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
266 Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
267 Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
268 Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
269 Index irow; // Current index row
270
271 if (nsupc == 1) {
272 for (Index j = 0; j < nrhs; j++) {
273 InnerIterator it(*this, fsupc);
274 ++it; // Skip the diagonal element
275 for (; it; ++it) {
276 irow = it.row();
277 X(fsupc, j) -= X(irow, j) * (Conjugate ? conj(it.value()) : it.value());
278 }
279 }
280 } else {
281 // The supernode has more than one column
282 Index luptr = colIndexPtr()[fsupc];
283 Index lda = colIndexPtr()[fsupc + 1] - luptr;
284
285 // Begin Gather
286 for (Index j = 0; j < nrhs; j++) {
287 Index iptr = istart + nsupc;
288 for (Index i = 0; i < nrow; i++) {
289 irow = rowIndex()[iptr];
290 work.topRows(nrow)(i, j) = X(irow, j); // Gather operation
291 iptr++;
292 }
293 }
294
295 // Matrix-vector product with transposed submatrix
296 Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr + nsupc]), nrow, nsupc,
297 OuterStride<>(lda));
298 typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
299 if (Conjugate)
300 U = U - A.adjoint() * work.topRows(nrow);
301 else
302 U = U - A.transpose() * work.topRows(nrow);
303
304 // Triangular solve (of transposed diagonal block)
305 new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr]), nsupc, nsupc,
306 OuterStride<>(lda));
307 if (Conjugate)
308 U = A.adjoint().template triangularView<UnitUpper>().solve(U);
309 else
310 U = A.transpose().template triangularView<UnitUpper>().solve(U);
311 }
312 }
313}
314
315} // end namespace internal
316
317} // end namespace Eigen
318
319#endif // EIGEN_SPARSELU_MATRIX_H
Namespace containing all symbols from the Eigen library.
Definition Core:137
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83