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

/home/vivien/public_html/.src_seldon/computation/solver/iterative/TfQmr.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_TFQMR_CXX
00022 
00023 namespace Seldon
00024 {
00025 
00027 
00044   template <class Titer, class Matrix1, class Vector1, class Preconditioner>
00045   int TfQmr(Matrix1& A, Vector1& x, const Vector1& b,
00046             Preconditioner& M, Iteration<Titer> & iter)
00047   {
00048     const int N = A.GetM();
00049     if (N <= 0)
00050       return 0;
00051 
00052     Vector1 tmp(b), r0(b), v(b), h(b), w(b),
00053       y1(b), g(b), y0(b), rtilde(b), d(b);
00054 
00055     typedef typename Vector1::value_type Complexe;
00056     Complexe sigma, alpha, beta, eta, rho, rho0;
00057     Titer c, kappa, tau, theta;
00058 
00059     tmp.Zero();
00060     // x is initial value
00061     // 1. r0 = M^{-1} (b - A x)
00062     Copy(b, tmp);
00063     if (!iter.IsInitGuess_Null())
00064       MltAdd(Complexe(-1), A, x, Complexe(1), tmp);
00065     else
00066       x.Zero();
00067 
00068     M.Solve(A, tmp, r0);
00069 
00070     // we initialize iter
00071     int success_init = iter.Init(r0);
00072     if (success_init != 0)
00073       return iter.ErrorCode();
00074 
00075     // 2. w=y=r
00076     Copy(r0, w);
00077     Copy(r0, y1);
00078 
00079     // 3. g=v=M^{-1}Ay
00080     Copy(y1, v);
00081     Mlt(A, v, tmp);
00082     M.Solve(A, tmp, v);
00083     ++iter;
00084 
00085     Copy(v, g);
00086 
00087     // 4. d=0
00088     d.Zero();
00089 
00090     // 5. tau = ||r||
00091     tau = Norm2(r0);
00092 
00093     // 6. theta = eta = 0
00094     theta = 0.0;
00095     eta = 0.0;
00096 
00097     // 7. rtilde = r
00098     Copy(r0, rtilde);
00099 
00100     // 8. rho=dot(rtilde, r)
00101     rho = DotProd(rtilde, r0);
00102     rho0 = rho;
00103 
00104     iter.SetNumberIteration(0);
00105     // Loop until the stopping criteria are reached
00106     for (;;)
00107       {
00108         // 9. 10. 11.
00109         // sigma=dot(rtilde,v)
00110         // alpha=rho/sigma
00111         // y2k=y(2k-1)-alpha*v
00112         sigma = DotProd(rtilde, v);
00113 
00114         if (sigma == Complexe(0))
00115           {
00116             iter.Fail(1, "Tfqmr breakdown: sigma=0");
00117             break;
00118           }
00119         alpha = rho / sigma;
00120 
00121         //y0 = y1 - alpha * v;
00122         Copy(y1, y0);
00123         Add(-alpha, v, y0);
00124 
00125         // 12. h=M^{-1}*A*y
00126         Copy(y0, h);
00127         Mlt(A, h, tmp);
00128         M.Solve(A, tmp, h);
00129         //split the loop of "for m = 2k-1, 2k"
00130 
00131         //The first one
00132         // 13. w = w-alpha*M^{-1} A y0
00133         //w = w - alpha * g;
00134         Add(-alpha, g, w);
00135         // 18. d=y0+((theta0^2)*eta0/alpha)*d         //need check breakdown
00136         if (alpha == Complexe(0))
00137           {
00138             iter.Fail(2, "Tfqmr breakdown: alpha=0");
00139             break;
00140           }
00141         //d = y1 + ( theta * theta * eta / alpha ) * d;
00142         Mlt(theta * theta * eta / alpha,d);
00143         Add(Complexe(1), y1, d);
00144 
00145         // 14. theta=||w||_2/tau0       //need check breakdown
00146         if (tau == Titer(0))
00147           {
00148             iter.Fail(3, "Tfqmr breakdown: tau=0");
00149             break;
00150           }
00151         theta  = Norm2(w) / tau;
00152 
00153         // 15. c = 1/sqrt(1+theta^2)
00154         c = Titer(1) / sqrt(Titer(1) + theta * theta);
00155 
00156         // 16. tau = tau0*theta*c
00157         tau = tau * c * theta;
00158 
00159         // 17.  eta = (c^2)*alpha
00160         eta = c * c * alpha;
00161 
00162         // 19. x = x+eta*d
00163         Add(eta, d, x);
00164         // 20. kappa = tau*sqrt(m+1)
00165         kappa = tau * sqrt( 2.* (iter.GetNumberIteration()+1) );
00166 
00167         // 21. check stopping criterion
00168         if ( iter.Finished(kappa) )
00169           {
00170             break;
00171           }
00172         ++iter;
00173         // g = h;
00174         Copy(h, g);
00175         //The second one
00176 
00177         // 13. w = w-alpha*M^{-1} A y0
00178         // w = w - alpha * g;
00179         Add(-alpha,g,w);
00180         // 18. d = y0+((theta0^2)*eta0/alpha)*d
00181         Mlt(theta * theta * eta / alpha,d);
00182         Add(Complexe(1), y0, d);
00183         // 14. theta=||w||_2/tau0
00184         if (tau == Titer(0))
00185           {
00186             iter.Fail(4, "Tfqmr breakdown: tau=0");
00187             break;
00188           }
00189         theta = Norm2(w) / tau;
00190 
00191         // 15. c = 1/sqrt(1+theta^2)
00192         c = Titer(1) / sqrt(Titer(1) + theta * theta);
00193 
00194         // 16. tau = tau0*theta*c
00195         tau = tau * c * theta;
00196 
00197         // 17.  eta = (c^2)*alpha
00198         eta = c * c * alpha;
00199 
00200         // 19. x = x+eta*d
00201         Add(eta, d, x);
00202 
00203         // 20. kappa = tau*sqrt(m+1)
00204         kappa = tau * sqrt(2.* (iter.GetNumberIteration()+1)  + 1.);
00205 
00206         // 21. check stopping criterion
00207         if ( iter.Finished(kappa) )
00208           {
00209             break;
00210           }
00211 
00212         // 22. rho = dot(rtilde,w)
00213         // 23. beta = rho/rho0                     //need check breakdown
00214 
00215         rho0 = rho;
00216         rho = DotProd(rtilde, w);
00217         if (rho0 == Complexe(0))
00218           {
00219             iter.Fail(5, "tfqmr breakdown: beta=0");
00220             break;
00221           }
00222         beta = rho/rho0;
00223 
00224         // 24. y = w+beta*y0
00225         Copy(w, y1);
00226         Add(beta, y0, y1);
00227 
00228         // 25. g=M^{-1} A y
00229         Copy(y1, g);
00230         Mlt(A, g, tmp);
00231         M.Solve(A, tmp, g);
00232 
00233         // 26. v = M^{-1}A y + beta*( M^{-1} A y0 + beta*v)
00234 
00235         Mlt(beta*beta, v);
00236         Add(beta, h, v);
00237         Add(Complexe(1), g, v);
00238 
00239         ++iter;
00240       }
00241 
00242     return iter.ErrorCode();
00243   }
00244 
00245 } // end namespace
00246 
00247 #define SELDON_FILE_ITERATIVE_TFQMR_CXX
00248 #endif