Belos Version of the Day
Loading...
Searching...
No Matches
BelosBlockCGSolMgr.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_BLOCK_CG_SOLMGR_HPP
11#define BELOS_BLOCK_CG_SOLMGR_HPP
12
17#include "BelosConfigDefs.hpp"
18#include "BelosTypes.hpp"
19
22
23#include "BelosCGIter.hpp"
25#include "BelosBlockCGIter.hpp"
32#ifdef BELOS_TEUCHOS_TIME_MONITOR
33# include "Teuchos_TimeMonitor.hpp"
34#endif
35#include <algorithm>
36
56namespace Belos {
57
59
60
70
71 template<class ScalarType, class MV, class OP, class DM = DefaultDenseMatrix<int, ScalarType>,
72 const bool lapackSupportsScalarType =
73 Belos::Details::LapackSupportsScalar<ScalarType>::value>
75 public Details::SolverManagerRequiresLapack<ScalarType,MV,OP,DM>
76 {
77 static const bool requiresLapack =
80
81 public:
83 base_type ()
84 {}
86 const Teuchos::RCP<Teuchos::ParameterList>& pl) :
87 base_type ()
88 {}
89 virtual ~BlockCGSolMgr () = default;
90 };
91
92
93 // Partial specialization for ScalarType types for which
94 // Teuchos::LAPACK has a valid implementation. This contains the
95 // actual working implementation of BlockCGSolMgr.
96 template<class ScalarType, class MV, class OP, class DM>
97 class BlockCGSolMgr<ScalarType, MV, OP, DM, true> :
98 public Details::SolverManagerRequiresLapack<ScalarType, MV, OP, DM, true>
99 {
100 private:
103 using SCT = Teuchos::ScalarTraits<ScalarType>;
104 using MagnitudeType = typename Teuchos::ScalarTraits<ScalarType>::magnitudeType;
105 using MT = Teuchos::ScalarTraits<MagnitudeType>;
106
107 public:
108
110
111
118
156 const Teuchos::RCP<Teuchos::ParameterList> &pl );
157
159 virtual ~BlockCGSolMgr() = default;
160
162 Teuchos::RCP<SolverManager<ScalarType, MV, OP, DM> > clone () const override {
163 return Teuchos::rcp(new BlockCGSolMgr<ScalarType,MV,OP,DM>);
164 }
166
168
169
171 return *problem_;
172 }
173
176 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override;
177
180 Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const override { return params_; }
181
187 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
188 return Teuchos::tuple(timerSolve_);
189 }
190
196 MagnitudeType achievedTol() const override {
197 return achievedTol_;
198 }
199
201 int getNumIters() const override {
202 return numIters_;
203 }
204
207 bool isLOADetected() const override { return false; }
208
210
212
213
215 void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > &problem ) override { problem_ = problem; }
216
218 void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
219
222 debugStatusTest_ = debugStatusTest;
223 // Force the cached status-test tree (and its output wrapper) to be rebuilt
224 // on the next solve so the debug test is wired into sTest_. This manager
225 // caches sTest_/outputTest_ behind null checks, so clear them and re-run
226 // setParameters.
227 sTest_ = Teuchos::null;
228 outputTest_ = Teuchos::null;
229 isSet_ = false;
230 }
231
233
235
236
240 void reset( const ResetType type ) override { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
242
244
245
263 ReturnType solve() override;
264
266
269
271 std::string description() const override;
272
274
275 private:
276
278 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
279
281 Teuchos::RCP<OutputManager<ScalarType> > printer_;
283 Teuchos::RCP<std::ostream> outputStream_;
284
289 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > sTest_;
290
292 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP,DM> > maxIterTest_;
293
295 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > convTest_;
296
298 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP,DM> > outputTest_;
299 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > debugStatusTest_;
300
302 Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP,DM> > ortho_;
303
305 Teuchos::RCP<Teuchos::ParameterList> params_;
306
307 //
308 // Default solver parameters.
309 //
310 static constexpr int maxIters_default_ = 1000;
311 static constexpr bool adaptiveBlockSize_default_ = true;
312 static constexpr bool showMaxResNormOnly_default_ = false;
313 static constexpr bool useSingleReduction_default_ = false;
314 static constexpr int blockSize_default_ = 1;
315 static constexpr int verbosity_default_ = Belos::Errors;
316 static constexpr int outputStyle_default_ = Belos::General;
317 static constexpr int outputFreq_default_ = -1;
318 static constexpr const char * resNorm_default_ = "TwoNorm";
319 static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ = false;
320 static constexpr const char * resScale_default_ = "Norm of Initial Residual";
321 static constexpr const char * label_default_ = "Belos";
322 static constexpr const char * orthoType_default_ = "ICGS";
323 static constexpr bool assertPositiveDefiniteness_default_ = true;
324
325 //
326 // Current solver parameters and other values.
327 //
328
330 MagnitudeType convtol_;
331
333 MagnitudeType orthoKappa_;
334
340 MagnitudeType achievedTol_;
341
343 int maxIters_;
344
346 int numIters_;
347
349 int blockSize_, verbosity_, outputStyle_, outputFreq_;
350 bool adaptiveBlockSize_, showMaxResNormOnly_, useSingleReduction_;
351 std::string orthoType_, resScale_;
352 bool assertPositiveDefiniteness_;
353 bool foldConvergenceDetectionIntoAllreduce_;
354
355 Teuchos::RCP<CGIterationStateBase<ScalarType, MV, DM> > state_;
356
358 std::string label_;
359
361 Teuchos::RCP<Teuchos::Time> timerSolve_;
362
364 bool isSet_;
365 };
366
367
368// Empty Constructor
369template<class ScalarType, class MV, class OP, class DM>
371 outputStream_(Teuchos::rcpFromRef(std::cout)),
372 convtol_(DefaultSolverParameters::convTol),
373 orthoKappa_(DefaultSolverParameters::orthoKappa),
374 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
375 maxIters_(maxIters_default_),
376 numIters_(0),
377 blockSize_(blockSize_default_),
378 verbosity_(verbosity_default_),
379 outputStyle_(outputStyle_default_),
380 outputFreq_(outputFreq_default_),
381 adaptiveBlockSize_(adaptiveBlockSize_default_),
382 showMaxResNormOnly_(showMaxResNormOnly_default_),
383 useSingleReduction_(useSingleReduction_default_),
384 orthoType_(orthoType_default_),
385 resScale_(resScale_default_),
386 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
387 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
388 label_(label_default_),
389 isSet_(false)
390{}
391
392
393// Basic Constructor
394template<class ScalarType, class MV, class OP, class DM>
397 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
398 problem_(problem),
399 outputStream_(Teuchos::rcpFromRef(std::cout)),
400 convtol_(DefaultSolverParameters::convTol),
401 orthoKappa_(DefaultSolverParameters::orthoKappa),
402 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
403 maxIters_(maxIters_default_),
404 numIters_(0),
405 blockSize_(blockSize_default_),
406 verbosity_(verbosity_default_),
407 outputStyle_(outputStyle_default_),
408 outputFreq_(outputFreq_default_),
409 adaptiveBlockSize_(adaptiveBlockSize_default_),
410 showMaxResNormOnly_(showMaxResNormOnly_default_),
411 useSingleReduction_(useSingleReduction_default_),
412 orthoType_(orthoType_default_),
413 resScale_(resScale_default_),
414 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
415 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
416 label_(label_default_),
417 isSet_(false)
418{
419 TEUCHOS_TEST_FOR_EXCEPTION(problem_.is_null(), std::invalid_argument,
420 "BlockCGSolMgr's constructor requires a nonnull LinearProblem instance.");
421
422 // If the user passed in a nonnull parameter list, set parameters.
423 // Otherwise, the next solve() call will use default parameters,
424 // unless the user calls setParameters() first.
425 if (! pl.is_null()) {
426 setParameters (pl);
427 }
428}
429
430template<class ScalarType, class MV, class OP, class DM>
431void
433setParameters (const Teuchos::RCP<Teuchos::ParameterList> &params)
434{
435 // Create the internal parameter list if one doesn't already exist.
436 if (params_ == Teuchos::null) {
437 params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
438 }
439 else {
440 params->validateParameters(*getValidParameters());
441 }
442
443 // Check for maximum number of iterations
444 if (params->isParameter("Maximum Iterations")) {
445 maxIters_ = params->get("Maximum Iterations",maxIters_default_);
446
447 // Update parameter in our list and in status test.
448 params_->set("Maximum Iterations", maxIters_);
449 if (maxIterTest_!=Teuchos::null)
450 maxIterTest_->setMaxIters( maxIters_ );
451 }
452
453 // Check for blocksize
454 if (params->isParameter("Block Size")) {
455 blockSize_ = params->get("Block Size",blockSize_default_);
456 TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
457 "Belos::BlockCGSolMgr: \"Block Size\" must be strictly positive.");
458
459 // Update parameter in our list.
460 params_->set("Block Size", blockSize_);
461 }
462
463 // Check if the blocksize should be adaptive
464 if (params->isParameter("Adaptive Block Size")) {
465 adaptiveBlockSize_ = params->get("Adaptive Block Size",adaptiveBlockSize_default_);
466
467 // Update parameter in our list.
468 params_->set("Adaptive Block Size", adaptiveBlockSize_);
469 }
470
471 // Check if the user is requesting the single-reduction version of CG (only for blocksize == 1)
472 if (params->isParameter("Use Single Reduction")) {
473 useSingleReduction_ = params->get("Use Single Reduction", useSingleReduction_default_);
474 }
475
476 if (params->isParameter("Fold Convergence Detection Into Allreduce")) {
477 foldConvergenceDetectionIntoAllreduce_ = params->get("Fold Convergence Detection Into Allreduce",
478 foldConvergenceDetectionIntoAllreduce_default_);
479 }
480
481 // Check to see if the timer label changed.
482 if (params->isParameter("Timer Label")) {
483 std::string tempLabel = params->get("Timer Label", label_default_);
484
485 // Update parameter in our list and solver timer
486 if (tempLabel != label_) {
487 label_ = tempLabel;
488 params_->set("Timer Label", label_);
489 std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
490#ifdef BELOS_TEUCHOS_TIME_MONITOR
491 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
492#endif
493 if (ortho_ != Teuchos::null) {
494 ortho_->setLabel( label_ );
495 }
496 }
497 }
498
499 // Check for a change in verbosity level
500 if (params->isParameter("Verbosity")) {
501 if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
502 verbosity_ = params->get("Verbosity", verbosity_default_);
503 } else {
504 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
505 }
506
507 // Update parameter in our list.
508 params_->set("Verbosity", verbosity_);
509 if (printer_ != Teuchos::null)
510 printer_->setVerbosity(verbosity_);
511 }
512
513 // Check for a change in output style
514 if (params->isParameter("Output Style")) {
515 if (Teuchos::isParameterType<int>(*params,"Output Style")) {
516 outputStyle_ = params->get("Output Style", outputStyle_default_);
517 } else {
518 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
519 }
520
521 // Update parameter in our list.
522 params_->set("Output Style", outputStyle_);
523 outputTest_ = Teuchos::null;
524 }
525
526 // output stream
527 if (params->isParameter("Output Stream")) {
528 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
529
530 // Update parameter in our list.
531 params_->set("Output Stream", outputStream_);
532 if (printer_ != Teuchos::null)
533 printer_->setOStream( outputStream_ );
534 }
535
536 // frequency level
537 if (verbosity_ & Belos::StatusTestDetails) {
538 if (params->isParameter("Output Frequency")) {
539 outputFreq_ = params->get("Output Frequency", outputFreq_default_);
540 }
541
542 // Update parameter in out list and output status test.
543 params_->set("Output Frequency", outputFreq_);
544 if (outputTest_ != Teuchos::null)
545 outputTest_->setOutputFrequency( outputFreq_ );
546 }
547
548 // Create output manager if we need to.
549 if (printer_ == Teuchos::null) {
550 printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
551 }
552
553 // Check if the orthogonalization changed.
554 bool changedOrthoType = false;
555 if (params->isParameter("Orthogonalization")) {
556 std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
557 if (tempOrthoType != orthoType_) {
558 orthoType_ = tempOrthoType;
559 changedOrthoType = true;
560 }
561 }
562 params_->set("Orthogonalization", orthoType_);
563
564 // Check which orthogonalization constant to use.
565 if (params->isParameter("Orthogonalization Constant")) {
566 if (params->isType<MagnitudeType> ("Orthogonalization Constant")) {
567 orthoKappa_ = params->get ("Orthogonalization Constant",
568 static_cast<MagnitudeType> (DefaultSolverParameters::orthoKappa));
569 }
570 else {
571 orthoKappa_ = params->get ("Orthogonalization Constant",
573 }
574
575 // Update parameter in our list.
576 params_->set("Orthogonalization Constant",orthoKappa_);
577 if (orthoType_=="DGKS") {
578 if (orthoKappa_ > 0 && ortho_ != Teuchos::null && !changedOrthoType) {
579 Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP,DM> >(ortho_)->setDepTol( orthoKappa_ );
580 }
581 }
582 }
583
584 // Create orthogonalization manager if we need to.
585 if (ortho_ == Teuchos::null || changedOrthoType) {
587 Teuchos::RCP<Teuchos::ParameterList> paramsOrtho;
588 if (orthoType_=="DGKS" && orthoKappa_ > 0) {
589 paramsOrtho = Teuchos::rcp(new Teuchos::ParameterList());
590 paramsOrtho->set ("depTol", orthoKappa_ );
591 }
592
593 ortho_ = factory.makeMatOrthoManager (orthoType_, Teuchos::null, printer_, label_, paramsOrtho);
594 }
595
596 // Convergence
597 using StatusTestCombo_t = Belos::StatusTestCombo<ScalarType, MV, OP, DM>;
598 using StatusTestResNorm_t = Belos::StatusTestGenResNorm<ScalarType, MV, OP, DM>;
599
600 // Check for convergence tolerance
601 if (params->isParameter("Convergence Tolerance")) {
602 if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
603 convtol_ = params->get ("Convergence Tolerance",
604 static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
605 }
606 else {
607 convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
608 }
609
610 // Update parameter in our list and residual tests.
611 params_->set("Convergence Tolerance", convtol_);
612 if (convTest_ != Teuchos::null)
613 convTest_->setTolerance( convtol_ );
614 }
615
616 if (params->isParameter("Show Maximum Residual Norm Only")) {
617 showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,"Show Maximum Residual Norm Only");
618
619 // Update parameter in our list and residual tests
620 params_->set("Show Maximum Residual Norm Only", showMaxResNormOnly_);
621 if (convTest_ != Teuchos::null)
622 convTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
623 }
624
625 // Check for a change in scaling, if so we need to build new residual tests.
626 bool newResTest = false;
627 {
628 std::string tempResScale = resScale_;
629 if (params->isParameter ("Implicit Residual Scaling")) {
630 tempResScale = params->get<std::string> ("Implicit Residual Scaling");
631 }
632
633 // Only update the scaling if it's different.
634 if (resScale_ != tempResScale) {
637 resScale_ = tempResScale;
638
639 // Update parameter in our list and residual tests
640 params_->set ("Implicit Residual Scaling", resScale_);
641
642 if (! convTest_.is_null ()) {
643 try {
645 if (params->isParameter("Residual Norm")) {
646 if (params->isType<std::string> ("Residual Norm")) {
647 normType = convertStringToNormType(params->get<std::string> ("Residual Norm"));
648 }
649 }
650 convTest_->defineResForm(StatusTestResNorm_t::Implicit, normType);
651 convTest_->defineScaleForm (resScaleType, Belos::TwoNorm);
652 }
653 catch (std::exception& e) {
654 // Make sure the convergence test gets constructed again.
655 newResTest = true;
656 }
657 }
658 }
659 }
660
661 // Create status tests if we need to.
662
663 // Basic test checks maximum iterations and native residual.
664 if (maxIterTest_ == Teuchos::null)
665 maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP,DM>( maxIters_ ) );
666
667 // Implicit residual test, using the native residual to determine if convergence was achieved.
668 if (convTest_.is_null () || newResTest) {
669
671 if (params->isParameter("Residual Norm")) {
672 if (params->isType<std::string> ("Residual Norm")) {
673 normType = convertStringToNormType(params->get<std::string> ("Residual Norm"));
674 }
675 }
676
677 convTest_ = rcp (new StatusTestResNorm_t (convtol_, 1, showMaxResNormOnly_));
678 convTest_->defineResForm(StatusTestResNorm_t::Implicit, normType);
679 convTest_->defineScaleForm (convertStringToScaleType (resScale_), Belos::TwoNorm);
680 }
681
682 if (sTest_.is_null () || newResTest) {
683 sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
684 if (Teuchos::nonnull(debugStatusTest_)) {
685 // Add the debug convergence test, if it exists.
686 sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, sTest_, debugStatusTest_ ) );
687 }
688 }
689
690 if (outputTest_.is_null () || newResTest) {
691
692 // Create the status test output class.
693 // This class manages and formats the output from the status test.
695 outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
696
697 // Set the solver string for the output test
698 std::string solverDesc = " Block CG ";
699 outputTest_->setSolverDesc( solverDesc );
700
701 }
702
703 // BelosCgIter accepts a parameter specifying whether to assert for the positivity of p^H*A*p in the CG iteration
704 if (params->isParameter("Assert Positive Definiteness")) {
705 assertPositiveDefiniteness_ = Teuchos::getParameter<bool>(*params,"Assert Positive Definiteness");
706 params_->set("Assert Positive Definiteness", assertPositiveDefiniteness_);
707 }
708
709 // Create the timer if we need to.
710 if (timerSolve_ == Teuchos::null) {
711 std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
712#ifdef BELOS_TEUCHOS_TIME_MONITOR
713 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
714#endif
715 }
716
717 // Inform the solver manager that the current parameters were set.
718 isSet_ = true;
719}
720
721
722template<class ScalarType, class MV, class OP, class DM>
723Teuchos::RCP<const Teuchos::ParameterList>
725{
726 static Teuchos::RCP<const Teuchos::ParameterList> validPL;
727
728 // Set all the valid parameters and their default values.
729 if(is_null(validPL)) {
730 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
731 pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
732 "The relative residual tolerance that needs to be achieved by the\n"
733 "iterative solver in order for the linear system to be declared converged.");
734 pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
735 "The maximum number of block iterations allowed for each\n"
736 "set of RHS solved.");
737 pl->set("Block Size", static_cast<int>(blockSize_default_),
738 "The number of vectors in each block.");
739 pl->set("Adaptive Block Size", static_cast<bool>(adaptiveBlockSize_default_),
740 "Whether the solver manager should adapt to the block size\n"
741 "based on the number of RHS to solve.");
742 pl->set("Verbosity", static_cast<int>(verbosity_default_),
743 "What type(s) of solver information should be outputted\n"
744 "to the output stream.");
745 pl->set("Output Style", static_cast<int>(outputStyle_default_),
746 "What style is used for the solver information outputted\n"
747 "to the output stream.");
748 pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
749 "How often convergence information should be outputted\n"
750 "to the output stream.");
751 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
752 "A reference-counted pointer to the output stream where all\n"
753 "solver output is sent.");
754 pl->set("Show Maximum Residual Norm Only", static_cast<bool>(showMaxResNormOnly_default_),
755 "When convergence information is printed, only show the maximum\n"
756 "relative residual norm when the block size is greater than one.");
757 pl->set("Use Single Reduction", static_cast<bool>(useSingleReduction_default_),
758 "Use single reduction iteration when the block size is one.");
759 pl->set("Implicit Residual Scaling", resScale_default_,
760 "The type of scaling used in the residual convergence test.");
761 pl->set("Timer Label", static_cast<const char *>(label_default_),
762 "The string to use as a prefix for the timer labels.");
763 pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
764 "The type of orthogonalization to use: DGKS, ICGS, or IMGS.");
765 pl->set("Assert Positive Definiteness",static_cast<bool>(assertPositiveDefiniteness_default_),
766 "Assert for positivity of p^H*A*p in CG iteration.");
767 pl->set("Orthogonalization Constant",static_cast<MagnitudeType>(DefaultSolverParameters::orthoKappa),
768 "The constant used by DGKS orthogonalization to determine\n"
769 "whether another step of classical Gram-Schmidt is necessary.");
770 pl->set("Residual Norm",static_cast<const char *>(resNorm_default_),
771 "Norm used for the convergence check on the residual.");
772 pl->set("Fold Convergence Detection Into Allreduce",static_cast<bool>(foldConvergenceDetectionIntoAllreduce_default_),
773 "Merge the allreduce for convergence detection with the one for CG.\n"
774 "This saves one all-reduce, but incurs more computation.");
775 validPL = pl;
776 }
777 return validPL;
778}
779
780
781// solve()
782template<class ScalarType, class MV, class OP, class DM>
784 using Teuchos::RCP;
785 using Teuchos::rcp;
786 using Teuchos::rcp_const_cast;
787 using Teuchos::rcp_dynamic_cast;
788
790
791 // Set the current parameters if they were not set before. NOTE:
792 // This may occur if the user generated the solver manager with the
793 // default constructor and then didn't set any parameters using
794 // setParameters().
795 if (!isSet_) {
796 setParameters(Teuchos::parameterList(*getValidParameters()));
797 }
798
799 TEUCHOS_TEST_FOR_EXCEPTION( !problem_->isProblemSet(),
801 "Belos::BlockCGSolMgr::solve(): Linear problem is not ready, setProblem() "
802 "has not been called.");
803
804 // Create indices for the linear systems to be solved.
805 int startPtr = 0;
806 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
807 int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
808
809 std::vector<int> currIdx, currIdx2;
810 // If an adaptive block size is allowed then only the linear
811 // systems that need to be solved are solved. Otherwise, the index
812 // set is generated that informs the linear problem that some
813 // linear systems are augmented.
814 if ( adaptiveBlockSize_ ) {
815 blockSize_ = numCurrRHS;
816 currIdx.resize( numCurrRHS );
817 currIdx2.resize( numCurrRHS );
818 for (int i=0; i<numCurrRHS; ++i)
819 { currIdx[i] = startPtr+i; currIdx2[i]=i; }
820
821 }
822 else {
823 currIdx.resize( blockSize_ );
824 currIdx2.resize( blockSize_ );
825 for (int i=0; i<numCurrRHS; ++i)
826 { currIdx[i] = startPtr+i; currIdx2[i]=i; }
827 for (int i=numCurrRHS; i<blockSize_; ++i)
828 { currIdx[i] = -1; currIdx2[i] = i; }
829 }
830
831 // Inform the linear problem of the current linear system to solve.
832 problem_->setLSIndex( currIdx );
833
835 // Set up the parameter list for the Iteration subclass.
836 Teuchos::ParameterList plist;
837 plist.set("Block Size",blockSize_);
838
839 // Reset the output status test (controls all the other status tests).
840 outputTest_->reset();
841
842 // Assume convergence is achieved, then let any failed convergence
843 // set this to false. "Innocent until proven guilty."
844 bool isConverged = true;
845
847 // Set up the BlockCG Iteration subclass.
848
849 plist.set("Assert Positive Definiteness", assertPositiveDefiniteness_);
850
852 if (blockSize_ == 1) {
853 // Standard (nonblock) CG is faster for the special case of a
854 // block size of 1. A single reduction iteration can also be used
855 // if collectives are more expensive than vector updates.
856 plist.set("Fold Convergence Detection Into Allreduce",
857 foldConvergenceDetectionIntoAllreduce_);
858 if (useSingleReduction_) {
860 rcp (new CGSingleRedIter<ScalarType,MV,OP,DM> (problem_, printer_,
861 outputTest_, convTest_, plist));
862 if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGSingleRedIterationState<ScalarType, MV, DM> >(state_).is_null())
863 state_ = Teuchos::rcp(new CGSingleRedIterationState<ScalarType, MV, DM>());
864
865 }
866 else {
868 rcp (new CGIter<ScalarType,MV,OP,DM> (problem_, printer_,
869 outputTest_, convTest_, plist));
870 if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType, MV, DM> >(state_).is_null())
871 state_ = Teuchos::rcp(new CGIterationState<ScalarType, MV, DM>());
872 }
873 } else {
875 rcp (new BlockCGIter<ScalarType,MV,OP,DM> (problem_, printer_, outputTest_,
876 ortho_, plist));
877 if (state_.is_null() || Teuchos::rcp_dynamic_cast<BlockCGIterationState<ScalarType, MV, DM> >(state_).is_null())
878 state_ = Teuchos::rcp(new BlockCGIterationState<ScalarType, MV, DM>());
879 }
880
881
882 // Enter solve() iterations
883 {
884#ifdef BELOS_TEUCHOS_TIME_MONITOR
885 Teuchos::TimeMonitor slvtimer(*timerSolve_);
886#endif
887
888 while ( numRHS2Solve > 0 ) {
889 //
890 // Reset the active / converged vectors from this block
891 std::vector<int> convRHSIdx;
892 std::vector<int> currRHSIdx( currIdx );
893 currRHSIdx.resize(numCurrRHS);
894
895 // Reset the number of iterations.
896 block_cg_iter->resetNumIters();
897
898 // Reset the number of calls that the status test output knows about.
899 outputTest_->resetNumCalls();
900
901 // Get the current residual for this block of linear systems.
902 RCP<MV> R_0 = MVT::CloneViewNonConst( *(rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
903
904 // Set the new state and initialize the solver.
905 block_cg_iter->initializeCG(state_, R_0);
906
907 while(true) {
908
909 // tell block_cg_iter to iterate
910 try {
911 block_cg_iter->iterate();
912 //
913 // Check whether any of the linear systems converged.
914 //
915 if (convTest_->getStatus() == Passed) {
916 // At least one of the linear system(s) converged.
917 //
918 // Get the column indices of the linear systems that converged.
920 std::vector<int> convIdx =
921 rcp_dynamic_cast<conv_test_type>(convTest_)->convIndices();
922
923 // If the number of converged linear systems equals the
924 // number of linear systems currently being solved, then
925 // we are done with this block.
926 if (convIdx.size() == currRHSIdx.size())
927 break; // break from while(1){block_cg_iter->iterate()}
928
929 // Inform the linear problem that we are finished with
930 // this current linear system.
931 problem_->setCurrLS();
932
933 // Reset currRHSIdx to contain the right-hand sides that
934 // are left to converge for this block.
935 int have = 0;
936 std::vector<int> unconvIdx(currRHSIdx.size());
937 for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
938 bool found = false;
939 for (unsigned int j=0; j<convIdx.size(); ++j) {
940 if (currRHSIdx[i] == convIdx[j]) {
941 found = true;
942 break;
943 }
944 }
945 if (!found) {
948 }
949 else {
950 }
951 }
952 currRHSIdx.resize(have);
953 currIdx2.resize(have);
954
955 // Set the remaining indices after deflation.
956 problem_->setLSIndex( currRHSIdx );
957
958 // Get the current residual vector.
959 std::vector<MagnitudeType> norms;
960 R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
961 for (int i=0; i<have; ++i) { currIdx2[i] = i; }
962
963 // Set the new blocksize for the solver.
964 block_cg_iter->setBlockSize( have );
965
966 // Set the new state and initialize the solver.
967 block_cg_iter->initializeCG(state_, R_0);
968 }
969 //
970 // None of the linear systems converged. Check whether the
971 // maximum iteration count was reached.
972 //
973 else if (maxIterTest_->getStatus() == Passed) {
975 isConverged = false; // None of the linear systems converged.
976 break; // break from while(1){block_cg_iter->iterate()}
977 }
978 //
979 // A debug status test (if any) stopped the iteration.
980 //
981 else if (Teuchos::nonnull(debugStatusTest_) &&
982 debugStatusTest_->getStatus() == Passed) {
984 isConverged = false; // A debug test asked us to stop.
985 break; // break from while(1){block_cg_iter->iterate()}
986 }
987 //
988 // iterate() returned, but none of our status tests Passed.
989 // This indicates a bug.
990 //
991 else {
993 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
994 "Belos::BlockCGSolMgr::solve(): Neither the convergence test nor "
995 "the maximum iteration count test passed. Please report this bug "
996 "to the Belos developers.");
997 }
998 }
999 catch (const StatusTestNaNError& e) {
1000 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
1002 achievedTol_ = MT::one();
1003 Teuchos::RCP<MV> X = problem_->getLHS();
1004 MVT::MvInit( *X, SCT::zero() );
1005 printer_->stream(Warnings) << "Belos::BlockCGSolMgr::solve(): Warning! NaN has been detected!"
1006 << std::endl;
1007 return retType;
1008 }
1009 catch (const std::exception &e) {
1011 std::ostream& err = printer_->stream (Errors);
1012 err << "Error! Caught std::exception in CGIteration::iterate() at "
1013 << "iteration " << block_cg_iter->getNumIters() << std::endl
1014 << e.what() << std::endl;
1015 throw;
1016 }
1017 }
1018
1019 // Inform the linear problem that we are finished with this
1020 // block linear system.
1021 problem_->setCurrLS();
1022
1023 // Update indices for the linear systems to be solved.
1026 if ( numRHS2Solve > 0 ) {
1027 numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
1028
1029 if ( adaptiveBlockSize_ ) {
1030 blockSize_ = numCurrRHS;
1031 currIdx.resize( numCurrRHS );
1032 currIdx2.resize( numCurrRHS );
1033 for (int i=0; i<numCurrRHS; ++i)
1034 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
1035 }
1036 else {
1037 currIdx.resize( blockSize_ );
1038 currIdx2.resize( blockSize_ );
1039 for (int i=0; i<numCurrRHS; ++i)
1040 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
1041 for (int i=numCurrRHS; i<blockSize_; ++i)
1042 { currIdx[i] = -1; currIdx2[i] = i; }
1043 }
1044 // Set the next indices.
1045 problem_->setLSIndex( currIdx );
1046
1047 // Set the new blocksize for the solver.
1048 block_cg_iter->setBlockSize( blockSize_ );
1049 }
1050 else {
1051 currIdx.resize( numRHS2Solve );
1052 }
1053
1054 }// while ( numRHS2Solve > 0 )
1055
1056 }
1057
1058 // print final summary
1059 sTest_->print( printer_->stream(FinalSummary) );
1060
1061 // print timing information
1062#ifdef BELOS_TEUCHOS_TIME_MONITOR
1063 // Calling summarize() requires communication in general, so don't
1064 // call it unless the user wants to print out timing details.
1065 // summarize() will do all the work even if it's passed a "black
1066 // hole" output stream.
1067 if (verbosity_ & TimingDetails) {
1068 Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
1069 }
1070#endif
1071
1072 // Save the iteration count for this solve.
1073 numIters_ = maxIterTest_->getNumIters();
1074
1075 // Save the convergence test value ("achieved tolerance") for this solve.
1076 {
1078 // testValues is nonnull and not persistent.
1079 const std::vector<MagnitudeType>* pTestValues =
1080 rcp_dynamic_cast<conv_test_type>(convTest_)->getTestValue();
1081
1082 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1083 "Belos::BlockCGSolMgr::solve(): The convergence test's getTestValue() "
1084 "method returned NULL. Please report this bug to the Belos developers.");
1085
1086 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1087 "Belos::BlockCGSolMgr::solve(): The convergence test's getTestValue() "
1088 "method returned a vector of length zero. Please report this bug to the "
1089 "Belos developers.");
1090
1091 // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
1092 // achieved tolerances for all vectors in the current solve(), or
1093 // just for the vectors from the last deflation?
1094 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
1095 }
1096
1097 if (!isConverged) {
1098 return retType; // return from BlockCGSolMgr::solve()
1099 }
1100 return Converged; // return from BlockCGSolMgr::solve()
1101}
1102
1103// This method requires the solver manager to return a std::string that describes itself.
1104template<class ScalarType, class MV, class OP, class DM>
1106{
1107 std::ostringstream oss;
1108 oss << "Belos::BlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
1109 oss << "{";
1110 oss << "Ortho Type='"<<orthoType_<<"\', Block Size=" << blockSize_;
1111 oss << "}";
1112 return oss.str();
1113}
1114
1115} // end Belos namespace
1116
1117#ifdef HAVE_BELOS_TPETRA
1119
1120#define BELOS_TPETRA_BLOCKCGSOLMGR_NOEXTERN_CALL(SC, LO, GO, NT) \
1121 BELOS_TPETRA_CALL(Belos::BlockCGSolMgr, SC, LO, GO, NT)
1122
1123#define BELOS_TPETRA_BLOCKCGSOLMGR_EXTERN_CALL(SC, LO, GO, NT) \
1124 BELOS_TPETRA_EXTERN_CALL(Belos::BlockCGSolMgr, SC, LO, GO, NT)
1125
1126TPETRA_INSTANTIATE_SLGN_NO_ORDINAL_SCALAR(BELOS_TPETRA_BLOCKCGSOLMGR_EXTERN_CALL)
1127#endif
1128
1129
1130#endif /* BELOS_BLOCK_CG_SOLMGR_HPP */
Belos concrete class for performing the block conjugate-gradient (CG) iteration.
Belos concrete class for performing the conjugate-gradient (CG) iteration.
Belos concrete class for performing a single-reduction conjugate-gradient (CG) iteration.
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.
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.
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.
int getNumIters() const override
Get the iteration count for the most recent call to solve().
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
void reset(const ResetType type) override
Performs a reset of the solver manager specified by the ResetType. This informs the solver manager th...
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve.
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)
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const override
Return a reference to the linear problem being solved by this solver manager.
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
The Belos::BlockCGSolMgr provides a powerful and fully-featured solver manager over the CG and BlockC...
virtual ~BlockCGSolMgr()=default
BlockCGSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
BlockCGSolMgrLinearProblemFailure is thrown when the linear problem is not setup (i....
BlockCGSolMgrLinearProblemFailure(const std::string &what_arg)
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).
ScaleType convertStringToScaleType(const std::string &scaleType)
Convert the given string to its ScaleType enum value.
NormType
The type of vector norm to compute.
@ StatusTestDetails
@ FinalSummary
@ TimingDetails
ReturnType
Whether the Belos solve converged for all linear systems.
@ NaNDetected
@ Unconverged
@ MaxItersReached
@ NonspecificException
@ InconsistentState
@ Undetermined
NormType convertStringToNormType(const std::string &normType)
Convert the given string to its NormType enum value.
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.
static const double orthoKappa
DGKS orthogonalization constant.

Generated for Belos by doxygen 1.9.8