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
221
223
224
228 void reset( const ResetType type ) override { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
230
232
233
251 ReturnType solve() override;
252
254
257
259 std::string description() const override;
260
262
263 private:
264
266 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
267
269 Teuchos::RCP<OutputManager<ScalarType> > printer_;
271 Teuchos::RCP<std::ostream> outputStream_;
272
277 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > sTest_;
278
280 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP,DM> > maxIterTest_;
281
283 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > convTest_;
284
286 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP,DM> > outputTest_;
287
289 Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP,DM> > ortho_;
290
292 Teuchos::RCP<Teuchos::ParameterList> params_;
293
294 //
295 // Default solver parameters.
296 //
297 static constexpr int maxIters_default_ = 1000;
298 static constexpr bool adaptiveBlockSize_default_ = true;
299 static constexpr bool showMaxResNormOnly_default_ = false;
300 static constexpr bool useSingleReduction_default_ = false;
301 static constexpr int blockSize_default_ = 1;
302 static constexpr int verbosity_default_ = Belos::Errors;
303 static constexpr int outputStyle_default_ = Belos::General;
304 static constexpr int outputFreq_default_ = -1;
305 static constexpr const char * resNorm_default_ = "TwoNorm";
306 static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ = false;
307 static constexpr const char * resScale_default_ = "Norm of Initial Residual";
308 static constexpr const char * label_default_ = "Belos";
309 static constexpr const char * orthoType_default_ = "ICGS";
310 static constexpr bool assertPositiveDefiniteness_default_ = true;
311
312 //
313 // Current solver parameters and other values.
314 //
315
317 MagnitudeType convtol_;
318
320 MagnitudeType orthoKappa_;
321
327 MagnitudeType achievedTol_;
328
330 int maxIters_;
331
333 int numIters_;
334
336 int blockSize_, verbosity_, outputStyle_, outputFreq_;
337 bool adaptiveBlockSize_, showMaxResNormOnly_, useSingleReduction_;
338 std::string orthoType_, resScale_;
339 bool assertPositiveDefiniteness_;
340 bool foldConvergenceDetectionIntoAllreduce_;
341
342 Teuchos::RCP<CGIterationStateBase<ScalarType, MV, DM> > state_;
343
345 std::string label_;
346
348 Teuchos::RCP<Teuchos::Time> timerSolve_;
349
351 bool isSet_;
352 };
353
354
355// Empty Constructor
356template<class ScalarType, class MV, class OP, class DM>
358 outputStream_(Teuchos::rcpFromRef(std::cout)),
359 convtol_(DefaultSolverParameters::convTol),
360 orthoKappa_(DefaultSolverParameters::orthoKappa),
361 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
362 maxIters_(maxIters_default_),
363 numIters_(0),
364 blockSize_(blockSize_default_),
365 verbosity_(verbosity_default_),
366 outputStyle_(outputStyle_default_),
367 outputFreq_(outputFreq_default_),
368 adaptiveBlockSize_(adaptiveBlockSize_default_),
369 showMaxResNormOnly_(showMaxResNormOnly_default_),
370 useSingleReduction_(useSingleReduction_default_),
371 orthoType_(orthoType_default_),
372 resScale_(resScale_default_),
373 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
374 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
375 label_(label_default_),
376 isSet_(false)
377{}
378
379
380// Basic Constructor
381template<class ScalarType, class MV, class OP, class DM>
384 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
385 problem_(problem),
386 outputStream_(Teuchos::rcpFromRef(std::cout)),
387 convtol_(DefaultSolverParameters::convTol),
388 orthoKappa_(DefaultSolverParameters::orthoKappa),
389 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
390 maxIters_(maxIters_default_),
391 numIters_(0),
392 blockSize_(blockSize_default_),
393 verbosity_(verbosity_default_),
394 outputStyle_(outputStyle_default_),
395 outputFreq_(outputFreq_default_),
396 adaptiveBlockSize_(adaptiveBlockSize_default_),
397 showMaxResNormOnly_(showMaxResNormOnly_default_),
398 useSingleReduction_(useSingleReduction_default_),
399 orthoType_(orthoType_default_),
400 resScale_(resScale_default_),
401 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
402 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
403 label_(label_default_),
404 isSet_(false)
405{
406 TEUCHOS_TEST_FOR_EXCEPTION(problem_.is_null(), std::invalid_argument,
407 "BlockCGSolMgr's constructor requires a nonnull LinearProblem instance.");
408
409 // If the user passed in a nonnull parameter list, set parameters.
410 // Otherwise, the next solve() call will use default parameters,
411 // unless the user calls setParameters() first.
412 if (! pl.is_null()) {
413 setParameters (pl);
414 }
415}
416
417template<class ScalarType, class MV, class OP, class DM>
418void
420setParameters (const Teuchos::RCP<Teuchos::ParameterList> &params)
421{
422 // Create the internal parameter list if one doesn't already exist.
423 if (params_ == Teuchos::null) {
424 params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
425 }
426 else {
427 params->validateParameters(*getValidParameters());
428 }
429
430 // Check for maximum number of iterations
431 if (params->isParameter("Maximum Iterations")) {
432 maxIters_ = params->get("Maximum Iterations",maxIters_default_);
433
434 // Update parameter in our list and in status test.
435 params_->set("Maximum Iterations", maxIters_);
436 if (maxIterTest_!=Teuchos::null)
437 maxIterTest_->setMaxIters( maxIters_ );
438 }
439
440 // Check for blocksize
441 if (params->isParameter("Block Size")) {
442 blockSize_ = params->get("Block Size",blockSize_default_);
443 TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
444 "Belos::BlockCGSolMgr: \"Block Size\" must be strictly positive.");
445
446 // Update parameter in our list.
447 params_->set("Block Size", blockSize_);
448 }
449
450 // Check if the blocksize should be adaptive
451 if (params->isParameter("Adaptive Block Size")) {
452 adaptiveBlockSize_ = params->get("Adaptive Block Size",adaptiveBlockSize_default_);
453
454 // Update parameter in our list.
455 params_->set("Adaptive Block Size", adaptiveBlockSize_);
456 }
457
458 // Check if the user is requesting the single-reduction version of CG (only for blocksize == 1)
459 if (params->isParameter("Use Single Reduction")) {
460 useSingleReduction_ = params->get("Use Single Reduction", useSingleReduction_default_);
461 }
462
463 if (params->isParameter("Fold Convergence Detection Into Allreduce")) {
464 foldConvergenceDetectionIntoAllreduce_ = params->get("Fold Convergence Detection Into Allreduce",
465 foldConvergenceDetectionIntoAllreduce_default_);
466 }
467
468 // Check to see if the timer label changed.
469 if (params->isParameter("Timer Label")) {
470 std::string tempLabel = params->get("Timer Label", label_default_);
471
472 // Update parameter in our list and solver timer
473 if (tempLabel != label_) {
474 label_ = tempLabel;
475 params_->set("Timer Label", label_);
476 std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
477#ifdef BELOS_TEUCHOS_TIME_MONITOR
478 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
479#endif
480 if (ortho_ != Teuchos::null) {
481 ortho_->setLabel( label_ );
482 }
483 }
484 }
485
486 // Check for a change in verbosity level
487 if (params->isParameter("Verbosity")) {
488 if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
489 verbosity_ = params->get("Verbosity", verbosity_default_);
490 } else {
491 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
492 }
493
494 // Update parameter in our list.
495 params_->set("Verbosity", verbosity_);
496 if (printer_ != Teuchos::null)
497 printer_->setVerbosity(verbosity_);
498 }
499
500 // Check for a change in output style
501 if (params->isParameter("Output Style")) {
502 if (Teuchos::isParameterType<int>(*params,"Output Style")) {
503 outputStyle_ = params->get("Output Style", outputStyle_default_);
504 } else {
505 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
506 }
507
508 // Update parameter in our list.
509 params_->set("Output Style", outputStyle_);
510 outputTest_ = Teuchos::null;
511 }
512
513 // output stream
514 if (params->isParameter("Output Stream")) {
515 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
516
517 // Update parameter in our list.
518 params_->set("Output Stream", outputStream_);
519 if (printer_ != Teuchos::null)
520 printer_->setOStream( outputStream_ );
521 }
522
523 // frequency level
524 if (verbosity_ & Belos::StatusTestDetails) {
525 if (params->isParameter("Output Frequency")) {
526 outputFreq_ = params->get("Output Frequency", outputFreq_default_);
527 }
528
529 // Update parameter in out list and output status test.
530 params_->set("Output Frequency", outputFreq_);
531 if (outputTest_ != Teuchos::null)
532 outputTest_->setOutputFrequency( outputFreq_ );
533 }
534
535 // Create output manager if we need to.
536 if (printer_ == Teuchos::null) {
537 printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
538 }
539
540 // Check if the orthogonalization changed.
541 bool changedOrthoType = false;
542 if (params->isParameter("Orthogonalization")) {
543 std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
544 if (tempOrthoType != orthoType_) {
545 orthoType_ = tempOrthoType;
546 changedOrthoType = true;
547 }
548 }
549 params_->set("Orthogonalization", orthoType_);
550
551 // Check which orthogonalization constant to use.
552 if (params->isParameter("Orthogonalization Constant")) {
553 if (params->isType<MagnitudeType> ("Orthogonalization Constant")) {
554 orthoKappa_ = params->get ("Orthogonalization Constant",
555 static_cast<MagnitudeType> (DefaultSolverParameters::orthoKappa));
556 }
557 else {
558 orthoKappa_ = params->get ("Orthogonalization Constant",
560 }
561
562 // Update parameter in our list.
563 params_->set("Orthogonalization Constant",orthoKappa_);
564 if (orthoType_=="DGKS") {
565 if (orthoKappa_ > 0 && ortho_ != Teuchos::null && !changedOrthoType) {
566 Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP,DM> >(ortho_)->setDepTol( orthoKappa_ );
567 }
568 }
569 }
570
571 // Create orthogonalization manager if we need to.
572 if (ortho_ == Teuchos::null || changedOrthoType) {
574 Teuchos::RCP<Teuchos::ParameterList> paramsOrtho;
575 if (orthoType_=="DGKS" && orthoKappa_ > 0) {
576 paramsOrtho = Teuchos::rcp(new Teuchos::ParameterList());
577 paramsOrtho->set ("depTol", orthoKappa_ );
578 }
579
580 ortho_ = factory.makeMatOrthoManager (orthoType_, Teuchos::null, printer_, label_, paramsOrtho);
581 }
582
583 // Convergence
584 using StatusTestCombo_t = Belos::StatusTestCombo<ScalarType, MV, OP, DM>;
585 using StatusTestResNorm_t = Belos::StatusTestGenResNorm<ScalarType, MV, OP, DM>;
586
587 // Check for convergence tolerance
588 if (params->isParameter("Convergence Tolerance")) {
589 if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
590 convtol_ = params->get ("Convergence Tolerance",
591 static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
592 }
593 else {
594 convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
595 }
596
597 // Update parameter in our list and residual tests.
598 params_->set("Convergence Tolerance", convtol_);
599 if (convTest_ != Teuchos::null)
600 convTest_->setTolerance( convtol_ );
601 }
602
603 if (params->isParameter("Show Maximum Residual Norm Only")) {
604 showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,"Show Maximum Residual Norm Only");
605
606 // Update parameter in our list and residual tests
607 params_->set("Show Maximum Residual Norm Only", showMaxResNormOnly_);
608 if (convTest_ != Teuchos::null)
609 convTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
610 }
611
612 // Check for a change in scaling, if so we need to build new residual tests.
613 bool newResTest = false;
614 {
615 std::string tempResScale = resScale_;
616 if (params->isParameter ("Implicit Residual Scaling")) {
617 tempResScale = params->get<std::string> ("Implicit Residual Scaling");
618 }
619
620 // Only update the scaling if it's different.
621 if (resScale_ != tempResScale) {
624 resScale_ = tempResScale;
625
626 // Update parameter in our list and residual tests
627 params_->set ("Implicit Residual Scaling", resScale_);
628
629 if (! convTest_.is_null ()) {
630 try {
632 if (params->isParameter("Residual Norm")) {
633 if (params->isType<std::string> ("Residual Norm")) {
634 normType = convertStringToNormType(params->get<std::string> ("Residual Norm"));
635 }
636 }
637 convTest_->defineResForm(StatusTestResNorm_t::Implicit, normType);
638 convTest_->defineScaleForm (resScaleType, Belos::TwoNorm);
639 }
640 catch (std::exception& e) {
641 // Make sure the convergence test gets constructed again.
642 newResTest = true;
643 }
644 }
645 }
646 }
647
648 // Create status tests if we need to.
649
650 // Basic test checks maximum iterations and native residual.
651 if (maxIterTest_ == Teuchos::null)
652 maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP,DM>( maxIters_ ) );
653
654 // Implicit residual test, using the native residual to determine if convergence was achieved.
655 if (convTest_.is_null () || newResTest) {
656
658 if (params->isParameter("Residual Norm")) {
659 if (params->isType<std::string> ("Residual Norm")) {
660 normType = convertStringToNormType(params->get<std::string> ("Residual Norm"));
661 }
662 }
663
664 convTest_ = rcp (new StatusTestResNorm_t (convtol_, 1, showMaxResNormOnly_));
665 convTest_->defineResForm(StatusTestResNorm_t::Implicit, normType);
666 convTest_->defineScaleForm (convertStringToScaleType (resScale_), Belos::TwoNorm);
667 }
668
669 if (sTest_.is_null () || newResTest)
670 sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
671
672 if (outputTest_.is_null () || newResTest) {
673
674 // Create the status test output class.
675 // This class manages and formats the output from the status test.
677 outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
678
679 // Set the solver string for the output test
680 std::string solverDesc = " Block CG ";
681 outputTest_->setSolverDesc( solverDesc );
682
683 }
684
685 // BelosCgIter accepts a parameter specifying whether to assert for the positivity of p^H*A*p in the CG iteration
686 if (params->isParameter("Assert Positive Definiteness")) {
687 assertPositiveDefiniteness_ = Teuchos::getParameter<bool>(*params,"Assert Positive Definiteness");
688 params_->set("Assert Positive Definiteness", assertPositiveDefiniteness_);
689 }
690
691 // Create the timer if we need to.
692 if (timerSolve_ == Teuchos::null) {
693 std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
694#ifdef BELOS_TEUCHOS_TIME_MONITOR
695 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
696#endif
697 }
698
699 // Inform the solver manager that the current parameters were set.
700 isSet_ = true;
701}
702
703
704template<class ScalarType, class MV, class OP, class DM>
705Teuchos::RCP<const Teuchos::ParameterList>
707{
708 static Teuchos::RCP<const Teuchos::ParameterList> validPL;
709
710 // Set all the valid parameters and their default values.
711 if(is_null(validPL)) {
712 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
713 pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
714 "The relative residual tolerance that needs to be achieved by the\n"
715 "iterative solver in order for the linear system to be declared converged.");
716 pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
717 "The maximum number of block iterations allowed for each\n"
718 "set of RHS solved.");
719 pl->set("Block Size", static_cast<int>(blockSize_default_),
720 "The number of vectors in each block.");
721 pl->set("Adaptive Block Size", static_cast<bool>(adaptiveBlockSize_default_),
722 "Whether the solver manager should adapt to the block size\n"
723 "based on the number of RHS to solve.");
724 pl->set("Verbosity", static_cast<int>(verbosity_default_),
725 "What type(s) of solver information should be outputted\n"
726 "to the output stream.");
727 pl->set("Output Style", static_cast<int>(outputStyle_default_),
728 "What style is used for the solver information outputted\n"
729 "to the output stream.");
730 pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
731 "How often convergence information should be outputted\n"
732 "to the output stream.");
733 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
734 "A reference-counted pointer to the output stream where all\n"
735 "solver output is sent.");
736 pl->set("Show Maximum Residual Norm Only", static_cast<bool>(showMaxResNormOnly_default_),
737 "When convergence information is printed, only show the maximum\n"
738 "relative residual norm when the block size is greater than one.");
739 pl->set("Use Single Reduction", static_cast<bool>(useSingleReduction_default_),
740 "Use single reduction iteration when the block size is one.");
741 pl->set("Implicit Residual Scaling", resScale_default_,
742 "The type of scaling used in the residual convergence test.");
743 pl->set("Timer Label", static_cast<const char *>(label_default_),
744 "The string to use as a prefix for the timer labels.");
745 pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
746 "The type of orthogonalization to use: DGKS, ICGS, or IMGS.");
747 pl->set("Assert Positive Definiteness",static_cast<bool>(assertPositiveDefiniteness_default_),
748 "Assert for positivity of p^H*A*p in CG iteration.");
749 pl->set("Orthogonalization Constant",static_cast<MagnitudeType>(DefaultSolverParameters::orthoKappa),
750 "The constant used by DGKS orthogonalization to determine\n"
751 "whether another step of classical Gram-Schmidt is necessary.");
752 pl->set("Residual Norm",static_cast<const char *>(resNorm_default_),
753 "Norm used for the convergence check on the residual.");
754 pl->set("Fold Convergence Detection Into Allreduce",static_cast<bool>(foldConvergenceDetectionIntoAllreduce_default_),
755 "Merge the allreduce for convergence detection with the one for CG.\n"
756 "This saves one all-reduce, but incurs more computation.");
757 validPL = pl;
758 }
759 return validPL;
760}
761
762
763// solve()
764template<class ScalarType, class MV, class OP, class DM>
766 using Teuchos::RCP;
767 using Teuchos::rcp;
768 using Teuchos::rcp_const_cast;
769 using Teuchos::rcp_dynamic_cast;
770
772
773 // Set the current parameters if they were not set before. NOTE:
774 // This may occur if the user generated the solver manager with the
775 // default constructor and then didn't set any parameters using
776 // setParameters().
777 if (!isSet_) {
778 setParameters(Teuchos::parameterList(*getValidParameters()));
779 }
780
781 TEUCHOS_TEST_FOR_EXCEPTION( !problem_->isProblemSet(),
783 "Belos::BlockCGSolMgr::solve(): Linear problem is not ready, setProblem() "
784 "has not been called.");
785
786 // Create indices for the linear systems to be solved.
787 int startPtr = 0;
788 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
789 int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
790
791 std::vector<int> currIdx, currIdx2;
792 // If an adaptive block size is allowed then only the linear
793 // systems that need to be solved are solved. Otherwise, the index
794 // set is generated that informs the linear problem that some
795 // linear systems are augmented.
796 if ( adaptiveBlockSize_ ) {
797 blockSize_ = numCurrRHS;
798 currIdx.resize( numCurrRHS );
799 currIdx2.resize( numCurrRHS );
800 for (int i=0; i<numCurrRHS; ++i)
801 { currIdx[i] = startPtr+i; currIdx2[i]=i; }
802
803 }
804 else {
805 currIdx.resize( blockSize_ );
806 currIdx2.resize( blockSize_ );
807 for (int i=0; i<numCurrRHS; ++i)
808 { currIdx[i] = startPtr+i; currIdx2[i]=i; }
809 for (int i=numCurrRHS; i<blockSize_; ++i)
810 { currIdx[i] = -1; currIdx2[i] = i; }
811 }
812
813 // Inform the linear problem of the current linear system to solve.
814 problem_->setLSIndex( currIdx );
815
817 // Set up the parameter list for the Iteration subclass.
818 Teuchos::ParameterList plist;
819 plist.set("Block Size",blockSize_);
820
821 // Reset the output status test (controls all the other status tests).
822 outputTest_->reset();
823
824 // Assume convergence is achieved, then let any failed convergence
825 // set this to false. "Innocent until proven guilty."
826 bool isConverged = true;
827
829 // Set up the BlockCG Iteration subclass.
830
831 plist.set("Assert Positive Definiteness", assertPositiveDefiniteness_);
832
834 if (blockSize_ == 1) {
835 // Standard (nonblock) CG is faster for the special case of a
836 // block size of 1. A single reduction iteration can also be used
837 // if collectives are more expensive than vector updates.
838 plist.set("Fold Convergence Detection Into Allreduce",
839 foldConvergenceDetectionIntoAllreduce_);
840 if (useSingleReduction_) {
842 rcp (new CGSingleRedIter<ScalarType,MV,OP,DM> (problem_, printer_,
843 outputTest_, convTest_, plist));
844 if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGSingleRedIterationState<ScalarType, MV, DM> >(state_).is_null())
845 state_ = Teuchos::rcp(new CGSingleRedIterationState<ScalarType, MV, DM>());
846
847 }
848 else {
850 rcp (new CGIter<ScalarType,MV,OP,DM> (problem_, printer_,
851 outputTest_, convTest_, plist));
852 if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType, MV, DM> >(state_).is_null())
853 state_ = Teuchos::rcp(new CGIterationState<ScalarType, MV, DM>());
854 }
855 } else {
857 rcp (new BlockCGIter<ScalarType,MV,OP,DM> (problem_, printer_, outputTest_,
858 ortho_, plist));
859 if (state_.is_null() || Teuchos::rcp_dynamic_cast<BlockCGIterationState<ScalarType, MV, DM> >(state_).is_null())
860 state_ = Teuchos::rcp(new BlockCGIterationState<ScalarType, MV, DM>());
861 }
862
863
864 // Enter solve() iterations
865 {
866#ifdef BELOS_TEUCHOS_TIME_MONITOR
867 Teuchos::TimeMonitor slvtimer(*timerSolve_);
868#endif
869
870 while ( numRHS2Solve > 0 ) {
871 //
872 // Reset the active / converged vectors from this block
873 std::vector<int> convRHSIdx;
874 std::vector<int> currRHSIdx( currIdx );
875 currRHSIdx.resize(numCurrRHS);
876
877 // Reset the number of iterations.
878 block_cg_iter->resetNumIters();
879
880 // Reset the number of calls that the status test output knows about.
881 outputTest_->resetNumCalls();
882
883 // Get the current residual for this block of linear systems.
884 RCP<MV> R_0 = MVT::CloneViewNonConst( *(rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
885
886 // Set the new state and initialize the solver.
887 block_cg_iter->initializeCG(state_, R_0);
888
889 while(true) {
890
891 // tell block_cg_iter to iterate
892 try {
893 block_cg_iter->iterate();
894 //
895 // Check whether any of the linear systems converged.
896 //
897 if (convTest_->getStatus() == Passed) {
898 // At least one of the linear system(s) converged.
899 //
900 // Get the column indices of the linear systems that converged.
902 std::vector<int> convIdx =
903 rcp_dynamic_cast<conv_test_type>(convTest_)->convIndices();
904
905 // If the number of converged linear systems equals the
906 // number of linear systems currently being solved, then
907 // we are done with this block.
908 if (convIdx.size() == currRHSIdx.size())
909 break; // break from while(1){block_cg_iter->iterate()}
910
911 // Inform the linear problem that we are finished with
912 // this current linear system.
913 problem_->setCurrLS();
914
915 // Reset currRHSIdx to contain the right-hand sides that
916 // are left to converge for this block.
917 int have = 0;
918 std::vector<int> unconvIdx(currRHSIdx.size());
919 for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
920 bool found = false;
921 for (unsigned int j=0; j<convIdx.size(); ++j) {
922 if (currRHSIdx[i] == convIdx[j]) {
923 found = true;
924 break;
925 }
926 }
927 if (!found) {
930 }
931 else {
932 }
933 }
934 currRHSIdx.resize(have);
935 currIdx2.resize(have);
936
937 // Set the remaining indices after deflation.
938 problem_->setLSIndex( currRHSIdx );
939
940 // Get the current residual vector.
941 std::vector<MagnitudeType> norms;
942 R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
943 for (int i=0; i<have; ++i) { currIdx2[i] = i; }
944
945 // Set the new blocksize for the solver.
946 block_cg_iter->setBlockSize( have );
947
948 // Set the new state and initialize the solver.
949 block_cg_iter->initializeCG(state_, R_0);
950 }
951 //
952 // None of the linear systems converged. Check whether the
953 // maximum iteration count was reached.
954 //
955 else if (maxIterTest_->getStatus() == Passed) {
957 isConverged = false; // None of the linear systems converged.
958 break; // break from while(1){block_cg_iter->iterate()}
959 }
960 //
961 // iterate() returned, but none of our status tests Passed.
962 // This indicates a bug.
963 //
964 else {
966 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
967 "Belos::BlockCGSolMgr::solve(): Neither the convergence test nor "
968 "the maximum iteration count test passed. Please report this bug "
969 "to the Belos developers.");
970 }
971 }
972 catch (const StatusTestNaNError& e) {
973 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
975 achievedTol_ = MT::one();
976 Teuchos::RCP<MV> X = problem_->getLHS();
977 MVT::MvInit( *X, SCT::zero() );
978 printer_->stream(Warnings) << "Belos::BlockCGSolMgr::solve(): Warning! NaN has been detected!"
979 << std::endl;
980 return retType;
981 }
982 catch (const std::exception &e) {
984 std::ostream& err = printer_->stream (Errors);
985 err << "Error! Caught std::exception in CGIteration::iterate() at "
986 << "iteration " << block_cg_iter->getNumIters() << std::endl
987 << e.what() << std::endl;
988 throw;
989 }
990 }
991
992 // Inform the linear problem that we are finished with this
993 // block linear system.
994 problem_->setCurrLS();
995
996 // Update indices for the linear systems to be solved.
999 if ( numRHS2Solve > 0 ) {
1000 numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
1001
1002 if ( adaptiveBlockSize_ ) {
1003 blockSize_ = numCurrRHS;
1004 currIdx.resize( numCurrRHS );
1005 currIdx2.resize( numCurrRHS );
1006 for (int i=0; i<numCurrRHS; ++i)
1007 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
1008 }
1009 else {
1010 currIdx.resize( blockSize_ );
1011 currIdx2.resize( blockSize_ );
1012 for (int i=0; i<numCurrRHS; ++i)
1013 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
1014 for (int i=numCurrRHS; i<blockSize_; ++i)
1015 { currIdx[i] = -1; currIdx2[i] = i; }
1016 }
1017 // Set the next indices.
1018 problem_->setLSIndex( currIdx );
1019
1020 // Set the new blocksize for the solver.
1021 block_cg_iter->setBlockSize( blockSize_ );
1022 }
1023 else {
1024 currIdx.resize( numRHS2Solve );
1025 }
1026
1027 }// while ( numRHS2Solve > 0 )
1028
1029 }
1030
1031 // print final summary
1032 sTest_->print( printer_->stream(FinalSummary) );
1033
1034 // print timing information
1035#ifdef BELOS_TEUCHOS_TIME_MONITOR
1036 // Calling summarize() requires communication in general, so don't
1037 // call it unless the user wants to print out timing details.
1038 // summarize() will do all the work even if it's passed a "black
1039 // hole" output stream.
1040 if (verbosity_ & TimingDetails) {
1041 Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
1042 }
1043#endif
1044
1045 // Save the iteration count for this solve.
1046 numIters_ = maxIterTest_->getNumIters();
1047
1048 // Save the convergence test value ("achieved tolerance") for this solve.
1049 {
1051 // testValues is nonnull and not persistent.
1052 const std::vector<MagnitudeType>* pTestValues =
1053 rcp_dynamic_cast<conv_test_type>(convTest_)->getTestValue();
1054
1055 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1056 "Belos::BlockCGSolMgr::solve(): The convergence test's getTestValue() "
1057 "method returned NULL. Please report this bug to the Belos developers.");
1058
1059 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1060 "Belos::BlockCGSolMgr::solve(): The convergence test's getTestValue() "
1061 "method returned a vector of length zero. Please report this bug to the "
1062 "Belos developers.");
1063
1064 // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
1065 // achieved tolerances for all vectors in the current solve(), or
1066 // just for the vectors from the last deflation?
1067 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
1068 }
1069
1070 if (!isConverged) {
1071 return retType; // return from BlockCGSolMgr::solve()
1072 }
1073 return Converged; // return from BlockCGSolMgr::solve()
1074}
1075
1076// This method requires the solver manager to return a std::string that describes itself.
1077template<class ScalarType, class MV, class OP, class DM>
1079{
1080 std::ostringstream oss;
1081 oss << "Belos::BlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
1082 oss << "{";
1083 oss << "Ortho Type='"<<orthoType_<<"\', Block Size=" << blockSize_;
1084 oss << "}";
1085 return oss.str();
1086}
1087
1088} // end Belos namespace
1089
1090#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.
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
@ 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