40struct BiCGStabSolverParams
42 using params = BiCGStabSolverParams;
45 ePreconditionerSideType
pside = ePreconditionerSideType::right;
54 double abstol = std::numeric_limits<double>::min();
66 BiCGStabSolverParams() =
default;
69 : ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
pside)
70 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
maxiter)
71 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
tol)
72 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
abstol)
74 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
ns_search)
75 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p,
verbose)
77 p.check_params( {
"pside",
"maxiter",
"tol",
"abstol",
"check_after",
"ns_search",
"verbose" });
82 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
pside);
83 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
maxiter);
84 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
tol);
85 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
abstol);
86 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
check_after);
87 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
ns_search);
88 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path,
verbose);
107 using backend_type = Backend;
108 using BackendType = Backend;
110 typedef typename Backend::vector vector;
111 typedef typename Backend::value_type value_type;
112 typedef typename Backend::params backend_params;
114 typedef typename math::scalar_of<value_type>::type scalar_type;
117 typename math::rhs_of<value_type>::type>::return_type coef_type;
123 const params& prm = params(),
124 const backend_params& backend_prm = backend_params(),
125 const InnerProduct& inner_product = InnerProduct())
128 , r(Backend::create_vector(n, backend_prm))
129 , p(Backend::create_vector(n, backend_prm))
130 , v(Backend::create_vector(n, backend_prm))
131 , s(Backend::create_vector(n, backend_prm))
132 , t(Backend::create_vector(n, backend_prm))
133 , rh(Backend::create_vector(n, backend_prm))
134 , T(Backend::create_vector(n, backend_prm))
135 , inner_product(inner_product)
150 template <
class Matrix,
class Precond,
class Vec1,
class Vec2>
151 SolverResult operator()(
const Matrix& A,
const Precond& P,
const Vec1& rhs, Vec2&& x)
const
153 static const coef_type one = math::identity<coef_type>();
154 static const coef_type zero = math::zero<coef_type>();
158 scalar_type norm_rhs = norm(rhs);
159 if (norm_rhs < Alina::detail::eps<scalar_type>(1)) {
161 norm_rhs = math::identity<scalar_type>();
165 return SolverResult(0, norm_rhs);
169 if (prm.pside == ePreconditionerSideType::left) {
170 backend::residual(rhs, A, x, *rh);
174 backend::residual(rhs, A, x, *r);
176 backend::copy(*r, *rh);
178 scalar_type eps = std::max(norm_rhs * prm.tol, prm.abstol);
179 scalar_type res = prm.check_after ? 2 * eps : norm(*r);
181 coef_type rho1 = zero;
182 coef_type rho2 = zero;
183 coef_type alpha = zero;
184 coef_type omega = zero;
187 for (
bool first =
true; res > eps && iter < prm.maxiter; ++iter) {
190 rho1 = inner_product(*r, *rh);
193 backend::copy(*r, *p);
197 precondition(!math::is_zero(rho2),
"Zero rho in BiCGStab");
198 coef_type beta = (rho1 * alpha) / (rho2 * omega);
199 backend::axpbypcz(one, *r, -beta * omega, *v, beta, *p);
202 preconditioner_spmv(prm.pside, P, A, *p, *v, *T);
204 alpha = rho1 / inner_product(*rh, *v);
206 if (prm.pside == ePreconditionerSideType::left) {
207 backend::axpby(alpha, *p, one, x);
210 backend::axpby(alpha, *T, one, x);
213 backend::axpbypcz(one, *r, -alpha, *v, zero, *s);
215 if ((res = norm(*s)) > eps) {
216 preconditioner_spmv(prm.pside, P, A, *s, *t, *T);
218 omega = inner_product(*t, *s) / inner_product(*t, *t);
220 precondition(!math::is_zero(omega),
"Zero omega in BiCGStab");
222 if (prm.pside == ePreconditionerSideType::left) {
223 backend::axpby(omega, *s, one, x);
226 backend::axpby(omega, *T, one, x);
229 backend::axpbypcz(one, *s, -omega, *t, zero, *r);
234 if (prm.verbose && iter % 5 == 0)
235 std::cout << iter <<
"\t" << std::scientific << res / norm_rhs << std::endl;
238 return SolverResult(iter, res / norm_rhs);
249 template <
class Precond,
class Vec1,
class Vec2>
250 SolverResult operator()(
const Precond& P,
const Vec1& rhs, Vec2&& x)
const
252 return (*
this)(P.system_matrix(), P, rhs, x);
257 return backend::bytes(*r) +
262 backend::bytes(*rh) +
266 friend std::ostream& operator<<(std::ostream& os,
const BiCGStabSolver& s)
268 return os <<
"Type: BiCGStab"
269 <<
"\nUnknowns: " << s.n
270 <<
"\nMemory footprint: " << human_readable_memory(s.
bytes())
282 std::shared_ptr<vector> r;
283 std::shared_ptr<vector> p;
284 std::shared_ptr<vector> v;
285 std::shared_ptr<vector> s;
286 std::shared_ptr<vector> t;
287 std::shared_ptr<vector> rh;
288 std::shared_ptr<vector> T;
290 InnerProduct inner_product;
293 scalar_type norm(
const Vec& x)
const
295 return sqrt(math::norm(inner_product(x, x)));