Eigen  5.0.1
 
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 <desire.nuentsa_wakam@inria.fr>
5// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
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// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
13#define EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
14
15// IWYU pragma: private
16#include "./InternalHeaderCheck.h"
17
18namespace Eigen {
19namespace internal {
20
31// TODO: add InnerIterator, SuperInnerIterator, and triangular solve support.
32template <typename Scalar_, typename StorageIndex_>
33class MappedSuperNodalMatrix {
34 public:
35 using Scalar = Scalar_;
36 using StorageIndex = StorageIndex_;
37 using IndexVector = Matrix<StorageIndex, Dynamic, 1>;
38 using ScalarVector = Matrix<Scalar, Dynamic, 1>;
39
40 public:
41 MappedSuperNodalMatrix() {}
42 MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
43 IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
44 setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
45 }
46
53 void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
54 IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
55 m_row = m;
56 m_col = n;
57 m_nzval = nzval.data();
58 m_nzval_colptr = nzval_colptr.data();
59 m_rowind = rowind.data();
60 m_rowind_colptr = rowind_colptr.data();
61 m_nsuper = col_to_sup(n);
62 m_col_to_sup = col_to_sup.data();
63 m_sup_to_col = sup_to_col.data();
64 }
65
69 Index rows() const { return m_row; }
70
74 Index cols() const { return m_col; }
75
81 Scalar* valuePtr() { return m_nzval; }
82
83 const Scalar* valuePtr() const { return m_nzval; }
87 StorageIndex* colIndexPtr() { return m_nzval_colptr; }
88
89 const StorageIndex* colIndexPtr() const { return m_nzval_colptr; }
90
94 StorageIndex* rowIndex() { return m_rowind; }
95
96 const StorageIndex* rowIndex() const { return m_rowind; }
97
101 StorageIndex* rowIndexPtr() { return m_rowind_colptr; }
102
103 const StorageIndex* rowIndexPtr() const { return m_rowind_colptr; }
104
108 StorageIndex* colToSup() { return m_col_to_sup; }
109
110 const StorageIndex* colToSup() const { return m_col_to_sup; }
114 StorageIndex* supToCol() { return m_sup_to_col; }
115
116 const StorageIndex* supToCol() const { return m_sup_to_col; }
117
121 Index nsuper() const { return m_nsuper; }
122
123 class InnerIterator;
124 template <typename Dest>
126 template <bool Conjugate, typename Dest>
127 void solveTransposedInPlace(MatrixBase<Dest>& X) const;
128
129 protected:
130 Index m_row; // Number of rows
131 Index m_col; // Number of columns
132 Index m_nsuper; // Number of supernodes
133 Scalar* m_nzval; // array of nonzero values packed by column
134 StorageIndex* m_nzval_colptr; // nzval_colptr[j] Stores the location in nzval[] which starts column j
135 StorageIndex* m_rowind; // Array of compressed row indices of rectangular supernodes
136 StorageIndex* m_rowind_colptr; // rowind_colptr[j] stores the location in rowind[] which starts column j
137 StorageIndex* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
138 StorageIndex* m_sup_to_col; // sup_to_col[s] points to the starting column of the s-th supernode
139
140 private:
141};
142
147template <typename Scalar, typename StorageIndex>
148class MappedSuperNodalMatrix<Scalar, StorageIndex>::InnerIterator {
149 public:
150 InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
151 : m_matrix(mat),
152 m_outer(outer),
153 m_supno(mat.colToSup()[outer]),
154 m_idval(mat.colIndexPtr()[outer]),
155 m_startidval(m_idval),
156 m_endidval(mat.colIndexPtr()[outer + 1]),
157 m_idrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]]),
158 m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]] + 1]) {}
159 inline InnerIterator& operator++() {
160 m_idval++;
161 m_idrow++;
162 return *this;
163 }
164 inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
165
166 inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
167
168 inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
169 inline Index row() const { return index(); }
170 inline Index col() const { return m_outer; }
171
172 inline Index supIndex() const { return m_supno; }
173
174 inline operator bool() const {
175 return ((m_idval < m_endidval) && (m_idval >= m_startidval) && (m_idrow < m_endidrow));
176 }
177
178 protected:
179 const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
180 const Index m_outer; // Current column
181 const Index m_supno; // Current SuperNode number
182 Index m_idval; // Index to browse the values in the current column
183 const Index m_startidval; // Start of the column value
184 const Index m_endidval; // End of the column value
185 Index m_idrow; // Index to browse the row indices
186 Index m_endidrow; // End index of row indices of the current column
187};
188
193template <typename Scalar, typename Index_>
194template <typename Dest>
196 /* Explicit type conversion as the Index type of MatrixBase<Dest> may be wider than Index */
197 Index n = int(X.rows());
198 Index nrhs = Index(X.cols());
199 const Scalar* Lval = valuePtr(); // Nonzero values
201 work.setZero();
202 for (Index k = 0; k <= nsuper(); k++) {
203 Index fsupc = supToCol()[k]; // First column of the current supernode
204 Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
205 Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
206 Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
207 Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
208 Index irow; // Current index row
209
210 if (nsupc == 1) {
211 for (Index j = 0; j < nrhs; j++) {
212 InnerIterator it(*this, fsupc);
213 ++it; // Skip the diagonal element
214 for (; it; ++it) {
215 irow = it.row();
216 X(irow, j) -= X(fsupc, j) * it.value();
217 }
218 }
219 } else {
220 // The supernode has more than one column
221 Index luptr = colIndexPtr()[fsupc];
222 Index lda = colIndexPtr()[fsupc + 1] - luptr;
223
224 // Triangular solve
225 Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr]), nsupc, nsupc,
226 OuterStride<>(lda));
227 typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
228 U = A.template triangularView<UnitLower>().solve(U);
229 // Matrix-vector product
230 new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr + nsupc]), nrow,
231 nsupc, OuterStride<>(lda));
232 work.topRows(nrow).noalias() = A * U;
233
234 // Begin Scatter
235 for (Index j = 0; j < nrhs; j++) {
236 Index iptr = istart + nsupc;
237 for (Index i = 0; i < nrow; i++) {
238 irow = rowIndex()[iptr];
239 X(irow, j) -= work(i, j); // Scatter operation
240 work(i, j) = Scalar(0);
241 iptr++;
242 }
243 }
244 }
245 }
246}
247
248template <typename Scalar, typename Index_>
249template <bool Conjugate, typename Dest>
250void MappedSuperNodalMatrix<Scalar, Index_>::solveTransposedInPlace(MatrixBase<Dest>& X) const {
251 using numext::conj;
252 Index n = int(X.rows());
253 Index nrhs = Index(X.cols());
254 const Scalar* Lval = valuePtr(); // Nonzero values
256 work.setZero();
257 for (Index k = nsuper(); k >= 0; k--) {
258 Index fsupc = supToCol()[k]; // First column of the current supernode
259 Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
260 Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
261 Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
262 Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
263 Index irow; // Current index row
264
265 if (nsupc == 1) {
266 for (Index j = 0; j < nrhs; j++) {
267 InnerIterator it(*this, fsupc);
268 ++it; // Skip the diagonal element
269 for (; it; ++it) {
270 irow = it.row();
271 X(fsupc, j) -= X(irow, j) * (Conjugate ? conj(it.value()) : it.value());
272 }
273 }
274 } else {
275 // The supernode has more than one column
276 Index luptr = colIndexPtr()[fsupc];
277 Index lda = colIndexPtr()[fsupc + 1] - luptr;
278
279 // Begin Gather
280 for (Index j = 0; j < nrhs; j++) {
281 Index iptr = istart + nsupc;
282 for (Index i = 0; i < nrow; i++) {
283 irow = rowIndex()[iptr];
284 work.topRows(nrow)(i, j) = X(irow, j); // Gather operation
285 iptr++;
286 }
287 }
288
289 // Matrix-vector product with transposed submatrix
290 Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr + nsupc]), nrow, nsupc,
291 OuterStride<>(lda));
292 typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
293 EIGEN_IF_CONSTEXPR (Conjugate)
294 U.noalias() -= A.adjoint() * work.topRows(nrow);
295 else
296 U.noalias() -= A.transpose() * work.topRows(nrow);
297
298 // Triangular solve (of transposed diagonal block)
299 new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr]), nsupc, nsupc,
300 OuterStride<>(lda));
301 EIGEN_IF_CONSTEXPR (Conjugate)
302 U = A.adjoint().template triangularView<UnitUpper>().solve(U);
303 else
304 U = A.transpose().template triangularView<UnitUpper>().solve(U);
305 }
306 }
307}
308
309} // end namespace internal
310
311} // end namespace Eigen
312
313#endif // EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
constexpr NRowsBlockXpr<... >::Type middleRows(Index startRow, NRowsType n)
Definition DenseBase.h:738
An InnerIterator allows to loop over the element of any matrix expression.
Definition CoreIterators.h:38
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
constexpr const Scalar * data() const
Definition PlainObjectBase.h:261
Derived & setZero(Index size)
Definition CwiseNullaryOp.h:536
InnerIterator class to iterate over nonzero values of the current column in the supernodal matrix L.
Definition SparseLU_SupernodalMatrix.h:148
StorageIndex * rowIndexPtr()
Definition SparseLU_SupernodalMatrix.h:101
void setInfos(Index m, Index n, ScalarVector &nzval, IndexVector &nzval_colptr, IndexVector &rowind, IndexVector &rowind_colptr, IndexVector &col_to_sup, IndexVector &sup_to_col)
Definition SparseLU_SupernodalMatrix.h:53
StorageIndex * rowIndex()
Definition SparseLU_SupernodalMatrix.h:94
Index nsuper() const
Definition SparseLU_SupernodalMatrix.h:121
StorageIndex * colIndexPtr()
Definition SparseLU_SupernodalMatrix.h:87
StorageIndex * supToCol()
Definition SparseLU_SupernodalMatrix.h:114
void solveInPlace(MatrixBase< Dest > &X) const
Solve with the supernode triangular matrix.
Definition SparseLU_SupernodalMatrix.h:195
Index rows() const
Definition SparseLU_SupernodalMatrix.h:69
StorageIndex * colToSup()
Definition SparseLU_SupernodalMatrix.h:108
Index cols() const
Definition SparseLU_SupernodalMatrix.h:74
Scalar * valuePtr()
Definition SparseLU_SupernodalMatrix.h:81