Thyra_TestingTools.hpp

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 
00037 // Utilities
00038 
00039 template <bool hasMachineParameters, class Scalar>
00040 class relErrSmallNumber {
00041 public:
00042   static Scalar smallNumber()
00043     {
00044       return Teuchos::ScalarTraits<Scalar>::ThisShouldNotCompile();
00045     }
00046 };
00047 
00048 template <class Scalar>
00049 class relErrSmallNumber<false,Scalar> {
00050 public:
00051   static Scalar smallNumber()
00052     {
00053       return Scalar(1e-8);
00054     }
00055 };
00056 
00057 template <class Scalar>
00058 class relErrSmallNumber<true,Scalar> {
00059 public:
00060   static Scalar smallNumber()
00061     {
00062       return Teuchos::ScalarTraits<Scalar>::eps();
00063     }
00064 };
00065 
00066 //
00067 
00068 template <class Scalar>
00069 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00070 Thyra::relErr( const Scalar &s1, const Scalar &s2 )
00071 {
00072   return
00073     Teuchos::ScalarTraits<Scalar>::magnitude( s1 - s2 )
00074     / (
00075       Teuchos::ScalarTraits<Scalar>::magnitude(
00076         relErrSmallNumber<Teuchos::ScalarTraits<Scalar>::hasMachineParameters,Scalar>::smallNumber()
00077         )
00078       + std::max( Teuchos::ScalarTraits<Scalar>::magnitude(s1), Teuchos::ScalarTraits<Scalar>::magnitude(s1) )
00079       );
00080 }
00081 
00082 template<class Scalar>
00083 bool Thyra::testRelErr(
00084   const std::string                                             &v1_name
00085   ,const Scalar                                                 &v1
00086   ,const std::string                                            &v2_name
00087   ,const Scalar                                                 &v2
00088   ,const std::string                                            &maxRelErr_error_name
00089   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &maxRelErr_error
00090   ,const std::string                                            &maxRelErr_warning_name
00091   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &maxRelErr_warning
00092   ,std::ostream                                                 *out
00093   ,const std::string                                            &li
00094   )
00095 {
00096   typedef Teuchos::ScalarTraits<Scalar> ST;
00097   typedef typename ST::magnitudeType ScalarMag;
00098   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00099   const ScalarMag rel_err = relErr( v1, v2 );
00100   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) && rel_err <= maxRelErr_error );
00101   if(out) {
00102     *out
00103       << std::endl
00104       << li << "Check: rel_err(" << v1_name << "," << v2_name << ")\n"
00105       << li << "       = rel_err(" << v1 << "," << v2 << ") "
00106       << "= " << rel_err << std::endl
00107       << li << "         <= " << maxRelErr_error_name << " = " << maxRelErr_error << " : " << passfail(success) << std::endl;
00108     if( success && rel_err >= maxRelErr_warning ) {
00109       *out
00110         << li << "Warning! rel_err(" << v1_name << "," << v2_name << ")\n"
00111         << li << "       = rel_err(" << v1 << "," << v2 << ") " << "= " << rel_err << std::endl
00112         << li << "         >= " << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00113     }
00114   }
00115   return success;
00116 }
00117 
00118 template<class Scalar1, class Scalar2, class ScalarMag>
00119 bool Thyra::testRelErrors(
00120   const int                                                     num_scalars
00121   ,const std::string                                            &v1_name
00122   ,const Scalar1                                                v1[]
00123   ,const std::string                                            &v2_name
00124   ,const Scalar2                                                v2[]
00125   ,const std::string                                            &maxRelErr_error_name
00126   ,const ScalarMag                                              &maxRelErr_error
00127   ,const std::string                                            &maxRelErr_warning_name
00128   ,const ScalarMag                                              &maxRelErr_warning
00129   ,std::ostream                                                 *out
00130   ,const std::string                                            &li
00131   )
00132 {
00133   using std::setw;
00134   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00135   typedef typename Teuchos::PromotionTraits<Scalar1,Scalar2>::promote Scalar;
00136   if(num_scalars==1) {
00137     return testRelErr<Scalar>(
00138       v1_name,v1[0],v2_name,v2[0]
00139       ,maxRelErr_error_name,maxRelErr_error
00140       ,maxRelErr_warning_name,maxRelErr_warning
00141       ,out,li
00142       );
00143   }
00144   bool success = true;
00145   if(out) *out
00146     << std::endl
00147     << li << "Check: rel_err(" << v1_name << "," << v2_name << ") <= " << maxRelErr_error_name << " ?\n";
00148   for( int i = 0; i < num_scalars; ++i ) {
00149     const ScalarMag rel_err = relErr<Scalar>( v1[i], v2[i] );
00150     const bool result = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) && rel_err <= maxRelErr_error );
00151     if(!result) success = false;
00152     if(out) {
00153       *out
00154         << li << "  "<<setw(2)<<i<<": rel_err("<<v1[i]<<","<<v2[i]<<") "<<"= "<<rel_err
00155         << " <= " << maxRelErr_error << " : " << passfail(result) << std::endl;
00156       if( result && rel_err >= maxRelErr_warning ) {
00157         *out
00158           << li << "      Warning! rel_err(...) >= " << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00159       }
00160     }
00161   }
00162   return success;
00163 }
00164 
00165 template<class Scalar>
00166 bool Thyra::testMaxErr(
00167   const std::string                                             &error_name
00168   ,const Scalar                                                 &error
00169   ,const std::string                                            &max_error_name
00170   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_error
00171   ,const std::string                                            &max_warning_name
00172   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_warning
00173   ,std::ostream                                                 *out
00174   ,const std::string                                            &li
00175   )
00176 {
00177   typedef Teuchos::ScalarTraits<Scalar> ST;
00178   typedef typename ST::magnitudeType ScalarMag;
00179   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00180   const ScalarMag error_mag = ST::magnitude(error);
00181   const bool success = ( !SMT::isnaninf(error_mag) && !SMT::isnaninf(max_error) && error_mag <= max_error );
00182   if(out) {
00183     *out
00184       << std::endl
00185       << li << "Check: |" << error_name << "| = " << error_mag
00186       << " <= " << max_error_name << " = " << max_error << " : " << passfail(success) << std::endl;
00187     if( success && error_mag >= max_warning ) {
00188       *out
00189         << li << "Warning! " << error_name << " = " << error_mag
00190         << " >= " << max_warning_name << " = " << max_warning << "!\n";
00191     }
00192   }
00193   return success;
00194 }
00195 
00196 template<class Scalar>
00197 bool Thyra::testMaxErrors(
00198   const int                                                     num_scalars
00199   ,const std::string                                            &error_name
00200   ,const Scalar                                                 error[]
00201   ,const std::string                                            &max_error_name
00202   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_error
00203   ,const std::string                                            &max_warning_name
00204   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_warning
00205   ,std::ostream                                                 *out
00206   ,const std::string                                            &li
00207   )
00208 {
00209   using std::setw;
00210   typedef Teuchos::ScalarTraits<Scalar> ST;
00211   typedef typename ST::magnitudeType ScalarMag;
00212   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00213   if(num_scalars==1) {
00214     return testMaxErr(
00215       error_name,error[0]
00216       ,max_error_name,max_error
00217       ,max_warning_name,max_warning
00218       ,out,li
00219       );
00220   }
00221   bool success = true;
00222   if(out) *out
00223     << std::endl
00224     << li << "Check: |"<<error_name<<"| <= "<<max_error_name<<" ?\n";
00225   for( int i = 0; i < num_scalars; ++i ) {
00226     const ScalarMag error_mag = ST::magnitude(error[i]);
00227     const bool result = ( !SMT::isnaninf(error_mag) && !SMT::isnaninf(max_error) && error_mag <= max_error );
00228     if(!result) success = false;
00229     if(out) {
00230       *out
00231         << li << "  "<<setw(2)<<i<<": |"<<error[i]<<"| = "<<error_mag<<" <= "<<max_error<<" : "<<passfail(success)<<"\n";
00232       if( result && error_mag >= max_warning ) {
00233         *out
00234           << li << "      Warning! |...| >= "<<max_warning_name<<" = "<<max_warning<<"!\n";
00235       }
00236     }
00237   }
00238   return success;
00239 }
00240 
00241 template<class Scalar>
00242 std::ostream& Thyra::operator<<( std::ostream& o, const VectorBase<Scalar>& v )
00243 {
00244   return o << describe(v,Teuchos::VERB_EXTREME);
00245 }
00246 
00247 template<class Scalar>
00248 std::ostream& Thyra::operator<<( std::ostream& o, const LinearOpBase<Scalar>& M )
00249 {
00250   return o << describe(M,Teuchos::VERB_EXTREME);
00251 }
00252 
00253 #endif // THYRA_TESTING_TOOLS_HPP

Generated on Thu Sep 18 12:32:32 2008 for Thyra Operator/Vector Support by doxygen 1.3.9.1