TEUCHOS_UNIT_TEST(tIterativePreconditionerFactory, inverse_test)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp  A = build2x2(Comm,1,2,3,4);
   RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
   RCP<Teko::InverseFactory> invFact = invLib->getInverseFactory("Amesos");
   Teko::LinearOp iP = Teko::buildInverse(*invFact,A);

   Thyra::LinearOpTester<double> tester;
   tester.dump_all(true);
   tester.show_all_tests(true);

   {
      RCP<Teko::InverseFactory> precOpFact = rcp(new Teko::StaticOpInverseFactory(iP));
      RCP<Teko::IterativePreconditionerFactory> precFact = rcp(new Teko::IterativePreconditionerFactory(9,precOpFact));
      RCP<Teko::InverseFactory> invFact = rcp(new Teko::PreconditionerInverseFactory(precFact,Teuchos::null));

      Teko::LinearOp prec = Teko::buildInverse(*invFact,A);

      const bool result = tester.compare( *prec, *iP, Teuchos::ptrFromRef(out));
      if (!result) {
         out << "Apply 0: FAILURE" << std::endl;
         success = false;
      }
      else
         out << "Apply 0: SUCCESS" << std::endl;
   }
}
Exemple #2
0
bool tLumping::test_invLumping(int verbosity,std::ostream & os)
{
   bool status = false;
   bool allPassed = true;

   Thyra::LinearOpTester<double> tester;
   tester.show_all_tests(true);
   tester.set_all_error_tol(tolerance_);

   Epetra_Map map(100,0,*GetComm());

   // A matrix...to be lumped
   Epetra_CrsMatrix A(Copy,map,5,false);
   int indices[5];
   double values[5] = {1,2,3,4,5};
   for(int i=0;i<A.NumMyRows()-5;i++) {
      int index = A.RowMap().GID(i);
      for(int j=0;j<5;j++)
         indices[j] = A.RowMap().GID(i+j);
      A.InsertGlobalValues(index,5,values,indices);
   }
   for(int i=A.NumMyRows()-5;i<A.NumMyRows();i++) {
      int index = A.RowMap().GID(i);
      for(int j=0;j<5;j++)
         indices[j] = A.RowMap().GID(j);
      A.InsertGlobalValues(index,5,values,indices);
   }
   A.FillComplete();

   // B matrix...already lumped
   Epetra_CrsMatrix B(Copy,map,1,true);
   double number = 1.0/15.0;
   for(int i=0;i<B.NumMyRows();i++) {
      int index = B.RowMap().GID(i);
      B.InsertGlobalValues(index,1,&number,&index);
   }
   B.FillComplete();

   Teko::LinearOp pA = Thyra::epetraLinearOp(rcpFromRef(A));
   Teko::LinearOp pB = Thyra::epetraLinearOp(rcpFromRef(B));
   Teko::LinearOp lumpedA = getInvLumpedMatrix(pA);

   {
      std::stringstream ss;
      Teuchos::FancyOStream fos(rcpFromRef(ss),"      |||");
      const bool result = tester.compare( *pB, *lumpedA, Teuchos::ptrFromRef(fos) );
      TEST_ASSERT(result,
             std::endl << "   tLummping::test_invLumping "
             << ": Testing basic inv lumping functionality");
      if(not result || verbosity>=10)
         os << ss.str();
   }

   return allPassed;
}
TEUCHOS_UNIT_TEST(tLU2x2InverseOp, exact_test_tpetra)
{
   Kokkos::initialize();

   // build global (or serial communicator)
   RCP<const Teuchos::Comm<int> > Comm = Tpetra::DefaultPlatform::getDefaultPlatform ().getComm ();

   Teko::LinearOp  A_00 = build2x2(Comm,1,2,3,4);
   Teko::LinearOp  A_01 = build2x2(Comm,5,6,7,8);
   Teko::LinearOp  A_02 = build2x2(Comm,9,10,11,12);
   Teko::LinearOp  A_10 = build2x2(Comm,9,10,11,12);
   Teko::LinearOp  A_11 = build2x2(Comm,-13,-14,-15,-16);
   Teko::LinearOp  A_12 = build2x2(Comm,-1,-4,-5,-6);
   Teko::LinearOp  A_20 = build2x2(Comm,-9,-10,-11,-12);
   Teko::LinearOp  A_21 = build2x2(Comm,13,14,15,16);
   Teko::LinearOp  A_22 = build2x2(Comm,1,4,5,6);
   Teko::BlockedLinearOp A = Teko::createBlockedOp();
   Teko::beginBlockFill(A,3,3);
      Teko::setBlock(0,0,A,A_00);
      Teko::setBlock(0,1,A,A_01);
      Teko::setBlock(0,2,A,A_02);

      Teko::setBlock(1,0,A,A_10);
      Teko::setBlock(1,1,A,A_11);
      Teko::setBlock(1,2,A,A_12);

      Teko::setBlock(2,0,A,A_20);
      Teko::setBlock(2,1,A,A_21);
      Teko::setBlock(2,2,A,A_22);
   Teko::endBlockFill(A);

   std::string reorderType = "[ [0 1] 2]";
   Teuchos::RCP<const Teko::BlockReorderManager> brm = Teko::blockedReorderFromString(reorderType);
   Teko::ModifiableLinearOp re_A = Teuchos::rcp_const_cast<Thyra::LinearOpBase<double> >(Teko::buildReorderedLinearOp(*brm,A));
   Teko::ModifiableLinearOp final_A = Teuchos::rcp(new Teko::ReorderedLinearOp(brm,re_A));

   Thyra::LinearOpTester<double> tester;
   tester.dump_all(true);
   tester.show_all_tests(true);

   {
      const bool result = tester.compare( *final_A, *A, Teuchos::ptrFromRef(out));
      if (!result) {
         out << "Apply: FAILURE" << std::endl;
         success = false;
      }
      else
         out << "Apply: SUCCESS" << std::endl;
   }

   Kokkos::finalize();
}
TEUCHOS_UNIT_TEST(tIterativePreconditionerFactory, constructor_test)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp  A = build2x2(Comm,1,2,3,4);
   Teko::LinearOp iP = build2x2(Comm,1.0,0.0,0.0,1.0/4.0);
   Teko::LinearOp ImAiP = build2x2(Comm,0.0,-0.5,-3.0,0.0);
   Teko::LinearOp I = Thyra::identity(ImAiP->range());

   Thyra::LinearOpTester<double> tester;
   tester.show_all_tests(true);

   {
      RCP<Teko::InverseFactory> precOpFact = rcp(new Teko::StaticOpInverseFactory(iP));
      RCP<Teko::IterativePreconditionerFactory> precFact = rcp(new Teko::IterativePreconditionerFactory(0,precOpFact));
      RCP<Teko::InverseFactory> invFact = rcp(new Teko::PreconditionerInverseFactory(precFact,Teuchos::null));

      Teko::LinearOp prec = Teko::buildInverse(*invFact,A);

      const bool result = tester.compare( *prec, *iP, Teuchos::ptrFromRef(out));
      if (!result) {
         out << "Apply 0: FAILURE" << std::endl;
         success = false;
      }
      else
         out << "Apply 0: SUCCESS" << std::endl;
   }

   {
      using Teko::multiply;

      RCP<Teko::InverseFactory> precOpFact = rcp(new Teko::StaticOpInverseFactory(iP));
      RCP<Teko::IterativePreconditionerFactory> precFact = rcp(new Teko::IterativePreconditionerFactory(2,precOpFact));
      RCP<Teko::InverseFactory> invFact = rcp(new Teko::PreconditionerInverseFactory(precFact,Teuchos::null));

      Teko::LinearOp prec = Teko::buildInverse(*invFact,A);
      Teko::LinearOp exact = Teko::multiply(iP,Teko::add(I,Teko::multiply(Teko::add(I,ImAiP),ImAiP))); // iP*(I+(I+X)*X)

      const bool result = tester.compare( *prec, *exact, Teuchos::ptrFromRef(out));
      if (!result) {
         out << "Apply 2: FAILURE" << std::endl;
         success = false;
      }
      else
         out << "Apply 2: SUCCESS" << std::endl;
   }
}
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)));
}
TEUCHOS_UNIT_TEST(tLU2x2InverseOp, exact_test)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp  A_00 = build2x2(Comm,1,2,3,4);
   Teko::LinearOp  A_01 = build2x2(Comm,5,6,7,8);
   Teko::LinearOp  A_10 = build2x2(Comm,9,10,11,12);
   Teko::LinearOp  A_11 = build2x2(Comm,-13,-14,-15,-16);
   Teko::BlockedLinearOp A = Teko::toBlockedLinearOp(Thyra::block2x2(A_00,A_01,A_10,A_11));

   Teko::LinearOp  S = build2x2(Comm,26.000000000000000, 28.000000000000004, 30.000000000000000, 32.000000000000000);

   Teko::LinearOp iA_00 = build2x2(Comm,-1.000000000000000,  0.500000000000000,  0.749999999999998, -0.249999999999998);
   Teko::LinearOp iA_01 = build2x2(Comm,-3.000000000000004,  2.500000000000003,  2.750000000000008, -2.250000000000007);
   Teko::LinearOp iA_10 = build2x2(Comm,-1.999999999999999,  1.499999999999999,  1.749999999999999, -1.249999999999999);
   Teko::LinearOp iA_11 = build2x2(Comm, 4.000000000000001, -3.500000000000001, -3.750000000000001,  3.250000000000001);
   Teko::LinearOp iA = Thyra::block2x2(iA_00,iA_01,iA_10,iA_11);

   Thyra::LinearOpTester<double> tester;
   tester.dump_all(true);
   tester.show_all_tests(true);

   {
      RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
      RCP<Teko::InverseFactory> invFact = invLib->getInverseFactory("Amesos");

      Teko::LinearOp invA_00 = Teko::buildInverse(*invFact,A_00);
      Teko::LinearOp invS    = Teko::buildInverse(*invFact,S);

      Teko::LinearOp invA = Teko::createLU2x2InverseOp(A,invA_00,invA_00,invS,"Approximation");
      
      const bool result = tester.compare( *invA, *iA, &out);
      if (!result) {
         out << "Apply: FAILURE" << std::endl;
         success = false;
      }
      else
         out << "Apply: SUCCESS" << std::endl;
   }
}
TEUCHOS_UNIT_TEST(tProbingFactory, invlib_constr)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp lo = buildSystem(Comm,10);

   Teuchos::ParameterList subList;
   subList.set("Type","Probing Preconditioner");
   subList.set("Inverse Type","Amesos");
   subList.set("Probing Graph Operator",lo);

   Teuchos::ParameterList pl;
   pl.set("Prober",subList);
   
   
   Teuchos::RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromParameterList(pl);
   Teuchos::RCP<Teko::InverseFactory> proberFactory = invLib->getInverseFactory("Prober");
   Teuchos::RCP<Teko::InverseFactory> directSolveFactory = invLib->getInverseFactory("Amesos");

   {
      Teko::LinearOp probedInverse = Teko::buildInverse(*proberFactory,lo);
      Teko::LinearOp invLo = Teko::buildInverse(*directSolveFactory,lo);
   
      Thyra::LinearOpTester<double> tester;
      tester.dump_all(true);
      tester.show_all_tests(true);
   
      {
         const bool result = tester.compare( *probedInverse, *invLo, &out);
         if (!result) {
            out << "Apply: FAILURE" << std::endl;
            success = false;
         }
         else
            out << "Apply: SUCCESS" << std::endl;
      }
   }
}
TEUCHOS_UNIT_TEST(tDiagonalPreconditionerFactory, diag_inv_test)
{
   using Teuchos::RCP;

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

   // preconditioners to test
   std::string precName[] = {"AbsRowSum","Diagonal","Lumped"};
   int numPrec = 3;

   RCP<Teuchos::ParameterList> pl = buildLibPL(4);
   RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromParameterList(*pl); 

   Teko::LinearOp A = buildSystem(Comm,20);
   
   for(int i=0;i<numPrec;i++) {
      RCP<Teko::InverseFactory> invFact = invLib->getInverseFactory(precName[i]);
      Teko::LinearOp idA_fact = Teko::buildInverse(*invFact,A);
      Teko::LinearOp idA_drct = Teko::getInvDiagonalOp(A,Teko::getDiagonalType(precName[i])); 
  
      Thyra::LinearOpTester<double> tester;
      tester.show_all_tests(true);
   
      const bool result = tester.compare( *idA_fact, *idA_drct, Teuchos::ptrFromRef(out));
      if (!result) {
         out << "Apply 0: FAILURE (\"" << precName[i] << "\")" << std::endl;
         success = false;
      }
      else
         out << "Apply 0: SUCCESS (\"" << precName[i] << "\")" << std::endl;

      // test type
      Teko::LinearOp srcOp = Teko::extractOperatorFromPrecOp(idA_fact);
      TEST_ASSERT(Teuchos::rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<double> >(srcOp)!=Teuchos::null);
   }
}
bool tBlockLowerTriInverseOp_tpetra::test_apply(int verbosity,std::ostream & os)
{
   bool status = false;
   bool allPassed = true;

   RCP<Thyra::PhysicallyBlockedLinearOpBase<ST> > U = getLowerTriBlocks(A_);
   RCP<const Thyra::LinearOpBase<ST> > invTri = createBlockLowerTriInverseOp(U,invDiag_);

   Thyra::LinearOpTester<ST> tester;
   tester.show_all_tests(true);
   std::stringstream ss;
   Teuchos::FancyOStream fos(Teuchos::rcpFromRef(ss),"      |||");
   const bool result = tester.compare( *invA_, *invTri, Teuchos::ptrFromRef(fos) );
   TEST_ASSERT(result,
          std::endl << "   tBlockLowerTriInverseOp_tpetra::test_apply "
                    << ": Comparing implicitly generated operator to exact operator");
     if(not result || verbosity>=10) 
        os << ss.str(); 

   return allPassed;
}
Exemple #10
0
  TEUCHOS_UNIT_TEST(assembly_engine, z_basic_epetra_vtpetra)
  {
     TEUCHOS_ASSERT(tLinearOp!=Teuchos::null);
     TEUCHOS_ASSERT(eLinearOp!=Teuchos::null);

     TEUCHOS_ASSERT(tVector!=Teuchos::null);
     TEUCHOS_ASSERT(eVector!=Teuchos::null);

     Thyra::LinearOpTester<double> tester;
     tester.set_all_error_tol(1e-14);
     tester.show_all_tests(true);
     tester.dump_all(true);
     tester.num_random_vectors(200);

     {
        const bool result = tester.compare( *tLinearOp, *eLinearOp, Teuchos::ptrFromRef(out) );
        TEST_ASSERT(result);
     }

     {
        const bool result = Thyra::testRelNormDiffErr(
           "Tpetra",*tVector,
           "Epetra",*eVector,
           "linear_properties_error_tol()", 1e-14,
           "linear_properties_warning_tol()", 1e-14,
           &out);
        TEST_ASSERT(result);
     }
  }
Exemple #11
0
bool tNeumannSeries::test_scaledOp(int verbosity,std::ostream & os)
{
   bool status = false;
   bool allPassed = true;

   // perform actual test
   Thyra::LinearOpTester<double> tester;
   tester.show_all_tests(true);
   std::stringstream ss;
   Teuchos::FancyOStream fos(rcpFromRef(ss),"      |||");

   {
      // build library parameter list
      Teuchos::RCP<Teuchos::ParameterList> pl = buildLibPL(2,"Diagonal");
      if(verbosity>=10) {
         os << "   tNeumannSeries::test_scaledOp :"
            << " printing library parameter list" << std::endl;
         pl->print(os);
      }

      RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromParameterList(*pl);
      RCP<Teko::InverseFactory> neumann = invLib->getInverseFactory("Neumann");
      RCP<Teko::InverseFactory> direct = invLib->getInverseFactory("Amesos");

      Teko::LinearOp op = buildExampleOp(2,*GetComm());
   
      Teko::LinearOp neuInv = Teko::buildInverse(*neumann,op);
      Teko::LinearOp dirInv = Teko::buildInverse(*direct,op);

      const bool result = tester.compare( *neuInv, *dirInv, Teuchos::ptrFromRef(fos) );
      TEST_ASSERT(result,
             std::endl << "   tNeumannSeries::test_scaledOp "
             << ": Comparing factory generated operator to correct operator");
      if(not result || verbosity>=10) 
         os << ss.str(); 
   }
 
   return allPassed;
}
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( SimpleDenseLinearOp, basic,
  Scalar )
{

  using Teuchos::rcp_dynamic_cast;
  typedef ScalarTraits<Scalar> ST;

  const RCP<MultiVectorBase<Scalar> > mv =
    createSerialMultiVector<Scalar>(g_dim, g_dim/2, ST::one());
  const RCP<LinearOpBase<Scalar> > op =
    createNonconstSimpleDenseLinearOp<Scalar>(mv);

  TEST_EQUALITY(
    mv,
    rcp_dynamic_cast<SimpleDenseLinearOp<Scalar> >(op)->getNonconstMultiVector()
    );

  Thyra::LinearOpTester<Scalar> linearOpTester;
  linearOpTester.dump_all(g_dumpAll);
  TEST_ASSERT(linearOpTester.check(*op, ptrFromRef(out)));

}
TEUCHOS_UNIT_TEST(tProbingFactory, basic_test)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp lo = buildSystem(Comm,10);
   
   Teuchos::RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
   Teuchos::RCP<Teko::InverseFactory> directSolveFactory = invLib->getInverseFactory("Amesos");

   Teuchos::RCP<Teko::ProbingPreconditionerFactory> probeFact
         = rcp(new Teko::ProbingPreconditionerFactory);
   probeFact->setGraphOperator(lo);
   probeFact->setInverseFactory(directSolveFactory);

   RCP<Teko::InverseFactory> invFact = Teuchos::rcp(new Teko::PreconditionerInverseFactory(probeFact,Teuchos::null));

   Teko::LinearOp probedInverse = Teko::buildInverse(*invFact,lo);
   Teko::LinearOp invLo = Teko::buildInverse(*directSolveFactory,lo);

   Thyra::LinearOpTester<double> tester;
   tester.dump_all(true);
   tester.show_all_tests(true);

   {
      const bool result = tester.compare( *probedInverse, *invLo, &out);
      if (!result) {
         out << "Apply: FAILURE" << std::endl;
         success = false;
      }
      else
         out << "Apply: SUCCESS" << std::endl;
   }
}
Exemple #14
0
TEUCHOS_UNIT_TEST(tExplicitOps, transpose)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm comm;
   #endif

   int nx = 39; // essentially random values
   int ny = 53;

   // create some big blocks to play with
   Trilinos_Util::CrsMatrixGallery FGallery("recirc_2d",comm,false); // CJ TODO FIXME: change for Epetra64
   FGallery.Set("nx",nx);
   FGallery.Set("ny",ny);
   Epetra_CrsMatrix & epetraF = FGallery.GetMatrixRef();
   Teko::LinearOp F = Thyra::epetraLinearOp(rcp(new Epetra_CrsMatrix(epetraF)));
   Teko::LinearOp F_T = Teko::explicitTranspose(F);
   Teko::LinearOp aF = Thyra::adjoint(F);

   Teuchos::RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*F_T);
   TEST_ASSERT(eOp!=Teuchos::null);
   Teuchos::RCP<const Epetra_CrsMatrix> eCrs = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp);
   TEST_ASSERT(eCrs!=Teuchos::null);

   Thyra::LinearOpTester<double> tester;
   tester.set_all_error_tol(1e-14);
   tester.show_all_tests(true);

   {
      std::stringstream ss;
      const bool result = tester.compare( *aF, *F_T, Teuchos::ptrFromRef(out) );
      TEST_ASSERT(result);
   }
}
  TEUCHOS_UNIT_TEST(assembly_engine, z_basic_epetra_vtpetra)
  {
    PHX::InitializeKokkosDevice();

     TEUCHOS_ASSERT(tLinearOp!=Teuchos::null);
     TEUCHOS_ASSERT(eLinearOp!=Teuchos::null);

     TEUCHOS_ASSERT(tVector!=Teuchos::null);
     TEUCHOS_ASSERT(eVector!=Teuchos::null);

     Thyra::LinearOpTester<double> tester;
     tester.set_all_error_tol(1e-14);
     tester.show_all_tests(true);
     tester.dump_all(true);
     tester.num_random_vectors(200);

     {
        const bool result = tester.compare( *tLinearOp, *eLinearOp, Teuchos::ptrFromRef(out) );
        TEST_ASSERT(result);
     }

     {
        const bool result = Thyra::testRelNormDiffErr(
           "Tpetra",*tVector,
           "Epetra",*eVector,
           "linear_properties_error_tol()", 1e-14,
           "linear_properties_warning_tol()", 1e-14,
           &out);
        TEST_ASSERT(result);
     }


     // Need to kill global objects so that memory leaks on kokkos ref
     // count pointing doesn't trigger test failure.
     eLinearOp = Teuchos::null;
     tLinearOp = Teuchos::null;
     eVector = Teuchos::null;
     tVector = Teuchos::null;

     PHX::FinalizeKokkosDevice();
  }
int exampleImplicitlyComposedLinearOperators(
  const int n0,
  const int n1,
  const int n2,
  Teuchos::FancyOStream &out,
  const Teuchos::EVerbosityLevel verbLevel,
  typename Teuchos::ScalarTraits<Scalar>::magnitudeType errorTol,
  const bool testAdjoint
  )
{

  // Using and other declarations
  typedef Teuchos::ScalarTraits<Scalar> ST;
  using Teuchos::as;
  using Teuchos::RCP;
  using Teuchos::OSTab;
  using Thyra::VectorSpaceBase;
  using Thyra::VectorBase;
  using Thyra::MultiVectorBase;
  using Thyra::LinearOpBase;
  using Thyra::defaultSpmdVectorSpace;
  using Thyra::randomize;
  using Thyra::identity;
  using Thyra::diagonal;
  using Thyra::multiply;
  using Thyra::add;
  using Thyra::subtract;
  using Thyra::scale;
  using Thyra::adjoint;
  using Thyra::block1x2;
  using Thyra::block2x2;
  using Thyra::block2x2;

  out << "\n***"
      << "\n*** Demonstrating building linear operators for scalar type "
      << ST::name()
      << "\n***\n";

  OSTab tab(out);

  //
  // A) Set up the basic objects and other inputs to build the implicitly
  // composed linear operators.
  //
  
  // Create serial vector spaces in this case
  const RCP<const VectorSpaceBase<Scalar> >
    space0 = defaultSpmdVectorSpace<Scalar>(n0),
    space1 = defaultSpmdVectorSpace<Scalar>(n1),
    space2 = defaultSpmdVectorSpace<Scalar>(n2);

  // Create the component linear operators first as multi-vectors
  const RCP<MultiVectorBase<Scalar> >
    mvA = createMembers(space2, n0, "A"),
    mvB = createMembers(space0, n2, "B"),
    mvC = createMembers(space0, n0, "C"),
    mvE = createMembers(space0, n1, "E"),
    mvF = createMembers(space0, n1, "F"),
    mvJ = createMembers(space2, n1, "J"),
    mvK = createMembers(space1, n2, "K"),
    mvL = createMembers(space2, n1, "L"),
    mvN = createMembers(space0, n1, "N"),
    mvP = createMembers(space2, n1, "P"),
    mvQ = createMembers(space0, n2, "Q");

  // Create the vector diagonal for D
  const RCP<VectorBase<Scalar> > d = createMember(space2);

  // Get the constants
  const Scalar
    one = 1.0,
    beta = 2.0,
    gamma = 3.0,
    eta = 4.0;

  // Randomize the values in the Multi-Vector
  randomize( -one, +one, mvA.ptr() );
  randomize( -one, +one, mvB.ptr() );
  randomize( -one, +one, mvC.ptr() );
  randomize( -one, +one, d.ptr() );
  randomize( -one, +one, mvE.ptr() );
  randomize( -one, +one, mvF.ptr() );
  randomize( -one, +one, mvJ.ptr() );
  randomize( -one, +one, mvK.ptr() );
  randomize( -one, +one, mvL.ptr() );
  randomize( -one, +one, mvN.ptr() );
  randomize( -one, +one, mvP.ptr() );
  randomize( -one, +one, mvQ.ptr() );

  // Get the linear operator forms of the basic component linear operators
  const RCP<const LinearOpBase<Scalar> >
    A = mvA,
    B = mvB,
    C = mvC,
    E = mvE,
    F = mvF,
    J = mvJ,
    K = mvK,
    L = mvL,
    N = mvN,
    P = mvP,
    Q = mvQ;

  out << describe(*A, verbLevel);
  out << describe(*B, verbLevel);
  out << describe(*C, verbLevel);
  out << describe(*E, verbLevel);
  out << describe(*F, verbLevel);
  out << describe(*J, verbLevel);
  out << describe(*K, verbLevel);
  out << describe(*L, verbLevel);
  out << describe(*N, verbLevel);
  out << describe(*P, verbLevel);
  out << describe(*Q, verbLevel);

  //
  // B) Create the composed linear operators
  //

  // I
  const RCP<const LinearOpBase<Scalar> > I = identity(space1, "I");

  // D = diag(d)
  const RCP<const LinearOpBase<Scalar> > D = diagonal(d, "D");

  // M00 = [ gama*B*A + C,  E + F ] ^H
  //       [ J^H * A,       I     ]
  const RCP<const LinearOpBase<Scalar> > M00 =
    adjoint(
      block2x2(
        add( scale(gamma,multiply(B,A)), C ),  add( E, F ),
        multiply(adjoint(J),A),                I
        ),
      "M00"
      );

  out << "\nM00 = " << describe(*M00, verbLevel);

  // M01 = beta * [ Q ]
  //              [ K ]
  const RCP<const LinearOpBase<Scalar> > M01 =
    scale(
      beta,
      block2x1( Q, K ),
      "M01"
      );

  out << "\nM01 = "  << describe(*M01, verbLevel);
            
  // M10 = [ L * N^H,  eta*P ]
  const RCP<const LinearOpBase<Scalar> > M10 =
    block1x2(
      multiply(L,adjoint(N)),  scale(eta,P),
      "M10"
      );

  out << "\nM10 = " << describe(*M10, verbLevel);

  // M11 = D - Q^H*Q
  const RCP<const LinearOpBase<Scalar> > M11 =
    subtract( D, multiply(adjoint(Q),Q), "M11" );

  out << "\nM11 = "  << describe(*M11, verbLevel);
  

  // M = [ M00, M01 ]
  //     [ M10, M11 ]
  const RCP<const LinearOpBase<Scalar> > M =
    block2x2(
      M00, M01,
      M10, M11,
      "M"
      );

  out << "\nM = " << describe(*M, verbLevel);

  
  //
  // C) Test the final composed operator
  //

  Thyra::LinearOpTester<Scalar> linearOpTester;
  linearOpTester.set_all_error_tol(errorTol);
  linearOpTester.check_adjoint(testAdjoint);
  if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH))
    linearOpTester.show_all_tests(true);
  if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME))
    linearOpTester.dump_all(true);

  const bool result = linearOpTester.check(*M,&out);

  return result;

}
Exemple #17
0
bool tPCDStrategy::test_PCDStrategy(int verbosity,std::ostream & os)
{
   bool status = false;
   bool allPassed = true;

   Thyra::LinearOpTester<double> tester;
   tester.show_all_tests(true);
   tester.set_all_error_tol(tolerance_);

   Teko::LinearOp M1 = buildExampleOp(1,*GetComm(),1.0);
   Teko::LinearOp M2 = buildExampleOp(2,*GetComm(),1.0);
   Teko::LinearOp A = Thyra::nonconstBlock2x2<double>(buildExampleOp(2,*GetComm(),1.0),
                                      buildExampleOp(1,*GetComm(),2.0),
                                      buildExampleOp(1,*GetComm(),3.0),
                                      buildExampleOp(2,*GetComm(),4.0));
   Teko::BlockedLinearOp blkA = Teko::toBlockedLinearOp(A);

   Teko::LinearOp laplace = Teko::explicitMultiply(M2,M1);
   Teko::LinearOp Fp = M1;
   Teko::LinearOp Qp = buildExampleOp(3,*GetComm(),1.0);

   std::string pcdStr      = Teko::NS::PCDStrategy::getPCDString();
   std::string presLapStr  = Teko::NS::PCDStrategy::getPressureLaplaceString();
   std::string presMassStr = Teko::NS::PCDStrategy::getPressureMassString();

   RCP<Teko::StaticRequestCallback<Teko::LinearOp> > pcdCb
         = rcp(new Teko::StaticRequestCallback<Teko::LinearOp>(pcdStr,Fp));
   RCP<Teko::StaticRequestCallback<Teko::LinearOp> > lapCb
         = rcp(new Teko::StaticRequestCallback<Teko::LinearOp>(presLapStr,laplace));
   RCP<Teko::StaticRequestCallback<Teko::LinearOp> > massCb
         = rcp(new Teko::StaticRequestCallback<Teko::LinearOp>(presMassStr,Qp));

   RCP<Teko::RequestHandler> rh = rcp(new Teko::RequestHandler);
   rh->addRequestCallback(pcdCb);
   rh->addRequestCallback(lapCb);
   rh->addRequestCallback(massCb);

   RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
   RCP<Teko::InverseFactory> inverseFact = invLib->getInverseFactory("Amesos");

   // test the inverse of the 00 block
   {
      bool result;
      std::stringstream ss;
      Teuchos::FancyOStream fos(Teuchos::rcpFromRef(ss),"      |||");

      Teko::LinearOp invA00 = inverseFact->buildInverse(M2);
      Teko::BlockPreconditionerState state;
      Teko::NS::PCDStrategy strategy(inverseFact,inverseFact);
      strategy.setRequestHandler(rh);

      // build the state object
      // state.addLinearOp(presLapStr,  laplace);
      // state.addLinearOp(pcdStr,      Fp);
      // state.addLinearOp(presMassStr, Qp);

      // test the 0,0 block inverses: hat
      Teko::LinearOp hatInvA00 = strategy.getHatInvA00(blkA,state);
      ss.str("");
      result = tester.compare( *hatInvA00, *invA00, Teuchos::ptrFromRef(fos) );
      TEST_ASSERT(result,
            std::endl << "   tPCDStrategy::test_PCDStrategy " << toString(status)
                      << " : Comparing invHatA00 operators");
      if(not result || verbosity>=10)
         os << ss.str();

      // test the 0,0 block inverses: tilde
      Teko::LinearOp tildeInvA00 = strategy.getTildeInvA00(blkA,state);
      ss.str("");
      result = tester.compare( *tildeInvA00, *invA00, Teuchos::ptrFromRef(fos) );
      TEST_ASSERT(result,
            std::endl << "   tPCDStrategy::test_PCDStrategy " << toString(status)
                      << " : Comparing invTildeA00 operators");
      if(not result || verbosity>=10)
         os << ss.str();
   }

   // test the inverse of the Schur complement
   {
      bool result;
      std::stringstream ss;
      Teuchos::FancyOStream fos(Teuchos::rcpFromRef(ss),"      |||");

      Teko::LinearOp invLaplace = inverseFact->buildInverse(laplace);
      Teko::LinearOp iQp = Teko::getInvDiagonalOp(Qp);
      Teko::LinearOp invSchur = multiply(iQp,Fp,invLaplace);

      Teko::BlockPreconditionerState state;
      Teko::NS::PCDStrategy strategy(inverseFact,inverseFact);
      strategy.setRequestHandler(rh);

      // build the state object
      // state.addLinearOp(presLapStr,  laplace);
      // state.addLinearOp(pcdStr,      Fp);
      // state.addLinearOp(presMassStr, Qp);

      // test the 0,0 block inverses: hat
      Teko::LinearOp invS_strategy = strategy.getInvS(blkA,state);
      ss.str("");
      result = tester.compare( *invS_strategy, *invSchur, Teuchos::ptrFromRef(fos) );
      TEST_ASSERT(result,
            std::endl << "   tPCDStrategy::test_PCDStrategy " << toString(status)
                      << " : Comparing invS operators");
      if(not result || verbosity>=10)
         os << ss.str();
   }

   return allPassed;
}
bool runCgSolveExample(
  const int dim,
  const Scalar diagScale,
  const bool symOp,
  const bool showAllTests,
  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance,
  const int maxNumIters
  )
{

  using Teuchos::as;
  using Teuchos::null;
  using Teuchos::RCP;
  using Teuchos::rcp;
  using Teuchos::OSTab;
  typedef Teuchos::ScalarTraits<Scalar> ST;
  using Thyra::multiply;
  using Thyra::scale;
  typedef typename ST::magnitudeType  ScalarMag;
  bool success = true;
  bool result;
  Teuchos::RCP<Teuchos::FancyOStream> out =
    Teuchos::VerboseObjectBase::getDefaultOStream();
  *out << "\n***\n*** Running silly CG solver using scalar type = \'"
       << ST::name() << "\' ...\n***\n";
  Teuchos::Time timer("");
  timer.start(true);

  //
  // (A) Setup a simple linear system with tridiagonal operator:
  //
  //       [   a*2   -1                         ]
  //       [ -r(1)  a*2       -1                ]
  //  A =  [          .        .        .       ]
  //       [             -r(n-2)      a*2    -1 ]
  //       [                      -r(n-1)   a*2 ]
  //

  // (A.1) Create the tridiagonal matrix operator
  *out << "\nConstructing tridiagonal matrix A of dimension = " << dim
       << " and diagonal multiplier = " << diagScale << " ...\n";
  Teuchos::Array<Scalar> lower(dim-1), diag(dim), upper(dim-1);
  const Scalar
    up = -ST::one(),
    diagTerm = as<Scalar>(2.0) * diagScale * ST::one(),
    low = -(symOp ? ST::one() : ST::random());
  int k = 0;
  // First row
  diag[k] = diagTerm; upper[k] = up;
  // Middle rows
  for( k = 1; k < dim - 1; ++k ) {
    lower[k-1] = low; diag[k] = diagTerm; upper[k] = up;
  }
  // Last row
  lower[k-1] = low; diag[k] = diagTerm;
  RCP<const Thyra::LinearOpBase<Scalar> > A =
    rcp(new ExampleTridiagSerialLinearOp<Scalar>(dim, lower, diag, upper));

  // (A.2) Testing the linear operator constructed linear operator
  *out << "\nTesting the constructed linear operator A ...\n";
  Thyra::LinearOpTester<Scalar> linearOpTester;
  linearOpTester.enable_all_tests(false);
  linearOpTester.check_linear_properties(true);
  linearOpTester.set_all_error_tol(tolerance);
  linearOpTester.set_all_warning_tol(1e-2*tolerance);
  linearOpTester.show_all_tests(showAllTests);
  result = linearOpTester.check(*A, out.ptr());
  if(!result) success = false;

  // (A.3) Create RHS vector b and set to a random value
  RCP<Thyra::VectorBase<Scalar> > b = createMember(A->range());
  Thyra::seed_randomize<Scalar>(0);
  Thyra::randomize( -ST::one(), +ST::one(), b.ptr() );

  // (A.4) Create LHS vector x and set to zero
  RCP<Thyra::VectorBase<Scalar> > x = createMember(A->domain());
  Thyra::V_S( x.ptr(), ST::zero() );

  // (A.5) Create the final linear system
  if(!symOp) {
    *out << "\nSetting up normal equations for unsymmetric system A^H*(A*x-b) => new A*x = b ...\n";
    // A^H*A
    RCP<const Thyra::LinearOpBase<Scalar> > AtA = multiply(adjoint(A), A);
    // A^H*b
    RCP<Thyra::VectorBase<Scalar> > nb = createMember(AtA->range());
    Thyra::apply<Scalar>(*A, Thyra::CONJTRANS, *b, nb.ptr());
    A = AtA;
    b = nb;
  }

  // (A.6) Testing the linear operator used with the solve
  *out << "\nTesting the linear operator used with the solve ...\n";
  linearOpTester.check_for_symmetry(true);
  result = linearOpTester.check(*A, out.ptr());
  if(!result) success = false;

  //
  // (B) Solve the linear system with the silly CG solver
  //
  *out << "\nSolving the linear system with sillyCgSolve(...) ...\n";
  {
    OSTab tab2(out);
    result = sillyCgSolve(*A, *b, maxNumIters, tolerance, x.ptr(), *out);
  }
  if(!result) success = false;

  //
  // (C) Check that the linear system was solved to the specified tolerance
  //
  RCP<Thyra::VectorBase<Scalar> > r = createMember(A->range());                     
  // r = b
  Thyra::V_V(r.ptr(), *b);
   // r = -A*x + r
  Thyra::apply<Scalar>(*A, Thyra::NOTRANS, *x, r.ptr(), -ST::one(), ST::one());
  const ScalarMag r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b);
  const ScalarMag rel_err = r_nrm/b_nrm, relaxTol = 10.0*tolerance;
  result = rel_err <= relaxTol;
  if(!result) success = false;
  *out << "\nChecking the residual ourselves ...\n";
  {
    OSTab tab(out);
    *out
      << "\n||b-A*x||/||b|| = "<<r_nrm<<"/"<<b_nrm<<" = "<<rel_err<<(result?" <= ":" > ")
      <<"10.0*tolerance = "<<relaxTol<<": "<<(result?"passed":"failed")<<std::endl;
  }
  timer.stop();
  *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n";
  
  return success;

} // end runCgSolveExample()
bool tLSCHIntegrationTest::test_hScaling(int verbosity,std::ostream & os)
{
   bool status = false;
   bool allPassed = true;
   
   RCP<const Epetra_Comm> comm = GetComm();

   // build some operators
   Teko::LinearOp F = Teko::Test::build2x2(*comm,1,2,2,1);
   Teko::LinearOp G = Teko::Test::build2x2(*comm,1,-1,-3,1);
   Teko::LinearOp D = Teko::Test::build2x2(*comm,1,-3,-1,1);

   double diag[2];
 
   diag[0] = 1.0/3.0; diag[1] = 1.0/2.0;
   Teko::LinearOp M = Teko::Test::DiagMatrix(2,diag,"M");

   diag[0] = 5.0; diag[1] = 9.0;
   Teko::LinearOp H = Teko::Test::DiagMatrix(2,diag,"H");

   Teko::LinearOp A = Thyra::block2x2<double>(F,G,D,Teuchos::null);

   Teko::LinearOp exact;
   {
      // build some operators
      Teko::LinearOp D0 = Teko::Test::build2x2(*comm,-1.0/3.0,2.0/3.0,2.0/3.0,-1.0/3.0);
      Teko::LinearOp D1 = Teko::Test::build2x2(*comm,-1.5,-3.0,-3.0,-5.5);
      Teko::LinearOp U  = Teko::Test::build2x2(*comm,-0.5,-1.5,-0.5,-0.5);
      
      exact = Thyra::block2x2<double>(D0,U,Teuchos::null,D1);
   }

   RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
   RCP<Teko::InverseFactory> invFact = invLib->getInverseFactory("Amesos");
   RCP<Teko::NS::InvLSCStrategy> strategy = rcp(new Teko::NS::InvLSCStrategy(invFact,M));
   strategy->setHScaling(Teko::getDiagonal(H));
   strategy->setUseFullLDU(false);

   RCP<Teko::BlockPreconditionerFactory> precFact = rcp(new Teko::NS::LSCPreconditionerFactory(strategy));
   RCP<Teko::BlockPreconditionerState> bps = Teuchos::rcp_dynamic_cast<Teko::BlockPreconditionerState>(precFact->buildPreconditionerState());
   Teko::LinearOp prec = precFact->buildPreconditionerOperator(A,*bps);

   Teko::BlockedLinearOp bA = Teko::toBlockedLinearOp(A);
   std::stringstream ss;
   ss << "invF = " << Teuchos::describe(*strategy->getInvF(bA,*bps),Teuchos::VERB_EXTREME) << std::endl;
   ss << "invBQBt = " << Teuchos::describe(*strategy->getInvBQBt(bA,*bps),Teuchos::VERB_EXTREME) << std::endl;
   ss << "invF = " << Teuchos::describe(*strategy->getInvBHBt(bA,*bps),Teuchos::VERB_EXTREME) << std::endl;
   ss << "invMass = " << Teuchos::describe(*strategy->getInvMass(bA,*bps),Teuchos::VERB_EXTREME) << std::endl;
   ss << "HScaling = " << Teuchos::describe(*strategy->getHScaling(bA,*bps),Teuchos::VERB_EXTREME) << std::endl;
   ss << "prec = " << Teuchos::describe(*prec,Teuchos::VERB_EXTREME) << std::endl;

   // construct a couple of vectors
   const RCP<Epetra_Map> map = rcp(new Epetra_Map(2,0,*GetComm()));
   Epetra_Vector ea(*map),eb(*map);
   const RCP<const Thyra::MultiVectorBase<double> > x = BlockVector(ea,eb,prec->domain());
   const RCP<Thyra::MultiVectorBase<double> > y = Thyra::createMembers(prec->range(),1); 
   ea[0] = 1.0; ea[1] = 0.0; eb[0] = 0.0; eb[1] = 0.0;
   Thyra::apply(*prec,Thyra::NOTRANS,*x,y.ptr());
   ss << "prec = " << Teuchos::describe(*y,Teuchos::VERB_EXTREME) << std::endl;
   ea[0] = 0.0; ea[1] = 1.0; eb[0] = 0.0; eb[1] = 0.0;
   Thyra::apply(*prec,Thyra::NOTRANS,*x,y.ptr());
   ss << "prec = " << Teuchos::describe(*y,Teuchos::VERB_EXTREME) << std::endl;
   ea[0] = 0.0; ea[1] = 0.0; eb[0] = 1.0; eb[1] = 0.0;
   Thyra::apply(*prec,Thyra::NOTRANS,*x,y.ptr());
   ss << "prec = " << Teuchos::describe(*y,Teuchos::VERB_EXTREME) << std::endl;
   ea[0] = 0.0; ea[1] = 0.0; eb[0] = 0.0; eb[1] = 1.0;
   Thyra::apply(*prec,Thyra::NOTRANS,*x,y.ptr());
   ss << "prec = " << Teuchos::describe(*y,Teuchos::VERB_EXTREME) << std::endl;
  
   Thyra::LinearOpTester<double> tester;
   tester.show_all_tests(true);
   Teuchos::FancyOStream fos(Teuchos::rcpFromRef(ss),"|||");
   const bool result = tester.compare( *prec, *exact, Teuchos::ptrFromRef(fos) );
   TEST_ASSERT(result,
          std::endl << "   tLSCHIntegration::test_hScaling "
                    << ": Comparing preconditioner to exactly computed version");

   const bool result2 = tester.compare( *H, *strategy->getHScaling(bA,*bps), Teuchos::ptrFromRef(fos) );
   TEST_ASSERT(result2,
          std::endl << "   tLSCHIntegration::test_hScaling "
                    << ": Comparing scaling of H operator");

   const bool result3 = tester.compare( *build2x2(*comm,0.208333333333333,0.375, 0.375, 0.875),
     *strategy->getInvBQBt(bA,*bps), Teuchos::ptrFromRef(fos) );
   TEST_ASSERT(result3,
          std::endl << "   tLSCHIntegration::test_hScaling "
                    << ": Comparing inv(BQBt) operator");

   const bool result4 = tester.compare( *build2x2(*comm, 0.077777777777778, 0.177777777777778, 0.177777777777778, 0.477777777777778),
     *strategy->getInvBHBt(bA,*bps), Teuchos::ptrFromRef(fos) );
   TEST_ASSERT(result4,
          std::endl << "   tLSCHIntegration::test_hScaling "
                    << ": Comparing inv(BHBt) operator");

   if(not allPassed || verbosity>=10) 
      os << ss.str(); 

   return allPassed;
}
  // Testing Parameter Support
  TEUCHOS_UNIT_TEST(model_evaluator_blocked_hessians, d2f_dp2)
  {
    typedef panzer::Traits::RealType RealType;
    typedef Thyra::VectorBase<RealType> VectorType;
    typedef Thyra::SpmdVectorBase<RealType> SpmdVectorType;
    typedef Thyra::LinearOpBase<RealType> OperatorType;

    using Teuchos::RCP;
    using Teuchos::rcp_dynamic_cast;

    typedef Thyra::ModelEvaluatorBase::InArgs<double> InArgs;
    typedef Thyra::ModelEvaluatorBase::OutArgs<double> OutArgs;
    typedef panzer::ModelEvaluator<double> PME;


    bool distr_param_on = true;
    AssemblyPieces ap;
    buildAssemblyPieces(distr_param_on,ap);

    int pIndex = -1;

    std::vector<Teuchos::RCP<Teuchos::Array<std::string> > > p_names;
    std::vector<Teuchos::RCP<Teuchos::Array<double> > > p_values;
    bool build_transient_support = true;
    RCP<PME> me 
        = Teuchos::rcp(new PME(ap.fmb,ap.rLibrary,ap.lof,p_names,p_values,Teuchos::null,ap.gd,build_transient_support,0.0));

    const double DENSITY_VALUE = 3.7;
    const double TEMPERATURE_VALUE = 2.0;
    const double PERTURB_VALUE = 0.1;

    // add distributed parameter
    {
      RCP<ThyraObjFactory<double> > th_param_lof = rcp_dynamic_cast<ThyraObjFactory<double> >(ap.param_lof);

      RCP<VectorType> param_density = Thyra::createMember(th_param_lof->getThyraDomainSpace());
      Thyra::assign(param_density.ptr(),DENSITY_VALUE);
      pIndex = me->addDistributedParameter("DENSITY_P",th_param_lof->getThyraDomainSpace(),
                                           ap.param_ged,param_density,ap.param_dofManager);
    }

    me->setupModel(ap.wkstContainer,ap.physicsBlocks,ap.bcs,
                   *ap.eqset_factory,
                   *ap.bc_factory,
                   ap.cm_factory,
                   ap.cm_factory,
                   ap.closure_models,
                   ap.user_data,false,"");

    // panzer::printMeshTopology(out,*ap.dofManager);
    

    RCP<OperatorType> D2fDp2 = me->create_DfDp_op(pIndex);

    // test hessian
    {

      RCP<VectorType> x = Thyra::createMember(*me->get_x_space());
      Thyra::assign(x.ptr(),TEMPERATURE_VALUE);

      RCP<VectorType> dx = Thyra::createMember(*me->get_x_space());
      Thyra::assign(dx.ptr(),PERTURB_VALUE);

      InArgs  in_args = me->createInArgs();
      in_args.set_x(x);
      in_args.set_alpha(1.0/0.1);
      in_args.set_beta(1.0);

      me->evalModel_D2fDp2(pIndex,in_args,dx,D2fDp2);

      out << "D2fDp2 = \n" << Teuchos::describe(*D2fDp2,Teuchos::VERB_EXTREME) << std::endl;
    }

    RCP<OperatorType> W = me->create_DfDp_op(pIndex);
    {
      RCP<VectorType> x = Thyra::createMember(*me->get_x_space());
      Thyra::assign(x.ptr(),TEMPERATURE_VALUE);

      InArgs in_args = me->createInArgs();
      in_args.set_x(x);
      in_args.set_alpha(1.0);
      in_args.set_beta(0.0);

      OutArgs out_args = me->createOutArgs();
      out_args.set_DfDp(pIndex,W);

      me->evalModel(in_args,out_args);

      out << "W = \n" << Teuchos::describe(*W,Teuchos::VERB_EXTREME) << std::endl;
    }

    Thyra::LinearOpTester<double> tester;
    tester.show_all_tests(true);
    tester.set_all_error_tol(1e-15);
    tester.num_random_vectors(20);

    double scaling_of_dfdp = PERTURB_VALUE/DENSITY_VALUE;

    Teuchos::FancyOStream fout(Teuchos::rcpFromRef(std::cout));
    const bool op_cmp = tester.compare( *Thyra::scaleAndAdjoint(scaling_of_dfdp,Thyra::NOTRANS,W.getConst()), *D2fDp2, Teuchos::ptrFromRef(fout));
    TEST_ASSERT(op_cmp);
  }
TEUCHOS_UNIT_TEST(tDiagonalPreconditionerFactory, blkdiag_inv_test)
{
   using Teuchos::RCP;

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

   int numProc = Comm.NumProc();

   // preconditioners to test
   std::string precName = "BlkDiag";

   int myRows = 20;
   int blockSize = 5;
   Teko::LinearOp A = buildSystem(Comm,myRows);

   // sanity check
   TEUCHOS_ASSERT(myRows % blockSize==0);

   {
      RCP<Teuchos::ParameterList> pl = buildLibPL(1); // test diagonal construction
      RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromParameterList(*pl); 
   
      RCP<Teko::InverseFactory> invFact = invLib->getInverseFactory(precName);
      Teko::LinearOp idA_fact = Teko::buildInverse(*invFact,A);

      // test type
      Teko::LinearOp srcOp = Teko::extractOperatorFromPrecOp(idA_fact);
      TEST_ASSERT(Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(srcOp)!=Teuchos::null);
   
      Teko::LinearOp idA_drct = Teko::getInvDiagonalOp(A,Teko::Diagonal);

      Thyra::LinearOpTester<double> tester;
      tester.show_all_tests(true);

      const bool result = tester.compare( *idA_fact, *idA_drct, Teuchos::ptrFromRef(out));
      if (!result) {
         out << "Apply 0: FAILURE (\"" << precName << "\")" << std::endl;
         success = false;
      }
      else
         out << "Apply 0: SUCCESS (\"" << precName << "\")" << std::endl;
   }

   {
      RCP<Teuchos::ParameterList> pl = buildLibPL(blockSize);
      RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromParameterList(*pl); 
   
      RCP<Teko::InverseFactory> invFact = invLib->getInverseFactory(precName);
      Teko::LinearOp idA_fact = Teko::buildInverse(*invFact,A);

      // test type
      Teko::LinearOp srcOp = Teko::extractOperatorFromPrecOp(idA_fact);
      TEST_ASSERT(Teuchos::rcp_dynamic_cast<const Thyra::EpetraLinearOp>(srcOp)!=Teuchos::null);
      RCP<const Epetra_CrsMatrix> eop = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(Thyra::get_Epetra_Operator(*srcOp));
      TEST_EQUALITY(eop->NumGlobalNonzeros(),blockSize*blockSize*(numProc*myRows)/blockSize);
      TEST_EQUALITY(eop->NumMyNonzeros(),blockSize*blockSize*myRows/blockSize);
   }
}
bool run_composite_linear_ops_tests(
  const Teuchos::RCP<const Teuchos::Comm<Thyra::Ordinal> > comm,
  const int n,
  const bool useSpmd,
  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &tol,
  const bool dumpAll,
  Teuchos::FancyOStream *out_arg
  )
{

  using Teuchos::as;
  typedef Teuchos::ScalarTraits<Scalar> ST;
  typedef typename ST::magnitudeType    ScalarMag;
  typedef Teuchos::ScalarTraits<ScalarMag> STM;
  using Teuchos::RCP;
  using Teuchos::rcp;
  using Teuchos::null;
  using Teuchos::rcp_const_cast;
  using Teuchos::rcp_dynamic_cast;
  using Teuchos::dyn_cast;
  using Teuchos::OSTab;
  using Thyra::relErr;
  using Thyra::passfail;

  RCP<Teuchos::FancyOStream>
    out = rcp(new Teuchos::FancyOStream(rcp(out_arg,false)));

  const Teuchos::EVerbosityLevel
    verbLevel = dumpAll?Teuchos::VERB_EXTREME:Teuchos::VERB_HIGH;

  if (nonnull(out)) *out
    << "\n*** Entering run_composite_linear_ops_tests<"<<ST::name()<<">(...) ...\n";

  bool success = true, result;

  const ScalarMag warning_tol = ScalarMag(1e-2)*tol, error_tol = tol;
  Thyra::LinearOpTester<Scalar> linearOpTester;
  linearOpTester.linear_properties_warning_tol(warning_tol);
  linearOpTester.linear_properties_error_tol(error_tol);
  linearOpTester.adjoint_warning_tol(warning_tol);
  linearOpTester.adjoint_error_tol(error_tol);
  linearOpTester.dump_all(dumpAll);
  Thyra::LinearOpTester<Scalar> symLinearOpTester(linearOpTester);
  symLinearOpTester.check_for_symmetry(true);
  symLinearOpTester.symmetry_warning_tol(STM::squareroot(warning_tol));
  symLinearOpTester.symmetry_error_tol(STM::squareroot(error_tol));

  RCP<const Thyra::VectorSpaceBase<Scalar> > space;
  if(useSpmd) space = Thyra::defaultSpmdVectorSpace<Scalar>(comm,n,-1);
  else space = Thyra::defaultSpmdVectorSpace<Scalar>(n);
  if (nonnull(out)) *out
    << "\nUsing a basic vector space described as " << describe(*space,verbLevel) << " ...\n";

  if (nonnull(out)) *out << "\nCreating random n x (n/2) multi-vector origA ...\n";
  RCP<Thyra::MultiVectorBase<Scalar> >
    mvOrigA = createMembers(space,n/2,"origA");
  Thyra::seed_randomize<Scalar>(0);
  //RTOpPack::show_spmd_apply_op_dump = true;
  Thyra::randomize( as<Scalar>(as<Scalar>(-1)*ST::one()), as<Scalar>(as<Scalar>(+1)*ST::one()),
    mvOrigA.ptr() );
  RCP<const Thyra::LinearOpBase<Scalar> >
    origA = mvOrigA;
  if (nonnull(out)) *out << "\norigA =\n" << describe(*origA,verbLevel);
  //RTOpPack::show_spmd_apply_op_dump = false;

  if (nonnull(out)) *out << "\nTesting origA ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*origA, out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out
    << "\nCreating implicit scaled linear operator A1 = scale(0.5,origA) ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A1 = scale(as<Scalar>(0.5),origA);
  if (nonnull(out)) *out << "\nA1 =\n" << describe(*A1,verbLevel);

  if (nonnull(out)) *out << "\nTesting A1 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A1,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nTesting that A1.getOp() == origA ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.compare(
    *dyn_cast<const Thyra::DefaultScaledAdjointLinearOp<Scalar> >(*A1).getOp(),
    *origA,out.ptr());
  if(!result) success = false;

  {

    if (nonnull(out)) *out
      << "\nUnwrapping origA to get non-persisting pointer to origA_1, scalar and transp ...\n";
    Scalar  scalar;
    Thyra::EOpTransp transp;
    const Thyra::LinearOpBase<Scalar> *origA_1 = NULL;
    unwrap( *origA, &scalar, &transp, &origA_1 );
    TEUCHOS_TEST_FOR_EXCEPT( origA_1 == NULL );

    if (nonnull(out)) *out << "\nscalar = " << scalar << " == 1 ? ";
    result = (scalar == ST::one());
    if(!result) success = false;
    if (nonnull(out))	*out << passfail(result) << std::endl;

    if (nonnull(out)) *out << "\ntransp = " << toString(transp) << " == NOTRANS ? ";
    result = (transp == Thyra::NOTRANS);
    if(!result) success = false;
    if (nonnull(out))	*out << passfail(result) << std::endl;

    if (nonnull(out)) *out << "\nTesting that origA_1 == origA ...\n";
    Thyra::seed_randomize<Scalar>(0);
    result = linearOpTester.compare(*origA_1,*origA,out.ptr());
    if(!result) success = false;

  }

  {

    if (nonnull(out)) *out << "\nUnwrapping A1 to get non-persisting pointer to origA_2 ...\n";
    Scalar  scalar;
    Thyra::EOpTransp transp;
    const Thyra::LinearOpBase<Scalar> *origA_2 = NULL;
    unwrap( *A1, &scalar, &transp, &origA_2 );
    TEUCHOS_TEST_FOR_EXCEPT( origA_2 == NULL );

    if (nonnull(out)) *out << "\nscalar = " << scalar << " == 0.5 ? ";
    result = (scalar == as<Scalar>(0.5));
    if(!result) success = false;
    if (nonnull(out))	*out << passfail(result) << std::endl;

    if (nonnull(out)) *out << "\ntransp = " << toString(transp) << " == NOTRANS ? ";
    result = (transp == Thyra::NOTRANS);
    if(!result) success = false;
    if (nonnull(out))	*out << passfail(result) << std::endl;

    if (nonnull(out)) *out << "\nTesting that origA_2 == origA ...\n";
    Thyra::seed_randomize<Scalar>(0);
    result = linearOpTester.compare(*origA_2,*origA,out.ptr());
    if(!result) success = false;

  }

  if (nonnull(out)) *out << "\nCreating implicit scaled linear operator A2 = adjoint(A1) ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A2 = adjoint(A1);
  if (nonnull(out)) *out << "\nA2 =\n" << describe(*A2,verbLevel);

  if (nonnull(out)) *out << "\nTesting A2 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A2,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nTesting that A2.getOp() == A1 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.compare(*dyn_cast<const Thyra::DefaultScaledAdjointLinearOp<Scalar> >(*A2).getOp(),*A1,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating implicit scaled, adjoined linear operator A3 = adjoint(scale(2.0,(A2)) ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A3 = adjoint(scale(as<Scalar>(2.0),A2));
  if (nonnull(out)) *out << "\nA3 =\n" << describe(*A3,verbLevel);

  if (nonnull(out)) *out << "\nTesting A3 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A3,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nTesting that A3 == origA ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.compare(*A3,*origA,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCalling all of the rest of the functions for non-const just to test them ...\n";
  RCP<Thyra::LinearOpBase<Scalar> >
    A4 = nonconstScale(
      as<Scalar>(0.25)
      ,nonconstAdjoint(
        nonconstTranspose(
          nonconstAdjoint(
            nonconstScaleAndAdjoint(
              as<Scalar>(4.0)
              ,Thyra::TRANS
              ,Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(origA)
              )
            )
          )
        )
      );
  if(!ST::isComplex) A4 = nonconstTranspose(nonconstAdjoint(A4)); // Should result in CONJ
  if (nonnull(out)) *out << "\nA4 =\n" << describe(*A4,verbLevel);

  if (nonnull(out)) *out << "\nTesting A4 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A4,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCalling all of the rest of the functions for const just to test them ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A5 = scale(
      as<Scalar>(0.25)
      ,adjoint(
        transpose(
          adjoint(
            scaleAndAdjoint(
              as<Scalar>(4.0)
              ,Thyra::TRANS
              ,origA
              )
            )
          )
        )
      );
  if(!ST::isComplex) A5 = transpose(adjoint(A5)); // Should result in CONJ
  if (nonnull(out)) *out << "\nA5 =\n" << describe(*A5,verbLevel);

  if (nonnull(out)) *out << "\nTesting A5 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A5,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a multiplied operator A6 = origA^H*A1 ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A6 = multiply(adjoint(origA),A1);
  if (nonnull(out)) *out << "\nA6 =\n" << describe(*A6,verbLevel);

  if (nonnull(out)) *out << "\nTesting A6 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A6,out.ptr());
  if(!result) success = false;
  // Note that testing the symmetry above helps to check the transpose mode
  // against the non-transpose mode!

#ifdef TEUCHOS_DEBUG
  if (nonnull(out)) *out << "\nCreating an invalid multiplied operator A6b = origA*origA (should throw an exception) ...\n\n";
  try {
    RCP<const Thyra::LinearOpBase<Scalar> >
      A6b = multiply(origA,origA);
    result = true;
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result)
  if (nonnull(out))
    *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n");
  if(result) success = false;
#endif // TEUCHOS_DEBUG

  if (nonnull(out)) *out << "\nCreating a non-const multiplied operator A7 = origA^H*A1 ...\n";
  RCP<Thyra::LinearOpBase<Scalar> >
    A7 = nonconstMultiply(
      rcp_const_cast<Thyra::LinearOpBase<Scalar> >(adjoint(origA))
      ,rcp_const_cast<Thyra::LinearOpBase<Scalar> >(A1)
      );
  if (nonnull(out)) *out << "\nA7 =\n" << describe(*A7,verbLevel);

  if (nonnull(out)) *out << "\nTesting A7 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A7,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating an added operator A8 = origA + A1 ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A8 = add(origA,A1);
  if (nonnull(out)) *out << "\nA8 =\n" << describe(*A8,verbLevel);

  if (nonnull(out)) *out << "\nTesting A8 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A8,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a symmetric subtracted operator A8b = A6 + adjoint(origA)*origA ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A8b = subtract(A6,multiply(adjoint(origA),origA));
  if (nonnull(out)) *out << "\nA8b =\n" << describe(*A8b,verbLevel);

  if (nonnull(out)) *out << "\nTesting A8b ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A8b,out.ptr());
  if(!result) success = false;

#ifdef TEUCHOS_DEBUG
  if (nonnull(out)) *out << "\nCreating an invalid added operator A8c = origA + adjoint(origA) (should throw an exception) ...\n\n";
  try {
    RCP<const Thyra::LinearOpBase<Scalar> >
      A8c = add(origA,adjoint(origA));
    result = true;
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result)
  if (nonnull(out))
    *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n");
  if(result) success = false;
#endif // TEUCHOS_DEBUG

  RCP<const Thyra::LinearOpBase<Scalar> >
    nullOp = null;

  if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9 = [ A6, A1^H; A1, null ] ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A9 = Thyra::block2x2<Scalar>(
      A6,  adjoint(A1)
      ,A1, nullOp
      );
  if (nonnull(out)) *out << "\nA9 =\n" << describe(*A9,verbLevel);

  if (nonnull(out)) *out << "\nTesting A9 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A9,out.ptr());
  if(!result) success = false;
  // Note that testing the symmetry above helps to check the transpose mode
  // against the non-transpose mode!

  if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9_a = [ A6, A1^H; A1, null ] using pre-formed range and domain product spaces ...\n";
  RCP<Thyra::PhysicallyBlockedLinearOpBase<Scalar> >
    A9_a = rcp(new Thyra::DefaultBlockedLinearOp<Scalar>());
  A9_a->beginBlockFill(
    rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(A9,true)->productRange()
    ,rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(A9,true)->productDomain()
    );
  A9_a->setBlock(0,0,A6);
  A9_a->setBlock(0,1,adjoint(A1));
  A9_a->setBlock(1,0,A1);
  A9_a->endBlockFill();
  if (nonnull(out)) *out << "\nA9_a =\n" << describe(*A9_a,verbLevel);

  if (nonnull(out)) *out << "\nTesting A9_a ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A9_a,out.ptr());
  if(!result) success = false;
  // Note that testing the symmetry above helps to check the transpose mode
  // against the non-transpose mode!

  if (nonnull(out)) *out << "\nComparing A9 == A9_a ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.compare(*A9,*A9_a,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9_b = [ A6, A1^H; A1, null ] using flexible fill ...\n";
  RCP<Thyra::PhysicallyBlockedLinearOpBase<Scalar> >
    A9_b = rcp(new Thyra::DefaultBlockedLinearOp<Scalar>());
  A9_b->beginBlockFill();
  A9_b->setBlock(0,0,A6);
  A9_b->setBlock(0,1,adjoint(A1));
  A9_b->setBlock(1,0,A1);
  A9_b->endBlockFill();
  if (nonnull(out)) *out << "\nA9_b =\n" << describe(*A9_b,verbLevel);

  if (nonnull(out)) *out << "\nTesting A9_b ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A9_b,out.ptr());
  if(!result) success = false;
  // Note that testing the symmetry above helps to check the transpose mode
  // against the non-transpose mode!

  if (nonnull(out)) *out << "\nComparing A9 == A9_b ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.compare(*A9,*A9_b,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A9a = [ null, A1^H; A1, null ] ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A9a = Thyra::block2x2<Scalar>(
      nullOp,  adjoint(A1),
      A1,      nullOp
      );
  if (nonnull(out)) *out << "\nA9a =\n" << describe(*A9a,verbLevel);

  if (nonnull(out)) *out << "\nTesting A9a ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A9a,out.ptr());
  if(!result) success = false;
  // Note that testing the symmetry above helps to check the transpose mode
  // against the non-transpose mode!

#ifdef TEUCHOS_DEBUG
  if (nonnull(out)) *out << "\nCreating an invalid blocked 2x2 operator A9b = [ A6, A1^H; A1, A1 ] (should throw an exception) ...\n\n";
  try {
    RCP<const Thyra::LinearOpBase<Scalar> >
      A9b = Thyra::block2x2<Scalar>(
        A6,  adjoint(A1),
        A1,  A1
        );
    result = true;
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result)
  if (nonnull(out))
    *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n");
  if(result) success = false;
#endif // TEUCHOS_DEBUG

#ifdef TEUCHOS_DEBUG
  if (nonnull(out)) *out << "\nCreating an invalid blocked 2x2 operator A9c = [ A1, A1 ; null, null ] (should throw an exception) ...\n\n";
  try {
    RCP<const Thyra::LinearOpBase<Scalar> >
      A9c = Thyra::block2x2<Scalar>(
        A1,       A1,
        nullOp,   nullOp
        );
    result = true;
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result)
  if (nonnull(out))
    *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n");
  if(result) success = false;
#endif // TEUCHOS_DEBUG

#ifdef TEUCHOS_DEBUG
  if (nonnull(out)) *out << "\nCreating an invalid blocked 2x2 operator A9d = [ A1, null; A1, null ] (should throw an exception) ...\n\n";
  try {
    RCP<const Thyra::LinearOpBase<Scalar> >
      A9d = Thyra::block2x2<Scalar>(
        A1,  nullOp,
        A1,  nullOp
        );
    result = true;
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,out.get()?*out:std::cerr,result)
  if (nonnull(out))
    *out << "\nCaught expected exception : " << (result?"failed\n":"passed\n");
  if(result) success = false;
#endif // TEUCHOS_DEBUG

  if (nonnull(out)) *out << "\nCreating a blocked 2x1 linear operator A10 = [ A6; A1 ] ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A10 = Thyra::block2x1<Scalar>(
      A6,
      A1
      );
  if (nonnull(out)) *out << "\nA10 =\n" << describe(*A10,verbLevel);

  if (nonnull(out)) *out << "\nTesting A10 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A10,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a blocked 1x2 linear operator A11 = [ A9, A10 ] ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A11 = Thyra::block1x2<Scalar>( A9, A10 );
  if (nonnull(out)) *out << "\nA11 =\n" << describe(*A11,verbLevel);

  if (nonnull(out)) *out << "\nTesting A11 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A11,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a zero linear operator A12 = 0 (range and domain spaces of origA) ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A12 = Thyra::zero(origA->range(),origA->domain());
  if (nonnull(out)) *out << "\nA12 =\n" << describe(*A12,verbLevel);

  if (nonnull(out)) *out << "\nTesting A12 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.check(*A12,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a blocked 2x2 linear operator A13 = [ zero, A1^H; A1, zero ] ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A13 = Thyra::block2x2<Scalar>(
      Thyra::zero(A1->domain(),A1->domain()),   adjoint(A1),
      A1,                                       Thyra::zero(A1->range(),A1->range())
      );
  if (nonnull(out)) *out << "\nA13 =\n" << describe(*A13,verbLevel);

  if (nonnull(out)) *out << "\nComparing A9a == A13 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = linearOpTester.compare(*A9a,*A13,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\nCreating a zero linear operator A14 = I (range space of origA) ...\n";
  RCP<const Thyra::LinearOpBase<Scalar> >
    A14 = Thyra::identity(origA->range());
  if (nonnull(out)) *out << "\nA14 =\n" << describe(*A14,verbLevel);

  if (nonnull(out)) *out << "\nTesting A14 ...\n";
  Thyra::seed_randomize<Scalar>(0);
  result = symLinearOpTester.check(*A14,out.ptr());
  if(!result) success = false;

  if (nonnull(out)) *out << "\n*** Leaving run_composite_linear_ops_tests<"<<ST::name()<<">(...) ...\n";

  return success;

} // end run_composite_linear_ops_tests() [Doxygen looks for this!]
int main(int argc, char* argv[])
{

    using Teuchos::describe;
    using Teuchos::rcp;
    using Teuchos::rcp_dynamic_cast;
    using Teuchos::rcp_const_cast;
    using Teuchos::RCP;
    using Teuchos::CommandLineProcessor;
    using Teuchos::ParameterList;
    using Teuchos::sublist;
    using Teuchos::getParametersFromXmlFile;
    typedef ParameterList::PrintOptions PLPrintOptions;
    using Thyra::inverse;
    using Thyra::initializePreconditionedOp;
    using Thyra::initializeOp;
    using Thyra::unspecifiedPrec;
    using Thyra::solve;
    typedef RCP<const Thyra::LinearOpBase<double> > LinearOpPtr;
    typedef RCP<Thyra::VectorBase<double> > VectorPtr;

    bool success = true;
    bool verbose = true;

    Teuchos::GlobalMPISession mpiSession(&argc,&argv);

    Teuchos::RCP<Teuchos::FancyOStream>
    out = Teuchos::VerboseObjectBase::getDefaultOStream();

    try {

        //
        // Read in options from the command line
        //

        CommandLineProcessor clp(false); // Don't throw exceptions

        const int numVerbLevels = 6;
        Teuchos::EVerbosityLevel
        verbLevelValues[] =
        {
            Teuchos::VERB_DEFAULT, Teuchos::VERB_NONE,
            Teuchos::VERB_LOW, Teuchos::VERB_MEDIUM,
            Teuchos::VERB_HIGH, Teuchos::VERB_EXTREME
        };
        const char*
        verbLevelNames[] =
        { "default", "none", "low", "medium", "high", "extreme" };

        Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_MEDIUM;
        clp.setOption( "verb-level", &verbLevel,
                       numVerbLevels, verbLevelValues, verbLevelNames,
                       "Verbosity level used for all objects."
                     );

        std::string matrixFile = ".";
        clp.setOption( "matrix-file", &matrixFile,
                       "Matrix file."
                     );

        std::string paramListFile = "";
        clp.setOption( "param-list-file", &paramListFile,
                       "Parameter list for preconditioner and solver blocks."
                     );

        bool showParams = false;
        clp.setOption( "show-params", "no-show-params", &showParams,
                       "Show the parameter list or not."
                     );

        bool testPrecIsLinearOp = true;
        clp.setOption( "test-prec-is-linear-op", "test-prec-is-linear-op", &testPrecIsLinearOp,
                       "Test if the preconditioner is a linear operator or not."
                     );

        double solveTol = 1e-8;
        clp.setOption( "solve-tol", &solveTol,
                       "Tolerance for the solution to determine success or failure!"
                     );

        clp.setDocString(
            "This example program shows how to use one linear solver (e.g. AztecOO)\n"
            "as a preconditioner for another iterative solver (e.g. Belos).\n"
        );

        // Note: Use --help on the command line to see the above documentation

        CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
        if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;


        //
        *out << "\nA) Reading in the matrix ...\n";
        //

#ifdef HAVE_MPI
        Epetra_MpiComm comm(MPI_COMM_WORLD);
#else
        Epetra_SerialComm comm;
#endif

        const LinearOpPtr A = readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
                                  matrixFile, comm, "A");
        *out << "\nA = " << describe(*A,verbLevel) << "\n";

        const RCP<ParameterList> paramList = getParametersFromXmlFile(paramListFile);
        if (showParams) {
            *out << "\nRead in parameter list:\n\n";
            paramList->print(*out, PLPrintOptions().indent(2).showTypes(true));
        }

        //
        *out << "\nB) Get the preconditioner as a forward solver\n";
        //

        const RCP<ParameterList> precParamList = sublist(paramList, "Preconditioner Solver");
        Stratimikos::DefaultLinearSolverBuilder precSolverBuilder;
        precSolverBuilder.setParameterList(precParamList);
        const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > precSolverStrategy
            = createLinearSolveStrategy(precSolverBuilder);
        //precSolverStrategy->setVerbLevel(verbLevel);

        const LinearOpPtr A_inv_prec = inverse<double>(*precSolverStrategy, A,
                                       Thyra::SUPPORT_SOLVE_FORWARD_ONLY,
                                       Teuchos::null, // Use internal solve criteria
                                       Thyra::IGNORE_SOLVE_FAILURE // Ignore solve failures since this is just a prec
                                                      );
        *out << "\nA_inv_prec = " << describe(*A_inv_prec, verbLevel) << "\n";

        if (testPrecIsLinearOp) {
            *out << "\nTest that the preconditioner A_inv_prec is indeed a linear operator.\n";
            Thyra::LinearOpTester<double> linearOpTester;
            linearOpTester.check_adjoint(false);
            const bool linearOpCheck = linearOpTester.check(*A_inv_prec, out.ptr());
            if (!linearOpCheck) {
                success = false;
            }
        }

        //
        *out << "\nC) Create the forward solver using the created preconditioner ...\n";
        //

        const RCP<ParameterList> fwdSolverParamList = sublist(paramList, "Forward Solver");
        Stratimikos::DefaultLinearSolverBuilder fwdSolverSolverBuilder;
        fwdSolverSolverBuilder.setParameterList(fwdSolverParamList);
        const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > fwdSolverSolverStrategy
            = createLinearSolveStrategy(fwdSolverSolverBuilder);

        const RCP<Thyra::LinearOpWithSolveBase<double> >
        A_lows = fwdSolverSolverStrategy->createOp();

        initializePreconditionedOp<double>( *fwdSolverSolverStrategy, A,
                                            unspecifiedPrec(A_inv_prec), A_lows.ptr());
        //A_lows->setVerbLevel(verbLevel);
        *out << "\nA_lows = " << describe(*A_lows, verbLevel) << "\n";

        //
        *out << "\nD) Solve the linear system for a random RHS ...\n";
        //

        VectorPtr x = createMember(A->domain());
        VectorPtr b = createMember(A->range());
        Thyra::randomize(-1.0, +1.0, b.ptr());
        Thyra::assign(x.ptr(), 0.0); // Must give an initial guess!

        Thyra::SolveStatus<double>
        solveStatus = solve<double>( *A_lows, Thyra::NOTRANS, *b, x.ptr() );

        *out << "\nSolve status:\n" << solveStatus;

        *out << "\nSolution ||x|| = " << Thyra::norm(*x) << "\n";

        if(showParams) {
            *out << "\nParameter list after use:\n\n";
            paramList->print(*out, PLPrintOptions().indent(2).showTypes(true));
        }

        //
        *out << "\nF) Checking the error in the solution of r=b-A*x ...\n";
        //

        VectorPtr Ax = Thyra::createMember(b->space());
        Thyra::apply( *A, Thyra::NOTRANS, *x, Ax.ptr() );
        VectorPtr r = Thyra::createMember(b->space());
        Thyra::V_VmV<double>(r.ptr(), *b, *Ax);

        double
        Ax_nrm = Thyra::norm(*Ax),
        r_nrm = Thyra::norm(*r),
        b_nrm = Thyra::norm(*b),
        r_nrm_over_b_nrm = r_nrm / b_nrm;

        bool resid_tol_check = ( r_nrm_over_b_nrm <= solveTol );
        if(!resid_tol_check) success = false;

        *out
                << "\n||A*x|| = " << Ax_nrm << "\n";

        *out
                << "\n||A*x-b||/||b|| = " << r_nrm << "/" << b_nrm
                << " = " << r_nrm_over_b_nrm << " <= " << solveTol
                << " : " << Thyra::passfail(resid_tol_check) << "\n";

        Teuchos::TimeMonitor::summarize(*out<<"\n");
    }
    TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success)

    if (verbose) {
        if(success)  *out << "\nCongratulations! All of the tests checked out!\n";
        else         *out << "\nOh no! At least one of the tests failed!\n";
    }

    return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
}
TEUCHOS_UNIT_TEST(tProbingFactory, parameterlist_constr)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp lo = buildSystem(Comm,10);
   
   Teuchos::RCP<Teko::InverseLibrary> invLib = Teko::InverseLibrary::buildFromStratimikos();
   Teuchos::RCP<Teko::InverseFactory> directSolveFactory = invLib->getInverseFactory("Amesos");

   {
      Teuchos::ParameterList pl;
      pl.set("Inverse Type","Amesos");
      pl.set("Probing Graph Operator",lo);
   
      Teuchos::RCP<Teko::ProbingPreconditionerFactory> probeFact
            = rcp(new Teko::ProbingPreconditionerFactory);
      probeFact->initializeFromParameterList(pl);
   
      RCP<Teko::InverseFactory> invFact = Teuchos::rcp(new Teko::PreconditionerInverseFactory(probeFact,Teuchos::null));
   
      Teko::LinearOp probedInverse = Teko::buildInverse(*invFact,lo);
      Teko::LinearOp invLo = Teko::buildInverse(*directSolveFactory,lo);
   
      Thyra::LinearOpTester<double> tester;
      tester.dump_all(true);
      tester.show_all_tests(true);
   
      {
         const bool result = tester.compare( *probedInverse, *invLo, &out);
         if (!result) {
            out << "Apply: FAILURE" << std::endl;
            success = false;
         }
         else
            out << "Apply: SUCCESS" << std::endl;
      }
   }

   {
      Teuchos::RCP<const Epetra_CrsGraph> theGraph
            = rcpFromRef(rcp_dynamic_cast<const Epetra_CrsMatrix>(Thyra::get_Epetra_Operator(*lo))->Graph());

      Teuchos::ParameterList pl;
      pl.set("Inverse Type","Amesos");
      pl.set("Probing Graph",theGraph);
   
      Teuchos::RCP<Teko::ProbingPreconditionerFactory> probeFact
            = rcp(new Teko::ProbingPreconditionerFactory);
      probeFact->initializeFromParameterList(pl);
   
      RCP<Teko::InverseFactory> invFact = Teuchos::rcp(new Teko::PreconditionerInverseFactory(probeFact,Teuchos::null));
   
      Teko::LinearOp probedInverse = Teko::buildInverse(*invFact,lo);
      Teko::LinearOp invLo = Teko::buildInverse(*directSolveFactory,lo);
   
      Thyra::LinearOpTester<double> tester;
      tester.dump_all(true);
      tester.show_all_tests(true);
   
      {
         const bool result = tester.compare( *probedInverse, *invLo, &out);
         if (!result) {
            out << "Apply: FAILURE" << std::endl;
            success = false;
         }
         else
            out << "Apply: SUCCESS" << std::endl;
      }
   }
}
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)));
}
TEUCHOS_UNIT_TEST(tIterativePreconditionerFactory, parameter_list_init)
{
   // build global (or serial communicator)
   #ifdef HAVE_MPI
      Epetra_MpiComm Comm(MPI_COMM_WORLD);
   #else
      Epetra_SerialComm Comm;
   #endif

   Teko::LinearOp  A = build2x2(Comm,1,2,3,4);

   Thyra::LinearOpTester<double> tester;
   tester.show_all_tests(true);

   {
      RCP<Teuchos::ParameterList> pl = buildLibPL(4,"Amesos");
      RCP<Teko::IterativePreconditionerFactory> precFact = rcp(new Teko::IterativePreconditionerFactory());
      RCP<Teko::InverseFactory> invFact = rcp(new Teko::PreconditionerInverseFactory(precFact,Teuchos::null));

      try {
         precFact->initializeFromParameterList(*pl);
         out << "Passed correct parameter list" << std::endl;

         Teko::LinearOp prec = Teko::buildInverse(*invFact,A);
      }
      catch(...) {
         success = false; 
         out << "Failed correct parameter list" << std::endl;
      }
   }

   {
      Teuchos::ParameterList pl;
      pl.set("Preconditioner Type","Amesos");

      RCP<Teko::IterativePreconditionerFactory> precFact = rcp(new Teko::IterativePreconditionerFactory());
      RCP<Teko::InverseFactory> invFact = rcp(new Teko::PreconditionerInverseFactory(precFact,Teuchos::null));

      try {
         precFact->initializeFromParameterList(pl);
         out << "Passed iteration count" << std::endl;

         Teko::LinearOp prec = Teko::buildInverse(*invFact,A);
      }
      catch(...) {
         out << "Failed iteration count" << std::endl;
      }
   }

   {
      Teuchos::ParameterList pl;
      pl.set("Iteration Count",4);
      pl.set("Precondiioner Type","Amesos");

      RCP<Teko::IterativePreconditionerFactory> precFact = rcp(new Teko::IterativePreconditionerFactory());

      try {
         precFact->initializeFromParameterList(pl);
         success = false;
         out << "Failed preconditioner type" << std::endl;

         // these should not be executed
         RCP<Teko::InverseFactory> invFact = rcp(new Teko::PreconditionerInverseFactory(precFact,Teuchos::null));
         Teko::LinearOp prec = Teko::buildInverse(*invFact,A);
      }
      catch(const std::exception & exp) {
         out << "Passed preconditioner type" << std::endl;
      }
   }
}