int EpetraSymOp::ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const { int info=0; Epetra_MultiVector temp_vec(OperatorDomainMap(), Y.NumVectors()); // // This generalized operator computes Y = (A^T*A)^{-1}*X or Y = (A*A^T)^{-1}*X // // Transpose the operator (if isTrans_ = true) if (!isTrans_) { info=Epetra_Op->SetUseTranspose( !isTrans_ ); if (info!=0) { return info; } } // // Compute A^{-1}*X or A^{-T}*X // info=Epetra_Op->ApplyInverse( X, temp_vec ); if (info!=0) { return info; } // // Transpose/Un-transpose the operator based on value of isTrans_ info=Epetra_Op->SetUseTranspose( isTrans_ ); if (info!=0) { return info; } // Compute A^{-T}*(A^{-1}*X) or A^{-1}*A^{-T} info=Epetra_Op->Apply( temp_vec, Y ); if (info!=0) { return info; } // Un-transpose the operator info=Epetra_Op->SetUseTranspose( false ); return info; }
//============================================================================= //============================================================================= 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 EpetraGenOp::ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const { // // This generalized operator computes Y = M^{-1}*A*X // int info=0; Epetra_MultiVector temp_Y(OperatorDomainMap(), Y.NumVectors()); // Apply A or A^{-1} if (isAInverse) info = Epetra_AOp->Apply( X, temp_Y ); else info = Epetra_AOp->ApplyInverse( X, temp_Y ); if (info!=0) return info; // Apply M^{-1} info = Epetra_MOp->ApplyInverse( temp_Y, Y ); return info; }
//============================================================================= 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 Poisson2dOperator::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { // This is a very brain-dead implementation of a 5-point finite difference stencil, but // it should illustrate the basic process for implementing the Epetra_Operator interface. if (!X.Map().SameAs(OperatorDomainMap())) abort(); // These aborts should be handled as int return codes. if (!Y.Map().SameAs(OperatorRangeMap())) abort(); if (Y.NumVectors()!=X.NumVectors()) abort(); if (comm_.NumProc()>1) { if (importX_==0) importX_ = new Epetra_MultiVector(*importMap_, X.NumVectors()); else if (importX_->NumVectors()!=X.NumVectors()) { delete importX_; importX_ = new Epetra_MultiVector(*importMap_, X.NumVectors()); } importX_->Import(X, *importer_, Insert); // Get x values we need } double * importx1 = 0; double * importx2 = 0; int nx = nx_; //int ny = ny_; for (int j=0; j < X.NumVectors(); j++) { const double * x = X[j]; if (comm_.NumProc()>1) { importx1 = (*importX_)[j]; importx2 = importx1+nx; if (comm_.MyPID()==0) importx2=importx1; } double * y = Y[j]; if (comm_.MyPID()==0) { y[0] = 4.0*x[0]-x[nx]-x[1]; y[nx-1] = 4.0*x[nx-1]-x[nx-2]-x[nx+nx-1]; for (int ix=1; ix< nx-1; ix++) y[ix] = 4.0*x[ix]-x[ix-1]-x[ix+1]-x[ix+nx]; } else { y[0] = 4.0*x[0]-x[nx]-x[1]-importx1[0]; y[nx-1] = 4.0*x[nx-1]-x[nx-2]-x[nx+nx-1]-importx1[nx-1]; for (int ix=1; ix< nx-1; ix++) y[ix] = 4.0*x[ix]-x[ix-1]-x[ix+1]-x[ix+nx]-importx1[ix]; } if (comm_.MyPID()+1==comm_.NumProc()) { int curxy = nx*myny_-1; y[curxy] = 4.0*x[curxy]-x[curxy-nx]-x[curxy-1]; curxy -= (nx-1); y[curxy] = 4.0*x[curxy]-x[curxy-nx]-x[curxy+1]; for (int ix=1; ix< nx-1; ix++) { curxy++; y[curxy] = 4.0*x[curxy]-x[curxy-1]-x[curxy+1]-x[curxy-nx]; } } else { int curxy = nx*myny_-1; y[curxy] = 4.0*x[curxy]-x[curxy-nx]-x[curxy-1]-importx2[nx-1]; curxy -= (nx-1); y[curxy] = 4.0*x[curxy]-x[curxy-nx]-x[curxy+1]-importx2[0]; for (int ix=1; ix< nx-1; ix++) { curxy++; y[curxy] = 4.0*x[curxy]-x[curxy-1]-x[curxy+1]-x[curxy-nx]-importx2[ix]; } } for (int iy=1; iy< myny_-1; iy++) { int curxy = nx*(iy+1)-1; y[curxy] = 4.0*x[curxy]-x[curxy-nx]-x[curxy-1]-x[curxy+nx]; curxy -= (nx-1); y[curxy] = 4.0*x[curxy]-x[curxy-nx]-x[curxy+1]-x[curxy+nx]; for (int ix=1; ix< nx-1; ix++) { curxy++; y[curxy] = 4.0*x[curxy]-x[curxy-1]-x[curxy+1]-x[curxy-nx]-x[curxy+nx]; } } } return(0); }
// ================================================ ====== ==== ==== == = // Computes the preconditioner int ML_Epetra::FaceMatrixFreePreconditioner::ComputePreconditioner(const bool CheckFiltering) { Teuchos::ParameterList & ListCoarse=List_.sublist("face matrix free: coarse"); /* ML Communicator */ ML_Comm_Create(&ml_comm_); /* Parameter List Options */ int SmootherSweeps = List_.get("smoother: sweeps", 0); MaxLevels = List_.get("max levels",10); print_hierarchy= List_.get("print hierarchy",false); num_cycles = List_.get("cycle applications",1); /* Sanity Checking*/ int OperatorDomainPoints = OperatorDomainMap().NumGlobalPoints(); int OperatorRangePoints = OperatorRangeMap().NumGlobalPoints(); if (OperatorDomainPoints != OperatorRangePoints) ML_CHK_ERR(-1); // only square matrices /* Output Header */ if(verbose_ && !Comm_->MyPID()) { printf("------------------------------------------------------------------------------\n"); printf("***\n"); printf("*** ML_Epetra::FaceMatrixFreePreconditioner [%s]\n",Label()); printf("***\n"); } /* Invert non-zeros on the diagonal */ if(SmootherSweeps){ for (int i = 0; i < InvDiagonal_->MyLength(); ++i) if ((*InvDiagonal_)[i] != 0.0) (*InvDiagonal_)[i] = 1.0 / (*InvDiagonal_)[i]; double nrm; InvDiagonal_->Norm2(&nrm); if(verbose_ && !Comm_->MyPID()) printf("Inverse Diagonal Norm = %6.4e\n",nrm); }/*end if*/ /* Do the eigenvalue estimation for Chebyshev */ if(SmootherSweeps) ML_CHK_ERR(SetupSmoother()); if(MaxLevels > 0) { /* Build the prolongator */ ML_CHK_ERR(BuildProlongator()); /* DEBUG: Output matrices */ if(print_hierarchy) EpetraExt::RowMatrixToMatlabFile("prolongator.dat",*Prolongator_); /* Form the coarse matrix */ ML_CHK_ERR(FormCoarseMatrix()); /* DEBUG: Output matrices */ if(print_hierarchy) EpetraExt::RowMatrixToMatlabFile("coarsemat.dat",*CoarseMatrix); /* Setup Preconditioner on Coarse Matrix */ CoarsePC = new MultiLevelPreconditioner(*CoarseMatrix,ListCoarse); if(!CoarsePC) ML_CHK_ERR(-2); /* Clean Up */ //delete nullspace; }/*end if*/ return 0; }/*end ComputePreconditioner*/