Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
simple_tpetra_stratimikos_example.cpp
Go to the documentation of this file.
1 #include "Tpetra_Core.hpp"
2 #include "Tpetra_CrsMatrix.hpp"
3 #include "Tpetra_Vector.hpp"
6 #include "Thyra_LinearOpTester.hpp"
7 #include "Thyra_LinearOpWithSolveTester.hpp"
8 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
10 #include "Thyra_TpetraVector.hpp"
11 #include "MatrixMarket_Tpetra.hpp"
15 
16 
17 namespace {
18 
19 // Helper function to compute a single norm for a vector
20 template<class Scalar, class LO, class GO, class Node>
21 double tpetraNorm2( const Tpetra::Vector<Scalar,LO,GO,Node> &v )
22 {
24  norm[0] = -1.0;
25  v.norm2(norm());
26  return norm[0];
27 }
28 
29 } // namespace
30 
31 
32 bool readAndSolveLinearSystem(int argc, char* argv[])
33 {
34 
35  using Teuchos::rcp;
36  using Teuchos::RCP;
37  using Teuchos::rcp_dynamic_cast;
41 
42  using Scalar = double;
43  using LocalOrdinal = Tpetra::Map<>::local_ordinal_type;
44  using GlobalOrdinal = Tpetra::Map<>::global_ordinal_type;
45  using NodeType = Tpetra::Map<>::node_type;
46  using CrsMatrix_t = Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, NodeType>;
47  using Vector_t = Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, NodeType>;
49 
50  bool success = true;
51 
52  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
53 
55  out = Teuchos::VerboseObjectBase::getDefaultOStream();
56 
57  //
58  // A) Program setup code
59  //
60 
61  //
62  // Read options from command-line
63  //
64 
65  std::string matrixFile = "";
66  std::string extraParamsFile = "";
67  double tol = 1e-5;
68  bool onlyPrintOptions = false;
69  bool printXmlFormat = false;
70  bool showDoc = true;
72 
73  auto validVerbLevels = Teuchos::getValidVerbLevels();
74  auto validVerbLevelsNamesRawStrings = Teuchos::getValidVerbLevelsNamesRawStrings();
75 
76  Stratimikos::DefaultLinearSolverBuilder linearSolverBuilder;
77 
78  CommandLineProcessor clp(false); // Don't throw exceptions
79 
80  // Set up command-line options for the linear solver that will be used!
81  linearSolverBuilder.setupCLP(&clp);
82 
83  clp.setOption( "matrix-file", &matrixFile,
84  "Defines the matrix and perhaps the RHS and LHS for a linear system to be solved." );
85  clp.setOption( "tol", &tol,
86  "Tolerance to check against the scaled residual norm." );
87  clp.setOption( "extra-params-file", &extraParamsFile,
88  "File containing extra parameters in XML format.");
89  clp.setOption( "only-print-options", "continue-after-printing-options",
90  &onlyPrintOptions,
91  "Only print options and stop or continue on" );
92  clp.setOption( "print-xml-format", "print-readable-format", &printXmlFormat,
93  "Print the valid options in XML format or in readable format." );
94  clp.setOption( "show-doc", "hide-doc", &showDoc,
95  "Print the valid options with or without documentation." );
96  clp.setOption("verb-level", &verbLevel, validVerbLevels.size(),
97  validVerbLevels.getRawPtr(), validVerbLevelsNamesRawStrings.getRawPtr(),
98  "The verbosity level." );
99 
100  clp.setDocString(
101  "Simple example for using TrilinosLinearSolver interface.\n"
102  "\n"
103  "To print out just the valid options use --only-print-options with"
104  " --print-xml-format or --print-readable-format.\n"
105  "\n"
106  "To solve a linear system read from a file use --matrix-file=\"<matrix>.mtx\""
107  " with options read from an XML file using"
108  " --linear-solver-params-file=\"<paramList>.xml\"\n"
109  );
110 
111  CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
112  if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
113 
114  //
115  // Print out the valid options and stop if asked
116  //
117 
118  if(onlyPrintOptions) {
119  if(printXmlFormat)
120  Teuchos::writeParameterListToXmlOStream(
121  *linearSolverBuilder.getValidParameters(), *out );
122  else
123  linearSolverBuilder.getValidParameters()->print(
124  *out,PLPrintOptions().indent(2).showTypes(true).showDoc(showDoc) );
125  return 0;
126  }
127 
128  //
129  // B) Set Tpetra-specific code that sets up the linear system to be solved
130  //
131  // While the below code reads in the Tpetra objects from a file, you can
132  // setup the Tpetra objects any way you would like.
133  //
134 
135  *out << "\nReading in Tpetra matrix A from the file"
136  << " \'"<<matrixFile<<"\' ...\n";
137 
138  RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
139  RCP<const CrsMatrix_t> tpetra_A =
140  Tpetra::MatrixMarket::Reader<CrsMatrix_t>::readSparseFile(matrixFile, comm);
141 
142  *out << "\nGenerate a random RHS random vector ...\n";
143  auto tpetra_b = rcp(new Vector_t(tpetra_A->getRangeMap()));
144  tpetra_b->randomize();
145 
146  *out << "\nGenerate LHS of zeros ...\n";
147  auto tpetra_x = rcp(new Vector_t(tpetra_A->getDomainMap()));
148  tpetra_x->putScalar(0.0); // Initial guess is critical!
149 
150  *out << "\nPrinting statistics of the Tpetra linear system ...\n";
151 
152  *out
153  << "\n Tpetra::CrsMatrix tpetra_A of dimension "
154  << tpetra_A->getRangeMap()->getGlobalNumElements()
155  << " x " << tpetra_A->getDomainMap()->getGlobalNumElements() << "\n"
156  << " ||tpetra_A||_F = " << tpetra_A->getFrobeniusNorm() << "\n"
157  << " ||tpetra_b||2 = " << tpetraNorm2(*tpetra_b) << "\n"
158  << " ||tpetra_x||2 = " << tpetraNorm2(*tpetra_x) << "\n";
159 
160  //
161  // C) The "Glue" code that takes Tpetra objects and wraps them as Thyra
162  // objects
163  //
164  // This next set of code wraps the Tpetra objects that define the linear
165  // system to be solved as Thyra objects so that they can be passed to the
166  // linear solver.
167  //
168 
169  using TpetraVectorSpace_t =
171 
172  RCP<const Thyra::LinearOpBase<double>> A =
173  Thyra::createConstLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,NodeType>(tpetra_A);
174  RCP<Thyra::VectorBase<Scalar>> x =
175  Thyra::tpetraVector(rcp_dynamic_cast<const TpetraVectorSpace_t>(A->domain()),
176  tpetra_x);
177  RCP<const Thyra::VectorBase<Scalar>> b =
178  Thyra::tpetraVector(rcp_dynamic_cast<const TpetraVectorSpace_t>(A->range()),
179  tpetra_b);
180 
181  //
182  // D) Thyra-specific code for solving the linear system
183  //
184 
185  // Read in the solver parameters from the parameters file and/or from the
186  // command line. This was setup by the command-line options set by the
187  // setupCLP(...) function above.
188  linearSolverBuilder.readParameters(out.get());
189 
190  // Augment parameters if appropriate
191  if(extraParamsFile.length()) {
192  Teuchos::updateParametersFromXmlFile( "./"+extraParamsFile,
193  linearSolverBuilder.getNonconstParameterList().ptr() );
194  }
195 
196  // Create a linear solver factory given information read from the
197  // parameter list.
198  RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > lowsFactory =
199  linearSolverBuilder.createLinearSolveStrategy("");
200  *out << "\nlowsFactory: " << describe(*lowsFactory, verbLevel);
201 
202  // Setup output stream and the verbosity level
203  lowsFactory->setOStream(out);
204  lowsFactory->setVerbLevel(verbLevel);
205 
206  // Create a linear solver based on the forward operator A
207  RCP<Thyra::LinearOpWithSolveBase<Scalar> > A_lows =
208  Thyra::linearOpWithSolve(*lowsFactory, A);
209  *out << "\nA: " << describe(*A, verbLevel);
210  *out << "\nA_lows: " << describe(*A_lows, verbLevel);
211 
212  // Solve the linear system (note: the initial guess in 'x' is critical)
213  Thyra::SolveStatus<Scalar> status =
214  Thyra::solve<Scalar>(*A_lows, Thyra::NOTRANS, *b, x.ptr());
215  *out << "\nSolve status:\n" << status;
216 
217  // Write the linear solver parameters after they were read
218  linearSolverBuilder.writeParamsFile(*lowsFactory);
219 
220  //
221  // E) Post process the solution and check the error
222  //
223  // Note that the below code is based only on the Tpetra objects themselves
224  // and does not in any way depend or interact with any Thyra-based objects.
225  // The point is that most users of Thyra can largely gloss over the fact
226  // that Thyra is really being used for anything.
227  //
228 
229  // Wipe out the Thyra wrapper for x to guarantee that the solution will be
230  // written back to tpetra_x! At the time of this writting this is not
231  // really needed but the behavior may change at some point so this is a
232  // good idea.
233  x = Teuchos::null;
234 
235  *out << "\nSolution ||tpetra_x||2 = " << tpetraNorm2(*tpetra_x) << "\n";
236 
237  *out << "\nTesting the solution error ||b-A*x||/||b||:\n";
238 
239  // r = b - A*x
240  auto tpetra_r = rcp(new Vector_t(tpetra_b->getMap()));
241  tpetra_r->assign(*tpetra_b);
242  tpetra_A->apply(*tpetra_x, *tpetra_r, Teuchos::NO_TRANS, -ST::one(), ST::one());
243 
244  const double
245  nrm_r = tpetraNorm2(*tpetra_r),
246  nrm_b = tpetraNorm2(*tpetra_b),
247  rel_err = ( nrm_r / nrm_b );
248  const bool
249  passed = (rel_err <= tol);
250 
251  *out
252  << "||b-A*x||/||b|| = " << nrm_r << "/" << nrm_b << " = " << rel_err
253  << " < tol = " << tol << " ? " << ( passed ? "passed" : "failed" ) << "\n";
254 
255  if(!passed) success = false;
256 
257  return success;
258 
259 }
260 
261 
262 int main(int argc, char* argv[])
263 {
264 
266  out = Teuchos::VerboseObjectBase::getDefaultOStream();
267 
268  bool success = false;
269 
270  try {
271  success = readAndSolveLinearSystem(argc, argv);
272  }
273  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success)
274 
275  if(success) *out << "\nCongratulations! All of the tests checked out!\n";
276  else *out << "\nOh no! At least one of the tests failed!\n";
277 
278  return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
279 
280 }
int main(int argc, char *argv[])
TEUCHOSCORE_LIB_DLL_EXPORT ArrayView< const EVerbosityLevel > getValidVerbLevels()
T * get() const
void readParameters(std::ostream *out)
Force the parameters to be read from a file and/or an extra XML string.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool readAndSolveLinearSystem(int argc, char *argv[])
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
ParameterList::PrintOptions PLPrintOptions
RCP< Thyra::LinearOpWithSolveFactoryBase< Scalar > > createLinearSolveStrategy(const std::string &linearSolveStrategyName) const
Concrete subclass of Thyra::LinearSolverBuilderBase for creating Thyra::LinearOpWithSolveFactoryBase ...
void writeParamsFile(const Thyra::LinearOpWithSolveFactoryBase< Scalar > &lowsFactory, const std::string &outputXmlFileName="") const
Write the parameters list for a LinearOpWithSolveFactoryBase object to a file after the parameters ar...
void setupCLP(Teuchos::CommandLineProcessor *clp)
Setup the command-line processor to read in the needed data to extra the parameters from...
TEUCHOSCORE_LIB_DLL_EXPORT ArrayView< const char *const > getValidVerbLevelsNamesRawStrings()
RCP< const ParameterList > getValidParameters() const