00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef SELDON_FILE_ITERATIVE_QMR_CXX
00022
00023 namespace Seldon
00024 {
00025
00027
00041 template <class Titer, class Matrix1, class Vector1, class Preconditioner>
00042 int Qmr(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, xi;
00052 Complexe theta_1, gamma_1;
00053 Complexe theta(0), gamma(1), eta(-1);
00054
00055 Vector1 r(b), y(b), z_tld(b); r.Zero();
00056 Vector1 v(b), w(b), p_tld(b);
00057 Vector1 p(b), q(b), d(b), s(b);
00058
00059
00060 int success_init = iter.Init(b);
00061 if (success_init != 0)
00062 return iter.ErrorCode();
00063
00064
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 Copy(r, w);
00077 xi = Norm2(w);
00078
00079 iter.SetNumberIteration(0);
00080
00081 while (! iter.Finished(r))
00082 {
00083 if (rho == Titer(0))
00084 {
00085 iter.Fail(1, "Qmr breakdown #1");
00086 break;
00087 }
00088 if (xi == Titer(0))
00089 {
00090 iter.Fail(2, "Qmr breakdown #2");
00091 break;
00092 }
00093
00094
00095
00096 Mlt(Complexe(1./rho), v);
00097 Mlt(Complexe(1./rho), y);
00098
00099
00100 Mlt(Complexe(1./xi), w);
00101
00102 delta = DotProd(w, y);
00103 if (delta == Complexe(0))
00104 {
00105 iter.Fail(3, "Qmr breakdown #3");
00106 break;
00107 }
00108
00109 M.TransSolve(A, w, z_tld);
00110
00111 if (iter.First())
00112 {
00113 Copy(y, p);
00114 Copy(z_tld, q);
00115 }
00116 else
00117 {
00118
00119
00120 Mlt(Complexe(-(xi * delta / ep)), p);
00121 Add(Complexe(1), y, p);
00122 Mlt(Complexe(-(rho * delta / ep)), q);
00123 Add(Complexe(1), z_tld, q);
00124 }
00125
00126
00127 Mlt(A, p, p_tld);
00128
00129 ep = DotProd(q, p_tld);
00130 if (ep == Complexe(0))
00131 {
00132 iter.Fail(4, "Qmr breakdown #4");
00133 break;
00134 }
00135
00136 beta = ep / delta;
00137 if (beta == Complexe(0))
00138 {
00139 iter.Fail(5, "Qmr breakdown #5");
00140 break;
00141 }
00142
00143
00144 Mlt(Complexe(-beta), v);
00145 Add(Complexe(1), p_tld, v);
00146 M.Solve(A, v, y);
00147
00148 rho_1 = rho;
00149 rho = Norm2(y);
00150
00151
00152 Mlt(SeldonTrans, A, q, z_tld);
00153
00154 Mlt(Complexe(-beta), w); Add(Complexe(1), z_tld, w);
00155
00156 xi = Norm2(w);
00157
00158 gamma_1 = gamma;
00159 theta_1 = theta;
00160
00161 ++iter;
00162 theta = rho / (gamma_1 * beta);
00163 gamma = Complexe(1) / sqrt(1.0 + theta * theta);
00164
00165 if (gamma == Titer(0))
00166 {
00167 iter.Fail(6, "Qmr breakdown #6");
00168 break;
00169 }
00170
00171 eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1);
00172
00173 if (iter.First())
00174 {
00175 Copy(p, d);
00176 Mlt(eta, d);
00177 Copy(p_tld, s);
00178 Mlt(eta, s);
00179 }
00180 else
00181 {
00182 Complexe tmp = (theta_1 * theta_1 * gamma * gamma);
00183 Mlt(tmp, d);
00184 Add(eta, p, d);
00185 Mlt(tmp, s);
00186 Add(eta, p_tld, s);
00187 }
00188 Add(Complexe(1), d, x);
00189 Add(-Complexe(1), s, r);
00190
00191 ++iter;
00192 }
00193
00194 return iter.ErrorCode();
00195 }
00196
00197 }
00198
00199 #define SELDON_FILE_ITERATIVE_QMR_CXX
00200 #endif