/* *************************************************************************/ /* File: superluinverse.cpp */ /* Author: Florian Bachinger */ /* Date: Feb. 2004 */ /* *************************************************************************/ #include #ifdef USE_SUPERLU namespace ngla { using namespace ngla; using namespace ngstd; using namespace double_superlu; using namespace complex_superlu; template int NumRows(TM entry) { return entry.Height(); } int NumRows(double entry) { return 1; } int NumRows(Complex entry) { return 1; } template int NumCols(TM entry) { return entry.Width(); } int NumCols(double entry) { return 1; } int NumCols(Complex entry) { return 1; } template typename TM::TSCAL Elem(TM entry, int i, int j) { return entry(i,j); } double Elem (double entry, int i, int j) { return entry; } Complex Elem (Complex entry, int i, int j) { return entry; } template int IsComplex(TM entry) { return ( sizeof( Elem(entry,0,0) ) == sizeof( Complex ) ); } template SuperLUInverse :: SuperLUInverse (const SparseMatrix & a, const BitArray * ainner, const ARRAY * acluster, int asymmetric) { // (*testout) << "matrix = " << a << endl; symmetric = asymmetric; inner = ainner; cluster = acluster; if ( inner && inner->Size() < a.Height() || cluster && cluster->Size() < a.Height() ) { cout << "PardisoInverse: Size of inner/cluster does not match matrix size!" << endl; throw Exception("Invalid parameters inner/cluster. Thrown by PardisoInverse."); } clock_t starttime, time1, time2; starttime = clock(); // prepare matrix and parameters for SuperLU TM entry = a(0,0); if ( NumRows(entry) != NumCols(entry) ) { cout << "SuperLU: Each entry in the square matrix has to be a square matrix!" << endl; throw Exception("No Square Matrix. Thrown by SuperLUInverse."); } entrysize = NumRows(entry); iscomplex = IsComplex(entry); height = a.Height() * entrysize; colstart = new int[height+1]; int * counter = new int[height]; int i, j, k, l; int col; for ( i=0; iTest(i-1) && inner->Test(col) ) ) || (!inner && cluster && ((*cluster)[i-1] == (*cluster)[col] && (*cluster)[i-1] )) ) { for ( k=0; kTest(i) && inner->Test(col) ) ) || (!inner && cluster && ((*cluster)[i] == (*cluster)[col] && (*cluster)[i] )) ) { entry = a(i,col); for ( k=0; kTest(i-1) && inner->Test(col) ) ) || (!inner && cluster && ((*cluster)[i-1] == (*cluster)[col] && (*cluster)[i-1] )) ) { for ( k=0; kTest(i) && inner->Test(col) ) ) || (!inner && cluster && ((*cluster)[i] == (*cluster)[col] && (*cluster)[i] )) ) { entry = a(i,col); for ( k=0; k(matrix), indices, colstart, SLU_NC, SLU_Z, SLU_GE); zCreate_Dense_Matrix(&B, height, 1, reinterpret_cast(rhs), height, SLU_DN, SLU_Z, SLU_GE); zgssv( &options, &A, perm_c, perm_r, &L, &U, &B, &stat, &error ); } else { dCreate_CompCol_Matrix(&A, height, height, nze, reinterpret_cast(matrix), indices, colstart, SLU_NC, SLU_D, SLU_GE); dCreate_Dense_Matrix(&B, height, 1, reinterpret_cast(rhs), height, SLU_DN, SLU_D, SLU_GE); dgssv( &options, &A, perm_c, perm_r, &L, &U, &B, &stat, &error ); } time2 = clock(); if ( error != 0 ) { cout << "Setup and Factorization: SuperLU returned error " << error << "!" << endl; throw Exception("SuperLUInverse: Setup and Factorization failed."); } (*testout) << endl << "Direct Solver: SuperLU by Lawrence Berkeley National Laboratory." << endl; (*testout) << "Matrix prepared for SuperLU in " << double(time1 - starttime)/CLOCKS_PER_SEC << " sec." << endl; (*testout) << "Factorization by SuperLU done in " << double(time2 - time1)/CLOCKS_PER_SEC << " sec." << endl << endl; delete [] counter; delete [] rhs; } template SuperLUInverse :: SuperLUInverse (const ARRAY & aorder, const ARRAY & cliques, const ARRAY & vertices, int symmetric) { Allocate (aorder, cliques, vertices); } template void SuperLUInverse :: Allocate (const ARRAY & aorder, const ARRAY & cliques, const ARRAY & vertices) { cout << "SuperLUInverse::Allocate not implemented!" << endl; } template void SuperLUInverse :: FactorNew (const SparseMatrix & a) { throw Exception ("SuperLUInverse::FactorNew not implemented"); } template void SuperLUInverse :: Factor (const int * blocknr) { cout << "SuperLUInverse::Factor not implemented!" << endl; } template void SuperLUInverse :: Mult (const BaseVector & x, BaseVector & y) const { FlatVector fx = dynamic_cast &> (const_cast (x)).FV(); FlatVector fy = dynamic_cast &> (y).FV(); int error; fy = fx; if ( iscomplex ) { zCreate_Dense_Matrix(const_cast(&B), height, 1, static_cast(fy.Data()), height, SLU_DN, SLU_Z, SLU_GE); zgstrs( NOTRANS, const_cast(&L), const_cast(&U), perm_c, perm_r, const_cast(&B), const_cast(&stat), &error ); } else { dCreate_Dense_Matrix(const_cast(&B), height, 1, static_cast(fy.Data()), height, SLU_DN, SLU_D, SLU_GE); dgstrs( NOTRANS, const_cast(&L), const_cast(&U), perm_c, perm_r, const_cast(&B), const_cast(&stat), &error ); } if ( error != 0 ) cout << "Apply Inverse: SuperLU returned error " << error << "!" << endl; if (inner) { for (int i=0; iTest(i)) for (int j=0; j void SuperLUInverse :: Set (int i, int j, const TM & val) { cout << "SuperLUInverse::Set not implemented!" << endl; } template const TM & SuperLUInverse :: Get (int i, int j) const { cout << "SuperLUInverse::Get not implemented!" << endl; } template ostream & SuperLUInverse :: Print (ostream & ost) const { cout << "SuperLUInverse::Print not implemented!" << endl; return ost; } template SuperLUInverse :: ~SuperLUInverse() { // Destroy_CompCol_Matrix(&A); // Destroy_SuperMatrix_Store(&B); Destroy_SuperNode_Matrix(&L); Destroy_CompCol_Matrix(&U); StatFree(&stat); delete [] perm_c; delete [] perm_r; delete [] colstart; delete [] indices; delete [] matrix; } template class SuperLUInverse; template class SuperLUInverse; #if MAX_SYS_DIM >= 1 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 2 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 3 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 4 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 5 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 6 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 7 template class SuperLUInverse >; template class SuperLUInverse >; #endif #if MAX_SYS_DIM >= 8 template class SuperLUInverse >; template class SuperLUInverse >; #endif } #endif