//============================================================================= 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::Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { (void)TransA; int NumVectors = X.NumVectors(); if (NumVectors!=Y.NumVectors()) EPETRA_CHK_ERR(-1); // X and Y must have same number of vectors double ** xptrs; double ** yptrs; X.ExtractView(&xptrs); Y.ExtractView(&yptrs); if (RowMatrixImporter()!=0) { if (ImportVector_!=0) { if (ImportVector_->NumVectors()!=NumVectors) { delete ImportVector_; ImportVector_= 0;} } if (ImportVector_==0) ImportVector_ = new Epetra_MultiVector(RowMatrixColMap(),NumVectors); // Create import vector if needed ImportVector_->Import(X, *RowMatrixImporter(), Insert); ImportVector_->ExtractView(&xptrs); } for (int i=0; i<NumVectors; i++) Amat_->matvec(xptrs[i], yptrs[i], Amat_, proc_config_); double flops = NumGlobalNonzeros(); flops *= 2.0; flops *= (double) NumVectors; UpdateFlops(flops); return(0); }
int Epetra_PETScAIJMatrix::Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { (void)TransA; int NumVectors = X.NumVectors(); if (NumVectors!=Y.NumVectors()) EPETRA_CHK_ERR(-1); // X and Y must have same number of vectors double ** xptrs; double ** yptrs; X.ExtractView(&xptrs); Y.ExtractView(&yptrs); if (RowMatrixImporter()!=0) { if (ImportVector_!=0) { if (ImportVector_->NumVectors()!=NumVectors) { delete ImportVector_; ImportVector_= 0;} } if (ImportVector_==0) ImportVector_ = new Epetra_MultiVector(RowMatrixColMap(),NumVectors); ImportVector_->Import(X, *RowMatrixImporter(), Insert); ImportVector_->ExtractView(&xptrs); } double *vals=0; int length; Vec petscX, petscY; int ierr; for (int i=0; i<NumVectors; i++) { # ifdef HAVE_MPI ierr=VecCreateMPIWithArray(Comm_->Comm(),X.MyLength(),X.GlobalLength(),xptrs[i],&petscX); CHKERRQ(ierr); ierr=VecCreateMPIWithArray(Comm_->Comm(),Y.MyLength(),Y.GlobalLength(),yptrs[i],&petscY); CHKERRQ(ierr); # else //FIXME untested ierr=VecCreateSeqWithArray(Comm_->Comm(),X.MyLength(),X.GlobalLength(),xptrs[i],&petscX); CHKERRQ(ierr); ierr=VecCreateSeqWithArray(Comm_->Comm(),Y.MyLength(),Y.GlobalLength(),yptrs[i],&petscY); CHKERRQ(ierr); # endif ierr = MatMult(Amat_,petscX,petscY);CHKERRQ(ierr); ierr = VecGetArray(petscY,&vals);CHKERRQ(ierr); ierr = VecGetLocalSize(petscY,&length);CHKERRQ(ierr); for (int j=0; j<length; j++) yptrs[i][j] = vals[j]; ierr = VecRestoreArray(petscY,&vals);CHKERRQ(ierr); } VecDestroy(petscX); VecDestroy(petscY); double flops = NumGlobalNonzeros(); flops *= 2.0; flops *= (double) NumVectors; UpdateFlops(flops); return(0); } //Multiply()
//============================================================================= //============================================================================= 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); }
//============================================================================= 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); }