00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef ITL_GMRES_INCLUDE
00016 #define ITL_GMRES_INCLUDE
00017
00018 #include <algorithm>
00019 #include <boost/numeric/mtl/concept/collection.hpp>
00020 #include <boost/numeric/mtl/vector/dense_vector.hpp>
00021 #include <boost/numeric/mtl/matrix/dense2D.hpp>
00022
00023 namespace itl {
00024
00025 template < typename Matrix, typename Vector, typename LeftPreconditioner, typename RightPreconditioner, typename Iteration >
00026 int gmres_full(const Matrix &A, Vector &x, const Vector &b,
00027 LeftPreconditioner &L, RightPreconditioner &R,
00028 Iteration& iter, typename mtl::Collection<Vector>::size_type kmax_in)
00029 {
00030 using mtl::irange; using mtl::iall; using mtl::matrix::strict_upper; using std::abs;
00031 typedef typename mtl::Collection<Vector>::value_type Scalar;
00032 typedef typename mtl::Collection<Vector>::size_type Size;
00033
00034 if (size(b) == 0) throw mtl::logic_error("empty rhs vector");
00035
00036 const Scalar zero= math::zero(b[0]);
00037 Scalar rho, w1, w2, nu, hr;
00038 Size k, n(size(x)), kmax(std::min(size(x), kmax_in));
00039 Vector r0(b - A *x), r(solve(L,r0)), s(kmax+1),
00040 c(kmax+1), g(kmax+1), va(n), va0(n), va00(n);
00041 mtl::multi_vector<Vector> v(kmax+1, Vector(n, zero));
00042 mtl::dense2D<Scalar> h(kmax+1, kmax);
00043 irange range_n(0, n);
00044
00045 rho= g[0]= two_norm(r);
00046 if (iter.finished(rho)){
00047 return iter;
00048 }
00049 v.vector(0)= r / rho;
00050
00051
00052 for (k= 0; rho >= iter.atol() && k < kmax; k++, ++iter) {
00053 va0= A * solve(R, v.vector(k));
00054 v.vector(k+1)= va= solve(L,va0);
00055
00056
00057 for (Size j= 0; j < k+1; j++) {
00058 h[j][k]= dot(v.vector(j), v.vector(k+1));
00059 v.vector(k+1)-= h[j][k] * v.vector(j);
00060 }
00061
00062 h[k+1][k]= two_norm(v.vector(k+1));
00063
00064 for(Size j= 0; j < k+1; j++) {
00065 hr= dot(v.vector(k+1), v.vector(j));
00066 h[j][k]+= hr;
00067 v.vector(k+1)-= hr * v.vector(j);
00068 }
00069 h[k+1][k]= two_norm(v.vector(k+1));
00070
00071 if (h[k+1][k] != zero)
00072 v.vector(k+1)*= 1. / h[k+1][k];
00073
00074
00075 for(Size i= 0; i < k; i++) {
00076 w1= c[i]*h[i][k]-s[i]*h[i+1][k];
00077 w2= s[i]*h[i][k]+c[i]*h[i+1][k];
00078 h[i][k]= w1;
00079 h[i+1][k]= w2;
00080 }
00081 nu= sqrt(h[k][k]*h[k][k]+h[k+1][k]*h[k+1][k]);
00082 if(nu != zero){
00083 c[k]= h[k][k]/nu;
00084 s[k]= -h[k+1][k]/nu;
00085 h[k][k]=c[k]*h[k][k]-s[k]*h[k+1][k];
00086 h[k+1][k]=0;
00087 w1= c[k]*g[k]-s[k]*g[k+1];
00088 w2= s[k]*g[k]+c[k]*g[k+1];
00089 g[k]= w1;
00090 g[k+1]= w2;
00091 }
00092 rho= abs(g[k+1]);
00093 }
00094
00095
00096 irange range_k(0, k);
00097
00098 mtl::dense2D<Scalar> v_a(n, k);
00099
00100 for(Size j = 0 ; j < k; j++) {
00101 for(Size i = 0; i < n; i++)
00102 v_a[i][j]= v[i][j];
00103 }
00104
00105 Vector g_a(g[range_k]), y;
00106 try {
00107 y= lu_solve(h[range_k][range_k], g_a);
00108 } catch (mtl::matrix_singular e) {
00109 return iter.fail(2, "GMRES sub-system singular");
00110 }
00111
00112
00113 x+= solve(R, Vector(v_a*y));
00114
00115 r= b - A*x;
00116 if (!iter.finished(r))
00117 return iter.fail(2, "GMRES does not converge");
00118 return iter.error_code();
00119 }
00120
00121
00122 template < typename Matrix, typename Vector, typename LeftPreconditioner,
00123 typename RightPreconditioner, typename Iteration >
00124 int gmres(const Matrix &A, Vector &x, const Vector &b,
00125 LeftPreconditioner &L, RightPreconditioner &R,
00126 Iteration& iter, typename mtl::Collection<Vector>::size_type restart)
00127 {
00128 iter.set_quite(true);
00129 while (!iter.finished())
00130 gmres_full(A, x, b, L, R, iter, restart);
00131 iter.set_quite(false);
00132 return iter;
00133 }
00134
00135
00136
00137 }
00138
00139 #endif // ITL_GMRES_INCLUDE
00140