72 #ifndef GMM_SOLVER_BICGSTAB_H__
73 #define GMM_SOLVER_BICGSTAB_H__
85 template <
typename Matrix,
typename Vector,
typename VectorB,
86 typename Preconditioner>
87 void bicgstab(
const Matrix& A, Vector& x,
const VectorB& b,
88 const Preconditioner& M, iteration &iter) {
90 typedef typename linalg_traits<Vector>::value_type T;
91 typedef typename number_traits<T>::magnitude_type R;
92 typedef typename temporary_dense_vector<Vector>::vector_type temp_vector;
94 T rho_1, rho_2(0),
alpha(0), beta, omega(0);
95 temp_vector p(vect_size(x)), phat(vect_size(x)), s(vect_size(x)),
97 t(vect_size(x)), v(vect_size(x)), r(vect_size(x)), rtilde(vect_size(x));
99 gmm::mult(A, gmm::scaled(x, -T(1)), b, r);
100 gmm::copy(r, rtilde);
102 iter.set_rhsnorm(gmm::vect_norm2(b));
104 if (iter.get_rhsnorm() == 0.0) {
clear(x);
return; }
106 while (!iter.finished(norm_r)) {
108 rho_1 = gmm::vect_sp(rtilde, r);
111 { GMM_ASSERT1(
false,
"Bicgstab failed to converge"); }
112 else { GMM_WARNING1(
"Bicgstab failed to converge");
return; }
120 { GMM_ASSERT1(
false,
"Bicgstab failed to converge"); }
121 else { GMM_WARNING1(
"Bicgstab failed to converge");
return; }
124 beta = (rho_1 / rho_2) * (alpha / omega);
126 gmm::add(gmm::scaled(v, -omega), p);
127 gmm::add(r, gmm::scaled(p, beta), p);
129 gmm::mult(M, p, phat);
130 gmm::mult(A, phat, v);
131 alpha = rho_1 / gmm::vect_sp(v, rtilde);
132 gmm::add(r, gmm::scaled(v, -alpha), s);
134 if (iter.finished_vect(s))
135 { gmm::add(gmm::scaled(phat, alpha), x);
break; }
137 gmm::mult(M, s, shat);
138 gmm::mult(A, shat, t);
141 gmm::add(gmm::scaled(phat, alpha), x);
142 gmm::add(gmm::scaled(shat, omega), x);
143 gmm::add(s, gmm::scaled(t, -omega), r);
151 template <
typename Matrix,
typename Vector,
typename VectorB,
152 typename Preconditioner>
153 void bicgstab(
const Matrix& A,
const Vector& x,
const VectorB& b,
154 const Preconditioner& M, iteration &iter)
155 { bicgstab(A, linalg_const_cast(x), b, M, iter); }
160 #endif // GMM_SOLVER_BICGSTAB_H__