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_VerboseObject.hpp"
00031
00032 #ifndef SUN_CXX
00033
00034 #include "Thyra_DefaultSpmdVectorSpace.hpp"
00035 #include "Thyra_DefaultSpmdMultiVector.hpp"
00036 #include "Thyra_LinearOpScalarProd.hpp"
00037 #include "Thyra_EuclideanScalarProd.hpp"
00038 #include "Thyra_VectorBase.hpp"
00039 #include "Thyra_MultiVectorBase.hpp"
00040 #include "Thyra_VectorStdOps.hpp"
00041 #include "Thyra_MultiVectorStdOps.hpp"
00042 #include "Thyra_DefaultDiagonalLinearOp.hpp"
00043 #include "Thyra_DefaultSerialVectorSpaceConverter.hpp"
00044 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00045 #include "Thyra_TestingTools.hpp"
00046 #include "Thyra_LinearOpTester.hpp"
00047
00050 template <class Scalar>
00051 bool run_scalar_product_tests(
00052 const int n
00053 ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &tol
00054 ,const bool dumpAll
00055 ,Teuchos::FancyOStream *out_arg
00056 )
00057 {
00058
00059 using Thyra::relErr;
00060 using Thyra::testBoolExpr;
00061 typedef Teuchos::ScalarTraits<Scalar> ST;
00062 typedef typename ST::magnitudeType ScalarMag;
00063 typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00064 using Teuchos::RCP;
00065 using Teuchos::rcp;
00066 using Teuchos::rcp_implicit_cast;
00067 using Teuchos::OSTab;
00068
00069 RCP<Teuchos::FancyOStream>
00070 out = rcp(new Teuchos::FancyOStream(rcp(out_arg,false)));
00071
00072 if(out.get()) *out << "\n*** Entering run_scalar_product_tests<"<<ST::name()<<">(...) ...\n" << std::boolalpha;
00073
00074 bool success = true, result;
00075
00076 RCP<Thyra::DefaultSpmdVectorSpace<Scalar> >
00077 domain = Thyra::defaultSpmdVectorSpace<Scalar>(n/2),
00078 range = Thyra::defaultSpmdVectorSpace<Scalar>(n);
00079
00080 RCP<Thyra::DefaultSpmdMultiVector<Scalar> >
00081 op_coeff = rcp(new Thyra::DefaultSpmdMultiVector<Scalar>(range,domain)),
00082 op = rcp(new Thyra::DefaultSpmdMultiVector<Scalar>(range,domain));
00083
00084 RCP<Thyra::DefaultDiagonalLinearOp<Scalar> >
00085 domainScalarProdOp = rcp(
00086 new Thyra::DefaultDiagonalLinearOp<Scalar>(
00087 rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(domain)
00088 )
00089 ),
00090 rangeScalarProdOp = rcp(
00091 new Thyra::DefaultDiagonalLinearOp<Scalar>(
00092 rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(range)
00093 )
00094 );
00095
00096 Thyra::seed_randomize<Scalar>(0);
00097 Thyra::randomize( Scalar(Scalar(-1)*ST::one()), Scalar(Scalar(+1)*ST::one()), &*op_coeff );
00098 if(out.get() && dumpAll) *out << "\nop_coeff =\n" << *op_coeff;
00099 RCP<const Thyra::VectorSpaceConverterBase<ScalarMag,Scalar> >
00100 vecSpcConverterFromMag = rcp(new Thyra::DefaultSerialVectorSpaceConverter<ScalarMag,Scalar>());
00101 RCP<const Thyra::VectorSpaceBase<ScalarMag> >
00102 magDomain = vecSpcConverterFromMag->createVectorSpaceFrom(*rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(domain)),
00103 magRange = vecSpcConverterFromMag->createVectorSpaceFrom(*rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(range));
00104 RCP<Thyra::VectorBase<ScalarMag> >
00105 _domainScalarProdDiag = createMember(magDomain),
00106 _rangeScalarProdDiag = createMember(*magRange);
00107 Thyra::randomize( ScalarMag(ScalarMag(+1)*SMT::one()), ScalarMag(ScalarMag(+2)*SMT::one()), &*_domainScalarProdDiag );
00108 Thyra::randomize( ScalarMag(ScalarMag(+1)*SMT::one()), ScalarMag(ScalarMag(+2)*SMT::one()), &*_rangeScalarProdDiag );
00109 vecSpcConverterFromMag->convert( *_domainScalarProdDiag, &*domainScalarProdOp->getNonconstDiag() );
00110 vecSpcConverterFromMag->convert( *_rangeScalarProdDiag, &*rangeScalarProdOp->getNonconstDiag() );
00111
00112 RCP<const Thyra::EuclideanScalarProd<Scalar> >
00113 euclideanScalarProd = rcp(new Thyra::EuclideanScalarProd<Scalar>());
00114 RCP<const Thyra::LinearOpScalarProd<Scalar> >
00115 domainScalarProd = rcp(new Thyra::LinearOpScalarProd<Scalar>(domainScalarProdOp.create_weak())),
00116 rangeScalarProd = rcp(new Thyra::LinearOpScalarProd<Scalar>(rangeScalarProdOp.create_weak()));
00117
00118 const ScalarMag warning_tol = ScalarMag(1e-2)*tol, error_tol = tol;
00119 Thyra::LinearOpTester<Scalar> linearOpTester;
00120 linearOpTester.linear_properties_warning_tol(warning_tol);
00121 linearOpTester.linear_properties_error_tol(error_tol);
00122 linearOpTester.adjoint_warning_tol(warning_tol);
00123 linearOpTester.adjoint_error_tol(error_tol);
00124 linearOpTester.show_all_tests(true);
00125 linearOpTester.dump_all(dumpAll);
00126
00127 if(out.get()) *out << "\nTesting LinearOpBase with Euclidean domain and range scalar products ...\n";
00128 {
00129 OSTab tab(out);
00130 Thyra::assign( &*op, *op_coeff );
00131 if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00132 if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00133 result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),true,out.get());
00134 if(!result) success = false;
00135 result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),true,out.get());
00136 if(!result) success = false;
00137 result = linearOpTester.check(*op,out.get());
00138 if(!result) success = false;
00139 }
00140
00141 if(out.get()) *out << "\nTesting LinearOpBase with non-Euclidean domain and Euclidean range scalar products ...\n";
00142 {
00143 OSTab tab(out);
00144 range->setScalarProd(euclideanScalarProd);
00145 domain->setScalarProd(domainScalarProd);
00146 op->initialize(range,domain);
00147 Thyra::assign( &*op, *op_coeff );
00148 if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00149 if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00150 result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),false,out.get());
00151 if(!result) success = false;
00152 result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),true,out.get());
00153 if(!result) success = false;
00154 result = linearOpTester.check(*op,out.get());
00155 if(!result) success = false;
00156 }
00157
00158 if(out.get()) *out << "\nTesting LinearOpBase with Euclidean domain and non-Euclidean range scalar products ...\n";
00159 {
00160 OSTab tab(out);
00161 range->setScalarProd(rangeScalarProd);
00162 domain->setScalarProd(euclideanScalarProd);
00163 op->initialize(range,domain);
00164 Thyra::assign( &*op, *op_coeff );
00165 if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00166 if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00167 result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),true,out.get());
00168 if(!result) success = false;
00169 result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),false,out.get());
00170 if(!result) success = false;
00171 result = linearOpTester.check(*op,out.get());
00172 if(!result) success = false;
00173 }
00174
00175 if(out.get()) *out << "\nTesting LinearOpBase with non-Euclidean domain and non-Euclidean range scalar products ...\n";
00176 {
00177 OSTab tab(out);
00178 range->setScalarProd(rangeScalarProd);
00179 domain->setScalarProd(domainScalarProd);
00180 op->initialize(range,domain);
00181 Thyra::assign( &*op, *op_coeff );
00182 if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00183 if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00184 result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),false,out.get());
00185 if(!result) success = false;
00186 result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),false,out.get());
00187 if(!result) success = false;
00188 result = linearOpTester.check(*op,out.get());
00189 if(!result) success = false;
00190 }
00191
00192 if(out.get()) *out << "\n*** Leaving run_scalar_product_tests<"<<ST::name()<<">(...) ...\n";
00193
00194 return success;
00195
00196 }
00197
00198 #endif // SUN_CXX
00199
00200 int main( int argc, char* argv[] ) {
00201
00202 bool success = true;
00203 bool verbose = true;
00204
00205 using Teuchos::CommandLineProcessor;
00206
00207 Teuchos::RCP<Teuchos::FancyOStream>
00208 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00209
00210 try {
00211
00212
00213
00214
00215
00216 int n = 4;
00217 bool dumpAll = false;
00218
00219 CommandLineProcessor clp;
00220 clp.throwExceptions(false);
00221 clp.addOutputSetupOptions(true);
00222 clp.setOption( "verbose", "quiet", &verbose, "Set if output is printed or not." );
00223 clp.setOption( "n", &n, "Number of elements in each constituent vector." );
00224 clp.setOption( "dump-all", "no-dump-all", &dumpAll, "Determines if vectors are printed or not." );
00225 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00226 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00227
00228 #ifndef SUN_CXX
00229
00230
00231
00232
00233
00234 #ifdef HAVE_THYRA_TEUCHOS_BLASFLOAT
00235 if( !run_scalar_product_tests<float>(n,float(1e-5),dumpAll,verbose?&*out:NULL) ) success = false;
00236 #endif // HAVE_THYRA_TEUCHOS_BLASFLOAT
00237 if( !run_scalar_product_tests<double>(n,double(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
00238 #if defined(HAVE_THYRA_COMPLEX)
00239 #ifdef HAVE_THYRA_TEUCHOS_BLASFLOAT
00240 if( !run_scalar_product_tests<std::complex<float> >(n,float(1e-5),dumpAll,verbose?&*out:NULL) ) success = false;
00241 #endif // HAVE_THYRA_TEUCHOS_BLASFLOAT
00242 if( !run_scalar_product_tests<std::complex<double> >(n,double(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
00243 #endif
00244 #ifdef HAVE_TEUCHOS_GNU_MP
00245 if( !run_scalar_product_tests<mpf_class>(n,mpf_class(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
00246 #endif
00247
00248 #endif // ifndef SUN_CXX
00249
00250 }
00251 catch( const std::exception &excpt ) {
00252 if(verbose)
00253 std::cerr << "*** Caught a standard exception : " << excpt.what() << std::endl;
00254 success = false;
00255 }
00256 catch( ... ) {
00257 if(verbose)
00258 std::cerr << "*** Caught an unknown exception!\n";
00259 success = false;
00260 }
00261
00262 #ifndef SUN_CXX
00263
00264 if(verbose) {
00265 if(success)
00266 *out << "\nAll of the tests seem to have run successfully!\n";
00267 else
00268 *out << "\nOh no! at least one of the test failed!\n";
00269 }
00270
00271 return success ? 0 : 1;
00272
00273 #else // ifndef SUN_CXX
00274
00275 if (verbose) {
00276 std::cout << "\nError, the test was never run since SUN_CXX was defined and this test does not build on the Sun compiler!\n";
00277 }
00278
00279 return 1;
00280
00281 #endif //ifndef SUN_CXX
00282
00283 }