10#ifndef THYRA_LINEAR_OP_TESTER_DEF_HPP 
   11#define THYRA_LINEAR_OP_TESTER_DEF_HPP 
   13#include "Thyra_LinearOpTester_decl.hpp" 
   14#include "Thyra_LinearOpBase.hpp" 
   15#include "Thyra_DefaultScaledAdjointLinearOp.hpp" 
   16#include "Thyra_describeLinearOp.hpp" 
   17#include "Thyra_VectorStdOps.hpp" 
   18#include "Thyra_TestingTools.hpp" 
   19#include "Thyra_UniversalMultiVectorRandomizer.hpp" 
   20#include "Teuchos_TestingHelpers.hpp" 
   27class SymmetricLinearOpTester {
 
   30  static void checkSymmetry(
 
   31    const LinearOpBase<Scalar> &op,
 
   32    const Ptr<MultiVectorRandomizerBase<Scalar> > &dRand,
 
   35    const int num_random_vectors,
 
   38    const ScalarMag &symmetry_error_tol,
 
   39    const ScalarMag &symmetry_warning_tol,
 
   40    const Ptr<bool> &these_results
 
   49      const Scalar half = Scalar(0.4)*ST::one();
 
   50      RCP<const VectorSpaceBase<Scalar> > domain = op.domain();
 
   52      testOut << endl << 
"op.domain()->isCompatible(*op.range()) == true : ";
 
   53      result = op.domain()->isCompatible(*op.range());
 
   54      if(!result) *these_results = 
false;
 
   60          << endl << 
"Checking that the operator is symmetric as:\n" 
   61          << endl << 
"  <0.5*op*v2,v1> == <v2,0.5*op*v1>" 
   62          << endl << 
"   \\_______/            \\_______/" 
   65          << endl << 
"         <v4,v1> == <v2,v3>" 
   66          << endl << std::flush;
 
   68        for( 
int rand_vec_i = 1; rand_vec_i <= num_random_vectors; ++rand_vec_i ) {
 
   70          testOut << endl << 
"Random vector tests = " << rand_vec_i << endl;
 
   74          if(dump_all) testOut << endl << 
"v1 = randomize(-1,+1); ...\n" ;
 
   75          RCP<MultiVectorBase<Scalar> > v1 = createMembers(domain,num_rhs);
 
   76          dRand->randomize(v1.ptr());
 
   77          if(dump_all) testOut << endl << 
"v1 =\n" << describe(*v1,verbLevel);
 
   79          if(dump_all) testOut << endl << 
"v2 = randomize(-1,+1); ...\n" ;
 
   80          RCP<MultiVectorBase<Scalar> > v2 = createMembers(domain,num_rhs);
 
   81          dRand->randomize(v2.ptr());
 
   82          if(dump_all) testOut << endl << 
"v2 =\n" << describe(*v2,verbLevel);
 
   84          if(dump_all) testOut << endl << 
"v3 = 0.5*op*v1 ...\n" ;
 
   85          RCP<MultiVectorBase<Scalar> > v3 = createMembers(domain,num_rhs);
 
   86          apply( op, 
NOTRANS, *v1, v3.ptr(), half );
 
   87          if(dump_all) testOut << endl << 
"v3 =\n" << describe(*v3,verbLevel);
 
   89          if(dump_all) testOut << endl << 
"v4 = 0.5*op*v2 ...\n" ;
 
   90          RCP<MultiVectorBase<Scalar> > v4 = createMembers(domain,num_rhs);
 
   91          apply( op, 
NOTRANS, *v2, v4.ptr(), half );
 
   92          if(dump_all) testOut << endl << 
"v4 =\n" << describe(*v4,verbLevel);
 
   94          Array<Scalar> prod1(num_rhs), prod2(num_rhs);
 
   95          domain->scalarProds(*v4, *v1, prod1());
 
   96          domain->scalarProds(*v2, *v3, prod2());
 
   98          result = testRelErrors<Scalar, Scalar, ScalarMag>(
 
  101            "symmetry_error_tol()", symmetry_error_tol,
 
  102            "symmetry_warning_tol()", symmetry_warning_tol,
 
  105          if(!result) *these_results = 
false;
 
  110        testOut << endl << 
"Range and domain spaces are different, skipping check!\n";
 
  121template<
class Scalar>
 
  123  :check_linear_properties_(true),
 
  124   linear_properties_warning_tol_(-1.0),
 
  125   linear_properties_error_tol_(-1.0),
 
  126   check_adjoint_(true),
 
  127   adjoint_warning_tol_(-1.0),
 
  128   adjoint_error_tol_(-1.0),
 
  129   check_for_symmetry_(false),
 
  130   symmetry_warning_tol_(-1.0),
 
  131   symmetry_error_tol_(-1.0),
 
  132   num_random_vectors_(1),
 
  133   show_all_tests_(false),
 
 
  141template<
class Scalar>
 
  144  check_linear_properties_ = enable_all_tests_in;
 
  145  check_adjoint_ = enable_all_tests_in;
 
  146  check_for_symmetry_ = enable_all_tests_in;
 
 
  150template<
class Scalar>
 
  153  linear_properties_warning_tol_ = warning_tol_in;
 
  154  adjoint_warning_tol_ = warning_tol_in;
 
  155  symmetry_warning_tol_ = warning_tol_in;
 
 
  159template<
class Scalar>
 
  162  linear_properties_error_tol_ = error_tol_in;
 
  163  adjoint_error_tol_ = error_tol_in;
 
  164  symmetry_error_tol_ = error_tol_in;
 
 
  168template<
class Scalar>
 
  180  using Teuchos::rcpFromPtr;
 
  181  using Teuchos::rcpFromRef;
 
  182  using Teuchos::outArg;
 
  183  using Teuchos::inoutArg;
 
  184  using Teuchos::fancyOStream;
 
  189  bool success = 
true, result;
 
  190  const int loc_num_rhs = this->num_rhs();
 
  191  const Scalar r_one  = ST::one();
 
  192  const Scalar d_one  = ST::one();
 
  193  const Scalar r_half = as<Scalar>(0.5)*r_one;
 
  194  const Scalar d_half = as<Scalar>(0.5)*d_one;
 
  197  if (!is_null(out_inout))
 
  198    out = Teuchos::rcpFromPtr(out_inout);
 
  205  OSTab tab2(out,1,
"THYRA");
 
  210  *out << endl << 
"*** Entering LinearOpTester<"<<ST::name()<<
","<<ST::name()<<
">::check(op,...) ...\n";
 
  211  if(show_all_tests()) {
 
  212    *out << endl << 
"describe op:\n" << Teuchos::describe(op,verbLevel);
 
  224  RCP< MultiVectorRandomizerBase<Scalar> >  rRand;
 
  226    rRand = rcpFromPtr(rangeRandomizer);
 
  228    rRand = universalMultiVectorRandomizer<Scalar>();
 
  229  RCP< MultiVectorRandomizerBase<Scalar> > dRand;
 
  230  if (!
is_null(domainRandomizer))
 
  231    dRand = rcpFromPtr(domainRandomizer);
 
  233    dRand = universalMultiVectorRandomizer<Scalar>();
 
  235  *out << endl << 
"Checking the domain and range spaces ... ";
 
  237  RCP<const VectorSpaceBase<Scalar> >  range  = op.
range();
 
  238  RCP<const VectorSpaceBase<Scalar> > domain = op.
domain();
 
  242    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  243    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  245    bool these_results = 
true;
 
  247    *testOut << endl << 
"op.domain().get() != NULL ? ";
 
  248    result = domain.get() != NULL;
 
  249    if(!result) these_results = 
false;
 
  250    *testOut << 
passfail(result) << endl;
 
  252    *testOut << endl << 
"op.range().get() != NULL ? ";
 
  253    result = range.get() != NULL;
 
  254    if(!result) these_results = 
false;
 
  255    *testOut << 
passfail(result) << endl;
 
  257    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  261  if( check_linear_properties() ) {
 
  263    *out << endl << 
"this->check_linear_properties()==true:" 
  264         << 
"Checking the linear properties of the forward linear operator ... ";
 
  266    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  267    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  269    bool these_results = 
true;
 
  276        << endl << 
"Checking that the forward operator is truly linear:\n" 
  277        << endl << 
"  0.5*op*(v1 + v2) == 0.5*op*v1 + 0.5*op*v2" 
  278        << endl << 
"          \\_____/         \\___/" 
  280        << endl << 
"  \\_____________/     \\___________________/" 
  283        << endl << 
"           sum(v4) == sum(v5)" 
  284        << endl << std::flush;
 
  286      for( 
int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
 
  288        *testOut << endl << 
"Random vector tests = " << rand_vec_i << endl;
 
  292        *testOut << endl << 
"v1 = randomize(-1,+1); ...\n" ;
 
  293        RCP<MultiVectorBase<Scalar> > v1 = createMembers(domain,loc_num_rhs);
 
  294        dRand->randomize(v1.ptr());
 
  295        if(dump_all()) *testOut << endl << 
"v1 =\n" << describe(*v1,verbLevel);
 
  297        *testOut << endl << 
"v2 = randomize(-1,+1); ...\n" ;
 
  298        RCP<MultiVectorBase<Scalar> > v2 = createMembers(domain,loc_num_rhs);
 
  299        dRand->randomize(v2.ptr());
 
  300        if(dump_all()) *testOut << endl << 
"v2 =\n" << describe(*v2,verbLevel);
 
  302        *testOut << endl << 
"v3 = v1 + v2 ...\n" ;
 
  303        RCP<MultiVectorBase<Scalar> > v3 = createMembers(domain,loc_num_rhs);
 
  304        V_VpV(v3.ptr(),*v1,*v2);
 
  305        if(dump_all()) *testOut << endl << 
"v3 =\n" << describe(*v3,verbLevel);
 
  307        *testOut << endl << 
"v4 = 0.5*op*v3 ...\n" ;
 
  308        RCP<MultiVectorBase<Scalar> > v4 = createMembers(range,loc_num_rhs);
 
  309        apply( op, 
NOTRANS, *v3, v4.ptr(), r_half );
 
  310        if(dump_all()) *testOut << endl << 
"v4 =\n" << describe(*v4,verbLevel);
 
  312        *testOut << endl << 
"v5 = op*v1 ...\n" ;
 
  313        RCP<MultiVectorBase<Scalar> > v5 = createMembers(range,loc_num_rhs);
 
  314        apply( op, 
NOTRANS, *v1, v5.ptr() );
 
  315        if(dump_all()) *testOut << endl << 
"v5 =\n" << describe(*v5,verbLevel);
 
  317        *testOut << endl << 
"v5 = 0.5*op*v2 + 0.5*v5 ...\n" ;
 
  318        apply( op, 
NOTRANS, *v2, v5.ptr(), r_half, r_half );
 
  319        if(dump_all()) *testOut << endl << 
"v5 =\n" << describe(*v5,verbLevel);
 
  321        Array<Scalar> sum_v4(loc_num_rhs), sum_v5(loc_num_rhs);
 
  325        result = testRelErrors<Scalar, Scalar, ScalarMag>(
 
  328          "linear_properties_error_tol()", linear_properties_error_tol(),
 
  329          "linear_properties_warning_tol()", linear_properties_warning_tol(),
 
  332        if(!result) these_results = 
false;
 
  337      *testOut << endl << 
"Forward operator not supported, skipping check!\n";
 
  340    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  344    *out << endl << 
"this->check_linear_properties()==false: Skipping the check of the linear properties of the forward operator!\n";
 
  347  if( check_linear_properties() && check_adjoint() ) {
 
  349    *out << endl << 
"(this->check_linear_properties()&&this->check_adjoint())==true:" 
  350         << 
" Checking the linear properties of the adjoint operator ... ";
 
  353    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  354    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  356    bool these_results = 
true;
 
  363        << endl << 
"Checking that the adjoint operator is truly linear:\n" 
  364        << endl << 
"  0.5*op'*(v1 + v2) == 0.5*op'*v1 + 0.5*op'*v2" 
  365        << endl << 
"           \\_____/         \\____/" 
  367        << endl << 
"  \\_______________/    \\_____________________/" 
  370        << endl << 
"           sum(v4) == sum(v5)" 
  371        << endl << std::flush;
 
  373      for( 
int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
 
  375        *testOut << endl << 
"Random vector tests = " << rand_vec_i << endl;
 
  379        *testOut << endl << 
"v1 = randomize(-1,+1); ...\n" ;
 
  380        RCP<MultiVectorBase<Scalar> > v1 = createMembers(range,loc_num_rhs);
 
  381        rRand->randomize(v1.ptr());
 
  382        if(dump_all()) *testOut << endl << 
"v1 =\n" << describe(*v1,verbLevel);
 
  384        *testOut << endl << 
"v2 = randomize(-1,+1); ...\n" ;
 
  385        RCP<MultiVectorBase<Scalar> > v2 = createMembers(range,loc_num_rhs);
 
  386        rRand->randomize(v2.ptr());
 
  387        if(dump_all()) *testOut << endl << 
"v2 =\n" << describe(*v2,verbLevel);
 
  389        *testOut << endl << 
"v3 = v1 + v2 ...\n" ;
 
  390        RCP<MultiVectorBase<Scalar> > v3 = createMembers(range,loc_num_rhs);
 
  391        V_VpV(v3.ptr(),*v1,*v2);
 
  392        if(dump_all()) *testOut << endl << 
"v3 =\n" << describe(*v3,verbLevel);
 
  394        *testOut << endl << 
"v4 = 0.5*op'*v3 ...\n" ;
 
  395        RCP<MultiVectorBase<Scalar> > v4 = createMembers(domain,loc_num_rhs);
 
  396        apply( op, 
CONJTRANS, *v3, v4.ptr(), d_half );
 
  397        if(dump_all()) *testOut << endl << 
"v4 =\n" << describe(*v4,verbLevel);
 
  399        *testOut << endl << 
"v5 = op'*v1 ...\n" ;
 
  400        RCP<MultiVectorBase<Scalar> > v5 = createMembers(domain,loc_num_rhs);
 
  402        if(dump_all()) *testOut << endl << 
"v5 =\n" << describe(*v5,verbLevel);
 
  404        *testOut << endl << 
"v5 = 0.5*op'*v2 + 0.5*v5 ...\n" ;
 
  405        apply( op, 
CONJTRANS, *v2, v5.ptr(), d_half, d_half );
 
  406        if(dump_all()) *testOut << endl << 
"v5 =\n" << describe(*v5,verbLevel);
 
  408        Array<Scalar> sum_v4(loc_num_rhs), sum_v5(loc_num_rhs);
 
  412        result = testRelErrors<Scalar, Scalar, ScalarMag>(
 
  415          "linear_properties_error_tol()", linear_properties_error_tol(),
 
  416          "linear_properties_warning_tol()", linear_properties_warning_tol(),
 
  419        if(!result) these_results = 
false;
 
  424      *testOut << endl << 
"Adjoint operator not supported, skipping check!\n";
 
  427    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  431    *out << endl << 
"(this->check_linear_properties()&&this->check_adjoint())==false: Skipping the check of the linear properties of the adjoint operator!\n";
 
  434  if( check_adjoint() ) {
 
  436    *out << endl << 
"this->check_adjoint()==true:" 
  437         << 
" Checking the agreement of the adjoint and forward operators ... ";
 
  439    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  440    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  442    bool these_results = 
true;
 
  449        << endl << 
"Checking that the adjoint agrees with the non-adjoint operator as:\n" 
  450        << endl << 
"  <0.5*op'*v2,v1> == <v2,0.5*op*v1>" 
  451        << endl << 
"   \\________/            \\_______/" 
  454        << endl << 
"         <v4,v1>  == <v2,v3>" 
  455        << endl << std::flush;
 
  457      for( 
int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
 
  459        *testOut << endl << 
"Random vector tests = " << rand_vec_i << endl;
 
  463        *testOut << endl << 
"v1 = randomize(-1,+1); ...\n" ;
 
  464        RCP<MultiVectorBase<Scalar> > v1 = createMembers(domain,loc_num_rhs);
 
  465        dRand->randomize(v1.ptr());
 
  466        if(dump_all()) *testOut << endl << 
"v1 =\n" << describe(*v1,verbLevel);
 
  468        *testOut << endl << 
"v2 = randomize(-1,+1); ...\n" ;
 
  469        RCP<MultiVectorBase<Scalar> > v2 = createMembers(range,loc_num_rhs);
 
  470        rRand->randomize(v2.ptr());
 
  471        if(dump_all()) *testOut << endl << 
"v2 =\n" << describe(*v2,verbLevel);
 
  473        *testOut << endl << 
"v3 = 0.5*op*v1 ...\n" ;
 
  474        RCP<MultiVectorBase<Scalar> > v3 = createMembers(range,loc_num_rhs);
 
  475        apply( op, 
NOTRANS, *v1, v3.ptr(), r_half );
 
  476        if(dump_all()) *testOut << endl << 
"v3 =\n" << describe(*v3,verbLevel);
 
  478        *testOut << endl << 
"v4 = 0.5*op'*v2 ...\n" ;
 
  479        RCP<MultiVectorBase<Scalar> > v4 = createMembers(domain,loc_num_rhs);
 
  480        apply( op, 
CONJTRANS, *v2, v4.ptr(), d_half );
 
  481        if(dump_all()) *testOut << endl << 
"v4 =\n" << describe(*v4,verbLevel);
 
  483        Array<Scalar> prod_v4_v1(loc_num_rhs);
 
  484        domain->scalarProds(*v4, *v1, prod_v4_v1());
 
  485        Array<Scalar> prod_v2_v3(loc_num_rhs);
 
  486        range->scalarProds(*v2, *v3, prod_v2_v3());
 
  488        result = testRelErrors<Scalar, Scalar, ScalarMag>(
 
  489          "<v4,v1>", prod_v4_v1(),
 
  490          "<v2,v3>", prod_v2_v3(),
 
  491          "adjoint_error_tol()", adjoint_error_tol(),
 
  492          "adjoint_warning_tol()", adjoint_warning_tol(),
 
  495        if(!result) these_results = 
false;
 
  500      *testOut << endl << 
"Adjoint operator not supported, skipping check!\n";
 
  503    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  507    *out << endl << 
"this->check_adjoint()==false:" 
  508         << 
" Skipping check for the agreement of the adjoint and forward operators!\n";
 
  512  if( check_for_symmetry() ) {
 
  514    *out << endl << 
"this->check_for_symmetry()==true: Performing check of symmetry ... ";
 
  516    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  517    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  519    bool these_results = 
true;
 
  521    SymmetricLinearOpTester<Scalar>::checkSymmetry(
 
  522      op, dRand.ptr(), *testOut, loc_num_rhs,num_random_vectors(), verbLevel,dump_all(),
 
  523      symmetry_error_tol(), symmetry_warning_tol(),
 
  524      outArg(these_results)
 
  527    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  531    *out << endl << 
"this->check_for_symmetry()==false: Skipping check of symmetry ...\n";
 
  535    *out << endl <<
"Congratulations, this LinearOpBase object seems to check out!\n";
 
  537    *out << endl <<
"Oh no, at least one of the tests performed with this LinearOpBase object failed (see above failures)!\n";
 
  538  *out << endl << 
"*** Leaving LinearOpTester<"<<ST::name()<<
","<<ST::name()<<
">::check(...)\n";
 
  545template<
class Scalar>
 
  547  const LinearOpBase<Scalar> &op,
 
  548  const Ptr<Teuchos::FancyOStream> &out
 
  552  return check(op, null, null, out);
 
  556template<
class Scalar>
 
  558  const LinearOpBase<Scalar> &op1,
 
  559  const LinearOpBase<Scalar> &op2,
 
  560  const Ptr<MultiVectorRandomizerBase<Scalar> > &domainRandomizer,
 
  561  const Ptr<Teuchos::FancyOStream> &out_arg
 
  566  using Teuchos::rcpFromPtr;
 
  567  using Teuchos::inoutArg;
 
  571  bool success = 
true, result;
 
  572  const int loc_num_rhs = this->num_rhs();
 
  573  const Scalar  r_half = Scalar(0.5)*ST::one();
 
  574  const RCP<FancyOStream> out = rcpFromPtr(out_arg);
 
  577  OSTab tab(out,1,
"THYRA");
 
  581      << endl << 
"*** Entering LinearOpTester<"<<ST::name()<<
","<<ST::name()<<
">::compare(op1,op2,...) ...\n";
 
  583      *out << endl << 
"describe op1:\n" << Teuchos::describe(op1,verbLevel);
 
  585      *out << endl << 
"describe op1: " << op1.description() << endl;
 
  587      *out << endl << 
"describe op2:\n" << Teuchos::describe(op2,verbLevel);
 
  589      *out << endl << 
"describe op2: " << op2.description() << endl;
 
  592  RCP<MultiVectorRandomizerBase<Scalar> > dRand;
 
  593  if (
nonnull(domainRandomizer)) dRand = rcpFromPtr(domainRandomizer);
 
  594  else dRand = universalMultiVectorRandomizer<Scalar>();
 
  596  RCP<const VectorSpaceBase<Scalar> >  range  = op1.range();
 
  597  RCP<const VectorSpaceBase<Scalar> > domain = op1.domain();
 
  599  if(out.get()) *out << endl << 
"Checking that range and domain spaces are compatible ... ";
 
  603    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  604    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  606    bool these_results = 
true;
 
  608    *testOut << endl << 
"op1.domain()->isCompatible(*op2.domain()) ? ";
 
  609    result = op1.domain()->isCompatible(*op2.domain());
 
  610    if(!result) these_results = 
false;
 
  611    *testOut << 
passfail(result) << endl;
 
  613    *testOut << endl << 
"op1.range()->isCompatible(*op2.range()) ? ";
 
  614    result = op1.range()->isCompatible(*op2.range());
 
  615    if(!result) these_results = 
false;
 
  616    *testOut << 
passfail(result) << endl;
 
  618    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  623    if(out.get()) *out << endl << 
"Skipping further checks since operators are not compatible!\n";
 
  627  if(out.get()) *out << endl << 
"Checking that op1 == op2 ... ";
 
  631    TestResultsPrinter testResultsPrinter(out, show_all_tests());
 
  632    const RCP<FancyOStream> testOut = testResultsPrinter.getTestOStream();
 
  634    bool these_results = 
true;
 
  637      << endl << 
"Checking that op1 and op2 produce the same results:\n" 
  638      << endl << 
"  0.5*op1*v1 == 0.5*op2*v1" 
  639      << endl << 
"  \\________/    \\________/" 
  642      << endl << 
"   norm(v2-v3) ~= 0" 
  644      << endl << std::flush;
 
  646    for( 
int rand_vec_i = 1; rand_vec_i <= num_random_vectors(); ++rand_vec_i ) {
 
  648      *testOut << endl << 
"Random vector tests = " << rand_vec_i << endl;
 
  652      if(dump_all()) *testOut << endl << 
"v1 = randomize(-1,+1); ...\n" ;
 
  653      RCP<MultiVectorBase<Scalar> > v1 = createMembers(domain,loc_num_rhs);
 
  654      dRand->randomize(v1.ptr());
 
  655      if(dump_all()) *testOut << endl << 
"v1 =\n" << *v1;
 
  657      if(dump_all()) *testOut << endl << 
"v2 = 0.5*op1*v1 ...\n" ;
 
  658      RCP<MultiVectorBase<Scalar> > v2 = createMembers(range,loc_num_rhs);
 
  659      apply( op1, 
NOTRANS, *v1, v2.ptr(), r_half );
 
  660      if(dump_all()) *testOut << endl << 
"v2 =\n" << *v2;
 
  662      if(dump_all()) *testOut << endl << 
"v3 = 0.5*op2*v1 ...\n" ;
 
  663      RCP<MultiVectorBase<Scalar> > v3 = createMembers(range,loc_num_rhs);
 
  664      apply( op2, 
NOTRANS, *v1, v3.ptr(), r_half );
 
  665      if(dump_all()) *testOut << endl << 
"v3 =\n" << *v3;
 
  668      for(
int col_id=0;col_id < v1->domain()->dim();col_id++) {
 
  669         std::stringstream ss;
 
  670         ss << 
".col[" << col_id << 
"]";
 
  673           "v2"+ss.str(),*v2->col(col_id),
 
  674           "v3"+ss.str(),*v3->col(col_id),
 
  675           "linear_properties_error_tol()", linear_properties_error_tol(),
 
  676           "linear_properties_warning_tol()", linear_properties_warning_tol(),
 
  678         if(!result) these_results = 
false;
 
  694      if(!result) these_results = 
false;
 
  698    testResultsPrinter.printTestResults(these_results, inoutArg(success));
 
  704      *out << endl <<
"Congratulations, these two LinearOpBase objects seem to be the same!\n";
 
  706      *out << endl <<
"Oh no, these two LinearOpBase objects seem to be different (see above failures)!\n";
 
  707    *out << endl << 
"*** Leaving LinearOpTester<"<<ST::name()<<
","<<ST::name()<<
">::compare(...)\n";
 
  715template<
class Scalar>
 
  717  const LinearOpBase<Scalar> &op1,
 
  718  const LinearOpBase<Scalar> &op2,
 
  719  const Ptr<Teuchos::FancyOStream> &out_arg
 
  730template<
class ScalarMag>
 
  732void setDefaultTol(
const ScalarMag &defaultDefaultTol,
 
  733    ScalarMag &defaultTol)
 
  735  typedef ScalarTraits<ScalarMag> SMT;
 
  736  if (defaultTol < SMT::zero()) {
 
  737    defaultTol = defaultDefaultTol;
 
  742template<
class Scalar>
 
  743void LinearOpTester<Scalar>::setDefaultTols()
 
  745  typedef ScalarTraits<ScalarMag> SMT;
 
  746  const ScalarMag defaultWarningTol = 1e+2 * SMT::eps();
 
  747  const ScalarMag defaultErrorTol = 1e+4 * SMT::eps();
 
  748  setDefaultTol(defaultWarningTol, linear_properties_warning_tol_);
 
  749  setDefaultTol(defaultErrorTol, linear_properties_error_tol_);
 
  750  setDefaultTol(defaultWarningTol, adjoint_warning_tol_);
 
  751  setDefaultTol(defaultErrorTol, adjoint_error_tol_);
 
  752  setDefaultTol(defaultWarningTol, symmetry_warning_tol_);
 
  753  setDefaultTol(defaultErrorTol, symmetry_error_tol_);
 
Base class for all linear operators.
 
virtual RCP< const VectorSpaceBase< Scalar > > range() const =0
Return a smart pointer for the range space for this operator.
 
virtual RCP< const VectorSpaceBase< Scalar > > domain() const =0
Return a smart pointer for the domain space for this operator.
 
bool opSupported(EOpTransp M_trans) const
Return if the M_trans operation of apply() is supported or not.
 
bool compare(const LinearOpBase< Scalar > &op1, const LinearOpBase< Scalar > &op2, const Ptr< MultiVectorRandomizerBase< Scalar > > &domainRandomizer, const Ptr< FancyOStream > &out_arg) const
Check if two linear operators are the same or not.
 
LinearOpTester()
Default constructor which sets default parameter values.
 
void set_all_warning_tol(const ScalarMag warning_tol)
Set all the warning tolerances to the same value.
 
void enable_all_tests(const bool enable_all_tests)
Enable or disable all tests.
 
void set_all_error_tol(const ScalarMag error_tol)
Set all the error tolerances to the same value.
 
Teuchos::ScalarTraits< Scalar >::magnitudeType ScalarMag
Local typedef for promoted scalar magnitude.
 
bool check(const LinearOpBase< Scalar > &op, const Ptr< MultiVectorRandomizerBase< Scalar > > &rangeRandomizer, const Ptr< MultiVectorRandomizerBase< Scalar > > &domainRandomizer, const Ptr< FancyOStream > &out) const
Check a linear operator.
 
Base interface for a strategy object for randomizing a multi-vector.
 
bool is_null(const std::shared_ptr< T > &p)
 
bool nonnull(const std::shared_ptr< T > &p)
 
const std::string passfail(const bool result)
 
bool testRelNormDiffErr(const std::string &v1_name, const VectorBase< Scalar > &v1, const std::string &v2_name, const VectorBase< Scalar > &v2, const std::string &maxRelErr_error_name, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType &maxRelErr_error, const std::string &maxRelErr_warning_name, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType &maxRelErr_warning, std::ostream *out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::VERB_LOW, const std::string &leadingIndent=std::string(""))
Compute, check and optionally print the relative errors in two vectors.
 
@ NOTRANS
Use the non-transposed operator.
 
@ CONJTRANS
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types).
 
TypeTo as(const TypeFrom &t)
 
T_To & dyn_cast(T_From &from)
 
basic_OSTab< char > OSTab
 
#define TEUCHOS_TEST_EQUALITY_CONST(v1, v2, out, success)
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)