Stratimikos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
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"
5#include "Thyra_TpetraThyraWrappers.hpp"
6#include "Thyra_LinearOpTester.hpp"
7#include "Thyra_LinearOpWithSolveTester.hpp"
8#include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
9#include "Thyra_TpetraLinearOp.hpp"
10#include "Thyra_TpetraVector.hpp"
11#include "MatrixMarket_Tpetra.hpp"
12#include "Teuchos_ParameterList.hpp"
13#include "Teuchos_XMLParameterListHelpers.hpp"
14#include "Teuchos_StandardCatchMacros.hpp"
15
16
17namespace {
18
19// Helper function to compute a single norm for a vector
20template<class Scalar, class LO, class GO, class Node>
21double tpetraNorm2( const Tpetra::Vector<Scalar,LO,GO,Node> &v )
22{
23 Teuchos::Tuple<double,1> norm;
24 norm[0] = -1.0;
25 v.norm2(norm());
26 return norm[0];
27}
28
29} // namespace
30
31
32bool readAndSolveLinearSystem(int argc, char* argv[])
33{
34
35 using Teuchos::rcp;
36 using Teuchos::RCP;
37 using Teuchos::rcp_dynamic_cast;
38 using Teuchos::CommandLineProcessor;
39 using Teuchos::EVerbosityLevel;
40 typedef Teuchos::ParameterList::PrintOptions PLPrintOptions;
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>;
48 using ST = Teuchos::ScalarTraits<Scalar>;
49
50 bool success = true;
51
52 Teuchos::GlobalMPISession mpiSession(&argc, &argv);
53
54 Teuchos::RCP<Teuchos::FancyOStream>
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;
71 EVerbosityLevel verbLevel = Teuchos::VERB_LOW;
72
73 auto validVerbLevels = Teuchos::getValidVerbLevels();
74 auto validVerbLevelsNamesRawStrings = Teuchos::getValidVerbLevelsNamesRawStrings();
75
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 =
170 const Thyra::TpetraVectorSpace<Scalar, LocalOrdinal, GlobalOrdinal, NodeType>;
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
262int main(int argc, char* argv[])
263{
264
265 Teuchos::RCP<Teuchos::FancyOStream>
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}
RCP< const ParameterList > getValidParameters() const
RCP< Thyra::LinearOpWithSolveFactoryBase< Scalar > > createLinearSolveStrategy(const std::string &linearSolveStrategyName) const
void setupCLP(Teuchos::CommandLineProcessor *clp)
Setup the command-line processor to read in the needed data to extra the parameters from.
void readParameters(std::ostream *out)
Force the parameters to be read from a file and/or an extra XML string.
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...
LinearSolverBuilder< double > DefaultLinearSolverBuilder
int main(int argc, char *argv[])
bool readAndSolveLinearSystem(int argc, char *argv[])