//========================================================================== int Ifpack_CrsRiluk::InitValues(const Epetra_CrsMatrix & A) { UserMatrixIsCrs_ = true; if (!Allocated()) AllocateCrs(); Teuchos::RefCountPtr<Epetra_CrsMatrix> OverlapA = Teuchos::rcp( (Epetra_CrsMatrix *) &A, false ); if (IsOverlapped_) { OverlapA = Teuchos::rcp( new Epetra_CrsMatrix(Copy, *Graph_.OverlapGraph()) ); EPETRA_CHK_ERR(OverlapA->Import(A, *Graph_.OverlapImporter(), Insert)); EPETRA_CHK_ERR(OverlapA->FillComplete()); } // Get Maximun Row length int MaxNumEntries = OverlapA->MaxNumEntries(); // Set L range map and U domain map U_DomainMap_ = Teuchos::rcp( &(A.DomainMap()), false ); L_RangeMap_ = Teuchos::rcp( &(A.RangeMap()), false ); // Do the rest using generic Epetra_RowMatrix interface EPETRA_CHK_ERR(InitAllValues(*OverlapA, MaxNumEntries)); return(0); }
int build_matrix_unfused(const Epetra_CrsMatrix & SourceMatrix, Epetra_Export & RowExporter, Epetra_CrsMatrix *&A){ int rv=0; rv=A->Export(SourceMatrix, RowExporter, Insert); if(rv) {cerr<<"build_matrix_unfused: Export failed"<<endl; return rv;} rv=A->FillComplete(SourceMatrix.DomainMap(), SourceMatrix.RangeMap()); return rv; }
double test_with_matvec(const Epetra_CrsMatrix &A, const Epetra_CrsMatrix &B){ const Epetra_Map & Xamap = A.DomainMap(); const Epetra_Map & Yamap = A.RangeMap(); const Epetra_Map & Xbmap = B.DomainMap(); const Epetra_Map & Ybmap = B.RangeMap(); Epetra_Vector Xa(Xamap), Xb(Xbmap), Ya(Yamap), Yb(Ybmap), Diff(Yamap); Xa.SetSeed(24601); Xa.Random(); // Handle domain map change if(!Xamap.SameAs(Xbmap)) { Epetra_Import Ximport(Xbmap,Xamap); Xb.Import(Xa,Ximport,Insert); } else { Xb=Xa; } // Do the multiplies A.Apply(Xa,Ya); B.Apply(Xb,Yb); // Handle Rangemap change if(!Yamap.SameAs(Ybmap)) { Epetra_Import Yimport(Yamap,Ybmap); Diff.Import(Yb,Yimport,Insert); } else { Diff=Yb; } // Check solution Diff.Update(-1.0,Ya,1.0); double norm; Diff.Norm2(&norm); return norm; }
int main(int narg, char *arg[]) { using std::cout; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&narg,&arg); Epetra_MpiComm comm(MPI_COMM_WORLD); #else Epetra_SerialComm comm; #endif int me = comm.MyPID(); int np = comm.NumProc(); ITYPE nGlobalRows = 10; if (narg > 1) nGlobalRows = (ITYPE) atol(arg[1]); bool verbose = (nGlobalRows < 20); // Linear map similar to Trilinos default, // but want to allow adding OFFSET_EPETRA64 to the indices. int nMyRows = (int) (nGlobalRows / np + (nGlobalRows % np > me)); ITYPE myFirstRow = (ITYPE)(me * (nGlobalRows / np) + MIN(nGlobalRows%np, me)); ITYPE *myGlobalRows = new ITYPE[nMyRows]; for (int i = 0; i < nMyRows; i++) myGlobalRows[i] = (ITYPE)i + myFirstRow + OFFSET_EPETRA64; Epetra_Map *rowMap = new Epetra_Map(-1, nMyRows, &myGlobalRows[0], 0, comm); if (verbose) rowMap->Print(std::cout); // Create an integer vector nnzPerRow that is used to build the Epetra Matrix. // nnzPerRow[i] is the number of entries for the ith local equation std::vector<int> nnzPerRow(nMyRows+1, 0); // Also create lists of the nonzeros to be assigned to processors. // To save programming time and complexity, these vectors are allocated // bigger than they may actually be needed. std::vector<ITYPE> iv(3*nMyRows+1); std::vector<ITYPE> jv(3*nMyRows+1); std::vector<double> vv(3*nMyRows+1); // Generate the nonzeros for the Laplacian matrix. ITYPE nMyNonzeros = 0; for (ITYPE i = 0, myrowcnt = 0; i < nGlobalRows; i++) { if (rowMap->MyGID(i+OFFSET_EPETRA64)) { // This processor owns this row; add nonzeros. if (i > 0) { iv[nMyNonzeros] = i + OFFSET_EPETRA64; jv[nMyNonzeros] = i-1 + OFFSET_EPETRA64; vv[nMyNonzeros] = -1; if (verbose) std::cout << "(" << iv[nMyNonzeros] << "," << jv[nMyNonzeros] << ")=" << vv[nMyNonzeros] << " on processor " << me << " in " << myrowcnt << std::endl; nMyNonzeros++; nnzPerRow[myrowcnt]++; } iv[nMyNonzeros] = i + OFFSET_EPETRA64; jv[nMyNonzeros] = i + OFFSET_EPETRA64; vv[nMyNonzeros] = ((i == 0 || i == nGlobalRows-1) ? 1. : 2.); if (verbose) std::cout << "(" << iv[nMyNonzeros] << "," << jv[nMyNonzeros] << ")=" << vv[nMyNonzeros] << " on processor " << me << " in " << myrowcnt << std::endl; nMyNonzeros++; nnzPerRow[myrowcnt]++; if (i < nGlobalRows - 1) { iv[nMyNonzeros] = i + OFFSET_EPETRA64; jv[nMyNonzeros] = i+1 + OFFSET_EPETRA64; vv[nMyNonzeros] = -1; if (verbose) std::cout << "(" << iv[nMyNonzeros] << "," << jv[nMyNonzeros] << ")=" << vv[nMyNonzeros] << " on processor " << me << " in " << myrowcnt << std::endl; nMyNonzeros++; nnzPerRow[myrowcnt]++; } myrowcnt++; } } // Create an Epetra_Matrix Epetra_CrsMatrix *A = new Epetra_CrsMatrix(Copy, *rowMap, &nnzPerRow[0], false); // Insert the nonzeros. int info; ITYPE sum = 0; for (int i=0; i < nMyRows; i++) { if (nnzPerRow[i]) { if (verbose) { std::cout << "InsertGlobalValus row " << iv[sum] << " count " << nnzPerRow[i] << " cols " << jv[sum] << " " << jv[sum+1] << " "; if (nnzPerRow[i] == 3) std::cout << jv[sum+2]; std::cout << std::endl; } info = A->InsertGlobalValues(iv[sum],nnzPerRow[i],&vv[sum],&jv[sum]); assert(info==0); sum += nnzPerRow[i]; } } // Finish up info = A->FillComplete(); assert(info==0); if (verbose) A->Print(std::cout); // Sanity test: Product of matrix and vector of ones should have norm == 0 // and max/min/mean values of 0 Epetra_Vector sanity(A->RangeMap()); Epetra_Vector sanityres(A->DomainMap()); sanity.PutScalar(1.); A->Multiply(false, sanity, sanityres); double jjone, jjtwo, jjmax; sanityres.Norm1(&jjone); sanityres.Norm2(&jjtwo); sanityres.NormInf(&jjmax); if (me == 0) std::cout << "SanityTest norms 1/2/inf: " << jjone << " " << jjtwo << " " << jjmax << std::endl; bool test_failed = (jjone != 0) || (jjtwo != 0) || (jjmax != 0); sanityres.MinValue(&jjone); sanityres.MeanValue(&jjtwo); sanityres.MaxValue(&jjmax); if (me == 0) std::cout << "SanityTest values min/max/avg: " << jjone << " " << jjmax << " " << jjtwo << std::endl; test_failed = test_failed || (jjone != 0) || (jjtwo != 0) || (jjmax != 0); if (me == 0) { if(test_failed) std::cout << "Bug_5794_IndexBase_LL tests FAILED" << std::endl; } delete A; delete rowMap; delete [] myGlobalRows; FINALIZE; }
// // 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; }