Clean the supernodal matrix class

This commit is contained in:
Desire NUENTSA 2012-08-07 17:10:42 +02:00
parent 43f74cb5b1
commit 63d2dcfb70
2 changed files with 95 additions and 117 deletions

View File

@ -153,107 +153,48 @@ class SparseLU
for(int j = 0; j < nrhs; ++j) for(int j = 0; j < nrhs; ++j)
X.col(j) = m_perm_r * B.col(j); X.col(j) = m_perm_r * B.col(j);
// Forward solve PLy = Pb; //Forward substitution with L
Index fsupc; // First column of the current supernode m_Lstore.solveInPlace(X);
Index istart; // Pointer index to the subscript of the current column
Index nsupr; // Number of rows in the current supernode
Index nsupc; // Number of columns in the current supernode
Index nrow; // Number of rows in the non-diagonal part of the supernode
Index luptr; // Pointer index to the current nonzero value
Index iptr; // row index pointer iterator
Index irow; //Current index row
const Scalar * Lval = m_Lstore.valuePtr(); // Nonzero values
Matrix<Scalar,Dynamic,Dynamic> work(n, nrhs); // working vector
work.setZero();
int j, k, i,jcol;
for (k = 0; k <= m_Lstore.nsuper(); k ++)
{
fsupc = m_Lstore.supToCol()[k];
istart = m_Lstore.rowIndexPtr()[fsupc];
nsupr = m_Lstore.rowIndexPtr()[fsupc+1] - istart;
nsupc = m_Lstore.supToCol()[k+1] - fsupc;
nrow = nsupr - nsupc;
if (nsupc == 1 )
{
for (j = 0; j < nrhs; j++)
{
luptr = m_Lstore.colIndexPtr()[fsupc];
for (iptr = istart+1; iptr < m_Lstore.rowIndexPtr()[fsupc+1]; iptr++)
{
irow = m_Lstore.rowIndex()[iptr];
++luptr;
X(irow, j) -= X(fsupc, j) * Lval[luptr];
}
}
}
else
{
// The supernode has more than one column
luptr = m_Lstore.colIndexPtr()[fsupc];
// Triangular solve
Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(nsupr) );
Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X.data()[fsupc]), 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<>(nsupr) );
work.block(0, 0, nrow, nrhs) = A * U;
//Begin Scatter
for (j = 0; j < nrhs; j++)
{
iptr = istart + nsupc;
for (i = 0; i < nrow; i++)
{
irow = m_Lstore.rowIndex()[iptr];
X(irow, j) -= work(i, j); // Scatter operation
work(i, j) = Scalar(0);
iptr++;
}
}
}
} // end for all supernodes
// Back solve Ux = y // Backward solve with U
for (k = m_Lstore.nsuper(); k >= 0; k--) for (int k = m_Lstore.nsuper(); k >= 0; k--)
{ {
fsupc = m_Lstore.supToCol()[k]; Index fsupc = m_Lstore.supToCol()[k];
istart = m_Lstore.rowIndexPtr()[fsupc]; Index istart = m_Lstore.rowIndexPtr()[fsupc];
nsupr = m_Lstore.rowIndexPtr()[fsupc+1] - istart; Index nsupr = m_Lstore.rowIndexPtr()[fsupc+1] - istart;
nsupc = m_Lstore.supToCol()[k+1] - fsupc; Index nsupc = m_Lstore.supToCol()[k+1] - fsupc;
luptr = m_Lstore.colIndexPtr()[fsupc]; Index luptr = m_Lstore.colIndexPtr()[fsupc];
if (nsupc == 1) if (nsupc == 1)
{ {
for (j = 0; j < nrhs; j++) for (int j = 0; j < nrhs; j++)
{ {
X(fsupc, j) /= Lval[luptr]; X(fsupc, j) /= m_Lstore.valuePtr()[luptr];
} }
} }
else else
{ {
Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(nsupr) ); Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(m_Lstore.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(nsupr) );
Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X.data()[fsupc]), nsupc, nrhs, OuterStride<>(n) ); Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
U = A.template triangularView<Upper>().solve(U); U = A.template triangularView<Upper>().solve(U);
} }
for (j = 0; j < nrhs; ++j) for (int j = 0; j < nrhs; ++j)
{ {
for (jcol = fsupc; jcol < fsupc + nsupc; jcol++) for (int jcol = fsupc; jcol < fsupc + nsupc; jcol++)
{ {
for (i = m_Ustore.outerIndexPtr()[jcol]; i < m_Ustore.outerIndexPtr()[jcol+1]; i++) typename MappedSparseMatrix<Scalar>::InnerIterator it(m_Ustore, jcol);
for ( ; it; ++it)
{ {
irow = m_Ustore.innerIndexPtr()[i]; Index irow = it.index();
X(irow, j) -= X(jcol, j) * m_Ustore.valuePtr()[i]; X(irow, j) -= X(jcol, j) * it.value();
} }
} }
} }
} // End For U-solve } // End For U-solve
// Permute back the solution // Permute back the solution
for (j = 0; j < nrhs; ++j) for (int j = 0; j < nrhs; ++j)
X.col(j) = m_perm_c.inverse() * X.col(j); X.col(j) = m_perm_c.inverse() * X.col(j);
return true; return true;

View File

@ -171,8 +171,13 @@ class SuperNodalMatrix
{ {
return m_nsuper; return m_nsuper;
} }
class InnerIterator; class InnerIterator;
class SuperNodeIterator; template<typename Dest>
void solveInPlace( MatrixBase<Dest>&X) const;
protected: protected:
Index m_row; // Number of rows Index m_row; // Number of rows
@ -189,7 +194,7 @@ class SuperNodalMatrix
}; };
/** /**
* \brief InnerIterator class to iterate over nonzero values in the triangular supernodal matrix * \brief InnerIterator class to iterate over nonzero values of the current column in the supernode
* *
*/ */
template<typename Scalar, typename Index> template<typename Scalar, typename Index>
@ -209,7 +214,7 @@ class SuperNodalMatrix<Scalar,Index>::InnerIterator
inline InnerIterator& operator++() inline InnerIterator& operator++()
{ {
m_idval++; m_idval++;
m_idrow++ ; m_idrow++;
return *this; return *this;
} }
inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; } inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
@ -229,48 +234,80 @@ class SuperNodalMatrix<Scalar,Index>::InnerIterator
} }
protected: protected:
const SuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix const SuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
const Index m_outer; // Current column const Index m_outer; // Current column
Index m_idval; //Index to browse the values in the 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_startval; // Start of the column value
const Index m_endval; // End of the column value const Index m_endval; // End of the column value
Index m_idrow; //Index to browse the row indices 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_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 const Index m_endidrow; // End of the row indices of the current column value
}; };
/** /**
* \brief Iterator class to iterate over Supernodes in the triangular supernodal matrix * \brief Solve with the supernode triangular matrix
* *
* The final goal is to use this class when dealing with supernodes during numerical factorization
*/ */
template<typename Scalar, typename Index> template<typename Scalar, typename Index>
class SuperNodalMatrix<Scalar,Index>::SuperNodeIterator template<typename Dest>
void SuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) const
{ {
public: Index n = X.rows();
SuperNodeIterator(const SuperNodalMatrix& mat) int nrhs = X.cols();
const Scalar * Lval = valuePtr(); // Nonzero values
Matrix<Scalar,Dynamic,Dynamic> work(n, nrhs); // working vector
work.setZero();
for (int k = 0; k <= nsuper(); k ++)
{ {
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
} if (nsupc == 1 )
SuperNodeIterator(const SuperNodalMatrix& mat, Index supno) {
{ for (int j = 0; j < nrhs; j++)
{
} InnerIterator it(*this, fsupc);
++it; // Skip the diagonal element
/* for (; it; ++it)
* Available Methods : {
* Browse all supernodes (operator ++ ) irow = it.row();
* Number of supernodes X(irow, j) -= X(fsupc, j) * it.value();
* Columns of the current supernode }
* triangular matrix of the current supernode }
* rectangular part of the current supernode }
*/ else
protected: {
const SuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix // The supernode has more than one column
Index m_idsup; // Index to browse all supernodes Index luptr = colIndexPtr()[fsupc];
const Index m_nsuper; // Number of all supernodes
Index m_startidsup; // Triangular solve
Index m_endidsup; Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(nsupr) );
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<>(nsupr) );
work.block(0, 0, nrow, nrhs) = A * U;
//Begin Scatter
for (int j = 0; j < nrhs; j++)
{
Index iptr = istart + nsupc;
for (int i = 0; i < nrow; i++)
{
irow = rowIndex()[iptr];
X(irow, j) -= work(i, j); // Scatter operation
work(i, j) = Scalar(0);
iptr++;
}
}
}
}
}
#endif #endif