43 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp" 
   44 #include "Thyra_PreconditionerFactoryHelpers.hpp" 
   45 #include "Thyra_DefaultInverseLinearOp.hpp" 
   46 #include "Thyra_DefaultMultipliedLinearOp.hpp" 
   50 #include "Thyra_TestingTools.hpp" 
   51 #include "EpetraExt_CrsMatrixIn.h" 
   52 #include "Epetra_CrsMatrix.h" 
   60 #  include "Epetra_MpiComm.h" 
   62 #  include "Epetra_SerialComm.h" 
   80 readEpetraCrsMatrixFromMatrixMarket(
 
   81   const std::string fileName, 
const Epetra_Comm &comm
 
   84   Epetra_CrsMatrix *
A = 0;
 
   86     0!=EpetraExt::MatrixMarketFileToCrsMatrix( fileName.c_str(), comm, A ),
 
   88     "Error, could not read matrix file \""<<fileName<<
"\"!" 
   96 readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
   97   const std::string fileName, 
const Epetra_Comm &comm,
 
   98   const std::string &label
 
  101   return Thyra::epetraLinearOp(
 
  102     readEpetraCrsMatrixFromMatrixMarket(fileName,comm),label
 
  110 int main(
int argc, 
char* argv[])
 
  113   using Teuchos::describe;
 
  115   using Teuchos::rcp_dynamic_cast;
 
  116   using Teuchos::rcp_const_cast;
 
  120   using Teuchos::sublist;
 
  122   using Thyra::inverse;
 
  123   using Thyra::initializePreconditionedOp;
 
  124   using Thyra::initializeOp;
 
  125   using Thyra::unspecifiedPrec;
 
  127   typedef RCP<const Thyra::LinearOpBase<double> > LinearOpPtr;
 
  128   typedef RCP<Thyra::VectorBase<double> > VectorPtr;
 
  136     out = Teuchos::VerboseObjectBase::getDefaultOStream();
 
  144     const int numVerbLevels = 6;
 
  154       { 
"default", 
"none", 
"low", 
"medium", 
"high", 
"extreme" };
 
  157     std::string paramsFile = 
"";
 
  158     std::string extraParamsFile = 
"";
 
  159     std::string baseDir = 
".";
 
  160     bool useP1Prec = 
true;
 
  161     bool invertP1 = 
false;
 
  162     bool showParams = 
false;
 
  163     double solveTol = 1e-8;
 
  165     CommandLineProcessor clp(
false); 
 
  167     clp.setOption( 
"verb-level", &verbLevel,
 
  168       numVerbLevels, verbLevelValues, verbLevelNames,
 
  169       "Verbosity level used for all objects." 
  171     clp.setOption( 
"params-file", ¶msFile,
 
  172       "File containing parameters in XML format.",
 
  175     clp.setOption( 
"extra-params-file", &extraParamsFile,
 
  176       "File containing extra parameters in XML format." 
  178     clp.setOption( 
"base-dir", &baseDir,
 
  179       "Base directory for all of the files." 
  181     clp.setOption( 
"use-P1-prec", 
"use-algebraic-prec", &useP1Prec,
 
  182       "Use the physics-based preconditioner for P2 based on P1 or just an algebraic preconditioner" 
  184     clp.setOption( 
"invert-P1", 
"prec-P1-only", &invertP1,
 
  185       "In the physics-based preconditioner, use P1's preconditioner or fully invert P1." 
  187     clp.setOption( 
"solve-tol", &solveTol,
 
  188       "Tolerance for the solution to determine success or failure!" 
  190     clp.setOption( 
"show-params", 
"no-show-params", &showParams,
 
  191       "Show the parameter list or not." 
  194       "This example program shows an attempt to create a physics-based\n" 
  195       "preconditioner using the building blocks of Stratimikos and Thyra\n" 
  196       "implicit linear operators.  The idea is to use the linear operator\n" 
  197       "for first-order Lagrange finite elements as the preconditioner for the\n" 
  198       "operator using second-order Lagrange finite elements.  The details of the\n" 
  199       "PDE being represented, the mesh being used, or the boundary conditions are\n" 
  200       "beyond the scope of this example.\n" 
  202       "The matrices used in this example are:\n" 
  204       "  P2: The discretized PDE matrix using second-order Lagrange finite elements.\n" 
  205       "  P1: The discretized PDE matrix using first-order Lagrange finite elements.\n" 
  206       "  M22: The mass matrix for the second-order Lagrange finite-element basis functions.\n" 
  207       "  M11: The mass matrix for the first-order Lagrange finite-element basis functions.\n" 
  208       "  M21: A rectangular matrix that uses mixed first- and second-order basis functions\n" 
  209       "       to map from P2 space to P1 space.\n" 
  210       "  M12: A rectangular matrix that uses mixed first- and second-order basis functions\n" 
  211       "       to map from P1 space to P2 space.\n" 
  213       "The above matrices are read from Matrix Market *.mtx files in the directory given by\n" 
  214       "the --base-dir command-line option.\n" 
  216       "The preconditioner operator created in this example program is:\n" 
  218       "   precP2Op = (inv(M22) * M12) * prec(P1) * (inv(M11) * M21)\n" 
  220       "where prec(P1) is either the algebraic preconditioner for P1 (--prec-P1-only)\n" 
  221       "or is a full solve for P1 (--invert-P1).\n" 
  223       "We use Stratimikos to specify the linear solvers and/or algebraic\n" 
  224       "preconditioners and we use the Thyra implicit operators to build the\n" 
  225       "implicitly multiplied linear operators associated with the preconditioner.\n" 
  227       "Warning!  This physics-based preconditioner is singular and can not\n" 
  228       "be used to solve the linear system given a random right-hand side.  However,\n" 
  229       "singular or not, this example shows how one can use Thyra/Stratimikos to quickly\n" 
  230       "try out these types of preconditioning ideas (even if they do not work).\n" 
  235     CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
 
  236     if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) 
return parse_return;
 
  240     *out << 
"\nA) Reading in Epetra_CrsMatrix objects for P1, P2, M11, M12, M21, and M22 ...\n";
 
  244     Epetra_MpiComm comm(MPI_COMM_WORLD);
 
  246     Epetra_SerialComm comm;
 
  249     LinearOpPtr P1=readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
  250       baseDir+
"/P1.mtx",comm,
"P1");
 
  251     *out << 
"\nP1 = " << describe(*P1,verbLevel) << 
"\n";
 
  252     LinearOpPtr P2= readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
  253       baseDir+
"/P2.mtx",comm,
"P2");
 
  254     *out << 
"\nP2 = " << describe(*P2,verbLevel) << 
"\n";
 
  255     LinearOpPtr M11=readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
  256       baseDir+
"/M11.mtx",comm,
"M11");
 
  257     *out << 
"\nM11 = " << describe(*M11,verbLevel) << 
"\n";
 
  258     LinearOpPtr M22=readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
  259       baseDir+
"/M22.mtx",comm,
"M22");
 
  260     *out << 
"\nM22 = " << describe(*M22,verbLevel) << 
"\n";
 
  261     LinearOpPtr M12=readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
  262       baseDir+
"/M12.mtx",comm,
"M12");
 
  263     *out << 
"\nM12 = " << describe(*M12,verbLevel) << 
"\n";
 
  264     LinearOpPtr M21=readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
 
  265       baseDir+
"/M21.mtx",comm,
"M21");
 
  266     *out << 
"\nM21 = " << describe(*M21,verbLevel) << 
"\n";
 
  272     *out << 
"\nB) Get the preconditioner and/or linear solver strategies to invert M11, M22, P1, and P2 ...\n";
 
  280     RCP<ParameterList> paramList =
 
  281       Teuchos::getParametersFromXmlFile( baseDir+
"/"+paramsFile );
 
  282     if (extraParamsFile.length()) {
 
  283       Teuchos::updateParametersFromXmlFile( baseDir+
"/"+extraParamsFile, paramList.ptr() );
 
  286       *out << 
"\nRead in parameter list:\n\n";
 
  287       paramList->print(*out,PLPrintOptions().indent(2).showTypes(
true));
 
  292       sublist(paramList,
"M11 Solver",
true) );
 
  296       sublist(paramList,
"M22 Solver",
true) );
 
  300       sublist(paramList,
"P1 Solver",
true) );
 
  304       sublist(paramList,
"P2 Solver",
true) );
 
  314     RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > M11_linsolve_strategy
 
  315       = createLinearSolveStrategy(M11_linsolve_strategy_builder);
 
  317     RCP<Thyra::LinearOpWithSolveFactoryBase<double> > M22_linsolve_strategy
 
  318       = createLinearSolveStrategy(M22_linsolve_strategy_builder);
 
  322     RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > P1_linsolve_strategy;
 
  323     RCP<const Thyra::PreconditionerFactoryBase<double> > P1_prec_strategy;
 
  326         = createLinearSolveStrategy(P1_linsolve_strategy_builder);
 
  329         = createPreconditioningStrategy(P1_linsolve_strategy_builder);
 
  334     RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > P2_linsolve_strategy
 
  335       = createLinearSolveStrategy(P2_linsolve_strategy_builder);
 
  338     *out << 
"\nC) Create the physics-based preconditioner! ...\n";
 
  341     *out << 
"\nCreating inv(M11) ...\n";
 
  342     LinearOpPtr invM11 = inverse(*M11_linsolve_strategy, M11);
 
  343     *out << 
"\ninvM11 = " << describe(*invM11,verbLevel) << 
"\n";
 
  345     *out << 
"\nCreating inv(M22) ...\n";
 
  346     LinearOpPtr invM22 = inverse(*M22_linsolve_strategy, M22);
 
  347     *out << 
"\ninvM22 = " << describe(*invM22,verbLevel) << 
"\n";
 
  349     *out << 
"\nCreating prec(P1) ...\n";
 
  352       *out << 
"\nCreating prec(P1) as a full solver ...\n";
 
  353       invP1 = inverse(*P1_linsolve_strategy, P1);
 
  356       *out << 
"\nCreating prec(P1) as just an algebraic preconditioner ...\n";
 
  357       RCP<Thyra::PreconditionerBase<double> >
 
  358         precP1 = prec(*P1_prec_strategy,P1);
 
  359       *out << 
"\nprecP1 = " << describe(*precP1,verbLevel) << 
"\n";
 
  360       invP1 = precP1->getUnspecifiedPrecOp();
 
  362     rcp_const_cast<Thyra::LinearOpBase<double> >(
 
  363       invP1)->setObjectLabel(
"invP1"); 
 
  364     *out << 
"\ninvP1 = " << describe(*invP1,verbLevel) << 
"\n";
 
  366     LinearOpPtr P2ToP1 = multiply( invM11, M21 );
 
  367     *out << 
"\nP2ToP1 = " << describe(*P2ToP1,verbLevel) << 
"\n";
 
  369     LinearOpPtr P1ToP2 = multiply( invM22, M12 );
 
  370     *out << 
"\nP1ToP2 = " << describe(*P1ToP2,verbLevel) << 
"\n";
 
  372     LinearOpPtr precP2Op = multiply( P1ToP2, invP1, P2ToP1 );
 
  373     *out << 
"\nprecP2Op = " << describe(*precP2Op,verbLevel) << 
"\n";
 
  376     *out << 
"\nD) Setup the solver for P2 ...\n";
 
  379     RCP<Thyra::LinearOpWithSolveBase<double> >
 
  380       P2_lows = P2_linsolve_strategy->createOp();
 
  382       *out << 
"\nCreating the solver P2 using the specialized precP2Op\n";
 
  383       initializePreconditionedOp<double>( *P2_linsolve_strategy, P2,
 
  384         unspecifiedPrec(precP2Op), P2_lows.ptr());
 
  387       *out << 
"\nCreating the solver P2 using algebraic preconditioner\n";
 
  388       initializeOp(*P2_linsolve_strategy, P2, P2_lows.ptr());
 
  390     *out << 
"\nP2_lows = " << describe(*P2_lows, verbLevel) << 
"\n";
 
  393     *out << 
"\nE) Solve P2 for a random RHS ...\n";
 
  396     VectorPtr x = createMember(P2->domain());
 
  397     VectorPtr b = createMember(P2->range());
 
  398     Thyra::randomize(-1.0, +1.0, b.ptr());
 
  399     Thyra::assign(x.ptr(), 0.0); 
 
  401     Thyra::SolveStatus<double>
 
  402       solveStatus = solve<double>( *P2_lows, Thyra::NOTRANS, *b, x.ptr() );
 
  404     *out << 
"\nSolve status:\n" << solveStatus;
 
  406     *out << 
"\nSolution ||x|| = " << Thyra::norm(*x) << 
"\n";
 
  409       *out << 
"\nParameter list after use:\n\n";
 
  410       paramList->print(*out, PLPrintOptions().indent(2).showTypes(
true));
 
  414     *out << 
"\nF) Checking the error in the solution of r=b-P2*x ...\n";
 
  417     VectorPtr P2x = Thyra::createMember(b->space());
 
  418     Thyra::apply( *P2, Thyra::NOTRANS, *x, P2x.ptr() );
 
  419     VectorPtr r = Thyra::createMember(b->space());
 
  420     Thyra::V_VmV<double>(r.ptr(), *b, *P2x);
 
  423       P2x_nrm = Thyra::norm(*P2x),
 
  424       r_nrm = Thyra::norm(*r),
 
  425       b_nrm = Thyra::norm(*b),
 
  426       r_nrm_over_b_nrm = r_nrm / b_nrm;
 
  428     bool result = r_nrm_over_b_nrm <= solveTol;
 
  429     if(!result) success = 
false;
 
  432       << 
"\n||P2*x|| = " << P2x_nrm << 
"\n";
 
  435       << 
"\n||P2*x-b||/||b|| = " << r_nrm << 
"/" << b_nrm
 
  436       << 
" = " << r_nrm_over_b_nrm << 
" <= " << solveTol
 
  437       << 
" : " << Thyra::passfail(result) << 
"\n";
 
  444     if(success)  *out << 
"\nCongratulations! All of the tests checked out!\n";
 
  445     else         *out << 
"\nOh no! At least one of the tests failed!\n";
 
  448   return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
 
int main(int argc, char *argv[])
 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
 
void setParameterList(RCP< ParameterList > const ¶mList)
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
 
static void summarize(Ptr< const Comm< int > > comm, std::ostream &out=std::cout, const bool alwaysWriteLocal=false, const bool writeGlobalStats=true, const bool writeZeroTimers=true, const ECounterSetOp setOp=Intersection, const std::string &filter="", const bool ignoreZeroTimers=false)
 
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
 
ParameterList::PrintOptions PLPrintOptions
 
Concrete subclass of Thyra::LinearSolverBuilderBase for creating LinearOpWithSolveFactoryBase objects...