VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag, PreconditionerType const & precond) { typedef typename VectorType::value_type ScalarType; typedef typename viennacl::tools::CPU_SCALAR_TYPE_DEDUCER<ScalarType>::ResultType CPU_ScalarType; VectorType result(rhs.size()); result.clear(); VectorType residual = rhs; VectorType tmp(rhs.size()); VectorType z = rhs; precond.apply(z); VectorType p = z; ScalarType ip_rr = viennacl::linalg::inner_prod(residual, z); ScalarType alpha; ScalarType new_ip_rr = 0; ScalarType beta; ScalarType norm_rhs = ip_rr; for (unsigned int i = 0; i < tag.iterations(); ++i) { tag.iters(i+1); tmp = viennacl::linalg::prod(matrix, p); alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p); result += alpha * p; residual -= alpha * tmp; z = residual; precond.apply(z); new_ip_rr = viennacl::linalg::inner_prod(residual, z); if (std::fabs(new_ip_rr / norm_rhs) < tag.tolerance() * tag.tolerance()) //squared norms involved here break; beta = new_ip_rr / ip_rr; ip_rr = new_ip_rr; p = z + beta*p; } //store last error estimate: tag.error(sqrt(std::fabs(new_ip_rr / norm_rhs))); return result; }
VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag) { typedef typename VectorType::value_type ScalarType; VectorType result(rhs.size()); result.clear(); VectorType residual = rhs; VectorType p = rhs; VectorType tmp(rhs.size()); ScalarType ip_rr = viennacl::linalg::inner_prod(rhs,rhs); ScalarType alpha; ScalarType new_ip_rr = 0; ScalarType beta; ScalarType norm_rhs = ip_rr; //std::cout << "Starting CG solver... " << std::endl; for (unsigned int i = 0; i < tag.iterations(); ++i) { tag.iters(i+1); tmp = viennacl::linalg::prod(matrix, p); alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p); result += alpha * p; residual -= alpha * tmp; new_ip_rr = viennacl::linalg::inner_prod(residual,residual); if (new_ip_rr / norm_rhs < tag.tolerance() * tag.tolerance())//squared norms involved here break; beta = new_ip_rr / ip_rr; ip_rr = new_ip_rr; p = residual + beta*p; } //store last error estimate: tag.error(sqrt(new_ip_rr / norm_rhs)); return result; }