#include "Teuchos_CommandLineProcessor.hpp"
#ifndef __sun
#include "Thyra_DefaultSpmdVectorSpace.hpp"
#include "Thyra_DefaultSpmdMultiVector.hpp"
#include "Thyra_LinearOpScalarProd.hpp"
#include "Thyra_EuclideanScalarProd.hpp"
#include "Thyra_VectorBase.hpp"
#include "Thyra_MultiVectorBase.hpp"
#include "Thyra_VectorStdOps.hpp"
#include "Thyra_MultiVectorStdOps.hpp"
#include "Thyra_DefaultDiagonalLinearOp.hpp"
#include "Thyra_DefaultSerialVectorSpaceConverter.hpp"
#include "Thyra_DefaultScaledAdjointLinearOp.hpp"
#include "Thyra_TestingTools.hpp"
#include "Thyra_LinearOpTester.hpp"
template <class Scalar>
bool run_scalar_product_tests(
const int n
,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &tol
,const bool dumpAll
,Teuchos::FancyOStream *out_arg
)
{
using Thyra::relErr;
using Thyra::testBoolExpr;
typedef Teuchos::ScalarTraits<Scalar> ST;
typedef typename ST::magnitudeType ScalarMag;
typedef Teuchos::ScalarTraits<ScalarMag> SMT;
using Teuchos::RefCountPtr;
using Teuchos::rcp;
using Teuchos::rcp_implicit_cast;
using Teuchos::OSTab;
RefCountPtr<Teuchos::FancyOStream>
out = rcp(new Teuchos::FancyOStream(rcp(out_arg,false)));
if(out.get()) *out << "\n*** Entering run_scalar_product_tests<"<<ST::name()<<">(...) ...\n" << std::boolalpha;
bool success = true, result;
RefCountPtr<Thyra::DefaultSpmdVectorSpace<Scalar> >
domain = rcp(new Thyra::DefaultSpmdVectorSpace<Scalar>(n/2)),
range = rcp(new Thyra::DefaultSpmdVectorSpace<Scalar>(n));
RefCountPtr<Thyra::DefaultSpmdMultiVector<Scalar> >
op_coeff = rcp(new Thyra::DefaultSpmdMultiVector<Scalar>(range,domain)),
op = rcp(new Thyra::DefaultSpmdMultiVector<Scalar>(range,domain));
RefCountPtr<Thyra::DefaultDiagonalLinearOp<Scalar> >
domainScalarProdOp = rcp(
new Thyra::DefaultDiagonalLinearOp<Scalar>(
rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(domain)
)
),
rangeScalarProdOp = rcp(
new Thyra::DefaultDiagonalLinearOp<Scalar>(
rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(range)
)
);
Thyra::seed_randomize<Scalar>(0);
Thyra::randomize( Scalar(Scalar(-1)*ST::one()), Scalar(Scalar(+1)*ST::one()), &*op_coeff );
if(out.get() && dumpAll) *out << "\nop_coeff =\n" << *op_coeff;
RefCountPtr<const Thyra::VectorSpaceConverterBase<ScalarMag,Scalar> >
vecSpcConverterFromMag = rcp(new Thyra::DefaultSerialVectorSpaceConverter<ScalarMag,Scalar>());
RefCountPtr<const Thyra::VectorSpaceBase<ScalarMag> >
magDomain = vecSpcConverterFromMag->createVectorSpaceFrom(*rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(domain)),
magRange = vecSpcConverterFromMag->createVectorSpaceFrom(*rcp_implicit_cast<const Thyra::VectorSpaceBase<Scalar> >(range));
RefCountPtr<Thyra::VectorBase<ScalarMag> >
_domainScalarProdDiag = createMember(magDomain),
_rangeScalarProdDiag = createMember(*magRange);
Thyra::randomize( ScalarMag(ScalarMag(+1)*SMT::one()), ScalarMag(ScalarMag(+2)*SMT::one()), &*_domainScalarProdDiag );
Thyra::randomize( ScalarMag(ScalarMag(+1)*SMT::one()), ScalarMag(ScalarMag(+2)*SMT::one()), &*_rangeScalarProdDiag );
vecSpcConverterFromMag->convert( *_domainScalarProdDiag, &*domainScalarProdOp->getNonconstDiag() );
vecSpcConverterFromMag->convert( *_rangeScalarProdDiag, &*rangeScalarProdOp->getNonconstDiag() );
RefCountPtr<const Thyra::EuclideanScalarProd<Scalar> >
euclideanScalarProd = rcp(new Thyra::EuclideanScalarProd<Scalar>());
RefCountPtr<const Thyra::LinearOpScalarProd<Scalar> >
domainScalarProd = rcp(new Thyra::LinearOpScalarProd<Scalar>(domainScalarProdOp)),
rangeScalarProd = rcp(new Thyra::LinearOpScalarProd<Scalar>(rangeScalarProdOp));
const ScalarMag warning_tol = ScalarMag(1e-2)*tol, error_tol = tol;
Thyra::LinearOpTester<Scalar> linearOpTester;
linearOpTester.linear_properties_warning_tol(warning_tol);
linearOpTester.linear_properties_error_tol(error_tol);
linearOpTester.adjoint_warning_tol(warning_tol);
linearOpTester.adjoint_error_tol(error_tol);
linearOpTester.show_all_tests(true);
if(out.get()) *out << "\nTesting LinearOpBase with Euclidean domain and range scalar products ...\n";
if(1) {
OSTab tab(out);
Thyra::assign( &*op, *op_coeff );
if(out.get() && dumpAll) *out << "\nop =\n" << *op;
if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),true,out.get());
if(!result) success = false;
result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),true,out.get());
if(!result) success = false;
result = linearOpTester.check(*op,out.get());
if(!result) success = false;
}
if(out.get()) *out << "\nTesting LinearOpBase with non-Euclidean domain and Euclidean range scalar products ...\n";
if(1) {
OSTab tab(out);
range->setScalarProd(euclideanScalarProd);
domain->setScalarProd(domainScalarProd);
op->initialize(range,domain);
Thyra::assign( &*op, *op_coeff );
if(out.get() && dumpAll) *out << "\nop =\n" << *op;
if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),false,out.get());
if(!result) success = false;
result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),true,out.get());
if(!result) success = false;
result = linearOpTester.check(*op,out.get());
if(!result) success = false;
}
if(out.get()) *out << "\nTesting LinearOpBase with Euclidean domain and non-Euclidean range scalar products ...\n";
if(1) {
OSTab tab(out);
range->setScalarProd(rangeScalarProd);
domain->setScalarProd(euclideanScalarProd);
op->initialize(range,domain);
Thyra::assign( &*op, *op_coeff );
if(out.get() && dumpAll) *out << "\nop =\n" << *op;
if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),true,out.get());
if(!result) success = false;
result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),false,out.get());
if(!result) success = false;
result = linearOpTester.check(*op,out.get());
if(!result) success = false;
}
if(out.get()) *out << "\nTesting LinearOpBase with non-Euclidean domain and non-Euclidean range scalar products ...\n";
if(1) {
OSTab tab(out);
range->setScalarProd(rangeScalarProd);
domain->setScalarProd(domainScalarProd);
op->initialize(range,domain);
Thyra::assign( &*op, *op_coeff );
if(out.get() && dumpAll) *out << "\nop =\n" << *op;
if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),false,out.get());
if(!result) success = false;
result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),false,out.get());
if(!result) success = false;
result = linearOpTester.check(*op,out.get());
if(!result) success = false;
}
if(out.get()) *out << "\n*** Leaving run_scalar_product_tests<"<<ST::name()<<">(...) ...\n";
return success;
}
#endif // __sun
int main( int argc, char* argv[] ) {
bool success = true;
bool verbose = true;
using Teuchos::CommandLineProcessor;
Teuchos::RefCountPtr<Teuchos::FancyOStream>
out = Teuchos::VerboseObjectBase::getDefaultOStream();
try {
int n = 4;
bool dumpAll = false;
CommandLineProcessor clp;
clp.throwExceptions(false);
clp.addOutputSetupOptions(true);
clp.setOption( "verbose", "quiet", &verbose, "Set if output is printed or not." );
clp.setOption( "n", &n, "Number of elements in each constituent vector." );
clp.setOption( "dump-all", "no-dump-all", &dumpAll, "Determines if vectors are printed or not." );
CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
#ifndef __sun
if( !run_scalar_product_tests<float>(n,float(1e-5),dumpAll,verbose?&*out:NULL) ) success = false;
if( !run_scalar_product_tests<double>(n,double(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
#if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX)
if( !run_scalar_product_tests<std::complex<float> >(n,float(1e-5),dumpAll,verbose?&*out:NULL) ) success = false;
if( !run_scalar_product_tests<std::complex<double> >(n,double(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
#endif
#ifdef HAVE_TEUCHOS_GNU_MP
if( !run_scalar_product_tests<mpf_class>(n,mpf_class(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
#endif
#endif // ifndef __sun
}
catch( const std::exception &excpt ) {
if(verbose)
std::cerr << "*** Caught a standard exception : " << excpt.what() << std::endl;
success = false;
}
catch( ... ) {
if(verbose)
std::cerr << "*** Caught an unknown exception!\n";
success = false;
}
#ifndef __sun
if(verbose) {
if(success)
*out << "\nAll of the tests seem to have run successfully!\n";
else
*out << "\nOh no! at least one of the test failed!\n";
}
return success ? 0 : 1;
#else // ifndef __sun
if (verbose) {
std::c*out << "\nError, the test was never run since __sun was defined and this test does not build on the Sun compiler!\n";
}
return 1;
#endif //ifndef __sun
}