Thyra Version of the Day
sillyPowerMethod.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef THYRA_SILLY_POWER_METHOD_HPP
00043 #define THYRA_SILLY_POWER_METHOD_HPP
00044 
00045 #include "Thyra_LinearOpBase.hpp"
00046 #include "Thyra_VectorStdOps.hpp"
00047 
00048 
00060 template<class Scalar>
00061 bool sillyPowerMethod(
00062   const Thyra::LinearOpBase<Scalar> &A,
00063   const int maxNumIters,
00064   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance,
00065   const Teuchos::Ptr<Scalar> &lambda,
00066   std::ostream &out
00067   )
00068 {
00069 
00070   // Create some typedefs and some other stuff to make the code cleaner
00071   typedef Teuchos::ScalarTraits<Scalar> ST; typedef typename ST::magnitudeType ScalarMag;
00072   using Thyra::apply;
00073   const Scalar one = ST::one(); using Thyra::NOTRANS;
00074   typedef Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > VectorSpacePtr;
00075   typedef Teuchos::RCP<Thyra::VectorBase<Scalar> > VectorPtr;
00076 
00077   // Initialize
00078   out << "\nStarting power method (target tolerance = "<<tolerance<<") ...\n\n";
00079   VectorPtr q = createMember(A.domain()), z = createMember(A.range()), r = createMember(A.range());
00080   Thyra::seed_randomize<Scalar>(0);
00081   Thyra::randomize( Scalar(-one), Scalar(+one), z.ptr() );
00082 
00083   // Perform iterations
00084   for( int iter = 0; iter < maxNumIters; ++iter ) {
00085     const ScalarMag z_nrm = norm(*z);           // Compute natural norm of z
00086     V_StV( q.ptr(), Scalar(one/z_nrm), *z );    // q = (1/||z||)*z 
00087     apply<Scalar>( A, NOTRANS , *q, z.ptr() );  // z = A*q
00088     *lambda = scalarProd(*q,*z);                // lambda = <q,z>
00089     if( iter%(maxNumIters/10) == 0 || iter+1 == maxNumIters ) {
00090       V_StVpV(r.ptr(),Scalar(-*lambda),*q,*z);  // r = -lambda*q + z
00091       const ScalarMag r_nrm = norm(*r);         // Compute natural norm of r
00092       out << "Iter = " << iter << ", lambda = " << (*lambda)
00093           << ", ||A*q-lambda*q|| = " << r_nrm << std::endl;
00094       if( r_nrm < tolerance )
00095         return true;  // Success!
00096     }
00097   }
00098 
00099   out << "\nMaximum number of iterations exceeded with ||-lambda*q + z||"
00100     " > tolerence = " << tolerance << "\n";
00101   return false; // Failure
00102 
00103 } // end sillyPowerMethod
00104 
00105 
00106 #endif // THYRA_SILLY_POWER_METHOD_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines