42struct ConjugateGradientSolverParams
44 using params = ConjugateGradientSolverParams;
53 double abstol = std::numeric_limits<double>::min();
65 ConjugateGradientSolverParams() =
default;
68 : ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
maxiter)
69 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
tol)
70 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
abstol)
71 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
ns_search)
72 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
verbose)
74 p.check_params( {
"maxiter",
"tol",
"abstol",
"ns_search",
"verbose" });
79 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
maxiter);
80 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
tol);
81 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
abstol);
82 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
ns_search);
83 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
verbose);
100 using Backend = Backend_;
101 using backend_type = Backend;
102 using BackendType = Backend;
104 typedef typename Backend::vector vector;
105 typedef typename Backend::value_type value_type;
106 typedef typename Backend::params backend_params;
108 typedef typename math::scalar_of<value_type>::type scalar_type;
111 typename math::rhs_of<value_type>::type>::return_type coef_type;
117 const backend_params& backend_prm = backend_params(),
118 const InnerProduct& inner_product = InnerProduct())
121 , r(Backend::create_vector(n, backend_prm))
122 , s(Backend::create_vector(n, backend_prm))
123 , p(Backend::create_vector(n, backend_prm))
124 , q(Backend::create_vector(n, backend_prm))
125 , inner_product(inner_product)
140 template <
class Matrix,
class Precond,
class Vec1,
class Vec2>
141 SolverResult operator()(
const Matrix& A,
const Precond& P,
const Vec1& rhs, Vec2&& x)
const
143 static const coef_type one = math::identity<coef_type>();
144 static const coef_type zero = math::zero<coef_type>();
148 scalar_type norm_rhs = norm(rhs);
149 if (norm_rhs < Alina::detail::eps<scalar_type>(1)) {
151 norm_rhs = math::identity<scalar_type>();
155 return SolverResult(0, norm_rhs);
159 scalar_type eps = std::max(prm.tol * norm_rhs, prm.abstol);
161 coef_type rho1 = 2 * eps * one;
162 coef_type rho2 = zero;
164 backend::residual(rhs, A, x, *r);
165 scalar_type res_norm = norm(*r);
168 for (; iter < prm.maxiter && math::norm(res_norm) > eps; ++iter) {
172 rho1 = inner_product(*r, *s);
175 backend::axpby(one, *s, rho1 / rho2, *p);
177 backend::copy(*s, *p);
179 backend::spmv(one, A, *p, zero, *q);
181 coef_type alpha = rho1 / inner_product(*q, *p);
183 backend::axpby(alpha, *p, one, x);
184 backend::axpby(-alpha, *q, one, *r);
187 if (prm.verbose && iter % 5 == 0)
188 std::cout << iter <<
"\t" << std::scientific << res_norm / norm_rhs << std::endl;
191 return SolverResult(iter, res_norm / norm_rhs);
204 template <
class Precond,
class Vec1,
class Vec2>
207 return (*
this)(P.system_matrix(), P, rhs, x);
212 return backend::bytes(*r) +
220 return os <<
"Type: CG"
221 <<
"\nUnknowns: " << s.n
222 <<
"\nMemory footprint: " << human_readable_memory(s.
bytes())
234 std::shared_ptr<vector> r;
235 std::shared_ptr<vector> s;
236 std::shared_ptr<vector> p;
237 std::shared_ptr<vector> q;
239 InnerProduct inner_product;
242 scalar_type norm(
const Vec& x)
const
244 return sqrt(math::norm(inner_product(x, x)));
ConjugateGradientSolver(size_t n, const params &prm=params(), const backend_params &backend_prm=backend_params(), const InnerProduct &inner_product=InnerProduct())
Preallocates necessary data structures for the system of size n.