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
220
222
223
227 void reset( const ResetType type ) override { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
229
231
232
250 ReturnType solve() override;
251
253
256
258 std::string description() const override;
259
261 private:
262 // Compute the condition number estimate
263 void compute_condnum_tridiag_sym(Teuchos::ArrayView<MagnitudeType> diag,
264 Teuchos::ArrayView<MagnitudeType> offdiag,
265 Teuchos::ArrayRCP<MagnitudeType>& lambdas,
269
270 // Linear problem.
271 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
272
273 // Output manager.
274 Teuchos::RCP<OutputManager<ScalarType> > printer_;
275 Teuchos::RCP<std::ostream> outputStream_;
276
277 // Status test.
278 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > sTest_;
279 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP,DM> > maxIterTest_;
280 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > convTest_;
281 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP,DM> > outputTest_;
282
283 // Current parameter list.
284 Teuchos::RCP<Teuchos::ParameterList> params_;
285
291 mutable Teuchos::RCP<const Teuchos::ParameterList> validParams_;
292
293 // Default solver values.
294 static constexpr int maxIters_default_ = 1000;
295 static constexpr bool assertPositiveDefiniteness_default_ = true;
296 static constexpr bool showMaxResNormOnly_default_ = false;
297 static constexpr int verbosity_default_ = Belos::Errors;
298 static constexpr int outputStyle_default_ = Belos::General;
299 static constexpr int outputFreq_default_ = -1;
300 static constexpr int defQuorum_default_ = 1;
301 static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ = false;
302 static constexpr const char * resScale_default_ = "Norm of Initial Residual";
303 static constexpr const char * label_default_ = "Belos";
304 static constexpr bool genCondEst_default_ = false;
305
306 // Current solver values.
307 MagnitudeType convtol_,achievedTol_;
308 int maxIters_, numIters_;
309 int verbosity_, outputStyle_, outputFreq_, defQuorum_;
310 bool assertPositiveDefiniteness_, showMaxResNormOnly_;
311 bool foldConvergenceDetectionIntoAllreduce_;
312 std::string resScale_;
313 bool genCondEst_;
314 ScalarType condEstimate_;
315 Teuchos::ArrayRCP<MagnitudeType> eigenEstimates_;
316
317 Teuchos::RCP<CGIterationStateBase<ScalarType, MV, DM> > state_;
318
319 // Timers.
320 std::string label_;
321 Teuchos::RCP<Teuchos::Time> timerSolve_;
322
323 // Internal state variables.
324 bool isSet_;
325 };
326
327
328// Empty Constructor
329template<class ScalarType, class MV, class OP, class DM>
331 outputStream_(Teuchos::rcpFromRef(std::cout)),
332 convtol_(DefaultSolverParameters::convTol),
333 maxIters_(maxIters_default_),
334 numIters_(0),
335 verbosity_(verbosity_default_),
336 outputStyle_(outputStyle_default_),
337 outputFreq_(outputFreq_default_),
338 defQuorum_(defQuorum_default_),
339 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
340 showMaxResNormOnly_(showMaxResNormOnly_default_),
341 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
342 resScale_(resScale_default_),
343 genCondEst_(genCondEst_default_),
344 condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
345 label_(label_default_),
346 isSet_(false)
347{}
348
349// Basic Constructor
350template<class ScalarType, class MV, class OP, class DM>
353 const Teuchos::RCP<Teuchos::ParameterList> &pl ) :
354 problem_(problem),
355 outputStream_(Teuchos::rcpFromRef(std::cout)),
356 convtol_(DefaultSolverParameters::convTol),
357 maxIters_(maxIters_default_),
358 numIters_(0),
359 verbosity_(verbosity_default_),
360 outputStyle_(outputStyle_default_),
361 outputFreq_(outputFreq_default_),
362 defQuorum_(defQuorum_default_),
363 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
364 showMaxResNormOnly_(showMaxResNormOnly_default_),
365 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
366 resScale_(resScale_default_),
367 genCondEst_(genCondEst_default_),
368 condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
369 label_(label_default_),
370 isSet_(false)
371{
373 problem_.is_null (), std::invalid_argument,
374 "Belos::PseudoBlockCGSolMgr two-argument constructor: "
375 "'problem' is null. You must supply a non-null Belos::LinearProblem "
376 "instance when calling this constructor.");
377
378 if (! pl.is_null ()) {
379 // Set the parameters using the list that was passed in.
380 setParameters (pl);
381 }
382}
383
384template<class ScalarType, class MV, class OP, class DM>
386setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params)
387{
388 using Teuchos::ParameterList;
389 using Teuchos::parameterList;
390 using Teuchos::RCP;
391 using Teuchos::rcp;
392
393 RCP<const ParameterList> defaultParams = this->getValidParameters ();
394
395 // Create the internal parameter list if one doesn't already exist.
396 // Belos' solvers treat the input ParameterList to setParameters as
397 // a "delta" -- that is, a change from the current state -- so the
398 // default parameter list (if the input is null) should be empty.
399 // This explains also why Belos' solvers copy parameters one by one
400 // from the input list to the current list.
401 //
402 // Belos obfuscates the latter, because it takes the input parameter
403 // list by RCP, rather than by (nonconst) reference. The latter
404 // would make more sense, given that it doesn't actually keep the
405 // input parameter list.
406 //
407 // Note, however, that Belos still correctly triggers the "used"
408 // field of each parameter in the input list. While isParameter()
409 // doesn't (apparently) trigger the "used" flag, get() certainly
410 // does.
411
412 if (params_.is_null ()) {
413 // Create an empty list with the same name as the default list.
414 params_ = parameterList (defaultParams->name ());
415 } else {
416 params->validateParameters (*defaultParams);
417 }
418
419 // Check for maximum number of iterations
420 if (params->isParameter ("Maximum Iterations")) {
421 maxIters_ = params->get ("Maximum Iterations", maxIters_default_);
422
423 // Update parameter in our list and in status test.
424 params_->set ("Maximum Iterations", maxIters_);
425 if (! maxIterTest_.is_null ()) {
426 maxIterTest_->setMaxIters (maxIters_);
427 }
428 }
429
430 // Check if positive definiteness assertions are to be performed
431 if (params->isParameter ("Assert Positive Definiteness")) {
432 assertPositiveDefiniteness_ =
433 params->get ("Assert Positive Definiteness",
434 assertPositiveDefiniteness_default_);
435
436 // Update parameter in our list.
437 params_->set ("Assert Positive Definiteness", assertPositiveDefiniteness_);
438 }
439
440 if (params->isParameter("Fold Convergence Detection Into Allreduce")) {
441 foldConvergenceDetectionIntoAllreduce_ = params->get("Fold Convergence Detection Into Allreduce",
442 foldConvergenceDetectionIntoAllreduce_default_);
443 }
444
445 // Check to see if the timer label changed.
446 if (params->isParameter ("Timer Label")) {
447 const std::string tempLabel = params->get ("Timer Label", label_default_);
448
449 // Update parameter in our list and solver timer
450 if (tempLabel != label_) {
451 label_ = tempLabel;
452 params_->set ("Timer Label", label_);
453 const std::string solveLabel =
454 label_ + ": PseudoBlockCGSolMgr total solve time";
455#ifdef BELOS_TEUCHOS_TIME_MONITOR
456 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
457#endif
458 }
459 }
460
461 // Check for a change in verbosity level
462 if (params->isParameter ("Verbosity")) {
463 if (Teuchos::isParameterType<int> (*params, "Verbosity")) {
464 verbosity_ = params->get ("Verbosity", verbosity_default_);
465 } else {
466 verbosity_ = (int) Teuchos::getParameter<Belos::MsgType> (*params, "Verbosity");
467 }
468
469 // Update parameter in our list.
470 params_->set ("Verbosity", verbosity_);
471 if (! printer_.is_null ()) {
472 printer_->setVerbosity (verbosity_);
473 }
474 }
475
476 // Check for a change in output style
477 if (params->isParameter ("Output Style")) {
478 if (Teuchos::isParameterType<int> (*params, "Output Style")) {
479 outputStyle_ = params->get ("Output Style", outputStyle_default_);
480 } else {
481 // FIXME (mfh 29 Jul 2015) What if the type is wrong?
482 outputStyle_ = (int) Teuchos::getParameter<Belos::OutputType> (*params, "Output Style");
483 }
484
485 // Reconstruct the convergence test if the explicit residual test
486 // is not being used.
487 params_->set ("Output Style", outputStyle_);
488 outputTest_ = Teuchos::null;
489 }
490
491 // output stream
492 if (params->isParameter ("Output Stream")) {
493 outputStream_ = params->get<RCP<std::ostream> > ("Output Stream");
494
495 // Update parameter in our list.
496 params_->set ("Output Stream", outputStream_);
497 if (! printer_.is_null ()) {
498 printer_->setOStream (outputStream_);
499 }
500 }
501
502 // frequency level
503 if (verbosity_ & Belos::StatusTestDetails) {
504 if (params->isParameter ("Output Frequency")) {
505 outputFreq_ = params->get ("Output Frequency", outputFreq_default_);
506 }
507
508 // Update parameter in out list and output status test.
509 params_->set ("Output Frequency", outputFreq_);
510 if (! outputTest_.is_null ()) {
511 outputTest_->setOutputFrequency (outputFreq_);
512 }
513 }
514
515 // Condition estimate
516 if (params->isParameter ("Estimate Condition Number")) {
517 genCondEst_ = params->get ("Estimate Condition Number", genCondEst_default_);
518 }
519
520 // Create output manager if we need to.
521 if (printer_.is_null ()) {
522 printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_));
523 }
524
525 // Convergence
526 using StatusTestCombo_t = Belos::StatusTestCombo<ScalarType, MV, OP, DM>;
527 using StatusTestResNorm_t = Belos::StatusTestGenResNorm<ScalarType, MV, OP, DM>;
528
529 // Check for convergence tolerance
530 if (params->isParameter ("Convergence Tolerance")) {
531 if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
532 convtol_ = params->get ("Convergence Tolerance",
533 static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
534 }
535 else {
536 convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
537 }
538
539 // Update parameter in our list and residual tests.
540 params_->set ("Convergence Tolerance", convtol_);
541 if (! convTest_.is_null ()) {
542 convTest_->setTolerance (convtol_);
543 }
544 }
545
546 if (params->isParameter ("Show Maximum Residual Norm Only")) {
547 showMaxResNormOnly_ = params->get<bool> ("Show Maximum Residual Norm Only");
548
549 // Update parameter in our list and residual tests
550 params_->set ("Show Maximum Residual Norm Only", showMaxResNormOnly_);
551 if (! convTest_.is_null ()) {
552 convTest_->setShowMaxResNormOnly (showMaxResNormOnly_);
553 }
554 }
555
556 // Check for a change in scaling, if so we need to build new residual tests.
557 bool newResTest = false;
558 {
559 // "Residual Scaling" is the old parameter name; "Implicit
560 // Residual Scaling" is the new name. We support both options for
561 // backwards compatibility.
562 std::string tempResScale = resScale_;
563 bool implicitResidualScalingName = false;
564 if (params->isParameter ("Residual Scaling")) {
565 tempResScale = params->get<std::string> ("Residual Scaling");
566 }
567 else if (params->isParameter ("Implicit Residual Scaling")) {
568 tempResScale = params->get<std::string> ("Implicit Residual Scaling");
570 }
571
572 // Only update the scaling if it's different.
573 if (resScale_ != tempResScale) {
576 resScale_ = tempResScale;
577
578 // Update parameter in our list and residual tests, using the
579 // given parameter name.
581 params_->set ("Implicit Residual Scaling", resScale_);
582 }
583 else {
584 params_->set ("Residual Scaling", resScale_);
585 }
586
587 if (! convTest_.is_null ()) {
588 try {
589 convTest_->defineScaleForm (resScaleType, Belos::TwoNorm);
590 }
591 catch (std::exception& e) {
592 // Make sure the convergence test gets constructed again.
593 newResTest = true;
594 }
595 }
596 }
597 }
598
599 // Get the deflation quorum, or number of converged systems before deflation is allowed
600 if (params->isParameter ("Deflation Quorum")) {
601 defQuorum_ = params->get ("Deflation Quorum", defQuorum_);
602 params_->set ("Deflation Quorum", defQuorum_);
603 if (! convTest_.is_null ()) {
604 convTest_->setQuorum( defQuorum_ );
605 }
606 }
607
608 // Create status tests if we need to.
609
610 // Basic test checks maximum iterations and native residual.
611 if (maxIterTest_.is_null ()) {
612 maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP,DM> (maxIters_));
613 }
614
615 // Implicit residual test, using the native residual to determine if convergence was achieved.
616 if (convTest_.is_null () || newResTest) {
617 convTest_ = rcp (new StatusTestResNorm_t (convtol_, defQuorum_, showMaxResNormOnly_));
618 convTest_->defineScaleForm (convertStringToScaleType (resScale_), Belos::TwoNorm);
619 }
620
621 if (sTest_.is_null () || newResTest) {
622 sTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::OR, maxIterTest_, convTest_));
623 }
624
625 if (outputTest_.is_null () || newResTest) {
626 // Create the status test output class.
627 // This class manages and formats the output from the status test.
629 outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_,
631
632 // Set the solver string for the output test
633 const std::string solverDesc = " Pseudo Block CG ";
634 outputTest_->setSolverDesc (solverDesc);
635 }
636
637 // Create the timer if we need to.
638 if (timerSolve_.is_null ()) {
639 const std::string solveLabel =
640 label_ + ": PseudoBlockCGSolMgr total solve time";
641#ifdef BELOS_TEUCHOS_TIME_MONITOR
642 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
643#endif
644 }
645
646 // Inform the solver manager that the current parameters were set.
647 isSet_ = true;
648}
649
650
651template<class ScalarType, class MV, class OP, class DM>
652Teuchos::RCP<const Teuchos::ParameterList>
654{
655 using Teuchos::ParameterList;
656 using Teuchos::parameterList;
657 using Teuchos::RCP;
658
659 if (validParams_.is_null()) {
660 // Set all the valid parameters and their default values.
662 pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
663 "The relative residual tolerance that needs to be achieved by the\n"
664 "iterative solver in order for the linear system to be declared converged.");
665 pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
666 "The maximum number of block iterations allowed for each\n"
667 "set of RHS solved.");
668 pl->set("Assert Positive Definiteness", static_cast<bool>(assertPositiveDefiniteness_default_),
669 "Whether or not to assert that the linear operator\n"
670 "and the preconditioner are indeed positive definite.");
671 pl->set("Verbosity", static_cast<int>(verbosity_default_),
672 "What type(s) of solver information should be outputted\n"
673 "to the output stream.");
674 pl->set("Output Style", static_cast<int>(outputStyle_default_),
675 "What style is used for the solver information outputted\n"
676 "to the output stream.");
677 pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
678 "How often convergence information should be outputted\n"
679 "to the output stream.");
680 pl->set("Deflation Quorum", static_cast<int>(defQuorum_default_),
681 "The number of linear systems that need to converge before\n"
682 "they are deflated. This number should be <= block size.");
683 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
684 "A reference-counted pointer to the output stream where all\n"
685 "solver output is sent.");
686 pl->set("Show Maximum Residual Norm Only", static_cast<bool>(showMaxResNormOnly_default_),
687 "When convergence information is printed, only show the maximum\n"
688 "relative residual norm when the block size is greater than one.");
689 pl->set("Implicit Residual Scaling", resScale_default_,
690 "The type of scaling used in the residual convergence test.");
691 pl->set("Estimate Condition Number", static_cast<bool>(genCondEst_default_),
692 "Whether or not to estimate the condition number of the preconditioned system.");
693 // We leave the old name as a valid parameter for backwards
694 // compatibility (so that validateParametersAndSetDefaults()
695 // doesn't raise an exception if it encounters "Residual
696 // Scaling"). The new name was added for compatibility with other
697 // solvers, none of which use "Residual Scaling".
698 pl->set("Residual Scaling", resScale_default_,
699 "The type of scaling used in the residual convergence test. This "
700 "name is deprecated; the new name is \"Implicit Residual Scaling\".");
701 pl->set("Timer Label", static_cast<const char *>(label_default_),
702 "The string to use as a prefix for the timer labels.");
703 pl->set("Fold Convergence Detection Into Allreduce",static_cast<bool>(foldConvergenceDetectionIntoAllreduce_default_),
704 "Merge the allreduce for convergence detection with the one for CG.\n"
705 "This saves one all-reduce, but incurs more computation.");
706 validParams_ = pl;
707 }
708 return validParams_;
709}
710
711
712// solve()
713template<class ScalarType, class MV, class OP, class DM>
715{
716 const char prefix[] = "Belos::PseudoBlockCGSolMgr::solve: ";
717
719
720 // Set the current parameters if they were not set before.
721 // NOTE: This may occur if the user generated the solver manager with the default constructor and
722 // then didn't set any parameters using setParameters().
723 if (!isSet_) { setParameters( params_ ); }
724
726 (! problem_->isProblemSet (), PseudoBlockCGSolMgrLinearProblemFailure,
727 prefix << "The linear problem to solve is not ready. You must call "
728 "setProblem() on the Belos::LinearProblem instance before telling the "
729 "Belos solver to solve it.");
730
731 // Create indices for the linear systems to be solved.
732 int startPtr = 0;
733 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
735
736 std::vector<int> currIdx( numRHS2Solve ), currIdx2( numRHS2Solve );
737 for (int i=0; i<numRHS2Solve; ++i) {
738 currIdx[i] = startPtr+i;
739 currIdx2[i]=i;
740 }
741
742 // Inform the linear problem of the current linear system to solve.
743 problem_->setLSIndex( currIdx );
744
746 // Parameter list (iteration)
747 Teuchos::ParameterList plist;
748
749 plist.set("Assert Positive Definiteness",assertPositiveDefiniteness_);
750 if(genCondEst_) plist.set("Max Size For Condest",maxIters_);
751
752 // Reset the status test.
753 outputTest_->reset();
754
755 // Assume convergence is achieved, then let any failed convergence set this to false.
756 bool isConverged = true;
757
759 // Pseudo-Block CG solver
760 Teuchos::RCP<CGIteration<ScalarType,MV,OP,DM> > block_cg_iter;
761 if (numRHS2Solve == 1) {
762 plist.set("Fold Convergence Detection Into Allreduce",
763 foldConvergenceDetectionIntoAllreduce_);
765 Teuchos::rcp (new CGIter<ScalarType,MV,OP,DM> (problem_, printer_, outputTest_, convTest_, plist));
766 if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType, MV, DM> >(state_).is_null())
767 state_ = Teuchos::rcp(new CGIterationState<ScalarType, MV, DM>());
768 } else {
770 Teuchos::rcp (new PseudoBlockCGIter<ScalarType,MV,OP,DM> (problem_, printer_, outputTest_, plist));
771 if (state_.is_null() || Teuchos::rcp_dynamic_cast<PseudoBlockCGIterationState<ScalarType, MV, DM> >(state_).is_null())
772 state_ = Teuchos::rcp(new PseudoBlockCGIterationState<ScalarType, MV, DM>());
773 }
774
775 // Setup condition estimate
776 block_cg_iter->setDoCondEst(genCondEst_);
777 bool condEstPerf = false;
778
779 // Enter solve() iterations
780 {
781#ifdef BELOS_TEUCHOS_TIME_MONITOR
782 Teuchos::TimeMonitor slvtimer(*timerSolve_);
783#endif
784
785 while ( numRHS2Solve > 0 ) {
786
787 // Reset the active / converged vectors from this block
788 std::vector<int> convRHSIdx;
789 std::vector<int> currRHSIdx( currIdx );
790 currRHSIdx.resize(numCurrRHS);
791
792 // Reset the number of iterations.
793 block_cg_iter->resetNumIters();
794
795 // Reset the number of calls that the status test output knows about.
796 outputTest_->resetNumCalls();
797
798 // Get the current residual for this block of linear systems.
799 Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
800
801 // Get a new state struct and initialize the solver.
802 block_cg_iter->initializeCG(state_, R_0);
803
804 while(true) {
805
806 // tell block_gmres_iter to iterate
807 try {
808
809 block_cg_iter->iterate();
810
812 //
813 // check convergence first
814 //
816 if ( convTest_->getStatus() == Passed ) {
817
818 // Figure out which linear systems converged.
819 std::vector<int> convIdx = Teuchos::rcp_dynamic_cast<StatusTestGenResNorm<ScalarType,MV,OP,DM> >(convTest_)->convIndices();
820
821 // If the number of converged linear systems is equal to the
822 // number of current linear systems, then we are done with this block.
823 if (convIdx.size() == currRHSIdx.size())
824 break; // break from while(1){block_cg_iter->iterate()}
825
826 // Inform the linear problem that we are finished with this current linear system.
827 problem_->setCurrLS();
828
829 // Reset currRHSIdx to have the right-hand sides that are left to converge for this block.
830 int have = 0;
831 for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
832 bool found = false;
833 for (unsigned int j=0; j<convIdx.size(); ++j) {
834 if (currRHSIdx[i] == convIdx[j]) {
835 found = true;
836 break;
837 }
838 }
839 if (!found) {
842 }
843 }
844 currRHSIdx.resize(have);
845 currIdx2.resize(have);
846
847 // Compute condition estimate if the very first linear system in the block has converged.
848 if (currRHSIdx[0] != 0 && genCondEst_ && !condEstPerf)
849 {
850 // Compute the estimate.
852 Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
853 Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
854 compute_condnum_tridiag_sym(diag,offdiag,eigenEstimates_,l_min,l_max,condEstimate_);
855
856 // Make sure not to do more condition estimate computations for this solve.
857 block_cg_iter->setDoCondEst(false);
858 condEstPerf = true;
859 }
860
861 // Set the remaining indices after deflation.
862 problem_->setLSIndex( currRHSIdx );
863
864 // Get the current residual vector.
865 std::vector<MagnitudeType> norms;
866 R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
867 for (int i=0; i<have; ++i) { currIdx2[i] = i; }
868
869 // Set the new state and initialize the solver.
870 block_cg_iter->initializeCG(state_, R_0);
871 }
872
874 //
875 // check for maximum iterations
876 //
878 else if ( maxIterTest_->getStatus() == Passed ) {
879 // we don't have convergence
881 isConverged = false;
882 break; // break from while(1){block_cg_iter->iterate()}
883 }
884
886 //
887 // we returned from iterate(), but none of our status tests Passed.
888 // something is wrong, and it is probably our fault.
889 //
891
892 else {
894 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
895 "Belos::PseudoBlockCGSolMgr::solve(): Invalid return from PseudoBlockCGIter::iterate().");
896 }
897 }
898 catch (const StatusTestNaNError& e) {
899 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
901 achievedTol_ = MT::one();
902 Teuchos::RCP<MV> X = problem_->getLHS();
903 MVT::MvInit( *X, SCT::zero() );
904 printer_->stream(Warnings) << "Belos::PseudoBlockCGSolMgr::solve(): Warning! NaN has been detected!"
905 << std::endl;
906 return retType;
907 }
908 catch (const std::exception &e) {
910 printer_->stream(Errors) << "Error! Caught std::exception in PseudoBlockCGIter::iterate() at iteration "
911 << block_cg_iter->getNumIters() << std::endl
912 << e.what() << std::endl;
913 throw;
914 }
915 }
916
917 // Inform the linear problem that we are finished with this block linear system.
918 problem_->setCurrLS();
919
920 // Update indices for the linear systems to be solved.
923
924 if ( numRHS2Solve > 0 ) {
925
927 currIdx.resize( numCurrRHS );
928 currIdx2.resize( numCurrRHS );
929 for (int i=0; i<numCurrRHS; ++i)
930 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
931
932 // Set the next indices.
933 problem_->setLSIndex( currIdx );
934 }
935 else {
936 currIdx.resize( numRHS2Solve );
937 }
938
939 }// while ( numRHS2Solve > 0 )
940
941 }
942
943 // print final summary
944 sTest_->print( printer_->stream(FinalSummary) );
945
946 // print timing information
947#ifdef BELOS_TEUCHOS_TIME_MONITOR
948 // Calling summarize() can be expensive, so don't call unless the
949 // user wants to print out timing details. summarize() will do all
950 // the work even if it's passed a "black hole" output stream.
951 if (verbosity_ & TimingDetails)
952 Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
953#endif
954
955 // get iteration information for this solve
956 numIters_ = maxIterTest_->getNumIters();
957
958 // Save the convergence test value ("achieved tolerance") for this
959 // solve.
960 const std::vector<MagnitudeType>* pTestValues = convTest_->getTestValue();
961 if (pTestValues != NULL && pTestValues->size () > 0) {
962 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
963 }
964
965 // Do condition estimate, if needed
966 if (genCondEst_ && !condEstPerf) {
968 Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
969 Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
970 compute_condnum_tridiag_sym(diag,offdiag,eigenEstimates_,l_min,l_max,condEstimate_);
971 condEstPerf = true;
972 }
973
974 if (!isConverged) {
975 return retType; // return from PseudoBlockCGSolMgr::solve()
976 }
977 return Converged; // return from PseudoBlockCGSolMgr::solve()
978}
979
980// This method requires the solver manager to return a std::string that describes itself.
981template<class ScalarType, class MV, class OP, class DM>
983{
984 std::ostringstream oss;
985 oss << "Belos::PseudoBlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
986 oss << "{";
987 oss << "}";
988 return oss.str();
989}
990
991
992template<class ScalarType, class MV, class OP, class DM>
994compute_condnum_tridiag_sym (Teuchos::ArrayView<MagnitudeType> diag,
995 Teuchos::ArrayView<MagnitudeType> offdiag,
996 Teuchos::ArrayRCP<MagnitudeType>& lambdas,
1000{
1001 using STS = Teuchos::ScalarTraits<ScalarType>;
1002
1003 /* Copied from az_cg.c: compute_condnum_tridiag_sym */
1004 /* diag == ScalarType vector of size N, containing the diagonal
1005 elements of A
1006 offdiag == ScalarType vector of size N-1, containing the offdiagonal
1007 elements of A. Note that A is supposed to be symmatric
1008 */
1009 int info = 0;
1010 const int N = diag.size ();
1012 std::vector<MagnitudeType> mag_dummy(4*N);
1013 char char_N = 'N';
1014 Teuchos::LAPACK<int,ScalarType> lapack;
1015
1016 lambdas.resize(N, 0.0);
1017 lambda_min = STS::one ();
1018 lambda_max = STS::one ();
1019 if( N > 2 ) {
1020 lapack.PTEQR (char_N, N, diag.getRawPtr (), offdiag.getRawPtr (),
1021 &scalar_dummy, 1, &mag_dummy[0], &info);
1023 (info < 0, std::logic_error, "Belos::PseudoBlockCGSolMgr::"
1024 "compute_condnum_tridiag_sym: LAPACK's _PTEQR failed with info = "
1025 << info << " < 0. This suggests there might be a bug in the way Belos "
1026 "is calling LAPACK. Please report this to the Belos developers.");
1027 for (int k = 0; k < N; k++) {
1028 lambdas[k] = diag[N - 1 - k];
1029 }
1030 lambda_min = Teuchos::as<ScalarType> (diag[N-1]);
1031 lambda_max = Teuchos::as<ScalarType> (diag[0]);
1032 }
1033
1034 // info > 0 means that LAPACK's eigensolver didn't converge. This
1035 // is unlikely but may be possible. In that case, the best we can
1036 // do is use the eigenvalues that it computes, as long as lambda_max
1037 // >= lambda_min.
1038 if (STS::real (lambda_max) < STS::real (lambda_min)) {
1039 ConditionNumber = STS::one ();
1040 }
1041 else {
1042 // It's OK for the condition number to be Inf.
1044 }
1045
1046} /* compute_condnum_tridiag_sym */
1047
1048
1049
1050
1051
1052} // end Belos namespace
1053
1054#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...
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
@ 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