Exemplo n.º 1
0
int bicgstab(const LinearOperator& A, HilbertSpaceX& x, const HilbertSpaceB& b, 
	     const Preconditioner& M, Iteration& iter)
{
  typedef typename mtl::Collection<HilbertSpaceX>::value_type Scalar;
  typedef HilbertSpaceX                                       Vector;

  Scalar     rho_1(0), rho_2(0), alpha(0), beta(0), gamma, omega(0);
  Vector     p(size(x)), phat(size(x)), s(size(x)), shat(size(x)), 
             t(size(x)), v(size(x)), r(size(x)), rtilde(size(x));

  r = b - A * x;
  rtilde = r;

  while (! iter.finished(r)) {
    
    rho_1 = dot(rtilde, r);
    MTL_THROW_IF(rho_1 == 0.0, unexpected_orthogonality());

    if (iter.first())
      p = r;
    else {
      MTL_THROW_IF(omega == 0.0, unexpected_orthogonality());
      beta = (rho_1 / rho_2) * (alpha / omega);
      p = r + beta * (p - omega * v);
    }
    phat = solve(M, p);
    v = A * phat;

    gamma = dot(rtilde, v);
    MTL_THROW_IF(gamma == 0.0, unexpected_orthogonality());

    alpha = rho_1 / gamma;
    s = r - alpha * v;
    
    if (iter.finished(s)) {
      x += alpha * phat;
      break;
    }
    shat = solve(M, s);
    t = A * shat;
    omega = dot(t, s) / dot(t, t);
    
    x += omega * shat + alpha * phat;
    r = s - omega * t;
    
    rho_2 = rho_1;    
    ++iter;
  }
  return iter;
}
Exemplo n.º 2
0
int tfqmr(const Matrix& A, Vector& x, const Vector& b, const Precond1& M1, const Precond2& M2)
{
	Vector r0(x.size()),v(x.size());
	Vector tmp(x.size());
	Vector tmp1(x.size());

	//x is initial value

	// 1. r0 = Q1 (b - A Q2 x)
	r0.copy(M2.solve(x));	//r0=M2^{-1}.x
	A.mult(r0,tmp);		//tmp=A.r0
	b.add(-1.0,tmp,tmp);	//tmp=b-tmp
	M1.solve(tmp,r0);	//r0=M1^{-1}.tmp

	// 2. w=y=r
	// 2. w=y=r0?
	Vector w(x.size()),y1(x.size());
	w.copy(r0);
	y1.copy(r0);

	// 3. g=v=Q1.A.Q2.y
	M2.solve(y1,v);
	A.mult(v,tmp);
	M1.solve(tmp,v);

	Vector g(x.size());
	g.copy(v);

	// 4. d=0
	Vector d(x.size());
	d.set(0.0); // set all elements to 0.0

	// 5. tau=||r||2
	double tau = r0.norm2();

	// 6. theta=eta=0
	double theta = 0.0;
	double eta = 0.0;

	// 7. rtilde=r
	Vector rtilde(x.size());
	rtilde.copy(r0);

	// 8. rho=dot(rtilde,r)
	double rho  = tau*tau; // note: tau=r0.norm2()
	double rho0 = rho;

	//Vector y0(size(x));
	double sigma, alpha, c, kappa, beta;
	Vector y0(x.size()),h(x.size());
	while(1) {
		// 9. 10. 11.
		// sigma=dot(rtilde,v)
		// alpha=rho/sigma 
		// y2k=y(2k-1)-alpha*v

		// 9. sigma=dot(rtilde,v)
		sigma = rtilde.dot(v);

		// 10. alpha=rho/sigma
		if (sigma==0.) { iter.breakdown(5, "tfqmr breakdown: sigma=0"); break; }
		alpha = rho / sigma;

		// 11. y2k=y(2k-1)-alpha*v
		// y0 = y1 - alpha * v;
		y1.add(-alpha,v,y0);

		// 12. h=Q1*A*Q2*y
		M2.solve(y0,h);
		A.mult(h,tmp);
		M1.solve(tmp,h);

		//split the loop of "for m = 2k-1, 2k" 

		/**************************************/
		//The first one

		// 13. w=w-alpha*Q1AQ2y0
		// w = w - alpha * g;
		w.add(-alpha,g,w);

		// 18. d=y0+((theta0^2)*eta0/alpha)*d         //need check breakdown
		// d = y1 + ( theta * theta * eta / alpha ) * d;
		if (alpha==0.) { iter.breakdown(3, "tfqmr breakdown: alpha=0"); break; }
		y1.add(theta*theta*eta/alpha,d,d);

		// 14. theta=||w||_2/tau0       //need check breakdown
		if (tau==0.) { iter.breakdown(2, "tfqmr breakdown: tau=0"); break; }
		theta=w.norm2()/tau; // tau is not updated yet

		// 15. c=1/sqrt(1+theta^2)
		c=1.0/sqrt(1.0+theta*theta);

		// 16. tau=tau0*theta*c
		tau = tau * c * theta;

		// 17.  eta=(c^2)*alpha
		eta = c * c * alpha;

		// 19. x=x+eta*d
		x.add(eta,d,x);

		// 20. kappa=tau*sqrt(m+1)
		kappa = tau * sqrt( 2.* (iter.iterations()+1) );

		// 21. check stopping criterion
		if ( iter.finished(kappa) ) {
			//before return, transform x to the solution of Ax = b
			solve(M2, x, tmp);
			itl::copy(tmp, x);
			break;
		}
		//g = h;
		g.copy(h);

		/**************************************/
		//The second one

		// 13. w=w-alpha*Q1AQ2y0
		// w = w - alpha * g;
		w.add(-alpha,g,w);

		// 18. d=y0+((theta0^2)*eta0/alpha)*d
		// d = y0 + ( theta * theta * eta / alpha ) * d;
		if (alpha==0.) { iter.breakdown(3,"tfqmr breakdown: alpha=0"); break; }
		y0.add(theta*theta*eta/alpha,d,d);

		// 14. theta=||w||_2/tau0
		if (tau==0.) { iter.breakdown(2, "tfqmr breakdown: tau=0"); break; }
		//theta = itl::two_norm(w) / tau;
		theta = w.norm2()/tau;

		// 15. c=1/sqrt(1+theta^2)
		c = 1.0 / sqrt(1.0 + theta * theta);

		// 16. tau=tau0*theta*c
		tau = tau * c * theta;

		// 17.  eta=(c^2)*alpha
		eta = c * c * alpha;

		// 19. x=x+eta*d
		x.add(eta,d,x);

		// 20. kappa=tau*sqrt(m+1)
		kappa = tau * sqrt(2.* (iter.iterations()+1)  + 1.);

		// 21. check stopping criterion
		if ( iter.finished(kappa) ) {
			itl::solve(M2, x, tmp);
			itl::copy(tmp, x);
			break;
		}    

		// 22. rho=dot(rtilde,w)
		// 23. beta=rho/rho0                     //need check breakdown

		rho0 = rho;
		//rho = itl::dot(rtilde, w);
		rho  = rtilde.dot(w);
		if (rho0==0.) { iter.breakdown(4, "tfqmr breakdown: beta=0"); break; }
		beta=rho/rho0;

		// 24. y=w+beta*y0
		// y1 = w + beta * y0;
		w.add(beta,y0,y1);

		// 25. g=Q1.A.Q2.y
		// g = Q1 * ( A * ( Q2 * y1) );
		M2.solve(y1,g);
		A.mult(g,tmp);
		M1.solve(tmp,g);

		// 26. v=Q1AQ2y+beta*(Q1AQ2y0+beta*v)
		// v = g + beta * ( h + beta * v );
		h.add(beta,v,tmp);
		g.add(beta,tmp,v);

		++iter;
	}

	return iter.error_code();
}
Exemplo n.º 3
0
void BiCGSTAB(Epetra_CrsMatrix &A, 
	      Epetra_Vector &x, 
	      Epetra_Vector &b, 
	      Ifpack_CrsRiluk *M, 
	      int Maxiter, 
	      double Tolerance, 
	      double *residual, bool verbose) {

  // Allocate vectors needed for iterations
  Epetra_Vector phat(x.Map()); phat.SetFlopCounter(x);
  Epetra_Vector p(x.Map()); p.SetFlopCounter(x);
  Epetra_Vector shat(x.Map()); shat.SetFlopCounter(x);
  Epetra_Vector s(x.Map()); s.SetFlopCounter(x);
  Epetra_Vector r(x.Map()); r.SetFlopCounter(x);
  Epetra_Vector rtilde(x.Map()); rtilde.Random(); rtilde.SetFlopCounter(x);
  Epetra_Vector v(x.Map()); v.SetFlopCounter(x);
  

  A.Multiply(false, x, r); // r = A*x

  r.Update(1.0, b, -1.0); // r = b - A*x

  double r_norm, b_norm, scaled_r_norm, rhon, rhonm1 = 1.0;
  double alpha = 1.0, omega = 1.0, sigma;
  double omega_num, omega_den;
  r.Norm2(&r_norm);
  b.Norm2(&b_norm);
  scaled_r_norm = r_norm/b_norm;
  r.Dot(rtilde,&rhon);

  if (verbose) cout << "Initial residual = " << r_norm
		    << " Scaled residual = " << scaled_r_norm << endl;


  for (int i=0; i<Maxiter; i++) { // Main iteration loop   

    double beta = (rhon/rhonm1) * (alpha/omega);
    rhonm1 = rhon;

    /* p    = r + beta*(p - omega*v)       */
    /* phat = M^-1 p                       */
    /* v    = A phat                       */

    double dtemp = - beta*omega;

    p.Update(1.0, r, dtemp, v, beta);
    if (M==0) 
      phat.Scale(1.0, p);
    else
      M->Solve(false, p, phat);
    A.Multiply(false, phat, v);

    
    rtilde.Dot(v,&sigma);
    alpha = rhon/sigma;    

    /* s = r - alpha*v                     */
    /* shat = M^-1 s                       */
    /* r = A shat (r is a tmp here for t ) */

    s.Update(-alpha, v, 1.0, r, 0.0);
    if (M==0) 
      shat.Scale(1.0, s);
    else
      M->Solve(false, s, shat);
    A.Multiply(false, shat, r);

    r.Dot(s, &omega_num);
    r.Dot(r, &omega_den);
    omega = omega_num / omega_den;

    /* x = x + alpha*phat + omega*shat */
    /* r = s - omega*r */

    x.Update(alpha, phat, omega, shat, 1.0);
    r.Update(1.0, s, -omega); 
    
    r.Norm2(&r_norm);
    scaled_r_norm = r_norm/b_norm;
    r.Dot(rtilde,&rhon);

    if (verbose) cout << "Iter "<< i << " residual = " << r_norm
		      << " Scaled residual = " << scaled_r_norm << endl;

    if (scaled_r_norm < Tolerance) break;
  }
  return;
}