Warning: this documentation for the development version is under construction.
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