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_QMRSYM_CXX 00022 00023 namespace Seldon 00024 { 00025 00027 00041 template <class Titer, class Matrix1, class Vector1, class Preconditioner> 00042 int QmrSym(Matrix1& A, Vector1& x, const Vector1& b, 00043 Preconditioner& M, Iteration<Titer> & iter) 00044 { 00045 const int N = A.GetM(); 00046 if (N <= 0) 00047 return 0; 00048 00049 typedef typename Vector1::value_type Complexe; 00050 Complexe delta, ep(0), beta; 00051 Titer rho, rho_1; 00052 Complexe theta_1, gamma_1; 00053 Complexe theta(0), gamma(1), eta(-1); 00054 00055 Vector1 r(b), y(b); 00056 Vector1 v(b), p_tld(b); 00057 Vector1 p(b), d(b), s(b); 00058 00059 // we initialize iter 00060 int success_init = iter.Init(b); 00061 if (success_init != 0) 00062 return iter.ErrorCode(); 00063 00064 // r = b - Ax 00065 Copy(b, r); 00066 if (!iter.IsInitGuess_Null()) 00067 MltAdd(Complexe(-1), A, x, Complexe(1), r); 00068 else 00069 x.Zero(); 00070 00071 Copy(r, v); 00072 00073 M.Solve(A, v, y); 00074 rho = Norm2(y); 00075 00076 iter.SetNumberIteration(0); 00077 // Loop until the stopping criteria are reached 00078 while (! iter.Finished(r)) 00079 { 00080 00081 if (rho == Titer(0)) 00082 { 00083 iter.Fail(1, "Qmr breakdown #1"); 00084 break; 00085 } 00086 00087 // v = v / rho 00088 // y = y / rho 00089 Mlt(Complexe(1./rho), v); 00090 Mlt(Complexe(1./rho), y); 00091 00092 delta = DotProd(v, y); 00093 if (delta == Complexe(0)) 00094 { 00095 iter.Fail(3, "Qmr breakdown #2"); 00096 break; 00097 } 00098 00099 if (iter.First()) 00100 Copy(y, p); 00101 else 00102 { 00103 // p = y - (rho delta / ep) p 00104 Mlt(Complexe(-(rho * delta / ep)), p); 00105 Add(Complexe(1), y, p); 00106 } 00107 00108 // product matrix vector p_tld = A*p 00109 Mlt(A, p, p_tld); 00110 00111 ep = DotProd(p, p_tld); 00112 if (ep == Complexe(0)) 00113 { 00114 iter.Fail(4, "Qmr breakdown #3"); 00115 break; 00116 } 00117 00118 beta = ep / delta; 00119 if (beta == Complexe(0)) 00120 { 00121 iter.Fail(5, "Qmr breakdown #4"); 00122 break; 00123 } 00124 00125 // v = -beta v + p_tld 00126 Mlt(Complexe(-beta), v); Add(Complexe(1), p_tld, v); 00127 M.Solve(A, v, y); 00128 00129 rho_1 = rho; 00130 rho = Norm2(y); 00131 00132 gamma_1 = gamma; 00133 theta_1 = theta; 00134 00135 theta = rho / (gamma_1 * beta); 00136 gamma = Complexe(1) / sqrt(1.0 + theta * theta); 00137 00138 if (gamma == Titer(0)) 00139 { 00140 iter.Fail(6, "Qmr breakdown #5"); 00141 break; 00142 } 00143 00144 eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1); 00145 00146 if (iter.First()) 00147 { 00148 Copy(p, d); 00149 Mlt(eta, d); 00150 Copy(p_tld, s); 00151 Mlt(eta, s); 00152 } 00153 else 00154 { 00155 Complexe tmp = (theta_1 * theta_1 * gamma * gamma); 00156 Mlt(tmp, d); 00157 Add(eta, p, d); 00158 Mlt(tmp, s); 00159 Add(eta, p_tld, s); 00160 } 00161 Add(Complexe(1), d, x); 00162 Add(-Complexe(1), s, r); 00163 00164 ++iter; 00165 } 00166 00167 return iter.ErrorCode(); 00168 } 00169 00170 } // end namespace 00171 00172 #define SELDON_FILE_ITERATIVE_QMRSYM_CXX 00173 #endif