00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef ITL_BICG_INCLUDE
00013 #define ITL_BICG_INCLUDE
00014
00015 #include <complex>
00016 #include <boost/numeric/mtl/concept/collection.hpp>
00017 #include <boost/numeric/itl/itl_fwd.hpp>
00018
00019 namespace itl {
00020
00021
00022 template < typename LinearOperator, typename Vector,
00023 typename Preconditioner, typename Iteration >
00024 int bicg(const LinearOperator &A, Vector &x, const Vector &b,
00025 const Preconditioner &M, Iteration& iter)
00026 {
00027 using mtl::conj;
00028 typedef typename mtl::Collection<Vector>::value_type Scalar;
00029 Scalar rho_1(0), rho_2(0), alpha(0), beta(0);
00030 Vector r(b - A * x), z(size(x)), p(size(x)), q(size(x)),
00031 r_tilde(r), z_tilde(size(x)), p_tilde(size(x)), q_tilde(size(x));
00032
00033 while (! iter.finished(r)) {
00034 z= solve(M, r);
00035 z_tilde= adjoint_solve(M, r_tilde);
00036 rho_1= dot(z_tilde, z);
00037
00038 if (rho_1 == 0.) {
00039 iter.fail(2, "bicg breakdown");
00040 break;
00041 }
00042 if (iter.first()) {
00043 p= z;
00044 p_tilde= z_tilde;
00045 } else {
00046 beta= rho_1 / rho_2;
00047 p= z + beta * p;
00048 p_tilde= z_tilde + conj(beta) * p_tilde;
00049 }
00050
00051 q= A * p;
00052 q_tilde= adjoint(A) * p_tilde;
00053 alpha= rho_1 / dot(p_tilde, q);
00054
00055 x+= alpha * p;
00056 r-= alpha * q;
00057 r_tilde-= conj(alpha) * q_tilde;
00058
00059 rho_2= rho_1;
00060
00061 ++iter;
00062 }
00063 return iter.error_code();
00064 }
00065
00066 }
00067
00068 #endif // ITL_BICG_INCLUDE
00069
00070
00071
00072
00073
00074