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_BICGSTABL_CXX 00022 00023 namespace Seldon 00024 { 00025 00027 00043 template <class Titer, class Matrix1, class Vector1, class Preconditioner> 00044 int BiCgStabl(Matrix1& A, Vector1& x, const Vector1& b, 00045 Preconditioner& M, Iteration<Titer> & iter) 00046 { 00047 const int N = A.GetM(); 00048 if (N <= 0) 00049 return 0; 00050 00051 typedef typename Vector1::value_type Complexe; 00052 int m = iter.GetRestart(); 00053 int l = m; 00054 Complexe rho_0, rho_1, alpha, beta, omega, sigma, zero, unity; 00055 zero = 0.0; unity = 1.0; 00056 00057 // q temporary vector before preconditioning, r0 initial residual 00058 Vector1 q(b), r0(b); 00059 Vector<Complexe> gamma(l+1), gamma_prime(l+1), gamma_twice(l+1); 00060 Matrix<Complexe, General, RowMajor> tau(l+1,l+1); 00061 // history of u and residual r 00062 std::vector<Vector1> r(l+1, b), u(l+1, b); 00063 for (int i = 0; i <= l; i++) 00064 { 00065 r[i].Zero(); 00066 u[i].Zero(); 00067 } 00068 tau.Zero(); gamma.Zero(); gamma_prime.Zero(); gamma_twice.Zero(); 00069 00070 // we compute the residual r = (b - Ax) 00071 Copy(b, r[0]); 00072 if (!iter.IsInitGuess_Null()) 00073 MltAdd(Complexe(-1), A, x, Complexe(1), r[0]); 00074 else 00075 x.Zero(); 00076 00077 // we initialize iter 00078 int success_init = iter.Init(b); 00079 if (success_init !=0 ) 00080 return iter.ErrorCode(); 00081 00082 Copy(r[0], r0); // we keep the first residual 00083 00084 // we initialize constants 00085 rho_0 = unity; alpha = zero; omega = unity; tau.Zero(); 00086 00087 iter.SetNumberIteration(0); 00088 // Loop until the stopping criteria are satisfied 00089 while (! iter.Finished(r[0])) 00090 { 00091 rho_0 *= -omega; 00092 00093 // Bi-CG Part 00094 for (int j = 0; j < l; j++) 00095 { 00096 rho_1 = DotProd(r[j], r0); 00097 if (rho_0 == zero) 00098 { 00099 iter.Fail(1, "Bicgstabl breakdown #1"); 00100 break; 00101 } 00102 beta = alpha*(rho_1/rho_0); 00103 rho_0 = rho_1; 00104 for (int i = 0; i <= j; i++) 00105 { 00106 Mlt(-beta, u[i]); Add(unity, r[i], u[i]); 00107 } 00108 M.Solve(A, u[j], q); // preconditioning 00109 Mlt(A, q, u[j+1]); // product Matrix Vector 00110 00111 ++iter; 00112 sigma = DotProd(u[j+1], r0); 00113 if (sigma == zero) 00114 { 00115 iter.Fail(2, "Bicgstabl Breakdown #2"); 00116 break; 00117 } 00118 alpha = rho_1/sigma; 00119 Add(alpha, u[0], x); 00120 for (int i = 0; i <= j; i++) 00121 Add(-alpha, u[i+1], r[i]); 00122 00123 M.Solve(A, r[j], q); // preconditioning 00124 Mlt(A, q, r[j+1]); // product matrix vector 00125 00126 ++iter; 00127 } 00128 00129 // MR Part modified Gram-Schmidt 00130 for (int j = 1; j <= l; j++) 00131 { 00132 for (int i = 1; i < j; i++) 00133 { 00134 if (gamma(i) != zero) 00135 { 00136 tau(i,j) = DotProd(r[j], r[i])/gamma(i); 00137 Add(-tau(i,j), r[i], r[j]); 00138 } 00139 } 00140 gamma(j) = DotProd(r[j], r[j]); 00141 if (gamma(j) != zero) 00142 gamma_prime(j) = DotProd(r[0], r[j])/gamma(j); 00143 } 00144 00145 // gamma = tau-1 * gamma_prime 00146 gamma(l) = gamma_prime(l); omega = gamma(l); 00147 for (int j = l-1; j >= 1; j--) 00148 { 00149 sigma = zero; 00150 for (int i = j+1; i <= l; i++) 00151 sigma += tau(j,i)*gamma(i); 00152 00153 gamma(j) = gamma_prime(j)-sigma; 00154 } 00155 00156 // gamma_twice=T*S*gamma 00157 for (int j = 1; j <= l-1; j++) 00158 { 00159 sigma = zero; 00160 for (int i = j+1; i <= l-1; i++) 00161 sigma += tau(j,i)*gamma(i+1); 00162 00163 gamma_twice(j) = gamma(j+1)+sigma; 00164 } 00165 00166 // update 00167 Add(gamma(1), r[0], x); 00168 Add(-gamma_prime(l), r[l], r[0]); 00169 Add(-gamma(l), u[l], u[0]); 00170 for (int j = 1;j <= l-1; j++) 00171 { 00172 Add(-gamma(j), u[j], u[0]); 00173 Add(gamma_twice(j), r[j], x); 00174 Add(-gamma_prime(j), r[j], r[0]); 00175 } 00176 } 00177 // change of coordinates (right preconditioning) 00178 Copy(x,q); M.Solve(A, q, x); 00179 return iter.ErrorCode(); 00180 } 00181 00182 } 00183 00184 #define SELDON_FILE_ITERATIVE_BICGSTABL_CXX 00185 #endif