00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef THYRA_SILLIEST_CG_SOLVE_HPP
00030 #define THYRA_SILLIEST_CG_SOLVE_HPP
00031
00032 #include "Thyra_LinearOperatorImpl.hpp"
00033 #include "Thyra_VectorSpaceImpl.hpp"
00034 #include "Thyra_VectorImpl.hpp"
00035 #include "Thyra_AssertOp.hpp"
00036
00048 template<class Scalar>
00049 bool silliestCgSolve(
00050 Thyra::ConstLinearOperator<Scalar> const& A
00051 ,Thyra::ConstVector<Scalar> const& b
00052 ,const int maxNumIters
00053 ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance
00054 ,Thyra::Vector<Scalar> & x
00055 ,std::ostream * out = NULL
00056 )
00057 {
00058
00059 typedef Teuchos::ScalarTraits<Scalar> ST;
00060 typedef typename ST::magnitudeType ScalarMag;
00061 const Scalar one = ST::one(), zero = ST::zero();
00062 using Thyra::VectorSpace;
00063 using Thyra::Vector;
00064
00065 const VectorSpace<Scalar> space = A.domain();
00066 Vector<Scalar> r = b - A*x;
00067 ScalarMag r0_nrm = norm(r);
00068 if(r0_nrm==zero) return true;
00069 Vector<Scalar> p(space), q(space);
00070 Scalar rho_old = -one;
00071
00072 for( int iter = 0; iter <= maxNumIters; ++iter ) {
00073
00074 const ScalarMag r_nrm = norm(r);
00075 const bool isConverged = ( (r_nrm/r0_nrm) <= tolerance );
00076 if( ( iter%(maxNumIters/10+1) == 0 || iter == maxNumIters || isConverged ) && out )
00077 *out<<"Iter = "<<iter<<", ||b-A*x||/||b-A*x0|| = "<<(r_nrm/r0_nrm)<<std::endl;
00078 if( r_nrm/r0_nrm < tolerance ) return true;
00079
00080 const Scalar rho = inner(r,r);
00081 if(iter==0) copyInto(r,p);
00082 else p = Scalar(rho/rho_old)*p + r;
00083 q = A*p;
00084 const Scalar alpha = rho/inner(p,q);
00085 x += Scalar(+alpha)*p;
00086 r += Scalar(-alpha)*q;
00087 rho_old = rho;
00088 }
00089 return false;
00090 }
00091
00092 #endif // THYRA_SILLIEST_CG_SOLVE_HPP