bool compare_matrices(const Epetra_CrsMatrix& A, const Epetra_CrsMatrix& B) { const Epetra_Map& Amap = A.RowMap(); const Epetra_Map& Bmap = B.RowMap(); if (!Amap.PointSameAs(Bmap)) { return(false); } int numRows = Amap.NumMyElements(); int* rows = Amap.MyGlobalElements(); Epetra_Util util; for(int i=0; i<numRows; ++i) { int row = rows[i]; int rowLen = A.NumGlobalEntries(row); if (rowLen != B.NumGlobalEntries(row)) { return(false); } int* indices = new int[rowLen*2]; int* Bindices = indices+rowLen; double* values = new double[rowLen*2]; double* Bvalues = values+rowLen; A.ExtractGlobalRowCopy(row, rowLen, rowLen, values, indices); B.ExtractGlobalRowCopy(row, rowLen, rowLen, Bvalues, Bindices); util.Sort(true, rowLen, indices, 1, &values, 0, 0); util.Sort(true, rowLen, Bindices, 1, &Bvalues, 0, 0); bool same = true; for(int j=0; j<rowLen; ++j) { if (indices[j] != Bindices[j]) { same = false; break; } if (values[j] != Bvalues[j]) { same = false; break; } } delete [] indices; delete [] values; if (!same) { return(false); } } return(true); }
int main (int argc, char *argv[]) { // These "using" statements make the code a bit more concise. using std::cout; using std::endl; int ierr = 0, i; // If Trilinos was built with MPI, initialize MPI, otherwise // initialize the serial "communicator" that stands in for MPI. #ifdef EPETRA_MPI MPI_Init (&argc,&argv); Epetra_MpiComm Comm (MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif const int MyPID = Comm.MyPID(); const int NumProc = Comm.NumProc(); // We only allow (MPI) Process 0 to write to stdout. const bool verbose = (MyPID == 0); const int NumGlobalElements = 100; if (verbose) cout << Epetra_Version() << endl << endl; // Asking the Epetra_Comm to print itself is a good test for whether // you are running in an MPI environment. However, it will print // something on all MPI processes, so you should remove it for a // large-scale parallel run. cout << Comm << endl; if (NumGlobalElements < NumProc) { if (verbose) cout << "numGlobalBlocks = " << NumGlobalElements << " cannot be < number of processors = " << NumProc << endl; std::exit (EXIT_FAILURE); } // Construct a Map that puts approximately the same number of rows // of the matrix A on each processor. Epetra_Map Map (NumGlobalElements, 0, Comm); // Get update list and number of local equations from newly created Map. int NumMyElements = Map.NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map.MyGlobalElements(&MyGlobalElements[0]); // NumNz[i] is the number of nonzero elements in row i of the sparse // matrix on this MPI process. Epetra_CrsMatrix uses this to figure // out how much space to allocate. std::vector<int> NumNz (NumMyElements); // We are building a tridiagonal matrix where each row contains the // nonzero elements (-1 2 -1). Thus, we need 2 off-diagonal terms, // except for the first and last row of the matrix. for (int i = 0; i < NumMyElements; ++i) if (MyGlobalElements[i] == 0 || MyGlobalElements[i] == NumGlobalElements-1) NumNz[i] = 2; // First or last row else NumNz[i] = 3; // Not the (first or last row) // Create the Epetra_CrsMatrix. Epetra_CrsMatrix A (Copy, Map, &NumNz[0]); // // Add rows to the sparse matrix one at a time. // std::vector<double> Values(2); Values[0] = -1.0; Values[1] = -1.0; std::vector<int> Indices(2); const double two = 2.0; int NumEntries; for (int i = 0; i < NumMyElements; ++i) { if (MyGlobalElements[i] == 0) { // The first row of the matrix. Indices[0] = 1; NumEntries = 1; } else if (MyGlobalElements[i] == NumGlobalElements - 1) { // The last row of the matrix. Indices[0] = NumGlobalElements-2; NumEntries = 1; } else { // Any row of the matrix other than the first or last. Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; NumEntries = 2; } ierr = A.InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert (ierr==0); // Insert the diagonal entry. ierr = A.InsertGlobalValues(MyGlobalElements[i], 1, &two, &MyGlobalElements[i]); assert(ierr==0); } // Finish up. We can call FillComplete() with no arguments, because // the matrix is square. ierr = A.FillComplete (); assert (ierr==0); // Parameters for the power method. const int niters = NumGlobalElements*10; const double tolerance = 1.0e-2; // // Run the power method. Keep track of the flop count and the total // elapsed time. // Epetra_Flops counter; A.SetFlopCounter(counter); Epetra_Time timer(Comm); double lambda = 0.0; ierr += powerMethod (lambda, A, niters, tolerance, verbose); double elapsedTime = timer.ElapsedTime (); double totalFlops =counter.Flops (); // Mflop/s: Million floating-point arithmetic operations per second. double Mflop_per_s = totalFlops / elapsedTime / 1000000.0; if (verbose) cout << endl << endl << "Total Mflop/s for first solve = " << Mflop_per_s << endl<< endl; // Increase the first (0,0) diagonal entry of the matrix. if (verbose) cout << endl << "Increasing magnitude of first diagonal term, solving again" << endl << endl << endl; if (A.MyGlobalRow (0)) { int numvals = A.NumGlobalEntries (0); std::vector<double> Rowvals (numvals); std::vector<int> Rowinds (numvals); A.ExtractGlobalRowCopy (0, numvals, numvals, &Rowvals[0], &Rowinds[0]); // Get A(0,0) for (int i = 0; i < numvals; ++i) if (Rowinds[i] == 0) Rowvals[i] *= 10.0; A.ReplaceGlobalValues (0, numvals, &Rowvals[0], &Rowinds[0]); } // // Run the power method again. Keep track of the flop count and the // total elapsed time. // lambda = 0.0; timer.ResetStartTime(); counter.ResetFlops(); ierr += powerMethod (lambda, A, niters, tolerance, verbose); elapsedTime = timer.ElapsedTime(); totalFlops = counter.Flops(); Mflop_per_s = totalFlops / elapsedTime / 1000000.0; if (verbose) cout << endl << endl << "Total Mflop/s for second solve = " << Mflop_per_s << endl << endl; #ifdef EPETRA_MPI MPI_Finalize() ; #endif return ierr; }
bool matrix_data::compare_local_data(const Epetra_CrsMatrix& A) { const Epetra_Map& map = A.RowMap(); int numMyRows = map.NumMyElements(); Epetra_Util util; if(map.GlobalIndicesInt()) { #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES int* myRows_int = map.MyGlobalElements(); for(int i=0; i<numMyRows; ++i) { int row = myRows_int[i]; int rowLen = A.NumGlobalEntries(row); if (rowLen != rowlengths_[row]) { return(false); } int* indices = new int[rowLen]; double* values = new double[rowLen]; A.ExtractGlobalRowCopy(row, rowLen, rowLen, values, indices); util.Sort(true, rowLen, indices, 1, &values, 0, 0, 0, 0); bool same = true; int* this_indices = colindices_[row]; double* this_coefs = coefs_[row]; for(int j=0; j<rowLen; ++j) { if (indices[j] != this_indices[j]) { same = false; break; } if (values[j] != this_coefs[j]) { same = false; break; } } delete [] indices; delete [] values; if (!same) return(false); } #else throw "matrix_data::compare_local_data: global index int but no API for it."; #endif } else if(map.GlobalIndicesLongLong()) { #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES long long* myRows_LL = map.MyGlobalElements64(); for(int i=0; i<numMyRows; ++i) { long long row = myRows_LL[i]; int rowLen = A.NumGlobalEntries(row); if (rowLen != rowlengths_[row]) { return(false); } long long* indices = new long long[rowLen]; double* values = new double[rowLen]; A.ExtractGlobalRowCopy(row, rowLen, rowLen, values, indices); util.Sort(true, rowLen, indices, 1, &values, 0, 0, 0, 0); bool same = true; int* this_indices = colindices_[row]; double* this_coefs = coefs_[row]; for(int j=0; j<rowLen; ++j) { if (indices[j] != this_indices[j]) { same = false; break; } if (values[j] != this_coefs[j]) { same = false; break; } } delete [] indices; delete [] values; if (!same) return(false); } #else throw "matrix_data::compare_local_data: global index long long but no API for it."; #endif } else { assert(false); throw "matrix_data::compare_local_data: global index type of map unknown."; } return(true); }