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