Belos Version of the Day
Loading...
Searching...
No Matches
BelosMinresSolMgr.hpp
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
10#ifndef BELOS_MINRES_SOLMGR_HPP
11#define BELOS_MINRES_SOLMGR_HPP
12
15
16#include "BelosConfigDefs.hpp"
17#include "BelosTypes.hpp"
18
21
22#include "BelosMinresIter.hpp"
28#ifdef BELOS_TEUCHOS_TIME_MONITOR
29#include "Teuchos_TimeMonitor.hpp"
30#endif
31
32#include "Teuchos_StandardParameterEntryValidators.hpp"
33// Teuchos::ScalarTraits<int> doesn't define rmax(), alas, so we get
34// INT_MAX from here.
35#include <climits>
36
37namespace Belos {
38
40
41
51 //
56 public:
60 };
61
80 template<class ScalarType, class MV, class OP>
81 class MinresSolMgr : public SolverManager<ScalarType,MV,OP> {
82
83 private:
86 typedef Teuchos::ScalarTraits<ScalarType> SCT;
87 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
88 typedef Teuchos::ScalarTraits< MagnitudeType > MST;
89
90 public:
91
103 static Teuchos::RCP<const Teuchos::ParameterList> defaultParameters();
104
106
107
116 MinresSolMgr();
117
150 const Teuchos::RCP<Teuchos::ParameterList> &params);
151
153 virtual ~MinresSolMgr() {};
154
156 Teuchos::RCP<SolverManager<ScalarType, MV, OP> > clone () const override {
157 return Teuchos::rcp(new MinresSolMgr<ScalarType,MV,OP>);
158 }
160
162
163
166 return *problem_;
167 }
168
170 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override {
171 if (defaultParams_.is_null()) {
172 defaultParams_ = defaultParameters ();
173 }
174 return defaultParams_;
175 }
176
178 Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const override {
179 return params_;
180 }
181
191 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
192 return Teuchos::tuple (timerSolve_);
193 }
194
200 MagnitudeType achievedTol() const override {
201 return achievedTol_;
202 }
203
205 int getNumIters() const override {
206 return numIters_;
207 }
208
214 bool isLOADetected() const override { return false; }
215
217
219
220
221 void
222 setProblem (const Teuchos::RCP<LinearProblem<ScalarType, MV, OP> > &problem) override
223 {
224 problem_ = problem;
225 }
226
227 void
228 setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params) override;
229
231
233
234
235 void
236 reset (const ResetType type) override
237 {
238 if ((type & Belos::Problem) && ! problem_.is_null()) {
239 problem_->setProblem ();
240 }
241 }
243
245
246
264 ReturnType solve() override;
265
267
270
271 std::string description() const override;
272
274
275 private:
277 Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
278
280 Teuchos::RCP<OutputManager<ScalarType> > printer_;
281 Teuchos::RCP<std::ostream> outputStream_;
282
289 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
290
294 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
295
299 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > convTest_;
300
304 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > impConvTest_;
305
309 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > expConvTest_;
310
315 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
316
320 mutable Teuchos::RCP<const Teuchos::ParameterList> defaultParams_;
321
323 Teuchos::RCP<Teuchos::ParameterList> params_;
324
326 MagnitudeType convtol_;
327
329 MagnitudeType achievedTol_;
330
332 int maxIters_;
333
335 int numIters_;
336
338 int blockSize_;
339
341 int verbosity_;
342
344 int outputStyle_;
345
347 int outputFreq_;
348
350 std::string label_;
351
353 Teuchos::RCP<Teuchos::Time> timerSolve_;
354
356 bool parametersSet_;
357
363 static void
364 validateProblem (const Teuchos::RCP<LinearProblem<ScalarType, MV, OP> >& problem);
365 };
366
367
368 template<class ScalarType, class MV, class OP>
369 Teuchos::RCP<const Teuchos::ParameterList>
371 {
372 using Teuchos::ParameterList;
373 using Teuchos::parameterList;
374 using Teuchos::RCP;
375 using Teuchos::rcp;
376 using Teuchos::rcpFromRef;
377 using Teuchos::EnhancedNumberValidator;
378 typedef MagnitudeType MT;
379
380 // List of parameters accepted by MINRES, and their default values.
382
383 pl->set ("Convergence Tolerance", MST::squareroot (MST::eps()),
384 "Relative residual tolerance that needs to be achieved by "
385 "the iterative solver, in order for the linear system to be "
386 "declared converged.",
387 rcp (new EnhancedNumberValidator<MT> (MST::zero(), MST::rmax())));
388 pl->set ("Maximum Iterations", static_cast<int>(1000),
389 "Maximum number of iterations allowed for each right-hand "
390 "side solved.",
392 pl->set ("Num Blocks", static_cast<int> (-1),
393 "Ignored, but permitted, for compatibility with other Belos "
394 "solvers.");
395 pl->set ("Block Size", static_cast<int> (1),
396 "Number of vectors in each block. WARNING: The current "
397 "implementation of MINRES only accepts a block size of 1, "
398 "since it can only solve for 1 right-hand side at a time.",
399 rcp (new EnhancedNumberValidator<int> (1, 1)));
400 pl->set ("Verbosity", (int) Belos::Errors,
401 "The type(s) of solver information that should "
402 "be written to the output stream.");
403 pl->set ("Output Style", (int) Belos::General,
404 "What style is used for the solver information written "
405 "to the output stream.");
406 pl->set ("Output Frequency", static_cast<int>(-1),
407 "How often (in terms of number of iterations) intermediate "
408 "convergence information should be written to the output stream."
409 " -1 means never.");
410 pl->set ("Output Stream", rcpFromRef(std::cout),
411 "A reference-counted pointer to the output stream where all "
412 "solver output is sent. The output stream defaults to stdout.");
413 pl->set ("Timer Label", std::string("Belos"),
414 "The string to use as a prefix for the timer labels.");
415 return pl;
416 }
417
418 //
419 // Empty Constructor
420 //
421 template<class ScalarType, class MV, class OP>
423 convtol_(0.0),
424 achievedTol_(0.0),
425 maxIters_(0),
426 numIters_ (0),
427 blockSize_(0),
428 verbosity_(0),
429 outputStyle_(0),
430 outputFreq_(0),
431 parametersSet_ (false)
432 {}
433
434 //
435 // Primary constructor (use this one)
436 //
437 template<class ScalarType, class MV, class OP>
440 const Teuchos::RCP<Teuchos::ParameterList>& params) :
441 problem_ (problem),
442 numIters_ (0),
443 parametersSet_ (false)
444 {
445 TEUCHOS_TEST_FOR_EXCEPTION(problem_.is_null(), std::invalid_argument,
446 "MinresSolMgr: The version of the constructor "
447 "that takes a LinearProblem to solve was given a "
448 "null LinearProblem.");
450 }
451
452 template<class ScalarType, class MV, class OP>
453 void
456 {
459 "MINRES requires that you have provided a nonnull LinearProblem to the "
460 "solver manager, before you call the solve() method.");
461 TEUCHOS_TEST_FOR_EXCEPTION(problem->getOperator().is_null(),
463 "MINRES requires a LinearProblem object with a non-null operator (the "
464 "matrix A).");
465 TEUCHOS_TEST_FOR_EXCEPTION(problem->getRHS().is_null(),
467 "MINRES requires a LinearProblem object with a non-null right-hand side.");
468 TEUCHOS_TEST_FOR_EXCEPTION( ! problem->isProblemSet(),
470 "MINRES requires that before you give it a LinearProblem to solve, you "
471 "must first call the linear problem's setProblem() method.");
472 }
473
474 template<class ScalarType, class MV, class OP>
475 void
477 setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params)
478 {
479 using Teuchos::ParameterList;
480 using Teuchos::parameterList;
481 using Teuchos::RCP;
482 using Teuchos::rcp;
483 using Teuchos::rcpFromRef;
484 using Teuchos::null;
485 using Teuchos::is_null;
486 using std::string;
487 using std::ostream;
488 using std::endl;
489
490 if (params_.is_null()) {
491 params_ = parameterList (*getValidParameters());
492 }
494 pl->validateParametersAndSetDefaults (*params_);
495
496 //
497 // Read parameters from the parameter list. We have already
498 // populated it with defaults.
499 //
500 blockSize_ = pl->get<int> ("Block Size");
501 verbosity_ = pl->get<int> ("Verbosity");
502 outputStyle_ = pl->get<int> ("Output Style");
503 outputFreq_ = pl->get<int>("Output Frequency");
504 outputStream_ = pl->get<RCP<std::ostream> > ("Output Stream");
505 convtol_ = pl->get<MagnitudeType> ("Convergence Tolerance");
506 maxIters_ = pl->get<int> ("Maximum Iterations");
507 //
508 // All done reading parameters from the parameter list.
509 // Now we know it's valid and we can store it.
510 //
511 params_ = pl;
512
513 // Change the timer label, and create the timer if necessary.
514 const string newLabel = pl->get<string> ("Timer Label");
515 {
516 if (newLabel != label_ || timerSolve_.is_null()) {
517 label_ = newLabel;
518#ifdef BELOS_TEUCHOS_TIME_MONITOR
519 const string solveLabel = label_ + ": MinresSolMgr total solve time";
520 // Unregister the old timer before creating a new one.
521 if (! timerSolve_.is_null()) {
522 Teuchos::TimeMonitor::clearCounter (label_);
523 timerSolve_ = Teuchos::null;
524 }
525 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
526#endif // BELOS_TEUCHOS_TIME_MONITOR
527 }
528 }
529
530 // Create output manager, if necessary; otherwise, set its parameters.
531 bool recreatedPrinter = false;
532 if (printer_.is_null()) {
533 printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_));
534 recreatedPrinter = true;
535 } else {
536 // Set the output stream's verbosity level.
537 printer_->setVerbosity (verbosity_);
538 // Tell the output manager about the new output stream.
539 printer_->setOStream (outputStream_);
540 }
541
542 //
543 // Set up the convergence tests
544 //
547
548 // Do we need to allocate at least one of the implicit or explicit
549 // residual norm convergence tests?
550 const bool allocatedConvergenceTests =
551 impConvTest_.is_null() || expConvTest_.is_null();
552
553 // Allocate or set the tolerance of the implicit residual norm
554 // convergence test.
555 if (impConvTest_.is_null()) {
556 impConvTest_ = rcp (new res_norm_type (convtol_));
557 impConvTest_->defineResForm (res_norm_type::Implicit, TwoNorm);
558 // TODO (mfh 03 Nov 2011) Allow users to define the type of
559 // scaling (or a custom scaling factor).
560 impConvTest_->defineScaleForm (NormOfInitRes, TwoNorm);
561 } else {
562 impConvTest_->setTolerance (convtol_);
563 }
564
565 // Allocate or set the tolerance of the explicit residual norm
566 // convergence test.
567 if (expConvTest_.is_null()) {
568 expConvTest_ = rcp (new res_norm_type (convtol_));
569 expConvTest_->defineResForm (res_norm_type::Explicit, TwoNorm);
570 // TODO (mfh 03 Nov 2011) Allow users to define the type of
571 // scaling (or a custom scaling factor).
572 expConvTest_->defineScaleForm (NormOfInitRes, TwoNorm);
573 } else {
574 expConvTest_->setTolerance (convtol_);
575 }
576
577 // Whether we need to recreate the full status test. We only need
578 // to do that if at least one of convTest_ or maxIterTest_ had to
579 // be reallocated.
580 bool needToRecreateFullStatusTest = sTest_.is_null();
581
582 // Residual status test is a combo of the implicit and explicit
583 // convergence tests.
584 if (convTest_.is_null() || allocatedConvergenceTests) {
585 convTest_ = rcp (new combo_type (combo_type::SEQ, impConvTest_, expConvTest_));
587 }
588
589 // Maximum number of iterations status test. It tells the solver to
590 // stop iteration, if the maximum number of iterations has been
591 // exceeded. Initialize it if we haven't yet done so, otherwise
592 // tell it the new maximum number of iterations.
593 if (maxIterTest_.is_null()) {
594 maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP> (maxIters_));
596 } else {
597 maxIterTest_->setMaxIters (maxIters_);
598 }
599
600 // Create the full status test if we need to.
601 //
602 // The full status test: the maximum number of iterations have
603 // been reached, OR the residual has converged.
604 //
605 // "If we need to" means either that the status test was never
606 // created before, or that its two component tests had to be
607 // reallocated.
609 sTest_ = rcp (new combo_type (combo_type::OR, maxIterTest_, convTest_));
610 }
611
612 // If necessary, create the status test output class. This class
613 // manages and formats the output from the status test. We have
614 // to recreate the output test if we had to (re)allocate either
615 // printer_ or sTest_.
616 if (outputTest_.is_null() || needToRecreateFullStatusTest || recreatedPrinter) {
618 outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_,
620 } else {
621 outputTest_->setOutputFrequency (outputFreq_);
622 }
623 // Set the solver string for the output test.
624 // StatusTestOutputFactory has no constructor argument for this.
625 outputTest_->setSolverDesc (std::string (" MINRES "));
626
627 // Inform the solver manager that the current parameters were set.
628 parametersSet_ = true;
629
630 if (verbosity_ & Debug) {
631 using std::endl;
632
633 std::ostream& dbg = printer_->stream (Debug);
634 dbg << "MINRES parameters:" << endl << params_ << endl;
635 }
636 }
637
638
639 template<class ScalarType, class MV, class OP>
641 {
642 using Teuchos::RCP;
643 using Teuchos::rcp;
644 using Teuchos::rcp_const_cast;
645 using std::endl;
646
647 if (! parametersSet_) {
648 setParameters (params_);
649 }
650 std::ostream& dbg = printer_->stream (Debug);
651
652#ifdef BELOS_TEUCHOS_TIME_MONITOR
653 Teuchos::TimeMonitor solveTimerMonitor (*timerSolve_);
654#endif // BELOS_TEUCHOS_TIME_MONITOR
655
656 // We need a problem to solve, else we can't solve it.
657 validateProblem (problem_);
658
659 // Reset the status test for this solve.
660 outputTest_->reset();
661
662 // The linear problem has this many right-hand sides to solve.
663 // MINRES can solve only one at a time, so we solve for each
664 // right-hand side in succession.
665 const int numRHS2Solve = MVT::GetNumberVecs (*(problem_->getRHS()));
666
667 // Create MINRES iteration object. Pass along the solver
668 // manager's parameters, which have already been validated.
671 rcp (new iter_type (problem_, printer_, outputTest_, *params_));
672
673 // The index/indices of the right-hand sides for which MINRES did
674 // _not_ converge. Hopefully this is empty after the for loop
675 // below! If it is not empty, at least one right-hand side did
676 // not converge.
677 std::vector<int> notConverged;
678 std::vector<int> currentIndices(1);
679
680 numIters_ = 0;
681
682 // Solve for each right-hand side in turn.
683 for (int currentRHS = 0; currentRHS < numRHS2Solve; ++currentRHS) {
684 // Inform the linear problem of the right-hand side(s) currently
685 // being solved. MINRES only knows how to solve linear problems
686 // with one right-hand side, so we only include one index, which
687 // is the index of the current right-hand side.
689 problem_->setLSIndex (currentIndices);
690
691 dbg << "-- Current right-hand side index being solved: "
692 << currentRHS << endl;
693
694 // Reset the number of iterations.
695 minres_iter->resetNumIters();
696 // Reset the number of calls that the status test output knows about.
697 outputTest_->resetNumCalls();
698 // Set the new state and initialize the solver.
700
701 // Get the residual vector for the current linear system
702 // (that is, for the current right-hand side).
703 newstate.Y = MVT::CloneViewNonConst (*(rcp_const_cast<MV> (problem_->getInitResVec())), currentIndices);
704 minres_iter->initializeMinres (newstate);
705
706 // Attempt to solve for the solution corresponding to the
707 // current right-hand side.
708 while (true) {
709 try {
710 minres_iter->iterate();
711
712 // First check for convergence
713 if (convTest_->getStatus() == Passed) {
714 dbg << "---- Converged after " << maxIterTest_->getNumIters()
715 << " iterations" << endl;
716 break;
717 }
718 // Now check for max # of iterations
719 else if (maxIterTest_->getStatus() == Passed) {
720 dbg << "---- Did not converge after " << maxIterTest_->getNumIters()
721 << " iterations" << endl;
722 // This right-hand side didn't converge!
723 notConverged.push_back (currentRHS);
724 break;
725 } else {
726 // If we get here, we returned from iterate(), but none of
727 // our status tests Passed. Something is wrong, and it is
728 // probably our fault.
729 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
730 "Belos::MinresSolMgr::solve(): iterations neither converged, "
731 "nor reached the maximum number of iterations " << maxIters_
732 << ". That means something went wrong.");
733 }
734 }
735 catch (const StatusTestNaNError& e) {
736 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
737 achievedTol_ = MST::one();
738 Teuchos::RCP<MV> X = problem_->getLHS();
739 MVT::MvInit( *X, SCT::zero() );
740 printer_->stream(Warnings) << "Belos::MinresSolMgr::solve(): Warning! NaN has been detected!"
741 << std::endl;
742 return Unconverged;
743 }
744 catch (const std::exception &e) {
745 printer_->stream (Errors)
746 << "Error! Caught std::exception in MinresIter::iterate() at "
747 << "iteration " << minres_iter->getNumIters() << endl
748 << e.what() << endl;
749 throw e;
750 }
751 }
752
753 // Inform the linear problem that we are finished with the
754 // current right-hand side. It may or may not have converged,
755 // but we don't try again if the first time didn't work.
756 problem_->setCurrLS();
757
758 // Get iteration information for this solve: total number of
759 // iterations for all right-hand sides.
760 numIters_ += maxIterTest_->getNumIters();
761 }
762
763 // Print final summary of the solution process
764 sTest_->print (printer_->stream (FinalSummary));
765
766 // Print timing information, if the corresponding compile-time and
767 // run-time options are enabled.
768#ifdef BELOS_TEUCHOS_TIME_MONITOR
769 // Calling summarize() can be expensive, so don't call unless the
770 // user wants to print out timing details. summarize() will do all
771 // the work even if it's passed a "black hole" output stream.
772 if (verbosity_ & TimingDetails) {
773 Teuchos::TimeMonitor::summarize (printer_->stream (TimingDetails));
774 }
775#endif // BELOS_TEUCHOS_TIME_MONITOR
776
777 // Save the convergence test value ("achieved tolerance") for this
778 // solve. This solver always has two residual norm status tests:
779 // an explicit and an implicit test. The master convergence test
780 // convTest_ is a SEQ combo of the implicit resp. explicit tests.
781 // If the implicit test never passes, then the explicit test won't
782 // ever be executed. This manifests as
783 // expConvTest_->getTestValue()->size() < 1. We deal with this
784 // case by using the values returned by
785 // impConvTest_->getTestValue().
786 {
787 const std::vector<MagnitudeType>* pTestValues = expConvTest_->getTestValue();
788 if (pTestValues == NULL || pTestValues->size() < 1) {
789 pTestValues = impConvTest_->getTestValue();
790 }
791 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
792 "Belos::MinresSolMgr::solve(): The implicit convergence test's getTestValue() "
793 "method returned NULL. Please report this bug to the Belos developers.");
794 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
795 "Belos::MinresSolMgr::solve(): The implicit convergence test's getTestValue() "
796 "method returned a vector of length zero. Please report this bug to the "
797 "Belos developers.");
798
799 // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
800 // achieved tolerances for all vectors in the current solve(), or
801 // just for the vectors from the last deflation?
802 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
803 }
804
805 if (notConverged.size() > 0) {
806 return Unconverged;
807 } else {
808 return Converged;
809 }
810 }
811
812 // This method requires the solver manager to return a std::string that describes itself.
813 template<class ScalarType, class MV, class OP>
815 {
816 std::ostringstream oss;
817 oss << "Belos::MinresSolMgr< "
818 << Teuchos::ScalarTraits<ScalarType>::name()
819 <<", MV, OP >";
820 // oss << "{";
821 // oss << "Block Size=" << blockSize_;
822 // oss << "}";
823 return oss.str();
824 }
825
826} // end Belos namespace
827
828#endif /* BELOS_MINRES_SOLMGR_HPP */
Belos header file which uses auto-configuration information to include necessary C++ headers.
Class which describes the linear problem to be solved by the iterative solver.
MINRES iteration implementation.
Class which manages the output and verbosity of the Belos solvers.
Pure virtual base class which describes the basic interface for a solver manager.
Belos::StatusTest for logically combining several status tests.
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
Belos::StatusTest class for specifying a maximum number of iterations.
A factory class for generating StatusTestOutput objects.
Collection of types and exceptions used within the Belos solvers.
Parent class to all Belos exceptions.
This subclass of std::exception may be thrown from the MinresSolMgr::solve() method.
MinresSolMgrLinearProblemFailure(const std::string &what_arg)
MINRES linear solver solution manager.
const LinearProblem< ScalarType, MV, OP > & getProblem() const override
Return the linear problem to be solved.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return all timers for this object.
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Return the list of current parameters for this object.
MinresSolMgr()
Default constructor.
void setParameters(const Teuchos::RCP< Teuchos::ParameterList > &params) override
Set the parameters to use when solving the linear problem.
ReturnType solve() override
Iterate until the status test tells us to stop.
bool isLOADetected() const override
Whether a loss of accuracy was detected in the solver.
Teuchos::RCP< SolverManager< ScalarType, MV, OP > > clone() const override
clone for Inverted Injection (DII)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Return the list of default parameters for this object.
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
static Teuchos::RCP< const Teuchos::ParameterList > defaultParameters()
List of valid MINRES parameters and their default values.
void reset(const ResetType type) override
Reset the solver manager.
std::string description() const override
int getNumIters() const override
Get the iteration count for the most recent call to solve().
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem) override
Set the linear problem that needs to be solved.
virtual ~MinresSolMgr()
Destructor.
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
The Belos::SolverManager is a templated virtual base class that defines the basic interface that any ...
@ FinalSummary
@ TimingDetails
ReturnType
Whether the Belos solve converged for all linear systems.
@ Unconverged
@ NormOfInitRes
ResetType
How to reset the solver.

Generated for Belos by doxygen 1.9.8