00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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