Thyra_TestingTools.hpp

Go to the documentation of this file.
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 #ifndef THYRA_TESTING_TOOLS_HPP
00030 #define THYRA_TESTING_TOOLS_HPP
00031 
00032 #include "Thyra_TestingToolsDecl.hpp"
00033 #include "Thyra_VectorBase.hpp"
00034 #include "Thyra_VectorStdOps.hpp"
00035 #include "Thyra_LinearOpBase.hpp"
00036 #include "Thyra_AssertOp.hpp"
00037 #include "Teuchos_as.hpp"
00038 
00039 // Utilities
00040 
00041 template <bool hasMachineParameters, class Scalar>
00042 class relErrSmallNumber {
00043 public:
00044   static Scalar smallNumber()
00045     {
00046       return Teuchos::ScalarTraits<Scalar>::ThisShouldNotCompile();
00047     }
00048 };
00049 
00050 template <class Scalar>
00051 class relErrSmallNumber<false,Scalar> {
00052 public:
00053   static Scalar smallNumber()
00054     {
00055       return Scalar(1e-8);
00056     }
00057 };
00058 
00059 
00060 template <class Scalar>
00061 class relErrSmallNumber<true,Scalar> {
00062 public:
00063   static Scalar smallNumber()
00064     {
00065       return Teuchos::ScalarTraits<Scalar>::eps();
00066     }
00067 };
00068 
00069 
00070 template <class Scalar>
00071 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00072 Thyra::relErr( const Scalar &s1, const Scalar &s2 )
00073 {
00074   typedef Teuchos::ScalarTraits<Scalar> ST;
00075   return
00076     ST::magnitude( s1 - s2 )
00077     / (
00078       ST::magnitude(
00079         relErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00080         )
00081       + std::max( ST::magnitude(s1), ST::magnitude(s1) )
00082       );
00083 }
00084 
00085 
00086 template <class Scalar>
00087 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00088 Thyra::relVectorErr( const VectorBase<Scalar> &v1, const VectorBase<Scalar> &v2 )
00089 {
00090   typedef Teuchos::ScalarTraits<Scalar> ST;
00091   typedef typename ST::magnitudeType ScalarMag;
00092 #ifdef TEUCHOS_DEBUG
00093   THYRA_ASSERT_VEC_SPACES( "relErr(v1,v2)", *v1.space(), *v2.space() );
00094 #endif
00095   Teuchos::RCP<VectorBase<Scalar> >
00096     diff = createMember(v1.space());
00097   V_VmV( &*diff, v1, v2 );
00098   const ScalarMag
00099     nrm_v1 = norm(v1),
00100     nrm_v2 = norm(v2),
00101     nrm_diff = norm(*diff);
00102   return
00103     ( nrm_diff
00104       / (
00105         ST::magnitude(
00106           relErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00107           )
00108         + std::max( nrm_v1, nrm_v2 )
00109         )
00110       );
00111 }
00112 
00113 
00114 template<class Scalar>
00115 bool Thyra::testRelErr(
00116   const std::string                                             &v1_name
00117   ,const Scalar                                                 &v1
00118   ,const std::string                                            &v2_name
00119   ,const Scalar                                                 &v2
00120   ,const std::string                                            &maxRelErr_error_name
00121   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &maxRelErr_error
00122   ,const std::string                                            &maxRelErr_warning_name
00123   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &maxRelErr_warning
00124   ,std::ostream                                                 *out
00125   ,const std::string                                            &li
00126   )
00127 {
00128   typedef Teuchos::ScalarTraits<Scalar> ST;
00129   typedef typename ST::magnitudeType ScalarMag;
00130   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00131   const ScalarMag rel_err = relErr( v1, v2 );
00132   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) && rel_err <= maxRelErr_error );
00133   if(out) {
00134     *out
00135       << std::endl
00136       << li << "Check: rel_err(" << v1_name << "," << v2_name << ")\n"
00137       << li << "       = rel_err(" << v1 << "," << v2 << ") "
00138       << "= " << rel_err << std::endl
00139       << li << "         <= " << maxRelErr_error_name << " = " << maxRelErr_error << " : " << passfail(success) << std::endl;
00140     if( success && rel_err >= maxRelErr_warning ) {
00141       *out
00142         << li << "Warning! rel_err(" << v1_name << "," << v2_name << ")\n"
00143         << li << "       = rel_err(" << v1 << "," << v2 << ") " << "= " << rel_err << std::endl
00144         << li << "         >= " << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00145     }
00146   }
00147   return success;
00148 }
00149 
00150 template<class Scalar1, class Scalar2, class ScalarMag>
00151 bool Thyra::testRelErrors(
00152   const int                                                     num_scalars
00153   ,const std::string                                            &v1_name
00154   ,const Scalar1                                                v1[]
00155   ,const std::string                                            &v2_name
00156   ,const Scalar2                                                v2[]
00157   ,const std::string                                            &maxRelErr_error_name
00158   ,const ScalarMag                                              &maxRelErr_error
00159   ,const std::string                                            &maxRelErr_warning_name
00160   ,const ScalarMag                                              &maxRelErr_warning
00161   ,std::ostream                                                 *out
00162   ,const std::string                                            &li
00163   )
00164 {
00165   using std::setw;
00166   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00167   typedef typename Teuchos::PromotionTraits<Scalar1,Scalar2>::promote Scalar;
00168   if(num_scalars==1) {
00169     return testRelErr<Scalar>(
00170       v1_name,v1[0],v2_name,v2[0]
00171       ,maxRelErr_error_name,maxRelErr_error
00172       ,maxRelErr_warning_name,maxRelErr_warning
00173       ,out,li
00174       );
00175   }
00176   bool success = true;
00177   if(out) *out
00178     << std::endl
00179     << li << "Check: rel_err(" << v1_name << "," << v2_name << ") <= " << maxRelErr_error_name << " ?\n";
00180   for( int i = 0; i < num_scalars; ++i ) {
00181     const ScalarMag rel_err = relErr<Scalar>( v1[i], v2[i] );
00182     const bool result = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) && rel_err <= maxRelErr_error );
00183     if(!result) success = false;
00184     if(out) {
00185       *out
00186         << li << "  "<<setw(2)<<i<<": rel_err("<<v1[i]<<","<<v2[i]<<") "<<"= "<<rel_err
00187         << " <= " << maxRelErr_error << " : " << passfail(result) << std::endl;
00188       if( result && rel_err >= maxRelErr_warning ) {
00189         *out
00190           << li << "      Warning! rel_err(...) >= " << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00191       }
00192     }
00193   }
00194   return success;
00195 }
00196 
00197 
00198 template<class Scalar>
00199 bool Thyra::testRelNormDiffErr(
00200   const std::string &v1_name,
00201   const VectorBase<Scalar> &v1,
00202   const std::string &v2_name,
00203   const VectorBase<Scalar> &v2,
00204   const std::string &maxRelErr_error_name,
00205   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00206   const std::string &maxRelErr_warning_name,
00207   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00208   std::ostream *out,
00209   const Teuchos::EVerbosityLevel verbLevel,
00210   const std::string &li
00211   )
00212 {
00213   using std::endl;
00214   using Teuchos::as;
00215   typedef Teuchos::ScalarTraits<Scalar> ST;
00216   typedef typename ST::magnitudeType ScalarMag;
00217   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00218   const ScalarMag
00219     nrm_v1 = norm(v1),
00220     nrm_v2 = norm(v2);
00221   const ScalarMag rel_err = relVectorErr(v1,v2);
00222   const bool success =
00223     (
00224       !SMT::isnaninf(rel_err)
00225       && !SMT::isnaninf(maxRelErr_error)
00226       && rel_err <= maxRelErr_error
00227       );
00228   if(out) {
00229     *out
00230       << endl
00231       << li << "Testing relative error between vectors " << v1_name << " and " << v2_name << ":\n"
00232       << li << "  ||"<<v1_name<<"|| = " << nrm_v1 << endl
00233       << li << "  ||"<<v2_name<<"|| = " << nrm_v2 << endl;
00234     if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00235       *out
00236         << li << "  " << v1_name << " = " << describe(v1,verbLevel)
00237         << li << "  " << v2_name << " = " << describe(v2,verbLevel);
00238       Teuchos::RCP<VectorBase<Scalar> >
00239         diff = createMember(v1.space());
00240       V_VmV( &*diff, v1, v2 );
00241       *out
00242         << li << "  " << v1_name << " - " << v2_name << " = " << describe(*diff,verbLevel);
00243     }
00244     *out
00245       << li << "  Check: rel_err(" << v1_name << "," << v2_name << ") = "
00246       << rel_err << " <= " << maxRelErr_error_name << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00247     if( success && rel_err >= maxRelErr_warning ) {
00248       *out
00249         << li << "  Warning! rel_err(" << v1_name << "," << v2_name << " >= "
00250         << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00251     }
00252   }
00253   return success;
00254 }
00255 
00256 
00257 template<class Scalar>
00258 bool Thyra::testMaxErr(
00259   const std::string                                             &error_name
00260   ,const Scalar                                                 &error
00261   ,const std::string                                            &max_error_name
00262   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_error
00263   ,const std::string                                            &max_warning_name
00264   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_warning
00265   ,std::ostream                                                 *out
00266   ,const std::string                                            &li
00267   )
00268 {
00269   typedef Teuchos::ScalarTraits<Scalar> ST;
00270   typedef typename ST::magnitudeType ScalarMag;
00271   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00272   const ScalarMag error_mag = ST::magnitude(error);
00273   const bool success = ( !SMT::isnaninf(error_mag) && !SMT::isnaninf(max_error) && error_mag <= max_error );
00274   if(out) {
00275     *out
00276       << std::endl
00277       << li << "Check: |" << error_name << "| = " << error_mag
00278       << " <= " << max_error_name << " = " << max_error << " : " << passfail(success) << std::endl;
00279     if( success && error_mag >= max_warning ) {
00280       *out
00281         << li << "Warning! " << error_name << " = " << error_mag
00282         << " >= " << max_warning_name << " = " << max_warning << "!\n";
00283     }
00284   }
00285   return success;
00286 }
00287 
00288 template<class Scalar>
00289 bool Thyra::testMaxErrors(
00290   const int                                                     num_scalars
00291   ,const std::string                                            &error_name
00292   ,const Scalar                                                 error[]
00293   ,const std::string                                            &max_error_name
00294   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_error
00295   ,const std::string                                            &max_warning_name
00296   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_warning
00297   ,std::ostream                                                 *out
00298   ,const std::string                                            &li
00299   )
00300 {
00301   using std::setw;
00302   typedef Teuchos::ScalarTraits<Scalar> ST;
00303   typedef typename ST::magnitudeType ScalarMag;
00304   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00305   if(num_scalars==1) {
00306     return testMaxErr(
00307       error_name,error[0]
00308       ,max_error_name,max_error
00309       ,max_warning_name,max_warning
00310       ,out,li
00311       );
00312   }
00313   bool success = true;
00314   if(out) *out
00315     << std::endl
00316     << li << "Check: |"<<error_name<<"| <= "<<max_error_name<<" ?\n";
00317   for( int i = 0; i < num_scalars; ++i ) {
00318     const ScalarMag error_mag = ST::magnitude(error[i]);
00319     const bool result = ( !SMT::isnaninf(error_mag) && !SMT::isnaninf(max_error) && error_mag <= max_error );
00320     if(!result) success = false;
00321     if(out) {
00322       *out
00323         << li << "  "<<setw(2)<<i<<": |"<<error[i]<<"| = "<<error_mag<<" <= "<<max_error<<" : "<<passfail(success)<<"\n";
00324       if( result && error_mag >= max_warning ) {
00325         *out
00326           << li << "      Warning! |...| >= "<<max_warning_name<<" = "<<max_warning<<"!\n";
00327       }
00328     }
00329   }
00330   return success;
00331 }
00332 
00333 template<class Scalar>
00334 std::ostream& Thyra::operator<<( std::ostream& o, const VectorBase<Scalar>& v )
00335 {
00336   return o << Teuchos::describe(v,Teuchos::VERB_EXTREME);
00337 }
00338 
00339 template<class Scalar>
00340 std::ostream& Thyra::operator<<( std::ostream& o, const LinearOpBase<Scalar>& M )
00341 {
00342   return o << Teuchos::describe(M,Teuchos::VERB_EXTREME);
00343 }
00344 
00345 #endif // THYRA_TESTING_TOOLS_HPP

Generated on Tue Oct 20 12:47:27 2009 for Thyra Package Browser (Single Doxygen Collection) by doxygen 1.4.7