int InitMatValues( const Epetra_CrsMatrix& newA, Epetra_CrsMatrix* A ) { int numMyRows = newA.NumMyRows(); int maxNum = newA.MaxNumEntries(); int numIn; int *idx = 0; double *vals = 0; idx = new int[maxNum]; vals = new double[maxNum]; // For each row get the values and indices, and replace the values in A. for (int i=0; i<numMyRows; ++i) { // Get the values and indices from newA. EPETRA_CHK_ERR( newA.ExtractMyRowCopy(i, maxNum, numIn, vals, idx) ); // Replace the values in A EPETRA_CHK_ERR( A->ReplaceMyValues(i, numIn, vals, idx) ); } // Clean up. delete [] idx; delete [] vals; 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; }
// // Diagonal: 0=no change, 1=eliminate entry // from the map for the largest row element in process 0 // 2=add diagonal entries to the matrix, with a zero value // (assume row map contains all diagonal entries). // // ReindexRowMap: // 0=no change, 1= add 2 (still contiguous), 2=non-contiguous // // ReindexColMap // 0=same as RowMap, 1=add 4 - Different From RowMap, but contiguous) // // RangeMap: // 0=no change, 1=serial map, 2=bizarre distribution, 3=replicated map // // DomainMap: // 0=no change, 1=serial map, 2=bizarre distribution, 3=replicated map // RCP<Epetra_CrsMatrix> NewMatNewMap(Epetra_CrsMatrix& In, int Diagonal, int ReindexRowMap, int ReindexColMap, int RangeMapType, int DomainMapType ) { // // If we are making no change, return the original matrix (which has a linear map) // #if 0 std::cout << __FILE__ << "::" << __LINE__ << " " << Diagonal << " " << ReindexRowMap << " " << ReindexColMap << " " << RangeMapType << " " << DomainMapType << " " << std::endl ; #endif if ( Diagonal + ReindexRowMap + ReindexColMap + RangeMapType + DomainMapType == 0 ) { RCP<Epetra_CrsMatrix> ReturnOrig = rcp( &In, false ); return ReturnOrig ; } // // Diagonal==2 is used for a different purpose - // Making sure that the diagonal of the matrix is non-empty. // Note: The diagonal must exist in In.RowMap(). // if ( Diagonal == 2 ) { assert( ReindexRowMap==0 && ReindexColMap == 0 ) ; } int (*RowPermute)(int in) = 0; int (*ColPermute)(int in) = 0; assert( Diagonal >= 0 && Diagonal <= 2 ); assert( ReindexRowMap>=0 && ReindexRowMap<=2 ); assert( ReindexColMap>=0 && ReindexColMap<=1 ); assert( RangeMapType>=0 && RangeMapType<=3 ); assert( DomainMapType>=0 && DomainMapType<=3 ); Epetra_Map DomainMap = In.DomainMap(); Epetra_Map RangeMap = In.RangeMap(); Epetra_Map ColMap = In.ColMap(); Epetra_Map RowMap = In.RowMap(); int NumMyRowElements = RowMap.NumMyElements(); int NumMyColElements = ColMap.NumMyElements(); int NumMyRangeElements = RangeMap.NumMyElements(); int NumMyDomainElements = DomainMap.NumMyElements(); int NumGlobalRowElements = RowMap.NumGlobalElements(); int NumGlobalColElements = ColMap.NumGlobalElements(); int NumGlobalRangeElements = RangeMap.NumGlobalElements(); int NumGlobalDomainElements = DomainMap.NumGlobalElements(); assert( NumGlobalRangeElements == NumGlobalDomainElements ) ; std::vector<int> MyGlobalRowElements( NumMyRowElements ) ; std::vector<int> NumEntriesPerRow( NumMyRowElements ) ; std::vector<int> MyPermutedGlobalRowElements( NumMyRowElements ) ; std::vector<int> MyGlobalColElements( NumMyColElements ) ; std::vector<int> MyPermutedGlobalColElements( NumMyColElements ) ; // Used to create the column map std::vector<int> MyPermutedGlobalColElementTable( NumMyColElements ) ; // To convert local indices to global std::vector<int> MyGlobalRangeElements( NumMyRangeElements ) ; std::vector<int> MyPermutedGlobalRangeElements( NumMyRangeElements ) ; std::vector<int> MyGlobalDomainElements( NumMyDomainElements ) ; std::vector<int> MyPermutedGlobalDomainElements( NumMyDomainElements ) ; RowMap.MyGlobalElements(&MyGlobalRowElements[0]); ColMap.MyGlobalElements(&MyGlobalColElements[0]); RangeMap.MyGlobalElements(&MyGlobalRangeElements[0]); DomainMap.MyGlobalElements(&MyGlobalDomainElements[0]); switch( ReindexRowMap ) { case 0: RowPermute = &NoPermute ; break; case 1: RowPermute = &SmallRowPermute ; break; case 2: RowPermute = BigRowPermute ; break; } switch( ReindexColMap ) { case 0: ColPermute = RowPermute ; break; case 1: ColPermute = &SmallColPermute ; break; } // // Create Serial Range and Domain Maps based on the permuted indexing // int nlocal = 0; if (In.Comm().MyPID()==0) nlocal = NumGlobalRangeElements; std::vector<int> AllIDs( NumGlobalRangeElements ) ; for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDs[i] = (*RowPermute)( i ) ; Epetra_Map SerialRangeMap( -1, nlocal, &AllIDs[0], 0, In.Comm()); std::vector<int> AllIDBs( NumGlobalRangeElements ) ; for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDBs[i] = (*ColPermute)( i ) ; Epetra_Map SerialDomainMap( -1, nlocal, &AllIDBs[0], 0, In.Comm()); // // Create Bizarre Range and Domain Maps based on the permuted indexing // These are nearly serial, having all but one element on process 0 // The goal here is to make sure that we can use Domain and Range maps // that are neither serial, nor distributed in the normal manner. // std::vector<int> AllIDCs( NumGlobalRangeElements ) ; for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDCs[i] = (*ColPermute)( i ) ; if ( In.Comm().NumProc() > 1 ) { if (In.Comm().MyPID()==0) nlocal = NumGlobalRangeElements-1; if (In.Comm().MyPID()==1) { nlocal = 1; AllIDCs[0] = (*ColPermute)( NumGlobalRangeElements - 1 ); } } int iam = In.Comm().MyPID(); Epetra_Map BizarreDomainMap( -1, nlocal, &AllIDCs[0], 0, In.Comm()); std::vector<int> AllIDDs( NumGlobalRangeElements ) ; for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDDs[i] = (*RowPermute)( i ) ; if ( In.Comm().NumProc() > 1 ) { if (In.Comm().MyPID()==0) nlocal = NumGlobalRangeElements-1; if (In.Comm().MyPID()==1) { nlocal = 1; AllIDDs[0] = (*RowPermute)( NumGlobalRangeElements -1 ) ; } } Epetra_Map BizarreRangeMap( -1, nlocal, &AllIDDs[0], 0, In.Comm()); // // Compute the column map // // If Diagonal==1, remove the column corresponding to the last row owned // by process 0. Removing this column from a tridiagonal matrix, leaves // a disconnected, but non-singular matrix. // int NumMyColElementsOut = 0 ; int NumGlobalColElementsOut ; if ( Diagonal == 1 ) NumGlobalColElementsOut = NumGlobalColElements-1; else NumGlobalColElementsOut = NumGlobalColElements; if ( Diagonal == 1 && iam==0 ) { for ( int i=0; i < NumMyColElements ; i++ ) { if ( MyGlobalColElements[i] != MyGlobalRowElements[NumMyRowElements-1] ) { MyPermutedGlobalColElements[NumMyColElementsOut++] = (*ColPermute)( MyGlobalColElements[i] ) ; } } assert( NumMyColElementsOut == NumMyColElements-1 ); } else { for ( int i=0; i < NumMyColElements ; i++ ) MyPermutedGlobalColElements[i] = (*ColPermute)( MyGlobalColElements[i] ) ; NumMyColElementsOut = NumMyColElements ; if ( Diagonal == 2 ) { // For each row, make sure that the column map has this row in it, // if it doesn't, add it to the column map. // Note: MyPermutedGlobalColElements == MyGlobalColElements when // Diagonal==2 because ( Diagonal == 2 ) implies: // ReindexRowMap==0 && ReindexColMap == 0 - see assert above for ( int i=0; i < NumMyRowElements ; i++ ) { bool MissingDiagonal = true; for ( int j=0; j < NumMyColElements; j++ ) { if ( MyGlobalRowElements[i] == MyGlobalColElements[j] ) { MissingDiagonal = false; } } if ( MissingDiagonal ) { MyPermutedGlobalColElements.resize(NumMyColElements+1); MyPermutedGlobalColElements[NumMyColElementsOut] = MyGlobalRowElements[i]; NumMyColElementsOut++; } } In.Comm().SumAll(&NumMyColElementsOut,&NumGlobalColElementsOut,1); } } // // These tables are used both as the permutation tables and to create the maps. // for ( int i=0; i < NumMyColElements ; i++ ) MyPermutedGlobalColElementTable[i] = (*ColPermute)( MyGlobalColElements[i] ) ; for ( int i=0; i < NumMyRowElements ; i++ ) MyPermutedGlobalRowElements[i] = (*RowPermute)( MyGlobalRowElements[i] ) ; for ( int i=0; i < NumMyRangeElements ; i++ ) MyPermutedGlobalRangeElements[i] = (*RowPermute)( MyGlobalRangeElements[i] ) ; for ( int i=0; i < NumMyDomainElements ; i++ ) MyPermutedGlobalDomainElements[i] = (*ColPermute)( MyGlobalDomainElements[i] ) ; RCP<Epetra_Map> PermutedRowMap = rcp( new Epetra_Map( NumGlobalRowElements, NumMyRowElements, &MyPermutedGlobalRowElements[0], 0, In.Comm() ) ); RCP<Epetra_Map> PermutedColMap = rcp( new Epetra_Map( NumGlobalColElementsOut, NumMyColElementsOut, &MyPermutedGlobalColElements[0], 0, In.Comm() ) ); RCP<Epetra_Map> PermutedRangeMap = rcp( new Epetra_Map( NumGlobalRangeElements, NumMyRangeElements, &MyPermutedGlobalRangeElements[0], 0, In.Comm() ) ); RCP<Epetra_Map> PermutedDomainMap = rcp( new Epetra_Map( NumGlobalDomainElements, NumMyDomainElements, &MyPermutedGlobalDomainElements[0], 0, In.Comm() ) ); // // These vectors are filled and then passed to InsertGlobalValues // std::vector<int> ThisRowIndices( In.MaxNumEntries() ); std::vector<double> ThisRowValues( In.MaxNumEntries() ); std::vector<int> PermutedGlobalColIndices( In.MaxNumEntries() ); //std::cout << __FILE__ << "::" <<__LINE__ << std::endl ; RCP<Epetra_CrsMatrix> Out = rcp( new Epetra_CrsMatrix( Copy, *PermutedRowMap, *PermutedColMap, 0 ) ); for (int i=0; i<NumMyRowElements; i++) { int NumIndicesThisRow = 0; assert( In.ExtractMyRowCopy( i, In.MaxNumEntries(), NumIndicesThisRow, &ThisRowValues[0], &ThisRowIndices[0] ) == 0 ) ; for (int j = 0 ; j < NumIndicesThisRow ; j++ ) { PermutedGlobalColIndices[j] = MyPermutedGlobalColElementTable[ ThisRowIndices[j] ] ; } bool MissingDiagonal = false; if ( Diagonal==2 ) { // assert( MyGlobalRowElements[i] == MyPermutedGlobalRowElements[i] ); MissingDiagonal = true; for( int j =0 ; j < NumIndicesThisRow ; j++ ) { if ( PermutedGlobalColIndices[j] == MyPermutedGlobalRowElements[i] ) { MissingDiagonal = false ; } } #if 0 std::cout << __FILE__ << "::" << __LINE__ << " i = " << i << " MyPermutedGlobalRowElements[i] = " << MyPermutedGlobalRowElements[i] << " MissingDiagonal = " << MissingDiagonal << std::endl ; #endif } if ( MissingDiagonal ) { ThisRowValues.resize(NumIndicesThisRow+1) ; ThisRowValues[NumIndicesThisRow] = 0.0; PermutedGlobalColIndices.resize(NumIndicesThisRow+1); PermutedGlobalColIndices[NumIndicesThisRow] = MyPermutedGlobalRowElements[i] ; #if 0 std::cout << __FILE__ << "::" << __LINE__ << " i = " << i << "NumIndicesThisRow = " << NumIndicesThisRow << "ThisRowValues[NumIndicesThisRow = " << ThisRowValues[NumIndicesThisRow] << " PermutedGlobalColIndices[NumIndcesThisRow] = " << PermutedGlobalColIndices[NumIndicesThisRow] << std::endl ; #endif NumIndicesThisRow++ ; } assert( Out->InsertGlobalValues( MyPermutedGlobalRowElements[i], NumIndicesThisRow, &ThisRowValues[0], &PermutedGlobalColIndices[0] ) >= 0 ); } // Epetra_LocalMap ReplicatedMap( NumGlobalRangeElements, 0, In.Comm() ); RCP<Epetra_Map> OutRangeMap ; RCP<Epetra_Map> OutDomainMap ; switch( RangeMapType ) { case 0: OutRangeMap = PermutedRangeMap ; break; case 1: OutRangeMap = rcp(&SerialRangeMap, false); break; case 2: OutRangeMap = rcp(&BizarreRangeMap, false); break; case 3: OutRangeMap = rcp(&ReplicatedMap, false); break; } // switch( DomainMapType ) { switch( DomainMapType ) { case 0: OutDomainMap = PermutedDomainMap ; break; case 1: OutDomainMap = rcp(&SerialDomainMap, false); break; case 2: OutDomainMap = rcp(&BizarreDomainMap, false); break; case 3: OutDomainMap = rcp(&ReplicatedMap, false); break; } #if 0 assert(Out->FillComplete( *PermutedDomainMap, *PermutedRangeMap )==0); #else assert(Out->FillComplete( *OutDomainMap, *OutRangeMap )==0); #endif #if 0 std::cout << __FILE__ << "::" << __LINE__ << std::endl ; Out->Print( std::cout ) ; #endif return Out; }
int check(Epetra_CrsMatrix& A, int NumMyRows1, int NumGlobalRows1, int NumMyNonzeros1, int NumGlobalNonzeros1, int* MyGlobalElements, bool verbose) { (void)MyGlobalElements; int ierr = 0, forierr = 0; int NumGlobalIndices; int NumMyIndices; int* MyViewIndices = 0; int* GlobalViewIndices = 0; double* MyViewValues = 0; double* GlobalViewValues = 0; int MaxNumIndices = A.Graph().MaxNumIndices(); int* MyCopyIndices = new int[MaxNumIndices]; int* GlobalCopyIndices = new int[MaxNumIndices]; double* MyCopyValues = new double[MaxNumIndices]; double* GlobalCopyValues = new double[MaxNumIndices]; // Test query functions int NumMyRows = A.NumMyRows(); if (verbose) cout << "\n\nNumber of local Rows = " << NumMyRows << endl<< endl; EPETRA_TEST_ERR(!(NumMyRows==NumMyRows1),ierr); int NumMyNonzeros = A.NumMyNonzeros(); if (verbose) cout << "\n\nNumber of local Nonzero entries = " << NumMyNonzeros << endl<< endl; EPETRA_TEST_ERR(!(NumMyNonzeros==NumMyNonzeros1),ierr); int NumGlobalRows = A.NumGlobalRows(); if (verbose) cout << "\n\nNumber of global Rows = " << NumGlobalRows << endl<< endl; EPETRA_TEST_ERR(!(NumGlobalRows==NumGlobalRows1),ierr); int NumGlobalNonzeros = A.NumGlobalNonzeros(); if (verbose) cout << "\n\nNumber of global Nonzero entries = " << NumGlobalNonzeros << endl<< endl; EPETRA_TEST_ERR(!(NumGlobalNonzeros==NumGlobalNonzeros1),ierr); // GlobalRowView should be illegal (since we have local indices) EPETRA_TEST_ERR(!(A.ExtractGlobalRowView(A.RowMap().MaxMyGID(), NumGlobalIndices, GlobalViewValues, GlobalViewIndices)==-2),ierr); // Other binary tests EPETRA_TEST_ERR(A.NoDiagonal(),ierr); EPETRA_TEST_ERR(!(A.Filled()),ierr); EPETRA_TEST_ERR(!(A.MyGRID(A.RowMap().MaxMyGID())),ierr); EPETRA_TEST_ERR(!(A.MyGRID(A.RowMap().MinMyGID())),ierr); EPETRA_TEST_ERR(A.MyGRID(1+A.RowMap().MaxMyGID()),ierr); EPETRA_TEST_ERR(A.MyGRID(-1+A.RowMap().MinMyGID()),ierr); EPETRA_TEST_ERR(!(A.MyLRID(0)),ierr); EPETRA_TEST_ERR(!(A.MyLRID(NumMyRows-1)),ierr); EPETRA_TEST_ERR(A.MyLRID(-1),ierr); EPETRA_TEST_ERR(A.MyLRID(NumMyRows),ierr); forierr = 0; for (int i = 0; i < NumMyRows; i++) { int Row = A.GRID(i); A.ExtractGlobalRowCopy(Row, MaxNumIndices, NumGlobalIndices, GlobalCopyValues, GlobalCopyIndices); A.ExtractMyRowView(i, NumMyIndices, MyViewValues, MyViewIndices); // this is where the problem comes from forierr += !(NumGlobalIndices == NumMyIndices); for(int j = 1; j < NumMyIndices; j++) { forierr += !(MyViewIndices[j-1] < MyViewIndices[j]); // this is where the test fails } for(int j = 0; j < NumGlobalIndices; j++) { forierr += !(GlobalCopyIndices[j] == A.GCID(MyViewIndices[j])); forierr += !(A.LCID(GlobalCopyIndices[j]) == MyViewIndices[j]); forierr += !(GlobalCopyValues[j] == MyViewValues[j]); } } EPETRA_TEST_ERR(forierr,ierr); forierr = 0; for (int i = 0; i < NumMyRows; i++) { int Row = A.GRID(i); A.ExtractGlobalRowCopy(Row, MaxNumIndices, NumGlobalIndices, GlobalCopyValues, GlobalCopyIndices); A.ExtractMyRowCopy(i, MaxNumIndices, NumMyIndices, MyCopyValues, MyCopyIndices); forierr += !(NumGlobalIndices == NumMyIndices); for (int j = 1; j < NumMyIndices; j++) forierr += !(MyCopyIndices[j-1] < MyCopyIndices[j]); for (int j = 0; j < NumGlobalIndices; j++) { forierr += !(GlobalCopyIndices[j] == A.GCID(MyCopyIndices[j])); forierr += !(A.LCID(GlobalCopyIndices[j]) == MyCopyIndices[j]); forierr += !(GlobalCopyValues[j] == MyCopyValues[j]); } } EPETRA_TEST_ERR(forierr,ierr); delete [] MyCopyIndices; delete [] GlobalCopyIndices; delete [] MyCopyValues; delete [] GlobalCopyValues; if (verbose) cout << "\n\nRows sorted check OK" << endl<< endl; return (ierr); }
int TPackAndPrepareWithOwningPIDs(const Epetra_CrsMatrix & A, int NumExportIDs, int * ExportLIDs, int & LenExports, char *& Exports, int & SizeOfPacket, int * Sizes, bool & VarSizes, std::vector<int>& pids) { int i, j; VarSizes = true; //enable variable block size data comm int TotalSendLength = 0; int * IntSizes = 0; if( NumExportIDs>0 ) IntSizes = new int[NumExportIDs]; int SizeofIntType = sizeof(int_type); for(i = 0; i < NumExportIDs; ++i) { int NumEntries; A.NumMyRowEntries( ExportLIDs[i], NumEntries ); // Will have NumEntries doubles, 2*NumEntries +2 ints pack them interleaved Sizes[i] = NumEntries; // NTS: We add the owning PID as the SECOND int of the pair for each entry Sizes[i] = NumEntries; // NOTE: Mixing and matching Int Types would be more efficient, BUT what about variable alignment? IntSizes[i] = 1 + (((2*NumEntries+2)*SizeofIntType)/(int)sizeof(double)); TotalSendLength += (Sizes[i]+IntSizes[i]); } double * DoubleExports = 0; SizeOfPacket = (int)sizeof(double); //setup buffer locally for memory management by this object if( TotalSendLength*SizeOfPacket > LenExports ) { if( LenExports > 0 ) delete [] Exports; LenExports = TotalSendLength*SizeOfPacket; DoubleExports = new double[TotalSendLength]; for( int i = 0; i < TotalSendLength; ++i ) DoubleExports[i] = 0.0; Exports = (char *) DoubleExports; } int NumEntries; double * values; double * valptr, * dintptr; // Each segment of Exports will be filled by a packed row of information for each row as follows: // 1st int: GRID of row where GRID is the global row ID for the source matrix // next int: NumEntries, Number of indices in row // next 2*NumEntries: The actual indices and owning [1] PID each for the row in (GID,PID) pairs with the GID first. // [1] Owning is defined in the sense of "Who owns the GID in the DomainMap," aka, who sends the GID in the importer const Epetra_Map & rowMap = A.RowMap(); const Epetra_Map & colMap = A.ColMap(); if( NumExportIDs > 0 ) { int_type * Indices; int_type FromRow; int_type * intptr; int maxNumEntries = A.MaxNumEntries(); std::vector<int> MyIndices(maxNumEntries); dintptr = (double *) Exports; valptr = dintptr + IntSizes[0]; intptr = (int_type *) dintptr; for (i=0; i<NumExportIDs; i++) { FromRow = (int_type) rowMap.GID64(ExportLIDs[i]); intptr[0] = FromRow; values = valptr; Indices = intptr + 2; EPETRA_CHK_ERR(A.ExtractMyRowCopy(ExportLIDs[i], maxNumEntries, NumEntries, values, &MyIndices[0])); for (j=0; j<NumEntries; j++) { Indices[2*j] = (int_type) colMap.GID64(MyIndices[j]); // convert to GIDs Indices[2*j+1] = pids[MyIndices[j]]; // PID owning the entry. } intptr[1] = NumEntries; // Load second slot of segment if( i < (NumExportIDs-1) ) { dintptr += (IntSizes[i]+Sizes[i]); valptr = dintptr + IntSizes[i+1]; intptr = (int_type *) dintptr; } } for(i = 0; i < NumExportIDs; ++i ) Sizes[i] += IntSizes[i]; } if( IntSizes ) delete [] IntSizes; return(0); }