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 = 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 } // end run_scalar_product_tests() [Doxygen looks for this!]
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     // Read options from command-line
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     // Run the tests
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   } // end try
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 } // end main() [Doxygen looks for this!]

Generated on Wed Feb 10 16:28:08 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7