387 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
389 outputStream_(Teuchos::rcpFromRef(std::cout)),
392 achievedTol_(Teuchos::ScalarTraits<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>::zero()),
393 maxRestarts_(maxRestarts_default_),
394 maxIters_(maxIters_default_),
396 blockSize_(blockSize_default_),
397 numBlocks_(numBlocks_default_),
398 verbosity_(verbosity_default_),
399 outputStyle_(outputStyle_default_),
400 outputFreq_(outputFreq_default_),
401 adaptiveBlockSize_(adaptiveBlockSize_default_),
402 showMaxResNormOnly_(showMaxResNormOnly_default_),
403 isFlexible_(flexibleGmres_default_),
404 expResTest_(expResTest_default_),
405 orthoType_(orthoType_default_),
406 impResScale_(impResScale_default_),
407 expResScale_(expResScale_default_),
408 label_(label_default_),
414 TEUCHOS_TEST_FOR_EXCEPTION(
problem_ == Teuchos::null, std::invalid_argument,
"Problem not given to solver manager.");
417 if ( !is_null(pl) ) {
494 if (params_ == Teuchos::null) {
495 params_ = Teuchos::rcp(
new Teuchos::ParameterList(*getValidParameters()) );
498 params->validateParameters(*getValidParameters());
502 if (params->isParameter(
"Maximum Restarts")) {
503 maxRestarts_ = params->get(
"Maximum Restarts",maxRestarts_default_);
506 params_->set(
"Maximum Restarts", maxRestarts_);
510 if (params->isParameter(
"Maximum Iterations")) {
511 maxIters_ = params->get(
"Maximum Iterations",maxIters_default_);
514 params_->set(
"Maximum Iterations", maxIters_);
515 if (maxIterTest_!=Teuchos::null)
516 maxIterTest_->setMaxIters( maxIters_ );
520 if (params->isParameter(
"Block Size")) {
521 blockSize_ = params->get(
"Block Size",blockSize_default_);
522 TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
523 "Belos::BlockGmresSolMgr: \"Block Size\" must be strictly positive.");
526 params_->set(
"Block Size", blockSize_);
530 if (params->isParameter(
"Adaptive Block Size")) {
531 adaptiveBlockSize_ = params->get(
"Adaptive Block Size",adaptiveBlockSize_default_);
534 params_->set(
"Adaptive Block Size", adaptiveBlockSize_);
538 if (params->isParameter(
"Num Blocks")) {
539 numBlocks_ = params->get(
"Num Blocks",numBlocks_default_);
540 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks_ <= 0, std::invalid_argument,
541 "Belos::BlockGmresSolMgr: \"Num Blocks\" must be strictly positive.");
544 params_->set(
"Num Blocks", numBlocks_);
548 if (params->isParameter(
"Timer Label")) {
549 std::string tempLabel = params->get(
"Timer Label", label_default_);
552 if (tempLabel != label_) {
554 params_->set(
"Timer Label", label_);
555 std::string solveLabel = label_ +
": BlockGmresSolMgr total solve time";
556#ifdef BELOS_TEUCHOS_TIME_MONITOR
557 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
559 if (ortho_ != Teuchos::null) {
560 ortho_->setLabel( label_ );
566 if (params->isParameter(
"Flexible Gmres")) {
567 isFlexible_ = Teuchos::getParameter<bool>(*params,
"Flexible Gmres");
568 params_->set(
"Flexible Gmres", isFlexible_);
569 if (isFlexible_ && expResTest_) {
576 if (params->isParameter(
"Verbosity")) {
577 if (Teuchos::isParameterType<int>(*params,
"Verbosity")) {
578 verbosity_ = params->get(
"Verbosity", verbosity_default_);
580 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,
"Verbosity");
584 params_->set(
"Verbosity", verbosity_);
585 if (printer_ != Teuchos::null)
586 printer_->setVerbosity(verbosity_);
590 if (params->isParameter(
"Output Style")) {
591 if (Teuchos::isParameterType<int>(*params,
"Output Style")) {
592 outputStyle_ = params->get(
"Output Style", outputStyle_default_);
594 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,
"Output Style");
598 params_->set(
"Output Style", outputStyle_);
599 if (outputTest_ != Teuchos::null) {
605 if (params->isParameter(
"Output Stream")) {
606 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,
"Output Stream");
609 params_->set(
"Output Stream", outputStream_);
610 if (printer_ != Teuchos::null)
611 printer_->setOStream( outputStream_ );
616 if (params->isParameter(
"Output Frequency")) {
617 outputFreq_ = params->get(
"Output Frequency", outputFreq_default_);
621 params_->set(
"Output Frequency", outputFreq_);
622 if (outputTest_ != Teuchos::null)
623 outputTest_->setOutputFrequency( outputFreq_ );
627 if (printer_ == Teuchos::null) {
632 bool changedOrthoType =
false;
633 if (params->isParameter(
"Orthogonalization")) {
634 std::string tempOrthoType = params->get(
"Orthogonalization",orthoType_default_);
635 if (tempOrthoType != orthoType_) {
636 orthoType_ = tempOrthoType;
637 changedOrthoType =
true;
640 params_->set(
"Orthogonalization", orthoType_);
643 if (params->isParameter(
"Orthogonalization Constant")) {
644 if (params->isType<
MagnitudeType> (
"Orthogonalization Constant")) {
645 orthoKappa_ = params->get (
"Orthogonalization Constant",
649 orthoKappa_ = params->get (
"Orthogonalization Constant",
654 params_->set(
"Orthogonalization Constant",orthoKappa_);
655 if (orthoType_==
"DGKS") {
656 if (orthoKappa_ > 0 && ortho_ != Teuchos::null && !changedOrthoType) {
657 Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
663 if (ortho_ == Teuchos::null || changedOrthoType) {
665 Teuchos::RCP<Teuchos::ParameterList> paramsOrtho;
666 if (orthoType_==
"DGKS" && orthoKappa_ > 0) {
667 paramsOrtho->set (
"depTol", orthoKappa_ );
670 ortho_ = factory.
makeMatOrthoManager (orthoType_, Teuchos::null, printer_, label_, paramsOrtho);
674 if (params->isParameter(
"Convergence Tolerance")) {
675 if (params->isType<
MagnitudeType> (
"Convergence Tolerance")) {
676 convtol_ = params->get (
"Convergence Tolerance",
684 params_->set(
"Convergence Tolerance", convtol_);
685 if (impConvTest_ != Teuchos::null)
686 impConvTest_->setTolerance( convtol_ );
687 if (expConvTest_ != Teuchos::null)
688 expConvTest_->setTolerance( convtol_ );
692 if (params->isParameter(
"Implicit Residual Scaling")) {
693 std::string tempImpResScale = Teuchos::getParameter<std::string>( *params,
"Implicit Residual Scaling" );
696 if (impResScale_ != tempImpResScale) {
698 impResScale_ = tempImpResScale;
701 params_->set(
"Implicit Residual Scaling", impResScale_);
702 if (impConvTest_ != Teuchos::null) {
706 catch (std::exception& e) {
714 if (params->isParameter(
"Explicit Residual Scaling")) {
715 std::string tempExpResScale = Teuchos::getParameter<std::string>( *params,
"Explicit Residual Scaling" );
718 if (expResScale_ != tempExpResScale) {
720 expResScale_ = tempExpResScale;
723 params_->set(
"Explicit Residual Scaling", expResScale_);
724 if (expConvTest_ != Teuchos::null) {
728 catch (std::exception& e) {
736 if (params->isParameter(
"Explicit Residual Test")) {
737 expResTest_ = Teuchos::getParameter<bool>( *params,
"Explicit Residual Test" );
740 params_->set(
"Explicit Residual Test", expResTest_);
741 if (expConvTest_ == Teuchos::null) {
746 if (params->isParameter(
"Show Maximum Residual Norm Only")) {
747 showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,
"Show Maximum Residual Norm Only");
750 params_->set(
"Show Maximum Residual Norm Only", showMaxResNormOnly_);
751 if (impConvTest_ != Teuchos::null)
752 impConvTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
753 if (expConvTest_ != Teuchos::null)
754 expConvTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
759 if (timerSolve_ == Teuchos::null) {
760 std::string solveLabel = label_ +
": BlockGmresSolMgr total solve time";
761#ifdef BELOS_TEUCHOS_TIME_MONITOR
762 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
784 if (isFlexible_ && Teuchos::is_null(problem_->getRightPrec())) {
786 params_->set(
"Flexible Gmres", isFlexible_);
790 "Belos::BlockGmresSolMgr::solve(): Linear problem has a left preconditioner, not a right preconditioner, which is required for flexible GMRES.");
795 if (!Teuchos::is_null(problem_->getLeftPrec()) && !isFlexible_) {
802 Teuchos::RCP<StatusTestGenResNorm_t> tmpImpConvTest =
803 Teuchos::rcp(
new StatusTestGenResNorm_t( convtol_ ) );
805 tmpImpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
806 impConvTest_ = tmpImpConvTest;
809 Teuchos::RCP<StatusTestGenResNorm_t> tmpExpConvTest =
810 Teuchos::rcp(
new StatusTestGenResNorm_t( convtol_ ) );
811 tmpExpConvTest->defineResForm( StatusTestGenResNorm_t::Explicit,
Belos::TwoNorm );
813 tmpExpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
814 expConvTest_ = tmpExpConvTest;
817 convTest_ = Teuchos::rcp(
new StatusTestCombo_t( StatusTestCombo_t::SEQ, impConvTest_, expConvTest_ ) );
823 Teuchos::RCP<StatusTestGenResNorm_t> tmpImpConvTest =
824 Teuchos::rcp(
new StatusTestGenResNorm_t( convtol_ ) );
826 tmpImpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
827 impConvTest_ = tmpImpConvTest;
832 Teuchos::RCP<StatusTestImpResNorm_t> tmpImpConvTest =
833 Teuchos::rcp(
new StatusTestImpResNorm_t( convtol_ ) );
835 tmpImpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
836 impConvTest_ = tmpImpConvTest;
840 expConvTest_ = impConvTest_;
841 convTest_ = impConvTest_;
845 sTest_ = Teuchos::rcp(
new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
848 if (nonnull(debugStatusTest_) ) {
850 Teuchos::rcp_dynamic_cast<StatusTestCombo_t>(sTest_)->addStatusTest( debugStatusTest_ );
859 std::string solverDesc =
" Block Gmres ";
861 solverDesc =
"Flexible" + solverDesc;
862 outputTest_->setSolverDesc( solverDesc );
887 setParameters(Teuchos::parameterList(*getValidParameters()));
891 "Belos::BlockGmresSolMgr::solve(): Linear problem is not a valid object.");
894 "Belos::BlockGmresSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
896 if (!isSTSet_ || (!expResTest_ && !Teuchos::is_null(problem_->getLeftPrec())) ) {
898 "Belos::BlockGmresSolMgr::solve(): Linear problem and requested status tests are incompatible.");
903 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
904 int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
906 std::vector<int> currIdx;
909 if ( adaptiveBlockSize_ ) {
910 blockSize_ = numCurrRHS;
911 currIdx.resize( numCurrRHS );
912 for (
int i=0; i<numCurrRHS; ++i)
913 { currIdx[i] = startPtr+i; }
917 currIdx.resize( blockSize_ );
918 for (
int i=0; i<numCurrRHS; ++i)
919 { currIdx[i] = startPtr+i; }
920 for (
int i=numCurrRHS; i<blockSize_; ++i)
925 problem_->setLSIndex( currIdx );
929 Teuchos::ParameterList plist;
930 plist.set(
"Block Size",blockSize_);
932 ptrdiff_t dim = MVT::GetGlobalLength( *(problem_->getRHS()) );
933 if (blockSize_*
static_cast<ptrdiff_t
>(numBlocks_) > dim) {
934 int tmpNumBlocks = 0;
936 tmpNumBlocks = dim / blockSize_;
938 tmpNumBlocks = ( dim - blockSize_) / blockSize_;
940 "Belos::BlockGmresSolMgr::solve(): Warning! Requested Krylov subspace dimension is larger than operator dimension!"
941 << std::endl <<
" The maximum number of blocks allowed for the Krylov subspace will be adjusted to " << tmpNumBlocks << std::endl;
942 plist.set(
"Num Blocks",tmpNumBlocks);
945 plist.set(
"Num Blocks",numBlocks_);
948 outputTest_->reset();
949 loaDetected_ =
false;
952 bool isConverged =
true;
957 Teuchos::RCP<GmresIteration<ScalarType,MV,OP> > block_gmres_iter;
966#ifdef BELOS_TEUCHOS_TIME_MONITOR
967 Teuchos::TimeMonitor slvtimer(*timerSolve_);
970 while ( numRHS2Solve > 0 ) {
973 if (blockSize_*numBlocks_ > dim) {
974 int tmpNumBlocks = 0;
976 tmpNumBlocks = dim / blockSize_;
978 tmpNumBlocks = ( dim - blockSize_) / blockSize_;
979 block_gmres_iter->setSize( blockSize_, tmpNumBlocks );
982 block_gmres_iter->setSize( blockSize_, numBlocks_ );
985 block_gmres_iter->resetNumIters();
988 outputTest_->resetNumCalls();
991 Teuchos::RCP<MV> V_0;
994 if (currIdx[blockSize_-1] == -1) {
995 V_0 = MVT::Clone( *(problem_->getInitResVec()), blockSize_ );
996 problem_->computeCurrResVec( &*V_0 );
999 V_0 = MVT::CloneCopy( *(problem_->getInitResVec()), currIdx );
1004 if (currIdx[blockSize_-1] == -1) {
1005 V_0 = MVT::Clone( *(problem_->getInitPrecResVec()), blockSize_ );
1006 problem_->computeCurrPrecResVec( &*V_0 );
1009 V_0 = MVT::CloneCopy( *(problem_->getInitPrecResVec()), currIdx );
1014 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > z_0 =
1015 Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( blockSize_, blockSize_ ) );
1018 int rank = ortho_->normalize( *V_0, z_0 );
1020 "Belos::BlockGmresSolMgr::solve(): Failed to compute initial block of orthonormal vectors.");
1027 block_gmres_iter->initializeGmres(newstate);
1028 int numRestarts = 0;
1033 block_gmres_iter->iterate();
1040 if ( convTest_->getStatus() ==
Passed ) {
1041 if ( expConvTest_->getLOADetected() ) {
1043 loaDetected_ =
true;
1045 "Belos::BlockGmresSolMgr::solve(): Warning! Solver has experienced a loss of accuracy!" << std::endl;
1046 isConverged =
false;
1055 else if ( maxIterTest_->getStatus() ==
Passed ) {
1057 isConverged =
false;
1065 else if ( block_gmres_iter->getCurSubspaceDim() == block_gmres_iter->getMaxSubspaceDim() ) {
1067 if ( numRestarts >= maxRestarts_ ) {
1068 isConverged =
false;
1073 printer_->stream(
Debug) <<
" Performing restart number " << numRestarts <<
" of " << maxRestarts_ << std::endl << std::endl;
1076 Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
1079 Teuchos::RCP<MV> curX = problem_->getCurrLHSVec();
1080 MVT::MvAddMv( 1.0, *curX, 1.0, *update, *curX );
1083 problem_->updateSolution( update,
true );
1090 V_0 = MVT::Clone( *(oldState.
V), blockSize_ );
1092 problem_->computeCurrResVec( &*V_0 );
1094 problem_->computeCurrPrecResVec( &*V_0 );
1097 z_0 = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( blockSize_, blockSize_ ) );
1100 rank = ortho_->normalize( *V_0, z_0 );
1102 "Belos::BlockGmresSolMgr::solve(): Failed to compute initial block of orthonormal vectors after restart.");
1108 block_gmres_iter->initializeGmres(newstate);
1120 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
1121 "Belos::BlockGmresSolMgr::solve(): Invalid return from BlockGmresIter::iterate().");
1126 if (blockSize_ != 1) {
1127 printer_->stream(
Errors) <<
"Error! Caught std::exception in BlockGmresIter::iterate() at iteration "
1128 << block_gmres_iter->getNumIters() << std::endl
1129 << e.what() << std::endl;
1130 if (convTest_->getStatus() !=
Passed)
1131 isConverged =
false;
1136 block_gmres_iter->updateLSQR( block_gmres_iter->getCurSubspaceDim() );
1139 sTest_->checkStatus( &*block_gmres_iter );
1140 if (convTest_->getStatus() !=
Passed)
1141 isConverged =
false;
1145 catch (
const std::exception &e) {
1146 printer_->stream(
Errors) <<
"Error! Caught std::exception in BlockGmresIter::iterate() at iteration "
1147 << block_gmres_iter->getNumIters() << std::endl
1148 << e.what() << std::endl;
1157 Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
1158 Teuchos::RCP<MV> curX = problem_->getCurrLHSVec();
1160 if (update != Teuchos::null)
1161 MVT::MvAddMv( 1.0, *curX, 1.0, *update, *curX );
1165 if ( !Teuchos::is_null(expConvTest_->getSolution()) ) {
1166 Teuchos::RCP<MV> newX = expConvTest_->getSolution();
1167 Teuchos::RCP<MV> curX = problem_->getCurrLHSVec();
1168 MVT::MvAddMv( 0.0, *newX, 1.0, *newX, *curX );
1171 Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
1172 problem_->updateSolution( update,
true );
1177 problem_->setCurrLS();
1180 startPtr += numCurrRHS;
1181 numRHS2Solve -= numCurrRHS;
1182 if ( numRHS2Solve > 0 ) {
1183 numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
1185 if ( adaptiveBlockSize_ ) {
1186 blockSize_ = numCurrRHS;
1187 currIdx.resize( numCurrRHS );
1188 for (
int i=0; i<numCurrRHS; ++i)
1189 { currIdx[i] = startPtr+i; }
1192 currIdx.resize( blockSize_ );
1193 for (
int i=0; i<numCurrRHS; ++i)
1194 { currIdx[i] = startPtr+i; }
1195 for (
int i=numCurrRHS; i<blockSize_; ++i)
1196 { currIdx[i] = -1; }
1199 problem_->setLSIndex( currIdx );
1202 currIdx.resize( numRHS2Solve );
1213#ifdef BELOS_TEUCHOS_TIME_MONITOR
1218 Teuchos::TimeMonitor::summarize( printer_->stream(
TimingDetails) );
1222 numIters_ = maxIterTest_->getNumIters();
1236 const std::vector<MagnitudeType>* pTestValues = NULL;
1238 pTestValues = expConvTest_->getTestValue();
1239 if (pTestValues == NULL || pTestValues->size() < 1) {
1240 pTestValues = impConvTest_->getTestValue();
1245 pTestValues = impConvTest_->getTestValue();
1247 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1248 "Belos::BlockGmresSolMgr::solve(): The implicit convergence test's "
1249 "getTestValue() method returned NULL. Please report this bug to the "
1250 "Belos developers.");
1251 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1252 "Belos::BlockGmresSolMgr::solve(): The implicit convergence test's "
1253 "getTestValue() method returned a vector of length zero. Please report "
1254 "this bug to the Belos developers.");
1259 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
1262 if (!isConverged || loaDetected_) {