Qmr.cxx
1 // Copyright (C) 2003-2009 Marc DuruflĂ©
2 // Copyright (C) 2001-2009 Vivien Mallet
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 
21 #ifndef SELDON_FILE_ITERATIVE_QMR_CXX
22 
23 namespace Seldon
24 {
25 
27 
41 #ifdef SELDON_WITH_VIRTUAL
42  template<class T, class Vector1>
43  int Qmr(const VirtualMatrix<T>& A, Vector1& x, const Vector1& b,
44  Preconditioner_Base<T>& M,
45  Iteration<typename ClassComplexType<T>::Treal>& iter)
46 #else
47  template <class Titer, class Matrix1, class Vector1, class Preconditioner>
48  int Qmr(const Matrix1& A, Vector1& x, const Vector1& b,
49  Preconditioner& M, Iteration<Titer> & iter)
50 #endif
51  {
52  const int N = A.GetM();
53  if (N <= 0)
54  return 0;
55 
56  typedef typename Vector1::value_type Complexe;
57  Complexe delta, ep, beta;
58  typedef typename ClassComplexType<Complexe>::Treal Treal;
59  Treal rho, rho_1, xi;
60  Complexe theta_1, gamma_1;
61  Complexe theta, gamma, eta, one, zero;
62  SetComplexOne(one);
63  SetComplexZero(zero);
64  theta = zero; gamma = one; eta = -one; ep = zero;
65 
66  Vector1 r(b), y(b), z_tld(b);
67  Vector1 v(b), w(b), p_tld(b);
68  Vector1 p(b), q(b), d(b), s(b);
69 
70  // we initialize iter
71  int success_init = iter.Init(b);
72  if (success_init != 0)
73  return iter.ErrorCode();
74 
75  // r = b - Ax
76  Copy(b, r);
77  if (!iter.IsInitGuess_Null())
78  iter.MltAdd(-one, A, x, one, r);
79  else
80  x.Fill(zero);
81 
82  Copy(r, v);
83 
84  M.Solve(A, v, y);
85  rho = Norm2(y);
86 
87  Copy(r, w);
88  xi = Norm2(w);
89 
90  iter.SetNumberIteration(0);
91  // Loop until the stopping criteria are reached
92  while (! iter.Finished(r))
93  {
94  if (rho == Treal(0))
95  {
96  iter.Fail(1, "Qmr breakdown #1");
97  break;
98  }
99  if (xi == Treal(0))
100  {
101  iter.Fail(2, "Qmr breakdown #2");
102  break;
103  }
104 
105  // v = v / rho
106  // y = y / rho
107  Mlt(one/rho, v);
108  Mlt(one/rho, y);
109 
110  // w = w / xi
111  Mlt(one/xi, w);
112 
113  delta = DotProd(w, y);
114  if (delta == zero)
115  {
116  iter.Fail(3, "Qmr breakdown #3");
117  break;
118  }
119 
120  M.TransSolve(A, w, z_tld);
121 
122  if (iter.First())
123  {
124  Copy(y, p);
125  Copy(z_tld, q);
126  }
127  else
128  {
129  // p = y - (xi delta / ep) p
130  // q = z_tld - (rho delta / ep) q
131  Mlt(-xi * delta / ep, p);
132  Add(one, y, p);
133  Mlt(-rho * delta / ep, q);
134  Add(one, z_tld, q);
135  }
136 
137  // product matrix vector p_tld = A*p
138  iter.Mlt(A, p, p_tld);
139 
140  ep = DotProd(q, p_tld);
141  if (ep == zero)
142  {
143  iter.Fail(4, "Qmr breakdown #4");
144  break;
145  }
146 
147  beta = ep / delta;
148  if (beta == zero)
149  {
150  iter.Fail(5, "Qmr breakdown #5");
151  break;
152  }
153 
154  // v = -beta v + p_tld
155  Mlt(-beta, v);
156  Add(one, p_tld, v);
157  M.Solve(A, v, y);
158 
159  rho_1 = rho;
160  rho = Norm2(y);
161 
162  // product matrix vector z_tld = A q
163  iter.Mlt(SeldonTrans, A, q, z_tld);
164  // w = z_tld - beta*w
165  Mlt(-beta, w); Add(one, z_tld, w);
166 
167  xi = Norm2(w);
168 
169  gamma_1 = gamma;
170  theta_1 = theta;
171 
172  ++iter;
173  theta = rho / (gamma_1 * beta);
174  gamma = one / sqrt(one + theta * theta);
175 
176  if (gamma == Treal(0))
177  {
178  iter.Fail(6, "Qmr breakdown #6");
179  break;
180  }
181 
182  eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1);
183 
184  if (iter.First())
185  {
186  Copy(p, d);
187  Mlt(eta, d);
188  Copy(p_tld, s);
189  Mlt(eta, s);
190  }
191  else
192  {
193  Complexe tmp = (theta_1 * theta_1 * gamma * gamma);
194  Mlt(tmp, d);
195  Add(eta, p, d);
196  Mlt(tmp, s);
197  Add(eta, p_tld, s);
198  }
199  Add(one, d, x);
200  Add(-one, s, r);
201 
202  ++iter;
203  }
204 
205  return iter.ErrorCode();
206  }
207 
208 } // end namespace
209 
210 #define SELDON_FILE_ITERATIVE_QMR_CXX
211 #endif
Seldon::Iteration::First
bool First() const
Returns true if it is the first iteration.
Definition: Iterative.cxx:236
Seldon::Norm2
ClassComplexType< T >::Treal Norm2(const VectorExpression< T, E > &X)
returns 2-norm of an expression with vectors
Definition: Functions_BaseInline.cxx:153
Seldon::Iteration::Init
int Init(const Vector1 &r)
Initialization with the right hand side.
Definition: Iterative.cxx:218
Seldon::Iteration::Mlt
void Mlt(const Matrix1 &A, const Vector1 &x, Vector1 &y)
Computes y = A x.
Definition: IterativeInline.cxx:123
Seldon::Iteration::ErrorCode
int ErrorCode()
Returns the error code (if an error occured)
Definition: Iterative.cxx:351
Seldon::Iteration::Fail
void Fail(int i, const string &s)
Informs of a failure in the iterative solver.
Definition: Iterative.cxx:330
Seldon::Iteration::MltAdd
void MltAdd(const T1 &alpha, const Matrix1 &A, const Vector1 &x, const T1 &beta, Vector1 &y)
Computes y = beta y + alpha A x.
Definition: IterativeInline.cxx:109
Seldon::Iteration::SetNumberIteration
void SetNumberIteration(int nb)
Changes the number of iterations.
Definition: Iterative.cxx:177
Seldon::Qmr
int Qmr(const Matrix1 &A, Vector1 &x, const Vector1 &b, Preconditioner &M, Iteration< Titer > &iter)
Solves a linear system by using Quasi-Minimal Residual (QMR)
Definition: Qmr.cxx:48
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::Iteration
Class containing parameters for an iterative resolution.
Definition: Iterative.hxx:59
Seldon::Iteration::IsInitGuess_Null
bool IsInitGuess_Null() const
Returns true if the initial guess is null.
Definition: Iterative.cxx:247
Seldon::Iteration::Finished
bool Finished(const Vector1 &r) const
Returns true if the iterative solver has reached its end.
Definition: Iterative.cxx:264