2 #ifndef _SOLVER_MINRES_H_ 3 #define _SOLVER_MINRES_H_ 9 template<
class el_type,
class mat_type >
10 void solver<el_type, mat_type> :: minres(
int max_iter,
double stop_tol,
double shift) {
16 el_type alpha[2], beta[2];
20 vector< vector<el_type> > v(2, vector<el_type>(n));
27 double gamma_min = 1e99;
28 el_type delta1[2], delta2[2], ep[2], gamma1[2], gamma2[2];
32 vector<el_type> pk(n), tk(n);
38 vector< vector<el_type> > d(2, vector<el_type>(n));
43 beta[1] = norm(rhs, 2.0);
45 double norm_rhs = beta[1];
48 for (
int i = 0; i < n; i++) {
49 v[1][i] = rhs[i]/beta[1];
55 auto sign = [&](
double x) {
return (abs(x) < eps ? 0 : x/abs(x)); };
59 while (res[(k+1)%2]/norm_rhs > stop_tol && k <= max_iter) {
60 int cur = k%2, nxt = (k+1)%2;
64 D.sqrt_solve(v[cur], pk,
true);
65 L.forwardsolve(pk, tk);
72 D.sqrt_solve(tk, pk,
false);
75 for (
int i = 0; i < n; i++) {
76 pk[i] -= shift * v[cur][i];
80 alpha[cur] = dot_product(v[cur], pk);
83 vector_sum(1, pk, -alpha[cur], v[cur], pk);
85 vector_sum(1, pk, -beta[cur], v[nxt], v[nxt]);
86 beta[nxt] = norm(v[nxt], 2.0);
89 if (abs(beta[nxt]) > eps) {
90 for (
int i = 0; i < n; i++) {
91 v[nxt][i] /= beta[nxt];
97 delta2[cur] = c*delta1[cur] + s*alpha[cur];
98 gamma1[cur] = s*delta1[cur] - c*alpha[cur];
101 ep[nxt] = s*beta[nxt];
102 delta1[nxt] = -c*beta[nxt];
105 double a = gamma1[cur], b = beta[nxt];
108 gamma2[cur] = abs(a);
114 }
else if (abs(a) < eps) {
117 gamma2[cur] = abs(b);
118 }
else if (abs(b) > abs(a)) {
120 s = sign(b)/sqrt(1+t*t);
125 c = sign(a)/sqrt(1+t*t);
133 res[cur] = s*res[nxt];
135 if (k == 1) norm_A = sqrt(alpha[cur]*alpha[cur] + beta[nxt]*beta[nxt]);
137 double tnorm = sqrt(alpha[cur]*alpha[cur] + beta[nxt]*beta[nxt] + beta[cur]*beta[cur]);
138 norm_A = std::max(norm_A, tnorm);
142 if (abs(gamma2[cur]) > eps) {
145 vector_sum(1, v[cur], -ep[cur], d[cur], d[cur]);
146 vector_sum(1, d[cur], -delta2[cur], d[nxt], d[cur]);
148 for (
int i = 0; i < n; i++) {
149 d[cur][i] /= gamma2[cur];
153 vector_sum(1, sol_vec, tau, d[cur], sol_vec);
154 gamma_min = std::min(gamma_min, gamma2[cur]);
155 cond_A = norm_A/gamma_min;
164 if (msg_lvl) printf(
"The estimated condition number of the matrix is %e.\n", cond_A);
166 std::string iter_str =
"iterations";
167 if (k-1 == 1) iter_str =
"iteration";
169 if (msg_lvl) printf(
"MINRES took %i %s and got down to relative residual %e.\n", k-1, iter_str.c_str(), res[(k+1)%2]/norm_rhs);
173 #endif // _SOLVER_MINRES_H_