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 bicg(const LinearOperator &A, Vector &x, const Vector &b, const Preconditioner &M, Iteration& iter) { using mtl::conj; typedef typename mtl::Collection<Vector>::value_type Scalar; Scalar rho_1(0), rho_2(0), alpha(0), beta(0); Vector r(b - A * x), z(size(x)), p(size(x)), q(size(x)), r_tilde(r), z_tilde(size(x)), p_tilde(size(x)), q_tilde(size(x)); while (! iter.finished(r)) { z= solve(M, r); z_tilde= adjoint_solve(M, r_tilde); rho_1= dot(z_tilde, z); if (rho_1 == 0.) { iter.fail(2, "bicg breakdown"); break; } if (iter.first()) { p= z; p_tilde= z_tilde; } else { beta= rho_1 / rho_2; p= z + beta * p; p_tilde= z_tilde + conj(beta) * p_tilde; } q= A * p; q_tilde= adjoint(A) * p_tilde; alpha= rho_1 / dot(p_tilde, q); x+= alpha * p; r-= alpha * q; r_tilde-= conj(alpha) * q_tilde; rho_2= rho_1; ++iter; } return iter.error_code(); }
int cg(const LinearOperator& A, HilbertSpace& x, const HilbertSpace& b, Iteration& iter) { typedef HilbertSpace TmpVec; typedef typename mtl::Collection<HilbertSpace>::value_type Scalar; Scalar rho, rho_1, alpha, beta; TmpVec p(size(x)), q(size(x)), r(size(x)), z(size(x)); // r = b - A*x; r = b; r -= A*x; while (! iter.finished(r)) { rho = dot(r, r); if (iter.first()) p = r; else { beta = rho / rho_1; p = r + beta * p; } q = A * p; alpha = rho / dot(p, q); x += alpha * p; r -= alpha * q; rho_1 = rho; ++iter; } return iter.error_code(); }
int qmr(const Matrix& A, Vector& x, const Vector& b, LeftPreconditioner& L, const RightPreconditioner& R, Iteration& iter) { typedef typename mtl::Collection<Vector>::value_type Scalar; typedef typename mtl::Collection<Vector>::size_type Size; if (size(b) == 0) throw mtl::logic_error("empty rhs vector"); const Scalar zero= math::zero(b[0]), one= math::one(b[0]); Scalar rho_1, gamma(one), gamma_1, theta(zero), theta_1, eta(-one), delta, ep(one), beta; Size n(size(x)); Vector r(b - A * x), v_tld(r), y(solve(L, v_tld)), w_tld(r), z(adjoint_solve(R,w_tld)), v(n), w(n), y_tld(n), z_tld, p, q, p_tld, d, s; if (iter.finished(r)) return iter; Scalar rho = two_norm(y), xi = two_norm(z); while(! iter.finished(rho)) { if (rho == zero) return iter.fail(1, "qmr breakdown, rho=0 #1"); if (xi == zero) return iter.fail(2, "qmr breakdown, xi=0 #2"); v= v_tld / rho; y/= rho; w= w_tld / xi; z/= xi; delta = dot(z,y); if (delta == zero) return iter.fail(3, "qmr breakdown, delta=0 #3"); y_tld = solve(R,y); z_tld = adjoint_solve(L,z); if (iter.first()) { p = y_tld; q = z_tld; } else { p = y_tld - ((xi * delta) / ep) * p; q = z_tld - ((rho* delta) / ep) * q; } p_tld = A * p; ep = dot(q, p_tld); if (ep == zero) return iter.fail(4, "qmr breakdown ep=0 #4"); beta= ep / delta; if (beta == zero) return iter.fail(5, "qmr breakdown beta=0 #5"); v_tld = p_tld - beta * v; y = solve(L,v_tld); rho_1 = rho = two_norm(y); w_tld= trans(A)*q - beta*w; z = adjoint_solve(R, w_tld); xi = two_norm(z); gamma_1 = gamma; theta_1 = theta; theta = rho / (gamma_1 * beta); gamma = one / (sqrt(one + theta * theta)); if (gamma == zero) return iter.fail(6, "qmr breakdown gamma=0 #6"); eta= -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1); if (iter.first()) { d= eta * p; s= eta * p_tld; } else { d= eta * p + (theta_1 * theta_1 * gamma * gamma) * d; s= eta * p_tld + (theta_1 * theta_1 * gamma * gamma) * s; } x += d; r -= s; ++iter; } return iter; }