00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef ITL_BICGSTAB_ELL_INCLUDE
00016 #define ITL_BICGSTAB_ELL_INCLUDE
00017
00018 #include <boost/numeric/mtl/concept/collection.hpp>
00019 #include <boost/numeric/mtl/vector/dense_vector.hpp>
00020 #include <boost/numeric/mtl/matrix/strict_upper.hpp>
00021 #include <boost/numeric/linear_algebra/identity.hpp>
00022
00023 namespace itl {
00024
00025
00026 template < typename LinearOperator, typename Vector,
00027 typename LeftPreconditioner, typename RightPreconditioner,
00028 typename Iteration >
00029 int bicgstab_ell(const LinearOperator &A, Vector &x, const Vector &b,
00030 const LeftPreconditioner &L, const RightPreconditioner &R,
00031 Iteration& iter, size_t l)
00032 {
00033 using mtl::irange; using mtl::imax; using mtl::matrix::strict_upper;
00034 typedef typename mtl::Collection<Vector>::value_type Scalar;
00035 typedef typename mtl::Collection<Vector>::size_type Size;
00036
00037 if (size(b) == 0) throw mtl::logic_error("empty rhs vector");
00038
00039 const Scalar zero= math::zero(b[0]), one= math::one(b[0]);
00040 Vector x0(size(x)), y(size(x));
00041 mtl::dense_vector<Vector> r_hat(l+1,Vector(size(x))), u_hat(l+1,Vector(size(x)));
00042
00043
00044 x0= zero;
00045 r_hat[0]= b;
00046 if (two_norm(x) != zero) {
00047 r_hat[0]-= A * x;
00048 x0= x;
00049 x= zero;
00050 }
00051
00052 Vector r0_tilde(r_hat[0]/two_norm(r_hat[0]));
00053 y= solve(L, r_hat[0]);
00054 r_hat[0]= y;
00055 u_hat[0]= zero;
00056
00057 Scalar rho_0(one), rho_1(zero), alpha(zero), Gamma(zero), beta(zero), omega(one);
00058 mtl::dense2D<Scalar> tau(l+1, l+1);
00059 mtl::dense_vector<Scalar> sigma(l+1), gamma(l+1), gamma_a(l+1), gamma_aa(l+1);
00060
00061 while (! iter.finished(r_hat[0])) {
00062 rho_0= -omega * rho_0;
00063
00064 for (Size j= 0; j < l; ++j) {
00065 rho_1= dot(r0_tilde, r_hat[j]);
00066 beta= alpha * rho_1/rho_0; rho_0= rho_1;
00067
00068 for (Size i= 0; i <= j; ++i)
00069 u_hat[i]= r_hat[i] - beta * u_hat[i];
00070
00071 y= A * solve(R, u_hat[j]);
00072 u_hat[j+1]= solve(L, y);
00073 Gamma= dot(r0_tilde, u_hat[j+1]);
00074 alpha= rho_0 / Gamma;
00075
00076 for (Size i= 0; i <= j; ++i)
00077 r_hat[i]-= alpha * u_hat[i+1];
00078
00079 if (iter.finished(r_hat[j])) {
00080 x= solve(R, x) + x0;
00081 return iter.error_code();
00082 }
00083
00084 r_hat[j+1]= solve(R, r_hat[j]);
00085 y= A * r_hat[j+1];
00086 r_hat[j+1]= solve(L, y);
00087 x+= alpha * u_hat[0];
00088 }
00089
00090
00091 mtl::dense_vector<Vector> r_hat_tail(r_hat[irange(1, imax)]);
00092 tau[irange(1, imax)][irange(1, imax)]= orthogonalize_factors(r_hat_tail);
00093 for (Size j= 1; j <= l; ++j)
00094 gamma_a[j]= dot(r_hat[j], r_hat[0]) / tau[j][j];
00095
00096 gamma[l]= gamma_a[l]; omega= gamma[l];
00097 if (omega == zero)
00098 return iter.fail(3, "bicg breakdown #2");
00099
00100
00101 for (Size j= l-1; j > 0; --j) {
00102 Scalar sum= zero;
00103 for (Size i=j+1;i<=l;++i)
00104 sum += tau[j][i] * gamma[i];
00105 gamma[j] = gamma_a[j] - sum;
00106 }
00107
00108 gamma_aa[irange(1, l)]= strict_upper(tau[irange(1, l)][irange(1, l)]) * gamma[irange(2, l+1)] + gamma[irange(2, l+1)];
00109
00110 x+= gamma[1] * r_hat[0];
00111 r_hat[0]-= gamma_a[l] * r_hat[l];
00112 u_hat[0]-= gamma[l] * u_hat[l];
00113 for (Size j=1; j < l; ++j) {
00114 u_hat[0] -= gamma[j] * u_hat[j];
00115 x+= gamma_aa[j] * r_hat[j];
00116 r_hat[0] -= gamma_a[j] * r_hat[j];
00117 }
00118 ++iter;
00119 }
00120 x= solve(R, x) + x0;
00121 return iter.error_code();
00122 }
00123
00124
00125 }
00126
00127 #endif // ITL_BICGSTAB_ELL_INCLUDE