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;
114 typedef typename math::scalar_of<value_type>::type scalar_type;
117 typename math::rhs_of<value_type>::type>::return_type coef_type;
124 const params& prm = params(),
125 const backend_params& backend_prm = backend_params(),
126 const InnerProduct& inner_product = InnerProduct())
127 : SolverBase(context)
130 , r(Backend::create_vector(n, backend_prm))
131 , p(Backend::create_vector(n, backend_prm))
132 , v(Backend::create_vector(n, backend_prm))
133 , s(Backend::create_vector(n, backend_prm))
134 , t(Backend::create_vector(n, backend_prm))
135 , rh(Backend::create_vector(n, backend_prm))
136 , T(Backend::create_vector(n, backend_prm))
137 , inner_product(inner_product)
152 template <
class Matrix,
class Precond,
class Vec1,
class Vec2>
153 SolverResult operator()(
const Matrix& A,
const Precond& P,
const Vec1& rhs, Vec2&& x)
const
155 static const coef_type one = math::identity<coef_type>();
156 static const coef_type zero = math::zero<coef_type>();
160 scalar_type norm_rhs = norm(rhs);
162 std::cout <<
"BiCGStab solver rhs_norm=" << std::scientific << norm_rhs <<
"\n";
164 if (norm_rhs < Alina::detail::eps<scalar_type>(1)) {
166 norm_rhs = math::identity<scalar_type>();
170 return SolverResult(0, norm_rhs);
174 if (prm.pside == ePreconditionerSideType::left) {
175 backend::residual(rhs, A, x, *rh);
179 backend::residual(rhs, A, x, *r);
181 backend::copy(*r, *rh);
183 scalar_type eps = std::max(norm_rhs * prm.tol, prm.abstol);
184 scalar_type res = prm.check_after ? 2 * eps : norm(*r);
187 std::cout <<
"BiCGStab eps=" << std::scientific << eps <<
" res=" << res <<
"\n";
189 coef_type rho1 = zero;
190 coef_type rho2 = zero;
191 coef_type alpha = zero;
192 coef_type omega = zero;
195 for (
bool first =
true; res > eps && iter < prm.maxiter; ++iter) {
198 rho1 = inner_product(*r, *rh);
201 backend::copy(*r, *p);
205 precondition(!math::is_zero(rho2),
"Zero rho in BiCGStab");
206 coef_type beta = (rho1 * alpha) / (rho2 * omega);
207 backend::axpbypcz(one, *r, -beta * omega, *v, beta, *p);
210 preconditioner_spmv(prm.pside, P, A, *p, *v, *T);
212 alpha = rho1 / inner_product(*rh, *v);
214 if (prm.pside == ePreconditionerSideType::left) {
215 backend::axpby(alpha, *p, one, x);
218 backend::axpby(alpha, *T, one, x);
221 backend::axpbypcz(one, *r, -alpha, *v, zero, *s);
223 if ((res = norm(*s)) > eps) {
224 preconditioner_spmv(prm.pside, P, A, *s, *t, *T);
226 omega = inner_product(*t, *s) / inner_product(*t, *t);
228 precondition(!math::is_zero(omega),
"Zero omega in BiCGStab");
230 if (prm.pside == ePreconditionerSideType::left) {
231 backend::axpby(omega, *s, one, x);
234 backend::axpby(omega, *T, one, x);
237 backend::axpbypcz(one, *s, -omega, *t, zero, *r);
243 std::cout << iter <<
" res/norm_rhs=" << std::scientific << res / norm_rhs <<
" res=" << res <<
"\n";
246 return SolverResult(iter, res / norm_rhs);
257 template <
class Precond,
class Vec1,
class Vec2>
258 SolverResult operator()(
const Precond& P,
const Vec1& rhs, Vec2&& x)
const
260 return (*
this)(P.system_matrix(), P, rhs, x);
265 return backend::bytes(*r) +
270 backend::bytes(*rh) +
274 friend std::ostream& operator<<(std::ostream& os,
const BiCGStabSolver& s)
276 return os <<
"Type: BiCGStab"
277 <<
"\nUnknowns: " << s.n
278 <<
"\nMemory footprint: " << human_readable_memory(s.
bytes())
290 std::shared_ptr<vector> r;
291 std::shared_ptr<vector> p;
292 std::shared_ptr<vector> v;
293 std::shared_ptr<vector> s;
294 std::shared_ptr<vector> t;
295 std::shared_ptr<vector> rh;
296 std::shared_ptr<vector> T;
298 InnerProduct inner_product;
301 scalar_type norm(
const Vec& x)
const
303 return sqrt(math::norm(inner_product(x, x)));