92 template <
typename Matrix,
typename Vector,
typename VectorB,
94 void qmr(
const Matrix &A, Vector &x,
const VectorB &b,
const Precond1 &M1,
97 typedef typename linalg_traits<Vector>::value_type T;
98 typedef typename number_traits<T>::magnitude_type R;
100 T delta(0), ep(0), beta(0), theta_1(0), gamma_1(0);
101 T theta(0), gamma(1), eta(-1);
104 typedef typename temporary_vector<Vector>::vector_type TmpVec;
105 size_type nn = vect_size(x);
106 TmpVec r(nn), v_tld(nn), y(nn), w_tld(nn), z(nn), v(nn), w(nn);
107 TmpVec y_tld(nn), z_tld(nn), p(nn), q(nn), p_tld(nn), d(nn), s(nn);
110 if (iter.get_rhsnorm() == 0.0) {
clear(x);
return; }
112 gmm::mult(A, gmm::scaled(x, T(-1)), b, r);
115 gmm::left_mult(M1, v_tld, y);
119 gmm::transposed_right_mult(M1, w_tld, z);
122 while (! iter.finished_vect(r)) {
124 if (rho == R(0) || xi == R(0)) {
125 if (iter.get_maxiter() == size_type(-1))
126 { GMM_ASSERT1(
false,
"QMR failed to converge"); }
127 else { GMM_WARNING1(
"QMR failed to converge");
return; }
129 gmm::copy(gmm::scaled(v_tld, T(R(1)/rho)), v);
130 gmm::scale(y, T(R(1)/rho));
132 gmm::copy(gmm::scaled(w_tld, T(R(1)/xi)), w);
133 gmm::scale(z, T(R(1)/xi));
135 delta = gmm::vect_sp(z, y);
137 if (iter.get_maxiter() == size_type(-1))
138 { GMM_ASSERT1(
false,
"QMR failed to converge"); }
139 else { GMM_WARNING1(
"QMR failed to converge");
return; }
141 gmm::right_mult(M1, y, y_tld);
142 gmm::transposed_left_mult(M1, z, z_tld);
148 gmm::add(y_tld, gmm::scaled(p, -(T(xi * delta) / ep)), p);
149 gmm::add(z_tld, gmm::scaled(q, -(T(rho * delta) / ep)), q);
152 gmm::mult(A, p, p_tld);
154 ep = gmm::vect_sp(q, p_tld);
156 if (iter.get_maxiter() == size_type(-1))
157 { GMM_ASSERT1(
false,
"QMR failed to converge"); }
158 else { GMM_WARNING1(
"QMR failed to converge");
return; }
162 if (iter.get_maxiter() == size_type(-1))
163 { GMM_ASSERT1(
false,
"QMR failed to converge"); }
164 else { GMM_WARNING1(
"QMR failed to converge");
return; }
166 gmm::add(p_tld, gmm::scaled(v, -beta), v_tld);
167 gmm::left_mult(M1, v_tld, y);
172 gmm::mult(gmm::transposed(A), q, w_tld);
173 gmm::add(w_tld, gmm::scaled(w, -beta), w_tld);
174 gmm::transposed_right_mult(M1, w_tld, z);
181 theta = rho / (gamma_1 * beta);
182 gamma = T(1) / gmm::sqrt(T(1) + gmm::sqr(theta));
185 if (iter.get_maxiter() == size_type(-1))
186 { GMM_ASSERT1(
false,
"QMR failed to converge"); }
187 else { GMM_WARNING1(
"QMR failed to converge");
return; }
189 eta = -eta * T(rho_1) * gmm::sqr(gamma) / (beta * gmm::sqr(gamma_1));
192 gmm::copy(gmm::scaled(p, eta), d);
193 gmm::copy(gmm::scaled(p_tld, eta), s);
195 T tmp = gmm::sqr(theta_1 * gamma);
196 gmm::add(gmm::scaled(p, eta), gmm::scaled(d, tmp), d);
197 gmm::add(gmm::scaled(p_tld, eta), gmm::scaled(s, tmp), s);
200 gmm::add(gmm::scaled(s, T(-1)), r);