Thyra Version of the Day
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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef THYRA_TESTING_TOOLS_HPP
00043 #define THYRA_TESTING_TOOLS_HPP
00044 
00045 #include "Thyra_TestingToolsDecl.hpp"
00046 #include "Thyra_VectorBase.hpp"
00047 #include "Thyra_VectorStdOps.hpp"
00048 #include "Thyra_LinearOpBase.hpp"
00049 #include "Thyra_AssertOp.hpp"
00050 #include "Teuchos_as.hpp"
00051 
00052 
00053 template <class Scalar>
00054 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00055 Thyra::relVectorErr( const VectorBase<Scalar> &v1, const VectorBase<Scalar> &v2 )
00056 {
00057   typedef Teuchos::ScalarTraits<Scalar> ST;
00058   typedef typename ST::magnitudeType ScalarMag;
00059 #ifdef TEUCHOS_DEBUG
00060   THYRA_ASSERT_VEC_SPACES( "relErr(v1,v2)", *v1.space(), *v2.space() );
00061 #endif
00062   RCP<VectorBase<Scalar> >
00063     diff = createMember(v1.space());
00064   V_VmV( diff.ptr(), v1, v2 );
00065   const ScalarMag
00066     nrm_v1 = norm(v1),
00067     nrm_v2 = norm(v2),
00068     nrm_diff = norm(*diff);
00069   return
00070     ( nrm_diff
00071       / (
00072         ST::magnitude(
00073           Teuchos::RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00074           )
00075         + std::max( nrm_v1, nrm_v2 )
00076         )
00077       );
00078 }
00079 
00080 
00081 template<class Scalar1, class Scalar2, class ScalarMag>
00082 bool Thyra::testRelErrors(
00083   const std::string &v1_name,
00084   const ArrayView<const Scalar1> &v1,
00085   const std::string &v2_name,
00086   const ArrayView<const Scalar2> &v2,
00087   const std::string &maxRelErr_error_name,
00088   const ScalarMag &maxRelErr_error,
00089   const std::string &maxRelErr_warning_name,
00090   const ScalarMag &maxRelErr_warning,
00091   const Ptr<std::ostream> &out,
00092   const std::string &li
00093   )
00094 {
00095   using std::setw;
00096   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00097   typedef typename Teuchos::PromotionTraits<Scalar1,Scalar2>::promote Scalar;
00098 
00099   TEUCHOS_ASSERT_EQUALITY(v1.size(), v2.size());
00100   const int num_scalars = v1.size();
00101   
00102   if(num_scalars==1) {
00103     return Teuchos::testRelErr<Scalar>(
00104       v1_name, v1[0], v2_name, v2[0],
00105       maxRelErr_error_name, maxRelErr_error,
00106       maxRelErr_warning_name, maxRelErr_warning,
00107       out
00108       );
00109   }
00110 
00111   bool success = true;
00112 
00113   if (nonnull(out)) *out
00114     << std::endl
00115     << li << "Check: rel_err(" << v1_name << "," << v2_name << ") <= " << maxRelErr_error_name << " ?\n";
00116 
00117   for( int i = 0; i < num_scalars; ++i ) {
00118     const ScalarMag rel_err = relErr<Scalar>( v1[i], v2[i] );
00119     const bool result = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error) && rel_err <= maxRelErr_error );
00120     if(!result) success = false;
00121     if(nonnull(out)) {
00122       *out
00123         << li << "  "<<setw(2)<<i<<": rel_err("<<v1[i]<<","<<v2[i]<<") "<<"= "<<rel_err
00124         << " <= " << maxRelErr_error << " : " << passfail(result) << std::endl;
00125       if( result && rel_err >= maxRelErr_warning ) {
00126         *out
00127           << li << "      Warning! rel_err(...) >= " << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00128       }
00129     }
00130   }
00131 
00132   return success;
00133 
00134 }
00135 
00136 
00137 template<class Scalar>
00138 bool Thyra::testRelNormDiffErr(
00139   const std::string &v1_name,
00140   const VectorBase<Scalar> &v1,
00141   const std::string &v2_name,
00142   const VectorBase<Scalar> &v2,
00143   const std::string &maxRelErr_error_name,
00144   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00145   const std::string &maxRelErr_warning_name,
00146   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00147   std::ostream *out_inout,
00148   const Teuchos::EVerbosityLevel verbLevel,
00149   const std::string &li
00150   )
00151 {
00152   using std::endl;
00153   using Teuchos::as;
00154   using Teuchos::OSTab;
00155   typedef Teuchos::ScalarTraits<Scalar> ST;
00156   typedef typename ST::magnitudeType ScalarMag;
00157   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00158   const RCP<FancyOStream> out =
00159     Teuchos::fancyOStream(Teuchos::rcp(out_inout, false));
00160   const ScalarMag
00161     nrm_v1 = norm(v1),
00162     nrm_v2 = norm(v2);
00163   const ScalarMag rel_err = relVectorErr(v1,v2);
00164   const bool success =
00165     (
00166       !SMT::isnaninf(rel_err)
00167       && !SMT::isnaninf(maxRelErr_error)
00168       && rel_err <= maxRelErr_error
00169       );
00170   if (nonnull(out)) {
00171     *out
00172       << endl
00173       << li << "Testing relative error between vectors "
00174       << v1_name << " and " << v2_name << ":\n";
00175     OSTab tab(out);
00176     *out
00177       << li << "||"<<v1_name<<"|| = " << nrm_v1 << endl
00178       << li << "||"<<v2_name<<"|| = " << nrm_v2 << endl;
00179     if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH)) {
00180       *out
00181         << li << v1_name << " = " << describe(v1,verbLevel)
00182         << li << v2_name << " = " << describe(v2,verbLevel);
00183       RCP<VectorBase<Scalar> > diff = createMember(v1.space());
00184       V_VmV( diff.ptr(), v1, v2 );
00185       *out
00186         << li << v1_name << " - " << v2_name << " = " << describe(*diff,verbLevel);
00187     }
00188     *out
00189       << li << "Check: rel_err(" << v1_name << "," << v2_name << ") = "
00190       << rel_err << " <= " << maxRelErr_error_name << " = "
00191       << maxRelErr_error << " : " << passfail(success) << endl;
00192     if( success && rel_err >= maxRelErr_warning ) {
00193       *out
00194         << li << "Warning! rel_err(" << v1_name << "," << v2_name << " >= "
00195         << maxRelErr_warning_name << " = " << maxRelErr_warning << "!\n";
00196     }
00197   }
00198   return success;
00199 }
00200 
00201 
00202 template<class Scalar>
00203 bool Thyra::testMaxErr(
00204   const std::string                                             &error_name
00205   ,const Scalar                                                 &error
00206   ,const std::string                                            &max_error_name
00207   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_error
00208   ,const std::string                                            &max_warning_name
00209   ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType  &max_warning
00210   ,std::ostream                                                 *out
00211   ,const std::string                                            &li
00212   )
00213 {
00214   typedef Teuchos::ScalarTraits<Scalar> ST;
00215   typedef typename ST::magnitudeType ScalarMag;
00216   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00217   const ScalarMag error_mag = ST::magnitude(error);
00218   const bool success = (
00219     !SMT::isnaninf(error_mag)
00220     && !SMT::isnaninf(max_error)
00221     && error_mag <= max_error );
00222   if(out) {
00223     *out
00224       << std::endl
00225       << li << "Check: |" << error_name << "| = " << error_mag
00226       << " <= " << max_error_name << " = " << max_error << " : "
00227       << passfail(success) << std::endl;
00228     if( success && error_mag >= max_warning ) {
00229       *out
00230         << li << "Warning! " << error_name << " = " << error_mag
00231         << " >= " << max_warning_name << " = " << max_warning << "!\n";
00232     }
00233   }
00234   return success;
00235 }
00236 
00237 
00238 template<class Scalar>
00239 bool Thyra::testMaxErrors(
00240   const std::string &error_name,
00241   const ArrayView<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &errors,
00242   const std::string &max_error_name,
00243   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &max_error,
00244   const std::string &max_warning_name,
00245   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &max_warning,
00246   const Ptr<std::ostream> &out,
00247   const std::string &li
00248   )
00249 {
00250   using std::setw;
00251   typedef Teuchos::ScalarTraits<Scalar> ST;
00252   typedef typename ST::magnitudeType ScalarMag;
00253   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00254 
00255   const int num_scalars = errors.size();
00256 
00257   if(num_scalars==1) {
00258     return testMaxErr<Scalar>(
00259       error_name, errors[0],
00260       max_error_name, max_error,
00261       max_warning_name, max_warning,
00262       out.get(), li
00263       );
00264   }
00265 
00266   bool success = true;
00267 
00268   if (nonnull(out)) *out
00269     << std::endl
00270     << li << "Check: |"<<error_name<<"| <= "<<max_error_name<<" ?\n";
00271   for( int i = 0; i < num_scalars; ++i ) {
00272     const ScalarMag error_mag = ST::magnitude(errors[i]);
00273     const bool result = (
00274       !SMT::isnaninf(error_mag)
00275       && !SMT::isnaninf(max_error)
00276       && error_mag <= max_error );
00277     if(!result) success = false;
00278     if(nonnull(out)) {
00279       *out
00280         << li << "  "<<setw(2)<<i<<": |"<<errors[i]<<"| = "<<error_mag<<" <= "
00281         <<max_error<<" : "<<passfail(success)<<"\n";
00282       if( result && error_mag >= max_warning ) {
00283         *out
00284           << li << "      Warning! |...| >= "<<max_warning_name<<" = "<<max_warning<<"!\n";
00285       }
00286     }
00287   }
00288   return success;
00289 }
00290 
00291 
00292 template<class Scalar>
00293 std::ostream& Thyra::operator<<( std::ostream& o, const VectorBase<Scalar>& v )
00294 {
00295   return o << Teuchos::describe(v, Teuchos::VERB_EXTREME);
00296 }
00297 
00298 
00299 template<class Scalar>
00300 std::ostream& Thyra::operator<<( std::ostream& o, const LinearOpBase<Scalar>& M )
00301 {
00302   return o << Teuchos::describe(M, Teuchos::VERB_EXTREME);
00303 }
00304 
00305 
00306 #endif // THYRA_TESTING_TOOLS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines