VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag, PreconditionerType const & precond) { typedef typename viennacl::result_of::value_type<VectorType>::type ScalarType; typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type CPU_ScalarType; unsigned int problem_size = viennacl::traits::size(rhs); VectorType result(problem_size); viennacl::traits::clear(result); VectorType residual = rhs; VectorType tmp(problem_size); VectorType z = rhs; precond.apply(z); VectorType p = z; CPU_ScalarType ip_rr = viennacl::linalg::inner_prod(residual, z); CPU_ScalarType alpha; CPU_ScalarType new_ip_rr = 0; CPU_ScalarType beta; CPU_ScalarType norm_rhs_squared = ip_rr; CPU_ScalarType new_ipp_rr_over_norm_rhs; if (norm_rhs_squared == 0) //solution is zero if RHS norm is zero return result; for (unsigned int i = 0; i < tag.max_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); new_ipp_rr_over_norm_rhs = new_ip_rr / norm_rhs_squared; if (std::fabs(new_ipp_rr_over_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(std::sqrt(std::fabs(new_ip_rr / norm_rhs_squared))); return result; }
VectorType solve(const MatrixType & matrix, VectorType const & rhs, cg_tag const & tag) { //typedef typename VectorType::value_type ScalarType; typedef typename viennacl::result_of::value_type<VectorType>::type ScalarType; typedef typename viennacl::result_of::cpu_value_type<ScalarType>::type CPU_ScalarType; //std::cout << "Starting CG" << std::endl; std::size_t problem_size = viennacl::traits::size(rhs); VectorType result(problem_size); viennacl::traits::clear(result); VectorType residual = rhs; VectorType p = rhs; VectorType tmp(problem_size); CPU_ScalarType ip_rr = viennacl::linalg::inner_prod(rhs,rhs); CPU_ScalarType alpha; CPU_ScalarType new_ip_rr = 0; CPU_ScalarType beta; CPU_ScalarType norm_rhs = std::sqrt(ip_rr); //std::cout << "Starting CG solver iterations... " << std::endl; if (norm_rhs == 0) //solution is zero if RHS norm is zero return result; for (unsigned int i = 0; i < tag.max_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::norm_2(residual); if (new_ip_rr / norm_rhs < tag.tolerance()) break; new_ip_rr *= new_ip_rr; beta = new_ip_rr / ip_rr; ip_rr = new_ip_rr; p = residual + beta * p; } //store last error estimate: tag.error(std::sqrt(new_ip_rr) / norm_rhs); return result; }
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; }