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 //
4 // Belos: Block Linear Solvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 //@HEADER
41 
44 #include "BelosLinearProblem.hpp"
45 #include "BelosSolverFactory.hpp"
46 
47 #include "BelosGCRODRSolMgr.hpp"
51 #include "BelosBlockCGSolMgr.hpp"
53 #include "BelosLSQRSolMgr.hpp"
54 #include "BelosPCPGSolMgr.hpp"
55 #include "BelosRCGSolMgr.hpp"
56 #include "BelosBiCGStabSolMgr.hpp"
57 
58 #include "MyMultiVec.hpp"
59 #include "MyBetterOperator.hpp"
60 #include "MyOperator.hpp"
61 
62 
63 template<class ScalarType, class FactoryType, class SolverBaseType, class SolverImplType>
64 void
65 testSolver (bool& success, Teuchos::FancyOStream& out, const std::string& solverName)
66 {
69  using Teuchos::parameterList;
70  using Teuchos::RCP;
71  using Teuchos::rcp;
72  using Teuchos::rcp_dynamic_cast;
74  using std::endl;
75  typedef ScalarType ST;
76  typedef SolverBaseType solver_base_type;
77  typedef SolverImplType solver_impl_type;
78  typedef FactoryType factory_type;
79  typedef typename Teuchos::ScalarTraits<ST>::magnitudeType MT;
80 
81  const bool testOutputFreq = false;
82 
83  Teuchos::OSTab tab0 (out);
84  out << "Test Belos::SolverFactory::create for solver \"" << solverName << "\"" << endl;
85  Teuchos::OSTab tab1 (out);
86 
87  out << "ScalarType: " << TypeNameTraits<ScalarType>::name () << endl
88  << "FactoryType: " << TypeNameTraits<FactoryType>::name () << endl
89  << "SolverBaseType: " << TypeNameTraits<SolverBaseType>::name () << endl
90  << "SolverImplType: " << TypeNameTraits<SolverImplType>::name () << endl;
91 
92  RCP<factory_type> pFactory;
93  RCP<solver_base_type> solver;
94 
95  out << "Test whether creating a Belos::SolverFactory works" << endl;
96  try {
97  pFactory = rcp (new factory_type ());
98  }
99  catch (std::exception& e) {
100  out << "Belos::SolverFactory constructor threw an exception: "
101  << e.what () << endl;
102  success = false;
103  return; // doesn't make sense to continue
104  }
105  catch (...) {
106  out << "Belos::SolverFactory constructor threw an exception not a subclass "
107  "of std::exception" << endl;
108  success = false;
109  return; // doesn't make sense to continue
110  }
111  factory_type& factory = *pFactory;
112 
113  out << "Test whether factory works when input ParameterList is null" << endl;
114 
115  // It must work when the parameter list is null.
116  TEST_NOTHROW( solver = factory.create (solverName, Teuchos::null) );
117  TEST_ASSERT( ! solver.is_null () );
118  if (! solver.is_null ()) {
119  // Did we actually get the solver for which we asked?
120  RCP<solver_impl_type> solverImpl = rcp_dynamic_cast<solver_impl_type> (solver);
121  TEST_ASSERT( ! solverImpl.is_null () );
122  }
123 
124  out << "Test whether factory works when input ParameterList is nonnull" << endl;
125 
126  // The factory must work when the parameter list is nonnull, and the
127  // solver must actually read the provided parameters.
128  RCP<ParameterList> plist = parameterList ("Belos");
129  const MT tol = 0.99; // definitely a nondefault value
130  const int maxNumIters = 42; // definitely a nondefault value
131  const int verbosity = static_cast<int> (Belos::Errors) + static_cast<int> (Belos::Warnings);
132  const int outputStyle = Belos::Brief; // not default (imitates AztecOO)
133  const int outputFreq = 3; // definitely not default
134 
135  // Both of these parameters start out as "unused."
136  plist->set ("Convergence Tolerance", tol);
137  plist->set ("Maximum Iterations", maxNumIters);
138  plist->set ("Verbosity", verbosity);
139  plist->set ("Output Style", outputStyle);
140  if (testOutputFreq) {
141  plist->set ("Output Frequency", outputFreq);
142  }
143  TEST_ASSERT( ! plist->getEntry ("Convergence Tolerance").isUsed () );
144  TEST_ASSERT( ! plist->getEntry ("Maximum Iterations").isUsed () );
145  TEST_ASSERT( ! plist->getEntry ("Verbosity").isUsed () );
146  TEST_ASSERT( ! plist->getEntry ("Output Style").isUsed () );
147  if (testOutputFreq) {
148  TEST_ASSERT( ! plist->getEntry ("Output Frequency").isUsed () );
149  }
150 
151  out << "Input ParameterList: " << endl;
152  {
153  Teuchos::OSTab tab2 (out);
154  plist->print (out);
155  out << endl;
156  }
157 
158  solver = factory.create (solverName, plist);
159  TEST_ASSERT( ! solver.is_null () );
160  if (! solver.is_null ()) {
161  // Did we actually get the solver for which we asked?
162  RCP<solver_impl_type> solverImpl = rcp_dynamic_cast<solver_impl_type> (solver);
163  TEST_ASSERT( ! solverImpl.is_null () );
164 
165  // Did the solver (or the factory) actually read the parameters that we set?
166  TEST_ASSERT( plist->getEntry ("Convergence Tolerance").isUsed () );
167  TEST_ASSERT( plist->getEntry ("Maximum Iterations").isUsed () );
168  TEST_ASSERT( plist->getEntry ("Verbosity").isUsed () );
169  TEST_ASSERT( plist->getEntry ("Output Style").isUsed () );
170  if (testOutputFreq) {
171  TEST_ASSERT( plist->getEntry ("Output Frequency").isUsed () );
172  }
173 
174  // Did the solver get the parameters that we set on input?
175  RCP<const ParameterList> curParams = solver->getCurrentParameters ();
176  TEST_ASSERT( ! curParams.is_null () );
177  if (! curParams.is_null ()) {
178  // Are the parameters' values correct?
179  MT curTol = Teuchos::ScalarTraits<MT>::zero ();
180  TEST_NOTHROW( curTol = curParams->get<MT> ("Convergence Tolerance") );
181  TEST_EQUALITY( curTol, tol );
182  int curMaxNumIters = 0;
183  TEST_NOTHROW( curMaxNumIters = curParams->get<int> ("Maximum Iterations") );
184  TEST_EQUALITY( curMaxNumIters, maxNumIters );
185  int curVerbosity = 0;
186  TEST_NOTHROW( curVerbosity = curParams->get<int> ("Verbosity") );
187  TEST_EQUALITY( curVerbosity, verbosity );
188  int curOutputStyle = 0;
189  TEST_NOTHROW( curOutputStyle = curParams->get<int> ("Output Style") );
190  TEST_EQUALITY( curOutputStyle, outputStyle );
191  if (testOutputFreq) {
192  int curOutputFreq = 0;
193  TEST_NOTHROW( curOutputFreq = curParams->get<int> ("Output Frequency") );
194  TEST_EQUALITY( curOutputFreq, outputFreq );
195  }
196 
197  // The solver (or the factory) doesn't actually need to have
198  // read ("used") the parameters in curParams. curParams could
199  // be (generally is, for Belos) a deep copy of plist.
200  }
201  }
202 }
203 
204 
205 
206 // Unfortunately, the preprocessor doesn't let me do pasting like this:
207 //
208 // typedef Belos:: ## SOLVER_CLASS ## <ST, MV, OP> solver_impl_type;
209 //
210 // That's why I still have to do the typedef outside of the macro.
211 #define BELOS_TEST_SOLVER( SOLVER_NAME ) \
212 do { \
213  const std::string solverName (SOLVER_NAME); \
214  try { \
215  bool curSuccess = true; \
216  testSolver<ST, factory_type, solver_base_type, solver_impl_type> (curSuccess, out, solverName); \
217  if (! curSuccess) { \
218  failedSolvers.push_back (solverName); \
219  } \
220  success = success && curSuccess; \
221  } catch (std::exception& e) { \
222  out << "*** Solver \"" << solverName << "\" threw an exception: " \
223  << e.what () << std::endl; \
224  success = false; \
225  failedSolvers.push_back (solverName); \
226  } \
227 } while (false)
228 
229 
230 // Test that Belos::SolverFactory returns a solver of the right type,
231 // and that the solver (or the factory) read and respected the input
232 // parameters.
233 TEUCHOS_UNIT_TEST( Factory, Bug6383 )
234 {
235  using std::endl;
236  typedef double ST;
237  typedef Belos::MultiVec<ST> MV;
238  typedef Belos::Operator<ST> OP;
239  typedef Belos::SolverManager<ST, MV, OP> solver_base_type;
240  typedef Belos::SolverFactory<ST, MV, OP> factory_type;
241 
242  Teuchos::OSTab tab0 (out);
243  out << "Test for Bug 6383" << endl;
244  Teuchos::OSTab tab1 (out);
245 
246  // List of names of solvers that failed the test.
247  std::vector<std::string> failedSolvers;
248 
249  {
250  typedef Belos::GCRODRSolMgr<ST, MV, OP> solver_impl_type;
251  BELOS_TEST_SOLVER( "GCRODR" );
252  }
253  {
254  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
255  BELOS_TEST_SOLVER( "GMRES" );
256  }
257  // Make sure that the factory is case insensitive (Bug 6388).
258  {
259  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
260  BELOS_TEST_SOLVER( "gmres" );
261  }
262  {
263  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
264  BELOS_TEST_SOLVER( "CG" );
265  }
266  // Make sure that the factory is case insensitive (Bug 6388).
267  {
268  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
269  BELOS_TEST_SOLVER( "cg" );
270  }
271  {
272  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
273  BELOS_TEST_SOLVER( "Block GMRES" );
274  }
275  {
276  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
277  BELOS_TEST_SOLVER( "Block GMRES" );
278  }
279  {
280  typedef Belos::BlockCGSolMgr<ST, MV, OP> solver_impl_type;
281  BELOS_TEST_SOLVER( "Block CG" );
282  }
283  {
284  typedef Belos::FixedPointSolMgr<ST, MV, OP> solver_impl_type;
285  BELOS_TEST_SOLVER( "Fixed Point" );
286  }
287 
288  // FIXME (mfh 05 Aug 2015) When setting "Verbosity" and/or "Output
289  // Style", LSQR throws:
290  //
291  // .../packages/belos/src/BelosStatusTestResNormOutput.hpp:232:
292  //
293  // Throw test that evaluated to true: tmpComboTest == Teuchos::null
294  // StatusTestResNormOutput(): test must be Belos::StatusTest[MaxIters|ResNorm|Combo].
295  if (false) {
296  typedef Belos::LSQRSolMgr<ST, MV, OP> solver_impl_type;
297  BELOS_TEST_SOLVER( "LSQR" );
298  }
299 
300  {
301  typedef Belos::PCPGSolMgr<ST, MV, OP> solver_impl_type;
302  BELOS_TEST_SOLVER( "PCPG" );
303  }
304  {
305  typedef Belos::RCGSolMgr<ST, MV, OP> solver_impl_type;
306  BELOS_TEST_SOLVER( "RCG" );
307  }
308  {
309  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
310  BELOS_TEST_SOLVER( "BiCGStab" );
311  }
312  // Make sure that the factory is case insensitive (Bug 6388).
313  {
314  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
315  BELOS_TEST_SOLVER( "bicgstab" );
316  }
317 
318 #if 1
319  if (success) {
320  out << endl << "Test SUCCEEDED!" << endl;
321  }
322  else {
323  out << endl << "Test FAILED!" << endl
324  << "Solvers that failed: [";
325  for (size_t k = 0; k < failedSolvers.size (); ++k) {
326  out << "\"" << failedSolvers[k] << "\"";
327  if (k + 1 < failedSolvers.size ()) {
328  out << ", ";
329  }
330  }
331  out << "]" << endl;
332  }
333 #else
334  if (! success) {
335  out << endl << "*** Solvers that failed: ";
336  out << "[";
337  for (size_t k = 0; k < failedSolvers.size (); ++k) {
338  out << "\"" << failedSolvers[k] << "\"";
339  if (k + 1 < failedSolvers.size ()) {
340  out << ", ";
341  }
342  }
343  out << "]" << endl;
344  }
345 #endif // 0
346 }
347 
#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:211
TEUCHOS_UNIT_TEST(Factory, Bug6383)
Definition: Factory.cpp:233
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:65
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