void addMueLuToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder & builder,
                                  const std::string & stratName)
{
  TEUCHOS_TEST_FOR_EXCEPTION(builder.getValidParameters()->sublist("Preconditioner Types").isParameter(stratName),std::logic_error,
                             "MueLu::addMueLuToStratimikosBuilder cannot add \"" + stratName +"\" because it is already included in builder!");

  // use default constructor to add Teko::StratimikosFactory
  builder.setPreconditioningStrategyFactory(Teuchos::abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,Thyra::MueLuPreconditionerFactory>(),
                                            stratName);
}
Exemplo n.º 2
0
void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder & builder,
                               const Teuchos::RCP<Teko::RequestHandler> & rh,
                               const std::string & stratName)
{
   TEUCHOS_TEST_FOR_EXCEPTION(builder.getValidParameters()->sublist("Preconditioner Types").isParameter(stratName),std::logic_error,
                      "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +"\" because it is already included in builder!");

   // build an instance of a Teuchos::AbsractFactory<Thyra::PFB> so request handler is passed onto
   // the resulting StratimikosFactory
   Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder = Teuchos::rcp(new TekoFactoryBuilder(rh));
   builder.setPreconditioningStrategyFactory(tekoFactoryBuilder,stratName);
}
Exemplo n.º 3
0
TEUCHOS_UNIT_TEST(tStratimikosFactory, test_Defaults) 
{
  using Teuchos::RCP;
  using Teuchos::ParameterList;

  // build global (or serial communicator)
  #ifdef HAVE_MPI
     Epetra_MpiComm comm(MPI_COMM_WORLD);
  #else
     Epetra_SerialComm comm;
  #endif

  // build epetra operator
  RCP<Epetra_Operator> eA = buildSystem(comm,5);
  RCP<Thyra::LinearOpBase<double> > tA = Thyra::nonconstEpetraLinearOp(eA);

  // build stratimikos factory, adding Teko's version
  Stratimikos::DefaultLinearSolverBuilder stratFactory;
  stratFactory.setPreconditioningStrategyFactory(
        Teuchos::abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,Teko::StratimikosFactory>(),
        "Teko");
  RCP<const ParameterList> validParams = stratFactory.getValidParameters();
  stratFactory.setParameterList(Teuchos::rcp(new Teuchos::ParameterList(*validParams)));

  // print out Teko's parameter list and fail if it doesn't exist!
  TEST_NOTHROW(validParams->sublist("Preconditioner Types").sublist("Teko").print(out,
        ParameterList::PrintOptions().showDoc(true).indent(2).showTypes(true)));

  // build teko preconditioner factory
  RCP<Thyra::PreconditionerFactoryBase<double> > precFactory
        = stratFactory.createPreconditioningStrategy("Teko");

  // make sure factory is built
  TEST_ASSERT(precFactory!=Teuchos::null);

  // build preconditioner
  RCP<Thyra::PreconditionerBase<double> > prec = Thyra::prec<double>(*precFactory,tA);
  TEST_ASSERT(prec!=Teuchos::null);

  // build an operator to test against
  RCP<const Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
  RCP<const Teko::InverseFactory> invFact = invLib->getInverseFactory("Amesos");
  Teko::LinearOp testOp = Teko::buildInverse(*invFact,tA);

  Teko::LinearOp precOp = prec->getUnspecifiedPrecOp();
  TEST_ASSERT(precOp!=Teuchos::null);

  Thyra::LinearOpTester<double> tester;
  tester.show_all_tests(true);
  tester.set_all_error_tol(0);
  TEST_ASSERT(tester.compare(*precOp,*testOp,Teuchos::ptrFromRef(out)));
}
void Piro::RythmosSolver<Scalar>::initialize(
#endif
    const Teuchos::RCP<Teuchos::ParameterList> &appParams,
    const Teuchos::RCP< Thyra::ModelEvaluator<Scalar> > &in_model,
    const Teuchos::RCP<Rythmos::IntegrationObserverBase<Scalar> > &observer)
{

    using Teuchos::ParameterList;
    using Teuchos::parameterList;
    using Teuchos::RCP;
    using Teuchos::rcp;

    // set some internals
    model = in_model;
    num_p = in_model->Np();
    num_g = in_model->Ng();

    //
    *out << "\nA) Get the base parameter list ...\n";
    //


    if (appParams->isSublist("Rythmos")) {
        RCP<Teuchos::ParameterList> rythmosPL = sublist(appParams, "Rythmos", true);
        rythmosPL->validateParameters(*getValidRythmosParameters(),0);

        {
            const std::string verbosity = rythmosPL->get("Verbosity Level", "VERB_DEFAULT");
            if      (verbosity == "VERB_NONE")    solnVerbLevel = Teuchos::VERB_NONE;
            else if (verbosity == "VERB_DEFAULT") solnVerbLevel = Teuchos::VERB_DEFAULT;
            else if (verbosity == "VERB_LOW")     solnVerbLevel = Teuchos::VERB_LOW;
            else if (verbosity == "VERB_MEDIUM")  solnVerbLevel = Teuchos::VERB_MEDIUM;
            else if (verbosity == "VERB_HIGH")    solnVerbLevel = Teuchos::VERB_HIGH;
            else if (verbosity == "VERB_EXTREME") solnVerbLevel = Teuchos::VERB_EXTREME;
            else TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,"Unknown verbosity option specified in Piro_RythmosSolver.");
        }

        t_initial = rythmosPL->get("Initial Time", 0.0);
        t_final = rythmosPL->get("Final Time", 0.1);

        const std::string stepperType = rythmosPL->get("Stepper Type", "Backward Euler");

        //
        *out << "\nC) Create and initalize the forward model ...\n";
        //

        *out << "\nD) Create the stepper and integrator for the forward problem ...\n";
        //

        if (rythmosPL->get<std::string>("Nonlinear Solver Type") == "Rythmos") {
            Teuchos::RCP<Rythmos::TimeStepNonlinearSolver<Scalar> > rythmosTimeStepSolver =
                Rythmos::timeStepNonlinearSolver<Scalar>();
            if (rythmosPL->getEntryPtr("NonLinear Solver")) {
                RCP<Teuchos::ParameterList> nonlinePL =
                    sublist(rythmosPL, "NonLinear Solver", true);
                rythmosTimeStepSolver->setParameterList(nonlinePL);
            }
            fwdTimeStepSolver = rythmosTimeStepSolver;
        }
        else if (rythmosPL->get<std::string>("Nonlinear Solver Type") == "NOX") {
#ifdef HAVE_PIRO_NOX
            Teuchos::RCP<Thyra::NOXNonlinearSolver> nox_solver =  Teuchos::rcp(new Thyra::NOXNonlinearSolver);
            Teuchos::RCP<Teuchos::ParameterList> nox_params = Teuchos::rcp(new Teuchos::ParameterList);
            *nox_params = appParams->sublist("NOX");
            nox_solver->setParameterList(nox_params);
            fwdTimeStepSolver = nox_solver;
#else
            TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,"Requested NOX solver for a Rythmos Transient solve, Trilinos was not built with NOX enabled.  Please rebuild Trilinos or use the native Rythmos nonlinear solver.");
#endif

        }

        if (stepperType == "Backward Euler") {
            fwdStateStepper = Rythmos::backwardEulerStepper<Scalar> (model, fwdTimeStepSolver);
            fwdStateStepper->setParameterList(sublist(rythmosPL, "Rythmos Stepper", true));
        }
        else if (stepperType == "Forward Euler") {
            fwdStateStepper = Rythmos::forwardEulerStepper<Scalar> (model);
            fwdStateStepper->setParameterList(sublist(rythmosPL, "Rythmos Stepper", true));
        }
        else if (stepperType == "Explicit RK") {
            fwdStateStepper = Rythmos::explicitRKStepper<Scalar>(model);
            fwdStateStepper->setParameterList(sublist(rythmosPL, "Rythmos Stepper", true));
        }
        else if (stepperType == "BDF") {
            Teuchos::RCP<Teuchos::ParameterList> BDFparams =
                Teuchos::sublist(rythmosPL, "Rythmos Stepper", true);
            Teuchos::RCP<Teuchos::ParameterList> BDFStepControlPL =
                Teuchos::sublist(BDFparams,"Step Control Settings");

            fwdStateStepper = Teuchos::rcp( new Rythmos::ImplicitBDFStepper<Scalar>(model,fwdTimeStepSolver,BDFparams) );
            fwdStateStepper->setInitialCondition(model->getNominalValues());

        }
        else {
            // first (before failing) check to see if the user has added stepper factory
            typename std::map<std::string,Teuchos::RCP<Piro::RythmosStepperFactory<Scalar> > >::const_iterator
            stepFactItr = stepperFactories.find(stepperType);
            if(stepFactItr!=stepperFactories.end()) {
                // the user has added it, hot dog lets build a new stepper!
                Teuchos::RCP<Teuchos::ParameterList> stepperParams = Teuchos::sublist(rythmosPL, "Rythmos Stepper", true);

                // build the stepper using the factory
                fwdStateStepper = stepFactItr->second->buildStepper(model,fwdTimeStepSolver,stepperParams);

                // the user decided to override the model being used (let them)
                if(fwdStateStepper->getModel()!=model && fwdStateStepper->getModel()!=Teuchos::null) {
                    model = Teuchos::rcp_const_cast<Thyra::ModelEvaluator<Scalar> >(fwdStateStepper->getModel());

                    num_p = in_model->Np();
                    num_g = in_model->Ng();
                }
            }
            else {
                TEUCHOS_TEST_FOR_EXCEPTION(
                    true, Teuchos::Exceptions::InvalidParameter,
                    std::endl << "Error! Piro::RythmosSolver: Invalid Steper Type: "
                    << stepperType << std::endl);
            }
        }

        // Step control strategy
        {
            // If the stepper can accept a step control strategy, then attempt to build one.
            RCP<Rythmos::StepControlStrategyAcceptingStepperBase<Scalar> > scsa_stepper =
                Teuchos::rcp_dynamic_cast<Rythmos::StepControlStrategyAcceptingStepperBase<Scalar> >(fwdStateStepper);

            if (Teuchos::nonnull(scsa_stepper)) {
                const std::string step_control_strategy = rythmosPL->get("Step Control Strategy Type", "None");

                if (step_control_strategy == "None") {
                    // don't do anything, stepper will build default
                } else if (step_control_strategy == "ImplicitBDFRamping") {

                    const RCP<Rythmos::ImplicitBDFStepperRampingStepControl<Scalar> > rscs =
                        rcp(new Rythmos::ImplicitBDFStepperRampingStepControl<Scalar>);

                    const RCP<ParameterList> p = parameterList(rythmosPL->sublist("Rythmos Step Control Strategy"));
                    rscs->setParameterList(p);

                    scsa_stepper->setStepControlStrategy(rscs);
                }
                else {
                    // first (before failing) check to see if the user has added step control factory
                    typename std::map<std::string,Teuchos::RCP<Piro::RythmosStepControlFactory<Scalar> > >::const_iterator
                    stepControlFactItr = stepControlFactories.find(step_control_strategy);
                    if (stepControlFactItr != stepControlFactories.end())
                    {

                        const RCP<Rythmos::StepControlStrategyBase<Scalar> > rscs = stepControlFactItr->second->buildStepControl();

                        const RCP<ParameterList> p = parameterList(rythmosPL -> sublist("Rythmos Step Control Strategy"));

                        rscs->setParameterList(p);

                        scsa_stepper->setStepControlStrategy(rscs);
                    }
                    else {
                        TEUCHOS_TEST_FOR_EXCEPTION(
                            true, std::logic_error,
                            "Error! Piro::RythmosSolver: Invalid step control strategy type: "
                            << step_control_strategy << std::endl);
                    }
                }
            }
        }
        {
            const RCP<Teuchos::ParameterList> integrationControlPL =
                Teuchos::sublist(rythmosPL, "Rythmos Integration Control", true);

            RCP<Rythmos::DefaultIntegrator<Scalar> > defaultIntegrator;
            if (rythmosPL->get("Rythmos Integration Control Strategy", "Simple") == "Simple") {
                defaultIntegrator = Rythmos::controlledDefaultIntegrator<Scalar>(Rythmos::simpleIntegrationControlStrategy<Scalar>(integrationControlPL));
            }
            else if(rythmosPL->get<std::string>("Rythmos Integration Control Strategy") == "Ramping") {
                defaultIntegrator = Rythmos::controlledDefaultIntegrator<Scalar>(Rythmos::rampingIntegrationControlStrategy<Scalar>(integrationControlPL));
            }
            fwdStateIntegrator = defaultIntegrator;
        }

        fwdStateIntegrator->setParameterList(sublist(rythmosPL, "Rythmos Integrator", true));

        if (Teuchos::nonnull(observer)) {
            fwdStateIntegrator->setIntegrationObserver(observer);
        }
    }

    else if (appParams->isSublist("Rythmos Solver")) {
        /** New parameter list format **/
        RCP<Teuchos::ParameterList> rythmosSolverPL = sublist(appParams, "Rythmos Solver", true);
        RCP<Teuchos::ParameterList> rythmosPL = sublist(rythmosSolverPL, "Rythmos", true);

        {
            const std::string verbosity = rythmosSolverPL->get("Verbosity Level", "VERB_DEFAULT");
            if      (verbosity == "VERB_NONE")    solnVerbLevel = Teuchos::VERB_NONE;
            else if (verbosity == "VERB_DEFAULT") solnVerbLevel = Teuchos::VERB_DEFAULT;
            else if (verbosity == "VERB_LOW")     solnVerbLevel = Teuchos::VERB_LOW;
            else if (verbosity == "VERB_MEDIUM")  solnVerbLevel = Teuchos::VERB_MEDIUM;
            else if (verbosity == "VERB_HIGH")    solnVerbLevel = Teuchos::VERB_HIGH;
            else if (verbosity == "VERB_EXTREME") solnVerbLevel = Teuchos::VERB_EXTREME;
            else TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
                                                "Unknown verbosity option specified in Piro_RythmosSolver.");
        }

        t_initial = rythmosPL->sublist("Integrator Settings").get("Initial Time", 0.0);
        t_final = rythmosPL->sublist("Integrator Settings").get("Final Time", 0.1);

        const std::string stepperType = rythmosPL->sublist("Stepper Settings")
                                        .sublist("Stepper Selection").get("Stepper Type", "Backward Euler");
        //
        //    *out << "\nB) Create the Stratimikos linear solver factory ...\n";
        //
        // This is the linear solve strategy that will be used to solve for the
        // linear system with the W.
        //
        Stratimikos::DefaultLinearSolverBuilder linearSolverBuilder;

#ifdef HAVE_PIRO_IFPACK2
        typedef Thyra::PreconditionerFactoryBase<double> Base;
#ifdef ALBANY_BUILD
        typedef Thyra::Ifpack2PreconditionerFactory<Tpetra::CrsMatrix<double, LocalOrdinal, GlobalOrdinal, Node> > Impl;
#else
        typedef Thyra::Ifpack2PreconditionerFactory<Tpetra::CrsMatrix<double> > Impl;
#endif
        linearSolverBuilder.setPreconditioningStrategyFactory(Teuchos::abstractFactoryStd<Base, Impl>(), "Ifpack2");
#endif
#ifdef HAVE_PIRO_MUELU
#ifdef ALBANY_BUILD
        Stratimikos::enableMueLu<LocalOrdinal, GlobalOrdinal, Node>(linearSolverBuilder);
#else
        Stratimikos::enableMueLu(linearSolverBuilder);
#endif
#endif

        linearSolverBuilder.setParameterList(sublist(rythmosSolverPL, "Stratimikos", true));
        rythmosSolverPL->validateParameters(*getValidRythmosSolverParameters(),0);
        RCP<Thyra::LinearOpWithSolveFactoryBase<double> > lowsFactory =
            createLinearSolveStrategy(linearSolverBuilder);
        //
        *out << "\nC) Create and initalize the forward model ...\n";
        //
        // C.1) Create the underlying EpetraExt::ModelEvaluator
        // already constructed as "model". Decorate if needed.
        // TODO: Generelize to any explicit method, option to invert mass matrix
        if (stepperType == "Explicit RK") {
            if (rythmosSolverPL->get("Invert Mass Matrix", false)) {
                Teuchos::RCP<Thyra::ModelEvaluator<Scalar> > origModel = model;
                rythmosSolverPL->get("Lump Mass Matrix", false);  //JF line does not do anything
                model = Teuchos::rcp(new Piro::InvertMassMatrixDecorator<Scalar>(
                                         sublist(rythmosSolverPL,"Stratimikos", true), origModel,
                                         true,rythmosSolverPL->get("Lump Mass Matrix", false),false));
            }
        }
        // C.2) Create the Thyra-wrapped ModelEvaluator

        thyraModel = rcp(new Thyra::DefaultModelEvaluatorWithSolveFactory<Scalar>(model, lowsFactory));

        const RCP<const Thyra::VectorSpaceBase<double> > x_space =
            thyraModel->get_x_space();

        //
        *out << "\nD) Create the stepper and integrator for the forward problem ...\n";
        //
        fwdTimeStepSolver = Rythmos::timeStepNonlinearSolver<double>();

        if (rythmosSolverPL->getEntryPtr("NonLinear Solver")) {
            const RCP<Teuchos::ParameterList> nonlinePL =
                sublist(rythmosSolverPL, "NonLinear Solver", true);
            fwdTimeStepSolver->setParameterList(nonlinePL);
        }
        // Force Default Integrator since this is needed for Observers
        rythmosPL->sublist("Integrator Settings").sublist("Integrator Selection").
        set("Integrator Type","Default Integrator");

        RCP<Rythmos::IntegratorBuilder<double> > ib = Rythmos::integratorBuilder<double>();
        ib->setParameterList(rythmosPL);
        Thyra::ModelEvaluatorBase::InArgs<double> ic = thyraModel->getNominalValues();
        RCP<Rythmos::IntegratorBase<double> > integrator = ib->create(thyraModel,ic,fwdTimeStepSolver);
        fwdStateIntegrator = Teuchos::rcp_dynamic_cast<Rythmos::DefaultIntegrator<double> >(integrator,true);

        fwdStateStepper = fwdStateIntegrator->getNonconstStepper();

        if (Teuchos::nonnull(observer))
            fwdStateIntegrator->setIntegrationObserver(observer);

    }
    else {
        TEUCHOS_TEST_FOR_EXCEPTION(
            appParams->isSublist("Rythmos") || appParams->isSublist("Rythmos Solver"),
            Teuchos::Exceptions::InvalidParameter, std::endl <<
            "Error! Piro::RythmosSolver: must have either Rythmos or Rythmos Solver sublist ");

    }

    isInitialized = true;
}
Exemplo n.º 5
0
TEUCHOS_UNIT_TEST(tStratimikosFactory, test_multi_use) 
{
  using Teuchos::RCP;
  using Teuchos::ParameterList;

  // build global (or serial communicator)
  #ifdef HAVE_MPI
     Epetra_MpiComm comm(MPI_COMM_WORLD);
  #else
     Epetra_SerialComm comm;
  #endif

  // build epetra operator
  RCP<Epetra_Operator> eA = buildSystem(comm,5);
  RCP<Thyra::LinearOpBase<double> > tA = Thyra::nonconstEpetraLinearOp(eA);

  // build stratimikos factory, adding Teko's version
  Stratimikos::DefaultLinearSolverBuilder stratFactory;
  stratFactory.setPreconditioningStrategyFactory(
        Teuchos::abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,Teko::StratimikosFactory>(),
        "Teko");
  RCP<const ParameterList> validParams = stratFactory.getValidParameters();
  stratFactory.setParameterList(Teuchos::rcp(new Teuchos::ParameterList(*validParams)));

  // print out Teko's parameter list and fail if it doesn't exist!
  TEST_NOTHROW(validParams->sublist("Preconditioner Types").sublist("Teko").print(out,
        ParameterList::PrintOptions().showDoc(true).indent(2).showTypes(true)));

  // build teko preconditioner factory
  RCP<Thyra::PreconditionerFactoryBase<double> > precFactory
        = stratFactory.createPreconditioningStrategy("Teko");

  // make sure factory is built
  TEST_ASSERT(precFactory!=Teuchos::null);

  // try using a different preconditioner each time
  RCP<Thyra::PreconditionerBase<double> > prec;
  for(int i=0;i<2;i++) {
     prec = precFactory->createPrec();
     
     RCP<const Thyra::LinearOpSourceBase<double> > losb 
        = rcp(new Thyra::DefaultLinearOpSource<double>(tA));

     precFactory->initializePrec(losb,prec.get());

     RCP<Teko::StratimikosFactory> stratFact =
             rcp_dynamic_cast<Teko::StratimikosFactory>(precFactory);
     const std::vector<int> & decomp = stratFact->getDecomposition();

     TEST_EQUALITY(decomp.size(),1);
     TEST_EQUALITY(decomp[0],1);
  }

  // try using a single preconditioner multiple times
  prec = precFactory->createPrec();
  for(int i=0;i<2;i++) {
     RCP<const Thyra::LinearOpSourceBase<double> > losb 
        = rcp(new Thyra::DefaultLinearOpSource<double>(tA));

     precFactory->initializePrec(losb,prec.get());

     RCP<Teko::StratimikosFactory> stratFact =
             rcp_dynamic_cast<Teko::StratimikosFactory>(precFactory);
     const std::vector<int> & decomp = stratFact->getDecomposition();

     TEST_EQUALITY(decomp.size(),1);
     TEST_EQUALITY(decomp[0],1);
  }

}
Exemplo n.º 6
0
TEUCHOS_UNIT_TEST(tStratimikosFactory, test_BlockGaussSeidel) 
{
  using Teuchos::RCP;
  using Teuchos::ParameterList;

  // build global (or serial communicator)
  #ifdef HAVE_MPI
     Epetra_MpiComm comm(MPI_COMM_WORLD);
  #else
     Epetra_SerialComm comm;
  #endif

  // build epetra operator
  RCP<Epetra_Operator> eA = buildStridedSystem(comm,5);
  RCP<Thyra::LinearOpBase<double> > tA = Thyra::nonconstEpetraLinearOp(eA);

  // build stratimikos factory, adding Teko's version
  Stratimikos::DefaultLinearSolverBuilder stratFactory;
  stratFactory.setPreconditioningStrategyFactory(
        Teuchos::abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,Teko::StratimikosFactory>(),
        "Teko");
  RCP<ParameterList> params = Teuchos::rcp(new ParameterList(*stratFactory.getValidParameters()));
  ParameterList & tekoList = params->sublist("Preconditioner Types").sublist("Teko");
  tekoList.set("Write Block Operator", false);
  tekoList.set("Test Block Operator", false);
  tekoList.set("Strided Blocking","1 1");
  tekoList.set("Inverse Type","BGS");
  ParameterList & ifl = tekoList.sublist("Inverse Factory Library");
  ifl.sublist("BGS").set("Type","Block Gauss-Seidel");
  ifl.sublist("BGS").set("Inverse Type","Amesos");

  // RCP<Thyra::PreconditionerFactoryBase<double> > precFactory
  //       = stratFactory.createPreconditioningStrategy("Teko");

  // build operator to test against
  Teko::LinearOp testOp;
  {
     Teuchos::ParameterList iflCopy(ifl);
     RCP<Epetra_Operator> strided_eA = Teuchos::rcp(new Teko::Epetra::StridedEpetraOperator(2,eA));
     RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromParameterList(iflCopy);
     RCP<const Teko::InverseFactory> invFact = invLib->getInverseFactory("BGS");
     RCP<Teko::Epetra::InverseFactoryOperator> invFactOp = Teuchos::rcp(new Teko::Epetra::InverseFactoryOperator(invFact));
     invFactOp->buildInverseOperator(strided_eA);

     testOp = Thyra::epetraLinearOp(invFactOp,Thyra::NOTRANS,Thyra::EPETRA_OP_APPLY_APPLY_INVERSE);
  }

  stratFactory.setParameterList(params);
  RCP<Thyra::PreconditionerFactoryBase<double> > precFactory
        = stratFactory.createPreconditioningStrategy("Teko");

  // build teko preconditioner factory
  RCP<Thyra::PreconditionerBase<double> > prec = Thyra::prec<double>(*precFactory,tA);
  Teko::LinearOp precOp = prec->getUnspecifiedPrecOp();
  TEST_ASSERT(precOp!=Teuchos::null);

  Thyra::LinearOpTester<double> tester;
  tester.show_all_tests(true);
  tester.set_all_error_tol(0);
  TEST_ASSERT(tester.compare(*precOp,*testOp,Teuchos::ptrFromRef(out)));
}