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);
}
示例#5
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*/