77constexpr double BICGSTAB_DEFAULT_TOL = 1e-12;
79constexpr long BICGSTAB_DEFAULT_MAXIT = 200;
81constexpr double BICGSTAB_BREAKDOWN_TOL = 1e-14;
85BicgstabResult<T> bicgstab_solve(
const GmresPrepared<T>& prep,
const std::vector<T>& rhsIn,
86 const std::vector<T>& x0In,
double tol,
long maxit) {
87 const std::size_t n = prep.n;
90 if (tol <= 0.0) tol = BICGSTAB_DEFAULT_TOL;
91 if (maxit <= 0) maxit = std::min(
static_cast<long>(n), BICGSTAB_DEFAULT_MAXIT);
92 maxit = std::max(1L, std::min(maxit,
static_cast<long>(n)));
98 std::vector<T> rhs(n), x(n);
99 for (std::size_t i = 0; i < n; ++i) rhs[i] = rhsIn[prep.perm[i]] / prep.rowScale[prep.perm[i]];
100 for (std::size_t i = 0; i < n; ++i) x[i] = x0In[prep.perm[i]];
102 T bnorm = vec_norm2(rhs);
103 if (bnorm == zero) bnorm = one;
111 for (std::size_t i = 0; i < n; ++i) r[i] = rhs[i] - r[i];
112 out.
relres = vec_norm2(r) / bnorm;
114 out.
x.assign(n, zero);
115 for (std::size_t i = 0; i < n; ++i) out.
x[prep.perm[i]] = x[i];
122 const std::vector<T> rhat = r;
123 std::vector<T> p(n, zero), v(n, zero), s(n, zero), t(n, zero), ph(n, zero), sh(n, zero);
125 T rho = one, alpha = one, omega = one;
126 T bestrelres = out.
relres;
128 for (
long it = 0; it < maxit; ++it) {
129 const T rhoNew = vec_dot(rhat, r);
134 if (
num_abs(rhoNew) <= breakT * vec_norm2(rhat) * vec_norm2(r)) {
145 const T beta = (rhoNew / rho) * (alpha / omega);
146 for (std::size_t i = 0; i < n; ++i) p[i] = r[i] + beta * (p[i] - omega * v[i]);
151 prep.csr.mult(ph, v);
154 const T rhatv = vec_dot(rhat, v);
155 if (rhatv == zero || !num_isfinite(rhatv)) {
161 for (std::size_t i = 0; i < n; ++i) s[i] = r[i] - alpha * v[i];
165 const T snorm = vec_norm2(s);
166 if (snorm / bnorm <= tolT) {
167 for (std::size_t i = 0; i < n; ++i) x[i] += alpha * ph[i];
168 out.
relres = snorm / bnorm;
174 prep.csr.mult(sh, t);
177 const T tt = vec_dot(t, t);
178 if (tt == zero || !num_isfinite(tt)) {
182 omega = vec_dot(t, s) / tt;
184 for (std::size_t i = 0; i < n; ++i) x[i] += alpha * ph[i] + omega * sh[i];
185 for (std::size_t i = 0; i < n; ++i) r[i] = s[i] - omega * t[i];
187 out.
relres = vec_norm2(r) / bnorm;
194 if (
num_abs(omega) <= breakT) {
209 out.
x.assign(n, zero);
210 for (std::size_t i = 0; i < n; ++i) out.
x[prep.perm[i]] = x[i];
211 for (std::size_t i = 0; i < n; ++i)
212 if (!num_isfinite(out.
x[i])) {
235 long maxit = 0,
const std::vector<T>& x0 = std::vector<T>()) {
237 "ctmc_bicgstab requires transcendental arithmetic: the iteration stops on a "
238 "residual tolerance and normalizes by a Euclidean norm, so there is no exact "
239 "result to converge to; use ctmc_solve for an exact solve");
240 const std::size_t n = A.
rows();
241 if (A.
cols() != n)
throw InputError(
"ctmc_bicgstab: matrix is not square");
242 if (b.size() != n)
throw InputError(
"ctmc_bicgstab: right-hand side has the wrong length");
243 if (!x0.empty() && x0.size() != n)
throw InputError(
"ctmc_bicgstab: initial guess has the wrong length");
244 std::vector<T> guess = x0;
247 const detail::GmresPrepared<T> prep(A);
248 return detail::bicgstab_solve(prep, b, guess, tol, maxit);
267 "ctmc_bicgstab_multi requires transcendental arithmetic: see ctmc_bicgstab, the "
268 "iteration stops on a residual tolerance rather than reaching an exact value");
269 const std::size_t n = A.
rows();
270 if (A.
cols() != n)
throw InputError(
"ctmc_bicgstab_multi: matrix is not square");
271 if (B.
rows() != n)
throw InputError(
"ctmc_bicgstab_multi: right-hand side block has the wrong height");
273 const detail::GmresPrepared<T> prep(A);
274 const std::size_t nrhs = B.
cols();
277 std::vector<T> rhs(n);
280 for (std::size_t c = 0; c < nrhs; ++c) {
281 for (std::size_t i = 0; i < n; ++i) rhs[i] = B(i, c);
282 const BicgstabResult<T> r = detail::bicgstab_solve(prep, rhs, guess, tol, maxit);
288 for (std::size_t i = 0; i < n; ++i) X(i, c) = r.
x[i];
BicgstabResult< T > ctmc_bicgstab(const Matrix< T > &A, const std::vector< T > &b, double tol=1e-12, long maxit=0, const std::vector< T > &x0=std::vector< T >())
Preconditioned stabilized biconjugate gradients, for the linear systems a generator produces.
BicgstabMultiResult< T > ctmc_bicgstab_multi(const Matrix< T > &A, const Matrix< T > &B, double tol=1e-12, long maxit=0)
Every column of B solved against the SAME equilibration, reordering and ILUT factorization,...