silly1DFFT_serial.cpp

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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #include "Teuchos_CommandLineProcessor.hpp"
00030 #include "Teuchos_RCP.hpp"
00031 #include "Teuchos_VerboseObject.hpp"
00032 
00033 #ifndef SUN_CXX
00034 
00035 #include "ComplexFFTLinearOp.hpp"
00036 #include "RealComplexFFTLinearOp.hpp"
00037 #include "Thyra_DefaultInverseLinearOp.hpp"
00038 #include "Thyra_LinearOpTester.hpp"
00039 #include "Thyra_LinearOpWithSolveTester.hpp"
00040 #include "Thyra_ListedMultiVectorRandomizer.hpp"
00041 #include "Thyra_DefaultSerialVectorSpaceConverter.hpp"
00042 #include "Teuchos_arrayArg.hpp"
00043 #include "Teuchos_Time.hpp"
00044 #include "Teuchos_ScalarTraits.hpp"
00045 
00046 //
00047 // Creates random complex multi-vectors for FFT with symmetic entries
00048 //
00049 
00050 template<class RealScalar>
00051 class SymmetricComplexMultiVectorRandomizer : public Thyra::MultiVectorRandomizerBase< std::complex<RealScalar> > {
00052 public:
00053 
00054   typedef std::complex<RealScalar> Scalar;
00055 
00056   bool isCompatible( const Thyra::VectorSpaceBase<Scalar> &space ) const
00057     {
00058       return space.hasInCoreView();
00059     }
00060 
00061   void randomize( Thyra::MultiVectorBase<Scalar> *mv )
00062     {
00063       typedef Teuchos::ScalarTraits<Scalar> ST;
00064 #     ifdef TEUCHOS_DEBUG
00065       TEST_FOR_EXCEPT( mv == NULL );
00066       TEST_FOR_EXCEPT( mv->range()->dim() % 2 != 0 );
00067 #     endif
00068       Thyra::DetachedMultiVectorView<Scalar> ev_mv(*mv);
00069       const Thyra::Index n = ev_mv.subDim();
00070       for( Thyra::Index j = 1; j <= ev_mv.numSubCols(); ++j ) {
00071         for( Thyra::Index i = 1; i <= n/2; ++i ) {
00072           const Scalar val = ST::random();
00073           ev_mv(i,j)     = val;
00074           ev_mv(n-i+1,j) = ST::conjugate(val);
00075         }
00076       }
00077     }
00078   
00079 };
00080 
00081 //
00082 // This example program does some stuff with FFT.
00083 //
00084 template<class RealScalar>
00085 bool run1DFFTExample(
00086   const int                                                      N
00087   ,const bool                                                    verbose
00088   ,const bool                                                    dumpAll
00089   ,const RealScalar                                              tolerance
00090   ,const int                                                     outputPrec
00091   )
00092 {
00093   using Teuchos::RCP; using Teuchos::rcp;
00094   using Teuchos::OSTab;
00095   typedef std::complex<RealScalar> ComplexScalar;
00096   typedef Teuchos::ScalarTraits<RealScalar> RST;
00097   bool success = true;
00098   bool result;
00099 
00100   Teuchos::RCP<Teuchos::FancyOStream>
00101     out = ( verbose ? Teuchos::VerboseObjectBase::getDefaultOStream() : Teuchos::null );
00102 
00103   if(outputPrec > 0) out->precision(outputPrec);
00104 
00105   if(verbose)
00106     *out << "\n***\n*** Running 1D FFT example using real scalar type = \'" << RST::name() << "\' ...\n***\n";
00107 
00108   Teuchos::Time timer("");
00109   timer.start(true);
00110 
00111   if(verbose) *out << "\nA) Constructing a 1D complex-to-complex FFT linear operator C ...\n";
00112 
00113   Teuchos::RCP< const Thyra::LinearOpWithSolveBase<ComplexScalar> >
00114     C = Teuchos::rcp( new ComplexFFTLinearOp<RealScalar>(N) );
00115 
00116   if(verbose) *out << "\nB) Constructing as set of simple known vectors to be used as random domain and range vectors ...\n";
00117   Thyra::DefaultSerialVectorSpaceConverter<RealScalar,ComplexScalar>
00118     realToComplexConverter;
00119   RCP<const Thyra::VectorSpaceBase<RealScalar> >
00120     realDomainVecSpc = realToComplexConverter.createVectorSpaceFrom(*C->domain());
00121   RCP<Thyra::MultiVectorBase<RealScalar> >
00122     realDomainVec = Thyra::createMember(realDomainVecSpc);
00123   Thyra::seed_randomize<RealScalar>(0);
00124   Thyra::randomize( RealScalar(-RST::one()), RST::one(), &*realDomainVec );
00125   if(verbose && dumpAll)
00126     *out << "\nrealDomainVec:\n" << *realDomainVec;
00127   RCP<Thyra::MultiVectorBase<ComplexScalar> >
00128     complexDomainVec = Thyra::createMember(C->domain()),
00129     complexRangeVec = Thyra::createMember(C->range());
00130   realToComplexConverter.convert(*realDomainVec,&*complexDomainVec);
00131   Thyra::apply( *C, Thyra::NOTRANS, *complexDomainVec, &*complexRangeVec );
00132   if(verbose && dumpAll)
00133     *out << "\ncomplexDomainVec:\n" << *complexDomainVec << "\ncomplexRangeVec:\n" << *complexRangeVec;
00134   Thyra::ListedMultiVectorRandomizer<RealScalar>
00135     realDomainRand( Teuchos::arrayArg<RCP<const Thyra::MultiVectorBase<RealScalar> > >(realDomainVec)(), 1 );
00136   Thyra::ListedMultiVectorRandomizer<ComplexScalar>
00137     complexDomainRand( Teuchos::arrayArg<RCP<const Thyra::MultiVectorBase<ComplexScalar> > >(complexDomainVec)(), 1 ),
00138     complexRangeRand( Teuchos::arrayArg<RCP<const Thyra::MultiVectorBase<ComplexScalar> > >(complexRangeVec)(), 1 );
00139 
00140   if(verbose) *out << "\nC) Testing the LinearOpBase interface of the constructed linear operator C ...\n";
00141   Thyra::LinearOpTester<ComplexScalar> linearOpTester;
00142   linearOpTester.set_all_error_tol(tolerance);
00143   linearOpTester.set_all_warning_tol(RealScalar(RealScalar(1e-2)*tolerance));
00144   linearOpTester.show_all_tests(true);
00145   linearOpTester.dump_all(dumpAll);
00146   result = linearOpTester.check(*C,&complexRangeRand,&complexDomainRand,out.get());
00147   if(!result) success = false;
00148 
00149   if(verbose) *out << "\nD) Testing the LinearOpWithSolveBase interface of the constructed linear operator C ...\n";
00150 
00151   Thyra::LinearOpWithSolveTester<ComplexScalar> linearOpWithSolveTester;
00152   linearOpWithSolveTester.set_all_solve_tol(tolerance);
00153   linearOpWithSolveTester.set_all_slack_error_tol(RealScalar(RealScalar(1e+1)*tolerance));
00154   linearOpWithSolveTester.set_all_slack_warning_tol(tolerance);
00155   linearOpWithSolveTester.show_all_tests(true);
00156   linearOpWithSolveTester.dump_all(dumpAll);
00157   result = linearOpWithSolveTester.check(*C,out.get());
00158   if(!result) success = false;
00159 
00160   if(out.get()) *out << "\nE) Creating a DefaultInverseLinearOp object invC from C and testing the LinearOpBase interface ...\n";
00161 
00162   Teuchos::RCP<const Thyra::LinearOpBase<ComplexScalar> >
00163     invC = inverse(C);
00164 
00165   result = linearOpTester.check(*invC,out.get());
00166   if(!result) success = false;
00167 
00168   if(verbose) *out << "\nF) Constructing a 1D real-to-complex FFT linear operator R ...\n";
00169 
00170   Teuchos::RCP< const Thyra::LinearOpWithSolveBase< ComplexScalar, RealScalar > >
00171     R = Teuchos::rcp( new RealComplexFFTLinearOp<RealScalar>(N) );
00172 
00173   if(verbose) *out << "\nG) Testing the LinearOpBase interface of the constructed linear operator R ...\n";
00174   SymmetricComplexMultiVectorRandomizer<RealScalar> symmetricComplexMultiVectorRandomizer;
00175   Thyra::LinearOpTester<ComplexScalar,RealScalar> RlinearOpTester;
00176   RlinearOpTester.set_all_error_tol(tolerance);
00177   RlinearOpTester.set_all_warning_tol(RealScalar(RealScalar(1e-2)*tolerance));
00178   RlinearOpTester.show_all_tests(true);
00179   RlinearOpTester.dump_all(dumpAll);
00180   result = RlinearOpTester.check(*R,&complexRangeRand,&realDomainRand,out.get());
00181   if(!result) success = false;
00182 
00183   timer.stop();
00184 
00185   if(verbose) *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n";
00186 
00187   return success;
00188 
00189 } // end run1DFFTExample()
00190 
00191 #endif // SUN_CXX
00192 
00193 //
00194 // Actual main driver program
00195 //
00196 int main(int argc, char *argv[])
00197 {
00198 
00199   bool success = true;
00200 
00201   using Teuchos::CommandLineProcessor;
00202 
00203   bool verbose = true;
00204   bool result;
00205 
00206   Teuchos::RCP<Teuchos::FancyOStream>
00207     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00208 
00209   try {
00210 
00211     //
00212     // Read in command-line options
00213     //
00214 
00215     int    N             = 4;
00216     bool   dumpAll       = false;
00217     int    outputPrec    = -1;
00218 
00219     CommandLineProcessor  clp;
00220     clp.throwExceptions(false);
00221     clp.addOutputSetupOptions(true);
00222 
00223     clp.setOption( "verbose", "quiet", &verbose, "Determines if any output is printed or not." );
00224     clp.setOption( "N", &N, "Power of 2 for size of the FFT." );
00225     clp.setOption( "dump-all", "no-dump-all", &dumpAll, "Print all objects or not." );
00226     clp.setOption( "output-prec", &outputPrec, "Precision for outputting floating point numbers." );
00227 
00228     CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00229     if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00230 
00231 #ifndef SUN_CXX
00232 
00233     TEST_FOR_EXCEPTION( N < 0, std::logic_error, "Error, N=" << N << " < 1 is not allowed!" );
00234 
00235     // Run using float
00236     result = run1DFFTExample<float>(N,verbose,dumpAll,1e-5,outputPrec);
00237     if(!result) success = false;
00238 
00239     // Run using double
00240     result = run1DFFTExample<double>(N,verbose,dumpAll,1e-13,outputPrec);
00241     if(!result) success = false;
00242 
00243 #ifdef HAVE_TEUCHOS_GNU_MP
00244 
00245     // Run using mpf_class
00246     //result = run1DFFTExample<mpf_class>(N,verbose,dumpAll,1e-13,outputPrec);
00247     //if(!result) success = false;
00248 
00249 #endif // HAVE_TEUCHOS_GNU_MP
00250 
00251 #endif // ifndef SUN_CXX
00252 
00253   }
00254   catch( const std::exception &excpt ) {
00255     std::cerr << "*** Caught standard exception : " << excpt.what() << std::endl;
00256     success = false;
00257   }
00258   catch( ... ) {
00259     std::cerr << "*** Caught an unknown exception\n";
00260     success = false;
00261   }
00262 
00263 #ifndef SUN_CXX
00264 
00265   if (verbose) {
00266     if(success)   *out << "\nCongratulations! All of the tests checked out!\n";
00267     else          *out << "\nOh no! At least one of the tests failed!\n";
00268   }
00269   
00270   return success ? 0 : 1;
00271 
00272 #else // ifndef SUN_CXX
00273 
00274   if (verbose) {
00275     *out << "\nError, the test was never run since SUN_CXX was defined and this test does not build on the Sun compiler!\n";
00276   }
00277   
00278   return 1;
00279 
00280 #endif // SUN_CXX
00281 
00282 } // end main()

Generated on Tue Oct 20 12:47:11 2009 for Thyra Operator Solve Support by doxygen 1.4.7