Thyra_LinearOpTester.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_LINEAR_OP_TESTER_HPP
00030 #define THYRA_LINEAR_OP_TESTER_HPP
00031 
00032 #include "Thyra_LinearOpTesterDecl.hpp"
00033 #include "Thyra_LinearOpBase.hpp"
00034 #include "Thyra_ScaledAdjointLinearOp.hpp"
00035 #include "Thyra_describeLinearOp.hpp"
00036 #include "Thyra_VectorStdOps.hpp"
00037 #include "Thyra_TestingTools.hpp"
00038 #include "Thyra_UniversalMultiVectorRandomizer.hpp"
00039 
00040 namespace Thyra {
00041 
00042 // SymmetricLinearOpTester (using partial specialization only test symmetry on operators where RangeScalar and DomainScalar are the same)
00043 
00044 template<class RangeScalar, class DomainScalar>
00045 class SymmetricLinearOpTester {
00046 public:
00047   typedef typename Teuchos::PromotionTraits<RangeScalar,DomainScalar>::promote Scalar;
00048   typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00049   static void checkSymmetry(
00050     const LinearOpBase<RangeScalar,DomainScalar>  &op
00051     ,MultiVectorRandomizerBase<DomainScalar>      *dRand
00052     ,std::ostream                                 &oss
00053     ,const std::string                            &li
00054     ,const std::string                            &is
00055     ,const int                                    num_random_vectors
00056     ,const Teuchos::EVerbosityLevel               verbLevel
00057     ,const bool                                   dump_all
00058     ,const ScalarMag                              &symmetry_error_tol
00059     ,const ScalarMag                              &symmetry_warning_tol
00060     ,bool                                         *these_results
00061     )
00062     {
00063       using std::endl;
00064       typedef Teuchos::ScalarTraits<RangeScalar>  RST;
00065       typedef Teuchos::ScalarTraits<DomainScalar> DST;
00066       oss <<endl<<li<<li<< "RangeScalar = "<<RST::name()<<" == DomainScalar = "<<DST::name()<<": failed, the opeator can not be symmetric!\n";
00067       *these_results = false;
00068     }
00069 };
00070 
00071 template<class Scalar>
00072 class SymmetricLinearOpTester<Scalar,Scalar> {
00073 public:
00074   typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00075   static void checkSymmetry(
00076     const LinearOpBase<Scalar>                    &op
00077     ,MultiVectorRandomizerBase<Scalar>            *dRand
00078     ,std::ostream                                 &oss
00079     ,const std::string                            &li
00080     ,const std::string                            &is
00081     ,const int                                    num_random_vectors
00082     ,const Teuchos::EVerbosityLevel               verbLevel
00083     ,const bool                                   dump_all
00084     ,const ScalarMag                              &symmetry_error_tol
00085     ,const ScalarMag                              &symmetry_warning_tol
00086     ,bool                                         *these_results
00087     )
00088     {
00089 
00090       bool result;
00091       typedef Teuchos::ScalarTraits<Scalar> ST;
00092       const Scalar half = Scalar(0.4)*ST::one();
00093       Teuchos::RefCountPtr<const VectorSpaceBase<Scalar> > domain = op.domain();
00094       
00095       oss <<endl<<li<<is<< "op.domain()->isCompatible(*op.range()) == true : ";
00096       result = op.domain()->isCompatible(*op.range());
00097       if(!result) *these_results = false;
00098       oss << passfail(result) << endl;
00099       
00100       if(result) {
00101         
00102         oss
00103           <<endl<<li<<is<< "Checking that the operator is symmetric as:\n"
00104           <<endl<<li<<is<< "  <0.5*op*v2,v1> == <v2,0.5*op*v1>"
00105           <<endl<<li<<is<< "   \\_______/            \\_______/"
00106           <<endl<<li<<is<< "      v4                    v3"
00107           <<endl<<li<<is<< ""
00108           <<endl<<li<<is<< "         <v4,v1> == <v2,v3>"
00109           << endl;
00110         
00111         for( int rand_vec_i = 1; rand_vec_i <= num_random_vectors; ++rand_vec_i ) {
00112           
00113           oss <<endl<<li<<is<< "Random vector tests = " << rand_vec_i << endl;
00114           
00115           if(dump_all) oss <<endl<<li<<is<< "v1 = randomize(-1,+1); ...\n" ;
00116           Teuchos::RefCountPtr<VectorBase<Scalar> > v1 = createMember(domain);
00117           dRand->randomize(&*v1);
00118           if(dump_all) oss <<endl<<li<<is<< "v1 =\n" << describe(*v1,verbLevel,li,is);
00119           
00120           if(dump_all) oss <<endl<<li<<is<< "v2 = randomize(-1,+1); ...\n" ;
00121           Teuchos::RefCountPtr<VectorBase<Scalar> > v2 = createMember(domain);
00122           dRand->randomize(&*v2);
00123           if(dump_all) oss <<endl<<li<<is<< "v2 =\n" << describe(*v2,verbLevel,li,is);
00124           
00125           if(dump_all) oss <<endl<<li<<is<< "v3 = 0.5*op*v1 ...\n" ;
00126           Teuchos::RefCountPtr<VectorBase<Scalar> > v3 = createMember(domain);
00127           apply( op, NONCONJ_ELE, *v1, &*v3, half );
00128          if(dump_all) oss <<endl<<li<<is<< "v3 =\n" << describe(*v3,verbLevel,li,is);
00129           
00130           if(dump_all) oss <<endl<<li<<is<< "v4 = 0.5*op*v2 ...\n" ;
00131           Teuchos::RefCountPtr<VectorBase<Scalar> > v4 = createMember(domain);
00132           apply( op, NONCONJ_ELE, *v2, &*v4, half );
00133           if(dump_all) oss <<endl<<li<<is<< "v4 =\n" << describe(*v4,verbLevel,li,is);
00134           
00135           const Scalar
00136             prod1 = domain->scalarProd(*v4,*v1),
00137             prod2 = domain->scalarProd(*v2,*v3);
00138           
00139           result = testRelErr(
00140             "<v4,v1>", prod1
00141             ,"<v2,v3>", prod2
00142             ,"symmetry_error_tol()", symmetry_error_tol
00143             ,"symmetry_warning_tol()", symmetry_warning_tol
00144             ,&oss,li+is
00145             );
00146           if(!result) *these_results = false;
00147         
00148         }
00149       }
00150       else {
00151         oss <<endl<<li<<is<< "Range and domain spaces are different, skipping check!\n";
00152       }
00153     }
00154 };
00155 
00156 // LinearOpTester
00157 
00158 template<class RangeScalar, class DomainScalar>
00159 LinearOpTester<RangeScalar,DomainScalar>::LinearOpTester(
00160   const bool          check_linear_properties
00161   ,const ScalarMag    linear_properties_warning_tol
00162   ,const ScalarMag    linear_properties_error_tol
00163   ,const bool         check_adjoint
00164   ,const ScalarMag    adjoint_warning_tol
00165   ,const ScalarMag    adjoint_error_tol
00166   ,const bool         check_for_symmetry
00167   ,const ScalarMag    symmetry_warning_tol
00168   ,const ScalarMag    symmetry_error_tol
00169   ,const int          num_random_vectors
00170   ,const bool         show_all_tests
00171   ,const bool         dump_all
00172   )
00173   :check_linear_properties_(check_linear_properties)
00174   ,linear_properties_warning_tol_(linear_properties_warning_tol)
00175   ,linear_properties_error_tol_(linear_properties_error_tol)
00176   ,check_adjoint_(check_adjoint)
00177   ,adjoint_warning_tol_(adjoint_warning_tol)
00178   ,adjoint_error_tol_(adjoint_error_tol)
00179   ,check_for_symmetry_(check_for_symmetry)
00180   ,symmetry_warning_tol_(symmetry_warning_tol)
00181   ,symmetry_error_tol_(symmetry_error_tol)
00182   ,num_random_vectors_(num_random_vectors)
00183   ,show_all_tests_(show_all_tests)
00184   ,dump_all_(dump_all)
00185 {}
00186 
00187 template<class RangeScalar, class DomainScalar>
00188 void LinearOpTester<RangeScalar,DomainScalar>::set_all_warning_tol( const ScalarMag warning_tol )
00189 {
00190   linear_properties_warning_tol_  = warning_tol;
00191   adjoint_warning_tol_            = warning_tol;
00192   symmetry_warning_tol_           = warning_tol;
00193 }
00194 
00195 template<class RangeScalar, class DomainScalar>
00196 void LinearOpTester<RangeScalar,DomainScalar>::set_all_error_tol( const ScalarMag error_tol )
00197 {
00198   linear_properties_error_tol_  = error_tol;
00199   adjoint_error_tol_            = error_tol;
00200   symmetry_error_tol_           = error_tol;
00201 }
00202 
00203 template<class RangeScalar, class DomainScalar>
00204 bool LinearOpTester<RangeScalar,DomainScalar>::check(
00205   const LinearOpBase<RangeScalar,DomainScalar>  &op
00206   ,MultiVectorRandomizerBase<RangeScalar>       *rangeRandomizer
00207   ,MultiVectorRandomizerBase<DomainScalar>      *domainRandomizer
00208   ,std::ostream                                 *out
00209   ,const std::string                            &leadingIndent
00210   ,const std::string                            &indentSpacer
00211   ) const
00212 {
00213 
00214   using std::endl;
00215   typedef Teuchos::ScalarTraits<RangeScalar>  RST;
00216   typedef Teuchos::ScalarTraits<DomainScalar> DST;
00217   bool success = true, result;
00218   const RangeScalar  r_one  = RST::one();
00219   const DomainScalar d_one  = DST::one();
00220   const RangeScalar  r_half = RangeScalar(0.5)*r_one;
00221   const DomainScalar d_half = DomainScalar(0.5)*d_one;
00222   const std::string &li = leadingIndent, &is = indentSpacer;
00223   const Teuchos::EVerbosityLevel verbLevel = (dump_all()?Teuchos::VERB_EXTREME:Teuchos::VERB_MEDIUM);
00224 
00225   // ToDo 04/28/2005:
00226   // * Test the MultiVectorBase apply() function and output to the VectorBase apply() function!
00227 
00228   if(out) {
00229     *out <<endl<<li<< "*** Entering LinearOpTester<"<<RST::name()<<","<<DST::name()<<">::check(op,...) ...\n";
00230     if(show_all_tests()) {
00231       *out <<endl<<li<< "describe op:\n" << Teuchos::describe(op,verbLevel,li,is);
00232 /*
00233       if(op.applyTransposeSupports(CONJ_ELE) && verbLevel==Teuchos::VERB_EXTREME) {
00234         *out <<endl<<li<< "describe adjoint op:\n";
00235         describeLinearOp(*adjoint(Teuchos::rcp(&op,false)),*out,verbLevel,li,is);
00236       }
00237 */
00238     }
00239     else {
00240       *out <<endl<<li<< "describe op: " << op.description() << endl;
00241     }
00242   }
00243 
00244   Teuchos::RefCountPtr< MultiVectorRandomizerBase<RangeScalar> >  rRand;
00245   if(rangeRandomizer)   rRand = Teuchos::rcp(rangeRandomizer,false);
00246   else                  rRand = Teuchos::rcp(new UniversalMultiVectorRandomizer<RangeScalar>());
00247   Teuchos::RefCountPtr< MultiVectorRandomizerBase<DomainScalar> > dRand;
00248   if(domainRandomizer)  dRand = Teuchos::rcp(domainRandomizer,false);
00249   else                  dRand = Teuchos::rcp(new UniversalMultiVectorRandomizer<DomainScalar>());
00250   
00251   if(out)
00252     *out <<endl<<li << "Checking the domain and range spaces ... ";
00253 
00254   Teuchos::RefCountPtr<const VectorSpaceBase<RangeScalar> >  range  = op.range();
00255   Teuchos::RefCountPtr<const VectorSpaceBase<DomainScalar> > domain = op.domain();
00256   
00257   if(1) {
00258 
00259     std::ostringstream oss;
00260     if(out) oss.copyfmt(*out);
00261     bool these_results = true;
00262 
00263     oss <<endl<<li<<is<< "op.domain().get() != NULL ? ";
00264     result = domain.get() != NULL;
00265     if(!result) these_results = false;
00266     oss << passfail(result) << endl;
00267     
00268     oss <<endl<<li<<is<< "op.range().get() != NULL ? ";
00269     result = range.get() != NULL;
00270     if(!result) these_results = false;
00271     oss << passfail(result) << endl;
00272 
00273     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00274 
00275   }
00276 
00277   if( check_linear_properties() ) {
00278 
00279     if(out) *out <<endl<<li<< "this->check_linear_properties()==true: Checking the linear properties of the forward linear operator ... ";
00280 
00281     std::ostringstream oss;
00282     if(out) oss.copyfmt(*out);
00283     bool these_results = true;
00284 
00285     oss <<endl<<li<<is<< "op.applySupports(NONCONJ_ELE) == true ? ";
00286     result = op.applySupports(NONCONJ_ELE);
00287     if(!result) these_results = false;
00288     oss << passfail(result) << endl;
00289 
00290     if(result) {
00291     
00292       oss
00293         <<endl<<li<<is<< "Checking that the forward operator is truly linear:\n"
00294         <<endl<<li<<is<< "  0.5*op*(v1 + v2) == 0.5*op*v1 + 0.5*op*v2"
00295         <<endl<<li<<is<< "          \\_____/         \\___/"
00296         <<endl<<li<<is<< "             v3            v5"
00297         <<endl<<li<<is<< "  \\_____________/     \\___________________/"
00298         <<endl<<li<<is<< "         v4                    v5"
00299         <<endl<<li<<is<< ""
00300         <<endl<<li<<is<< "           sum(v4) == sum(v5)"
00301         << endl;
00302       
00303       for( int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
00304         
00305         oss <<endl<<li<<is<< "Random vector tests = " << rand_vec_i << endl;
00306         
00307         oss <<endl<<li<<is<< "v1 = randomize(-1,+1); ...\n" ;
00308         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v1 = createMember(domain);
00309         dRand->randomize(&*v1);
00310         if(dump_all()) oss <<endl<<li<<is<< "v1 =\n" << describe(*v1,verbLevel,li,is);
00311         
00312         oss <<endl<<li<<is<< "v2 = randomize(-1,+1); ...\n" ;
00313         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v2 = createMember(domain);
00314         dRand->randomize(&*v2);
00315         if(dump_all()) oss <<endl<<li<<is<< "v2 =\n" << describe(*v2,verbLevel,li,is);
00316         
00317         oss <<endl<<li<<is<< "v3 = v1 + v2 ...\n" ;
00318         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v3 = createMember(domain);
00319         V_VpV(&*v3,*v1,*v2);
00320         if(dump_all()) oss <<endl<<li<<is<< "v3 =\n" << describe(*v3,verbLevel,li,is);
00321         
00322         oss <<endl<<li<<is<< "v4 = 0.5*op*v3 ...\n" ;
00323         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v4 = createMember(range);
00324         apply( op, NONCONJ_ELE, *v3, &*v4, r_half );
00325         if(dump_all()) oss <<endl<<li<<is<< "v4 =\n" << describe(*v4,verbLevel,li,is);
00326         
00327         oss <<endl<<li<<is<< "v5 = op*v1 ...\n" ;
00328         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v5 = createMember(range);
00329         apply( op, NONCONJ_ELE, *v1, &*v5 );
00330         if(dump_all()) oss <<endl<<li<<is<< "v5 =\n" << describe(*v5,verbLevel,li,is);
00331         
00332         oss <<endl<<li<<is<< "v5 = 0.5*op*v2 + 0.5*v5 ...\n" ;
00333         apply( op, NONCONJ_ELE, *v2, &*v5, r_half, r_half );
00334         if(dump_all()) oss <<endl<<li<<is<< "v5 =\n" << describe(*v5,verbLevel,li,is);
00335         
00336         const Scalar
00337           sum_v4 = sum(*v4),
00338           sum_v5 = sum(*v5);
00339         
00340         result = testRelErr(
00341           "sum(v4)", sum_v4
00342           ,"sum(v5)", sum_v5
00343           ,"linear_properties_error_tol()", linear_properties_error_tol()
00344           ,"linear_properties_warning_tol()", linear_properties_warning_tol()
00345           ,&oss,li+is
00346           );
00347         if(!result) these_results = false;
00348         
00349       }
00350     }
00351     else {
00352       oss <<endl<<li<<is<< "Forward operator not supported, skipping check!\n";
00353     }
00354       
00355     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00356 
00357   }
00358   else {
00359     if(out) *out <<endl<<li<< "this->check_linear_properties()==false: Skipping the check of the linear properties of the forward operator!\n";
00360   }
00361 
00362   if( check_linear_properties() && check_adjoint() ) {
00363 
00364     if(out) *out <<endl<<li<< "(this->check_linear_properties()&&this->check_adjoint())==true: Checking the linear properties of the adjoint operator ... ";
00365 
00366     std::ostringstream oss;
00367     if(out) oss.copyfmt(*out);
00368     bool these_results = true;
00369 
00370     oss <<endl<<li<<is<< "op.applyTransposeSupports(CONJ_ELE) == true ? ";
00371     result = op.applyTransposeSupports(CONJ_ELE);
00372     if(!result) these_results = false;
00373     oss << passfail(result) << endl;
00374 
00375     if(result) {
00376     
00377       oss
00378         <<endl<<li<<is<< "Checking that the adjoint operator is truly linear:\n"
00379         <<endl<<li<<is<< "  0.5*op'*(v1 + v2) == 0.5*op'*v1 + 0.5*op'*v2"
00380         <<endl<<li<<is<< "           \\_____/         \\____/"
00381         <<endl<<li<<is<< "              v3             v5"
00382         <<endl<<li<<is<< "  \\_______________/    \\_____________________/"
00383         <<endl<<li<<is<< "         v4                      v5"
00384         <<endl<<li<<is<< ""
00385         <<endl<<li<<is<< "           sum(v4) == sum(v5)"
00386         << endl;
00387       
00388       for( int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
00389         
00390         oss <<endl<<li<<is<< "Random vector tests = " << rand_vec_i << endl;
00391         
00392         oss <<endl<<li<<is<< "v1 = randomize(-1,+1); ...\n" ;
00393         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v1 = createMember(range);
00394         rRand->randomize(&*v1);
00395         if(dump_all()) oss <<endl<<li<<is<< "v1 =\n" << describe(*v1,verbLevel,li,is);
00396         
00397         oss <<endl<<li<<is<< "v2 = randomize(-1,+1); ...\n" ;
00398         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v2 = createMember(range);
00399         rRand->randomize(&*v2);
00400         if(dump_all()) oss <<endl<<li<<is<< "v2 =\n" << describe(*v2,verbLevel,li,is);
00401         
00402         oss <<endl<<li<<is<< "v3 = v1 + v2 ...\n" ;
00403         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v3 = createMember(range);
00404         V_VpV(&*v3,*v1,*v2);
00405         if(dump_all()) oss <<endl<<li<<is<< "v3 =\n" << describe(*v3,verbLevel,li,is);
00406         
00407         oss <<endl<<li<<is<< "v4 = 0.5*op'*v3 ...\n" ;
00408         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v4 = createMember(domain);
00409         applyTranspose( op, CONJ_ELE, *v3, &*v4, d_half );
00410         if(dump_all()) oss <<endl<<li<<is<< "v4 =\n" << describe(*v4,verbLevel,li,is);
00411         
00412         oss <<endl<<li<<is<< "v5 = op'*v1 ...\n" ;
00413         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v5 = createMember(domain);
00414         applyTranspose( op, CONJ_ELE, *v1, &*v5 );
00415         if(dump_all()) oss <<endl<<li<<is<< "v5 =\n" << describe(*v5,verbLevel,li,is);
00416         
00417         oss <<endl<<li<<is<< "v5 = 0.5*op'*v2 + 0.5*v5 ...\n" ;
00418         applyTranspose( op, CONJ_ELE, *v2, &*v5, d_half, d_half );
00419         if(dump_all()) oss <<endl<<li<<is<< "v5 =\n" << describe(*v5,verbLevel,li,is);
00420         
00421         const Scalar
00422           sum_v4 = sum(*v4),
00423           sum_v5 = sum(*v5);
00424         
00425         result = testRelErr(
00426           "sum(v4)", sum_v4
00427           ,"sum(v5)", sum_v5
00428           ,"linear_properties_error_tol()", linear_properties_error_tol()
00429           ,"linear_properties_warning_tol()", linear_properties_warning_tol()
00430           ,&oss,li+is
00431           );
00432         if(!result) these_results = false;
00433         
00434       }
00435     }
00436     else {
00437       oss <<endl<<li<<is<< "Adjoint operator not supported, skipping check!\n";
00438     }
00439 
00440     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00441 
00442   }
00443   else {
00444     if(out) *out <<endl<<li<< "(this->check_linear_properties()&&this->check_adjoint())==false: Skipping the check of the linear properties of the adjoint operator!\n";
00445   }
00446   
00447   if( check_adjoint() ) {
00448 
00449     if(out) *out <<endl<<li<< "this->check_adjoint()==true: Checking the agreement of the adjoint and forward operators ... ";
00450 
00451     std::ostringstream oss;
00452     if(out) oss.copyfmt(*out);
00453     bool these_results = true;
00454     
00455     oss <<endl<<li<<is<< "op.applyTransposeSupports(CONJ_ELE) == true ? ";
00456     result = op.applyTransposeSupports(CONJ_ELE);
00457     if(!result) these_results = false;
00458     oss << passfail(result) << endl;
00459 
00460     if(result) {
00461     
00462       oss
00463         <<endl<<li<<is<< "Checking that the adjoint agrees with the non-adjoint operator as:\n"
00464         <<endl<<li<<is<< "  <0.5*op'*v2,v1> == <v2,0.5*op*v1>"
00465         <<endl<<li<<is<< "   \\________/            \\_______/"
00466         <<endl<<li<<is<< "       v4                   v3"
00467         <<endl<<li<<is<< ""
00468         <<endl<<li<<is<< "         <v4,v1>  == <v2,v3>"
00469         << endl;
00470     
00471       for( int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
00472       
00473         oss <<endl<<li<<is<< "Random vector tests = " << rand_vec_i << endl;
00474       
00475         oss <<endl<<li<<is<< "v1 = randomize(-1,+1); ...\n" ;
00476         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v1 = createMember(domain);
00477         dRand->randomize(&*v1);
00478         if(dump_all()) oss <<endl<<li<<is<< "v1 =\n" << describe(*v1,verbLevel,li,is);
00479       
00480         oss <<endl<<li<<is<< "v2 = randomize(-1,+1); ...\n" ;
00481         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v2 = createMember(range);
00482         rRand->randomize(&*v2);
00483         if(dump_all()) oss <<endl<<li<<is<< "v2 =\n" << describe(*v2,verbLevel,li,is);
00484       
00485         oss <<endl<<li<<is<< "v3 = 0.5*op*v1 ...\n" ;
00486         Teuchos::RefCountPtr<VectorBase<RangeScalar> > v3 = createMember(range);
00487         apply( op, NONCONJ_ELE, *v1, &*v3, r_half );
00488         if(dump_all()) oss <<endl<<li<<is<< "v3 =\n" << describe(*v3,verbLevel,li,is);
00489       
00490         oss <<endl<<li<<is<< "v4 = 0.5*op'*v2 ...\n" ;
00491         Teuchos::RefCountPtr<VectorBase<DomainScalar> > v4 = createMember(domain);
00492         applyTranspose( op, CONJ_ELE, *v2, &*v4, d_half );
00493         if(dump_all()) oss <<endl<<li<<is<< "v4 =\n" << describe(*v4,verbLevel,li,is);
00494       
00495         const Scalar
00496           prod1 = domain->scalarProd(*v4,*v1),
00497           prod2 = range->scalarProd(*v2,*v3);
00498 
00499         result = testRelErr(
00500           "<v4,v1>", prod1
00501           ,"<v2,v3>", prod2
00502           ,"adjoint_error_tol()", adjoint_error_tol()
00503           ,"adjoint_warning_tol()", adjoint_warning_tol()
00504           ,&oss,li+is
00505           );
00506         if(!result) these_results = false;
00507 
00508       }
00509     }
00510     else {
00511       oss <<endl<<li<<is<< "Adjoint operator not supported, skipping check!\n";
00512     }
00513 
00514     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00515 
00516   }
00517   else {
00518     if(out) *out <<endl<<li<< "this->check_adjoint()==false: Skipping check for the agreement of the adjoint and forward operators!\n";
00519   }
00520 
00521   if( check_for_symmetry() ) {
00522 
00523     if(out) *out <<endl<<li<< "this->check_for_symmetry()==true: Performing check of symmetry ... ";
00524 
00525     std::ostringstream oss;
00526     if(out) oss.copyfmt(*out);
00527     bool these_results = true;
00528 
00529     SymmetricLinearOpTester<RangeScalar,DomainScalar>::checkSymmetry(
00530       op,&*dRand,oss,li,is,num_random_vectors(),verbLevel,dump_all(),symmetry_error_tol(),symmetry_warning_tol(),&these_results
00531       );
00532     
00533     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00534     
00535   }
00536   else {
00537     if(out) *out <<endl<<li<< "this->check_for_symmetry()==false: Skipping check of symmetry ...\n";
00538   }
00539   
00540   if(out) {
00541     if(success)
00542       *out <<endl<<li<<"Congratulations, this LinearOpBase object seems to check out!\n";
00543     else
00544       *out <<endl<<li<<"Oh no, at least one of the tests performed with this LinearOpBase object failed (see above failures)!\n";
00545     *out <<endl<<li<< "*** Leaving LinearOpTester<"<<RST::name()<<","<<DST::name()<<">::check(...)\n";
00546   }
00547 
00548   return success;
00549 }
00550 
00551 
00552 template<class RangeScalar, class DomainScalar>
00553 bool LinearOpTester<RangeScalar,DomainScalar>::check(
00554   const LinearOpBase<RangeScalar,DomainScalar>  &op
00555   ,std::ostream                                 *out
00556   ,const std::string                            &leadingIndent
00557   ,const std::string                            &indentSpacer
00558   ) const
00559 {
00560   return check(op,NULL,NULL,out,leadingIndent,indentSpacer);
00561 }
00562 
00563 template<class RangeScalar, class DomainScalar>
00564 bool LinearOpTester<RangeScalar,DomainScalar>::compare(
00565   const LinearOpBase<RangeScalar,DomainScalar>  &op1
00566   ,const LinearOpBase<RangeScalar,DomainScalar> &op2
00567   ,MultiVectorRandomizerBase<DomainScalar>      *domainRandomizer
00568   ,std::ostream                                 *out
00569   ,const std::string                            &leadingIndent
00570   ,const std::string                            &indentSpacer
00571   ) const
00572 {
00573 
00574   using std::endl;
00575   using Teuchos::arrayArg;
00576   typedef Teuchos::ScalarTraits<RangeScalar>  RST;
00577   typedef Teuchos::ScalarTraits<DomainScalar> DST;
00578   bool success = true, result;
00579   const RangeScalar  r_half = RangeScalar(0.5)*RST::one();
00580   const std::string &li = leadingIndent, &is = indentSpacer;
00581   const Teuchos::EVerbosityLevel verbLevel = (dump_all()?Teuchos::VERB_EXTREME:Teuchos::VERB_MEDIUM);
00582 
00583   if(out) {
00584     *out
00585       <<endl<<li<< "*** Entering LinearOpTester<"<<RST::name()<<","<<DST::name()<<">::compare(op1,op2,...) ...\n";
00586     if(show_all_tests())
00587       *out <<endl<<li<< "describe op1:\n" << Teuchos::describe(op1,verbLevel,li,is);
00588     else
00589       *out <<endl<<li<< "describe op1: " << op1.description() << endl;
00590     if(show_all_tests())
00591       *out <<endl<<li<< "describe op2:\n" << Teuchos::describe(op2,verbLevel,li,is);
00592     else
00593       *out <<endl<<li<< "describe op2: " << op2.description() << endl;
00594   }
00595 
00596   Teuchos::RefCountPtr< MultiVectorRandomizerBase<DomainScalar> > dRand;
00597   if(domainRandomizer)  dRand = Teuchos::rcp(domainRandomizer,false);
00598   else                  dRand = Teuchos::rcp(new UniversalMultiVectorRandomizer<DomainScalar>());
00599 
00600   Teuchos::RefCountPtr<const VectorSpaceBase<RangeScalar> >  range  = op1.range();
00601   Teuchos::RefCountPtr<const VectorSpaceBase<DomainScalar> > domain = op1.domain();
00602 
00603   if(out) *out <<endl<<li<< "Checking that range and domain spaces are compatible ... ";
00604 
00605   if(1) {
00606 
00607     std::ostringstream oss;
00608     if(out) oss.copyfmt(*out);
00609     bool these_results = true;
00610 
00611     oss <<endl<<li<<is<< "op1.domain()->isCompatible(*op2.domain()) ? ";
00612     result = op1.domain()->isCompatible(*op2.domain());
00613     if(!result) these_results = false;
00614     oss << passfail(result) << endl;
00615     
00616     oss <<endl<<li<<is<< "op1.range()->isCompatible(*op2.range()) ? ";
00617     result = op1.range()->isCompatible(*op2.range());
00618     if(!result) these_results = false;
00619     oss << passfail(result) << endl;
00620 
00621     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00622 
00623   }
00624 
00625   if(!success) {
00626     if(out) *out <<endl<<li<< "Skipping further checks since operators are not compatible!\n";
00627     return success;
00628   }
00629 
00630   if(out) *out <<endl<<li<< "Checking that op1 == op2 ... ";
00631 
00632   if(1) {
00633 
00634     std::ostringstream oss;
00635     if(out) oss.copyfmt(*out);
00636     bool these_results = true;
00637 
00638     oss
00639       <<endl<<li<<is<< "Checking that op1 and op2 produce the same results:\n"
00640       <<endl<<li<<is<< "  0.5*op1*v1 == 0.5*op2*v1"
00641       <<endl<<li<<is<< "  \\________/    \\________/"
00642       <<endl<<li<<is<< "      v2            v3"
00643       <<endl<<li<<is<< ""
00644       <<endl<<li<<is<< "   |sum(v2)| == |sum(v3)|"
00645       << endl;
00646 
00647     for( int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
00648       
00649       oss <<endl<<li<<is<< "Random vector tests = " << rand_vec_i << endl;
00650       
00651       if(dump_all()) oss <<endl<<li<<is<< "v1 = randomize(-1,+1); ...\n" ;
00652       Teuchos::RefCountPtr<VectorBase<DomainScalar> > v1 = createMember(domain);
00653       dRand->randomize(&*v1);
00654       if(dump_all()) oss <<endl<<li<<is<< "v1 =\n" << *v1;
00655       
00656       if(dump_all()) oss <<endl<<li<<is<< "v2 = 0.5*op1*v1 ...\n" ;
00657       Teuchos::RefCountPtr<VectorBase<RangeScalar> > v2 = createMember(range);
00658       apply( op1, NONCONJ_ELE, *v1, &*v2, r_half );
00659       if(dump_all()) oss <<endl<<li<<is<< "v2 =\n" << *v2;
00660       
00661       if(dump_all()) oss <<endl<<li<<is<< "v3 = 0.5*op2*v1 ...\n" ;
00662       Teuchos::RefCountPtr<VectorBase<RangeScalar> > v3 = createMember(range);
00663       apply( op2, NONCONJ_ELE, *v1, &*v3, r_half );
00664       if(dump_all()) oss <<endl<<li<<is<< "v3 =\n" << *v3;
00665       
00666       const Scalar
00667         sum_v2 = sum(*v2),
00668         sum_v3 = sum(*v3);
00669       
00670       result = testRelErr(
00671         "sum(v2)", sum_v2
00672         ,"sum(v3)", sum_v3
00673         ,"linear_properties_error_tol()", linear_properties_error_tol()
00674         ,"linear_properties_warning_tol()", linear_properties_warning_tol()
00675         ,&oss,li+is
00676         );
00677       if(!result) these_results = false;
00678       
00679     }
00680 
00681     printTestResults(these_results,oss.str(),show_all_tests(),&success,out);
00682 
00683   }
00684 
00685   
00686   if(out) {
00687     if(success)
00688       *out <<endl<<li<<"Congratulations, these two LinearOpBase objects seem to be the same!\n";
00689     else
00690       *out <<endl<<li<<"Oh no, these two LinearOpBase objects seem to be different (see above failures)!\n";
00691     *out <<endl<<li<< "*** Leaving LinearOpTester<"<<RST::name()<<","<<DST::name()<<">::compare(...)\n";
00692   }
00693 
00694   return success;
00695 
00696 }
00697 
00698 template<class RangeScalar, class DomainScalar>
00699 bool LinearOpTester<RangeScalar,DomainScalar>::compare(
00700   const LinearOpBase<RangeScalar,DomainScalar>  &op1
00701   ,const LinearOpBase<RangeScalar,DomainScalar> &op2
00702   ,std::ostream                                 *out
00703   ,const std::string                            &leadingIndent
00704   ,const std::string                            &indentSpacer
00705   ) const
00706 {
00707   return compare(op1,op2,NULL,out,leadingIndent,indentSpacer);
00708 }
00709 
00710 } // namespace Thyra
00711 
00712 #endif // THYRA_LINEAR_OP_TESTER_HPP

Generated on Thu Sep 18 12:39:52 2008 for Thyra ANA Operator/VectorBase Interfaces and Related Software by doxygen 1.3.9.1