//============================================================================== int LinearProblem_CrsSingletonFilter::ConstructRedistributeExporter(Epetra_Map * SourceMap, Epetra_Map * TargetMap, Epetra_Export * & RedistributeExporter, Epetra_Map * & RedistributeMap) { int IndexBase = SourceMap->IndexBase(); if (IndexBase!=TargetMap->IndexBase()) EPETRA_CHK_ERR(-1); const Epetra_Comm & Comm = TargetMap->Comm(); int TargetNumMyElements = TargetMap->NumMyElements(); int SourceNumMyElements = SourceMap->NumMyElements(); // ContiguousTargetMap has same number of elements per PE as TargetMap, but uses contigious indexing Epetra_Map ContiguousTargetMap(-1, TargetNumMyElements, IndexBase,Comm); // Same for ContiguousSourceMap Epetra_Map ContiguousSourceMap(-1, SourceNumMyElements, IndexBase, Comm); assert(ContiguousSourceMap.NumGlobalElements()==ContiguousTargetMap.NumGlobalElements()); // Now create a vector that contains the global indices of the Source Epetra_MultiVector Epetra_IntVector SourceIndices(View, ContiguousSourceMap, SourceMap->MyGlobalElements()); // Create an exporter to send the SourceMap global IDs to the target distribution Epetra_Export Exporter(ContiguousSourceMap, ContiguousTargetMap); // Create a vector to catch the global IDs in the target distribution Epetra_IntVector TargetIndices(ContiguousTargetMap); TargetIndices.Export(SourceIndices, Exporter, Insert); // Create a new map that describes how the Source MultiVector should be laid out so that it has // the same number of elements on each processor as the TargetMap RedistributeMap = new Epetra_Map(-1, TargetNumMyElements, TargetIndices.Values(), IndexBase, Comm); // This exporter will finally redistribute the Source MultiVector to the same layout as the TargetMap RedistributeExporter = new Epetra_Export(*SourceMap, *RedistributeMap); return(0); }
//============================================================================= int Epetra_FastCrsMatrix::Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { // // This function forms the product Y = A * Y or Y = A' * X // if (X.NumVectors()==1 && Y.NumVectors()==1) { double * xp = (double *) X[0]; double * yp = (double *) Y[0]; Epetra_Vector x(View, X.Map(), xp); Epetra_Vector y(View, Y.Map(), yp); return(Multiply(TransA, x, y)); } if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. int i, j, k; int * NumEntriesPerRow = NumEntriesPerRow_; int ** Indices = Indices_; double ** Values = Values_; double **Xp = (double**)X.Pointers(); double **Yp = (double**)Y.Pointers(); int NumVectors = X.NumVectors(); int NumMyCols_ = NumMyCols(); // Need to better manage the Import and Export vectors: // - Need accessor functions // - Need to make the NumVector match (use a View to do this) // - Need to look at RightScale and ColSum routines too. if (!TransA) { // If we have a non-trivial importer, we must import elements that are permuted or are on other processors if (Importer()!=0) { if (ImportVector_!=0) { if (ImportVector_->NumVectors()!=NumVectors) { delete ImportVector_; ImportVector_= 0;} } if (ImportVector_==0) ImportVector_ = new Epetra_MultiVector(ColMap(),NumVectors); // Create import vector if needed ImportVector_->Import(X, *Importer(), Insert); Xp = (double**)ImportVector_->Pointers(); } // If we have a non-trivial exporter, we must export elements that are permuted or belong to other processors if (Exporter()!=0) { if (ExportVector_!=0) { if (ExportVector_->NumVectors()!=NumVectors) { delete ExportVector_; ExportVector_= 0;} } if (ExportVector_==0) ExportVector_ = new Epetra_MultiVector(RowMap(),NumVectors); // Create Export vector if needed Yp = (double**)ExportVector_->Pointers(); } // Do actual computation for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++; int * RowIndices = *Indices++; double * RowValues = *Values++; for (k=0; k<NumVectors; k++) { double sum = 0.0; for (j=0; j < NumEntries; j++) sum += RowValues[j] * Xp[k][RowIndices[j]]; Yp[k][i] = sum; } } if (Exporter()!=0) Y.Export(*ExportVector_, *Exporter(), Add); // Fill Y with Values from export vector } else { // Transpose operation // If we have a non-trivial exporter, we must import elements that are permuted or are on other processors if (Exporter()!=0) { if (ExportVector_!=0) { if (ExportVector_->NumVectors()!=NumVectors) { delete ExportVector_; ExportVector_= 0;} } if (ExportVector_==0) ExportVector_ = new Epetra_MultiVector(RowMap(),NumVectors); // Create Export vector if needed ExportVector_->Import(X, *Exporter(), Insert); Xp = (double**)ExportVector_->Pointers(); } // If we have a non-trivial importer, we must export elements that are permuted or belong to other processors if (Importer()!=0) { if (ImportVector_!=0) { if (ImportVector_->NumVectors()!=NumVectors) { delete ImportVector_; ImportVector_= 0;} } if (ImportVector_==0) ImportVector_ = new Epetra_MultiVector(ColMap(),NumVectors); // Create import vector if needed Yp = (double**)ImportVector_->Pointers(); } // Do actual computation for (k=0; k<NumVectors; k++) for (i=0; i < NumMyCols_; i++) Yp[k][i] = 0.0; // Initialize y for transpose multiply for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++; int * RowIndices = *Indices++; double * RowValues = *Values++; for (k=0; k<NumVectors; k++) { for (j=0; j < NumEntries; j++) Yp[k][RowIndices[j]] += RowValues[j] * Xp[k][i]; } } if (Importer()!=0) Y.Export(*ImportVector_, *Importer(), Add); // Fill Y with Values from export vector } UpdateFlops(2*NumVectors*NumGlobalNonzeros64()); return(0); }
//============================================================================= int Epetra_FastCrsMatrix::Multiply(bool TransA, const Epetra_Vector& x, Epetra_Vector& y) const { // // This function forms the product y = A * x or y = A' * x // int i, j; double * xp = (double*)x.Values(); double *yp = (double*)y.Values(); int NumMyCols_ = NumMyCols(); if (!TransA) { // If we have a non-trivial importer, we must import elements that are permuted or are on other processors if (Importer()!=0) { if (ImportVector_!=0) { if (ImportVector_->NumVectors()!=1) { delete ImportVector_; ImportVector_= 0;} } if (ImportVector_==0) ImportVector_ = new Epetra_MultiVector(ColMap(),1); // Create import vector if needed ImportVector_->Import(x, *Importer(), Insert); xp = (double*)ImportVector_->Values(); } // If we have a non-trivial exporter, we must export elements that are permuted or belong to other processors if (Exporter()!=0) { if (ExportVector_!=0) { if (ExportVector_->NumVectors()!=1) { delete ExportVector_; ExportVector_= 0;} } if (ExportVector_==0) ExportVector_ = new Epetra_MultiVector(RowMap(),1); // Create Export vector if needed yp = (double*)ExportVector_->Values(); } // Do actual computation for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++; int * RowIndices = *Indices++; double * RowValues = *Values++; double sum = 0.0; for (j=0; j < NumEntries; j++) sum += RowValues[j] * xp[RowIndices[j]]; yp[i] = sum; } if (Exporter()!=0) y.Export(*ExportVector_, *Exporter(), Add); // Fill y with Values from export vector } else { // Transpose operation // If we have a non-trivial exporter, we must import elements that are permuted or are on other processors if (Exporter()!=0) { if (ExportVector_!=0) { if (ExportVector_->NumVectors()!=1) { delete ExportVector_; ExportVector_= 0;} } if (ExportVector_==0) ExportVector_ = new Epetra_MultiVector(RowMap(),1); // Create Export vector if needed ExportVector_->Import(x, *Exporter(), Insert); xp = (double*)ExportVector_->Values(); } // If we have a non-trivial importer, we must export elements that are permuted or belong to other processors if (Importer()!=0) { if (ImportVector_!=0) { if (ImportVector_->NumVectors()!=1) { delete ImportVector_; ImportVector_= 0;} } if (ImportVector_==0) ImportVector_ = new Epetra_MultiVector(ColMap(),1); // Create import vector if needed yp = (double*)ImportVector_->Values(); } // Do actual computation for (i=0; i < NumMyCols_; i++) yp[i] = 0.0; // Initialize y for transpose multiply for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++; int * RowIndices = *Indices++; double * RowValues = *Values++; for (j=0; j < NumEntries; j++) yp[RowIndices[j]] += RowValues[j] * xp[i]; } if (Importer()!=0) y.Export(*ImportVector_, *Importer(), Add); // Fill y with Values from export vector } UpdateFlops(2*NumGlobalNonzeros64()); return(0); }
int main(int argc, char *argv[]) { int ierr = 0, i, j, forierr = 0; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif bool verbose = false; // Check if we should print results to standard out if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true; //char tmp; //if (Comm.MyPID()==0) cout << "Press any key to continue..."<< endl; //if (Comm.MyPID()==0) cin >> tmp; //Comm.Barrier(); Comm.SetTracebackMode(0); // This should shut down any error traceback reporting int MyPID = Comm.MyPID(); int NumProc = Comm.NumProc(); if (verbose && MyPID==0) cout << Epetra_Version() << endl << endl; if (verbose) cout << "Processor "<<MyPID<<" of "<< NumProc << " is alive."<<endl; // Redefine verbose to only print on PE 0 if (verbose && Comm.MyPID()!=0) verbose = false; int NumMyEquations = 20; long long NumGlobalEquations = NumMyEquations*NumProc+EPETRA_MIN(NumProc,3); if (MyPID < 3) NumMyEquations++; // Construct a Source Map that puts approximately the same Number of equations on each processor in // uniform global ordering Epetra_Map SourceMap(NumGlobalEquations, NumMyEquations, 0LL, Comm); // Get update list and number of local equations from newly created Map int NumMyElements = SourceMap.NumMyElements(); long long * SourceMyGlobalElements = new long long[NumMyElements]; SourceMap.MyGlobalElements(SourceMyGlobalElements); // Construct a Target Map that will contain: // some unchanged elements (relative to the soure map), // some permuted elements // some off-processor elements Epetra_Vector RandVec(SourceMap); RandVec.Random(); // This creates a vector of random numbers between negative one and one. long long *TargetMyGlobalElements = new long long[NumMyElements]; long long MinGID = SourceMap.MinMyGID64(); for (i=0; i< NumMyEquations/2; i++) TargetMyGlobalElements[i] = i + MinGID; // Half will be the same... for (i=NumMyEquations/2; i<NumMyEquations; i++) { int index = abs((int)(((double) (NumGlobalEquations-1) ) * RandVec[i])); TargetMyGlobalElements[i] = EPETRA_MIN(NumGlobalEquations-1,(long long) EPETRA_MAX(0,index)); } int NumSameIDs = 0; int NumPermutedIDs = 0; int NumRemoteIDs = 0; bool StillContiguous = true; for (i=0; i < NumMyEquations; i++) { if (SourceMyGlobalElements[i]==TargetMyGlobalElements[i] && StillContiguous) NumSameIDs++; else if (SourceMap.MyGID(TargetMyGlobalElements[i])) { StillContiguous = false; NumPermutedIDs++; } else { StillContiguous = false; NumRemoteIDs++; } } EPETRA_TEST_ERR(!(NumMyEquations==NumSameIDs+NumPermutedIDs+NumRemoteIDs),ierr); Epetra_Map TargetMap((long long) -1, NumMyElements, TargetMyGlobalElements, 0LL, Comm); // Create a multivector whose elements are GlobalID * (column number +1) int NumVectors = 3; Epetra_MultiVector SourceMultiVector(SourceMap, NumVectors); for (j=0; j < NumVectors; j++) for (i=0; i < NumMyElements; i++) SourceMultiVector[j][i] = (double) SourceMyGlobalElements[i]*(j+1); // Create a target multivector that we will fill using an Import Epetra_MultiVector TargetMultiVector(TargetMap, NumVectors); Epetra_Import Importer(TargetMap, SourceMap); EPETRA_TEST_ERR(!(TargetMultiVector.Import(SourceMultiVector, Importer, Insert)==0),ierr); // Test Target against expected values forierr = 0; for (j=0; j < NumVectors; j++) for (i=0; i < NumMyElements; i++) { if (TargetMultiVector[j][i]!= (double) TargetMyGlobalElements[i]*(j+1)) cout << "TargetMultiVector["<<i<<"]["<<j<<"] = " << TargetMultiVector[j][i] << " TargetMyGlobalElements[i]*(j+1) = " << TargetMyGlobalElements[i]*(j+1) << endl; forierr += !(TargetMultiVector[j][i]== (double) TargetMyGlobalElements[i]*(j+1)); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "MultiVector Import using Importer Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////// // Now use Importer to do an export Epetra_Vector TargetVector(SourceMap); Epetra_Vector ExpectedTarget(SourceMap); Epetra_Vector SourceVector(TargetMap); NumSameIDs = Importer.NumSameIDs(); int NumPermuteIDs = Importer.NumPermuteIDs(); int NumExportIDs = Importer.NumExportIDs(); int *PermuteFromLIDs = Importer.PermuteFromLIDs(); int *ExportLIDs = Importer.ExportLIDs(); int *ExportPIDs = Importer.ExportPIDs(); for (i=0; i < NumSameIDs; i++) ExpectedTarget[i] = (double) (MyPID+1); for (i=0; i < NumPermuteIDs; i++) ExpectedTarget[PermuteFromLIDs[i]] = (double) (MyPID+1); for (i=0; i < NumExportIDs; i++) ExpectedTarget[ExportLIDs[i]] += (double) (ExportPIDs[i]+1); for (i=0; i < NumMyElements; i++) SourceVector[i] = (double) (MyPID+1); EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, Importer, Add)==0),ierr); forierr = 0; for (i=0; i < NumMyElements; i++) { if (TargetVector[i]!= ExpectedTarget[i]) cout << " TargetVector["<<i<<"] = " << TargetVector[i] << " ExpectedTarget["<<i<<"] = " << ExpectedTarget[i] << " on PE " << MyPID << endl; forierr += !(TargetVector[i]== ExpectedTarget[i]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Vector Export using Importer Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////// // Now use Importer to create a reverse exporter TargetVector.PutScalar(0.0); Epetra_Export ReversedImport(Importer); EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, ReversedImport, Add)==0),ierr); forierr = 0; for (i=0; i < NumMyElements; i++) { if (TargetVector[i]!= ExpectedTarget[i]) cout << " TargetVector["<<i<<"] = " << TargetVector[i] << " ExpectedTarget["<<i<<"] = " << ExpectedTarget[i] << " on PE " << MyPID << endl; forierr += !(TargetVector[i]== ExpectedTarget[i]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Vector Export using Reversed Importer Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////// // Now use Exporter to create a reverse importer TargetVector.PutScalar(0.0); Epetra_Import ReversedExport(ReversedImport); EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, ReversedExport, Add)==0),ierr); forierr = 0; for (i=0; i < NumMyElements; i++) { if (TargetVector[i]!= ExpectedTarget[i]) cout << " TargetVector["<<i<<"] = " << TargetVector[i] << " ExpectedTarget["<<i<<"] = " << ExpectedTarget[i] << " on PE " << MyPID << endl; forierr += !(TargetVector[i]== ExpectedTarget[i]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Vector Export using Reversed Exporter Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////////////////// // Build a tridiagonal system two ways: // 1) From "standard" matrix view where equations are uniquely owned. // 2) From 1D PDE view where nodes (equations) between processors are shared and partial contributions are done // in parallel, then merged together at the end of the construction process. // ////////////////////////////////////////////////////////////////////////////////////////// // Construct a Standard Map that puts approximately the same number of equations on each processor in // uniform global ordering Epetra_Map StandardMap(NumGlobalEquations, NumMyEquations, 0LL, Comm); // Get update list and number of local equations from newly created Map NumMyElements = StandardMap.NumMyElements(); long long * StandardMyGlobalElements = new long long[NumMyElements]; StandardMap.MyGlobalElements(StandardMyGlobalElements); // Create a standard Epetra_CrsGraph Epetra_CrsGraph StandardGraph(Copy, StandardMap, 3); EPETRA_TEST_ERR(StandardGraph.IndicesAreGlobal(),ierr); EPETRA_TEST_ERR(StandardGraph.IndicesAreLocal(),ierr); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 long long *Indices = new long long[2]; int NumEntries; forierr = 0; for (i=0; i<NumMyEquations; i++) { if (StandardMyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (StandardMyGlobalElements[i] == NumGlobalEquations-1) { Indices[0] = NumGlobalEquations-2; NumEntries = 1; } else { Indices[0] = StandardMyGlobalElements[i]-1; Indices[1] = StandardMyGlobalElements[i]+1; NumEntries = 2; } forierr += !(StandardGraph.InsertGlobalIndices(StandardMyGlobalElements[i], NumEntries, Indices)==0); forierr += !(StandardGraph.InsertGlobalIndices(StandardMyGlobalElements[i], 1, StandardMyGlobalElements+i)==0); // Put in the diagonal entry } EPETRA_TEST_ERR(forierr,ierr); // Finish up EPETRA_TEST_ERR(!(StandardGraph.IndicesAreGlobal()),ierr); EPETRA_TEST_ERR(!(StandardGraph.FillComplete()==0),ierr); EPETRA_TEST_ERR(!(StandardGraph.IndicesAreLocal()),ierr); EPETRA_TEST_ERR(StandardGraph.StorageOptimized(),ierr); StandardGraph.OptimizeStorage(); EPETRA_TEST_ERR(!(StandardGraph.StorageOptimized()),ierr); EPETRA_TEST_ERR(StandardGraph.UpperTriangular(),ierr); EPETRA_TEST_ERR(StandardGraph.LowerTriangular(),ierr); // Create Epetra_CrsMatrix using the just-built graph Epetra_CrsMatrix StandardMatrix(Copy, StandardGraph); EPETRA_TEST_ERR(StandardMatrix.IndicesAreGlobal(),ierr); EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 double *Values = new double[2]; Values[0] = -1.0; Values[1] = -1.0; double two = 2.0; forierr = 0; for (i=0; i<NumMyEquations; i++) { if (StandardMyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (StandardMyGlobalElements[i] == NumGlobalEquations-1) { Indices[0] = NumGlobalEquations-2; NumEntries = 1; } else { Indices[0] = StandardMyGlobalElements[i]-1; Indices[1] = StandardMyGlobalElements[i]+1; NumEntries = 2; } forierr += !(StandardMatrix.ReplaceGlobalValues(StandardMyGlobalElements[i], NumEntries, Values, Indices)==0); // Put in the diagonal entry forierr += !(StandardMatrix.ReplaceGlobalValues(StandardMyGlobalElements[i], 1, &two, StandardMyGlobalElements+i)==0); } EPETRA_TEST_ERR(forierr,ierr); // Finish up EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr); EPETRA_TEST_ERR(!(StandardMatrix.FillComplete()==0),ierr); EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr); // EPETRA_TEST_ERR((StandardMatrix.StorageOptimized()),ierr); EPETRA_TEST_ERR((StandardMatrix.OptimizeStorage()),ierr); EPETRA_TEST_ERR(!(StandardMatrix.StorageOptimized()),ierr); EPETRA_TEST_ERR(StandardMatrix.UpperTriangular(),ierr); EPETRA_TEST_ERR(StandardMatrix.LowerTriangular(),ierr); // Construct an Overlapped Map of StandardMap that include the endpoints from two neighboring processors. int OverlapNumMyElements; long long OverlapMinMyGID; OverlapNumMyElements = NumMyElements + 1; if (MyPID==0) OverlapNumMyElements--; if (MyPID==0) OverlapMinMyGID = StandardMap.MinMyGID64(); else OverlapMinMyGID = StandardMap.MinMyGID64()-1; long long * OverlapMyGlobalElements = new long long[OverlapNumMyElements]; for (i=0; i< OverlapNumMyElements; i++) OverlapMyGlobalElements[i] = OverlapMinMyGID + i; Epetra_Map OverlapMap((long long) -1, OverlapNumMyElements, OverlapMyGlobalElements, 0LL, Comm); // Create the Overlap Epetra_Matrix Epetra_CrsMatrix OverlapMatrix(Copy, OverlapMap, 4); EPETRA_TEST_ERR(OverlapMatrix.IndicesAreGlobal(),ierr); EPETRA_TEST_ERR(OverlapMatrix.IndicesAreLocal(),ierr); // Add matrix element one cell at a time. // Each cell does an incoming and outgoing flux calculation double pos_one = 1.0; double neg_one = -1.0; forierr = 0; for (i=0; i<OverlapNumMyElements; i++) { long long node_left = OverlapMyGlobalElements[i]-1; long long node_center = node_left + 1; long long node_right = node_left + 2; if (i>0) { if (node_left>-1) forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &neg_one, &node_left)==0); forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0); } if (i<OverlapNumMyElements-1) { forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0); if (node_right<NumGlobalEquations) forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &neg_one, &node_right)==0); } } EPETRA_TEST_ERR(forierr,ierr); // Handle endpoints if (MyPID==0) { long long node_center = 0; EPETRA_TEST_ERR(!(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0),ierr); } if (MyPID==NumProc-1) { long long node_center = OverlapMyGlobalElements[OverlapNumMyElements-1]; EPETRA_TEST_ERR(!(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0),ierr); } EPETRA_TEST_ERR(!(OverlapMatrix.FillComplete()==0),ierr); // Make a gathered matrix from OverlapMatrix. It should be identical to StandardMatrix Epetra_CrsMatrix GatheredMatrix(Copy, StandardGraph); Epetra_Export Exporter(OverlapMap, StandardMap); EPETRA_TEST_ERR(!(GatheredMatrix.Export(OverlapMatrix, Exporter, Add)==0),ierr); EPETRA_TEST_ERR(!(GatheredMatrix.FillComplete()==0),ierr); // Check if entries of StandardMatrix and GatheredMatrix are identical int StandardNumEntries, GatheredNumEntries; int * StandardIndices, * GatheredIndices; double * StandardValues, * GatheredValues; int StandardNumMyNonzeros = StandardMatrix.NumMyNonzeros(); int GatheredNumMyNonzeros = GatheredMatrix.NumMyNonzeros(); EPETRA_TEST_ERR(!(StandardNumMyNonzeros==GatheredNumMyNonzeros),ierr); int StandardNumMyRows = StandardMatrix.NumMyRows(); int GatheredNumMyRows = GatheredMatrix.NumMyRows(); EPETRA_TEST_ERR(!(StandardNumMyRows==GatheredNumMyRows),ierr); forierr = 0; for (i=0; i< StandardNumMyRows; i++) { forierr += !(StandardMatrix.ExtractMyRowView(i, StandardNumEntries, StandardValues, StandardIndices)==0); forierr += !(GatheredMatrix.ExtractMyRowView(i, GatheredNumEntries, GatheredValues, GatheredIndices)==0); forierr += !(StandardNumEntries==GatheredNumEntries); for (j=0; j < StandardNumEntries; j++) { //if (StandardIndices[j]!=GatheredIndices[j]) // cout << "MyPID = " << MyPID << " i = " << i << " StandardIndices[" << j << "] = " << StandardIndices[j] // << " GatheredIndices[" << j << "] = " << GatheredIndices[j] << endl; //if (StandardValues[j]!=GatheredValues[j]) //cout << "MyPID = " << MyPID << " i = " << i << " StandardValues[" << j << "] = " << StandardValues[j] // << " GatheredValues[" << j << "] = " << GatheredValues[j] << endl; forierr += !(StandardIndices[j]==GatheredIndices[j]); forierr += !(StandardValues[j]==GatheredValues[j]); } } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Matrix Export Check OK" << endl << endl; //Do Again with use of Epetra_OffsetIndex object for speed Epetra_OffsetIndex OffsetIndex( OverlapMatrix.Graph(), GatheredMatrix.Graph(), Exporter ); EPETRA_TEST_ERR(!(GatheredMatrix.Export(OverlapMatrix, Exporter, Add)==0),ierr); if (verbose) cout << "Optimized Matrix Export Check OK" << endl << endl; bool passed; Epetra_LongLongVector v1(StandardMap); v1.PutValue(2); Epetra_LongLongVector v2(StandardMap); v2.PutValue(3); Epetra_Export identExporter(StandardMap,StandardMap); // Identity exporter EPETRA_TEST_ERR(!(v2.Export(v1, identExporter, Insert)==0),ierr); passed = (v2.MinValue()==2); EPETRA_TEST_ERR(!passed,ierr); v1.PutValue(1); Epetra_Import identImporter(StandardMap,StandardMap); // Identity importer EPETRA_TEST_ERR(!(v2.Import(v1, identExporter, Insert)==0),ierr); passed = passed && (v2.MaxValue()==1); EPETRA_TEST_ERR(!passed,ierr); if (verbose) { if (passed) cout << "Identity Import/Export Check OK" << endl << endl; else cout << "Identity Import/Export Check Failed" << endl << endl; } int NumSubMapElements = StandardMap.NumMyElements()/2; int SubStart = Comm.MyPID(); NumSubMapElements = EPETRA_MIN(NumSubMapElements,StandardMap.NumMyElements()-SubStart); Epetra_Map SubMap((long long) -1, NumSubMapElements, StandardMyGlobalElements+SubStart, 0LL, Comm); Epetra_LongLongVector v3(View, SubMap, SubMap.MyGlobalElements64()); // Fill v3 with GID values for variety Epetra_Export subExporter(SubMap, StandardMap); // Export to a subset of indices of standard map EPETRA_TEST_ERR(!(v2.Export(v3,subExporter,Insert)==0),ierr); forierr = 0; for (i=0; i<SubMap.NumMyElements(); i++) { int i1 = StandardMap.LID(SubMap.GID64(i)); forierr += !(v3[i]==v2[i1]); } EPETRA_TEST_ERR(forierr,ierr); Epetra_Import subImporter(StandardMap, SubMap); // Import to a subset of indices of standard map EPETRA_TEST_ERR(!(v1.Import(v3,subImporter,Insert)==0),ierr); for (i=0; i<SubMap.NumMyElements(); i++) { int i1 = StandardMap.LID(SubMap.GID64(i)); forierr += !(v3[i]==v1[i1]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) { if (forierr==0) cout << "SubMap Import/Export Check OK" << endl << endl; else cout << "SubMap Import/Export Check Failed" << endl << endl; } #ifdef DOESNT_WORK_IN_PARALLEL forierr = special_submap_import_test(Comm); EPETRA_TEST_ERR(forierr, ierr); if (verbose) { if (forierr==0) cout << "Special SubMap Import Check OK" << endl << endl; else cout << "Special SubMap Import Check Failed" << endl << endl; } #endif forierr = alternate_import_constructor_test(Comm); EPETRA_TEST_ERR(forierr, ierr); if (verbose) { if (forierr==0) cout << "Alternative Import Constructor Check OK" << endl << endl; else cout << "Alternative Import Constructor Check Failed" << endl << endl; } // Release all objects delete [] SourceMyGlobalElements; delete [] TargetMyGlobalElements; delete [] OverlapMyGlobalElements; delete [] StandardMyGlobalElements; delete [] Values; delete [] Indices; #ifdef EPETRA_MPI MPI_Finalize() ; #endif /* end main */ return ierr ; }
CrsGraph_Transpose::NewTypeRef CrsGraph_Transpose:: operator()( OriginalTypeRef orig ) { origObj_ = &orig; int nRows = orig.NumMyRows(); int nCols = orig.NumMyCols(); const Epetra_BlockMap & RowMap = orig.RowMap(); int numIndices; int * Indices; Epetra_CrsGraph * TransposeGraph = 0; if( !ignoreNonLocalCols_ && orig.DistributedGlobal() ) { std::vector<int> TransNumNZ( nCols, 0 ); for( int i = 0; i < nRows; ++i ) { orig.ExtractMyRowView( i, numIndices, Indices ); for( int j = 0; j < numIndices; ++j ) ++TransNumNZ[ Indices[j] ]; } std::vector< std::vector<int> > TransIndices( nCols ); for( int i = 0; i < nCols; ++i ) if( TransNumNZ[i] ) { TransIndices[i].resize( TransNumNZ[i] ); TransNumNZ[i] = 0; } for( int i = 0; i < nRows; ++i ) { orig.ExtractMyRowView( i, numIndices, Indices ); for( int j = 0; j < numIndices; ++j ) TransIndices[ Indices[j] ][ TransNumNZ[ Indices[j] ]++ ] = i; } Epetra_CrsGraph SharedTransGraph( View, orig.ImportMap(), RowMap, &TransNumNZ[0] ); for( int i = 0; i < nCols; ++i ) if( TransNumNZ[i] ) SharedTransGraph.InsertMyIndices( i, TransNumNZ[i], &TransIndices[i][0] ); SharedTransGraph.FillComplete(); TransposeGraph = new Epetra_CrsGraph( Copy, RowMap, 0 ); Epetra_Export Exporter( orig.ImportMap(), RowMap ); TransposeGraph->Export( SharedTransGraph, Exporter, Add ); TransposeGraph->FillComplete(); } else { std::vector<int> TransNumNZ( nRows, 0 ); for( int i = 0; i < nRows; ++i ) { orig.ExtractMyRowView( i, numIndices, Indices ); for( int j = 0; j < numIndices; ++j ) if( Indices[j] < nRows ) ++TransNumNZ[ Indices[j] ]; } std::vector< std::vector<int> > TransIndices( nRows ); for( int i = 0; i < nRows; ++i ) if( TransNumNZ[i] ) { TransIndices[i].resize( TransNumNZ[i] ); TransNumNZ[i] = 0; } for( int i = 0; i < nRows; ++i ) { orig.ExtractMyRowView( i, numIndices, Indices ); for( int j = 0; j < numIndices; ++j ) if( Indices[j] < nRows ) TransIndices[ Indices[j] ][ TransNumNZ[ Indices[j] ]++ ] = i; } TransposeGraph = new Epetra_CrsGraph( Copy, RowMap, RowMap, &TransNumNZ[0] ); for( int i = 0; i < nRows; ++i ) if( TransNumNZ[i] ) TransposeGraph->InsertMyIndices( i, TransNumNZ[i], &TransIndices[i][0] ); TransposeGraph->FillComplete(); } newObj_ = TransposeGraph; return *TransposeGraph; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc, &argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int NumGlobalElements = 4; // global dimension of the problem int NumMyElements; // local nodes Epetra_IntSerialDenseVector MyGlobalElements; if( Comm.MyPID() == 0 ) { NumMyElements = 3; MyGlobalElements.Size(NumMyElements); MyGlobalElements[0] = 0; MyGlobalElements[1] = 1; MyGlobalElements[2] = 2; } else { NumMyElements = 3; MyGlobalElements.Size(NumMyElements); MyGlobalElements[0] = 1; MyGlobalElements[1] = 2; MyGlobalElements[2] = 3; } // create a map Epetra_Map Map(-1,MyGlobalElements.Length(), MyGlobalElements.Values(),0, Comm); // create a vector based on map Epetra_Vector x(Map); for( int i=0 ; i<NumMyElements ; ++i ) x[i] = 10*( Comm.MyPID()+1 ); cout << x; // create a target map, in which all the elements are on proc 0 int NumMyElements_target; if( Comm.MyPID() == 0 ) NumMyElements_target = NumGlobalElements; else NumMyElements_target = 0; Epetra_Map TargetMap(-1,NumMyElements_target,0,Comm); Epetra_Export Exporter(Map,TargetMap); // work on vectors Epetra_Vector y(TargetMap); y.Export(x,Exporter,Add); cout << y; #ifdef HAVE_MPI MPI_Finalize(); #endif return(EXIT_SUCCESS); }