Warning: this documentation for the development version is under construction.

/home/vivien/public_html/.src_seldon/computation/solver/iterative/Gmres.cxx

00001 // Copyright (C) 2003-2009 Marc Duruflé
00002 //
00003 // This file is part of the linear-algebra library Seldon,
00004 // http://seldon.sourceforge.net/.
00005 //
00006 // Seldon is free software; you can redistribute it and/or modify it under the
00007 // terms of the GNU Lesser General Public License as published by the Free
00008 // Software Foundation; either version 2.1 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public License
00017 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00018 
00019 
00020 #ifndef SELDON_FILE_ITERATIVE_GMRES_CXX
00021 
00022 namespace Seldon
00023 {
00024 
00026 
00044   template <class Titer, class MatrixSparse, class Vector1, class Preconditioner>
00045   int Gmres(MatrixSparse& A, Vector1& x, const Vector1& b,
00046             Preconditioner& M, Iteration<Titer> & outer)
00047   {
00048     const int N = A.GetM();
00049     if (N <= 0)
00050       return 0;
00051 
00052     typedef typename Vector1::value_type Complexe;
00053     Complexe zero(0);
00054 
00055     int m = outer.GetRestart();
00056     // V is the array of orthogonal basis contructed
00057     // from the Krylov subspace (v0,A*v0,A^2*v0,...,A^m*v0)
00058     std::vector<Vector1> V(m+1, b);
00059 
00060     // Upper triangular hessenberg matrix
00061     // we don't store the sub-diagonal
00062     // we apply rotations to eliminate this sub-diagonal
00063     Matrix<Complexe, General, ColUpTriang> H(m+1,m+1); H.Fill(zero);
00064 
00065     // s is the vector of residual norm for each inner iteration
00066     // w is used in the Arnoldi algorithm
00067     // u is a temporary vector which contains the product A*v(i)
00068     // r is the residual
00069     Vector1 w(b), r(b), u(b);
00070     Vector<Complexe> s(m+1);
00071     s.Fill(zero); w.Fill(zero); r.Fill(zero); u.Fill(zero);
00072 
00073     for (int i = 0; i < m+1; i++)
00074       V[i].Fill(zero);
00075 
00076     Vector<Complexe> rotations_sin(m+1);
00077     rotations_sin.Fill(zero);
00078     Vector<Titer> rotations_cos(m+1);
00079     rotations_cos.Fill(Titer(0));
00080 
00081     // we compute residual
00082     Copy(b, w);
00083     if (!outer.IsInitGuess_Null())
00084       MltAdd(Complexe(-1), A, x, Complexe(1), w);
00085     else
00086       x.Fill(zero);
00087 
00088     // preconditioning
00089     M.Solve(A, w, r);
00090     Titer beta = Norm2(r);
00091 
00092     // we initialize outer
00093     int success_init = outer.Init(r);
00094     if (success_init != 0)
00095       return outer.ErrorCode();
00096 
00097     // the coefficient H(m+1,m)
00098     Complexe hi_ip1;
00099 
00100     outer.SetNumberIteration(0);
00101     // Loop until the stopping criteria are reached
00102     while (! outer.Finished(beta))
00103       {
00104         // we normalize V(0) and we init s
00105         Copy(r, V[0]);
00106         Mlt(Complexe(Complexe(1)/beta), V[0]);
00107         s.Fill(zero);
00108         s(0) = beta;
00109 
00110         int i = 0, k;
00111 
00112         // we initialize the iter iteration
00113         // m is the maximum number of inner iterations
00114         Iteration<Titer> inner(outer);
00115         inner.SetNumberIteration(outer.GetNumberIteration());
00116         inner.SetMaxNumberIteration(outer.GetNumberIteration()+m);
00117 
00118         do
00119           {
00120             // product matrix vector u=A*V(i)
00121             Mlt(A, V[i], u);
00122 
00123             // preconditioning
00124             M.Solve(A, u, w);
00125 
00126             // Arnoldi algorithm
00127             for (k = 0; k <= i; k++)
00128               {
00129                 // h_{k,i} = \bar{v(k)} w
00130                 H.Val(k, i) = DotProdConj(V[k], w);
00131                 Add(-H(k,i), V[k], w);
00132               }
00133 
00134             // we compute h(i+1,i)
00135             hi_ip1 = Norm2(w);
00136             Copy(w, V[i+1]);
00137 
00138             // we normalize V(i+1)
00139             if (hi_ip1 != zero)
00140               Mlt(Complexe(1)/hi_ip1, V[i+1]);
00141 
00142             // we apply precedent generated rotations
00143             // to the last column we computed.
00144             for (k = 0; k < i; k++)
00145               ApplyRot(H.Val(k,i), H.Val(k+1,i),
00146                        rotations_cos(k), rotations_sin(k));
00147 
00148             // we generate a new rotation Omega=[c s;-conj(s) c] in order to
00149             // cancel h(i+1,i) and we store this rotation
00150             if (hi_ip1 != zero)
00151               {
00152                 GenRot(H.Val(i,i), hi_ip1,
00153                        rotations_cos(i), rotations_sin(i));
00154                 // After this call we must have hi_ip1=0
00155                 // GenRot must modify the entries H(i,i) hi_ip1
00156                 // we apply the rotation to the right hand side s
00157                 ApplyRot(s(i), s(i+1), rotations_cos(i), rotations_sin(i));
00158               }
00159 
00160             ++inner, ++outer, ++i;
00161 
00162           } while (! inner.Finished(abs(s(i))));
00163 
00164         // Now we solve the triangular system H
00165         H.Resize(i, i); s.Resize(i);
00166         Solve(H, s); s.Resize(m+1);
00167 
00168         // new iterate x = x + sum_0^{i-1} s(k)*V(k)
00169         for (k = 0; k < i; k++)
00170           Add(s(k), V[k], x);
00171 
00172         // we compute the new residual
00173         Copy(b, w);
00174         MltAdd(Complexe(-1), A, x, Complexe(1), w);
00175         M.Solve(A, w, r);
00176 
00177         // residual norm
00178         beta = Norm2(r);
00179       }
00180 
00181     return outer.ErrorCode();
00182 
00183   }
00184 
00185 } // end namespace
00186 
00187 #define SELDON_FILE_ITERATIVE_GMRES_CXX
00188 #endif