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

Generated on Wed May 12 21:26:54 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7