00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef ITL_TFQMR_INCLUDE
00016 #define ITL_TFQMR_INCLUDE
00017
00018 #include <boost/numeric/mtl/concept/collection.hpp>
00019
00020
00021 namespace itl {
00022
00023
00024 template < typename Matrix, typename Vector,
00025 typename LeftPreconditioner, typename RightPreconditioner, typename Iteration >
00026 int tfqmr(const Matrix &A, Vector &x, const Vector &b, const LeftPreconditioner &L, const RightPreconditioner &R, Iteration& iter)
00027 {
00028 using mtl::irange; using mtl::imax; using math::reciprocal;
00029 typedef typename mtl::Collection<Vector>::value_type Scalar;
00030 typedef typename mtl::Collection<Vector>::size_type Size;
00031
00032 if (size(b) == 0) throw mtl::logic_error("empty rhs vector");
00033
00034 const Scalar zero= math::zero(b[0]), one= math::one(b[0]);
00035 Scalar theta(zero), eta(zero), tau, rho, rhon, sigma,
00036 alpha, beta, c, m;
00037 Size k(0), n(size(x));
00038
00039 Vector rt(b - A*solve(R,x)), r(solve(L,rt)),
00040 u1(n), u2(n), y1(n), y2(n), w(n), d(n, zero), v(n);
00041
00042 if (iter.finished(rt))
00043 return iter;
00044 y1= w= r;
00045 rt= A * solve(R, y1);
00046 u1= v= solve(L,rt);
00047 tau= two_norm(r);
00048 rho= tau*tau;
00049
00050
00051 while(! iter.finished(tau)){
00052 sigma= dot(r,v);
00053 if (sigma == zero)
00054 return iter.fail(1, "tfgmr breakdown, sigma=0 #1");
00055 alpha= rho / sigma;
00056
00057
00058 for(int j=1; j < 3; j++) {
00059 m= 2 * k - 2 + j;
00060 if (j == 1) {
00061 w-= alpha * u1;
00062 d= y1+ (theta * theta * eta / alpha) * d;
00063 } else {
00064 y2= y1 - alpha * v;
00065 rt= A * solve(R, y2);
00066 u2= solve(L, rt);
00067 w-= alpha * u2;
00068 d= y2 + (theta * theta * eta / alpha) * d;
00069 }
00070 theta= two_norm(w) / tau;
00071 c= reciprocal(sqrt(one + theta*theta));
00072 tau*= theta * c;
00073 eta= c * c * alpha;
00074 x+= eta * d;
00075 }
00076 if (rho == zero)
00077 return iter.fail(1, "tfgmr breakdown, rho=0 #2");
00078 rhon= dot(r,w);
00079 beta= rhon/rho;
00080 rho= rhon;
00081 y1= w + beta*y2;
00082 rt= A * solve(R, y1);
00083 u1= solve(L, rt);
00084 v= u1 + beta*(u2 + beta*v);
00085 rt= A*x-b;
00086
00087 ++iter;
00088 }
00089
00090 x= solve(R, x);
00091 return iter;
00092 }
00093
00094 }
00095
00096 #endif // ITL_TFQMR_INCLUDE