Gmres.cxx
1 // Copyright (C) 2003-2009 Marc DuruflĂ©
2 //
3 // This file is part of the linear-algebra library Seldon,
4 // http://seldon.sourceforge.net/.
5 //
6 // Seldon is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your option)
9 // any later version.
10 //
11 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
14 // more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with Seldon. If not, see http://www.gnu.org/licenses/.
18 
19 
20 #ifndef SELDON_FILE_ITERATIVE_GMRES_CXX
21 
22 namespace Seldon
23 {
24 
26 
44 #ifdef SELDON_WITH_VIRTUAL
45  template<class T, class Vector1>
46  int Gmres(const VirtualMatrix<T>& A, Vector1& x, const Vector1& b,
47  Preconditioner_Base<T>& M,
48  Iteration<typename ClassComplexType<T>::Treal>& outer)
49 #else
50  template <class Titer, class MatrixSparse, class Vector1, class Preconditioner>
51  int Gmres(const MatrixSparse& A, Vector1& x, const Vector1& b,
52  Preconditioner& M, Iteration<Titer> & outer)
53 #endif
54  {
55  const int N = A.GetM();
56  if (N <= 0)
57  return 0;
58 
59  typedef typename Vector1::value_type Complexe;
60  Complexe zero, one;
61  SetComplexZero(zero);
62  SetComplexOne(one);
63 
64  int m = outer.GetRestart();
65  // V is the array of orthogonal basis contructed
66  // from the Krylov subspace (v0,A*v0,A^2*v0,...,A^m*v0)
67  std::vector<Vector1> V(m+1, b);
68 
69  // Upper triangular hessenberg matrix
70  // we don't store the sub-diagonal
71  // we apply rotations to eliminate this sub-diagonal
73  H.Fill(zero);
74 
75  // s is the vector of residual norm for each inner iteration
76  // w is used in the Arnoldi algorithm
77  // u is a temporary vector which contains the product A*v(i)
78  // r is the residual
79  Vector1 w(b), r(b), u(b);
80  Vector<Complexe> s(m+1);
81  s.Fill(zero); w.Fill(zero); r.Fill(zero); u.Fill(zero);
82 
83  for (int i = 0; i < m+1; i++)
84  V[i].Fill(zero);
85 
86  typedef typename ClassComplexType<Complexe>::Treal Treal;
87  Vector<Complexe> rotations_sin(m+1);
88  rotations_sin.Fill(zero);
89  Vector<Treal> rotations_cos(m+1);
90  rotations_cos.Fill(Treal(0));
91 
92  // we compute residual
93  Copy(b, w);
94  if (!outer.IsInitGuess_Null())
95  outer.MltAdd(-one, A, x, one, w);
96  else
97  x.Fill(zero);
98 
99  // preconditioning
100  M.Solve(A, w, r);
101  Treal beta = Norm2(r);
102 
103  // we initialize outer
104  int success_init = outer.Init(r);
105  if (success_init != 0)
106  return outer.ErrorCode();
107 
108  // the coefficient H(m+1,m)
109  Complexe hi_ip1;
110 
111  outer.SetNumberIteration(0);
112  // Loop until the stopping criteria are reached
113  while (! outer.Finished(beta))
114  {
115  // we normalize V(0) and we init s
116  Copy(r, V[0]);
117  Mlt(one/beta, V[0]);
118  s.Fill(zero);
119  SetComplexReal(beta, s(0));
120 
121  int i = 0, k;
122 
123  // we initialize the iter iteration
124  // m is the maximum number of inner iterations
125  Iteration<Treal> inner(outer);
126  inner.SetNumberIteration(outer.GetNumberIteration());
127  inner.SetMaxNumberIteration(outer.GetNumberIteration()+m);
128  H.Reallocate(m+1, m+1);
129  H.Fill(zero);
130 
131  do
132  {
133  // product matrix vector u=A*V(i)
134  outer.Mlt(A, V[i], u);
135 
136  // preconditioning
137  M.Solve(A, u, w);
138 
139  // Arnoldi algorithm
140  for (k = 0; k <= i; k++)
141  {
142  // h_{k,i} = \bar{v(k)} w
143  H.Val(k, i) = DotProdConj(V[k], w);
144  Add(-H(k,i), V[k], w);
145  }
146 
147  // we compute h(i+1,i)
148  SetComplexReal(Norm2(w), hi_ip1);
149  Copy(w, V[i+1]);
150 
151  // we normalize V(i+1)
152  if (hi_ip1 != zero)
153  Mlt(one/hi_ip1, V[i+1]);
154 
155  // we apply precedent generated rotations
156  // to the last column we computed.
157  for (k = 0; k < i; k++)
158  ApplyRot(H.Val(k,i), H.Val(k+1,i),
159  rotations_cos(k), rotations_sin(k));
160 
161  // we generate a new rotation Omega=[c s;-conj(s) c] in order to
162  // cancel h(i+1,i) and we store this rotation
163  if (hi_ip1 != zero)
164  {
165  GenRot(H.Val(i,i), hi_ip1,
166  rotations_cos(i), rotations_sin(i));
167  // After this call we must have hi_ip1=0
168  // GenRot must modify the entries H(i,i) hi_ip1
169  // we apply the rotation to the right hand side s
170  ApplyRot(s(i), s(i+1), rotations_cos(i), rotations_sin(i));
171  }
172 
173  ++inner, ++outer, ++i;
174 
175  } while (! inner.Finished(abs(s(i))));
176 
177  // Now we solve the triangular system H
178  H.Resize(i, i); s.Resize(i);
179  Solve(H, s); s.Resize(m+1);
180 
181  // new iterate x = x + sum_0^{i-1} s(k)*V(k)
182  for (k = 0; k < i; k++)
183  Add(s(k), V[k], x);
184 
185  // we compute the new residual
186  Copy(b, w);
187  outer.MltAdd(-one, A, x, one, w);
188  M.Solve(A, w, r);
189 
190  // residual norm
191  beta = Norm2(r);
192  }
193 
194  return outer.ErrorCode();
195 
196  }
197 
198 } // end namespace
199 
200 #define SELDON_FILE_ITERATIVE_GMRES_CXX
201 #endif
Seldon::ApplyRot
void ApplyRot(T &x, T &y, const T &c_, const T &s_)
Rotation of a point in 2-D.
Definition: Functions_Vector.cxx:776
Seldon::Iteration::GetNumberIteration
int GetNumberIteration() const
Returns the number of iterations.
Definition: Iterative.cxx:134
Seldon::Iteration::GetRestart
int GetRestart() const
Returns the restart parameter.
Definition: Iterative.cxx:110
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::Vector
Definition: SeldonHeader.hxx:207
Seldon::Iteration::SetMaxNumberIteration
void SetMaxNumberIteration(int max_iteration)
Changes the maximum number of iterations.
Definition: Iterative.cxx:169
Seldon::Iteration::Init
int Init(const Vector1 &r)
Initialization with the right hand side.
Definition: Iterative.cxx:218
Seldon::Matrix
Definition: SeldonHeader.hxx:226
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::Gmres
int Gmres(const MatrixSparse &A, Vector1 &x, const Vector1 &b, Preconditioner &M, Iteration< Titer > &outer)
Solves a linear system by using Generalized Minimum Residual (GMRES)
Definition: Gmres.cxx:51
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
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::GenRot
void GenRot(T &a_in, T &b_in, T &c_, T &s_)
Computation of rotation between two points.
Definition: Functions_Vector.cxx:707
Seldon::SetComplexReal
void SetComplexReal(int n, std::complex< T > &number)
Sets a complex number to (n, 0).
Definition: CommonInline.cxx:234
Seldon::Iteration::Finished
bool Finished(const Vector1 &r) const
Returns true if the iterative solver has reached its end.
Definition: Iterative.cxx:264