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