Belos  Version of the Day
BelosStatusTestFactory.hpp
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 <BelosStatusTestCombo.hpp>
46 #include <Teuchos_ParameterList.hpp>
47 
48 namespace Belos {
49 
80  template<class Scalar, class MV, class OP>
82  public:
83  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
88 
138  static Teuchos::RCP<base_test>
139  gmresTest (const magnitude_type convTol,
140  const int maxIterCount,
141  const bool haveLeftPreconditioner,
142  const ScaleType implicitScaleType = Belos::NormOfPrecInitRes,
143  const ScaleType explicitScaleType = Belos::NormOfInitRes,
144  const int blockSize = 1,
145  const int defQuorum = -1,
146  const bool showMaxResNormOnly = false);
147 
156  static Teuchos::RCP<base_test>
157  gmresTest (const bool haveLeftPreconditioner,
158  const Teuchos::RCP<Teuchos::ParameterList>& params);
159 
184  static std::pair<bool, bool>
185  changeConvTolAndMaxIters (const Teuchos::RCP<base_test>& test,
186  const magnitude_type convTol,
187  const int maxIterCount);
188 
194  static bool
195  changeMaxNumIters (const Teuchos::RCP<base_test>& test,
196  const int maxIterCount);
197 
203  static bool
204  changeConvTol (const Teuchos::RCP<base_test>& test,
205  const magnitude_type convTol);
206 
219  static ScaleType
220  stringToScaleType (const std::string& scaleType);
221 
226  Teuchos::RCP<const Teuchos::ParameterList> getValidGmresParameters ();
227 
228  private:
230  Teuchos::RCP<const Teuchos::ParameterList> defaultGmresParams_;
231  };
232 
233 
234  template<class Scalar, class MV, class OP>
235  Teuchos::RCP<typename StatusTestFactory<Scalar, MV, OP>::base_test>
238  const int maxIterCount,
239  const bool haveLeftPreconditioner,
240  const ScaleType implicitScaleType = NormOfPrecInitRes,
241  const ScaleType explicitScaleType = NormOfInitRes,
242  const int blockSize = 1,
243  const int defQuorum = -1,
244  const bool showMaxResNormOnly = false)
245  {
246  using Teuchos::null;
247  using Teuchos::ParameterList;
248  using Teuchos::RCP;
249  using Teuchos::rcp;
250 
251  TEUCHOS_TEST_FOR_EXCEPTION(blockSize < 1, std::invalid_argument,
252  "blockSize (= " << blockSize << ") must be >= 1.");
253  TEUCHOS_TEST_FOR_EXCEPTION(defQuorum > blockSize, std::invalid_argument,
254  "defQuorum (= " << defQuorum << ") may be no larger "
255  "than blockSize (= " << blockSize << ").");
256 
257  // The "implicit" residual test checks the "native" residual
258  // norm to determine if convergence was achieved. It is less
259  // expensive than the "explicit" residual test.
260  RCP<res_norm_test> implicitTest
261  = rcp (new res_norm_test (convTol, defQuorum));
262  implicitTest->defineScaleForm (stringToScaleType (implicitScaleType),
264  implicitTest->setShowMaxResNormOnly (showMaxResNormOnly);
265 
266  // If there's a left preconditioner, create a combined status
267  // test that check first the "explicit," then the "implicit"
268  // residual norm, requiring that both have converged to within
269  // the specified tolerance. Otherwise, we only perform the
270  // "implicit" test.
271  RCP<res_norm_test> explicitTest;
272  if (haveLeftPreconditioner) { // ! problem_->getLeftPrec().is_null()
273  explicitTest = rcp (new res_norm_test (convTol, defQuorum));
274  explicitTest->defineResForm (res_norm_test::Explicit, Belos::TwoNorm);
275  explicitTest->defineScaleForm (stringToScaleType (explicitScaleType),
277  explicitTest->setShowMaxResNormOnly (showMaxResNormOnly);
278  }
279  else {
280  explicitTest = null;
281  }
282 
283  // Full convergence test:
284  //
285  // First, the implicit residual norm test,
286  // Followed by the explicit residual norm test if applicable,
287  // Followed by the user-defined convergence test if supplied.
288  RCP<base_test> convTest;
289  if (explicitTest.is_null()) {
290  convTest = implicitTest;
291  }
292  else {
293  // The "explicit" residual test is only performed once the
294  // native ("implicit") residual is below the convergence
295  // tolerance.
296  convTest = rcp (new combo_test (combo_test::SEQ,
297  implicitTest,
298  explicitTest));
299  }
300 
301  // Stopping criterion for maximum number of iterations.
302  RCP<max_iter_test> maxIterTest = rcp (new max_iter_test (maxIterCount));
303 
304  // The "final" stopping criterion:
305  //
306  // Either we've run out of iterations, OR we've converged.
307  return rcp (new combo_test (combo_test::OR, maxIterTest, convTest));
308  }
309 
310 
311  template<class Scalar, class MV, class OP>
312  Teuchos::RCP<typename StatusTestFactory<Scalar, MV, OP>::base_test>
314  gmresTest (const bool haveLeftPreconditioner,
315  const Teuchos::RCP<Teuchos::ParameterList>& params)
316  {
317  using Teuchos::Exceptions::InvalidParameter;
318  using std::string;
319  typedef Teuchos::ScalarTraits<magnitude_type> STM;
320 
321  // "Convergence Tolerance" is a required parameter and must be
322  // nonnegative.
323  const magnitude_type convTol =
324  params->get<magnitude_type> ("Convergence Tolerance");
325  TEUCHOS_TEST_FOR_EXCEPTION(convTol < STM::zero(), std::invalid_argument,
326  "Convergence tolerance " << convTol
327  << " is negative.");
328  // "Maximum Iterations" is a required parameter and must be nonnegative.
329  const int maxIterCount = params->get<int> ("Maximum Iterations");
330  TEUCHOS_TEST_FOR_EXCEPTION(maxIterCount < 0, std::invalid_argument,
331  "Maximum number of iterations " << maxIterCount
332  << " is negative.");
333 
334  // PseudoBlockGmresSolMgr uses as defaults the preconditioned
335  // initial residual for the implicit test, and the
336  // unpreconditioned initial residual for the explicit test.
337  ScaleType implicitScaleType = NormOfPrecInitRes;
338  {
339  const std::string defaultImplicitScaleType ("Norm of Preconditioned Initial Residual");
340  implicitScaleType = stringToScaleType (params->get ("Implicit Residual Scaling", defaultImplicitScaleType));
341  }
342  ScaleType explicitScaleType = NormOfInitRes;
343  {
344  const std::string defaultExplicitScaleType ("Norm of Initial Residual");
345  explicitScaleType = stringToScaleType (params->get ("Explicit Residual Scaling", defaultExplicitScaleType));
346  }
347  const int defaultBlockSize = 1;
348  int blockSize = params->get ("Block Size", defaultBlockSize);
349 
350  const int defaultDefQuorum = -1;
351  int defQuorum = params->get ("Deflation Quorum", defaultDefQuorum);
352 
353  const bool defaultShowMaxResNormOnly = false;
354  bool showMaxResNormOnly = params->get ("Show Maximum Residual Norm Only", defaultShowMaxResNormOnly);
355 
356  return gmresTest (convTol, maxIterCount, haveLeftPreconditioner,
357  implicitScaleType, explicitScaleType, blockSize,
358  defQuorum, showMaxResNormOnly);
359  }
360 
361  template<class Scalar, class MV, class OP>
362  Teuchos::RCP<const Teuchos::ParameterList>
364  {
365  using Teuchos::ParameterList;
366  using Teuchos::parameterList;
367  using Teuchos::RCP;
368  typedef Teuchos::ScalarTraits<Scalar> STS;
369  typedef Teuchos::ScalarTraits<magnitude_type> STM;
370 
371  if (defaultGmresParams_.is_null()) {
372  // These two parameters are required. We supply defaults only
373  // as examples.
374  const magnitude_type convTol = STS::squareroot (STS::eps());
375  const int maxIterCount = 200;
376 
377  // PseudoBlockGmresSolMgr uses as defaults the preconditioned
378  // initial residual for the implicit test, and the
379  // unpreconditioned initial residual for the explicit test. We
380  // take these as the standard for all GMRES variants.
381  const std::string defaultImplicitScaleType ("Norm of Preconditioned Initial Residual");
382  const std::string defaultExplicitScaleType ("Norm of Initial Residual");
383  const int defaultBlockSize = 1;
384  const int defaultDefQuorum = -1;
385  const bool defaultShowMaxResNormOnly = false;
386 
387  RCP<ParameterList> params = parameterList ();
388  params->set ("Convergence Tolerance", convTol);
389  params->set ("Maximum Iterations", maxIterCount);
390  params->set ("Implicit Residual Scaling", defaultImplicitScaleType);
391  params->set ("Explicit Residual Scaling", defaultExplicitScaleType);
392  params->set ("Block Size", defaultBlockSize);
393  params->set ("Deflation Quorum", defaultDefQuorum);
394  params->set ("Show Maximum Residual Norm Only", defaultShowMaxResNormOnly);
395 
396  defaultGmresParams_ = params;
397  }
398  return defaultGmresParams_;
399  }
400 
401 
402  template<class Scalar, class MV, class OP>
403  bool
406  const int maxIterCount)
407  {
408  using Teuchos::rcp_dynamic_cast;
409  using Teuchos::nonnull;
410  using Teuchos::RCP;
411  using Teuchos::rcp;
412 
413  // We declare "success" if the test or at least one of its
414  // children (if it's a combo_test) is a max_iter_test.
415  bool success = false;
416  RCP<max_iter_test> maxIterTest = rcp_dynamic_cast<max_iter_test> (test);
417  if (nonnull (maxIterTest))
418  {
419  test->setMaxIters (maxIterCount);
420  success = true;
421  }
422  else
423  {
424  RCP<combo_test> comboTest = rcp_dynamic_cast<combo_test> (test);
425  if (nonnull (comboTest))
426  {
427  typedef typename combo_test::st_vector st_vector;
428  typedef typename st_vector::size_type size_type;
429  st_vector tests = test->getStatusTests ();
430  // We could use boost lambda to remove this for loop.
431  // Standard STL doesn't have a version of mem_fun for
432  // member functions that take > 1 argument.
433  for (size_type k = 0; result || k < tests.end(); ++k)
434  { // Recurse on all children, since it's possible for
435  // more than one child to be a max_iter_test.
436  const bool result =
437  changeMaxNumIters (tests[k], maxIterCount);
438  success = result || success;
439  }
440  }
441  }
442  return success;
443  }
444 
445  template<class Scalar, class MV, class OP>
446  std::pair<bool, bool>
450  const int maxIterCount)
451  {
452  using Teuchos::rcp_dynamic_cast;
453  using Teuchos::nonnull;
454  using Teuchos::RCP;
455  using Teuchos::rcp;
456  typedef StatusTestResNorm<Scalar,MV,OP> res_norm_base_test;
457  RCP<max_iter_test> maxIterTest = rcp_dynamic_cast<max_iter_test> (test);
458 
459  // We declare "success" if we encountered a res_norm_base_test
460  // _and_ a max_iter_test somewhere along the recursion path.
461  bool foundResNormTest = false;
462  bool foundMaxIterTest = false;
463 
464  RCP<res_norm_base_test> normTest =
465  rcp_dynamic_cast<res_norm_base_test> (test);
466  if (nonnull (normTest))
467  {
468  // NOTE (mfh 03 Mar 2011) setTolerance() returns an int
469  // result. However, all subclasses' implementations return 0
470  // here, and all of them always (re)set the tolerance, so I
471  // think it's OK to ignore the result.
472  (void) test->setTolerance (convTol);
473  foundResNormTest = true;
474  }
475  else
476  {
477  RCP<max_iter_test> maxIterTest =
478  rcp_dynamic_cast<max_iter_test> (test);
479  if (nonnull (maxIterTest))
480  {
481  test->setMaxIters (maxIterCount);
482  foundMaxIterTest = true;
483  }
484  }
485  if (! foundResNormTest && ! foundMaxIterTest)
486  {
487  RCP<combo_test> comboTest = rcp_dynamic_cast<combo_test> (test);
488  if (nonnull (comboTest))
489  {
490  typedef typename combo_test::st_vector st_vector;
491  typedef typename st_vector::size_type size_type;
492  st_vector tests = test->getStatusTests ();
493  // We could use boost lambda to remove this for loop.
494  // Standard STL doesn't have a version of mem_fun for
495  // member functions that take > 1 argument.
496  for (size_type k = 0; result || k < tests.end(); ++k)
497  { // Recurse on all children.
498  const std::pair<bool, bool> result =
499  changeConvTolAndMaxIters (tests[k], convTol, maxIterCount);
500  foundResNormTest = result.first || foundResNormTest;
501  foundMaxIterTest = result.second || foundMaxIterTest;
502  }
503  }
504  }
505  return std::make_pair (foundResNormTest, foundMaxIterTest);
506  }
507 
508  template<class Scalar, class MV, class OP>
509  bool
513  {
514  using Teuchos::rcp_dynamic_cast;
515  using Teuchos::nonnull;
516  using Teuchos::RCP;
517  using Teuchos::rcp;
518  typedef StatusTestResNorm<Scalar,MV,OP> res_norm_base_test;
519 
520  // We declare "success" if the test or at least one of its
521  // children (if it's a combo_test) is a res_norm_base_test.
522  bool success = false;
523  RCP<res_norm_base_test> normTest =
524  rcp_dynamic_cast<res_norm_base_test> (test);
525  if (nonnull (normTest))
526  {
527  // NOTE (mfh 03 Mar 2011) setTolerance() returns an int
528  // result. However, all subclasses' implementations return 0
529  // here, and all of them always (re)set the tolerance, so I
530  // think it's OK to ignore the result.
531  (void) test->setTolerance (convTol);
532  success = true;
533  }
534  else
535  {
536  RCP<combo_test> comboTest = rcp_dynamic_cast<combo_test> (test);
537  if (nonnull (comboTest))
538  {
539  typedef typename combo_test::st_vector st_vector;
540  typedef typename st_vector::size_type size_type;
541  st_vector tests = test->getStatusTests ();
542  // We could use boost lambda to remove this for loop.
543  // Standard STL doesn't have a version of mem_fun for
544  // member functions that take > 1 argument.
545  for (size_type k = 0; result || k < tests.end(); ++k)
546  { // Recurse on all children, since it's possible for
547  // more than one child to be a res_norm_base_test.
548  const bool result = changeConvTol (tests[k], convTol);
549  success = result || success;
550  }
551  }
552  }
553  return success;
554  }
555 
556 
557  template<class Scalar, class MV, class OP>
558  static ScaleType
560  stringToScaleType (const std::string& scaleType)
561  {
562  const char* validNames[] = {
563  "Norm of Initial Residual",
564  "Norm of Preconditioned Initial Residual",
565  "Norm of RHS",
566  "Norm of Right-Hand Side",
567  "None"
568  };
569  const int numValidNames = 5;
570  const ScaleType correspondingOutputs[] = {
576  };
577  for (int k = 0; k < numValidNames; ++k)
578  {
579  if (scaleType == validNames[k])
580  return correspondingOutputs[k];
581  }
582  TEUCHOS_TEST_FOR_EXCEPTION (true, std::logic_error,
583  "Invalid residual scaling type \"" << scaleType
584  << "\".");
585  }
586 
587 } // namespace Belos
static bool changeMaxNumIters(const Teuchos::RCP< base_test > &test, const int maxIterCount)
Change max number of iterations in place.
static bool changeConvTol(const Teuchos::RCP< base_test > &test, const magnitude_type convTol)
Change convergence tolerance in place.
StatusTestMaxIters< Scalar, MV, OP > max_iter_test
ScaleType
The type of scaling to use on the residual norm value.
Definition: BelosTypes.hpp:119
StatusTest< Scalar, MV, OP > base_test
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
An abstract class of StatusTest for stopping criteria using residual norms.
An implementation of StatusTestResNorm using a family of residual norms.
Belos::StatusTest class for specifying a maximum number of iterations.
A pure virtual class for defining the status tests for the Belos iterative solvers.
static ScaleType stringToScaleType(const std::string &scaleType)
Convert string to enum that tells residual test how to scale.
Belos::StatusTest for logically combining several status tests.
A Belos::StatusTest class for specifying a maximum number of iterations.
static std::pair< bool, bool > changeConvTolAndMaxIters(const Teuchos::RCP< base_test > &test, const magnitude_type convTol, const int maxIterCount)
Change convergence tolerance and max number of iterations.
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
static Teuchos::RCP< base_test > gmresTest(const magnitude_type convTol, const int maxIterCount, const bool haveLeftPreconditioner, const ScaleType implicitScaleType=Belos::NormOfPrecInitRes, const ScaleType explicitScaleType=Belos::NormOfInitRes, const int blockSize=1, const int defQuorum=-1, const bool showMaxResNormOnly=false)
Status test suitable for (preconditioned) GMRES.
Belos::StatusTest for specifying an implicit residual norm stopping criteria that checks for loss of ...
StatusTestGenResNorm< Scalar, MV, OP > res_norm_test
A class for extending the status testing capabilities of Belos via logical combinations.
st_vector getStatusTests()
Return the vector of status tests.
StatusTestCombo< Scalar, MV, OP > combo_test
virtual int setTolerance(MagnitudeType tolerance)=0
Set the value of the tolerance.
A factory for making common cases of stopping criteria.
Teuchos::RCP< const Teuchos::ParameterList > getValidGmresParameters()
Default parameters for a status test suitable for GMRES.
void setMaxIters(int maxIters)
Sets the maximum number of iterations allowed.

Generated on Thu Jul 21 2016 14:43:57 for Belos by doxygen 1.8.11