bool IterativeSolvers::pcg(const IRCMatrix &A, Vector &x, const Vector &b, const Preconditioner &M) { /*! Solves Ax=b using the preconditioned conjugate gradient method. */ const idx N = x.getLength(); real resid(100.0); Vector p(N), z(N), q(N); real alpha; real normr(0); real normb = norm(b); real rho(0), rho_1(0), beta(0); Vector r = b - A * x; if (normb == 0.0) normb = 1; resid = norm(r) / normb; if (resid <= IterativeSolvers::toler) { IterativeSolvers::toler = resid; IterativeSolvers::maxIter = 0; return true; } // MAIN LOOP idx i = 1; for (; i <= IterativeSolvers::maxIter; i++) { M.solveMxb(z, r); rho = dot(r, z); if (i == 1) p = z; else { beta = rho / rho_1; aypx(beta, p, z); // p = beta*p + z; } // CALCULATES q = A*p AND dp = dot(q,p) real dp = multiply_dot(A, p, q); alpha = rho / dp; normr = 0; #ifdef USES_OPENMP #pragma omp parallel for reduction(+:normr) #endif for (idx j = 0 ; j < N ; ++j) { x[j] += alpha * p[j]; // x + alpha(0) * p; r[j] -= alpha * q[j]; // r - alpha(0) * q; normr += r[j] * r[j]; } normr = sqrt(normr); resid = normr / normb; if (resid <= IterativeSolvers::toler) { IterativeSolvers::toler = resid; IterativeSolvers::maxIter = i; return true; } rho_1 = rho; } IterativeSolvers::toler = resid; return false; }
int CG(const MMatrix &A, MVector &x, const MVector &b, const Preconditioner &M, int &max_iter, Real &tol) { Real resid; MVector p, z, q; MVector alpha(1), beta(1), rho(1), rho_1(1); MVector r = b - A*x; Real normb = norm(b); if (normb == 0.0) normb = 1; if ((resid = norm(r) / normb) <= tol){ tol = resid; max_iter = 0; return 0; } for (int i = 1; i <= max_iter; i++) { // Assign Z z = M.solve(r); rho.p_[0] = dot(r, z); // Assign P if (i == 1) p = z; else { beta.p_[0] = rho.p_[0] / rho_1.p_[0]; p = z + beta.p_[0] * p; } // Assign Q q = A*p; alpha.p_[0] = rho.p_[0] / dot(p, q); // Change X and R x += alpha.p_[0] * p; r -= alpha.p_[0] * q; // Check tol if ((resid = norm(r) / normb) <= tol) { tol = resid; max_iter = i; return 0; } rho_1.p_[0] = rho.p_[0]; } tol = resid; return 1; }
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; }