//============================================================================= 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_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); }
//============================================================================== 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*/