//============================================================================= 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_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_SerialSpdDenseSolver::Factor(void) { if (Factored()) return(0); // Already factored if (Inverted()) EPETRA_CHK_ERR(-100); // Cannot factor inverted matrix int ierr = 0; ANORM_ = SymMatrix_->OneNorm(); // If we want to refine the solution, then the factor must // be stored separatedly from the original matrix if (A_ == AF_) if (RefineSolution_ ) { SymFactor_ = new Epetra_SerialSymDenseMatrix(*SymMatrix_); Factor_ = SymFactor_; AF_ = SymFactor_->A(); LDAF_ = SymFactor_->LDA(); } if (Equilibrate_) ierr = EquilibrateMatrix(); if (ierr!=0) EPETRA_CHK_ERR(ierr-2); POTRF (SymMatrix_->UPLO(), N_, AF_, LDAF_, &INFO_); Factored_ = true; double DN = N_; UpdateFlops((DN*DN*DN)/3.0); EPETRA_CHK_ERR(INFO_); return(0); }
//============================================================================= 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_MsrMatrix::InvRowSums(Epetra_Vector& x) const { // // Put inverse of the sum of absolute values of the ith row of A in x[i]. // if (!OperatorRangeMap().SameAs(x.Map())) EPETRA_CHK_ERR(-2); // x must have the same distribution as the range of A int ierr = 0; int i, j; for (i=0; i < NumMyRows_; i++) { int NumEntries = GetRow(i); // Copies ith row of matrix into Values_ and Indices_ double scale = 0.0; for (j=0; j < NumEntries; j++) scale += fabs(Values_[j]); 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; x[i] = Epetra_MaxDouble; } else x[i] = 1.0/scale; } UpdateFlops(NumGlobalNonzeros()); EPETRA_CHK_ERR(ierr); return(0); }
//============================================================================= int Epetra_SerialSpdDenseSolver::ApplyRefinement(void) { double DN = N_; double DNRHS = NRHS_; if (!Solved()) EPETRA_CHK_ERR(-100); // Must have an existing solution if (A_==AF_) EPETRA_CHK_ERR(-101); // Cannot apply refine if no original copy of A. if (FERR_ != 0) delete [] FERR_; // Always start with a fresh copy of FERR_, since NRHS_ may change FERR_ = new double[NRHS_]; if (BERR_ != 0) delete [] BERR_; // Always start with a fresh copy of FERR_, since NRHS_ may change BERR_ = new double[NRHS_]; AllocateWORK(); AllocateIWORK(); PORFS(SymMatrix_->UPLO(), N_, NRHS_, A_, LDA_, AF_, LDAF_, B_, LDB_, X_, LDX_, FERR_, BERR_, WORK_, IWORK_, &INFO_); SolutionErrorsEstimated_ = true; ReciprocalConditionEstimated_ = true; SolutionRefined_ = true; UpdateFlops(2.0*DN*DN*DNRHS); // Not sure of count EPETRA_CHK_ERR(INFO_); return(0); }
//======================================================= int EpetraExt_HypreIJMatrix::RightScale(const Epetra_Vector& X) { // First we need to import off-processor values of the vector Epetra_Import Importer(RowMatrixColMap(), RowMatrixRowMap()); Epetra_Vector Import_Vector(RowMatrixColMap(), true); EPETRA_CHK_ERR(Import_Vector.Import(X, Importer, Insert, 0)); for(int i = 0; i < NumMyRows_; i++){ //Vector-scalar mult on ith column int num_entries; double *values; int *indices; // Get values and indices of ith row of matrix EPETRA_CHK_ERR(HYPRE_ParCSRMatrixGetRow(ParMatrix_,i+MyRowStart_, &num_entries, &indices, &values)); EPETRA_CHK_ERR(HYPRE_ParCSRMatrixRestoreRow(ParMatrix_,i+MyRowStart_,&num_entries,&indices,&values)); Teuchos::Array<int> new_indices; new_indices.resize(num_entries); Teuchos::Array<double> new_values; new_values.resize(num_entries); for(int j = 0; j < num_entries; j++){ // Multiply column j with jth element int index = RowMatrixColMap().LID(indices[j]); TEUCHOS_TEST_FOR_EXCEPTION(index < 0, std::logic_error, "Index is negtive."); new_values[j] = values[j] * Import_Vector[index]; new_indices[j] = indices[j]; } // Finally set values of the Matrix for this row int rows[1]; rows[0] = i+MyRowStart_; EPETRA_CHK_ERR(HYPRE_IJMatrixSetValues(Matrix_, 1, &num_entries, rows, &new_indices[0], &new_values[0])); } HaveNumericConstants_ = false; UpdateFlops(NumGlobalNonzeros()); return 0; } //RightScale()
double Epetra_PETScAIJMatrix::NormInf() const { if (NormInf_>-1.0) return(NormInf_); MatNorm(Amat_, NORM_INFINITY,&NormInf_); UpdateFlops(NumGlobalNonzeros()); return(NormInf_); }
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_); }
//========================================================================= double Epetra_SerialDenseVector::Norm2() const { // 2-norm of vector double result = NRM2(Length(), Values()); UpdateFlops(2*Length()); return(result); }
//======================================================= int EpetraExt_HypreIJMatrix::Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { //printf("Proc[%d], Row start: %d, Row End: %d\n", Comm().MyPID(), MyRowStart_, MyRowEnd_); bool SameVectors = false; int NumVectors = X.NumVectors(); if (NumVectors != Y.NumVectors()) return -1; // X and Y must have same number of vectors if(X.Pointers() == Y.Pointers()){ SameVectors = true; } for(int VecNum = 0; VecNum < NumVectors; VecNum++) { //Get values for current vector in multivector. double * x_values; double * y_values; EPETRA_CHK_ERR((*X(VecNum)).ExtractView(&x_values)); double *x_temp = x_local->data; double *y_temp = y_local->data; if(!SameVectors){ EPETRA_CHK_ERR((*Y(VecNum)).ExtractView(&y_values)); } else { y_values = new double[X.MyLength()]; } y_local->data = y_values; EPETRA_CHK_ERR(HYPRE_ParVectorSetConstantValues(par_y,0.0)); // Temporarily make a pointer to data in Hypre for end // Replace data in Hypre vectors with epetra values x_local->data = x_values; // Do actual computation. if(TransA) { // Use transpose of A in multiply EPETRA_CHK_ERR(HYPRE_ParCSRMatrixMatvecT(1.0, ParMatrix_, par_x, 1.0, par_y)); } else { EPETRA_CHK_ERR(HYPRE_ParCSRMatrixMatvec(1.0, ParMatrix_, par_x, 1.0, par_y)); } if(SameVectors){ int NumEntries = Y.MyLength(); std::vector<double> new_values; new_values.resize(NumEntries); std::vector<int> new_indices; new_indices.resize(NumEntries); for(int i = 0; i < NumEntries; i++){ new_values[i] = y_values[i]; new_indices[i] = i; } EPETRA_CHK_ERR((*Y(VecNum)).ReplaceMyValues(NumEntries, &new_values[0], &new_indices[0])); delete[] y_values; } x_local->data = x_temp; y_local->data = y_temp; } double flops = (double) NumVectors * (double) NumGlobalNonzeros(); UpdateFlops(flops); return 0; } //Multiply()
//============================================================================= int Epetra_SerialDenseSVD::Invert( double rthresh, double athresh ) { if (!Factored()) Factor(); // Need matrix factored. //apply threshold double thresh = S_[0]*rthresh + athresh; int num_replaced = 0; for( int i = 0; i < M_; ++i ) if( S_[i] < thresh ) { //cout << num_replaced << thresh << " " << S_[0] << " " << S_[i] << std::endl; // S_[i] = thresh; S_[i] = 0.0; ++num_replaced; } //scale cols of U_ with reciprocal singular values double *p = U_; for( int i = 0; i < N_; ++i ) { double scale = 0.0; if( S_[i] ) scale = 1./S_[i]; for( int j = 0; j < M_; ++j ) *p++ *= scale; } //create new Inverse_ if necessary if( Inverse_ == 0 ) { Inverse_ = new Epetra_SerialDenseMatrix(); Inverse_->Shape( N_, M_ ); AI_ = Inverse_->A(); LDAI_ = Inverse_->LDA(); } /* else //zero it out { for( int i = 0; i < Inverse_->M(); ++i ) for( int j = 0; j < Inverse_->N(); ++j ) (*Inverse_)(i,j) = 0.0; } */ GEMM( 'T', 'T', M_, M_, M_, 1.0, Vt_, M_, U_, M_, 0.0, AI_, M_ ); double DN = N_; UpdateFlops((DN*DN*DN)); Inverted_ = true; Factored_ = false; EPETRA_CHK_ERR(INFO_); return(num_replaced); }
//============================================================================= int Epetra_SerialSpdDenseSolver::Invert(void) { if (!Factored()) Factor(); // Need matrix factored. POTRI ( SymMatrix_->UPLO(), N_, AF_, LDAF_, &INFO_); // Copy lower/upper triangle to upper/lower triangle: make full inverse SymMatrix_->CopyUPLOMat(SymMatrix_->Upper(), AF_, LDAF_, N_); double DN = N_; UpdateFlops((DN*DN*DN)); Inverted_ = true; Factored_ = false; EPETRA_CHK_ERR(INFO_); 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); }
//============================================================================= double Epetra_MsrMatrix::NormInf() const { if (NormInf_>-1.0) return(NormInf_); double Local_NormInf = 0.0; for (int i=0; i < NumMyRows_; i++) { int NumEntries = GetRow(i); double sum = 0.0; for (int j=0; j < NumEntries; j++) sum += fabs(Values_[j]); Local_NormInf = EPETRA_MAX(Local_NormInf, sum); } Comm().MaxAll(&Local_NormInf, &NormInf_, 1); UpdateFlops(NumGlobalNonzeros()); return(NormInf_); }
//========================================================================= double Epetra_SerialDenseVector::Dot(const Epetra_SerialDenseVector & x) const { #ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK if (Length()!=x.Length()) throw ReportError("Length of this object = " + toString(Length()) + " is not equal to length of x = " + toString(x.Length()), -1); #endif // dot-product of this and x. double result = DOT(Length(), Values(), x.Values()); UpdateFlops(2*Length()); return(result); }
//============================================================================= int Epetra_SerialSpdDenseSolver::ComputeEquilibrateScaling(void) { if (R_!=0) return(0); // Already computed double DN = N_; R_ = new double[N_]; C_ = R_; POEQU (N_, AF_, LDAF_, R_, &SCOND_, &AMAX_, &INFO_); if (INFO_ != 0) EPETRA_CHK_ERR(INFO_); if (SCOND_<0.1 || AMAX_ < Epetra_Underflow || AMAX_ > Epetra_Overflow) ShouldEquilibrate_ = true; C_ = R_; // Set column scaling pointer so we can use EquilibrateRHS and UnequilibrateLHS from base class UpdateFlops(2.0*DN*DN); return(0); }
//============================================================================= int Epetra_SerialDenseSVD::Factor() { int ierr = 0; ANORM_ = Matrix_->OneNorm(); // Compute 1-Norm of A //allocate U_, S_, and Vt_ if not already done if(U_==0) { U_ = new double[M_*N_]; S_ = new double[M_]; Vt_ = new double[M_*N_]; } else //zero them out { for( int i = 0; i < M_; ++i ) S_[i]=0.0; for( int i = 0; i < M_*N_; ++i ) { U_[i]=0.0; Vt_[i]=0.0; } } // if (Equilibrate_) ierr = EquilibrateMatrix(); if (ierr!=0) EPETRA_CHK_ERR(ierr-2); //allocate temp work space int lwork = 5*M_; double *work = new double[lwork]; char job = 'A'; //create temporary matrix to avoid writeover of original Epetra_SerialDenseMatrix tempMat( *Matrix_ ); GESVD( job, job, M_, N_, tempMat.A(), LDA_, S_, U_, N_, Vt_, M_, work, &lwork, &INFO_ ); delete [] work; Factored_ = true; double DN = N_; UpdateFlops(2.0*(DN*DN*DN)/3.0); EPETRA_CHK_ERR(INFO_); return(0); }
int InverseOperator::Apply(const MultiVector& x, MultiVector& y) const { ResetTimer(); StackPush(); if (GetDomainSpace() != x.GetVectorSpace()) ML_THROW("DomainSpace and x.GetVectorSpace() differ", -1); if (GetRangeSpace() != y.GetVectorSpace()) ML_THROW("RangeSpace and y.GetVectorSpace() differ", -1); int x_nv = x.GetNumVectors(); int y_nv = y.GetNumVectors(); double FL = 0.0; if (RCPData_ != Teuchos::null) FL = RCPData_->ComputeFlops(); if (x_nv != y_nv) ML_THROW("Number of vectors of x and y differ (" + GetString(x_nv) + " vs. " + GetString(x_nv), -1); for (int v = 0 ; v < x_nv ; ++v) { Epetra_Vector x_Epetra(View,RowMatrix()->OperatorDomainMap(), (double*)&(x(0,v))); Epetra_Vector y_Epetra(View,RowMatrix()->OperatorRangeMap(), (double*)&(y(0,v))); if (RCPData_ != Teuchos::null) RCPData_->ApplyInverse(x_Epetra,y_Epetra); else if (RCPMLPrec_ != Teuchos::null) RCPMLPrec_->ApplyInverse(x_Epetra,y_Epetra); else ML_THROW("Neither Ifpack nor ML smoother is properly set up", -1); } StackPop(); if (RCPData_ != Teuchos::null) UpdateFlops(RCPData_->ComputeFlops() - FL); UpdateTime(); return(0); }
//============================================================================= int Epetra_SerialSymDenseMatrix::Scale(double ScalarA) { int i, j; double * ptr; if (!Upper()) { for (j=0; j<N_; j++) { ptr = A_ + j + j*LDA_; for (i=j; i<N_; i++) {*ptr = *ptr * ScalarA; ptr++;} } } else { for (j=0; j<N_; j++) { ptr = A_ + j*LDA_; for (i=0; i<j; i++) {*ptr = *ptr * ScalarA; ptr++;} } } UpdateFlops(N_*(N_+1)/2); return(0); }
//============================================================================= int Epetra_SerialSpdDenseSolver::ReciprocalConditionEstimate(double & Value) { int ierr = 0; if (ReciprocalConditionEstimated()) { Value = RCOND_; return(0); // Already computed, just return it. } if (ANORM_<0.0) ANORM_ = SymMatrix_->OneNorm(); if (ierr!=0) EPETRA_CHK_ERR(ierr-1); if (!Factored()) ierr = Factor(); // Need matrix factored. if (ierr!=0) EPETRA_CHK_ERR(ierr-2); AllocateWORK(); AllocateIWORK(); POCON( SymMatrix_->UPLO(), N_, AF_, LDAF_, ANORM_, &RCOND_, WORK_, IWORK_, &INFO_); ReciprocalConditionEstimated_ = true; Value = RCOND_; UpdateFlops(2*N_*N_); // Not sure of count EPETRA_CHK_ERR(INFO_); 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); }
//======================================================= int EpetraExt_HypreIJMatrix::LeftScale(const Epetra_Vector& X) { for(int i = 0; i < NumMyRows_; i++){ //Vector-scalar mult on ith row int num_entries; int *indices; double *values; EPETRA_CHK_ERR(HYPRE_ParCSRMatrixGetRow(ParMatrix_,i+MyRowStart_, &num_entries, &indices, &values)); EPETRA_CHK_ERR(HYPRE_ParCSRMatrixRestoreRow(ParMatrix_,i+MyRowStart_, &num_entries, &indices, &values)); Teuchos::Array<double> new_values; new_values.resize(num_entries); Teuchos::Array<int> new_indices; new_indices.resize(num_entries); for(int j = 0; j < num_entries; j++){ // Scale this row with the appropriate values from the vector new_values[j] = X[i]*values[j]; new_indices[j] = indices[j]; } int rows[1]; rows[0] = i+MyRowStart_; EPETRA_CHK_ERR(HYPRE_IJMatrixSetValues(Matrix_, 1, &num_entries, rows, &new_indices[0], &new_values[0])); // Finally set values of the Matrix for this row } HaveNumericConstants_ = false; UpdateFlops(NumGlobalNonzeros()); return 0; } //LeftScale()
//============================================================================= double Epetra_SerialSymDenseMatrix::NormInf(void) const { int i, j; double anorm = 0.0; double * ptr; if (!Upper()) { for (j=0; j<N_; j++) { double sum = 0.0; ptr = A_ + j + j*LDA_; for (i=j; i<N_; i++) sum += std::abs(*ptr++); ptr = A_ + j; for (i=0; i<j; i++) { sum += std::abs(*ptr); ptr += LDA_; } anorm = EPETRA_MAX(anorm, sum); } } else { for (j=0; j<N_; j++) { double sum = 0.0; ptr = A_ + j*LDA_; for (i=0; i<j; i++) sum += std::abs(*ptr++); ptr = A_ + j + j*LDA_; for (i=j; i<N_; i++) { sum += std::abs(*ptr); ptr += LDA_; } anorm = EPETRA_MAX(anorm, sum); } } UpdateFlops(N_*N_); return(anorm); }
//========================================================================== int Ifpack_CrsIct::Factor() { // if (!Allocated()) return(-1); // This test is not needed at this time. All constructors allocate. if (!ValuesInitialized_) EPETRA_CHK_ERR(-2); // Must have values initialized. if (Factored()) EPETRA_CHK_ERR(-3); // Can't have already computed factors. SetValuesInitialized(false); int i; int m, n, nz, Nrhs, ldrhs, ldlhs; int * ptr=0, * ind; double * val, * rhs, * lhs; int ierr = Epetra_Util_ExtractHbData(U_.get(), 0, 0, m, n, nz, ptr, ind, val, Nrhs, rhs, ldrhs, lhs, ldlhs); if (ierr<0) EPETRA_CHK_ERR(ierr); Matrix * Aict; if (Aict_==0) { Aict = new Matrix; Aict_ = (void *) Aict; } else Aict = (Matrix *) Aict_; Matrix * Lict; if (Lict_==0) { Lict = new Matrix; Lict_ = (void *) Lict; } else Lict = (Matrix *) Lict_; Aict->val = val; Aict->col = ind; Aict->ptr = ptr; double *DV; EPETRA_CHK_ERR(D_->ExtractView(&DV)); // Get view of diagonal crout_ict(m, Aict, DV, Droptol_, Lfil_, Lict, &Ldiag_); // Get rid of unnecessary data delete [] ptr; // Create Epetra View of L from crout_ict if (LevelOverlap_==0) { U_ = Teuchos::rcp( new Epetra_CrsMatrix(View, A_.RowMatrixRowMap(), A_.RowMatrixRowMap(),0) ); D_ = Teuchos::rcp( new Epetra_Vector(View, A_.RowMatrixRowMap(), Ldiag_) ); } else { EPETRA_CHK_ERR(-1); // LevelOverlap > 0 not implemented yet // U_ = new Epetra_CrsMatrix(Copy, OverlapRowMap()); // D_ = new Epetra_Vector(OverlapRowMap()); } ptr = Lict->ptr; ind = Lict->col; val = Lict->val; for (i=0; i< m; i++) { int NumEntries = ptr[i+1]-ptr[i]; int * Indices = ind+ptr[i]; double * Values = val+ptr[i]; U_->InsertMyValues(i, NumEntries, Values, Indices); } U_->FillComplete(A_.OperatorDomainMap(), A_.OperatorRangeMap()); D_->Reciprocal(*D_); // Put reciprocal of diagonal in this vector // Add up flops double current_flops = 2 * nz; // Just an estimate double total_flops = 0; A_.Comm().SumAll(¤t_flops, &total_flops, 1); // Get total madds across all PEs // Now count the rest total_flops += (double) U_->NumGlobalNonzeros(); // Accounts for multiplier above total_flops += (double) D_->GlobalLength(); // Accounts for reciprocal of diagonal UpdateFlops(total_flops); // Update flop count SetFactored(true); return(0); }
//========================================================================== int Ifpack_CrsRiluk::Factor() { // if (!Allocated()) return(-1); // This test is not needed at this time. All constructors allocate. if (!ValuesInitialized()) return(-2); // Must have values initialized. if (Factored()) return(-3); // Can't have already computed factors. SetValuesInitialized(false); // MinMachNum should be officially defined, for now pick something a little // bigger than IEEE underflow value double MinDiagonalValue = Epetra_MinDouble; double MaxDiagonalValue = 1.0/MinDiagonalValue; int ierr = 0; int i, j, k; int * LI=0, * UI = 0; double * LV=0, * UV = 0; int NumIn, NumL, NumU; // Get Maximun Row length int MaxNumEntries = L_->MaxNumEntries() + U_->MaxNumEntries() + 1; vector<int> InI(MaxNumEntries); // Allocate temp space vector<double> InV(MaxNumEntries); vector<int> colflag(NumMyCols()); double *DV; ierr = D_->ExtractView(&DV); // Get view of diagonal #ifdef IFPACK_FLOPCOUNTERS int current_madds = 0; // We will count multiply-add as they happen #endif // Now start the factorization. // Need some integer workspace and pointers int NumUU; int * UUI; double * UUV; for (j=0; j<NumMyCols(); j++) colflag[j] = - 1; for(i=0; i<NumMyRows(); i++) { // Fill InV, InI with current row of L, D and U combined NumIn = MaxNumEntries; EPETRA_CHK_ERR(L_->ExtractMyRowCopy(i, NumIn, NumL, &InV[0], &InI[0])); LV = &InV[0]; LI = &InI[0]; InV[NumL] = DV[i]; // Put in diagonal InI[NumL] = i; EPETRA_CHK_ERR(U_->ExtractMyRowCopy(i, NumIn-NumL-1, NumU, &InV[NumL+1], &InI[NumL+1])); NumIn = NumL+NumU+1; UV = &InV[NumL+1]; UI = &InI[NumL+1]; // Set column flags for (j=0; j<NumIn; j++) colflag[InI[j]] = j; double diagmod = 0.0; // Off-diagonal accumulator for (int jj=0; jj<NumL; jj++) { j = InI[jj]; double multiplier = InV[jj]; // current_mults++; InV[jj] *= DV[j]; EPETRA_CHK_ERR(U_->ExtractMyRowView(j, NumUU, UUV, UUI)); // View of row above if (RelaxValue_==0.0) { for (k=0; k<NumUU; k++) { int kk = colflag[UUI[k]]; if (kk>-1) { InV[kk] -= multiplier*UUV[k]; #ifdef IFPACK_FLOPCOUNTERS current_madds++; #endif } } } else { for (k=0; k<NumUU; k++) { int kk = colflag[UUI[k]]; if (kk>-1) InV[kk] -= multiplier*UUV[k]; else diagmod -= multiplier*UUV[k]; #ifdef IFPACK_FLOPCOUNTERS current_madds++; #endif } } } if (NumL) { EPETRA_CHK_ERR(L_->ReplaceMyValues(i, NumL, LV, LI)); // Replace current row of L } DV[i] = InV[NumL]; // Extract Diagonal value if (RelaxValue_!=0.0) { DV[i] += RelaxValue_*diagmod; // Add off diagonal modifications // current_madds++; } if (fabs(DV[i]) > MaxDiagonalValue) { if (DV[i] < 0) DV[i] = - MinDiagonalValue; else DV[i] = MinDiagonalValue; } else DV[i] = 1.0/DV[i]; // Invert diagonal value for (j=0; j<NumU; j++) UV[j] *= DV[i]; // Scale U by inverse of diagonal if (NumU) { EPETRA_CHK_ERR(U_->ReplaceMyValues(i, NumU, UV, UI)); // Replace current row of L and U } // Reset column flags for (j=0; j<NumIn; j++) colflag[InI[j]] = -1; } // Validate that the L and U factors are actually lower and upper triangular if( !L_->LowerTriangular() ) EPETRA_CHK_ERR(-2); if( !U_->UpperTriangular() ) EPETRA_CHK_ERR(-3); #ifdef IFPACK_FLOPCOUNTERS // Add up flops double current_flops = 2 * current_madds; double total_flops = 0; EPETRA_CHK_ERR(Graph_.L_Graph().RowMap().Comm().SumAll(¤t_flops, &total_flops, 1)); // Get total madds across all PEs // Now count the rest total_flops += (double) L_->NumGlobalNonzeros(); // Accounts for multiplier above total_flops += (double) D_->GlobalLength(); // Accounts for reciprocal of diagonal if (RelaxValue_!=0.0) total_flops += 2 * (double)D_->GlobalLength(); // Accounts for relax update of diag UpdateFlops(total_flops); // Update flop count #endif SetFactored(true); return(ierr); }
//============================================================================= 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); }
//============================================================================= 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); }