00001
00007 #ifndef TBCI_SOLVER_QMR_H
00008 #define TBCI_SOLVER_QMR_H
00009
00010 #include "../basics.h"
00011
00012 NAMESPACE_TBCI
00013
00014
00015 INST3(template <typename T, Matrix<T>, Vector<T> > class NN friend \
00016 int QMR (const Matrix<T>&, Vector<T>&, const Vector<T>&,\
00017 const Preconditioner_Sig<T, Matrix<T> >&, const Preconditioner_Sig<T, Matrix<T> >&, unsigned int&, double&);)
00018 INST3(template <typename T, BdMatrix<T>, Vector<T> > class NN friend \
00019 int QMR (const BdMatrix<T>&, Vector<T>&, const Vector<T>&,\
00020 const Preconditioner_Sig<T, BdMatrix<T> >&, const Preconditioner_Sig<T, BdMatrix<T> >&, unsigned int&, double&);)
00021
00022
00057
00058 template < typename T,typename SysMatrix,typename SysVector >
00059 int QMR(const SysMatrix &A, SysVector &x, const SysVector &b,
00060 const Preconditioner_Sig<T, SysMatrix> &M1, const Preconditioner_Sig<T, SysMatrix> &M2,
00061 unsigned int &max_iter, double &tol)
00062 {
00063 double rho, rho_1, xi;
00064
00065
00066
00067
00068 double gamma, gamma_1;
00069
00070 typename SysVector::value_type theta, theta_1;
00071
00072 typename SysVector::value_type eta, delta, beta;
00073 typename SysVector::value_type ep = (typename SysVector::value_type)0;
00074
00075 const unsigned int dim = A.rows();
00076
00077 SysVector r(dim), v_tld(dim), y(dim), w_tld(dim), z(dim);
00078 SysVector v(dim), w(dim), y_tld(dim), z_tld(dim);
00079 SysVector p(dim), q(dim), p_tld(dim), d(dim), s(dim);
00080
00081 double residsqr;
00082 double normbsqr = b.fabssqr();
00083 if (normbsqr < 1e-32)
00084 normbsqr = 1e32;
00085 else
00086 normbsqr = 1.0/normbsqr;
00087 const double tolsqr = sqr(tol);
00088
00089 int err = 1;
00090
00091 r = b - A * x;
00092
00093 #define QMR_OUT(r) do { err = r; goto qmr_out; } while(0)
00094
00095 unsigned i = 0;
00096 if ((residsqr = r.fabssqr() * normbsqr) <= tolsqr)
00097 QMR_OUT (0);
00098
00099
00100
00101
00102 v_tld = r;
00103 y = M1.solve(v_tld);
00104 rho = y.fabs();
00105
00106 w_tld = r;
00107 z = M2.transSolve(w_tld);
00108 xi = z.fabs();
00109
00110 gamma = 1.0;
00111 eta = (typename SysVector::value_type)-1.0;
00112 theta = (typename SysVector::value_type) 0.0;
00113
00114 for (i = 1; i <= max_iter; i++)
00115 {
00116 if (rho == 0.0)
00117 QMR_OUT(2);
00118
00119 if (xi == 0.0)
00120 QMR_OUT(7);
00121
00122 v = v_tld * (1. / rho);
00123 y = y * (1. / rho);
00124
00125 w = w_tld * (1. / xi);
00126 z = z * (1. / xi);
00127
00128
00129 delta = z * y;
00130 if (delta == 0.0)
00131 QMR_OUT(5);
00132
00133 y_tld = M2.solve(y);
00134 z_tld = M1.transSolve(z);
00135
00136 if (i > 1) {
00137 p = y_tld - (typename SysVector::value_type)(xi * delta / ep) * p;
00138 q = z_tld - (typename SysVector::value_type)(rho* delta / ep) * q;
00139 } else {
00140 p = y_tld;
00141 q = z_tld;
00142 }
00143
00144 p_tld = A * p;
00145
00146 ep = q * p_tld;
00147 if (ep == 0.0)
00148 QMR_OUT(6);
00149
00150 beta = ep / delta;
00151 if (beta == 0.0)
00152 QMR_OUT(3);
00153
00154 v_tld = p_tld - beta * v;
00155
00156 y = M1.solve(v_tld);
00157
00158 rho_1 = rho;
00159 rho = y.fabs();
00160 w_tld = A.transMult(q) - beta * w;
00161
00162 z = M2.transSolve(w_tld);
00163
00164 xi = z.fabs();
00165
00166 gamma_1 = gamma;
00167 theta_1 = theta;
00168 theta = rho / (gamma_1 * beta);
00169
00170
00171 #ifdef _MSC_VER
00172
00173 double c(1.0 + fabssqr(theta));
00174 {
00175 using std::sqrt; using ::sqrt;
00176 gamma = sqrt(c);
00177 }
00178 #else
00179 # ifdef HAVE_LIBC_NEQ_CPLX_BUG
00180 # if !defined(_SGI_SOURCE) || !defined(_COMPILER_VERSION)
00181 using STD__ sqrt;
00182 # endif
00183 using MATH__ sqrt;
00184 gamma = 1.0 / sqrt(1.0 + fabssqr(theta));
00185 # else
00186 gamma = 1.0 / MATH__ sqrt(1.0 + fabssqr(theta));
00187 # endif
00188 #endif
00189
00190 if (gamma == 0.0)
00191 QMR_OUT(4);
00192
00193 #if defined(USE_BUILTIN_CPLX) && defined(TYPE)
00194 eta = -hcplx(eta)* rho_1 * gamma * gamma /
00195 (beta * gamma_1 * gamma_1);
00196 #else
00197 eta = -eta * rho_1 * gamma * gamma /
00198 (beta * gamma_1 * gamma_1);
00199 #endif
00200
00201 if (i > 1) {
00202 const typename SysVector::value_type _tmp = fabssqr(theta_1) * fabssqr(gamma);
00203 d = eta * p + _tmp * d;
00204 s = eta * p_tld + _tmp * s;
00205 } else {
00206 d = eta * p;
00207 s = eta * p_tld;
00208 }
00209
00210 x += d;
00211 r -= s;
00212
00213 if ((residsqr = r.fabssqr() * normbsqr) <= tolsqr)
00214 QMR_OUT(0);
00215 }
00216
00217 qmr_out:
00218 max_iter = i;
00219 tol = MATH__ sqrt(residsqr);
00220 return err;
00221 }
00222
00223 NAMESPACE_END
00224
00225 #endif