00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef ITL_BICGSTAB_INCLUDE
00013 #define ITL_BICGSTAB_INCLUDE
00014
00015 #include <boost/numeric/mtl/concept/collection.hpp>
00016 #include <boost/numeric/mtl/utility/exception.hpp>
00017 #include <boost/numeric/itl/utility/exception.hpp>
00018
00019 namespace itl {
00020
00021 template < class LinearOperator, class HilbertSpaceX, class HilbertSpaceB,
00022 class Preconditioner, class Iteration >
00023 int bicgstab(const LinearOperator& A, HilbertSpaceX& x, const HilbertSpaceB& b,
00024 const Preconditioner& M, Iteration& iter)
00025 {
00026 typedef typename mtl::Collection<HilbertSpaceX>::value_type Scalar;
00027 typedef HilbertSpaceX Vector;
00028
00029 Scalar rho_1(0), rho_2(0), alpha(0), beta(0), gamma, omega(0);
00030 Vector p(size(x)), phat(size(x)), s(size(x)), shat(size(x)),
00031 t(size(x)), v(size(x)), r(size(x)), rtilde(size(x));
00032
00033 r = b - A * x;
00034 rtilde = r;
00035
00036 while (! iter.finished(r)) {
00037
00038 rho_1 = dot(rtilde, r);
00039 MTL_THROW_IF(rho_1 == 0.0, unexpected_orthogonality());
00040
00041 if (iter.first())
00042 p = r;
00043 else {
00044 MTL_THROW_IF(omega == 0.0, unexpected_orthogonality());
00045 beta = (rho_1 / rho_2) * (alpha / omega);
00046 p = r + beta * (p - omega * v);
00047 }
00048 phat = solve(M, p);
00049 v = A * phat;
00050
00051 gamma = dot(rtilde, v);
00052 MTL_THROW_IF(gamma == 0.0, unexpected_orthogonality());
00053
00054 alpha = rho_1 / gamma;
00055 s = r - alpha * v;
00056
00057 if (iter.finished(s)) {
00058 x += alpha * phat;
00059 break;
00060 }
00061 shat = solve(M, s);
00062 t = A * shat;
00063 omega = dot(t, s) / dot(t, t);
00064
00065 x += omega * shat + alpha * phat;
00066 r = s - omega * t;
00067
00068 rho_2 = rho_1;
00069 ++iter;
00070 }
00071 return iter;
00072 }
00073
00074
00075 }
00076
00077 #endif // ITL_BICGSTAB_INCLUDE