示例#1
0
void CR<OperatorType, VectorType, ValueType>::SolvePrecond_(const VectorType &rhs,
                                                            VectorType *x) {

  LOG_DEBUG(this, "CR::SolvePrecond_()",
            " #*# begin");

  assert(x != NULL);
  assert(x != &rhs);
  assert(this->op_  != NULL);
  assert(this->precond_ != NULL);
  assert(this->build_ == true);

  const OperatorType *op = this->op_;

  VectorType *r = &this->r_;
  VectorType *z = &this->z_;
  VectorType *p = &this->p_;
  VectorType *q = &this->q_;
  VectorType *v = &this->v_;
  VectorType *t = &this->t_;

  ValueType alpha, beta;
  ValueType rho, rho_old;

  // initial residual = b - Ax
  op->Apply(*x, z);
  z->ScaleAdd(ValueType(-1.0), rhs);

  // Solve Mr=z
  this->precond_->SolveZeroSol(*z, r);

  // p = r
  p->CopyFrom(*r);

  // t = z
  t->CopyFrom(*z);

  // use for |b-Ax0|
  ValueType res_norm = this->Norm(*t);

  if (this->iter_ctrl_.InitResidual(paralution_abs(res_norm)) == false) {

    LOG_DEBUG(this, "CR::SolvePrecond_()",
              " #*# end");

    return;
  }


  // use for |b|
  //  this->iter_ctrl_.InitResidual(rhs.Norm());

  // v=Ar
  op->Apply(*r, v);

  // rho = (r,v)
  rho = r->DotNonConj(*v);

  // q=Ap
  op->Apply(*p, q);

  // Mz=q
  this->precond_->SolveZeroSol(*q, z);

  // alpha = rho / (q,z)
  alpha = rho / q->DotNonConj(*z);

  // x = x + alpha * p
  x->AddScale(*p, alpha);

  // r = r - alpha * z
  r->AddScale(*z, ValueType(-1.0)*alpha);

  // t = t - alpha * q
  t->AddScale(*q, ValueType(-1.0)*alpha);

  res_norm = this->Norm(*t);

  while (!this->iter_ctrl_.CheckResidual(paralution_abs(res_norm), this->index_)) {

    rho_old = rho;

    // v=Ar
    op->Apply(*r, v);

    // rho = (r,v)
    rho = r->DotNonConj(*v);

    beta = rho / rho_old;

    // p = beta*p + r
    p->ScaleAdd(beta, *r);

    // q = beta*q + v
    q->ScaleAdd(beta, *v);

    // Mz=q
    this->precond_->SolveZeroSol(*q, z);

    // alpha = rho / (q,z)
    alpha = rho / q->DotNonConj(*z);

    // x = x + alpha * p
    x->AddScale(*p, alpha);

    // r = r - alpha * z
    r->AddScale(*z, ValueType(-1.0)*alpha);

    // t = t - alpha * q
    t->AddScale(*q, ValueType(-1.0)*alpha);

    res_norm = this->Norm(*t);

  }

  LOG_DEBUG(this, "CR::SolvePrecond_()",
            " #*# end");

}