//============================================================================= // // See also pre and post conditions in Amesos_Klu.h // Preconditions: // firsttime specifies that this is the first time that // ConertToKluCrs has been called, i.e. in symbolic factorization. // No data allocation should happen unless firsttime=true. // SerialMatrix_ points to the matrix to be factored and solved // NumGlobalElements_ has been set to the dimension of the matrix // numentries_ has been set to the number of non-zeros in the matrix // (i.e. CreateLocalMatrixAndExporters() has been callded) // // Postconditions: // Ap, VecAi, VecAval contain the matrix as Klu needs it // // int Amesos_Klu::ConvertToKluCRS(bool firsttime) { ResetTimer(0); // // Convert matrix to the form that Klu expects (Ap, VecAi, VecAval) // if (MyPID_==0) { assert( NumGlobalElements_ == SerialMatrix_->NumGlobalRows()); assert( NumGlobalElements_ == SerialMatrix_->NumGlobalCols()); if ( ! AddZeroToDiag_ ) { assert( numentries_ == SerialMatrix_->NumGlobalNonzeros()) ; } else { numentries_ = SerialMatrix_->NumGlobalNonzeros() ; } Epetra_CrsMatrix *CrsMatrix = dynamic_cast<Epetra_CrsMatrix *>(SerialMatrix_); bool StorageOptimized = ( CrsMatrix != 0 && CrsMatrix->StorageOptimized() ); if ( AddToDiag_ != 0.0 ) StorageOptimized = false ; if ( firsttime ) { Ap.resize( NumGlobalElements_+1 ); if ( ! StorageOptimized ) { VecAi.resize( EPETRA_MAX( NumGlobalElements_, numentries_) ) ; VecAval.resize( EPETRA_MAX( NumGlobalElements_, numentries_) ) ; Ai = &VecAi[0]; Aval = &VecAval[0]; } } double *RowValues; int *ColIndices; int NumEntriesThisRow; if( StorageOptimized ) { if ( firsttime ) { Ap[0] = 0; for ( int MyRow = 0; MyRow <NumGlobalElements_; MyRow++ ) { if( CrsMatrix-> ExtractMyRowView( MyRow, NumEntriesThisRow, RowValues, ColIndices ) != 0 ) AMESOS_CHK_ERR( -10 ); if ( MyRow == 0 ) { Ai = ColIndices ; Aval = RowValues ; } Ap[MyRow+1] = Ap[MyRow] + NumEntriesThisRow ; } } } else { int Ai_index = 0 ; int MyRow; int MaxNumEntries_ = SerialMatrix_->MaxNumEntries(); if ( firsttime && CrsMatrix == 0 ) { ColIndicesV_.resize(MaxNumEntries_); RowValuesV_.resize(MaxNumEntries_); } for ( MyRow = 0; MyRow <NumGlobalElements_; MyRow++ ) { if ( CrsMatrix != 0 ) { if( CrsMatrix-> ExtractMyRowView( MyRow, NumEntriesThisRow, RowValues, ColIndices ) != 0 ) AMESOS_CHK_ERR( -11 ); } else { if( SerialMatrix_-> ExtractMyRowCopy( MyRow, MaxNumEntries_, NumEntriesThisRow, &RowValuesV_[0], &ColIndicesV_[0] ) != 0 ) AMESOS_CHK_ERR( -12 ); RowValues = &RowValuesV_[0]; ColIndices = &ColIndicesV_[0]; } if ( firsttime ) { Ap[MyRow] = Ai_index ; for ( int j = 0; j < NumEntriesThisRow; j++ ) { VecAi[Ai_index] = ColIndices[j] ; // assert( VecAi[Ai_index] == Ai[Ai_index] ) ; VecAval[Ai_index] = RowValues[j] ; // We have to do this because of the hacks to get aroun bug #1502 if (ColIndices[j] == MyRow) { VecAval[Ai_index] += AddToDiag_; } Ai_index++; } } else { for ( int j = 0; j < NumEntriesThisRow; j++ ) { VecAval[Ai_index] = RowValues[j] ; if (ColIndices[j] == MyRow) { VecAval[Ai_index] += AddToDiag_; } Ai_index++; } } } Ap[MyRow] = Ai_index ; } } MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_, 0); return 0; }
bool CrsMatrixInfo( const Epetra_CrsMatrix & A, ostream & os ) { int MyPID = A.Comm().MyPID(); // take care that matrix is already trasformed bool IndicesAreGlobal = A.IndicesAreGlobal(); if( IndicesAreGlobal == true ) { if( MyPID == 0 ) { os << "WARNING : matrix must be transformed to local\n"; os << " before calling CrsMatrixInfo\n"; os << " Now returning...\n"; } return false; } int NumGlobalRows = A.NumGlobalRows(); int NumGlobalNonzeros = A.NumGlobalNonzeros(); int NumGlobalCols = A.NumGlobalCols(); double NormInf = A.NormInf(); double NormOne = A.NormOne(); int NumGlobalDiagonals = A.NumGlobalDiagonals(); int GlobalMaxNumEntries = A.GlobalMaxNumEntries(); int IndexBase = A.IndexBase(); bool StorageOptimized = A.StorageOptimized(); bool LowerTriangular = A.LowerTriangular(); bool UpperTriangular = A.UpperTriangular(); bool NoDiagonal = A.NoDiagonal(); // these variables identifies quantities I have to compute, // since not provided by Epetra_CrsMatrix double MyFrobeniusNorm( 0.0 ), FrobeniusNorm( 0.0 ); double MyMinElement( DBL_MAX ), MinElement( DBL_MAX ); double MyMaxElement( DBL_MIN ), MaxElement( DBL_MIN ); double MyMinAbsElement( DBL_MAX ), MinAbsElement( DBL_MAX ); double MyMaxAbsElement( 0.0 ), MaxAbsElement( 0.0 ); int NumMyRows = A.NumMyRows(); int * NzPerRow = new int[NumMyRows]; int Row; // iterator on rows int Col; // iterator on cols int MaxNumEntries = A.MaxNumEntries(); double * Values = new double[MaxNumEntries]; int * Indices = new int[MaxNumEntries]; double Element, AbsElement; // generic nonzero element and its abs value int NumEntries; double * Diagonal = new double [NumMyRows]; // SumOffDiagonal is the sum of absolute values for off-diagonals double * SumOffDiagonal = new double [NumMyRows]; for( Row=0 ; Row<NumMyRows ; ++Row ) { SumOffDiagonal[Row] = 0.0; } int * IsDiagonallyDominant = new int [NumMyRows]; int GlobalRow; // cycle over all matrix elements for( Row=0 ; Row<NumMyRows ; ++Row ) { GlobalRow = A.GRID(Row); NzPerRow[Row] = A.NumMyEntries(Row); A.ExtractMyRowCopy(Row,NzPerRow[Row],NumEntries,Values,Indices); for( Col=0 ; Col<NumEntries ; ++Col ) { Element = Values[Col]; AbsElement = abs(Element); if( Element<MyMinElement ) MyMinElement = Element; if( Element>MyMaxElement ) MyMaxElement = Element; if( AbsElement<MyMinAbsElement ) MyMinAbsElement = AbsElement; if( AbsElement>MyMaxAbsElement ) MyMaxAbsElement = AbsElement; if( Indices[Col] == Row ) Diagonal[Row] = Element; else SumOffDiagonal[Row] += abs(Element); MyFrobeniusNorm += pow(Element,2); } } // analise storage per row int MyMinNzPerRow( NumMyRows ), MinNzPerRow( NumMyRows ); int MyMaxNzPerRow( 0 ), MaxNzPerRow( 0 ); for( Row=0 ; Row<NumMyRows ; ++Row ) { if( NzPerRow[Row]<MyMinNzPerRow ) MyMinNzPerRow=NzPerRow[Row]; if( NzPerRow[Row]>MyMaxNzPerRow ) MyMaxNzPerRow=NzPerRow[Row]; } // a test to see if matrix is diagonally-dominant int MyDiagonalDominance( 0 ), DiagonalDominance( 0 ); int MyWeakDiagonalDominance( 0 ), WeakDiagonalDominance( 0 ); for( Row=0 ; Row<NumMyRows ; ++Row ) { if( abs(Diagonal[Row])>SumOffDiagonal[Row] ) ++MyDiagonalDominance; else if( abs(Diagonal[Row])==SumOffDiagonal[Row] ) ++MyWeakDiagonalDominance; } // reduction operations A.Comm().SumAll(&MyFrobeniusNorm, &FrobeniusNorm, 1); A.Comm().MinAll(&MyMinElement, &MinElement, 1); A.Comm().MaxAll(&MyMaxElement, &MaxElement, 1); A.Comm().MinAll(&MyMinAbsElement, &MinAbsElement, 1); A.Comm().MaxAll(&MyMaxAbsElement, &MaxAbsElement, 1); A.Comm().MinAll(&MyMinNzPerRow, &MinNzPerRow, 1); A.Comm().MaxAll(&MyMaxNzPerRow, &MaxNzPerRow, 1); A.Comm().SumAll(&MyDiagonalDominance, &DiagonalDominance, 1); A.Comm().SumAll(&MyWeakDiagonalDominance, &WeakDiagonalDominance, 1); // free memory delete Values; delete Indices; delete Diagonal; delete SumOffDiagonal; delete IsDiagonallyDominant; delete NzPerRow; // simply no output for MyPID>0, only proc 0 write on os if( MyPID != 0 ) return true; os << "*** general Information about the matrix\n"; os << "Number of Global Rows = " << NumGlobalRows << endl; os << "Number of Global Cols = " << NumGlobalCols << endl; os << "is the matrix square = " << ((NumGlobalRows==NumGlobalCols)?"yes":"no") << endl; os << "||A||_\\infty = " << NormInf << endl; os << "||A||_1 = " << NormOne << endl; os << "||A||_F = " << sqrt(FrobeniusNorm) << endl; os << "Number of nonzero diagonal entries = " << NumGlobalDiagonals << "( " << 1.0* NumGlobalDiagonals/NumGlobalRows*100 << " %)\n"; os << "Nonzero per row : min = " << MinNzPerRow << " average = " << 1.0*NumGlobalNonzeros/NumGlobalRows << " max = " << MaxNzPerRow << endl; os << "Maximum number of nonzero elements/row = " << GlobalMaxNumEntries << endl; os << "min( a_{i,j} ) = " << MinElement << endl; os << "max( a_{i,j} ) = " << MaxElement << endl; os << "min( abs(a_{i,j}) ) = " << MinAbsElement << endl; os << "max( abs(a_{i,j}) ) = " << MaxAbsElement << endl; os << "Number of diagonal dominant rows = " << DiagonalDominance << " (" << 100.0*DiagonalDominance/NumGlobalRows << " % of total)\n"; os << "Number of weakly diagonal dominant rows = " << WeakDiagonalDominance << " (" << 100.0*WeakDiagonalDominance/NumGlobalRows << " % of total)\n"; os << "*** Information about the Trilinos storage\n"; os << "Base Index = " << IndexBase << endl; os << "is storage optimized = " << ((StorageOptimized==true)?"yes":"no") << endl; os << "are indices global = " << ((IndicesAreGlobal==true)?"yes":"no") << endl; os << "is matrix lower triangular = " << ((LowerTriangular==true)?"yes":"no") << endl; os << "is matrix upper triangular = " << ((UpperTriangular==true)?"yes":"no") << endl; os << "are there diagonal entries = " << ((NoDiagonal==false)?"yes":"no") << endl; return true; }
//============================================================================= // // See also pre and post conditions in Amesos_Paraklete.h // Preconditions: // firsttime specifies that this is the first time that // ConertToParakleteCrs has been called, i.e. in symbolic factorization. // No data allocation should happen unless firsttime=true. // SerialMatrix_ points to the matrix to be factored and solved // NumGlobalElements_ has been set to the dimension of the matrix // numentries_ has been set to the number of non-zeros in the matrix // (i.e. CreateLocalMatrixAndExporters() has been callded) // // Postconditions: // pk_A_ contains the matrix as Paraklete needs it // // int Amesos_Paraklete::ConvertToParakleteCRS(bool firsttime) { ResetTimer(0); // // Convert matrix to the form that Klu expects (Ap, Ai, VecAval) // if (MyPID_==0) { assert( NumGlobalElements_ == SerialMatrix_->NumGlobalRows()); assert( NumGlobalElements_ == SerialMatrix_->NumGlobalCols()); if ( ! AddZeroToDiag_ ) { assert( numentries_ == SerialMatrix_->NumGlobalNonzeros()) ; } else { numentries_ = SerialMatrix_->NumGlobalNonzeros() ; } Epetra_CrsMatrix *CrsMatrix = dynamic_cast<Epetra_CrsMatrix *>(SerialMatrix_); bool StorageOptimized = ( CrsMatrix != 0 && CrsMatrix->StorageOptimized() ); if ( AddToDiag_ != 0.0 ) StorageOptimized = false ; if ( firsttime ) { Ap.resize( NumGlobalElements_+1 ); Ai.resize( EPETRA_MAX( NumGlobalElements_, numentries_) ) ; if ( ! StorageOptimized ) { VecAval.resize( EPETRA_MAX( NumGlobalElements_, numentries_) ) ; Aval = &VecAval[0]; } } double *RowValues; int *ColIndices; int NumEntriesThisRow; if( StorageOptimized ) { if ( firsttime ) { Ap[0] = 0; for ( int MyRow = 0; MyRow <NumGlobalElements_; MyRow++ ) { if( CrsMatrix-> ExtractMyRowView( MyRow, NumEntriesThisRow, RowValues, ColIndices ) != 0 ) AMESOS_CHK_ERR( -6 ); for ( int j=0; j < NumEntriesThisRow; j++ ) { Ai[Ap[MyRow]+j] = ColIndices[j]; } if ( MyRow == 0 ) { Aval = RowValues ; } Ap[MyRow+1] = Ap[MyRow] + NumEntriesThisRow ; } } } else { int Ai_index = 0 ; int MyRow; int MaxNumEntries_ = SerialMatrix_->MaxNumEntries(); if ( firsttime && CrsMatrix == 0 ) { ColIndicesV_.resize(MaxNumEntries_); RowValuesV_.resize(MaxNumEntries_); } for ( MyRow = 0; MyRow <NumGlobalElements_; MyRow++ ) { if ( CrsMatrix != 0 ) { if( CrsMatrix-> ExtractMyRowView( MyRow, NumEntriesThisRow, RowValues, ColIndices ) != 0 ) AMESOS_CHK_ERR( -6 ); } else { if( SerialMatrix_-> ExtractMyRowCopy( MyRow, MaxNumEntries_, NumEntriesThisRow, &RowValuesV_[0], &ColIndicesV_[0] ) != 0 ) AMESOS_CHK_ERR( -6 ); RowValues = &RowValuesV_[0]; ColIndices = &ColIndicesV_[0]; } if ( firsttime ) { Ap[MyRow] = Ai_index ; for ( int j = 0; j < NumEntriesThisRow; j++ ) { Ai[Ai_index] = ColIndices[j] ; // VecAval[Ai_index] = RowValues[j] ; // We have to do this because of the hacks to get around bug #1502 if (ColIndices[j] == MyRow) { VecAval[Ai_index] += AddToDiag_; } Ai_index++; } } else { for ( int j = 0; j < NumEntriesThisRow; j++ ) { VecAval[Ai_index] = RowValues[j] ; if (ColIndices[j] == MyRow) { VecAval[Ai_index] += AddToDiag_; } Ai_index++; } } } Ap[MyRow] = Ai_index ; } PrivateParakleteData_->pk_A_.nrow = NumGlobalElements_ ; cholmod_sparse& pk_A = PrivateParakleteData_->pk_A_ ; pk_A.nrow = NumGlobalElements_ ; pk_A.ncol = NumGlobalElements_ ; pk_A.nzmax = numentries_ ; pk_A.p = &Ap[0] ; pk_A.i = &Ai[0] ; pk_A.nz = 0; if ( firsttime ) { pk_A.x = 0 ; pk_A.xtype = CHOLMOD_PATTERN ; } else { pk_A.x = Aval ; pk_A.xtype = CHOLMOD_REAL ; } pk_A.z = 0 ; pk_A.stype = 0 ; // symmetric pk_A.itype = CHOLMOD_LONG ; pk_A.dtype = CHOLMOD_DOUBLE ; pk_A.sorted = 0 ; pk_A.packed = 1 ; } MtxConvTime_ = AddTime("Total matrix conversion time", MtxConvTime_, 0); return 0; }