//============================================================================= int Epetra_FastCrsMatrix::Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { // // This function find Y such that LY = X or UY = X or the transpose cases. // 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(Solve(Upper, Trans, UnitDiagonal, x, y)); } if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. if ((Upper) && (!UpperTriangular())) EPETRA_CHK_ERR(-2); if ((!Upper) && (!LowerTriangular())) EPETRA_CHK_ERR(-3); if ((!UnitDiagonal) && (NoDiagonal())) EPETRA_CHK_ERR(-4); // If matrix has no diagonal, we must use UnitDiagonal if ((!UnitDiagonal) && (NumMyDiagonals()<NumMyRows_)) EPETRA_CHK_ERR(-5); // Need each row to have a diagonal int i, j, j0, k; int * NumEntriesPerRow = NumEntriesPerRow_; int ** Indices = Indices_; double ** Values = Values_; double diag; // If upper, point to last row if ((Upper && !Trans) || (!Upper && Trans)) { NumEntriesPerRow += NumMyRows_-1; Indices += NumMyRows_-1; Values += NumMyRows_-1; } double **Xp = (double**)X.Pointers(); double **Yp = (double**)Y.Pointers(); int NumVectors = X.NumVectors(); if (!Trans) { if (Upper) { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=NumMyRows_-1; i >=0; i--) { int NumEntries = *NumEntriesPerRow--; int * RowIndices = *Indices--; double * RowValues = *Values--; if (!UnitDiagonal) diag = 1.0/RowValues[0]; // Take inverse of diagonal once for later use for (k=0; k<NumVectors; k++) { double sum = 0.0; for (j=j0; j < NumEntries; j++) sum += RowValues[j] * Yp[k][RowIndices[j]]; if (UnitDiagonal) Yp[k][i] = Xp[k][i] - sum; else Yp[k][i] = (Xp[k][i] - sum)*diag; } } } else { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++ - j0; int * RowIndices = *Indices++; double * RowValues = *Values++; if (!UnitDiagonal) diag = 1.0/RowValues[NumEntries]; // Take inverse of diagonal once for later use for (k=0; k<NumVectors; k++) { double sum = 0.0; for (j=0; j < NumEntries; j++) sum += RowValues[j] * Yp[k][RowIndices[j]]; if (UnitDiagonal) Yp[k][i] = Xp[k][i] - sum; else Yp[k][i] = (Xp[k][i] - sum)*diag; } } } } // *********** Transpose case ******************************* else { for (k=0; k<NumVectors; k++) if (Yp[k]!=Xp[k]) for (i=0; i < NumMyRows_; i++) Yp[k][i] = Xp[k][i]; // Initialize y for transpose multiply if (Upper) { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++; int * RowIndices = *Indices++; double * RowValues = *Values++; if (!UnitDiagonal) diag = 1.0/RowValues[j0]; // Take inverse of diagonal once for later use for (k=0; k<NumVectors; k++) { if (!UnitDiagonal) Yp[k][i] = Yp[k][i]*diag; for (j=j0; j < NumEntries; j++) Yp[k][RowIndices[j]] -= RowValues[j] * Yp[k][i]; } } } else { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=NumMyRows_-1; i>=0; i--) { int NumEntries = *NumEntriesPerRow-- - j0; int * RowIndices = *Indices--; double * RowValues = *Values--; for (k=0; k<NumVectors; k++) { if (!UnitDiagonal) Yp[k][i] = Yp[k][i]/Xp[k][i]; for (j=0; j < NumEntries; j++) Yp[k][RowIndices[j]] -= RowValues[j] * Yp[k][i]; } } } } UpdateFlops(2*NumVectors*NumGlobalNonzeros64()); return(0); }
//============================================================================= void Epetra_MsrMatrix::Print(ostream& os) const { int MyPID = RowMatrixRowMap().Comm().MyPID(); int NumProc = RowMatrixRowMap().Comm().NumProc(); for (int iproc=0; iproc < NumProc; iproc++) { if (MyPID==iproc) { /* const Epetra_fmtflags olda = os.setf(ios::right,ios::adjustfield); const Epetra_fmtflags oldf = os.setf(ios::scientific,ios::floatfield); const int oldp = os.precision(12); */ if (MyPID==0) { os << "\nNumber of Global Rows = "; os << NumGlobalRows(); os << endl; os << "Number of Global Cols = "; os << NumGlobalCols(); os << endl; os << "Number of Global Diagonals = "; os << NumGlobalDiagonals(); os << endl; os << "Number of Global Nonzeros = "; os << NumGlobalNonzeros(); os << endl; if (LowerTriangular()) os << " ** Matrix is Lower Triangular **"; os << endl; if (UpperTriangular()) os << " ** Matrix is Upper Triangular **"; os << endl; } os << "\nNumber of My Rows = "; os << NumMyRows(); os << endl; os << "Number of My Cols = "; os << NumMyCols(); os << endl; os << "Number of My Diagonals = "; os << NumMyDiagonals(); os << endl; os << "Number of My Nonzeros = "; os << NumMyNonzeros(); os << endl; os << endl; os << flush; // Reset os flags /* os.setf(olda,ios::adjustfield); os.setf(oldf,ios::floatfield); os.precision(oldp); */ } // Do a few global ops to give I/O a chance to complete Comm().Barrier(); Comm().Barrier(); Comm().Barrier(); } {for (int iproc=0; iproc < NumProc; iproc++) { if (MyPID==iproc) { int i, j; if (MyPID==0) { os.width(8); os << " Processor "; os.width(10); os << " Row Index "; os.width(10); os << " Col Index "; os.width(20); os << " Value "; os << endl; } for (i=0; i<NumMyRows_; i++) { int Row = RowMatrixRowMap().GID(i); // Get global row number int NumEntries = GetRow(i); // ith row is now in Values_ and Indices_ for (j = 0; j < NumEntries ; j++) { os.width(8); os << MyPID ; os << " "; os.width(10); os << Row ; os << " "; os.width(10); os << RowMatrixColMap().GID(Indices_[j]); os << " "; os.width(20); os << Values_[j]; os << " "; os << endl; } } os << flush; } // Do a few global ops to give I/O a chance to complete RowMatrixRowMap().Comm().Barrier(); RowMatrixRowMap().Comm().Barrier(); RowMatrixRowMap().Comm().Barrier(); }} return; }
//============================================================================= int Epetra_FastCrsMatrix::Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_Vector& x, Epetra_Vector& y) const { // // This function find y such that Ly = x or Uy = x or the transpose cases. // if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. if ((Upper) && (!UpperTriangular())) EPETRA_CHK_ERR(-2); if ((!Upper) && (!LowerTriangular())) EPETRA_CHK_ERR(-3); if ((!UnitDiagonal) && (NoDiagonal())) EPETRA_CHK_ERR(-4); // If matrix has no diagonal, we must use UnitDiagonal if ((!UnitDiagonal) && (NumMyDiagonals()<NumMyRows_)) EPETRA_CHK_ERR(-5); // Need each row to have a diagonal int i, j, j0; int * NumEntriesPerRow = NumEntriesPerRow_; int ** Indices = Indices_; double ** Values = Values_; int NumMyCols_ = NumMyCols(); // If upper, point to last row if ((Upper && !Trans) || (!Upper && Trans)) { NumEntriesPerRow += NumMyRows_-1; Indices += NumMyRows_-1; Values += NumMyRows_-1; } double *xp = (double*)x.Values(); double *yp = (double*)y.Values(); if (!Trans) { if (Upper) { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=NumMyRows_-1; i >=0; i--) { int NumEntries = *NumEntriesPerRow--; int * RowIndices = *Indices--; double * RowValues = *Values--; double sum = 0.0; for (j=j0; j < NumEntries; j++) sum += RowValues[j] * yp[RowIndices[j]]; if (UnitDiagonal) yp[i] = xp[i] - sum; else yp[i] = (xp[i] - sum)/RowValues[0]; } } else { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++ - j0; int * RowIndices = *Indices++; double * RowValues = *Values++; double sum = 0.0; for (j=0; j < NumEntries; j++) sum += RowValues[j] * yp[RowIndices[j]]; if (UnitDiagonal) yp[i] = xp[i] - sum; else yp[i] = (xp[i] - sum)/RowValues[NumEntries]; } } } // *********** Transpose case ******************************* else { if (xp!=yp) for (i=0; i < NumMyCols_; i++) yp[i] = xp[i]; // Initialize y for transpose solve if (Upper) { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=0; i < NumMyRows_; i++) { int NumEntries = *NumEntriesPerRow++; int * RowIndices = *Indices++; double * RowValues = *Values++; if (!UnitDiagonal) yp[i] = yp[i]/RowValues[0]; for (j=j0; j < NumEntries; j++) yp[RowIndices[j]] -= RowValues[j] * yp[i]; } } else { j0 = 1; if (NoDiagonal()) j0--; // Include first term if no diagonal for (i=NumMyRows_-1; i >= 0; i--) { int NumEntries = *NumEntriesPerRow-- - j0; int * RowIndices = *Indices--; double * RowValues = *Values--; if (!UnitDiagonal) yp[i] = yp[i]/RowValues[NumEntries]; for (j=0; j < NumEntries; j++) yp[RowIndices[j]] -= RowValues[j] * yp[i]; } } } UpdateFlops(2*NumGlobalNonzeros64()); return(0); }