test_scalar_product.cpp

Click here for a more detailed discussion of this example/test program.

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_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 = rcp(new Thyra::DefaultSpmdVectorSpace<Scalar>(n/2)),
00078     range  = rcp(new 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)),
00116     rangeScalarProd = rcp(new Thyra::LinearOpScalarProd<Scalar>(rangeScalarProdOp));
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 
00126   if(out.get()) *out << "\nTesting LinearOpBase with Euclidean domain and range scalar products ...\n";
00127   {
00128     OSTab tab(out);
00129     Thyra::assign( &*op, *op_coeff );
00130     if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00131     if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00132     result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),true,out.get());
00133     if(!result) success = false;
00134     result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),true,out.get());
00135     if(!result) success = false;
00136     result = linearOpTester.check(*op,out.get());
00137     if(!result) success = false;
00138   }
00139  
00140   if(out.get()) *out << "\nTesting LinearOpBase with non-Euclidean domain and Euclidean range scalar products ...\n";
00141   {
00142     OSTab tab(out);
00143     range->setScalarProd(euclideanScalarProd);
00144     domain->setScalarProd(domainScalarProd);
00145     op->initialize(range,domain);
00146     Thyra::assign( &*op, *op_coeff );
00147     if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00148     if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00149     result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),false,out.get());
00150     if(!result) success = false;
00151     result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),true,out.get());
00152     if(!result) success = false;
00153     result = linearOpTester.check(*op,out.get());
00154     if(!result) success = false;
00155   }
00156     
00157   if(out.get()) *out << "\nTesting LinearOpBase with Euclidean domain and non-Euclidean range scalar products ...\n";
00158   {
00159     OSTab tab(out);
00160     range->setScalarProd(rangeScalarProd);
00161     domain->setScalarProd(euclideanScalarProd);
00162     op->initialize(range,domain);
00163     Thyra::assign( &*op, *op_coeff );
00164     if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00165     if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00166     result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),true,out.get());
00167     if(!result) success = false;
00168     result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),false,out.get());
00169     if(!result) success = false;
00170     result = linearOpTester.check(*op,out.get());
00171     if(!result) success = false;
00172   }
00173     
00174   if(out.get()) *out << "\nTesting LinearOpBase with non-Euclidean domain and non-Euclidean range scalar products ...\n";
00175   {
00176     OSTab tab(out);
00177     range->setScalarProd(rangeScalarProd);
00178     domain->setScalarProd(domainScalarProd);
00179     op->initialize(range,domain);
00180     Thyra::assign( &*op, *op_coeff );
00181     if(out.get() && dumpAll) *out << "\nop =\n" << *op;
00182     if(out.get() && dumpAll) *out << "\nop' =\n" << *Thyra::adjoint(Teuchos::rcp_implicit_cast<const Thyra::LinearOpBase<Scalar> >(op));
00183     result = testBoolExpr("op->domain()->isEuclidean()",op->domain()->isEuclidean(),false,out.get());
00184     if(!result) success = false;
00185     result = testBoolExpr("op->range()->isEuclidean()",op->range()->isEuclidean(),false,out.get());
00186     if(!result) success = false;
00187     result = linearOpTester.check(*op,out.get());
00188     if(!result) success = false;
00189   }
00190     
00191   if(out.get()) *out << "\n*** Leaving run_scalar_product_tests<"<<ST::name()<<">(...) ...\n";
00192 
00193   return success;
00194 
00195 } // end run_scalar_product_tests() [Doxygen looks for this!]
00196 
00197 #endif // SUN_CXX
00198 
00199 int main( int argc, char* argv[] ) {
00200 
00201   bool success = true;
00202   bool verbose = true;
00203 
00204   using Teuchos::CommandLineProcessor;
00205 
00206   Teuchos::RCP<Teuchos::FancyOStream>
00207     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00208 
00209   try {
00210 
00211     //
00212     // Read options from command-line
00213     //
00214 
00215     int n         = 4;
00216     bool dumpAll  = false;
00217 
00218     CommandLineProcessor  clp;
00219     clp.throwExceptions(false);
00220     clp.addOutputSetupOptions(true);
00221     clp.setOption( "verbose", "quiet", &verbose, "Set if output is printed or not." );
00222     clp.setOption( "n", &n, "Number of elements in each constituent vector." );
00223     clp.setOption( "dump-all", "no-dump-all", &dumpAll, "Determines if vectors are printed or not." );
00224     CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00225     if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00226 
00227 #ifndef SUN_CXX
00228 
00229     //
00230     // Run the tests
00231     //
00232 
00233 #ifdef HAVE_THYRA_TEUCHOS_BLASFLOAT
00234     if( !run_scalar_product_tests<float>(n,float(1e-5),dumpAll,verbose?&*out:NULL) ) success = false;
00235 #endif // HAVE_THYRA_TEUCHOS_BLASFLOAT
00236     if( !run_scalar_product_tests<double>(n,double(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
00237 #if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX)
00238 #ifdef HAVE_THYRA_TEUCHOS_BLASFLOAT
00239     if( !run_scalar_product_tests<std::complex<float> >(n,float(1e-5),dumpAll,verbose?&*out:NULL) ) success = false;
00240 #endif // HAVE_THYRA_TEUCHOS_BLASFLOAT
00241     if( !run_scalar_product_tests<std::complex<double> >(n,double(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
00242 #endif
00243 #ifdef HAVE_TEUCHOS_GNU_MP
00244     if( !run_scalar_product_tests<mpf_class>(n,mpf_class(1e-14),dumpAll,verbose?&*out:NULL) ) success = false;
00245 #endif
00246 
00247 #endif // ifndef SUN_CXX
00248 
00249   } // end try
00250   catch( const std::exception &excpt ) {
00251     if(verbose)
00252       std::cerr << "*** Caught a standard exception : " << excpt.what() << std::endl;
00253     success = false;
00254   }
00255   catch( ... ) {
00256     if(verbose)
00257       std::cerr << "*** Caught an unknown exception!\n";
00258     success = false;
00259   }
00260 
00261 #ifndef SUN_CXX
00262 
00263   if(verbose) {
00264     if(success)
00265       *out << "\nAll of the tests seem to have run successfully!\n";
00266     else
00267       *out << "\nOh no! at least one of the test failed!\n";  
00268   }
00269   
00270   return success ? 0 : 1;
00271 
00272 #else // ifndef SUN_CXX
00273 
00274   if (verbose) {
00275     std::cout << "\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 //ifndef SUN_CXX
00281 
00282 } // end main() [Doxygen looks for this!]

Generated on Tue Oct 20 12:46:58 2009 for Thyra Operator/Vector Support by doxygen 1.4.7