NeoPZ
qmr.h
Go to the documentation of this file.
1 
6 #include <math.h>
7 
37 template < class Matrix, class Vector, class Preconditioner1,
38 class Preconditioner2, class Real >
39 int
40 QMR(const Matrix &A, Vector &x, const Vector &b, const Preconditioner1 &M1,
41  const Preconditioner2 &M2, int64_t &max_iter, Real &tol)
42 {
43  Real resid;
44 
45  Vector rho(1), rho_1(1), xi(1), gamma(1), gamma_1(1), theta(1), theta_1(1);
46  Vector eta(1), delta(1), ep(1), beta(1);
47 
48  Vector r, v_tld, y, w_tld, z;
49  Vector v, w, y_tld, z_tld;
50  Vector p, q, p_tld, d, s;
51 
52  Real normb = norm(b);
53 
54  if(normb == 0.0)
55  {
56  normb = 1.;
57  }
58 
59  r = b - A * x;
60 
61 
62  if ((resid = norm(r) / normb) <= tol) {
63  tol = resid;
64  max_iter = 0;
65  return 0;
66  }
67 
68  v_tld = r;
69  y = M1.solve(v_tld);
70  rho(0) = norm(y);
71 
72  w_tld = r;
73  z = M2.trans_solve(w_tld);
74  xi(0) = norm(z);
75 
76  gamma(0) = 1.0;
77  eta(0) = -1.0;
78  theta(0) = 0.0;
79 
80  for (int64_t i = 1; i <= max_iter; i++) {
81 
82  if (rho(0) == 0.0)
83  return 2; // return on breakdown
84 
85  if (xi(0) == 0.0)
86  return 7; // return on breakdown
87 
88  v = (1. / rho(0)) * v_tld;
89  y = (1. / rho(0)) * y;
90 
91  w = (1. / xi(0)) * w_tld;
92  z = (1. / xi(0)) * z;
93 
94  delta(0) = dot(z, y);
95  if (delta(0) == 0.0)
96  return 5; // return on breakdown
97 
98  y_tld = M2.solve(y); // apply preconditioners
99  z_tld = M1.trans_solve(z);
100 
101  if (i > 1) {
102  p = y_tld - (xi(0) * delta(0) / ep(0)) * p;
103  q = z_tld - (rho(0) * delta(0) / ep(0)) * q;
104  } else {
105  p = y_tld;
106  q = z_tld;
107  }
108 
109  p_tld = A * p;
110  ep(0) = dot(q, p_tld);
111  if (ep(0) == 0.0)
112  return 6; // return on breakdown
113 
114  beta(0) = ep(0) / delta(0);
115  if (beta(0) == 0.0)
116  return 3; // return on breakdown
117 
118  v_tld = p_tld - beta(0) * v;
119  y = M1.solve(v_tld);
120 
121  rho_1(0) = rho(0);
122  rho(0) = norm(y);
123  w_tld = A.trans_mult(q) - beta(0) * w;
124  z = M2.trans_solve(w_tld);
125 
126  xi(0) = norm(z);
127 
128  gamma_1(0) = gamma(0);
129  theta_1(0) = theta(0);
130 
131  theta(0) = rho(0) / (gamma_1(0) * beta(0));
132  gamma(0) = 1.0 / sqrt(1.0 + theta(0) * theta(0));
133 
134  if (gamma(0) == 0.0)
135  return 4; // return on breakdown
136 
137  eta(0) = -eta(0) * rho_1(0) * gamma(0) * gamma(0) /
138  (beta(0) * gamma_1(0) * gamma_1(0));
139 
140  if (i > 1) {
141  d = eta(0) * p + (theta_1(0) * theta_1(0) * gamma(0) * gamma(0)) * d;
142  s = eta(0) * p_tld + (theta_1(0) * theta_1(0) * gamma(0) * gamma(0)) * s;
143  } else {
144  d = eta(0) * p;
145  s = eta(0) * p_tld;
146  }
147 
148  x += d; // update approximation vector
149  r -= s; // compute residual
150 
151  if ((resid = norm(r) / normb) <= tol) {
152  tol = resid;
153  max_iter = i;
154  return 0;
155  }
156  }
157 
158  tol = resid;
159  return 1; // no convergence
160 }
static const double tol
Definition: pzgeoprism.cpp:23
expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ sqrt
Definition: tfadfunc.h:120
int QMR(const Matrix &A, Vector &x, const Vector &b, const Preconditioner1 &M1, const Preconditioner2 &M2, int64_t &max_iter, Real &tol)
QMR solves the unsymmetric linear system using the Quasi-Minimal Residual method.
Definition: qmr.h:40
long double gamma(unsigned int n)
Evaluate the factorial of a integer.
Definition: vectors.h:81