//============================================================================= double Epetra_MsrMatrix::NormOne() const { if (NormOne_>-1.0) return(NormOne_); if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. Epetra_Vector * x = new Epetra_Vector(RowMatrixRowMap()); // Need temp vector for column sums Epetra_Vector * xp = 0; Epetra_Vector * x_tmp = 0; // If we have a non-trivial importer, we must export elements that are permuted or belong to other processors if (RowMatrixImporter()!=0) { x_tmp = new Epetra_Vector(RowMatrixColMap()); // Create temporary import vector if needed xp = x_tmp; } int i, j; for (i=0; i < NumMyCols_; i++) (*xp)[i] = 0.0; for (i=0; i < NumMyRows_; i++) { int NumEntries = GetRow(i); for (j=0; j < NumEntries; j++) (*xp)[Indices_[j]] += fabs(Values_[j]); } if (RowMatrixImporter()!=0) x->Export(*x_tmp, *RowMatrixImporter(), Add); // Fill x with Values from temp vector x->MaxValue(&NormOne_); // Find max if (x_tmp!=0) delete x_tmp; delete x; UpdateFlops(NumGlobalNonzeros()); return(NormOne_); }
//============================================================================= int Epetra_MsrMatrix::LeftScale(const Epetra_Vector& x) { // // This function scales the ith row of A by x[i]. // // For this method, we have no choice but to work with the UGLY MSR data structures. if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. if (!OperatorRangeMap().SameAs(x.Map())) EPETRA_CHK_ERR(-2); // x must have the same distribution as the range of A int i, j; int * bindx = Amat_->bindx; double * val = Amat_->val; for (i=0; i < NumMyRows_; i++) { int NumEntries = bindx[i+1] - bindx[i]; double scale = x[i]; val[i] *= scale; double * Values = val + bindx[i]; for (j=0; j < NumEntries; j++) Values[j] *= scale; } NormOne_ = -1.0; // Reset Norm so it will be recomputed. NormInf_ = -1.0; // Reset Norm so it will be recomputed. UpdateFlops(NumGlobalNonzeros()); return(0); }
double Epetra_PETScAIJMatrix::NormOne() const { if (NormOne_>-1.0) return(NormOne_); if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. MatNorm(Amat_, NORM_1,&NormOne_); UpdateFlops(NumGlobalNonzeros()); return(NormOne_); }
//============================================================================= //============================================================================= int Epetra_MsrMatrix::InvColSums(Epetra_Vector& x) const { // // Put inverse of the sum of absolute values of the jth column of A in x[j]. // if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. if (!OperatorDomainMap().SameAs(x.Map())) EPETRA_CHK_ERR(-2); // x must have the same distribution as the domain of A Epetra_Vector * xp = 0; Epetra_Vector * x_tmp = 0; // If we have a non-trivial importer, we must export elements that are permuted or belong to other processors if (RowMatrixImporter()!=0) { x_tmp = new Epetra_Vector(RowMatrixColMap()); // Create import vector if needed xp = x_tmp; } int ierr = 0; int i, j; for (i=0; i < NumMyCols_; i++) (*xp)[i] = 0.0; for (i=0; i < NumMyRows_; i++) { int NumEntries = GetRow(i);// Copies ith row of matrix into Values_ and Indices_ for (j=0; j < NumEntries; j++) (*xp)[Indices_[j]] += fabs(Values_[j]); } if (RowMatrixImporter()!=0){ x.Export(*x_tmp, *RowMatrixImporter(), Add); // Fill x with Values from import vector delete x_tmp; xp = &x; } // Invert values, don't allow them to get too large for (i=0; i < NumMyRows_; i++) { double scale = (*xp)[i]; if (scale<Epetra_MinDouble) { if (scale==0.0) ierr = 1; // Set error to 1 to signal that zero rowsum found (supercedes ierr = 2) else if (ierr!=1) ierr = 2; (*xp)[i] = Epetra_MaxDouble; } else (*xp)[i] = 1.0/scale; } UpdateFlops(NumGlobalNonzeros()); EPETRA_CHK_ERR(ierr); return(0); }
void CTestRangeMap::TestRangeMap(void) const { Filling("CRangeMap"); typedef CRangeMultimap<CConstRef<CObject> > TMap; typedef TMap::const_iterator TMapCI; TMap m; // fill for ( int count = 0; count < m_RangeNumber; ) { TRange range = RandomRange(); m.insert(TMap::value_type(range, CConstRef<CObject>(0))); ++count; Added(range); } if ( m_PrintSize ) { Filled(m.size()); // Stat(m.stat()); } for ( TMapCI i = m.begin(); i; ++i ) { FromAll(i.GetInterval()); } size_t scannedCount = 0; for ( int count = 0; count < m_ScanCount; ++count ) { for ( int pos = 0; pos <= m_Length + 2*m_RangeLength; pos += m_ScanStep ) { TRange range; range.Set(pos, pos + m_ScanLength - 1); StartFrom(range); for ( TMapCI i = m.begin(range); i; ++i ) { From(range, i.GetInterval()); ++scannedCount; } } } PrintTotalScannedNumber(scannedCount); End(); }
void CTestRangeMap::TestIntervalTree(void) const { Filling("CIntervalTree"); typedef CIntervalTree TMap; typedef TMap::const_iterator TMapCI; TMap m; // fill for ( int count = 0; count < m_RangeNumber; ) { TRange range = RandomRange(); m.Insert(range, CConstRef<CObject>(0)); ++count; Added(range); } if ( m_PrintSize ) { Filled(m.Size()); Stat(m.Stat()); } for ( TMapCI i = m.AllIntervals(); i; ++i ) { FromAll(i.GetInterval()); } size_t scannedCount = 0; for ( int count = 0; count < m_ScanCount; ++count ) { for ( int pos = 0; pos <= m_Length + 2*m_RangeLength; pos += m_ScanStep ) { TRange range(pos, pos + m_ScanLength - 1); StartFrom(range); for ( TMapCI i = m.IntervalsOverlapping(range); i; ++i ) { From(range, i.GetInterval()); ++scannedCount; } } } PrintTotalScannedNumber(scannedCount); End(); }
//============================================================================= int Epetra_MsrMatrix::RightScale(const Epetra_Vector& x) { // // This function scales the jth row of A by x[j]. // // For this method, we have no choice but to work with the UGLY MSR data structures. if (!Filled()) EPETRA_CHK_ERR(-1); // Matrix must be filled. if (!OperatorDomainMap().SameAs(x.Map())) EPETRA_CHK_ERR(-2); // x must have the same distribution as the domain of A int * bindx = Amat_->bindx; double * val = Amat_->val; Epetra_Vector * xp = 0; Epetra_Vector * x_tmp = 0; // If we have a non-trivial importer, we must import elements that are permuted or are on other processors if (RowMatrixImporter()!=0) { x_tmp = new Epetra_Vector(RowMatrixColMap()); // Create import vector if needed x_tmp->Import(x,*RowMatrixImporter(), Insert); // x_tmp will have all the values we need xp = x_tmp; } int i, j; for (i=0; i < NumMyRows_; i++) { int NumEntries = bindx[i+1] - bindx[i]; double scale = (*xp)[i]; val[i] *= scale; double * Values = val + bindx[i]; int * Indices = bindx + bindx[i]; for (j=0; j < NumEntries; j++) Values[j] *= (*xp)[Indices[j]]; } if (x_tmp!=0) delete x_tmp; NormOne_ = -1.0; // Reset Norm so it will be recomputed. NormInf_ = -1.0; // Reset Norm so it will be recomputed. UpdateFlops(NumGlobalNonzeros()); return(0); }
//============================================================================= 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); }
//============================================================================= 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); }
//============================================================================= 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); }