00001
00004
00005
00006 #ifndef TBCI_SOLVER_BICGSTAB_H
00007 #define TBCI_SOLVER_BICGSTAB_H
00008
00009 #include "../vector.h"
00010 #include "precond.h"
00011
00012 #ifdef SOLVER_LOG
00013 # include <fstream>
00014 # include <iomanip>
00015 #endif
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 NAMESPACE_TBCI
00035
00036
00037
00038
00039
00040
00041
00042 INST3(template <typename T, Matrix<T>, double> class NN friend \
00043 int BiCGSTAB (const Matrix<T> &, Vector<T> &, const Vector<T> &, \
00044 const Preconditioner_Sig<T, Matrix<T> > &, unsigned int&, double&, const unsigned);)
00045 INST3(template <typename T, BdMatrix<T>, double> class NN friend \
00046 int BiCGSTAB (const BdMatrix<T> &, Vector<T> &, const Vector<T> &, \
00047 const Preconditioner_Sig<T, BdMatrix<T> > &, unsigned int&, double&, const unsigned);)
00048 INST3(template <typename T, Symm_BdMatrix<T>, double> class NN friend \
00049 int BiCGSTAB (const Symm_BdMatrix<T> &, Vector<T> &, const Vector<T> &, \
00050 const Preconditioner_Sig<T, Symm_BdMatrix<T> > &, unsigned int&, double&, const unsigned);)
00051
00052
00086 template < typename T, typename SysMatrix, typename T_tol /*= double*/>
00087 int BiCGSTAB (const SysMatrix &A, Vector<T> &x, const Vector<T> &b,
00088 const Preconditioner_Sig<T, SysMatrix> &M, unsigned int& max_iter,
00089 T_tol& tol, const unsigned off = 0)
00090 {
00091 const unsigned int dim = A.rows();
00092 typename SysMatrix::value_type rho_1, rho_2((typename SysMatrix::value_type)1),
00093 alpha((typename SysMatrix::value_type)0), beta,
00094 omega((typename SysMatrix::value_type)0);
00095
00096 Vector<T> p(dim), phat(dim), s(dim), shat(dim), t(dim), v(dim);
00097
00098 const T_tol tolsqr = TBCI__ sqr(tol);
00099 T_tol normbsqr = b.fabssqr();
00100 T_tol residsqr;
00101
00102 if (normbsqr <= (T_tol)1e-32)
00103 normbsqr = T_tol(1e32);
00104 else
00105 normbsqr = T_tol(1) / normbsqr;
00106
00107 Vector<T> r (b - A * x);
00108 Vector<T> rtilde (r);
00109
00110
00111 if (LIKELY((residsqr = r.fabssqr() * normbsqr) <= tolsqr)) {
00112 tol = MATH__ sqrt(residsqr);
00113 max_iter = 0;
00114 return 0;
00115 }
00116 #ifdef SOLVER_LOG
00117 alpha = beta = omega = rho_1 = (typename SysMatrix::value_type)0;
00118 STD__ ofstream cnvg;
00119 if (off) cnvg.open ("bicgstab_cnvg.gnu", STD__ ios::app);
00120 else cnvg.open ("bicgstab_cnvg.gnu");
00121 cnvg << "# Iter res alpha beta omega rho_1 rho_2 rho_1 / sqr(normb)" << STD__ endl;
00122 #endif
00123
00124 for (unsigned int i = 1; i <= max_iter; ++i) {
00125 #ifdef SOLVER_LOG
00126 cnvg << i+off << "\t" << MATH__ sqrt(residsqr) << "\t" << MATH__ fabs(alpha) << "\t" << MATH__ fabs(beta) << "\t"
00127 << MATH__ fabs (omega) << "\t" << MATH__ fabs(rho_1) << "\t" << MATH__ fabs(rho_2) << "\t" << MATH__ fabs(rho_1)*normbsqr << "\n";
00128 #endif
00129 rho_1 = dot (rtilde, r);
00130 if (UNLIKELY(rho_1 == (typename SysMatrix::value_type)0)) {
00131 #ifdef BICGSTAB_RESTART
00132 # ifdef BICGSTAB_REPORT_RESTART
00133 STD__ cerr << "BiCGstab failure 2 (iter " << i
00134 << ") rho1 == " << rho_1 << ". Restart.\n";
00135 # endif
00136
00137 rtilde = b - A*x; r = rtilde;
00138 alpha = 0;
00139 continue;
00140 #else
00141
00142 tol = MATH__ sqrt (residsqr);
00143 return 2;
00144 #endif
00145 }
00146 if (UNLIKELY(i == 1))
00147 p = r;
00148 else {
00149 beta = (rho_1 * alpha) / (rho_2 * omega);
00150 p = r + beta * (p - omega * v);
00151 }
00152 phat = M.solve(p);
00153 v = A * phat;
00154 alpha = rho_1 / dot (rtilde, v);
00155 s = r - alpha * v;
00156 if ((residsqr = s.fabssqr() * normbsqr) < tolsqr) {
00157 x += alpha * phat;
00158 max_iter = i; tol = MATH__ sqrt(residsqr);
00159 return 0;
00160 }
00161 shat = M.solve(s);
00162 t = A * shat;
00163 omega = dot(t,s) / fabssqr(t);
00164
00165 x += alpha * phat + omega * shat;
00166 r = s - omega * t;
00167
00168 rho_2 = rho_1;
00169
00170 if ((residsqr = r.fabssqr() * normbsqr) < tolsqr) {
00171 tol = MATH__ sqrt(residsqr); max_iter = i;
00172 #ifdef SOLVER_LOG
00173 cnvg << i+off << "\t" << MATH__ sqrt(residsqr) << "\t" << MATH__ fabs(alpha) << "\t" << MATH__ fabs(beta) << "\t"
00174 << MATH__ fabs (omega) << "\t" << MATH__ fabs(rho_1) << "\t" << MATH__ fabs(rho_2) << "\t" << MATH__ fabs(rho_1)*normbsqr << STD__ endl;
00175 #endif
00176 return 0;
00177 }
00178 if (UNLIKELY(omega == (typename SysMatrix::value_type)0)) {
00179 tol = MATH__ sqrt(residsqr);
00180 STD__ cerr << "BiCGstab failure 3: omega == 0\n";
00181 max_iter = i;
00182 return 3;
00183 }
00184 }
00185
00186 tol = MATH__ sqrt (residsqr);
00187 return 1;
00188 }
00189
00190 NAMESPACE_END
00191
00192 #endif