Files
eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h

297 lines
9.0 KiB
C
Raw Normal View History

2012-05-25 18:17:57 +02:00
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
//
2012-08-01 11:38:32 +02:00
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2012-05-25 18:17:57 +02:00
#ifndef EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
#define EIGEN_SPARSELU_SUPERNODAL_MATRIX_H
2012-05-25 18:17:57 +02:00
namespace Eigen {
namespace internal {
2012-05-25 18:17:57 +02:00
/** \ingroup SparseLU_Module
2012-06-01 18:44:51 +02:00
* \brief a class to manipulate the L supernodal factor from the SparseLU factorization
2012-05-25 18:17:57 +02:00
*
2012-06-01 18:44:51 +02:00
* This class contain the data to easily store
2012-05-25 18:17:57 +02:00
* and manipulate the supernodes during the factorization and solution phase of Sparse LU.
* Only the lower triangular matrix has supernodes.
*
* NOTE : This class corresponds to the SCformat structure in SuperLU
*
*/
/* TODO
2012-06-01 18:44:51 +02:00
* InnerIterator as for sparsematrix
* SuperInnerIterator to iterate through all supernodes
* Function for triangular solve
*/
2012-05-25 18:17:57 +02:00
template <typename _Scalar, typename _Index>
class MappedSuperNodalMatrix
2012-05-25 18:17:57 +02:00
{
public:
2012-06-13 18:26:05 +02:00
typedef _Scalar Scalar;
2012-06-14 18:45:04 +02:00
typedef _Index Index;
typedef Matrix<Index,Dynamic,1> IndexVector;
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
2012-06-01 18:44:51 +02:00
public:
MappedSuperNodalMatrix()
2012-06-01 18:44:51 +02:00
{
}
2013-01-29 16:21:24 +01:00
MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
2012-06-14 18:45:04 +02:00
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
2012-05-25 18:17:57 +02:00
{
2012-06-13 18:26:05 +02:00
setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
2012-05-25 18:17:57 +02:00
}
~MappedSuperNodalMatrix()
2012-05-25 18:17:57 +02:00
{
}
2012-06-06 18:23:39 +02:00
/**
* Set appropriate pointers for the lower triangular supernodal matrix
* These infos are available at the end of the numerical factorization
* FIXME This class will be modified such that it can be use in the course
* of the factorization.
*/
2013-01-29 16:21:24 +01:00
void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
2012-06-14 18:45:04 +02:00
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
2012-06-01 18:44:51 +02:00
{
m_row = m;
m_col = n;
2012-06-14 18:45:04 +02:00
m_nzval = nzval.data();
m_nzval_colptr = nzval_colptr.data();
m_rowind = rowind.data();
m_rowind_colptr = rowind_colptr.data();
2012-06-29 17:45:10 +02:00
m_nsuper = col_to_sup(n);
2012-06-14 18:45:04 +02:00
m_col_to_sup = col_to_sup.data();
m_sup_to_col = sup_to_col.data();
2012-06-01 18:44:51 +02:00
}
2012-05-25 18:17:57 +02:00
2012-06-06 18:23:39 +02:00
/**
* Number of rows
*/
2013-01-29 16:21:24 +01:00
Index rows() { return m_row; }
2012-06-06 18:23:39 +02:00
/**
* Number of columns
*/
2013-01-29 16:21:24 +01:00
Index cols() { return m_col; }
2012-06-06 18:23:39 +02:00
/**
* Return the array of nonzero values packed by column
*
* The size is nnz
*/
Scalar* valuePtr() { return m_nzval; }
2012-06-06 18:23:39 +02:00
2012-06-14 18:45:04 +02:00
const Scalar* valuePtr() const
{
return m_nzval;
}
2012-06-06 18:23:39 +02:00
/**
2012-06-08 17:23:38 +02:00
* Return the pointers to the beginning of each column in \ref valuePtr()
2012-06-06 18:23:39 +02:00
*/
Index* colIndexPtr()
2012-06-01 18:44:51 +02:00
{
2012-06-06 18:23:39 +02:00
return m_nzval_colptr;
}
2012-06-14 18:45:04 +02:00
const Index* colIndexPtr() const
{
return m_nzval_colptr;
}
2012-06-06 18:23:39 +02:00
/**
* Return the array of compressed row indices of all supernodes
*/
Index* rowIndex() { return m_rowind; }
2012-06-14 18:45:04 +02:00
const Index* rowIndex() const
{
return m_rowind;
}
2012-06-06 18:23:39 +02:00
/**
* Return the location in \em rowvaluePtr() which starts each column
*/
Index* rowIndexPtr() { return m_rowind_colptr; }
2012-06-14 18:45:04 +02:00
const Index* rowIndexPtr() const
{
return m_rowind_colptr;
}
2012-06-06 18:23:39 +02:00
/**
* Return the array of column-to-supernode mapping
*/
Index* colToSup() { return m_col_to_sup; }
2012-06-14 18:45:04 +02:00
const Index* colToSup() const
2012-06-06 18:23:39 +02:00
{
return m_col_to_sup;
}
/**
* Return the array of supernode-to-column mapping
*/
Index* supToCol() { return m_sup_to_col; }
2012-06-14 18:45:04 +02:00
const Index* supToCol() const
2012-06-06 18:23:39 +02:00
{
return m_sup_to_col;
}
2012-06-08 17:23:38 +02:00
/**
* Return the number of supernodes
*/
2013-01-29 16:21:24 +01:00
Index nsuper() const
2012-06-08 17:23:38 +02:00
{
return m_nsuper;
}
2012-08-07 17:10:42 +02:00
2012-06-06 18:23:39 +02:00
class InnerIterator;
2012-08-07 17:10:42 +02:00
template<typename Dest>
void solveInPlace( MatrixBase<Dest>&X) const;
2012-06-06 18:23:39 +02:00
2012-05-25 18:17:57 +02:00
protected:
2012-06-01 18:44:51 +02:00
Index m_row; // Number of rows
Index m_col; // Number of columns
2012-06-06 18:23:39 +02:00
Index m_nsuper; // Number of supernodes
Scalar* m_nzval; //array of nonzero values packed by column
2012-06-01 18:44:51 +02:00
Index* m_nzval_colptr; //nzval_colptr[j] Stores the location in nzval[] which starts column j
Index* m_rowind; // Array of compressed row indices of rectangular supernodes
Index* m_rowind_colptr; //rowind_colptr[j] stores the location in rowind[] which starts column j
2012-06-13 18:26:05 +02:00
Index* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
Index* m_sup_to_col; //sup_to_col[s] points to the starting column of the s-th supernode
2012-05-25 18:17:57 +02:00
private :
};
2012-06-06 18:23:39 +02:00
/**
2012-08-07 17:10:42 +02:00
* \brief InnerIterator class to iterate over nonzero values of the current column in the supernode
2012-06-06 18:23:39 +02:00
*
*/
template<typename Scalar, typename Index>
class MappedSuperNodalMatrix<Scalar,Index>::InnerIterator
2012-06-06 18:23:39 +02:00
{
public:
InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
2012-06-06 18:23:39 +02:00
: m_matrix(mat),
m_outer(outer),
m_idval(mat.colIndexPtr()[outer]),
m_startval(m_idval),
2012-06-13 18:26:05 +02:00
m_endval(mat.colIndexPtr()[outer+1]),
2012-06-06 18:23:39 +02:00
m_idrow(mat.rowIndexPtr()[outer]),
m_startidrow(m_idrow),
m_endidrow(mat.rowIndexPtr()[outer+1])
{}
inline InnerIterator& operator++()
{
m_idval++;
2012-08-07 17:10:42 +02:00
m_idrow++;
2012-06-06 18:23:39 +02:00
return *this;
}
inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
2012-06-13 18:26:05 +02:00
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
2012-06-06 18:23:39 +02:00
inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
inline Index row() const { return index(); }
inline Index col() const { return m_outer; }
inline Index supIndex() const { return m_matrix.colToSup()[m_outer]; }
inline operator bool() const
{
return ( (m_idrow < m_endidrow) && (m_idrow > m_startidrow) );
2012-06-06 18:23:39 +02:00
}
protected:
const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
2012-08-07 17:10:42 +02:00
const Index m_outer; // Current column
Index m_idval; //Index to browse the values in the current column
const Index m_startval; // Start of the column value
const Index m_endval; // End of the column value
Index m_idrow; //Index to browse the row indices
const Index m_startidrow; // Start of the row indices of the current column value
const Index m_endidrow; // End of the row indices of the current column value
2012-06-06 18:23:39 +02:00
};
2012-06-13 18:26:05 +02:00
2012-06-06 18:23:39 +02:00
/**
2012-08-07 17:10:42 +02:00
* \brief Solve with the supernode triangular matrix
2012-06-06 18:23:39 +02:00
*
*/
template<typename Scalar, typename Index>
2012-08-07 17:10:42 +02:00
template<typename Dest>
void MappedSuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) const
2012-05-25 18:17:57 +02:00
{
2012-08-07 17:10:42 +02:00
Index n = X.rows();
2013-01-29 16:21:24 +01:00
Index nrhs = X.cols();
2012-08-07 17:10:42 +02:00
const Scalar * Lval = valuePtr(); // Nonzero values
Matrix<Scalar,Dynamic,Dynamic> work(n, nrhs); // working vector
work.setZero();
2013-01-29 16:21:24 +01:00
for (Index k = 0; k <= nsuper(); k ++)
2012-06-06 18:23:39 +02:00
{
2012-08-07 17:10:42 +02:00
Index fsupc = supToCol()[k]; // First column of the current supernode
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
Index nsupr = rowIndexPtr()[fsupc+1] - istart; // Number of rows in the current supernode
Index nsupc = supToCol()[k+1] - fsupc; // Number of columns in the current supernode
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
Index irow; //Current index row
2012-06-06 18:23:39 +02:00
2012-08-07 17:10:42 +02:00
if (nsupc == 1 )
{
2013-01-29 16:21:24 +01:00
for (Index j = 0; j < nrhs; j++)
2012-08-07 17:10:42 +02:00
{
InnerIterator it(*this, fsupc);
++it; // Skip the diagonal element
for (; it; ++it)
{
irow = it.row();
X(irow, j) -= X(fsupc, j) * it.value();
}
}
}
else
{
// The supernode has more than one column
Index luptr = colIndexPtr()[fsupc];
Index lda = colIndexPtr()[fsupc+1] - luptr;
2012-08-07 17:10:42 +02:00
// Triangular solve
Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
2012-08-07 17:10:42 +02:00
Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
U = A.template triangularView<UnitLower>().solve(U);
// Matrix-vector product
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
2012-08-07 17:10:42 +02:00
work.block(0, 0, nrow, nrhs) = A * U;
//Begin Scatter
2013-01-29 16:21:24 +01:00
for (Index j = 0; j < nrhs; j++)
2012-08-07 17:10:42 +02:00
{
Index iptr = istart + nsupc;
2013-01-29 16:21:24 +01:00
for (Index i = 0; i < nrow; i++)
2012-08-07 17:10:42 +02:00
{
irow = rowIndex()[iptr];
X(irow, j) -= work(i, j); // Scatter operation
work(i, j) = Scalar(0);
iptr++;
}
}
}
}
}
} // end namespace internal
2012-08-07 17:10:42 +02:00
} // end namespace Eigen
#endif // EIGEN_SPARSELU_MATRIX_H