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_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
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
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 }
00190
00191 #endif // SUN_CXX
00192
00193
00194
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
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
00236 result = run1DFFTExample<float>(N,verbose,dumpAll,1e-5,outputPrec);
00237 if(!result) success = false;
00238
00239
00240 result = run1DFFTExample<double>(N,verbose,dumpAll,1e-13,outputPrec);
00241 if(!result) success = false;
00242
00243 #ifdef HAVE_TEUCHOS_GNU_MP
00244
00245
00246
00247
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 }