computation/solver/iterative/Gcr.cxx

00001 // Copyright (C) 2003-2009 Marc Duruflé
00002 // Copyright (C) 2001-2009 Vivien Mallet
00003 //
00004 // This file is part of the linear-algebra library Seldon,
00005 // http://seldon.sourceforge.net/.
00006 //
00007 // Seldon is free software; you can redistribute it and/or modify it under the
00008 // terms of the GNU Lesser General Public License as published by the Free
00009 // Software Foundation; either version 2.1 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public License
00018 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00019 
00020 
00021 #ifndef SELDON_FILE_ITERATIVE_GCR_CXX
00022 
00023 namespace Seldon
00024 {
00025 
00027 
00045   template <class Titer, class Matrix1, class Vector1, class Preconditioner>
00046   int Gcr(Matrix1& A, Vector1& x, const Vector1& b,
00047           Preconditioner& M, Iteration<Titer> & outer)
00048   {
00049     const int N = A.GetM();
00050     if (N <= 0)
00051       return 0;
00052 
00053     typedef typename Vector1::value_type Complexe;
00054     int m = outer.GetRestart();
00055     // we initialize outer
00056     int success_init = outer.Init(b);
00057     if (success_init != 0)
00058       return outer.ErrorCode();
00059 
00060     std::vector<Vector1> p(m+1, b), w(m+1, b);
00061 
00062     Vector<Complexe> beta(m+1);
00063 
00064     Vector1 r(b), q(b), u(b);
00065 
00066     for (int i = 0; i < (m+1); i++)
00067       {
00068         p[i].Zero();
00069         w[i].Zero();
00070       }
00071 
00072     // we compute initial residual
00073     Copy(b,u);
00074     if (!outer.IsInitGuess_Null())
00075       MltAdd(Complexe(-1), A, x, Complexe(1), u);
00076     else
00077       x.Zero();
00078 
00079     M.Solve(A, u, r);
00080 
00081     Complexe alpha,delta;
00082 
00083     Titer normr = Norm2(r);
00084     outer.SetNumberIteration(0);
00085     // Loop until the stopping criteria are satisfied
00086     while (! outer.Finished(r))
00087       {
00088         // m is the maximum number of inner iterations
00089         Iteration<Titer> inner(outer);
00090         inner.SetNumberIteration(outer.GetNumberIteration());
00091         inner.SetMaxNumberIteration(outer.GetNumberIteration()+m);
00092         Copy(r, p[0]);
00093         Mlt(Titer(1)/normr, p[0]);
00094 
00095         int j = 0;
00096 
00097         while (! inner.Finished(r) )
00098           {
00099             // product matrix vector u=A*p(j)
00100             Mlt(A, p[j], u);
00101 
00102             // preconditioning
00103             M.Solve(A, u, w[j]);
00104 
00105             beta(j) = DotProdConj(w[j], w[j]);
00106             if (beta(j) == Complexe(0))
00107               {
00108                 outer.Fail(1, "Gcr breakdown #1");
00109                 break;
00110               }
00111 
00112             // new iterate x = x + alpha*p(j) new residual r = r - alpha*w(j)
00113             // where alpha = (conj(r_j),A*p_j)/(A*p_j,A*p_j)
00114             alpha = DotProdConj(w[j], r) / beta(j);
00115             Add(alpha, p[j], x);
00116             Add(-alpha, w[j], r);
00117 
00118             ++inner;
00119             ++outer;
00120             // product Matrix vector u = A*r
00121             Mlt(A, r, u);
00122             M.Solve(A, u, q);
00123 
00124             Copy(r, p[j+1]);
00125             // we compute direction p(j+1) = r(j+1) +
00126             // \sum_{i=0..j} ( -(A*r_j+1,A*p_i)/(A*p_i,A*p_i) p(i))
00127             for (int i = 0; i <= j; i++)
00128               {
00129                 delta = -DotProdConj(w[i], q)/beta(i);
00130                 Add(delta, p[i], p[j+1]);
00131               }
00132 
00133             ++inner;
00134             ++outer;
00135             ++j;
00136           }
00137         normr = Norm2(r);
00138       }
00139 
00140     return outer.ErrorCode();
00141   }
00142 
00143 } // end namespace
00144 
00145 #define SELDON_FILE_ITERATIVE_GCR_CXX
00146 #endif