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_SILLY_POWER_METHOD_HPP
00030 #define THYRA_SILLY_POWER_METHOD_HPP
00031
00032 #include "Thyra_LinearOpBase.hpp"
00033 #include "Thyra_VectorStdOps.hpp"
00034
00046 template<class Scalar>
00047 bool sillyPowerMethod(
00048 const Thyra::LinearOpBase<Scalar> &A
00049 ,const int maxNumIters
00050 ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance
00051 ,Scalar *lambda
00052 ,std::ostream *out = NULL
00053 )
00054 {
00055
00056 typedef Teuchos::ScalarTraits<Scalar> ST; typedef typename ST::magnitudeType ScalarMag;
00057 const Scalar one = ST::one(); using Thyra::NOTRANS;
00058 typedef Teuchos::RefCountPtr<const Thyra::VectorSpaceBase<Scalar> > VectorSpacePtr;
00059 typedef Teuchos::RefCountPtr<Thyra::VectorBase<Scalar> > VectorPtr;
00060
00061 if(out) *out << "\nStarting power method (target tolerrance = "<<tolerance<<") ...\n\n";
00062 VectorPtr q = createMember(A.domain()), z = createMember(A.range()), r = createMember(A.range());
00063 Thyra::seed_randomize<Scalar>(0);
00064 Thyra::randomize( Scalar(-one), Scalar(+one), &*z );
00065
00066 for( int iter = 0; iter < maxNumIters; ++iter ) {
00067 const ScalarMag z_nrm = norm(*z);
00068 V_StV( &*q, Scalar(one/z_nrm), *z );
00069 apply( A, NOTRANS , *q, &*z );
00070 *lambda = scalarProd(*q,*z);
00071 if( iter%(maxNumIters/10) == 0 || iter+1 == maxNumIters ) {
00072 V_StVpV(&*r,Scalar(-*lambda),*q,*z);
00073 const ScalarMag r_nrm = norm(*r);
00074 if(out) *out << "Iter = " << iter << ", lambda = " << (*lambda) << ", ||A*q-lambda*q|| = " << r_nrm << std::endl;
00075 if( r_nrm < tolerance ) return true;
00076 }
00077 }
00078 if(out) *out << "\nMaximum number of iterations exceeded with ||-lambda*q + z|| > tolerence = " << tolerance << "\n";
00079 return false;
00080 }
00081
00082 #endif // THYRA_SILLY_POWER_METHOD_HPP