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; }
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(); }
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; }