Belos Version of the Day
Loading...
Searching...
No Matches
BelosPseudoBlockCGSolMgr.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_PSEUDO_BLOCK_CG_SOLMGR_HPP
11#define BELOS_PSEUDO_BLOCK_CG_SOLMGR_HPP
12
17#include "BelosCGIteration.hpp"
18#include "BelosConfigDefs.hpp"
19#include "BelosTypes.hpp"
20
23
25#include "BelosCGIter.hpp"
31#include "Teuchos_LAPACK.hpp"
32#ifdef BELOS_TEUCHOS_TIME_MONITOR
33#include "Teuchos_TimeMonitor.hpp"
34#endif
35
55namespace Belos {
56
58
59
69
70
71 // Partial specialization for unsupported ScalarType types.
72 // This contains a stub implementation.
73 template<class ScalarType, class MV, class OP, class DM = DefaultDenseMatrix<int,ScalarType>,
74 const bool supportsScalarType =
75 Details::LapackSupportsScalar<ScalarType>::value>
77 public Details::SolverManagerRequiresLapack<ScalarType, MV, OP, DM,
78 Details::LapackSupportsScalar<ScalarType>::value>
79 {
80 static const bool scalarTypeIsSupported =
83
84 public:
89 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
90 base_type ()
91 {}
92 virtual ~PseudoBlockCGSolMgr () = default;
93
94 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> >
95 getResidualStatusTest() const { return Teuchos::null; }
96 };
97
98
99 template<class ScalarType, class MV, class OP, class DM>
101 public Details::SolverManagerRequiresLapack<ScalarType, MV, OP, DM, true>
102 {
103 private:
106 using SCT = Teuchos::ScalarTraits<ScalarType>;
107 using MagnitudeType = typename Teuchos::ScalarTraits<ScalarType>::magnitudeType;
108 using MT = Teuchos::ScalarTraits<MagnitudeType>;
109
110 public:
111
113
114
121
138 const Teuchos::RCP<Teuchos::ParameterList> &pl );
139
141 virtual ~PseudoBlockCGSolMgr() = default;
142
144 Teuchos::RCP<SolverManager<ScalarType, MV, OP, DM> > clone () const override {
145 return Teuchos::rcp(new PseudoBlockCGSolMgr<ScalarType,MV,OP,DM>);
146 }
148
150
151
153 return *problem_;
154 }
155
158 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override;
159
162 Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const override { return params_; }
163
169 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
170 return Teuchos::tuple(timerSolve_);
171 }
172
173
184 MagnitudeType achievedTol() const override {
185 return achievedTol_;
186 }
187
189 int getNumIters() const override {
190 return numIters_;
191 }
192
196 bool isLOADetected() const override { return false; }
197
201 ScalarType getConditionEstimate() const {return condEstimate_;}
202 Teuchos::ArrayRCP<MagnitudeType> getEigenEstimates() const {return eigenEstimates_;}
203
205 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> >
206 getResidualStatusTest() const { return convTest_; }
207
209
211
212
214 void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > &problem ) override { problem_ = problem; }
215
217 void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
218
221 debugStatusTest_ = debugStatusTest;
222 // Force the cached status-test tree (and its output wrapper) to be rebuilt
223 // on the next solve so the debug test is wired into sTest_. This manager
224 // caches sTest_/outputTest_ behind null checks, so clear them and re-run
225 // setParameters.
226 sTest_ = Teuchos::null;
227 outputTest_ = Teuchos::null;
228 isSet_ = false;
229 }
230
232
234
235
239 void reset( const ResetType type ) override { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
241
243
244
262 ReturnType solve() override;
263
265
268
270 std::string description() const override;
271
273 private:
274 // Compute the condition number estimate
275 void compute_condnum_tridiag_sym(Teuchos::ArrayView<MagnitudeType> diag,
276 Teuchos::ArrayView<MagnitudeType> offdiag,
277 Teuchos::ArrayRCP<MagnitudeType>& lambdas,
281
282 // Linear problem.
283 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
284
285 // Output manager.
286 Teuchos::RCP<OutputManager<ScalarType> > printer_;
287 Teuchos::RCP<std::ostream> outputStream_;
288
289 // Status test.
290 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > sTest_;
291 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP,DM> > maxIterTest_;
292 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > convTest_;
293 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP,DM> > outputTest_;
294 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > debugStatusTest_;
295
296 // Current parameter list.
297 Teuchos::RCP<Teuchos::ParameterList> params_;
298
304 mutable Teuchos::RCP<const Teuchos::ParameterList> validParams_;
305
306 // Default solver values.
307 static constexpr int maxIters_default_ = 1000;
308 static constexpr bool assertPositiveDefiniteness_default_ = true;
309 static constexpr bool showMaxResNormOnly_default_ = false;
310 static constexpr int verbosity_default_ = Belos::Errors;
311 static constexpr int outputStyle_default_ = Belos::General;
312 static constexpr int outputFreq_default_ = -1;
313 static constexpr int defQuorum_default_ = 1;
314 static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ = false;
315 static constexpr const char * resScale_default_ = "Norm of Initial Residual";
316 static constexpr const char * label_default_ = "Belos";
317 static constexpr bool genCondEst_default_ = false;
318
319 // Current solver values.
320 MagnitudeType convtol_,achievedTol_;
321 int maxIters_, numIters_;
322 int verbosity_, outputStyle_, outputFreq_, defQuorum_;
323 bool assertPositiveDefiniteness_, showMaxResNormOnly_;
324 bool foldConvergenceDetectionIntoAllreduce_;
325 std::string resScale_;
326 bool genCondEst_;
327 ScalarType condEstimate_;
328 Teuchos::ArrayRCP<MagnitudeType> eigenEstimates_;
329
330 Teuchos::RCP<CGIterationStateBase<ScalarType, MV, DM> > state_;
331
332 // Timers.
333 std::string label_;
334 Teuchos::RCP<Teuchos::Time> timerSolve_;
335
336 // Internal state variables.
337 bool isSet_;
338 };
339
340
341// Empty Constructor
342template<class ScalarType, class MV, class OP, class DM>
344 outputStream_(Teuchos::rcpFromRef(std::cout)),
345 convtol_(DefaultSolverParameters::convTol),
346 maxIters_(maxIters_default_),
347 numIters_(0),
348 verbosity_(verbosity_default_),
349 outputStyle_(outputStyle_default_),
350 outputFreq_(outputFreq_default_),
351 defQuorum_(defQuorum_default_),
352 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
353 showMaxResNormOnly_(showMaxResNormOnly_default_),
354 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
355 resScale_(resScale_default_),
356 genCondEst_(genCondEst_default_),
357 condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
358 label_(label_default_),
359 isSet_(false)
360{}
361
362// Basic Constructor
363template<class ScalarType, class MV, class OP, class DM>
366 const Teuchos::RCP<Teuchos::ParameterList> &pl ) :
367 problem_(problem),
368 outputStream_(Teuchos::rcpFromRef(std::cout)),
369 convtol_(DefaultSolverParameters::convTol),
370 maxIters_(maxIters_default_),
371 numIters_(0),
372 verbosity_(verbosity_default_),
373 outputStyle_(outputStyle_default_),
374 outputFreq_(outputFreq_default_),
375 defQuorum_(defQuorum_default_),
376 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
377 showMaxResNormOnly_(showMaxResNormOnly_default_),
378 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
379 resScale_(resScale_default_),
380 genCondEst_(genCondEst_default_),
381 condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
382 label_(label_default_),
383 isSet_(false)
384{
386 problem_.is_null (), std::invalid_argument,
387 "Belos::PseudoBlockCGSolMgr two-argument constructor: "
388 "'problem' is null. You must supply a non-null Belos::LinearProblem "
389 "instance when calling this constructor.");
390
391 if (! pl.is_null ()) {
392 // Set the parameters using the list that was passed in.
393 setParameters (pl);
394 }
395}
396
397template<class ScalarType, class MV, class OP, class DM>
399setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params)
400{
401 using Teuchos::ParameterList;
402 using Teuchos::parameterList;
403 using Teuchos::RCP;
404 using Teuchos::rcp;
405
406 RCP<const ParameterList> defaultParams = this->getValidParameters ();
407
408 // Create the internal parameter list if one doesn't already exist.
409 // Belos' solvers treat the input ParameterList to setParameters as
410 // a "delta" -- that is, a change from the current state -- so the
411 // default parameter list (if the input is null) should be empty.
412 // This explains also why Belos' solvers copy parameters one by one
413 // from the input list to the current list.
414 //
415 // Belos obfuscates the latter, because it takes the input parameter
416 // list by RCP, rather than by (nonconst) reference. The latter
417 // would make more sense, given that it doesn't actually keep the
418 // input parameter list.
419 //
420 // Note, however, that Belos still correctly triggers the "used"
421 // field of each parameter in the input list. While isParameter()
422 // doesn't (apparently) trigger the "used" flag, get() certainly
423 // does.
424
425 if (params_.is_null ()) {
426 // Create an empty list with the same name as the default list.
427 params_ = parameterList (defaultParams->name ());
428 } else {
429 params->validateParameters (*defaultParams);
430 }
431
432 // Check for maximum number of iterations
433 if (params->isParameter ("Maximum Iterations")) {
434 maxIters_ = params->get ("Maximum Iterations", maxIters_default_);
435
436 // Update parameter in our list and in status test.
437 params_->set ("Maximum Iterations", maxIters_);
438 if (! maxIterTest_.is_null ()) {
439 maxIterTest_->setMaxIters (maxIters_);
440 }
441 }
442
443 // Check if positive definiteness assertions are to be performed
444 if (params->isParameter ("Assert Positive Definiteness")) {
445 assertPositiveDefiniteness_ =
446 params->get ("Assert Positive Definiteness",
447 assertPositiveDefiniteness_default_);
448
449 // Update parameter in our list.
450 params_->set ("Assert Positive Definiteness", assertPositiveDefiniteness_);
451 }
452
453 if (params->isParameter("Fold Convergence Detection Into Allreduce")) {
454 foldConvergenceDetectionIntoAllreduce_ = params->get("Fold Convergence Detection Into Allreduce",
455 foldConvergenceDetectionIntoAllreduce_default_);
456 }
457
458 // Check to see if the timer label changed.
459 if (params->isParameter ("Timer Label")) {
460 const std::string tempLabel = params->get ("Timer Label", label_default_);
461
462 // Update parameter in our list and solver timer
463 if (tempLabel != label_) {
464 label_ = tempLabel;
465 params_->set ("Timer Label", label_);
466 const std::string solveLabel =
467 label_ + ": PseudoBlockCGSolMgr total solve time";
468#ifdef BELOS_TEUCHOS_TIME_MONITOR
469 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
470#endif
471 }
472 }
473
474 // Check for a change in verbosity level
475 if (params->isParameter ("Verbosity")) {
476 if (Teuchos::isParameterType<int> (*params, "Verbosity")) {
477 verbosity_ = params->get ("Verbosity", verbosity_default_);
478 } else {
479 verbosity_ = (int) Teuchos::getParameter<Belos::MsgType> (*params, "Verbosity");
480 }
481
482 // Update parameter in our list.
483 params_->set ("Verbosity", verbosity_);
484 if (! printer_.is_null ()) {
485 printer_->setVerbosity (verbosity_);
486 }
487 }
488
489 // Check for a change in output style
490 if (params->isParameter ("Output Style")) {
491 if (Teuchos::isParameterType<int> (*params, "Output Style")) {
492 outputStyle_ = params->get ("Output Style", outputStyle_default_);
493 } else {
494 // FIXME (mfh 29 Jul 2015) What if the type is wrong?
495 outputStyle_ = (int) Teuchos::getParameter<Belos::OutputType> (*params, "Output Style");
496 }
497
498 // Reconstruct the convergence test if the explicit residual test
499 // is not being used.
500 params_->set ("Output Style", outputStyle_);
501 outputTest_ = Teuchos::null;
502 }
503
504 // output stream
505 if (params->isParameter ("Output Stream")) {
506 outputStream_ = params->get<RCP<std::ostream> > ("Output Stream");
507
508 // Update parameter in our list.
509 params_->set ("Output Stream", outputStream_);
510 if (! printer_.is_null ()) {
511 printer_->setOStream (outputStream_);
512 }
513 }
514
515 // frequency level
516 if (verbosity_ & Belos::StatusTestDetails) {
517 if (params->isParameter ("Output Frequency")) {
518 outputFreq_ = params->get ("Output Frequency", outputFreq_default_);
519 }
520
521 // Update parameter in out list and output status test.
522 params_->set ("Output Frequency", outputFreq_);
523 if (! outputTest_.is_null ()) {
524 outputTest_->setOutputFrequency (outputFreq_);
525 }
526 }
527
528 // Condition estimate
529 if (params->isParameter ("Estimate Condition Number")) {
530 genCondEst_ = params->get ("Estimate Condition Number", genCondEst_default_);
531 }
532
533 // Create output manager if we need to.
534 if (printer_.is_null ()) {
535 printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_));
536 }
537
538 // Convergence
539 using StatusTestCombo_t = Belos::StatusTestCombo<ScalarType, MV, OP, DM>;
540 using StatusTestResNorm_t = Belos::StatusTestGenResNorm<ScalarType, MV, OP, DM>;
541
542 // Check for convergence tolerance
543 if (params->isParameter ("Convergence Tolerance")) {
544 if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
545 convtol_ = params->get ("Convergence Tolerance",
546 static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
547 }
548 else {
549 convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
550 }
551
552 // Update parameter in our list and residual tests.
553 params_->set ("Convergence Tolerance", convtol_);
554 if (! convTest_.is_null ()) {
555 convTest_->setTolerance (convtol_);
556 }
557 }
558
559 if (params->isParameter ("Show Maximum Residual Norm Only")) {
560 showMaxResNormOnly_ = params->get<bool> ("Show Maximum Residual Norm Only");
561
562 // Update parameter in our list and residual tests
563 params_->set ("Show Maximum Residual Norm Only", showMaxResNormOnly_);
564 if (! convTest_.is_null ()) {
565 convTest_->setShowMaxResNormOnly (showMaxResNormOnly_);
566 }
567 }
568
569 // Check for a change in scaling, if so we need to build new residual tests.
570 bool newResTest = false;
571 {
572 // "Residual Scaling" is the old parameter name; "Implicit
573 // Residual Scaling" is the new name. We support both options for
574 // backwards compatibility.
575 std::string tempResScale = resScale_;
576 bool implicitResidualScalingName = false;
577 if (params->isParameter ("Residual Scaling")) {
578 tempResScale = params->get<std::string> ("Residual Scaling");
579 }
580 else if (params->isParameter ("Implicit Residual Scaling")) {
581 tempResScale = params->get<std::string> ("Implicit Residual Scaling");
583 }
584
585 // Only update the scaling if it's different.
586 if (resScale_ != tempResScale) {
589 resScale_ = tempResScale;
590
591 // Update parameter in our list and residual tests, using the
592 // given parameter name.
594 params_->set ("Implicit Residual Scaling", resScale_);
595 }
596 else {
597 params_->set ("Residual Scaling", resScale_);
598 }
599
600 if (! convTest_.is_null ()) {
601 try {
602 convTest_->defineScaleForm (resScaleType, Belos::TwoNorm);
603 }
604 catch (std::exception& e) {
605 // Make sure the convergence test gets constructed again.
606 newResTest = true;
607 }
608 }
609 }
610 }
611
612 // Get the deflation quorum, or number of converged systems before deflation is allowed
613 if (params->isParameter ("Deflation Quorum")) {
614 defQuorum_ = params->get ("Deflation Quorum", defQuorum_);
615 params_->set ("Deflation Quorum", defQuorum_);
616 if (! convTest_.is_null ()) {
617 convTest_->setQuorum( defQuorum_ );
618 }
619 }
620
621 // Create status tests if we need to.
622
623 // Basic test checks maximum iterations and native residual.
624 if (maxIterTest_.is_null ()) {
625 maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP,DM> (maxIters_));
626 }
627
628 // Implicit residual test, using the native residual to determine if convergence was achieved.
629 if (convTest_.is_null () || newResTest) {
630 convTest_ = rcp (new StatusTestResNorm_t (convtol_, defQuorum_, showMaxResNormOnly_));
631 convTest_->defineScaleForm (convertStringToScaleType (resScale_), Belos::TwoNorm);
632 }
633
634 if (sTest_.is_null () || newResTest) {
635 sTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::OR, maxIterTest_, convTest_));
636 if (Teuchos::nonnull(debugStatusTest_)) {
637 // Add the debug convergence test, if it exists.
638 sTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::OR, sTest_, debugStatusTest_));
639 }
640 }
641
642 if (outputTest_.is_null () || newResTest) {
643 // Create the status test output class.
644 // This class manages and formats the output from the status test.
646 outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_,
648
649 // Set the solver string for the output test
650 const std::string solverDesc = " Pseudo Block CG ";
651 outputTest_->setSolverDesc (solverDesc);
652 }
653
654 // Create the timer if we need to.
655 if (timerSolve_.is_null ()) {
656 const std::string solveLabel =
657 label_ + ": PseudoBlockCGSolMgr total solve time";
658#ifdef BELOS_TEUCHOS_TIME_MONITOR
659 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
660#endif
661 }
662
663 // Inform the solver manager that the current parameters were set.
664 isSet_ = true;
665}
666
667
668template<class ScalarType, class MV, class OP, class DM>
669Teuchos::RCP<const Teuchos::ParameterList>
671{
672 using Teuchos::ParameterList;
673 using Teuchos::parameterList;
674 using Teuchos::RCP;
675
676 if (validParams_.is_null()) {
677 // Set all the valid parameters and their default values.
679 pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
680 "The relative residual tolerance that needs to be achieved by the\n"
681 "iterative solver in order for the linear system to be declared converged.");
682 pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
683 "The maximum number of block iterations allowed for each\n"
684 "set of RHS solved.");
685 pl->set("Assert Positive Definiteness", static_cast<bool>(assertPositiveDefiniteness_default_),
686 "Whether or not to assert that the linear operator\n"
687 "and the preconditioner are indeed positive definite.");
688 pl->set("Verbosity", static_cast<int>(verbosity_default_),
689 "What type(s) of solver information should be outputted\n"
690 "to the output stream.");
691 pl->set("Output Style", static_cast<int>(outputStyle_default_),
692 "What style is used for the solver information outputted\n"
693 "to the output stream.");
694 pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
695 "How often convergence information should be outputted\n"
696 "to the output stream.");
697 pl->set("Deflation Quorum", static_cast<int>(defQuorum_default_),
698 "The number of linear systems that need to converge before\n"
699 "they are deflated. This number should be <= block size.");
700 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
701 "A reference-counted pointer to the output stream where all\n"
702 "solver output is sent.");
703 pl->set("Show Maximum Residual Norm Only", static_cast<bool>(showMaxResNormOnly_default_),
704 "When convergence information is printed, only show the maximum\n"
705 "relative residual norm when the block size is greater than one.");
706 pl->set("Implicit Residual Scaling", resScale_default_,
707 "The type of scaling used in the residual convergence test.");
708 pl->set("Estimate Condition Number", static_cast<bool>(genCondEst_default_),
709 "Whether or not to estimate the condition number of the preconditioned system.");
710 // We leave the old name as a valid parameter for backwards
711 // compatibility (so that validateParametersAndSetDefaults()
712 // doesn't raise an exception if it encounters "Residual
713 // Scaling"). The new name was added for compatibility with other
714 // solvers, none of which use "Residual Scaling".
715 pl->set("Residual Scaling", resScale_default_,
716 "The type of scaling used in the residual convergence test. This "
717 "name is deprecated; the new name is \"Implicit Residual Scaling\".");
718 pl->set("Timer Label", static_cast<const char *>(label_default_),
719 "The string to use as a prefix for the timer labels.");
720 pl->set("Fold Convergence Detection Into Allreduce",static_cast<bool>(foldConvergenceDetectionIntoAllreduce_default_),
721 "Merge the allreduce for convergence detection with the one for CG.\n"
722 "This saves one all-reduce, but incurs more computation.");
723 validParams_ = pl;
724 }
725 return validParams_;
726}
727
728
729// solve()
730template<class ScalarType, class MV, class OP, class DM>
732{
733 const char prefix[] = "Belos::PseudoBlockCGSolMgr::solve: ";
734
736
737 // Set the current parameters if they were not set before.
738 // NOTE: This may occur if the user generated the solver manager with the default constructor and
739 // then didn't set any parameters using setParameters().
740 if (!isSet_) { setParameters( params_ ); }
741
743 (! problem_->isProblemSet (), PseudoBlockCGSolMgrLinearProblemFailure,
744 prefix << "The linear problem to solve is not ready. You must call "
745 "setProblem() on the Belos::LinearProblem instance before telling the "
746 "Belos solver to solve it.");
747
748 // Create indices for the linear systems to be solved.
749 int startPtr = 0;
750 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
752
753 std::vector<int> currIdx( numRHS2Solve ), currIdx2( numRHS2Solve );
754 for (int i=0; i<numRHS2Solve; ++i) {
755 currIdx[i] = startPtr+i;
756 currIdx2[i]=i;
757 }
758
759 // Inform the linear problem of the current linear system to solve.
760 problem_->setLSIndex( currIdx );
761
763 // Parameter list (iteration)
764 Teuchos::ParameterList plist;
765
766 plist.set("Assert Positive Definiteness",assertPositiveDefiniteness_);
767 if(genCondEst_) plist.set("Max Size For Condest",maxIters_);
768
769 // Reset the status test.
770 outputTest_->reset();
771
772 // Assume convergence is achieved, then let any failed convergence set this to false.
773 bool isConverged = true;
774
776 // Pseudo-Block CG solver
777 Teuchos::RCP<CGIteration<ScalarType,MV,OP,DM> > block_cg_iter;
778 if (numRHS2Solve == 1) {
779 plist.set("Fold Convergence Detection Into Allreduce",
780 foldConvergenceDetectionIntoAllreduce_);
782 Teuchos::rcp (new CGIter<ScalarType,MV,OP,DM> (problem_, printer_, outputTest_, convTest_, plist));
783 if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType, MV, DM> >(state_).is_null())
784 state_ = Teuchos::rcp(new CGIterationState<ScalarType, MV, DM>());
785 } else {
787 Teuchos::rcp (new PseudoBlockCGIter<ScalarType,MV,OP,DM> (problem_, printer_, outputTest_, plist));
788 if (state_.is_null() || Teuchos::rcp_dynamic_cast<PseudoBlockCGIterationState<ScalarType, MV, DM> >(state_).is_null())
789 state_ = Teuchos::rcp(new PseudoBlockCGIterationState<ScalarType, MV, DM>());
790 }
791
792 // Setup condition estimate
793 block_cg_iter->setDoCondEst(genCondEst_);
794 bool condEstPerf = false;
795
796 // Enter solve() iterations
797 {
798#ifdef BELOS_TEUCHOS_TIME_MONITOR
799 Teuchos::TimeMonitor slvtimer(*timerSolve_);
800#endif
801
802 while ( numRHS2Solve > 0 ) {
803
804 // Reset the active / converged vectors from this block
805 std::vector<int> convRHSIdx;
806 std::vector<int> currRHSIdx( currIdx );
807 currRHSIdx.resize(numCurrRHS);
808
809 // Reset the number of iterations.
810 block_cg_iter->resetNumIters();
811
812 // Reset the number of calls that the status test output knows about.
813 outputTest_->resetNumCalls();
814
815 // Get the current residual for this block of linear systems.
816 Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
817
818 // Get a new state struct and initialize the solver.
819 block_cg_iter->initializeCG(state_, R_0);
820
821 while(true) {
822
823 // tell block_gmres_iter to iterate
824 try {
825
826 block_cg_iter->iterate();
827
829 //
830 // check convergence first
831 //
833 if ( convTest_->getStatus() == Passed ) {
834
835 // Figure out which linear systems converged.
836 std::vector<int> convIdx = Teuchos::rcp_dynamic_cast<StatusTestGenResNorm<ScalarType,MV,OP,DM> >(convTest_)->convIndices();
837
838 // If the number of converged linear systems is equal to the
839 // number of current linear systems, then we are done with this block.
840 if (convIdx.size() == currRHSIdx.size())
841 break; // break from while(1){block_cg_iter->iterate()}
842
843 // Inform the linear problem that we are finished with this current linear system.
844 problem_->setCurrLS();
845
846 // Reset currRHSIdx to have the right-hand sides that are left to converge for this block.
847 int have = 0;
848 for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
849 bool found = false;
850 for (unsigned int j=0; j<convIdx.size(); ++j) {
851 if (currRHSIdx[i] == convIdx[j]) {
852 found = true;
853 break;
854 }
855 }
856 if (!found) {
859 }
860 }
861 currRHSIdx.resize(have);
862 currIdx2.resize(have);
863
864 // Compute condition estimate if the very first linear system in the block has converged.
865 if (currRHSIdx[0] != 0 && genCondEst_ && !condEstPerf)
866 {
867 // Compute the estimate.
869 Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
870 Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
871 compute_condnum_tridiag_sym(diag,offdiag,eigenEstimates_,l_min,l_max,condEstimate_);
872
873 // Make sure not to do more condition estimate computations for this solve.
874 block_cg_iter->setDoCondEst(false);
875 condEstPerf = true;
876 }
877
878 // Set the remaining indices after deflation.
879 problem_->setLSIndex( currRHSIdx );
880
881 // Get the current residual vector.
882 std::vector<MagnitudeType> norms;
883 R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
884 for (int i=0; i<have; ++i) { currIdx2[i] = i; }
885
886 // Set the new state and initialize the solver.
887 block_cg_iter->initializeCG(state_, R_0);
888 }
889
891 //
892 // check for maximum iterations
893 //
895 else if ( maxIterTest_->getStatus() == Passed ) {
896 // we don't have convergence
898 isConverged = false;
899 break; // break from while(1){block_cg_iter->iterate()}
900 }
901
903 //
904 // a debug status test (if any) stopped the iteration
905 //
907 else if (Teuchos::nonnull(debugStatusTest_) &&
908 debugStatusTest_->getStatus() == Passed) {
909 // we don't have convergence, but a debug test asked us to stop
911 isConverged = false;
912 break; // break from while(1){block_cg_iter->iterate()}
913 }
914
916 //
917 // we returned from iterate(), but none of our status tests Passed.
918 // something is wrong, and it is probably our fault.
919 //
921
922 else {
924 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
925 "Belos::PseudoBlockCGSolMgr::solve(): Invalid return from PseudoBlockCGIter::iterate().");
926 }
927 }
928 catch (const StatusTestNaNError& e) {
929 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
931 achievedTol_ = MT::one();
932 Teuchos::RCP<MV> X = problem_->getLHS();
933 MVT::MvInit( *X, SCT::zero() );
934 printer_->stream(Warnings) << "Belos::PseudoBlockCGSolMgr::solve(): Warning! NaN has been detected!"
935 << std::endl;
936 return retType;
937 }
938 catch (const std::exception &e) {
940 printer_->stream(Errors) << "Error! Caught std::exception in PseudoBlockCGIter::iterate() at iteration "
941 << block_cg_iter->getNumIters() << std::endl
942 << e.what() << std::endl;
943 throw;
944 }
945 }
946
947 // Inform the linear problem that we are finished with this block linear system.
948 problem_->setCurrLS();
949
950 // Update indices for the linear systems to be solved.
953
954 if ( numRHS2Solve > 0 ) {
955
957 currIdx.resize( numCurrRHS );
958 currIdx2.resize( numCurrRHS );
959 for (int i=0; i<numCurrRHS; ++i)
960 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
961
962 // Set the next indices.
963 problem_->setLSIndex( currIdx );
964 }
965 else {
966 currIdx.resize( numRHS2Solve );
967 }
968
969 }// while ( numRHS2Solve > 0 )
970
971 }
972
973 // print final summary
974 sTest_->print( printer_->stream(FinalSummary) );
975
976 // print timing information
977#ifdef BELOS_TEUCHOS_TIME_MONITOR
978 // Calling summarize() can be expensive, so don't call unless the
979 // user wants to print out timing details. summarize() will do all
980 // the work even if it's passed a "black hole" output stream.
981 if (verbosity_ & TimingDetails)
982 Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
983#endif
984
985 // get iteration information for this solve
986 numIters_ = maxIterTest_->getNumIters();
987
988 // Save the convergence test value ("achieved tolerance") for this
989 // solve.
990 const std::vector<MagnitudeType>* pTestValues = convTest_->getTestValue();
991 if (pTestValues != NULL && pTestValues->size () > 0) {
992 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
993 }
994
995 // Do condition estimate, if needed
996 if (genCondEst_ && !condEstPerf) {
998 Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
999 Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
1000 compute_condnum_tridiag_sym(diag,offdiag,eigenEstimates_,l_min,l_max,condEstimate_);
1001 condEstPerf = true;
1002 }
1003
1004 if (!isConverged) {
1005 return retType; // return from PseudoBlockCGSolMgr::solve()
1006 }
1007 return Converged; // return from PseudoBlockCGSolMgr::solve()
1008}
1009
1010// This method requires the solver manager to return a std::string that describes itself.
1011template<class ScalarType, class MV, class OP, class DM>
1013{
1014 std::ostringstream oss;
1015 oss << "Belos::PseudoBlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
1016 oss << "{";
1017 oss << "}";
1018 return oss.str();
1019}
1020
1021
1022template<class ScalarType, class MV, class OP, class DM>
1024compute_condnum_tridiag_sym (Teuchos::ArrayView<MagnitudeType> diag,
1025 Teuchos::ArrayView<MagnitudeType> offdiag,
1026 Teuchos::ArrayRCP<MagnitudeType>& lambdas,
1030{
1031 using STS = Teuchos::ScalarTraits<ScalarType>;
1032
1033 /* Copied from az_cg.c: compute_condnum_tridiag_sym */
1034 /* diag == ScalarType vector of size N, containing the diagonal
1035 elements of A
1036 offdiag == ScalarType vector of size N-1, containing the offdiagonal
1037 elements of A. Note that A is supposed to be symmatric
1038 */
1039 int info = 0;
1040 const int N = diag.size ();
1042 std::vector<MagnitudeType> mag_dummy(4*N);
1043 char char_N = 'N';
1044 Teuchos::LAPACK<int,ScalarType> lapack;
1045
1046 lambdas.resize(N, 0.0);
1047 lambda_min = STS::one ();
1048 lambda_max = STS::one ();
1049 if( N > 2 ) {
1050 lapack.PTEQR (char_N, N, diag.getRawPtr (), offdiag.getRawPtr (),
1051 &scalar_dummy, 1, &mag_dummy[0], &info);
1053 (info < 0, std::logic_error, "Belos::PseudoBlockCGSolMgr::"
1054 "compute_condnum_tridiag_sym: LAPACK's _PTEQR failed with info = "
1055 << info << " < 0. This suggests there might be a bug in the way Belos "
1056 "is calling LAPACK. Please report this to the Belos developers.");
1057 for (int k = 0; k < N; k++) {
1058 lambdas[k] = diag[N - 1 - k];
1059 }
1060 lambda_min = Teuchos::as<ScalarType> (diag[N-1]);
1061 lambda_max = Teuchos::as<ScalarType> (diag[0]);
1062 }
1063
1064 // info > 0 means that LAPACK's eigensolver didn't converge. This
1065 // is unlikely but may be possible. In that case, the best we can
1066 // do is use the eigenvalues that it computes, as long as lambda_max
1067 // >= lambda_min.
1068 if (STS::real (lambda_max) < STS::real (lambda_min)) {
1069 ConditionNumber = STS::one ();
1070 }
1071 else {
1072 // It's OK for the condition number to be Inf.
1074 }
1075
1076} /* compute_condnum_tridiag_sym */
1077
1078
1079
1080
1081
1082} // end Belos namespace
1083
1084#ifdef HAVE_BELOS_TPETRA
1086
1087#define BELOS_TPETRA_PSEUDOBLOCKCGSOLMGR_NOEXTERN_CALL(SC, LO, GO, NT) \
1088 BELOS_TPETRA_CALL(Belos::PseudoBlockCGSolMgr, SC, LO, GO, NT)
1089
1090#define BELOS_TPETRA_PSEUDOBLOCKCGSOLMGR_EXTERN_CALL(SC, LO, GO, NT) \
1091 BELOS_TPETRA_EXTERN_CALL(Belos::PseudoBlockCGSolMgr, SC, LO, GO, NT)
1092
1093TPETRA_INSTANTIATE_SLGN_NO_ORDINAL_SCALAR(BELOS_TPETRA_PSEUDOBLOCKCGSOLMGR_EXTERN_CALL)
1094#endif
1095
1096#endif /* BELOS_PSEUDO_BLOCK_CG_SOLMGR_HPP */
Belos concrete class for performing the conjugate-gradient (CG) iteration.
Pure virtual base class which augments the basic interface for a conjugate gradient linear solver ite...
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.
Class which manages the output and verbosity of the Belos solvers.
Belos concrete class for performing the pseudo-block CG iteration.
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.
Type traits class that says whether Teuchos::LAPACK has a valid implementation for the given ScalarTy...
Base class for Belos::SolverManager subclasses which normally can only compile with ScalarType types ...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
int getNumIters() const override
Get the iteration count for the most recent call to solve().
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const override
Return a reference to the linear problem being solved by this solver manager.
void reset(const ResetType type) override
Performs a reset of the solver manager specified by the ResetType. This informs the solver manager th...
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &debugStatusTest) override
Set a debug status test, OR-combined into the top-level status test.
Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP, DM > > getResidualStatusTest() const
Return the residual status test.
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem) override
Set the linear problem that needs to be solved.
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve.
Teuchos::RCP< SolverManager< ScalarType, MV, OP, DM > > clone() const override
clone for Inverted Injection (DII)
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
ScalarType getConditionEstimate() const
Gets the estimated condition number.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
The Belos::PseudoBlockCGSolMgr provides a powerful and fully-featured solver manager over the pseudo-...
virtual ~PseudoBlockCGSolMgr()=default
PseudoBlockCGSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP, DM > > getResidualStatusTest() const
PseudoBlockCGSolMgrLinearProblemFailure is thrown when the linear problem is not setup (i....
PseudoBlockCGSolMgrLinearProblemFailure(const std::string &what_arg)
ScaleType convertStringToScaleType(const std::string &scaleType)
Convert the given string to its ScaleType enum value.
@ StatusTestDetails
@ FinalSummary
@ TimingDetails
ReturnType
Whether the Belos solve converged for all linear systems.
@ NaNDetected
@ Unconverged
@ MaxItersReached
@ NonspecificException
@ InconsistentState
@ Undetermined
ScaleType
The type of scaling to use on the residual norm value.
ResetType
How to reset the solver.
Default parameters common to most Belos solvers.
static const double convTol
Default convergence tolerance.

Generated for Belos by doxygen 1.9.8