00001
00005
00006
00007 #ifndef TBCI_SOLVER_GMRES_H
00008 #define TBCI_SOLVER_GMRES_H
00009
00010 #include "../basics.h"
00011
00012 NAMESPACE_TBCI
00013
00014 INST2(template <Matrix<T>, Vector<T> > class NN friend \
00015 void Update (Vector<T>&, int, Matrix<T>&, Vector<T>&, Vector<T>*);)
00016 INST2(template <BdMatrix<T>, Vector<T> > class NN friend \
00017 void Update (Vector<T>&, int, BdMatrix<T>&, Vector<T>&, Vector<T>*);)
00018
00019
00020
00021 template < typename SysMatrix, typename SysVector >
00022 void Update(SysVector& x, int k, SysMatrix& h, SysVector& s, SysVector *V)
00023 {
00024 SysVector y(s);
00025
00026
00027 for (int i = k; i >= 0; --i) {
00028 y(i) /= h(i,i);
00029 for (int j = i - 1; j >= 0; --j)
00030 y(j) -= h(j,i) * y(i);
00031 }
00032
00033 for (int j = 0; j <= k; ++j)
00034
00035
00036 x += (y(j)) * V[j];
00037
00038
00039
00040 }
00041
00049 INST(template <typename T> class NN friend \
00050 void GeneratePlaneRotation(const T &, const double &, double &, T &);)
00051
00052 template<typename T>
00053 inline void GeneratePlaneRotation(const T &dx, const double &dy, double &cs, T &sn)
00054 {
00055 if (UNLIKELY(dy == 0.0)) {
00056 cs = 1.0;
00057 sn = (T)0.0;
00058 } else if (UNLIKELY (dx == (T)0.0)) {
00059 cs = 0.0;
00060 sn = (T)1.0;
00061 }
00062 #if 1
00063 else {
00064 const double rel = fabssqr(dx/dy);
00065 const double ynorm = 1.0 / MATH__ sqrt (1.0 + rel);
00066 cs = MATH__ sqrt(rel) * ynorm;
00067 sn = cs * dy / dx;
00068 }
00069 #else
00070 else {
00071 const double rnorm = 1.0/MATH__ sqrt (fabssqr(dx) + fabssqr(dy));
00072 cs = MATH__ fabs(dx) * rnorm ;
00073 sn = cs * dy / dx;
00074 }
00075 #endif
00076 }
00077
00078
00079 INST(template <typename T> class NN friend \
00080 void ApplyPlaneRotation(T &, T &, const double &, const T &);)
00081
00082 template<typename T>
00083 inline void ApplyPlaneRotation(T &dx, T &dy, const double &cs, const T &sn)
00084 {
00085 register T temp = (cs) * dx + CPLX__ conj (sn) * dy;
00086 dy = cs * dy - sn * dx;
00087 dx = temp;
00088 }
00089
00090
00131 INST3(template <typename T, Matrix<T>, Vector<T> > class NN friend \
00132 int GMRES (const Matrix<T>&, Vector<T>&, const Vector<T>&,\
00133 const Preconditioner_Sig<T, Matrix<T> >&, int&, unsigned int&, double&);)
00134 INST3(template <typename T, BdMatrix<T>, Vector<T> > class NN friend \
00135 int GMRES (const BdMatrix<T>&, Vector<T>&, const Vector<T>&,\
00136 const Preconditioner_Sig<T, BdMatrix<T> >&, int&, unsigned int&, double&);)
00137
00138
00139 template < typename T, typename SysMatrix, typename SysVector >
00140 int GMRES (const SysMatrix &A, SysVector &x, const SysVector &b,
00141 const Preconditioner_Sig<T, SysMatrix> &M, int &m,
00142 unsigned int &max_iter, double &tol)
00143 {
00144 const unsigned int dim = A.rows();
00145 if (m == 0)
00146 m = dim/8+max_iter/4;
00147 if ((unsigned)m > max_iter)
00148 m = max_iter;
00149 SysVector s(m+1), sn(m+1), w(dim), r(dim);
00150 Vector<double> cs(m+1);
00151 Matrix<T> H(m+1, m+1);
00152 int restart = 0;
00153
00154 double normb = MATH__ sqrt(fabssqr(M.solve(b)));
00155 if (UNLIKELY(normb < 1e-16))
00156 normb = 1e-16;
00157
00158 r = M.solve(b - A * x);
00159
00160 const double rel_tol = tol*normb;
00161
00162 double beta = r.fabs();
00163
00164 if (beta <= rel_tol) {
00165 tol = beta / normb;
00166 max_iter = 0;
00167
00168 return 0;
00169 }
00170
00171 unsigned int j;
00172 int err = 0;
00173
00174
00175 SysVector *V = new SysVector[m+1];
00176 for (j = 0; j <= (unsigned)m; ++j)
00177 V[j].resize(dim);
00178
00179 j = 1;
00180 while (j <= max_iter) {
00181
00182 V[0] = r /(T)beta;
00183 s.fill ((T)0.0); s(0) = (T) beta;
00184
00185
00186 for (int i = 0; (i < m) && (j <= max_iter); ++i, ++j) {
00187 int k;
00188
00189 w = M.solve (A * V[i]);
00190
00191 for (k = 0; k <= i; k++) {
00192 H(k, i) = dot (V[k], w);
00193
00194
00195
00196 w -= H(k, i) * V[k];
00197
00198 }
00199 const register double normw = w.fabs();
00200 H(i+1, i) = normw;
00201
00202
00203
00204 if (UNLIKELY(normw == 0))
00205 V[i+1] = w;
00206 else
00207 V[i+1] = w / normw;
00208
00209
00210
00211
00212 for (k = 0; k < i; k++)
00213 ApplyPlaneRotation(H(k,i), H(k+1,i), cs(k), sn(k));
00214
00215 GeneratePlaneRotation(H(i,i), normw, cs(i), sn(i));
00216 ApplyPlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
00217 ApplyPlaneRotation(s(i), s(i+1), cs(i), sn(i));
00218
00219 #ifdef _MSC_VER
00220 using ::fabs;
00221 using ::std::fabs;
00222 beta = fabs(s(i+1));
00223 #else
00224 beta = MATH__ fabs(s(i+1));
00225 #endif
00226
00227 if (beta <= rel_tol) {
00228 Update(x, i, H, s, V);
00229 goto GMR_out;
00230 }
00231 }
00232 Update(x, m - 1, H, s, V);
00233 r = M.solve(b - A * x);
00234 beta = r.fabs();
00235 if (beta < rel_tol)
00236 goto GMR_out;
00237 ++restart;
00238 }
00239
00240 err = 1;
00241
00242 GMR_out:
00243 tol = beta / normb;
00244 max_iter = j;
00245
00246 delete[] V;
00247 return err;
00248 }
00249
00250 NAMESPACE_END
00251
00252 #endif