2012-03-08 18:59:08 +01: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>
//
2012-07-13 14:42:47 -04: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-03-08 18:59:08 +01:00
# ifndef EIGEN_PASTIXSUPPORT_H
# define EIGEN_PASTIXSUPPORT_H
2012-04-15 11:06:28 +01:00
namespace Eigen {
2012-03-08 18:59:08 +01:00
/** \ingroup PaStiXSupport_Module
* \ brief Interface to the PaStix solver
*
* This class is used to solve the linear systems A . X = B via the PaStix library .
* The matrix can be either real or complex , symmetric or not .
*
* \ sa TutorialSparseDirectSolvers
*/
template < typename _MatrixType , bool IsStrSym = false > class PastixLU ;
template < typename _MatrixType , int Options > class PastixLLT ;
template < typename _MatrixType , int Options > class PastixLDLT ;
namespace internal
{
template < class Pastix > struct pastix_traits ;
template < typename _MatrixType >
struct pastix_traits < PastixLU < _MatrixType > >
{
typedef _MatrixType MatrixType ;
typedef typename _MatrixType : : Scalar Scalar ;
typedef typename _MatrixType : : RealScalar RealScalar ;
typedef typename _MatrixType : : Index Index ;
} ;
template < typename _MatrixType , int Options >
struct pastix_traits < PastixLLT < _MatrixType , Options > >
{
typedef _MatrixType MatrixType ;
typedef typename _MatrixType : : Scalar Scalar ;
typedef typename _MatrixType : : RealScalar RealScalar ;
typedef typename _MatrixType : : Index Index ;
} ;
template < typename _MatrixType , int Options >
struct pastix_traits < PastixLDLT < _MatrixType , Options > >
{
typedef _MatrixType MatrixType ;
typedef typename _MatrixType : : Scalar Scalar ;
typedef typename _MatrixType : : RealScalar RealScalar ;
typedef typename _MatrixType : : Index Index ;
} ;
void eigen_pastix ( pastix_data_t * * pastix_data , int pastix_comm , int n , int * ptr , int * idx , float * vals , int * perm , int * invp , float * x , int nbrhs , int * iparm , double * dparm )
{
if ( n = = 0 ) { ptr = NULL ; idx = NULL ; vals = NULL ; }
2012-06-12 16:47:14 +02:00
if ( nbrhs = = 0 ) { x = NULL ; nbrhs = 1 ; }
2012-03-08 18:59:08 +01:00
s_pastix ( pastix_data , pastix_comm , n , ptr , idx , vals , perm , invp , x , nbrhs , iparm , dparm ) ;
}
void eigen_pastix ( pastix_data_t * * pastix_data , int pastix_comm , int n , int * ptr , int * idx , double * vals , int * perm , int * invp , double * x , int nbrhs , int * iparm , double * dparm )
{
if ( n = = 0 ) { ptr = NULL ; idx = NULL ; vals = NULL ; }
2012-06-12 16:47:14 +02:00
if ( nbrhs = = 0 ) { x = NULL ; nbrhs = 1 ; }
2012-03-08 18:59:08 +01:00
d_pastix ( pastix_data , pastix_comm , n , ptr , idx , vals , perm , invp , x , nbrhs , iparm , dparm ) ;
}
void eigen_pastix ( pastix_data_t * * pastix_data , int pastix_comm , int n , int * ptr , int * idx , std : : complex < float > * vals , int * perm , int * invp , std : : complex < float > * x , int nbrhs , int * iparm , double * dparm )
{
2012-06-12 16:47:14 +02:00
if ( n = = 0 ) { ptr = NULL ; idx = NULL ; vals = NULL ; }
if ( nbrhs = = 0 ) { x = NULL ; nbrhs = 1 ; }
2012-03-08 18:59:08 +01:00
c_pastix ( pastix_data , pastix_comm , n , ptr , idx , reinterpret_cast < COMPLEX * > ( vals ) , perm , invp , reinterpret_cast < COMPLEX * > ( x ) , nbrhs , iparm , dparm ) ;
}
void eigen_pastix ( pastix_data_t * * pastix_data , int pastix_comm , int n , int * ptr , int * idx , std : : complex < double > * vals , int * perm , int * invp , std : : complex < double > * x , int nbrhs , int * iparm , double * dparm )
{
if ( n = = 0 ) { ptr = NULL ; idx = NULL ; vals = NULL ; }
2012-06-12 16:47:14 +02:00
if ( nbrhs = = 0 ) { x = NULL ; nbrhs = 1 ; }
2012-03-08 18:59:08 +01:00
z_pastix ( pastix_data , pastix_comm , n , ptr , idx , reinterpret_cast < DCOMPLEX * > ( vals ) , perm , invp , reinterpret_cast < DCOMPLEX * > ( x ) , nbrhs , iparm , dparm ) ;
}
// Convert the matrix to Fortran-style Numbering
template < typename MatrixType >
2012-06-12 16:47:14 +02:00
void c_to_fortran_numbering ( MatrixType & mat )
2012-03-08 18:59:08 +01:00
{
if ( ! ( mat . outerIndexPtr ( ) [ 0 ] ) )
{
int i ;
for ( i = 0 ; i < = mat . rows ( ) ; + + i )
+ + mat . outerIndexPtr ( ) [ i ] ;
for ( i = 0 ; i < mat . nonZeros ( ) ; + + i )
+ + mat . innerIndexPtr ( ) [ i ] ;
}
}
// Convert to C-style Numbering
template < typename MatrixType >
2012-06-12 16:47:14 +02:00
void fortran_to_c_numbering ( MatrixType & mat )
2012-03-08 18:59:08 +01:00
{
// Check the Numbering
if ( mat . outerIndexPtr ( ) [ 0 ] = = 1 )
{ // Convert to C-style numbering
int i ;
for ( i = 0 ; i < = mat . rows ( ) ; + + i )
- - mat . outerIndexPtr ( ) [ i ] ;
for ( i = 0 ; i < mat . nonZeros ( ) ; + + i )
- - mat . innerIndexPtr ( ) [ i ] ;
}
}
}
// This is the base class to interface with PaStiX functions.
// Users should not used this class directly.
template < class Derived >
2012-06-12 16:47:14 +02:00
class PastixBase : internal : : noncopyable
2012-03-08 18:59:08 +01:00
{
public :
typedef typename internal : : pastix_traits < Derived > : : MatrixType _MatrixType ;
typedef _MatrixType MatrixType ;
typedef typename MatrixType : : Scalar Scalar ;
typedef typename MatrixType : : RealScalar RealScalar ;
typedef typename MatrixType : : Index Index ;
typedef Matrix < Scalar , Dynamic , 1 > Vector ;
2012-06-12 16:47:14 +02:00
typedef SparseMatrix < Scalar , ColMajor > ColSpMatrix ;
2012-03-08 18:59:08 +01:00
public :
2012-06-12 16:47:14 +02:00
PastixBase ( ) : m_initisOk ( false ) , m_analysisIsOk ( false ) , m_factorizationIsOk ( false ) , m_isInitialized ( false ) , m_pastixdata ( 0 ) , m_size ( 0 )
2012-03-08 18:59:08 +01:00
{
2012-06-12 16:47:14 +02:00
init ( ) ;
2012-03-08 18:59:08 +01:00
}
~ PastixBase ( )
{
2012-06-12 16:47:14 +02:00
clean ( ) ;
2012-03-08 18:59:08 +01:00
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
*
* \ sa compute ( )
*/
template < typename Rhs >
inline const internal : : solve_retval < PastixBase , Rhs >
solve ( const MatrixBase < Rhs > & b ) const
{
eigen_assert ( m_isInitialized & & " Pastix solver is not initialized. " ) ;
eigen_assert ( rows ( ) = = b . rows ( )
& & " PastixBase::solve(): invalid number of rows of the right hand side matrix b " ) ;
return internal : : solve_retval < PastixBase , Rhs > ( * this , b . derived ( ) ) ;
}
template < typename Rhs , typename Dest >
bool _solve ( const MatrixBase < Rhs > & b , MatrixBase < Dest > & x ) const ;
/** \internal */
template < typename Rhs , typename DestScalar , int DestOptions , typename DestIndex >
void _solve_sparse ( const Rhs & b , SparseMatrix < DestScalar , DestOptions , DestIndex > & dest ) const
{
eigen_assert ( m_factorizationIsOk & & " The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric() " ) ;
eigen_assert ( rows ( ) = = b . rows ( ) ) ;
// we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
static const int NbColsAtOnce = 1 ;
int rhsCols = b . cols ( ) ;
int size = b . rows ( ) ;
Eigen : : Matrix < DestScalar , Dynamic , Dynamic > tmp ( size , rhsCols ) ;
for ( int k = 0 ; k < rhsCols ; k + = NbColsAtOnce )
{
int actualCols = std : : min < int > ( rhsCols - k , NbColsAtOnce ) ;
tmp . leftCols ( actualCols ) = b . middleCols ( k , actualCols ) ;
tmp . leftCols ( actualCols ) = derived ( ) . solve ( tmp . leftCols ( actualCols ) ) ;
dest . middleCols ( k , actualCols ) = tmp . leftCols ( actualCols ) . sparseView ( ) ;
}
}
Derived & derived ( )
{
return * static_cast < Derived * > ( this ) ;
}
const Derived & derived ( ) const
{
return * static_cast < const Derived * > ( this ) ;
}
/** Returns a reference to the integer vector IPARM of PaStiX parameters
* to modify the default parameters .
* The statistics related to the different phases of factorization and solve are saved here as well
* \ sa analyzePattern ( ) factorize ( )
*/
Array < Index , IPARM_SIZE , 1 > & iparm ( )
{
return m_iparm ;
}
2012-03-22 15:54:52 +01:00
/** Return a reference to a particular index parameter of the IPARM vector
* \ sa iparm ( )
*/
int & iparm ( int idxparam )
{
return m_iparm ( idxparam ) ;
}
2012-03-08 18:59:08 +01:00
/** Returns a reference to the double vector DPARM of PaStiX parameters
* The statistics related to the different phases of factorization and solve are saved here as well
* \ sa analyzePattern ( ) factorize ( )
*/
Array < RealScalar , IPARM_SIZE , 1 > & dparm ( )
{
return m_dparm ;
}
2012-03-22 15:54:52 +01:00
/** Return a reference to a particular index parameter of the DPARM vector
* \ sa dparm ( )
*/
double & dparm ( int idxparam )
{
return m_dparm ( idxparam ) ;
}
2012-03-08 18:59:08 +01:00
inline Index cols ( ) const { return m_size ; }
inline Index rows ( ) const { return m_size ; }
/** \brief Reports whether previous computation was successful.
*
* \ returns \ c Success if computation was succesful ,
* \ c NumericalIssue if the PaStiX reports a problem
* \ c InvalidInput if the input matrix is invalid
*
* \ sa iparm ( )
*/
ComputationInfo info ( ) const
{
eigen_assert ( m_isInitialized & & " Decomposition is not initialized. " ) ;
return m_info ;
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
*
* \ sa compute ( )
*/
template < typename Rhs >
inline const internal : : sparse_solve_retval < PastixBase , Rhs >
solve ( const SparseMatrixBase < Rhs > & b ) const
{
eigen_assert ( m_isInitialized & & " Pastix LU, LLT or LDLT is not initialized. " ) ;
eigen_assert ( rows ( ) = = b . rows ( )
& & " PastixBase::solve(): invalid number of rows of the right hand side matrix b " ) ;
return internal : : sparse_solve_retval < PastixBase , Rhs > ( * this , b . derived ( ) ) ;
}
protected :
2012-06-12 16:47:14 +02:00
// Initialize the Pastix data structure, check the matrix
void init ( ) ;
// Compute the ordering and the symbolic factorization
void analyzePattern ( ColSpMatrix & mat ) ;
// Compute the numerical factorization
void factorize ( ColSpMatrix & mat ) ;
2012-03-08 18:59:08 +01:00
// Free all the data allocated by Pastix
2012-06-12 16:47:14 +02:00
void clean ( )
2012-03-08 18:59:08 +01:00
{
eigen_assert ( m_initisOk & & " The Pastix structure should be allocated first " ) ;
m_iparm ( IPARM_START_TASK ) = API_TASK_CLEAN ;
m_iparm ( IPARM_END_TASK ) = API_TASK_CLEAN ;
2012-06-12 16:47:14 +02:00
internal : : eigen_pastix ( & m_pastixdata , MPI_COMM_WORLD , 0 , 0 , 0 , ( Scalar * ) 0 ,
m_perm . data ( ) , m_invp . data ( ) , 0 , 0 , m_iparm . data ( ) , m_dparm . data ( ) ) ;
2012-03-08 18:59:08 +01:00
}
2012-06-12 16:47:14 +02:00
void compute ( ColSpMatrix & mat ) ;
2012-03-08 18:59:08 +01:00
int m_initisOk ;
int m_analysisIsOk ;
int m_factorizationIsOk ;
bool m_isInitialized ;
2012-03-22 15:54:52 +01:00
mutable ComputationInfo m_info ;
2012-03-08 18:59:08 +01:00
mutable pastix_data_t * m_pastixdata ; // Data structure for pastix
mutable int m_comm ; // The MPI communicator identifier
2012-06-12 16:47:14 +02:00
mutable Matrix < int , IPARM_SIZE , 1 > m_iparm ; // integer vector for the input parameters
2012-03-08 18:59:08 +01:00
mutable Matrix < double , DPARM_SIZE , 1 > m_dparm ; // Scalar vector for the input parameters
mutable Matrix < Index , Dynamic , 1 > m_perm ; // Permutation vector
mutable Matrix < Index , Dynamic , 1 > m_invp ; // Inverse permutation vector
mutable int m_size ; // Size of the matrix
} ;
/** Initialize the PaStiX data structure.
* A first call to this function fills iparm and dparm with the default PaStiX parameters
* \ sa iparm ( ) dparm ( )
*/
template < class Derived >
2012-06-12 16:47:14 +02:00
void PastixBase < Derived > : : init ( )
2012-03-08 18:59:08 +01:00
{
m_size = 0 ;
2012-06-12 16:47:14 +02:00
m_iparm . setZero ( IPARM_SIZE ) ;
m_dparm . setZero ( DPARM_SIZE ) ;
2012-03-08 18:59:08 +01:00
m_iparm ( IPARM_MODIFY_PARAMETER ) = API_NO ;
2012-06-12 16:47:14 +02:00
pastix ( & m_pastixdata , MPI_COMM_WORLD ,
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 1 , m_iparm . data ( ) , m_dparm . data ( ) ) ;
2012-03-08 18:59:08 +01:00
2012-06-12 16:47:14 +02:00
m_iparm [ IPARM_MATRIX_VERIFICATION ] = API_NO ;
m_iparm [ IPARM_VERBOSE ] = 2 ;
m_iparm [ IPARM_ORDERING ] = API_ORDER_SCOTCH ;
m_iparm [ IPARM_INCOMPLETE ] = API_NO ;
m_iparm [ IPARM_OOC_LIMIT ] = 2000 ;
m_iparm [ IPARM_RHS_MAKING ] = API_RHS_B ;
2012-03-08 18:59:08 +01:00
m_iparm ( IPARM_MATRIX_VERIFICATION ) = API_NO ;
2012-06-12 16:47:14 +02:00
m_iparm ( IPARM_START_TASK ) = API_TASK_INIT ;
m_iparm ( IPARM_END_TASK ) = API_TASK_INIT ;
internal : : eigen_pastix ( & m_pastixdata , MPI_COMM_WORLD , 0 , 0 , 0 , ( Scalar * ) 0 ,
0 , 0 , 0 , 0 , m_iparm . data ( ) , m_dparm . data ( ) ) ;
2012-03-08 18:59:08 +01:00
// Check the returned error
if ( m_iparm ( IPARM_ERROR_NUMBER ) ) {
m_info = InvalidInput ;
m_initisOk = false ;
}
else {
m_info = Success ;
m_initisOk = true ;
}
}
template < class Derived >
2012-06-12 16:47:14 +02:00
void PastixBase < Derived > : : compute ( ColSpMatrix & mat )
2012-03-08 18:59:08 +01:00
{
eigen_assert ( mat . rows ( ) = = mat . cols ( ) & & " The input matrix should be squared " ) ;
2012-06-12 16:47:14 +02:00
analyzePattern ( mat ) ;
2012-03-08 18:59:08 +01:00
factorize ( mat ) ;
2012-06-12 16:47:14 +02:00
m_iparm ( IPARM_MATRIX_VERIFICATION ) = API_NO ;
m_isInitialized = m_factorizationIsOk ;
2012-03-08 18:59:08 +01:00
}
template < class Derived >
2012-06-12 16:47:14 +02:00
void PastixBase < Derived > : : analyzePattern ( ColSpMatrix & mat )
{
eigen_assert ( m_initisOk & & " The initialization of PaSTiX failed " ) ;
// clean previous calls
if ( m_size > 0 )
clean ( ) ;
2012-03-08 18:59:08 +01:00
m_size = mat . rows ( ) ;
m_perm . resize ( m_size ) ;
m_invp . resize ( m_size ) ;
m_iparm ( IPARM_START_TASK ) = API_TASK_ORDERING ;
m_iparm ( IPARM_END_TASK ) = API_TASK_ANALYSE ;
internal : : eigen_pastix ( & m_pastixdata , MPI_COMM_WORLD , m_size , mat . outerIndexPtr ( ) , mat . innerIndexPtr ( ) ,
2012-06-12 16:47:14 +02:00
mat . valuePtr ( ) , m_perm . data ( ) , m_invp . data ( ) , 0 , 0 , m_iparm . data ( ) , m_dparm . data ( ) ) ;
2012-03-08 18:59:08 +01:00
// Check the returned error
2012-06-12 16:47:14 +02:00
if ( m_iparm ( IPARM_ERROR_NUMBER ) )
{
2012-03-08 18:59:08 +01:00
m_info = NumericalIssue ;
m_analysisIsOk = false ;
}
2012-06-12 16:47:14 +02:00
else
{
2012-03-08 18:59:08 +01:00
m_info = Success ;
m_analysisIsOk = true ;
}
}
template < class Derived >
2012-06-12 16:47:14 +02:00
void PastixBase < Derived > : : factorize ( ColSpMatrix & mat )
2012-03-08 18:59:08 +01:00
{
2012-06-12 16:47:14 +02:00
// if(&m_cpyMat != &mat) m_cpyMat = mat;
2012-03-08 18:59:08 +01:00
eigen_assert ( m_analysisIsOk & & " The analysis phase should be called before the factorization phase " ) ;
m_iparm ( IPARM_START_TASK ) = API_TASK_NUMFACT ;
m_iparm ( IPARM_END_TASK ) = API_TASK_NUMFACT ;
m_size = mat . rows ( ) ;
internal : : eigen_pastix ( & m_pastixdata , MPI_COMM_WORLD , m_size , mat . outerIndexPtr ( ) , mat . innerIndexPtr ( ) ,
2012-06-12 16:47:14 +02:00
mat . valuePtr ( ) , m_perm . data ( ) , m_invp . data ( ) , 0 , 0 , m_iparm . data ( ) , m_dparm . data ( ) ) ;
2012-03-08 18:59:08 +01:00
// Check the returned error
2012-06-12 16:47:14 +02:00
if ( m_iparm ( IPARM_ERROR_NUMBER ) )
{
2012-03-08 18:59:08 +01:00
m_info = NumericalIssue ;
m_factorizationIsOk = false ;
m_isInitialized = false ;
}
2012-06-12 16:47:14 +02:00
else
{
2012-03-08 18:59:08 +01:00
m_info = Success ;
m_factorizationIsOk = true ;
m_isInitialized = true ;
}
}
/* Solve the system */
template < typename Base >
template < typename Rhs , typename Dest >
bool PastixBase < Base > : : _solve ( const MatrixBase < Rhs > & b , MatrixBase < Dest > & x ) const
{
eigen_assert ( m_isInitialized & & " The matrix should be factorized first " ) ;
EIGEN_STATIC_ASSERT ( ( Dest : : Flags & RowMajorBit ) = = 0 ,
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES ) ;
int rhs = 1 ;
x = b ; /* on return, x is overwritten by the computed solution */
for ( int i = 0 ; i < b . cols ( ) ; i + + ) {
2012-06-12 16:47:14 +02:00
m_iparm [ IPARM_START_TASK ] = API_TASK_SOLVE ;
m_iparm [ IPARM_END_TASK ] = API_TASK_REFINE ;
internal : : eigen_pastix ( & m_pastixdata , MPI_COMM_WORLD , x . rows ( ) , 0 , 0 , 0 ,
m_perm . data ( ) , m_invp . data ( ) , & x ( 0 , i ) , rhs , m_iparm . data ( ) , m_dparm . data ( ) ) ;
2012-03-08 18:59:08 +01:00
}
2012-06-12 16:47:14 +02:00
2012-03-08 18:59:08 +01:00
// Check the returned error
2012-06-12 16:47:14 +02:00
m_info = m_iparm ( IPARM_ERROR_NUMBER ) = = 0 ? Success : NumericalIssue ;
return m_iparm ( IPARM_ERROR_NUMBER ) = = 0 ;
2012-03-08 18:59:08 +01:00
}
/** \ingroup PaStiXSupport_Module
* \ class PastixLU
* \ brief Sparse direct LU solver based on PaStiX library
*
* This class is used to solve the linear systems A . X = B with a supernodal LU
* factorization in the PaStiX library . The matrix A should be squared and nonsingular
* PaStiX requires that the matrix A has a symmetric structural pattern .
* This interface can symmetrize the input matrix otherwise .
* The vectors or matrices X and B can be either dense or sparse .
*
* \ tparam _MatrixType the type of the sparse matrix A , it must be a SparseMatrix < >
* \ tparam IsStrSym Indicates if the input matrix has a symmetric pattern , default is false
* NOTE : Note that if the analysis and factorization phase are called separately ,
* the input matrix will be symmetrized at each call , hence it is advised to
* symmetrize the matrix in a end - user program and set \ p IsStrSym to true
*
* \ sa \ ref TutorialSparseDirectSolvers
*
*/
template < typename _MatrixType , bool IsStrSym >
class PastixLU : public PastixBase < PastixLU < _MatrixType > >
{
public :
typedef _MatrixType MatrixType ;
typedef PastixBase < PastixLU < MatrixType > > Base ;
2012-06-12 16:47:14 +02:00
typedef typename Base : : ColSpMatrix ColSpMatrix ;
typedef typename MatrixType : : Index Index ;
2012-03-08 18:59:08 +01:00
public :
2012-06-12 16:47:14 +02:00
PastixLU ( ) : Base ( )
{
init ( ) ;
}
2012-03-08 18:59:08 +01:00
PastixLU ( const MatrixType & matrix ) : Base ( )
{
2012-06-12 16:47:14 +02:00
init ( ) ;
2012-03-08 18:59:08 +01:00
compute ( matrix ) ;
}
/** Compute the LU supernodal factorization of \p matrix.
* iparm and dparm can be used to tune the PaStiX parameters .
* see the PaStiX user ' s manual
* \ sa analyzePattern ( ) factorize ( )
*/
void compute ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
m_structureIsUptodate = false ;
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : compute ( temp ) ;
}
/** Compute the LU symbolic factorization of \p matrix using its sparsity pattern.
* Several ordering methods can be used at this step . See the PaStiX user ' s manual .
* The result of this operation can be used with successive matrices having the same pattern as \ p matrix
* \ sa factorize ( )
*/
void analyzePattern ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
m_structureIsUptodate = false ;
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : analyzePattern ( temp ) ;
}
/** Compute the LU supernodal factorization of \p matrix
* WARNING The matrix \ p matrix should have the same structural pattern
* as the same used in the analysis phase .
* \ sa analyzePattern ( )
*/
void factorize ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : factorize ( temp ) ;
}
protected :
2012-06-12 16:47:14 +02:00
void init ( )
{
m_structureIsUptodate = false ;
m_iparm ( IPARM_SYM ) = API_SYM_NO ;
m_iparm ( IPARM_FACTORIZATION ) = API_FACT_LU ;
}
void grabMatrix ( const MatrixType & matrix , ColSpMatrix & out )
{
if ( IsStrSym )
out = matrix ;
else
{
if ( ! m_structureIsUptodate )
{
// update the transposed structure
m_transposedStructure = matrix . transpose ( ) ;
// Set the elements of the matrix to zero
for ( Index j = 0 ; j < m_transposedStructure . outerSize ( ) ; + + j )
for ( typename ColSpMatrix : : InnerIterator it ( m_transposedStructure , j ) ; it ; + + it )
it . valueRef ( ) = 0.0 ;
m_structureIsUptodate = true ;
}
out = m_transposedStructure + matrix ;
}
internal : : c_to_fortran_numbering ( out ) ;
}
2012-03-08 18:59:08 +01:00
using Base : : m_iparm ;
using Base : : m_dparm ;
2012-03-29 19:19:12 +02:00
2012-06-12 16:47:14 +02:00
ColSpMatrix m_transposedStructure ;
bool m_structureIsUptodate ;
2012-03-08 18:59:08 +01:00
} ;
/** \ingroup PaStiXSupport_Module
* \ class PastixLLT
* \ brief A sparse direct supernodal Cholesky ( LLT ) factorization and solver based on the PaStiX library
*
* This class is used to solve the linear systems A . X = B via a LL ^ T supernodal Cholesky factorization
* available in the PaStiX library . The matrix A should be symmetric and positive definite
* WARNING Selfadjoint complex matrices are not supported in the current version of PaStiX
* The vectors or matrices X and B can be either dense or sparse
*
* \ tparam MatrixType the type of the sparse matrix A , it must be a SparseMatrix < >
* \ tparam UpLo The part of the matrix to use : Lower or Upper . The default is Lower as required by PaStiX
*
* \ sa \ ref TutorialSparseDirectSolvers
*/
template < typename _MatrixType , int _UpLo >
class PastixLLT : public PastixBase < PastixLLT < _MatrixType , _UpLo > >
{
public :
typedef _MatrixType MatrixType ;
typedef PastixBase < PastixLLT < MatrixType , _UpLo > > Base ;
2012-06-12 16:47:14 +02:00
typedef typename Base : : ColSpMatrix ColSpMatrix ;
2012-03-08 18:59:08 +01:00
public :
enum { UpLo = _UpLo } ;
2012-06-12 16:47:14 +02:00
PastixLLT ( ) : Base ( )
{
init ( ) ;
}
2012-03-08 18:59:08 +01:00
PastixLLT ( const MatrixType & matrix ) : Base ( )
{
2012-06-12 16:47:14 +02:00
init ( ) ;
2012-03-08 18:59:08 +01:00
compute ( matrix ) ;
}
/** Compute the L factor of the LL^T supernodal factorization of \p matrix
* \ sa analyzePattern ( ) factorize ( )
*/
void compute ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : compute ( temp ) ;
}
/** Compute the LL^T symbolic factorization of \p matrix using its sparsity pattern
* The result of this operation can be used with successive matrices having the same pattern as \ p matrix
* \ sa factorize ( )
*/
void analyzePattern ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : analyzePattern ( temp ) ;
}
/** Compute the LL^T supernodal numerical factorization of \p matrix
* \ sa analyzePattern ( )
*/
void factorize ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : factorize ( temp ) ;
}
protected :
using Base : : m_iparm ;
2012-03-29 19:19:12 +02:00
2012-06-12 16:47:14 +02:00
void init ( )
{
m_iparm ( IPARM_SYM ) = API_SYM_YES ;
m_iparm ( IPARM_FACTORIZATION ) = API_FACT_LLT ;
}
void grabMatrix ( const MatrixType & matrix , ColSpMatrix & out )
{
// Pastix supports only lower, column-major matrices
out . template selfadjointView < Lower > ( ) = matrix . template selfadjointView < UpLo > ( ) ;
internal : : c_to_fortran_numbering ( out ) ;
}
2012-03-08 18:59:08 +01:00
} ;
/** \ingroup PaStiXSupport_Module
* \ class PastixLDLT
* \ brief A sparse direct supernodal Cholesky ( LLT ) factorization and solver based on the PaStiX library
*
* This class is used to solve the linear systems A . X = B via a LDL ^ T supernodal Cholesky factorization
* available in the PaStiX library . The matrix A should be symmetric and positive definite
* WARNING Selfadjoint complex matrices are not supported in the current version of PaStiX
* The vectors or matrices X and B can be either dense or sparse
*
* \ tparam MatrixType the type of the sparse matrix A , it must be a SparseMatrix < >
* \ tparam UpLo The part of the matrix to use : Lower or Upper . The default is Lower as required by PaStiX
*
* \ sa \ ref TutorialSparseDirectSolvers
*/
template < typename _MatrixType , int _UpLo >
class PastixLDLT : public PastixBase < PastixLDLT < _MatrixType , _UpLo > >
{
2012-06-12 16:47:14 +02:00
public :
2012-03-08 18:59:08 +01:00
typedef _MatrixType MatrixType ;
typedef PastixBase < PastixLDLT < MatrixType , _UpLo > > Base ;
2012-06-12 16:47:14 +02:00
typedef typename Base : : ColSpMatrix ColSpMatrix ;
2012-03-08 18:59:08 +01:00
public :
enum { UpLo = _UpLo } ;
2012-06-12 16:47:14 +02:00
PastixLDLT ( ) : Base ( )
{
init ( ) ;
}
2012-03-08 18:59:08 +01:00
PastixLDLT ( const MatrixType & matrix ) : Base ( )
{
2012-06-12 16:47:14 +02:00
init ( ) ;
2012-03-08 18:59:08 +01:00
compute ( matrix ) ;
}
/** Compute the L and D factors of the LDL^T factorization of \p matrix
* \ sa analyzePattern ( ) factorize ( )
*/
void compute ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : compute ( temp ) ;
}
/** Compute the LDL^T symbolic factorization of \p matrix using its sparsity pattern
* The result of this operation can be used with successive matrices having the same pattern as \ p matrix
* \ sa factorize ( )
*/
void analyzePattern ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : analyzePattern ( temp ) ;
}
/** Compute the LDL^T supernodal numerical factorization of \p matrix
*
*/
void factorize ( const MatrixType & matrix )
{
2012-06-12 16:47:14 +02:00
ColSpMatrix temp ;
grabMatrix ( matrix , temp ) ;
2012-03-08 18:59:08 +01:00
Base : : factorize ( temp ) ;
}
protected :
using Base : : m_iparm ;
2012-03-29 19:19:12 +02:00
2012-06-12 16:47:14 +02:00
void init ( )
{
m_iparm ( IPARM_SYM ) = API_SYM_YES ;
m_iparm ( IPARM_FACTORIZATION ) = API_FACT_LDLT ;
}
void grabMatrix ( const MatrixType & matrix , ColSpMatrix & out )
{
// Pastix supports only lower, column-major matrices
out . template selfadjointView < Lower > ( ) = matrix . template selfadjointView < UpLo > ( ) ;
internal : : c_to_fortran_numbering ( out ) ;
}
2012-03-08 18:59:08 +01:00
} ;
namespace internal {
template < typename _MatrixType , typename Rhs >
struct solve_retval < PastixBase < _MatrixType > , Rhs >
: solve_retval_base < PastixBase < _MatrixType > , Rhs >
{
typedef PastixBase < _MatrixType > Dec ;
EIGEN_MAKE_SOLVE_HELPERS ( Dec , Rhs )
template < typename Dest > void evalTo ( Dest & dst ) const
{
dec ( ) . _solve ( rhs ( ) , dst ) ;
}
} ;
template < typename _MatrixType , typename Rhs >
struct sparse_solve_retval < PastixBase < _MatrixType > , Rhs >
: sparse_solve_retval_base < PastixBase < _MatrixType > , Rhs >
{
typedef PastixBase < _MatrixType > Dec ;
EIGEN_MAKE_SPARSE_SOLVE_HELPERS ( Dec , Rhs )
template < typename Dest > void evalTo ( Dest & dst ) const
{
dec ( ) . _solve_sparse ( rhs ( ) , dst ) ;
}
} ;
2012-04-15 11:06:28 +01:00
} // end namespace internal
} // end namespace Eigen
2012-03-08 18:59:08 +01:00
# endif