Belos Package Browser (Single Doxygen Collection)  Development
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 
42 #include "Teuchos_UnitTestHarness.hpp"
43 #include "Teuchos_CommandLineProcessor.hpp"
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 {
67  using Teuchos::ParameterEntry;
68  using Teuchos::ParameterList;
69  using Teuchos::parameterList;
70  using Teuchos::RCP;
71  using Teuchos::rcp;
72  using Teuchos::rcp_dynamic_cast;
73  using Teuchos::TypeNameTraits;
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  factory_type factory;
93  RCP<solver_base_type> solver;
94 
95  out << "Test whether factory works when input ParameterList is null" << endl;
96 
97  // It must work when the parameter list is null.
98  TEST_NOTHROW( solver = factory.create (solverName, Teuchos::null) );
99  TEST_ASSERT( ! solver.is_null () );
100  if (! solver.is_null ()) {
101  // Did we actually get the solver for which we asked?
102  RCP<solver_impl_type> solverImpl = rcp_dynamic_cast<solver_impl_type> (solver);
103  TEST_ASSERT( ! solverImpl.is_null () );
104  }
105 
106  out << "Test whether factory works when input ParameterList is nonnull" << endl;
107 
108  // The factory must work when the parameter list is nonnull, and the
109  // solver must actually read the provided parameters.
110  RCP<ParameterList> plist = parameterList ("Belos");
111  const MT tol = 0.99; // definitely a nondefault value
112  const int maxNumIters = 42; // definitely a nondefault value
113  const int verbosity = static_cast<int> (Belos::Errors) + static_cast<int> (Belos::Warnings);
114  const int outputStyle = Belos::Brief; // not default (imitates AztecOO)
115  const int outputFreq = 3; // definitely not default
116 
117  // Both of these parameters start out as "unused."
118  plist->set ("Convergence Tolerance", tol);
119  plist->set ("Maximum Iterations", maxNumIters);
120  plist->set ("Verbosity", verbosity);
121  plist->set ("Output Style", outputStyle);
122  if (testOutputFreq) {
123  plist->set ("Output Frequency", outputFreq);
124  }
125  TEST_ASSERT( ! plist->getEntry ("Convergence Tolerance").isUsed () );
126  TEST_ASSERT( ! plist->getEntry ("Maximum Iterations").isUsed () );
127  TEST_ASSERT( ! plist->getEntry ("Verbosity").isUsed () );
128  TEST_ASSERT( ! plist->getEntry ("Output Style").isUsed () );
129  if (testOutputFreq) {
130  TEST_ASSERT( ! plist->getEntry ("Output Frequency").isUsed () );
131  }
132 
133  out << "Input ParameterList: " << endl;
134  {
135  Teuchos::OSTab tab2 (out);
136  plist->print (out);
137  out << endl;
138  }
139 
140  solver = factory.create (solverName, plist);
141  TEST_ASSERT( ! solver.is_null () );
142  if (! solver.is_null ()) {
143  // Did we actually get the solver for which we asked?
144  RCP<solver_impl_type> solverImpl = rcp_dynamic_cast<solver_impl_type> (solver);
145  TEST_ASSERT( ! solverImpl.is_null () );
146 
147  // Did the solver (or the factory) actually read the parameters that we set?
148  TEST_ASSERT( plist->getEntry ("Convergence Tolerance").isUsed () );
149  TEST_ASSERT( plist->getEntry ("Maximum Iterations").isUsed () );
150  TEST_ASSERT( plist->getEntry ("Verbosity").isUsed () );
151  TEST_ASSERT( plist->getEntry ("Output Style").isUsed () );
152  if (testOutputFreq) {
153  TEST_ASSERT( plist->getEntry ("Output Frequency").isUsed () );
154  }
155 
156  // Did the solver get the parameters that we set on input?
157  RCP<const ParameterList> curParams = solver->getCurrentParameters ();
158  TEST_ASSERT( ! curParams.is_null () );
159  if (! curParams.is_null ()) {
160  // Are the parameters' values correct?
161  MT curTol = Teuchos::ScalarTraits<MT>::zero ();
162  TEST_NOTHROW( curTol = curParams->get<MT> ("Convergence Tolerance") );
163  TEST_EQUALITY( curTol, tol );
164  int curMaxNumIters = 0;
165  TEST_NOTHROW( curMaxNumIters = curParams->get<int> ("Maximum Iterations") );
166  TEST_EQUALITY( curMaxNumIters, maxNumIters );
167  int curVerbosity = 0;
168  TEST_NOTHROW( curVerbosity = curParams->get<int> ("Verbosity") );
169  TEST_EQUALITY( curVerbosity, verbosity );
170  int curOutputStyle = 0;
171  TEST_NOTHROW( curOutputStyle = curParams->get<int> ("Output Style") );
172  TEST_EQUALITY( curOutputStyle, outputStyle );
173  if (testOutputFreq) {
174  int curOutputFreq = 0;
175  TEST_NOTHROW( curOutputFreq = curParams->get<int> ("Output Frequency") );
176  TEST_EQUALITY( curOutputFreq, outputFreq );
177  }
178 
179  // The solver (or the factory) doesn't actually need to have
180  // read ("used") the parameters in curParams. curParams could
181  // be (generally is, for Belos) a deep copy of plist.
182  }
183  }
184 }
185 
186 
187 
188 // Unfortunately, the preprocessor doesn't let me do pasting like this:
189 //
190 // typedef Belos:: ## SOLVER_CLASS ## <ST, MV, OP> solver_impl_type;
191 //
192 // That's why I still have to do the typedef outside of the macro.
193 #define BELOS_TEST_SOLVER( SOLVER_NAME ) \
194 do { \
195  const std::string solverName (SOLVER_NAME); \
196  try { \
197  bool curSuccess = true; \
198  testSolver<ST, factory_type, solver_base_type, solver_impl_type> (curSuccess, out, solverName); \
199  if (! curSuccess) { \
200  failedSolvers.push_back (solverName); \
201  } \
202  success = success && curSuccess; \
203  } catch (std::exception& e) { \
204  out << "*** Solver \"" << solverName << "\" threw an exception: " \
205  << e.what () << std::endl; \
206  success = false; \
207  } \
208 } while (false)
209 
210 
211 // Test that Belos::SolverFactory returns a solver of the right type,
212 // and that the solver (or the factory) read and respected the input
213 // parameters.
214 TEUCHOS_UNIT_TEST( Factory, Bug6383 )
215 {
216  using std::endl;
217  typedef double ST;
218  typedef Belos::MultiVec<ST> MV;
219  typedef Belos::Operator<ST> OP;
220  typedef Belos::SolverManager<ST, MV, OP> solver_base_type;
221  typedef Belos::SolverFactory<ST, MV, OP> factory_type;
222 
223  Teuchos::OSTab tab0 (out);
224  out << "Test for Bug 6383" << endl;
225  Teuchos::OSTab tab1 (out);
226 
227  // List of names of solvers that failed the test.
228  std::vector<std::string> failedSolvers;
229 
230  {
231  typedef Belos::GCRODRSolMgr<ST, MV, OP> solver_impl_type;
232  BELOS_TEST_SOLVER( "GCRODR" );
233  }
234  {
235  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
236  BELOS_TEST_SOLVER( "GMRES" );
237  }
238  // Make sure that the factory is case insensitive (Bug 6388).
239  {
240  typedef Belos::PseudoBlockGmresSolMgr<ST, MV, OP> solver_impl_type;
241  BELOS_TEST_SOLVER( "gmres" );
242  }
243  {
244  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
245  BELOS_TEST_SOLVER( "CG" );
246  }
247  // Make sure that the factory is case insensitive (Bug 6388).
248  {
249  typedef Belos::PseudoBlockCGSolMgr<ST, MV, OP> solver_impl_type;
250  BELOS_TEST_SOLVER( "cg" );
251  }
252  {
253  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
254  BELOS_TEST_SOLVER( "Block GMRES" );
255  }
256  {
257  typedef Belos::BlockGmresSolMgr<ST, MV, OP> solver_impl_type;
258  BELOS_TEST_SOLVER( "Block GMRES" );
259  }
260  {
261  typedef Belos::BlockCGSolMgr<ST, MV, OP> solver_impl_type;
262  BELOS_TEST_SOLVER( "Block CG" );
263  }
264  {
265  typedef Belos::FixedPointSolMgr<ST, MV, OP> solver_impl_type;
266  BELOS_TEST_SOLVER( "Fixed Point" );
267  }
268 
269  // FIXME (mfh 05 Aug 2015) When setting "Verbosity" and/or "Output
270  // Style", LSQR throws:
271  //
272  // .../packages/belos/src/BelosStatusTestResNormOutput.hpp:232:
273  //
274  // Throw test that evaluated to true: tmpComboTest == Teuchos::null
275  // StatusTestResNormOutput(): test must be Belos::StatusTest[MaxIters|ResNorm|Combo].
276  if (false) {
277  typedef Belos::LSQRSolMgr<ST, MV, OP> solver_impl_type;
278  BELOS_TEST_SOLVER( "LSQR" );
279  }
280 
281  {
282  typedef Belos::PCPGSolMgr<ST, MV, OP> solver_impl_type;
283  BELOS_TEST_SOLVER( "PCPG" );
284  }
285  {
286  typedef Belos::RCGSolMgr<ST, MV, OP> solver_impl_type;
287  BELOS_TEST_SOLVER( "RCG" );
288  }
289  {
290  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
291  BELOS_TEST_SOLVER( "BiCGStab" );
292  }
293  // Make sure that the factory is case insensitive (Bug 6388).
294  {
295  typedef Belos::BiCGStabSolMgr<ST, MV, OP> solver_impl_type;
296  BELOS_TEST_SOLVER( "bicgstab" );
297  }
298 
299  if (! success) {
300  out << endl << "*** Solvers that failed: ";
301  out << "[";
302  for (size_t k = 0; k < failedSolvers.size (); ++k) {
303  out << "\"" << failedSolvers[k] << "\"";
304  if (k + 1 < failedSolvers.size ()) {
305  out << ", ";
306  }
307  }
308  out << "]" << endl;
309  }
310 }
311 
The Belos::FixedPointSolMgr provides a powerful and fully-featured solver manager over the FixedPoint...
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:193
TEUCHOS_UNIT_TEST(Factory, Bug6383)
Definition: Factory.cpp:214
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.
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 "pseudoblock" 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...
Factory for all solvers which Belos supports.