Belos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Factory.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Belos: Block Linear Solvers Package
4 //
5 // Copyright 2004-2016 NTESS and the Belos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
12 #include "BelosLinearProblem.hpp"
13 #include "BelosSolverFactory.hpp"
14 
15 #include "BelosGCRODRSolMgr.hpp"
19 #include "BelosBlockCGSolMgr.hpp"
21 #include "BelosLSQRSolMgr.hpp"
22 #include "BelosPCPGSolMgr.hpp"
23 #include "BelosRCGSolMgr.hpp"
24 #include "BelosBiCGStabSolMgr.hpp"
25 
26 #include "MyMultiVec.hpp"
27 #include "MyBetterOperator.hpp"
28 #include "MyOperator.hpp"
29 
30 
31 template<class ScalarType, class FactoryType, class SolverBaseType, class SolverImplType>
32 void
33 testSolver (bool& success, Teuchos::FancyOStream& out, const std::string& solverName)
34 {
37  using Teuchos::parameterList;
38  using Teuchos::RCP;
39  using Teuchos::rcp;
40  using Teuchos::rcp_dynamic_cast;
42  using std::endl;
43  typedef ScalarType ST;
44  typedef SolverBaseType solver_base_type;
45  typedef SolverImplType solver_impl_type;
46  typedef FactoryType factory_type;
47  typedef typename Teuchos::ScalarTraits<ST>::magnitudeType MT;
48 
49  const bool testOutputFreq = false;
50 
51  Teuchos::OSTab tab0 (out);
52  out << "Test Belos::SolverFactory::create for solver \"" << solverName << "\"" << endl;
53  Teuchos::OSTab tab1 (out);
54 
55  out << "ScalarType: " << TypeNameTraits<ScalarType>::name () << endl
56  << "FactoryType: " << TypeNameTraits<FactoryType>::name () << endl
57  << "SolverBaseType: " << TypeNameTraits<SolverBaseType>::name () << endl
58  << "SolverImplType: " << TypeNameTraits<SolverImplType>::name () << endl;
59 
60  RCP<factory_type> pFactory;
61  RCP<solver_base_type> solver;
62 
63  out << "Test whether creating a Belos::SolverFactory works" << endl;
64  try {
65  pFactory = rcp (new factory_type ());
66  }
67  catch (std::exception& e) {
68  out << "Belos::SolverFactory constructor threw an exception: "
69  << e.what () << endl;
70  success = false;
71  return; // doesn't make sense to continue
72  }
73  catch (...) {
74  out << "Belos::SolverFactory constructor threw an exception not a subclass "
75  "of std::exception" << endl;
76  success = false;
77  return; // doesn't make sense to continue
78  }
79  factory_type& factory = *pFactory;
80 
81  out << "Test whether factory works when input ParameterList is null" << endl;
82 
83  // It must work when the parameter list is null.
84  TEST_NOTHROW( solver = factory.create (solverName, Teuchos::null) );
85  TEST_ASSERT( ! solver.is_null () );
86  if (! solver.is_null ()) {
87  // Did we actually get the solver for which we asked?
88  RCP<solver_impl_type> solverImpl = rcp_dynamic_cast<solver_impl_type> (solver);
89  TEST_ASSERT( ! solverImpl.is_null () );
90  }
91 
92  out << "Test whether factory works when input ParameterList is nonnull" << endl;
93 
94  // The factory must work when the parameter list is nonnull, and the
95  // solver must actually read the provided parameters.
96  RCP<ParameterList> plist = parameterList ("Belos");
97  const MT tol = 0.99; // definitely a nondefault value
98  const int maxNumIters = 42; // definitely a nondefault value
99  const int verbosity = static_cast<int> (Belos::Errors) + static_cast<int> (Belos::Warnings);
100  const int outputStyle = Belos::Brief; // not default (imitates AztecOO)
101  const int outputFreq = 3; // definitely not default
102 
103  // Both of these parameters start out as "unused."
104  plist->set ("Convergence Tolerance", tol);
105  plist->set ("Maximum Iterations", maxNumIters);
106  plist->set ("Verbosity", verbosity);
107  plist->set ("Output Style", outputStyle);
108  if (testOutputFreq) {
109  plist->set ("Output Frequency", outputFreq);
110  }
111  TEST_ASSERT( ! plist->getEntry ("Convergence Tolerance").isUsed () );
112  TEST_ASSERT( ! plist->getEntry ("Maximum Iterations").isUsed () );
113  TEST_ASSERT( ! plist->getEntry ("Verbosity").isUsed () );
114  TEST_ASSERT( ! plist->getEntry ("Output Style").isUsed () );
115  if (testOutputFreq) {
116  TEST_ASSERT( ! plist->getEntry ("Output Frequency").isUsed () );
117  }
118 
119  out << "Input ParameterList: " << endl;
120  {
121  Teuchos::OSTab tab2 (out);
122  plist->print (out);
123  out << endl;
124  }
125 
126  solver = factory.create (solverName, plist);
127  TEST_ASSERT( ! solver.is_null () );
128  if (! solver.is_null ()) {
129  // Did we actually get the solver for which we asked?
130  RCP<solver_impl_type> solverImpl = rcp_dynamic_cast<solver_impl_type> (solver);
131  TEST_ASSERT( ! solverImpl.is_null () );
132 
133  // Did the solver (or the factory) actually read the parameters that we set?
134  TEST_ASSERT( plist->getEntry ("Convergence Tolerance").isUsed () );
135  TEST_ASSERT( plist->getEntry ("Maximum Iterations").isUsed () );
136  TEST_ASSERT( plist->getEntry ("Verbosity").isUsed () );
137  TEST_ASSERT( plist->getEntry ("Output Style").isUsed () );
138  if (testOutputFreq) {
139  TEST_ASSERT( plist->getEntry ("Output Frequency").isUsed () );
140  }
141 
142  // Did the solver get the parameters that we set on input?
143  RCP<const ParameterList> curParams = solver->getCurrentParameters ();
144  TEST_ASSERT( ! curParams.is_null () );
145  if (! curParams.is_null ()) {
146  // Are the parameters' values correct?
147  MT curTol = Teuchos::ScalarTraits<MT>::zero ();
148  TEST_NOTHROW( curTol = curParams->get<MT> ("Convergence Tolerance") );
149  TEST_EQUALITY( curTol, tol );
150  int curMaxNumIters = 0;
151  TEST_NOTHROW( curMaxNumIters = curParams->get<int> ("Maximum Iterations") );
152  TEST_EQUALITY( curMaxNumIters, maxNumIters );
153  int curVerbosity = 0;
154  TEST_NOTHROW( curVerbosity = curParams->get<int> ("Verbosity") );
155  TEST_EQUALITY( curVerbosity, verbosity );
156  int curOutputStyle = 0;
157  TEST_NOTHROW( curOutputStyle = curParams->get<int> ("Output Style") );
158  TEST_EQUALITY( curOutputStyle, outputStyle );
159  if (testOutputFreq) {
160  int curOutputFreq = 0;
161  TEST_NOTHROW( curOutputFreq = curParams->get<int> ("Output Frequency") );
162  TEST_EQUALITY( curOutputFreq, outputFreq );
163  }
164 
165  // The solver (or the factory) doesn't actually need to have
166  // read ("used") the parameters in curParams. curParams could
167  // be (generally is, for Belos) a deep copy of plist.
168  }
169  }
170 }
171 
172 
173 
174 // Unfortunately, the preprocessor doesn't let me do pasting like this:
175 //
176 // typedef Belos:: ## SOLVER_CLASS ## <ST, MV, OP> solver_impl_type;
177 //
178 // That's why I still have to do the typedef outside of the macro.
179 #define BELOS_TEST_SOLVER( SOLVER_NAME ) \
180 do { \
181  const std::string solverName (SOLVER_NAME); \
182  try { \
183  bool curSuccess = true; \
184  testSolver<ST, factory_type, solver_base_type, solver_impl_type> (curSuccess, out, solverName); \
185  if (! curSuccess) { \
186  failedSolvers.push_back (solverName); \
187  } \
188  success = success && curSuccess; \
189  } catch (std::exception& e) { \
190  out << "*** Solver \"" << solverName << "\" threw an exception: " \
191  << e.what () << std::endl; \
192  success = false; \
193  failedSolvers.push_back (solverName); \
194  } \
195 } while (false)
196 
197 
198 // Test that Belos::SolverFactory returns a solver of the right type,
199 // and that the solver (or the factory) read and respected the input
200 // parameters.
201 TEUCHOS_UNIT_TEST( Factory, Bug6383 )
202 {
203  using std::endl;
204  typedef double ST;
205  typedef Belos::MultiVec<ST> MV;
206  typedef Belos::Operator<ST> OP;
207  typedef Belos::SolverManager<ST, MV, OP> solver_base_type;
208  typedef Belos::SolverFactory<ST, MV, OP> factory_type;
209 
210  Teuchos::OSTab tab0 (out);
211  out << "Test for Bug 6383" << endl;
212  Teuchos::OSTab tab1 (out);
213 
214  // List of names of solvers that failed the test.
215  std::vector<std::string> failedSolvers;
216 
217  {
218  typedef Belos::GCRODRSolMgr<ST, MV, OP> solver_impl_type;
219  BELOS_TEST_SOLVER( "GCRODR" );
220  }
221  {
222  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
223  BELOS_TEST_SOLVER( "GMRES" );
224  }
225  // Make sure that the factory is case insensitive (Bug 6388).
226  {
227  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
228  BELOS_TEST_SOLVER( "gmres" );
229  }
230  {
231  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
232  BELOS_TEST_SOLVER( "CG" );
233  }
234  // Make sure that the factory is case insensitive (Bug 6388).
235  {
236  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
237  BELOS_TEST_SOLVER( "cg" );
238  }
239  {
240  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
241  BELOS_TEST_SOLVER( "Block GMRES" );
242  }
243  {
244  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
245  BELOS_TEST_SOLVER( "Block GMRES" );
246  }
247  {
248  typedef Belos::BlockCGSolMgr<ST, MV, OP> solver_impl_type;
249  BELOS_TEST_SOLVER( "Block CG" );
250  }
251  {
252  typedef Belos::FixedPointSolMgr<ST, MV, OP> solver_impl_type;
253  BELOS_TEST_SOLVER( "Fixed Point" );
254  }
255 
256  // FIXME (mfh 05 Aug 2015) When setting "Verbosity" and/or "Output
257  // Style", LSQR throws:
258  //
259  // .../packages/belos/src/BelosStatusTestResNormOutput.hpp:232:
260  //
261  // Throw test that evaluated to true: tmpComboTest == Teuchos::null
262  // StatusTestResNormOutput(): test must be Belos::StatusTest[MaxIters|ResNorm|Combo].
263  if (false) {
264  typedef Belos::LSQRSolMgr<ST, MV, OP> solver_impl_type;
265  BELOS_TEST_SOLVER( "LSQR" );
266  }
267 
268  {
269  typedef Belos::PCPGSolMgr<ST, MV, OP> solver_impl_type;
270  BELOS_TEST_SOLVER( "PCPG" );
271  }
272  {
273  typedef Belos::RCGSolMgr<ST, MV, OP> solver_impl_type;
274  BELOS_TEST_SOLVER( "RCG" );
275  }
276  {
277  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
278  BELOS_TEST_SOLVER( "BiCGStab" );
279  }
280  // Make sure that the factory is case insensitive (Bug 6388).
281  {
282  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
283  BELOS_TEST_SOLVER( "bicgstab" );
284  }
285 
286 #if 1
287  if (success) {
288  out << endl << "Test SUCCEEDED!" << endl;
289  }
290  else {
291  out << endl << "Test FAILED!" << endl
292  << "Solvers that failed: [";
293  for (size_t k = 0; k < failedSolvers.size (); ++k) {
294  out << "\"" << failedSolvers[k] << "\"";
295  if (k + 1 < failedSolvers.size ()) {
296  out << ", ";
297  }
298  }
299  out << "]" << endl;
300  }
301 #else
302  if (! success) {
303  out << endl << "*** Solvers that failed: ";
304  out << "[";
305  for (size_t k = 0; k < failedSolvers.size (); ++k) {
306  out << "\"" << failedSolvers[k] << "\"";
307  if (k + 1 < failedSolvers.size ()) {
308  out << ", ";
309  }
310  }
311  out << "]" << endl;
312  }
313 #endif // 0
314 }
315 
316 // Repeat the above test for the float scalar type.
317 TEUCHOS_UNIT_TEST( Factory, Bug6383_Float )
318 {
319  using std::endl;
320  typedef float ST;
321  typedef Belos::MultiVec<ST> MV;
322  typedef Belos::Operator<ST> OP;
323  typedef Belos::SolverManager<ST, MV, OP> solver_base_type;
324  typedef Belos::SolverFactory<ST, MV, OP> factory_type;
325 
326  Teuchos::OSTab tab0 (out);
327  out << "Test for Bug 6383" << endl;
328  Teuchos::OSTab tab1 (out);
329 
330  // List of names of solvers that failed the test.
331  std::vector<std::string> failedSolvers;
332 
333  {
334  typedef Belos::GCRODRSolMgr<ST, MV, OP> solver_impl_type;
335  BELOS_TEST_SOLVER( "GCRODR" );
336  }
337  {
338  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
339  BELOS_TEST_SOLVER( "GMRES" );
340  }
341  // Make sure that the factory is case insensitive (Bug 6388).
342  {
343  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
344  BELOS_TEST_SOLVER( "gmres" );
345  }
346  {
347  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
348  BELOS_TEST_SOLVER( "CG" );
349  }
350  // Make sure that the factory is case insensitive (Bug 6388).
351  {
352  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
353  BELOS_TEST_SOLVER( "cg" );
354  }
355  {
356  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
357  BELOS_TEST_SOLVER( "Block GMRES" );
358  }
359  {
360  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
361  BELOS_TEST_SOLVER( "Block GMRES" );
362  }
363  {
364  typedef Belos::BlockCGSolMgr<ST, MV, OP> solver_impl_type;
365  BELOS_TEST_SOLVER( "Block CG" );
366  }
367  {
368  typedef Belos::FixedPointSolMgr<ST, MV, OP> solver_impl_type;
369  BELOS_TEST_SOLVER( "Fixed Point" );
370  }
371 
372  // FIXME (mfh 05 Aug 2015) When setting "Verbosity" and/or "Output
373  // Style", LSQR throws:
374  //
375  // .../packages/belos/src/BelosStatusTestResNormOutput.hpp:232:
376  //
377  // Throw test that evaluated to true: tmpComboTest == Teuchos::null
378  // StatusTestResNormOutput(): test must be Belos::StatusTest[MaxIters|ResNorm|Combo].
379  if (false) {
380  typedef Belos::LSQRSolMgr<ST, MV, OP> solver_impl_type;
381  BELOS_TEST_SOLVER( "LSQR" );
382  }
383 
384  {
385  typedef Belos::PCPGSolMgr<ST, MV, OP> solver_impl_type;
386  BELOS_TEST_SOLVER( "PCPG" );
387  }
388  {
389  typedef Belos::RCGSolMgr<ST, MV, OP> solver_impl_type;
390  BELOS_TEST_SOLVER( "RCG" );
391  }
392  {
393  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
394  BELOS_TEST_SOLVER( "BiCGStab" );
395  }
396  // Make sure that the factory is case insensitive (Bug 6388).
397  {
398  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
399  BELOS_TEST_SOLVER( "bicgstab" );
400  }
401 
402 #if 1
403  if (success) {
404  out << endl << "Test SUCCEEDED!" << endl;
405  }
406  else {
407  out << endl << "Test FAILED!" << endl
408  << "Solvers that failed: [";
409  for (size_t k = 0; k < failedSolvers.size (); ++k) {
410  out << "\"" << failedSolvers[k] << "\"";
411  if (k + 1 < failedSolvers.size ()) {
412  out << ", ";
413  }
414  }
415  out << "]" << endl;
416  }
417 #else
418  if (! success) {
419  out << endl << "*** Solvers that failed: ";
420  out << "[";
421  for (size_t k = 0; k < failedSolvers.size (); ++k) {
422  out << "\"" << failedSolvers[k] << "\"";
423  if (k + 1 < failedSolvers.size ()) {
424  out << ", ";
425  }
426  }
427  out << "]" << endl;
428  }
429 #endif // 0
430 }
#define TEST_NOTHROW(code)
The Belos::FixedPointSolMgr provides a powerful and fully-featured solver manager over the FixedPoint...
#define TEST_ASSERT(v1)
The Belos::PseudoBlockCGSolMgr provides a solver manager for the BlockCG linear solver.
Implementation of the RCG (Recycling Conjugate Gradient) iterative linear solver. ...
The Belos::BlockCGSolMgr provides a powerful and fully-featured solver manager over the CG and BlockC...
The Belos::FixedPointSolMgr provides a solver manager for the FixedPoint linear solver.
Declaration and definition of Belos::PCPGSolMgr (PCPG iterative linear solver).
Interface to Block GMRES and Flexible GMRES.
#define BELOS_TEST_SOLVER(SOLVER_NAME)
Definition: Factory.cpp:179
TEUCHOS_UNIT_TEST(Factory, Bug6383)
Definition: Factory.cpp:201
The Belos::PseudoBlockCGSolMgr provides a powerful and fully-featured solver manager over the pseudo-...
Declaration and definition of Belos::GCRODRSolMgr, which implements the GCRODR (recycling GMRES) solv...
Alternative run-time polymorphic interface for operators.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
The Belos::BlockGmresSolMgr provides a solver manager for the BlockGmres linear solver.
The Belos::BiCGStabSolMgr provides a solver manager for the BiCGStab linear solver.
const double tol
Class which describes the linear problem to be solved by the iterative solver.
void testSolver(bool &success, Teuchos::FancyOStream &out, const std::string &solverName)
Definition: Factory.cpp:33
Implementation of the GCRODR (Recycling GMRES) iterative linear solver.
Interface to standard and &quot;pseudoblock&quot; GMRES.
The Belos::SolverManager is a templated virtual base class that defines the basic interface that any ...
The Belos::BlockCGSolMgr provides a solver manager for the BlockCG linear solver. ...
LSQRSolMgr: interface to the LSQR method.
The Belos::BiCGStabSolMgr provides a powerful and fully-featured solver manager over the pseudo-block...
PCPG iterative linear solver.
Interface for multivectors used by Belos&#39; linear solvers.
LSQR method (for linear systems and linear least-squares problems).
The Belos::RCGSolMgr provides a solver manager for the RCG (Recycling Conjugate Gradient) linear solv...
The Belos::PseudoBlockGmresSolMgr provides a solver manager for the BlockGmres linear solver...
#define TEST_EQUALITY(v1, v2)
typename::Belos::Impl::SolverFactorySelector< SC, MV, OP >::type SolverFactory