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_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
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 iter.SetNumberIteration(0);
00077
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
00088
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
00104 Mlt(Complexe(-(rho * delta / ep)), p);
00105 Add(Complexe(1), y, p);
00106 }
00107
00108
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
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 }
00171
00172 #define SELDON_FILE_ITERATIVE_QMRSYM_CXX
00173 #endif