Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ForwardSolverAsPreconditioner.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stratimikos: Thyra-based strategies for linear solvers
4 //
5 // Copyright 2006 NTESS and the Stratimikos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
12 #include "Thyra_PreconditionerFactoryHelpers.hpp"
13 #include "Thyra_DefaultInverseLinearOp.hpp"
14 #include "Thyra_DefaultMultipliedLinearOp.hpp"
16 #include "Thyra_EpetraLinearOp.hpp"
18 #include "Thyra_TestingTools.hpp"
19 #include "Thyra_LinearOpTester.hpp"
20 #include "EpetraExt_CrsMatrixIn.h"
21 #include "Epetra_CrsMatrix.h"
27 #include "Teuchos_TimeMonitor.hpp"
28 #ifdef HAVE_MPI
29 # include "Epetra_MpiComm.h"
30 #else
31 # include "Epetra_SerialComm.h"
32 #endif
33 
34 
43 namespace {
44 
45 
46 // Read a Epetra_CrsMatrix from a Matrix market file
48 readEpetraCrsMatrixFromMatrixMarket(
49  const std::string fileName, const Epetra_Comm &comm
50  )
51 {
52  Epetra_CrsMatrix *A = 0;
54  0!=EpetraExt::MatrixMarketFileToCrsMatrix( fileName.c_str(), comm, A ),
55  std::runtime_error,
56  "Error, could not read matrix file \""<<fileName<<"\"!"
57  );
58  return Teuchos::rcp(A);
59 }
60 
61 
62 // Read an Epetra_CrsMatrix in as a wrapped Thyra::EpetraLinearOp object
64 readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
65  const std::string fileName, const Epetra_Comm &comm,
66  const std::string &label
67  )
68 {
69  return Thyra::epetraLinearOp(
70  readEpetraCrsMatrixFromMatrixMarket(fileName,comm),label
71  );
72 }
73 
74 
75 } // namespace
76 
77 
78 int main(int argc, char* argv[])
79 {
80 
81  using Teuchos::describe;
82  using Teuchos::rcp;
83  using Teuchos::rcp_dynamic_cast;
84  using Teuchos::rcp_const_cast;
85  using Teuchos::RCP;
88  using Teuchos::sublist;
89  using Teuchos::getParametersFromXmlFile;
90  typedef ParameterList::PrintOptions PLPrintOptions;
91  using Thyra::inverse;
92  using Thyra::initializePreconditionedOp;
93  using Thyra::initializeOp;
94  using Thyra::unspecifiedPrec;
95  using Thyra::solve;
96  typedef RCP<const Thyra::LinearOpBase<double> > LinearOpPtr;
97  typedef RCP<Thyra::VectorBase<double> > VectorPtr;
98 
99  bool success = true;
100  bool verbose = true;
101 
102  Teuchos::GlobalMPISession mpiSession(&argc,&argv);
103 
105  out = Teuchos::VerboseObjectBase::getDefaultOStream();
106 
107  try {
108 
109  //
110  // Read in options from the command line
111  //
112 
113  CommandLineProcessor clp(false); // Don't throw exceptions
114 
115  const int numVerbLevels = 6;
117  verbLevelValues[] =
118  {
122  };
123  const char*
124  verbLevelNames[] =
125  { "default", "none", "low", "medium", "high", "extreme" };
126 
128  clp.setOption( "verb-level", &verbLevel,
129  numVerbLevels, verbLevelValues, verbLevelNames,
130  "Verbosity level used for all objects."
131  );
132 
133  std::string matrixFile = ".";
134  clp.setOption( "matrix-file", &matrixFile,
135  "Matrix file."
136  );
137 
138  std::string paramListFile = "";
139  clp.setOption( "param-list-file", &paramListFile,
140  "Parameter list for preconditioner and solver blocks."
141  );
142 
143  bool showParams = false;
144  clp.setOption( "show-params", "no-show-params", &showParams,
145  "Show the parameter list or not."
146  );
147 
148  bool testPrecIsLinearOp = true;
149  clp.setOption( "test-prec-is-linear-op", "test-prec-is-linear-op", &testPrecIsLinearOp,
150  "Test if the preconditioner is a linear operator or not."
151  );
152 
153  double solveTol = 1e-8;
154  clp.setOption( "solve-tol", &solveTol,
155  "Tolerance for the solution to determine success or failure!"
156  );
157 
158  clp.setDocString(
159  "This example program shows how to use one linear solver (e.g. AztecOO)\n"
160  "as a preconditioner for another iterative solver (e.g. Belos).\n"
161  );
162 
163  // Note: Use --help on the command line to see the above documentation
164 
165  CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
166  if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
167 
168 
169  //
170  *out << "\nA) Reading in the matrix ...\n";
171  //
172 
173 #ifdef HAVE_MPI
174  Epetra_MpiComm comm(MPI_COMM_WORLD);
175 #else
176  Epetra_SerialComm comm;
177 #endif
178 
179  const LinearOpPtr A = readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
180  matrixFile, comm, "A");
181  *out << "\nA = " << describe(*A,verbLevel) << "\n";
182 
183  const RCP<ParameterList> paramList = getParametersFromXmlFile(paramListFile);
184  if (showParams) {
185  *out << "\nRead in parameter list:\n\n";
186  paramList->print(*out, PLPrintOptions().indent(2).showTypes(true));
187  }
188 
189  //
190  *out << "\nB) Get the preconditioner as a forward solver\n";
191  //
192 
193  const RCP<ParameterList> precParamList = sublist(paramList, "Preconditioner Solver");
194  Stratimikos::DefaultLinearSolverBuilder precSolverBuilder;
195  precSolverBuilder.setParameterList(precParamList);
196  const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > precSolverStrategy
197  = createLinearSolveStrategy(precSolverBuilder);
198  //precSolverStrategy->setVerbLevel(verbLevel);
199 
200  const LinearOpPtr A_inv_prec = inverse<double>(*precSolverStrategy, A,
201  Thyra::SUPPORT_SOLVE_FORWARD_ONLY,
202  Teuchos::null, // Use internal solve criteria
203  Thyra::IGNORE_SOLVE_FAILURE // Ignore solve failures since this is just a prec
204  );
205  *out << "\nA_inv_prec = " << describe(*A_inv_prec, verbLevel) << "\n";
206 
207  if (testPrecIsLinearOp) {
208  *out << "\nTest that the preconditioner A_inv_prec is indeed a linear operator.\n";
209  Thyra::LinearOpTester<double> linearOpTester;
210  linearOpTester.check_adjoint(false);
211  const bool linearOpCheck = linearOpTester.check(*A_inv_prec, out.ptr());
212  if (!linearOpCheck) { success = false; }
213  }
214 
215  //
216  *out << "\nC) Create the forward solver using the created preconditioner ...\n";
217  //
218 
219  const RCP<ParameterList> fwdSolverParamList = sublist(paramList, "Forward Solver");
220  Stratimikos::DefaultLinearSolverBuilder fwdSolverSolverBuilder;
221  fwdSolverSolverBuilder.setParameterList(fwdSolverParamList);
222  const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > fwdSolverSolverStrategy
223  = createLinearSolveStrategy(fwdSolverSolverBuilder);
224 
225  const RCP<Thyra::LinearOpWithSolveBase<double> >
226  A_lows = fwdSolverSolverStrategy->createOp();
227 
228  initializePreconditionedOp<double>( *fwdSolverSolverStrategy, A,
229  unspecifiedPrec(A_inv_prec), A_lows.ptr());
230  //A_lows->setVerbLevel(verbLevel);
231  *out << "\nA_lows = " << describe(*A_lows, verbLevel) << "\n";
232 
233  //
234  *out << "\nD) Solve the linear system for a random RHS ...\n";
235  //
236 
237  VectorPtr x = createMember(A->domain());
238  VectorPtr b = createMember(A->range());
239  Thyra::randomize(-1.0, +1.0, b.ptr());
240  Thyra::assign(x.ptr(), 0.0); // Must give an initial guess!
241 
242  Thyra::SolveStatus<double>
243  solveStatus = solve<double>( *A_lows, Thyra::NOTRANS, *b, x.ptr() );
244 
245  *out << "\nSolve status:\n" << solveStatus;
246 
247  *out << "\nSolution ||x|| = " << Thyra::norm(*x) << "\n";
248 
249  if(showParams) {
250  *out << "\nParameter list after use:\n\n";
251  paramList->print(*out, PLPrintOptions().indent(2).showTypes(true));
252  }
253 
254  //
255  *out << "\nF) Checking the error in the solution of r=b-A*x ...\n";
256  //
257 
258  VectorPtr Ax = Thyra::createMember(b->space());
259  Thyra::apply( *A, Thyra::NOTRANS, *x, Ax.ptr() );
260  VectorPtr r = Thyra::createMember(b->space());
261  Thyra::V_VmV<double>(r.ptr(), *b, *Ax);
262 
263  double
264  Ax_nrm = Thyra::norm(*Ax),
265  r_nrm = Thyra::norm(*r),
266  b_nrm = Thyra::norm(*b),
267  r_nrm_over_b_nrm = r_nrm / b_nrm;
268 
269  bool resid_tol_check = ( r_nrm_over_b_nrm <= solveTol );
270  if(!resid_tol_check) success = false;
271 
272  *out
273  << "\n||A*x|| = " << Ax_nrm << "\n";
274 
275  *out
276  << "\n||A*x-b||/||b|| = " << r_nrm << "/" << b_nrm
277  << " = " << r_nrm_over_b_nrm << " <= " << solveTol
278  << " : " << Thyra::passfail(resid_tol_check) << "\n";
279 
281  }
282  TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success)
283 
284  if (verbose) {
285  if(success) *out << "\nCongratulations! All of the tests checked out!\n";
286  else *out << "\nOh no! At least one of the tests failed!\n";
287  }
288 
289  return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
290 }
int main(int argc, char *argv[])
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void setParameterList(RCP< ParameterList > const &paramList)
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)
Ptr< T > ptr() const
ParameterList::PrintOptions PLPrintOptions
Concrete subclass of Thyra::LinearSolverBuilderBase for creating Thyra::LinearOpWithSolveFactoryBase ...