157 typedef Teuchos::ScalarTraits<ScalarType> SCT;
158 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
159 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
210 const Teuchos::RCP<Teuchos::ParameterList> &pl );
216 Teuchos::RCP<SolverManager<ScalarType, MV, OP> >
clone ()
const override {
230 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters()
const override;
241 Teuchos::Array<Teuchos::RCP<Teuchos::Time> >
getTimers()
const {
242 return Teuchos::tuple(timerSolve_);
272 void setParameters(
const Teuchos::RCP<Teuchos::ParameterList> ¶ms )
override;
313 std::string description()
const override;
320 Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
323 Teuchos::RCP<OutputManager<ScalarType> > printer_;
325 Teuchos::RCP<std::ostream> outputStream_;
331 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
334 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
337 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > convTest_;
340 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
343 Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho_;
346 Teuchos::RCP<Teuchos::ParameterList> params_;
351 static constexpr int maxIters_default_ = 1000;
352 static constexpr bool adaptiveBlockSize_default_ =
true;
353 static constexpr bool showMaxResNormOnly_default_ =
false;
354 static constexpr bool useSingleReduction_default_ =
false;
355 static constexpr int blockSize_default_ = 1;
358 static constexpr int outputFreq_default_ = -1;
359 static constexpr const char * resNorm_default_ =
"TwoNorm";
360 static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ =
false;
361 static constexpr const char * resScale_default_ =
"Norm of Initial Residual";
362 static constexpr const char * label_default_ =
"Belos";
363 static constexpr const char * orthoType_default_ =
"ICGS";
364 static constexpr bool assertPositiveDefiniteness_default_ =
true;
366#if defined(_WIN32) && defined(__clang__)
367 static constexpr std::ostream * outputStream_default_ =
368 __builtin_constant_p(
reinterpret_cast<const std::ostream*
>(&std::cout));
370 static constexpr std::ostream * outputStream_default_ = &std::cout;
378 MagnitudeType convtol_;
381 MagnitudeType orthoKappa_;
388 MagnitudeType achievedTol_;
397 int blockSize_, verbosity_, outputStyle_, outputFreq_;
398 bool adaptiveBlockSize_, showMaxResNormOnly_, useSingleReduction_;
399 std::string orthoType_, resScale_;
400 bool assertPositiveDefiniteness_;
401 bool foldConvergenceDetectionIntoAllreduce_;
407 Teuchos::RCP<Teuchos::Time> timerSolve_;
417 outputStream_(Teuchos::rcp(outputStream_default_,false)),
420 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
421 maxIters_(maxIters_default_),
423 blockSize_(blockSize_default_),
424 verbosity_(verbosity_default_),
425 outputStyle_(outputStyle_default_),
426 outputFreq_(outputFreq_default_),
427 adaptiveBlockSize_(adaptiveBlockSize_default_),
428 showMaxResNormOnly_(showMaxResNormOnly_default_),
429 useSingleReduction_(useSingleReduction_default_),
430 orthoType_(orthoType_default_),
431 resScale_(resScale_default_),
432 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
433 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
434 label_(label_default_),
443 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
445 outputStream_(Teuchos::rcp(outputStream_default_,false)),
448 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
449 maxIters_(maxIters_default_),
451 blockSize_(blockSize_default_),
452 verbosity_(verbosity_default_),
453 outputStyle_(outputStyle_default_),
454 outputFreq_(outputFreq_default_),
455 adaptiveBlockSize_(adaptiveBlockSize_default_),
456 showMaxResNormOnly_(showMaxResNormOnly_default_),
457 useSingleReduction_(useSingleReduction_default_),
458 orthoType_(orthoType_default_),
459 resScale_(resScale_default_),
460 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
461 foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
462 label_(label_default_),
465 TEUCHOS_TEST_FOR_EXCEPTION(problem_.is_null(), std::invalid_argument,
466 "BlockCGSolMgr's constructor requires a nonnull LinearProblem instance.");
471 if (! pl.is_null()) {
479setParameters (
const Teuchos::RCP<Teuchos::ParameterList> ¶ms)
482 if (params_ == Teuchos::null) {
483 params_ = Teuchos::rcp(
new Teuchos::ParameterList(*getValidParameters()) );
486 params->validateParameters(*getValidParameters());
490 if (params->isParameter(
"Maximum Iterations")) {
491 maxIters_ = params->get(
"Maximum Iterations",maxIters_default_);
494 params_->set(
"Maximum Iterations", maxIters_);
495 if (maxIterTest_!=Teuchos::null)
496 maxIterTest_->setMaxIters( maxIters_ );
500 if (params->isParameter(
"Block Size")) {
501 blockSize_ = params->get(
"Block Size",blockSize_default_);
502 TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
503 "Belos::BlockCGSolMgr: \"Block Size\" must be strictly positive.");
506 params_->set(
"Block Size", blockSize_);
510 if (params->isParameter(
"Adaptive Block Size")) {
511 adaptiveBlockSize_ = params->get(
"Adaptive Block Size",adaptiveBlockSize_default_);
514 params_->set(
"Adaptive Block Size", adaptiveBlockSize_);
518 if (params->isParameter(
"Use Single Reduction")) {
519 useSingleReduction_ = params->get(
"Use Single Reduction", useSingleReduction_default_);
522 if (params->isParameter(
"Fold Convergence Detection Into Allreduce")) {
523 foldConvergenceDetectionIntoAllreduce_ = params->get(
"Fold Convergence Detection Into Allreduce",
524 foldConvergenceDetectionIntoAllreduce_default_);
528 if (params->isParameter(
"Timer Label")) {
529 std::string tempLabel = params->get(
"Timer Label", label_default_);
532 if (tempLabel != label_) {
534 params_->set(
"Timer Label", label_);
535 std::string solveLabel = label_ +
": BlockCGSolMgr total solve time";
536#ifdef BELOS_TEUCHOS_TIME_MONITOR
537 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
539 if (ortho_ != Teuchos::null) {
540 ortho_->setLabel( label_ );
546 if (params->isParameter(
"Verbosity")) {
547 if (Teuchos::isParameterType<int>(*params,
"Verbosity")) {
548 verbosity_ = params->get(
"Verbosity", verbosity_default_);
550 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,
"Verbosity");
554 params_->set(
"Verbosity", verbosity_);
555 if (printer_ != Teuchos::null)
556 printer_->setVerbosity(verbosity_);
560 if (params->isParameter(
"Output Style")) {
561 if (Teuchos::isParameterType<int>(*params,
"Output Style")) {
562 outputStyle_ = params->get(
"Output Style", outputStyle_default_);
564 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,
"Output Style");
568 params_->set(
"Output Style", outputStyle_);
569 outputTest_ = Teuchos::null;
573 if (params->isParameter(
"Output Stream")) {
574 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,
"Output Stream");
577 params_->set(
"Output Stream", outputStream_);
578 if (printer_ != Teuchos::null)
579 printer_->setOStream( outputStream_ );
584 if (params->isParameter(
"Output Frequency")) {
585 outputFreq_ = params->get(
"Output Frequency", outputFreq_default_);
589 params_->set(
"Output Frequency", outputFreq_);
590 if (outputTest_ != Teuchos::null)
591 outputTest_->setOutputFrequency( outputFreq_ );
595 if (printer_ == Teuchos::null) {
600 bool changedOrthoType =
false;
601 if (params->isParameter(
"Orthogonalization")) {
602 std::string tempOrthoType = params->get(
"Orthogonalization",orthoType_default_);
603 if (tempOrthoType != orthoType_) {
604 orthoType_ = tempOrthoType;
605 changedOrthoType =
true;
608 params_->set(
"Orthogonalization", orthoType_);
611 if (params->isParameter(
"Orthogonalization Constant")) {
612 if (params->isType<MagnitudeType> (
"Orthogonalization Constant")) {
613 orthoKappa_ = params->get (
"Orthogonalization Constant",
617 orthoKappa_ = params->get (
"Orthogonalization Constant",
622 params_->set(
"Orthogonalization Constant",orthoKappa_);
623 if (orthoType_==
"DGKS") {
624 if (orthoKappa_ > 0 && ortho_ != Teuchos::null && !changedOrthoType) {
625 Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
631 if (ortho_ == Teuchos::null || changedOrthoType) {
633 Teuchos::RCP<Teuchos::ParameterList> paramsOrtho;
634 if (orthoType_==
"DGKS" && orthoKappa_ > 0) {
635 paramsOrtho->set (
"depTol", orthoKappa_ );
638 ortho_ = factory.
makeMatOrthoManager (orthoType_, Teuchos::null, printer_, label_, paramsOrtho);
646 if (params->isParameter(
"Convergence Tolerance")) {
647 if (params->isType<MagnitudeType> (
"Convergence Tolerance")) {
648 convtol_ = params->get (
"Convergence Tolerance",
656 params_->set(
"Convergence Tolerance", convtol_);
657 if (convTest_ != Teuchos::null)
661 if (params->isParameter(
"Show Maximum Residual Norm Only")) {
662 showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,
"Show Maximum Residual Norm Only");
665 params_->set(
"Show Maximum Residual Norm Only", showMaxResNormOnly_);
666 if (convTest_ != Teuchos::null)
667 convTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
671 bool newResTest =
false;
673 std::string tempResScale = resScale_;
674 if (params->isParameter (
"Implicit Residual Scaling")) {
675 tempResScale = params->get<std::string> (
"Implicit Residual Scaling");
679 if (resScale_ != tempResScale) {
682 resScale_ = tempResScale;
685 params_->set (
"Implicit Residual Scaling", resScale_);
687 if (! convTest_.is_null ()) {
690 if (params->isParameter(
"Residual Norm")) {
691 if (params->isType<std::string> (
"Residual Norm")) {
695 convTest_->defineResForm(StatusTestResNorm_t::Implicit, normType);
698 catch (std::exception& e) {
709 if (maxIterTest_ == Teuchos::null)
713 if (convTest_.is_null () || newResTest) {
716 if (params->isParameter(
"Residual Norm")) {
717 if (params->isType<std::string> (
"Residual Norm")) {
722 convTest_ = rcp (
new StatusTestResNorm_t (convtol_, 1, showMaxResNormOnly_));
723 convTest_->defineResForm(StatusTestResNorm_t::Implicit, normType);
727 if (sTest_.is_null () || newResTest)
728 sTest_ = Teuchos::rcp(
new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
730 if (outputTest_.is_null () || newResTest) {
738 std::string solverDesc =
" Block CG ";
739 outputTest_->setSolverDesc( solverDesc );
744 if (params->isParameter(
"Assert Positive Definiteness")) {
745 assertPositiveDefiniteness_ = Teuchos::getParameter<bool>(*params,
"Assert Positive Definiteness");
746 params_->set(
"Assert Positive Definiteness", assertPositiveDefiniteness_);
750 if (timerSolve_ == Teuchos::null) {
751 std::string solveLabel = label_ +
": BlockCGSolMgr total solve time";
752#ifdef BELOS_TEUCHOS_TIME_MONITOR
753 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
826 using Teuchos::rcp_const_cast;
827 using Teuchos::rcp_dynamic_cast;
834 setParameters(Teuchos::parameterList(*getValidParameters()));
837 Teuchos::LAPACK<int,ScalarType> lapack;
839 TEUCHOS_TEST_FOR_EXCEPTION( !problem_->isProblemSet(),
841 "Belos::BlockCGSolMgr::solve(): Linear problem is not ready, setProblem() "
842 "has not been called.");
846 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
847 int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
849 std::vector<int> currIdx, currIdx2;
854 if ( adaptiveBlockSize_ ) {
855 blockSize_ = numCurrRHS;
856 currIdx.resize( numCurrRHS );
857 currIdx2.resize( numCurrRHS );
858 for (
int i=0; i<numCurrRHS; ++i)
859 { currIdx[i] = startPtr+i; currIdx2[i]=i; }
863 currIdx.resize( blockSize_ );
864 currIdx2.resize( blockSize_ );
865 for (
int i=0; i<numCurrRHS; ++i)
866 { currIdx[i] = startPtr+i; currIdx2[i]=i; }
867 for (
int i=numCurrRHS; i<blockSize_; ++i)
868 { currIdx[i] = -1; currIdx2[i] = i; }
872 problem_->setLSIndex( currIdx );
876 Teuchos::ParameterList plist;
877 plist.set(
"Block Size",blockSize_);
880 outputTest_->reset();
884 bool isConverged =
true;
889 plist.set(
"Assert Positive Definiteness", assertPositiveDefiniteness_);
891 RCP<CGIteration<ScalarType,MV,OP> > block_cg_iter;
892 if (blockSize_ == 1) {
896 plist.set(
"Fold Convergence Detection Into Allreduce",
897 foldConvergenceDetectionIntoAllreduce_);
898 if (useSingleReduction_) {
901 outputTest_, convTest_, plist));
906 outputTest_, convTest_, plist));
917#ifdef BELOS_TEUCHOS_TIME_MONITOR
918 Teuchos::TimeMonitor slvtimer(*timerSolve_);
921 while ( numRHS2Solve > 0 ) {
924 std::vector<int> convRHSIdx;
925 std::vector<int> currRHSIdx( currIdx );
926 currRHSIdx.resize(numCurrRHS);
929 block_cg_iter->resetNumIters();
932 outputTest_->resetNumCalls();
935 RCP<MV> R_0 = MVT::CloneViewNonConst( *(rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
940 block_cg_iter->initializeCG(newstate);
946 block_cg_iter->iterate();
950 if (convTest_->getStatus() ==
Passed) {
955 std::vector<int> convIdx =
956 rcp_dynamic_cast<conv_test_type>(convTest_)->
convIndices();
961 if (convIdx.size() == currRHSIdx.size())
966 problem_->setCurrLS();
971 std::vector<int> unconvIdx(currRHSIdx.size());
972 for (
unsigned int i=0; i<currRHSIdx.size(); ++i) {
974 for (
unsigned int j=0; j<convIdx.size(); ++j) {
975 if (currRHSIdx[i] == convIdx[j]) {
981 currIdx2[have] = currIdx2[i];
982 currRHSIdx[have++] = currRHSIdx[i];
987 currRHSIdx.resize(have);
988 currIdx2.resize(have);
991 problem_->setLSIndex( currRHSIdx );
994 std::vector<MagnitudeType> norms;
995 R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
996 for (
int i=0; i<have; ++i) { currIdx2[i] = i; }
999 block_cg_iter->setBlockSize( have );
1004 block_cg_iter->initializeCG(defstate);
1010 else if (maxIterTest_->getStatus() ==
Passed) {
1011 isConverged =
false;
1019 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
1020 "Belos::BlockCGSolMgr::solve(): Neither the convergence test nor "
1021 "the maximum iteration count test passed. Please report this bug "
1022 "to the Belos developers.");
1025 catch (
const std::exception &e) {
1026 std::ostream& err = printer_->stream (
Errors);
1027 err <<
"Error! Caught std::exception in CGIteration::iterate() at "
1028 <<
"iteration " << block_cg_iter->getNumIters() << std::endl
1029 << e.what() << std::endl;
1036 problem_->setCurrLS();
1039 startPtr += numCurrRHS;
1040 numRHS2Solve -= numCurrRHS;
1041 if ( numRHS2Solve > 0 ) {
1042 numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
1044 if ( adaptiveBlockSize_ ) {
1045 blockSize_ = numCurrRHS;
1046 currIdx.resize( numCurrRHS );
1047 currIdx2.resize( numCurrRHS );
1048 for (
int i=0; i<numCurrRHS; ++i)
1049 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
1052 currIdx.resize( blockSize_ );
1053 currIdx2.resize( blockSize_ );
1054 for (
int i=0; i<numCurrRHS; ++i)
1055 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
1056 for (
int i=numCurrRHS; i<blockSize_; ++i)
1057 { currIdx[i] = -1; currIdx2[i] = i; }
1060 problem_->setLSIndex( currIdx );
1063 block_cg_iter->setBlockSize( blockSize_ );
1066 currIdx.resize( numRHS2Solve );
1077#ifdef BELOS_TEUCHOS_TIME_MONITOR
1083 Teuchos::TimeMonitor::summarize( printer_->stream(
TimingDetails) );
1088 numIters_ = maxIterTest_->getNumIters();
1094 const std::vector<MagnitudeType>* pTestValues =
1095 rcp_dynamic_cast<conv_test_type>(convTest_)->
getTestValue();
1097 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1098 "Belos::BlockCGSolMgr::solve(): The convergence test's getTestValue() "
1099 "method returned NULL. Please report this bug to the Belos developers.");
1101 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1102 "Belos::BlockCGSolMgr::solve(): The convergence test's getTestValue() "
1103 "method returned a vector of length zero. Please report this bug to the "
1104 "Belos developers.");
1109 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());