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 #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_LinearOpTester.hpp"
00038 #include "Thyra_LinearOpWithSolveTester.hpp"
00039 #include "Thyra_ListedMultiVectorRandomizer.hpp"
00040 #include "Thyra_DefaultSerialVectorSpaceConverter.hpp"
00041 #include "Teuchos_arrayArg.hpp"
00042 #include "Teuchos_Time.hpp"
00043 #include "Teuchos_ScalarTraits.hpp"
00044
00045
00046
00047
00048
00049 template<class RealScalar>
00050 class SymmetricComplexMultiVectorRandomizer
00051 : public Thyra::MultiVectorRandomizerBase< std::complex<RealScalar> >
00052 {
00053 public:
00054
00055 typedef std::complex<RealScalar> Scalar;
00056
00057 bool isCompatible( const Thyra::VectorSpaceBase<Scalar> &space ) const
00058 {
00059 return space.hasInCoreView();
00060 }
00061
00062 void randomize( Thyra::MultiVectorBase<Scalar> *mv )
00063 {
00064 typedef Teuchos::ScalarTraits<Scalar> ST;
00065 # ifdef TEUCHOS_DEBUG
00066 TEST_FOR_EXCEPT( mv == NULL );
00067 TEST_FOR_EXCEPT( mv->range()->dim() % 2 != 0 );
00068 # endif
00069 Thyra::DetachedMultiVectorView<Scalar> ev_mv(*mv);
00070 const Thyra::Index n = ev_mv.subDim();
00071 for( Thyra::Index j = 1; j <= ev_mv.numSubCols(); ++j ) {
00072 for( Thyra::Index i = 1; i <= n/2; ++i ) {
00073 const Scalar val = ST::random();
00074 ev_mv(i,j) = val;
00075 ev_mv(n-i+1,j) = ST::conjugate(val);
00076 }
00077 }
00078 }
00079
00080 };
00081
00082
00083
00084
00085 template<class RealScalar>
00086 bool run1DFFTExample(
00087 const int N
00088 ,const bool verbose
00089 ,const bool dumpAll
00090 ,const RealScalar tolerance
00091 ,const int outputPrec
00092 )
00093 {
00094 using Teuchos::RCP; using Teuchos::rcp;
00095 using Teuchos::OSTab;
00096 typedef std::complex<RealScalar> ComplexScalar;
00097 typedef Teuchos::ScalarTraits<RealScalar> RST;
00098 bool success = true;
00099 bool result;
00100
00101 Teuchos::RCP<Teuchos::FancyOStream>
00102 out = ( verbose ? Teuchos::VerboseObjectBase::getDefaultOStream() : Teuchos::null );
00103
00104 if(outputPrec > 0) out->precision(outputPrec);
00105
00106 if(verbose)
00107 *out << "\n***\n*** Running 1D FFT example using real scalar type = \'" << RST::name() << "\' ...\n***\n";
00108
00109 Teuchos::Time timer("");
00110 timer.start(true);
00111
00112 if(verbose) *out << "\nA) Constructing a 1D complex-to-complex FFT linear operator C ...\n";
00113
00114 Teuchos::RCP< const Thyra::LinearOpWithSolveBase<ComplexScalar> >
00115 C = Teuchos::rcp( new ComplexFFTLinearOp<RealScalar>(N) );
00116
00117 if(verbose) *out << "\nB) Constructing as set of simple known vectors to be used as random domain and range vectors ...\n";
00118 Thyra::DefaultSerialVectorSpaceConverter<RealScalar,ComplexScalar>
00119 realToComplexConverter;
00120 RCP<const Thyra::VectorSpaceBase<RealScalar> >
00121 realDomainVecSpc = realToComplexConverter.createVectorSpaceFrom(*C->domain());
00122 RCP<Thyra::MultiVectorBase<RealScalar> >
00123 realDomainVec = Thyra::createMember(realDomainVecSpc);
00124 Thyra::seed_randomize<RealScalar>(0);
00125 Thyra::randomize( RealScalar(-RST::one()), RST::one(), &*realDomainVec );
00126 if(verbose && dumpAll)
00127 *out << "\nrealDomainVec:\n" << *realDomainVec;
00128 RCP<Thyra::MultiVectorBase<ComplexScalar> >
00129 complexDomainVec = Thyra::createMember(C->domain()),
00130 complexRangeVec = Thyra::createMember(C->range());
00131 realToComplexConverter.convert(*realDomainVec,&*complexDomainVec);
00132 Thyra::apply( *C, Thyra::NOTRANS, *complexDomainVec, &*complexRangeVec );
00133 if(verbose && dumpAll)
00134 *out << "\ncomplexDomainVec:\n" << *complexDomainVec << "\ncomplexRangeVec:\n" << *complexRangeVec;
00135 Thyra::ListedMultiVectorRandomizer<RealScalar>
00136 realDomainRand( Teuchos::arrayArg<RCP<const Thyra::MultiVectorBase<RealScalar> > >(realDomainVec)(), 1 );
00137 Thyra::ListedMultiVectorRandomizer<ComplexScalar>
00138 complexDomainRand( Teuchos::arrayArg<RCP<const Thyra::MultiVectorBase<ComplexScalar> > >(complexDomainVec)(), 1 ),
00139 complexRangeRand( Teuchos::arrayArg<RCP<const Thyra::MultiVectorBase<ComplexScalar> > >(complexRangeVec)(), 1 );
00140
00141 if(verbose) *out << "\nC) Testing the LinearOpBase interface of the constructed linear operator C ...\n";
00142 Thyra::LinearOpTester<ComplexScalar> linearOpTester;
00143 linearOpTester.set_all_error_tol(tolerance);
00144 linearOpTester.set_all_warning_tol(RealScalar(RealScalar(1e-2)*tolerance));
00145 linearOpTester.show_all_tests(true);
00146 linearOpTester.dump_all(dumpAll);
00147 result = linearOpTester.check(*C,&complexRangeRand,&complexDomainRand,out.get());
00148 if(!result) success = false;
00149
00150 if(verbose) *out << "\nD) Testing the LinearOpWithSolveBase interface of the constructed linear operator C ...\n";
00151
00152 Thyra::LinearOpWithSolveTester<ComplexScalar> linearOpWithSolveTester;
00153 linearOpWithSolveTester.set_all_solve_tol(tolerance);
00154 linearOpWithSolveTester.set_all_slack_error_tol(RealScalar(RealScalar(1e+1)*tolerance));
00155 linearOpWithSolveTester.set_all_slack_warning_tol(tolerance);
00156 linearOpWithSolveTester.show_all_tests(true);
00157 linearOpWithSolveTester.dump_all(dumpAll);
00158 result = linearOpWithSolveTester.check(*C,out.get());
00159 if(!result) success = false;
00160
00161 if(verbose) *out << "\nE) Constructing a 1D real-to-complex FFT linear operator R ...\n";
00162
00163 Teuchos::RCP< const Thyra::LinearOpWithSolveBase< ComplexScalar, RealScalar > >
00164 R = Teuchos::rcp( new RealComplexFFTLinearOp<RealScalar>(N) );
00165
00166 if(verbose) *out << "\nF) Testing the LinearOpBase interface of the constructed linear operator R ...\n";
00167 SymmetricComplexMultiVectorRandomizer<RealScalar> symmetricComplexMultiVectorRandomizer;
00168 Thyra::LinearOpTester<ComplexScalar,RealScalar> RlinearOpTester;
00169 RlinearOpTester.set_all_error_tol(tolerance);
00170 RlinearOpTester.set_all_warning_tol(RealScalar(RealScalar(1e-2)*tolerance));
00171 RlinearOpTester.show_all_tests(true);
00172 RlinearOpTester.dump_all(dumpAll);
00173 result = RlinearOpTester.check(*R,&complexRangeRand,&realDomainRand,out.get());
00174 if(!result) success = false;
00175
00176 timer.stop();
00177
00178 if(verbose) *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n";
00179
00180 return success;
00181
00182 }
00183
00184 #endif // SUN_CXX
00185
00186
00187
00188
00189 int main(int argc, char *argv[])
00190 {
00191
00192 bool success = true;
00193
00194 using Teuchos::CommandLineProcessor;
00195
00196 bool verbose = true;
00197 bool result;
00198
00199 Teuchos::RCP<Teuchos::FancyOStream>
00200 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00201
00202 try {
00203
00204
00205
00206
00207
00208 int N = 4;
00209 bool dumpAll = false;
00210 int outputPrec = -1;
00211
00212 CommandLineProcessor clp;
00213 clp.throwExceptions(false);
00214 clp.addOutputSetupOptions(true);
00215
00216 clp.setOption( "verbose", "quiet", &verbose, "Determines if any output is printed or not." );
00217 clp.setOption( "N", &N, "Power of 2 for size of the FFT." );
00218 clp.setOption( "dump-all", "no-dump-all", &dumpAll, "Print all objects or not." );
00219 clp.setOption( "output-prec", &outputPrec, "Precision for outputting floating point numbers." );
00220
00221 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00222 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00223
00224 #ifndef SUN_CXX
00225
00226 TEST_FOR_EXCEPTION( N < 0, std::logic_error, "Error, N=" << N << " < 1 is not allowed!" );
00227
00228
00229 result = run1DFFTExample<float>(N,verbose,dumpAll,1e-5,outputPrec);
00230 if(!result) success = false;
00231
00232
00233 result = run1DFFTExample<double>(N,verbose,dumpAll,1e-13,outputPrec);
00234 if(!result) success = false;
00235
00236 #ifdef HAVE_TEUCHOS_GNU_MP
00237
00238
00239
00240
00241
00242 #endif // HAVE_TEUCHOS_GNU_MP
00243
00244 #endif // ifndef SUN_CXX
00245
00246 }
00247 catch( const std::exception &excpt ) {
00248 std::cerr << "*** Caught standard exception : " << excpt.what() << std::endl;
00249 success = false;
00250 }
00251 catch( ... ) {
00252 std::cerr << "*** Caught an unknown exception\n";
00253 success = false;
00254 }
00255
00256 #ifndef SUN_CXX
00257
00258 if (verbose) {
00259 if(success) *out << "\nCongratulations! All of the tests checked out!\n";
00260 else *out << "\nOh no! At least one of the tests failed!\n";
00261 }
00262
00263 return success ? 0 : 1;
00264
00265 #else // ifndef SUN_CXX
00266
00267 if (verbose) {
00268 *out << "\nError, the test was never run since SUN_CXX was defined and this test does not build on the Sun compiler!\n";
00269 }
00270
00271 return 1;
00272
00273 #endif // SUN_CXX
00274
00275 }