Belos Version of the Day
Loading...
Searching...
No Matches
BelosGmresPolySolMgr.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
11#ifndef BELOS_GMRES_POLY_SOLMGR_HPP
12#define BELOS_GMRES_POLY_SOLMGR_HPP
13
17
18#include "BelosConfigDefs.hpp"
19#include "BelosTypes.hpp"
20
23#include "BelosGmresPolyOp.hpp"
26#include "Teuchos_as.hpp"
27#ifdef BELOS_TEUCHOS_TIME_MONITOR
28#include "Teuchos_TimeMonitor.hpp"
29#endif
30
35namespace Belos {
36
38
39
49
59
73//
108//
120
121template<class ScalarType, class MV, class OP, class DM = DefaultDenseMatrix<int,ScalarType>>
122class GmresPolySolMgr : public SolverManager<ScalarType,MV,OP,DM> {
123private:
124
125 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
126
127 typedef Teuchos::ScalarTraits<MagnitudeType> MTS;
130
131public:
132
134
135
142
162 const Teuchos::RCP<Teuchos::ParameterList> &pl );
163
165 virtual ~GmresPolySolMgr() {};
166
168 Teuchos::RCP<SolverManager<ScalarType, MV, OP, DM> > clone () const override {
169 return Teuchos::rcp(new GmresPolySolMgr<ScalarType,MV,OP,DM>);
170 }
172
174
175
179 return *problem_;
180 }
181
184 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override;
185
188 Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const override { return params_; }
189
206 MagnitudeType achievedTol() const override {
207 return achievedTol_;
208 }
209
215 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
216 return Teuchos::tuple(timerPoly_);
217 }
218
220 int getNumIters() const override {
221 return numIters_;
222 }
223
227 bool isLOADetected() const override { return loaDetected_; }
228
230
232
233
235 void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > &problem ) override { problem_ = problem; }
236
238 void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
239
242 debugStatusTest_ = debugStatusTest;
243 }
244
246
248
257 void reset( const ResetType type ) override {
258 if ((type & Belos::Problem) && ! problem_.is_null ()) {
259 problem_->setProblem ();
260 poly_Op_ = Teuchos::null;
261 poly_dim_ = 0; // Rebuild the GMRES polynomial
262 }
263 }
264
266
268
286 ReturnType solve() override;
287
289
292
294 std::string description() const override;
295
297
298private:
299
300 // Linear problem.
301 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
302
303 // Output manager.
304 Teuchos::RCP<std::ostream> outputStream_;
305
306 // Optional debug status test (e.g. a wall-clock time limit). This manager
307 // has no Krylov iteration of its own; it is forwarded to the outer solver
308 // manager, which runs the actual iteration, whenever forwarding is
309 // type-compatible.
310 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > debugStatusTest_;
311
312 // Current parameter list.
313 Teuchos::RCP<Teuchos::ParameterList> params_;
314 Teuchos::RCP<Teuchos::ParameterList> outerParams_;
315
316 // Default solver values.
317 static constexpr int maxDegree_default_ = 25;
318 static constexpr int verbosity_default_ = Belos::Errors;
319 static constexpr const char * label_default_ = "Belos";
320 static constexpr const char * outerSolverType_default_ = "";
321 static constexpr const char * polyType_default_ = "Arnoldi";
322 static constexpr const char * orthoType_default_ = "ICGS";
323 static constexpr bool addRoots_default_ = true;
324 static constexpr bool dampPoly_default_ = false;
325 static constexpr bool randomRHS_default_ = true;
326
327 // Current solver values.
328 MagnitudeType polyTol_, achievedTol_;
329 int maxDegree_, numIters_;
330 int verbosity_;
331 bool hasOuterSolver_;
332 bool randomRHS_;
333 bool damp_;
334 bool addRoots_;
335 std::string polyType_;
336 std::string outerSolverType_;
337 std::string orthoType_;
338
339 // Polynomial storage
340 int poly_dim_;
341 Teuchos::RCP<gmres_poly_t> poly_Op_;
342
343 // Timers.
344 std::string label_;
345 Teuchos::RCP<Teuchos::Time> timerPoly_;
346
347 // Internal state variables.
348 bool isSet_;
349 bool loaDetected_;
350
352 mutable Teuchos::RCP<const Teuchos::ParameterList> validPL_;
353};
354
355
356template<class ScalarType, class MV, class OP, class DM>
358 outputStream_ (Teuchos::rcpFromRef(std::cout)),
359 polyTol_ (DefaultSolverParameters::polyTol),
360 achievedTol_(MTS::zero()),
361 maxDegree_ (maxDegree_default_),
362 numIters_ (0),
363 verbosity_ (verbosity_default_),
364 hasOuterSolver_ (false),
365 randomRHS_ (randomRHS_default_),
366 damp_ (dampPoly_default_),
367 addRoots_ (addRoots_default_),
368 polyType_ (polyType_default_),
369 outerSolverType_ (outerSolverType_default_),
370 orthoType_ (orthoType_default_),
371 poly_dim_ (0),
372 label_ (label_default_),
373 isSet_ (false),
374 loaDetected_ (false)
375{}
376
377
378template<class ScalarType, class MV, class OP, class DM>
381 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
382 problem_ (problem),
383 outputStream_ (Teuchos::rcpFromRef(std::cout)),
384 polyTol_ (DefaultSolverParameters::polyTol),
385 maxDegree_ (maxDegree_default_),
386 numIters_ (0),
387 verbosity_ (verbosity_default_),
388 hasOuterSolver_ (false),
389 randomRHS_ (randomRHS_default_),
390 damp_ (dampPoly_default_),
391 addRoots_ (addRoots_default_),
392 polyType_ (polyType_default_),
393 outerSolverType_ (outerSolverType_default_),
394 orthoType_ (orthoType_default_),
395 poly_dim_ (0),
396 label_ (label_default_),
397 isSet_ (false),
398 loaDetected_ (false)
399{
401 problem_.is_null (), std::invalid_argument,
402 "Belos::GmresPolySolMgr: The given linear problem is null. "
403 "Please call this constructor with a nonnull LinearProblem argument, "
404 "or call the constructor that does not take a LinearProblem.");
405
406 // If the input parameter list is null, then the parameters take
407 // default values.
408 if (! pl.is_null ()) {
410 }
411}
412
413
414template<class ScalarType, class MV, class OP, class DM>
415Teuchos::RCP<const Teuchos::ParameterList>
417{
418 if (validPL_.is_null ()) {
419 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList ();
420
421 // The static_cast is to resolve an issue with older clang versions which
422 // would cause the constexpr to link fail. With c++17 the problem is resolved.
423 pl->set("Polynomial Type", static_cast<const char *>(polyType_default_),
424 "The type of GMRES polynomial that is used as a preconditioner: Roots, Arnoldi, or Gmres.");
425 pl->set("Polynomial Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::polyTol),
426 "The relative residual tolerance that used to construct the GMRES polynomial.");
427 pl->set("Maximum Degree", static_cast<int>(maxDegree_default_),
428 "The maximum degree allowed for any GMRES polynomial.");
429 pl->set("Outer Solver", static_cast<const char *>(outerSolverType_default_),
430 "The outer solver that this polynomial is used to precondition.");
431 pl->set("Outer Solver Params", Teuchos::ParameterList(),
432 "Parameter list for the outer solver.");
433 pl->set("Verbosity", static_cast<int>(verbosity_default_),
434 "What type(s) of solver information should be outputted\n"
435 "to the output stream.");
436 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
437 "A reference-counted pointer to the output stream where all\n"
438 "solver output is sent.");
439 pl->set("Timer Label", static_cast<const char *>(label_default_),
440 "The string to use as a prefix for the timer labels.");
441 pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
442 "The type of orthogonalization to use to generate polynomial: DGKS, ICGS, or IMGS.");
443 pl->set("Random RHS", static_cast<bool>(randomRHS_default_),
444 "Add roots to polynomial for stability.");
445 pl->set("Add Roots", static_cast<bool>(addRoots_default_),
446 "Add roots to polynomial for stability.");
447 pl->set("Damp Poly", static_cast<bool>(dampPoly_default_),
448 "Damp polynomial for ill-conditioned problems.");
449 validPL_ = pl;
450 }
451 return validPL_;
452}
453
454
455template<class ScalarType, class MV, class OP, class DM>
457setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params)
458{
459 // Create the internal parameter list if ones doesn't already exist.
460 if (params_.is_null ()) {
461 params_ = Teuchos::parameterList (*getValidParameters ());
462 }
463 else {
464 params->validateParameters (*getValidParameters (),0);
465 }
466
467 // Check which Gmres polynomial to use
468 if (params->isParameter("Polynomial Type")) {
469 polyType_ = params->get("Polynomial Type", polyType_default_);
470 }
471
472 // Update the outer solver in our list.
473 params_->set("Polynomial Type", polyType_);
474
475 // Check if there is an outer solver for this Gmres Polynomial
476 if (params->isParameter("Outer Solver")) {
477 outerSolverType_ = params->get("Outer Solver", outerSolverType_default_);
478 }
479
480 // Update the outer solver in our list.
481 params_->set("Outer Solver", outerSolverType_);
482
483 // Check if there is a parameter list for the outer solver
484 if (params->isSublist("Outer Solver Params")) {
485 outerParams_ = Teuchos::parameterList( params->get<Teuchos::ParameterList>("Outer Solver Params") );
486 }
487
488 // Check for maximum polynomial degree
489 if (params->isParameter("Maximum Degree")) {
490 maxDegree_ = params->get("Maximum Degree",maxDegree_default_);
491 }
492
493 // Update parameter in our list.
494 params_->set("Maximum Degree", maxDegree_);
495
496 // Check to see if the timer label changed.
497 if (params->isParameter("Timer Label")) {
498 std::string tempLabel = params->get("Timer Label", label_default_);
499
500 // Update parameter in our list and solver timer
501 if (tempLabel != label_) {
502 label_ = tempLabel;
503#ifdef BELOS_TEUCHOS_TIME_MONITOR
504 std::string polyLabel = label_ + ": GmresPolyOp creation time";
505 timerPoly_ = Teuchos::TimeMonitor::getNewCounter(polyLabel);
506#endif
507 }
508 }
509
510 // Update timer label
511 params_->set("Timer Label", label_);
512
513 // Check if the orthogonalization changed.
514 if (params->isParameter("Orthogonalization")) {
515 std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
517 // Ensure that the specified orthogonalization type is valid.
518 if (! factory.isValidName (tempOrthoType)) {
519 std::ostringstream os;
520 os << "Belos::GmresPolySolMgr: Invalid orthogonalization name \""
521 << tempOrthoType << "\". The following are valid options "
522 << "for the \"Orthogonalization\" name parameter: ";
523 factory.printValidNames (os);
524 throw std::invalid_argument (os.str());
525 }
526 if (tempOrthoType != orthoType_) {
527 orthoType_ = tempOrthoType;
528 }
529 }
530
531 params_->set("Orthogonalization", orthoType_);
532
533 // Check for a change in verbosity level
534 if (params->isParameter("Verbosity")) {
535 if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
536 verbosity_ = params->get("Verbosity", verbosity_default_);
537 } else {
538 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
539 }
540 }
541
542 // Update parameter in our list.
543 params_->set("Verbosity", verbosity_);
544
545 // output stream
546 if (params->isParameter("Output Stream")) {
547 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
548 }
549
550 // Update parameter in our list.
551 params_->set("Output Stream", outputStream_);
552
553 // Convergence
554 // Check for polynomial convergence tolerance
555 if (params->isParameter("Polynomial Tolerance")) {
556 if (params->isType<MagnitudeType> ("Polynomial Tolerance")) {
557 polyTol_ = params->get ("Polynomial Tolerance",
558 static_cast<MagnitudeType> (DefaultSolverParameters::polyTol));
559 }
560 else {
561 polyTol_ = params->get ("Polynomial Tolerance", DefaultSolverParameters::polyTol);
562 }
563 }
564
565 // Update parameter in our list and residual tests.
566 params_->set("Polynomial Tolerance", polyTol_);
567
568 // Check for maximum polynomial degree
569 if (params->isParameter("Random RHS")) {
570 randomRHS_ = params->get("Random RHS",randomRHS_default_);
571 }
572
573 // Update parameter in our list.
574 params_->set("Random RHS", randomRHS_);
575
576
577 // Check for polynomial damping
578 if (params->isParameter("Damped Poly")) {
579 damp_ = params->get("Damped Poly",dampPoly_default_);
580 }
581 // Update parameter in our list.
582 params_->set("Damped Poly", damp_);
583
584 // Check: Should we add roots for stability if needed?
585 if (params->isParameter("Add Roots")) {
586 addRoots_ = params->get("Add Roots",addRoots_default_);
587 }
588
589 // Update parameter in our list.
590 params_->set("Add Roots", addRoots_);
591
592 // Create the timers if we need to.
593#ifdef BELOS_TEUCHOS_TIME_MONITOR
594 if (timerPoly_ == Teuchos::null) {
595 std::string polyLabel = label_ + ": GmresPolyOp creation time";
596 timerPoly_ = Teuchos::TimeMonitor::getNewCounter(polyLabel);
597 }
598#endif
599
600 // Check if we are going to perform an outer solve.
601 if (outerSolverType_ != "") {
602 hasOuterSolver_ = true;
603 }
604
605 // Inform the solver manager that the current parameters were set.
606 isSet_ = true;
607}
608
609
610template<class ScalarType, class MV, class OP, class DM>
612{
613 using Teuchos::RCP;
614 using Teuchos::rcp;
615 using Teuchos::rcp_const_cast;
616
617 // Assume convergence is achieved if user does not require strict convergence.
619
620 // Set the current parameters if they were not set before. NOTE:
621 // This may occur if the user generated the solver manager with the
622 // default constructor and then didn't set any parameters using
623 // setParameters().
624 if (! isSet_) {
625 setParameters (Teuchos::parameterList (*getValidParameters ()));
626 }
627
629 problem_.is_null (), GmresPolySolMgrLinearProblemFailure,
630 "Belos::GmresPolySolMgr::solve: The linear problem has not been set yet, "
631 "or was set to null. Please call setProblem() with a nonnull input before "
632 "calling solve().");
633
635 ! problem_->isProblemSet (), GmresPolySolMgrLinearProblemFailure,
636 "Belos::GmresPolySolMgr::solve: The linear problem is not ready. Please "
637 "call setProblem() on the LinearProblem object before calling solve().");
638
639 // If the GMRES polynomial has not been constructed for this
640 // (nmatrix, preconditioner) pair, generate it.
641 if (!poly_dim_ && maxDegree_) {
642#ifdef BELOS_TEUCHOS_TIME_MONITOR
643 Teuchos::TimeMonitor slvtimer(*timerPoly_);
644#endif
645 poly_Op_ = Teuchos::rcp( new gmres_poly_t( problem_, params_ ) );
646 poly_dim_ = poly_Op_->polyDegree();
647
649 "Belos::GmresPolyOp: Failed to generate polynomial that satisfied requirements.");
650 }
651
652
653 // Solve the linear system using the polynomial
654 if (hasOuterSolver_ && maxDegree_) {
655
656 // Then the polynomial will be used as an operator for an outer solver.
657 // Use outer solver parameter list passed in a sublist.
659 RCP<SolverManager<ScalarType, MultiVec<ScalarType,DM>, Operator<ScalarType, DM>, DM> > solver = factory.create( outerSolverType_, outerParams_ );
660 TEUCHOS_TEST_FOR_EXCEPTION( solver == Teuchos::null, std::invalid_argument,
661 "Belos::GmresPolySolMgr::solve(): Selected solver is not valid.");
662
663 // Create a copy of the linear problem that uses the polynomial as a preconditioner.
664 // The original initial solution and right-hand side are thinly wrapped in the gmres_poly_mv_t
665 RCP<gmres_poly_mv_t> new_lhs = rcp( new gmres_poly_mv_t( problem_->getLHS() ) );
666 RCP<gmres_poly_mv_t> new_rhs = rcp( new gmres_poly_mv_t( rcp_const_cast<MV>( problem_->getRHS() ) ) );
667 RCP<gmres_poly_t> A = rcp( new gmres_poly_t( problem_ ) ); // This just performs problem_->applyOp
670 std::string solverLabel = label_ + ": Hybrid Gmres";
671 newProblem->setLabel(solverLabel);
672
673 // If the preconditioner is left preconditioner, use Gmres poly as a left preconditioner.
674 if (problem_->getLeftPrec() != Teuchos::null)
675 newProblem->setLeftPrec( poly_Op_ );
676 else
677 newProblem->setRightPrec( poly_Op_ );
678 // Set the initial residual vector, if it has already been set in the original problem.
679 // Don't set the preconditioned residual vector, because it is not the GmresPoly preconditioned residual vector.
680 if (problem_->getInitResVec() != Teuchos::null)
681 newProblem->setInitResVec( rcp( new gmres_poly_mv_t( rcp_const_cast<MV>( problem_->getInitResVec() ) ) ) );
682 newProblem->setProblem();
683
684 solver->setProblem( newProblem );
685
686 retType = solver->solve();
687 numIters_ = solver->getNumIters();
688 loaDetected_ = solver->isLOADetected();
689 achievedTol_ = solver->achievedTol();
690
691 } // if (hasOuterSolver_ && maxDegree_)
692 else if (hasOuterSolver_) {
693
694 // There is no polynomial, just create the outer solver with the outerSolverType_ and outerParams_.
696 RCP<SolverManager<ScalarType, MV, OP, DM> > solver = factory.create( outerSolverType_, outerParams_ );
697 TEUCHOS_TEST_FOR_EXCEPTION( solver == Teuchos::null, std::invalid_argument,
698 "Belos::GmresPolySolMgr::solve(): Selected solver is not valid.");
699
700 solver->setProblem( problem_ );
701
702 // Forward any debug status test (e.g. a wall-clock time limit) to the outer
703 // solver manager, which runs the actual Krylov iteration and honors it.
704 if (Teuchos::nonnull(debugStatusTest_)) {
705 solver->setDebugStatusTest(debugStatusTest_);
706 }
707
708 retType = solver->solve();
709 numIters_ = solver->getNumIters();
710 loaDetected_ = solver->isLOADetected();
711 achievedTol_ = solver->achievedTol();
712
713 }
714 else if (maxDegree_) {
715
716 // Apply the polynomial to the current linear system
717 poly_Op_->ApplyPoly( *problem_->getRHS(), *problem_->getLHS() );
718 achievedTol_ = MTS::one();
719
720 }
721
722 return retType;
723}
724
725
726template<class ScalarType, class MV, class OP, class DM>
728{
729 std::ostringstream out;
730
731 out << "\"Belos::GmresPolySolMgr\": {"
732 << "ScalarType: " << Teuchos::TypeNameTraits<ScalarType>::name ()
733 << ", Poly Degree: " << poly_dim_
734 << ", Poly Max Degree: " << maxDegree_
735 << ", Poly Tol: " << polyTol_;
736 out << "}";
737 return out.str ();
738}
739
740} // namespace Belos
741
742#ifdef HAVE_BELOS_TPETRA
744
745#define BELOS_TPETRA_GMRESPOLYSOLMGR_NOEXTERN_CALL(SC, LO, GO, NT) \
746 BELOS_TPETRA_CALL(Belos::GmresPolySolMgr, SC, LO, GO, NT)
747
748#define BELOS_TPETRA_GMRESPOLYSOLMGR_EXTERN_CALL(SC, LO, GO, NT) \
749 BELOS_TPETRA_EXTERN_CALL(Belos::GmresPolySolMgr, SC, LO, GO, NT)
750
751TPETRA_INSTANTIATE_SLGN_NO_ORDINAL_SCALAR(BELOS_TPETRA_GMRESPOLYSOLMGR_EXTERN_CALL)
752#endif
753
754#endif // BELOS_GMRES_POLY_SOLMGR_HPP
Belos header file which uses auto-configuration information to include necessary C++ headers.
Defines the GMRES polynomial operator hybrid-GMRES iterative linear solver.
Class which describes the linear problem to be solved by the iterative solver.
Pure virtual base class which describes the basic interface for a solver manager.
Collection of types and exceptions used within the Belos solvers.
Parent class to all Belos exceptions.
The GMRES polynomial can be created in conjunction with any standard preconditioner.
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
std::string description() const override
Method to return description of the hybrid block GMRES solver manager.
GmresPolySolMgr()
Empty constructor for GmresPolySolMgr. This constructor takes no arguments and sets the default value...
ReturnType solve() override
This method performs possibly repeated calls to the underlying linear solver's iterate() routine unti...
void reset(const ResetType type) override
Reset the solver.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Get a parameter list containing the valid parameters for this object.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem) override
Set the linear problem that needs to be solved.
Teuchos::RCP< SolverManager< ScalarType, MV, OP, DM > > clone() const override
clone for Inverted Injection (DII)
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve.
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &debugStatusTest) override
Set a debug status test, forwarded to the outer solver manager (if any).
void setParameters(const Teuchos::RCP< Teuchos::ParameterList > &params) override
Set the parameters the solver manager should use to solve the linear problem.
virtual ~GmresPolySolMgr()
Destructor.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const override
Get current linear problem being solved for in this object.
int getNumIters() const override
Get the iteration count for the most recent call to solve().
GmresPolySolMgrLinearProblemFailure is thrown when the linear problem is not setup (i....
GmresPolySolMgrLinearProblemFailure(const std::string &what_arg)
GmresPolySolMgrPolynomialFailure is thrown when their is a problem generating the GMRES polynomial fo...
GmresPolySolMgrPolynomialFailure(const std::string &what_arg)
A linear system to solve, and its associated information.
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 ...
ReturnType
Whether the Belos solve converged for all linear systems.
ResetType
How to reset the solver.
Default parameters common to most Belos solvers.
static const double polyTol
Relative residual tolerance for matrix polynomial construction.

Generated for Belos by doxygen 1.9.8