42 #ifndef BELOS_PSEUDO_BLOCK_TFQMR_SOLMGR_HPP
43 #define BELOS_PSEUDO_BLOCK_TFQMR_SOLMGR_HPP
61 #ifdef BELOS_TEUCHOS_TIME_MONITOR
62 #include "Teuchos_TimeMonitor.hpp"
103 template<
class ScalarType,
class MV,
class OP>
109 typedef Teuchos::ScalarTraits<ScalarType> SCT;
110 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
111 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
142 const Teuchos::RCP<Teuchos::ParameterList> &pl );
148 Teuchos::RCP<SolverManager<ScalarType, MV, OP> >
clone ()
const override {
173 Teuchos::Array<Teuchos::RCP<Teuchos::Time> >
getTimers()
const {
174 return Teuchos::tuple(timerSolve_);
208 void setParameters(
const Teuchos::RCP<Teuchos::ParameterList> ¶ms )
override;
254 bool checkStatusTest();
257 Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
260 Teuchos::RCP<OutputManager<ScalarType> > printer_;
261 Teuchos::RCP<std::ostream> outputStream_;
264 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
265 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
266 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > convTest_;
267 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > expConvTest_, impConvTest_;
268 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
271 Teuchos::RCP<Teuchos::ParameterList> params_;
274 static constexpr
int maxIters_default_ = 1000;
275 static constexpr
bool expResTest_default_ =
false;
278 static constexpr
int outputFreq_default_ = -1;
279 static constexpr
int defQuorum_default_ = 1;
280 static constexpr
const char * impResScale_default_ =
"Norm of Preconditioned Initial Residual";
281 static constexpr
const char * expResScale_default_ =
"Norm of Initial Residual";
282 static constexpr
const char * label_default_ =
"Belos";
283 static constexpr std::ostream * outputStream_default_ = &std::cout;
286 MagnitudeType convtol_, impTolScale_, achievedTol_;
287 int maxIters_, numIters_;
288 int verbosity_, outputStyle_, outputFreq_, defQuorum_;
290 std::string impResScale_, expResScale_;
294 Teuchos::RCP<Teuchos::Time> timerSolve_;
297 bool isSet_, isSTSet_;
302 template<
class ScalarType,
class MV,
class OP>
304 outputStream_(Teuchos::rcp(outputStream_default_,false)),
307 achievedTol_(Teuchos::ScalarTraits<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>::zero()),
308 maxIters_(maxIters_default_),
310 verbosity_(verbosity_default_),
311 outputStyle_(outputStyle_default_),
312 outputFreq_(outputFreq_default_),
313 defQuorum_(defQuorum_default_),
314 expResTest_(expResTest_default_),
315 impResScale_(impResScale_default_),
316 expResScale_(expResScale_default_),
317 label_(label_default_),
324 template<
class ScalarType,
class MV,
class OP>
327 const Teuchos::RCP<Teuchos::ParameterList> &pl ) :
329 outputStream_(Teuchos::rcp(outputStream_default_,false)),
332 achievedTol_(Teuchos::ScalarTraits<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>::zero()),
333 maxIters_(maxIters_default_),
335 verbosity_(verbosity_default_),
336 outputStyle_(outputStyle_default_),
337 outputFreq_(outputFreq_default_),
338 defQuorum_(defQuorum_default_),
339 expResTest_(expResTest_default_),
340 impResScale_(impResScale_default_),
341 expResScale_(expResScale_default_),
342 label_(label_default_),
346 TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument,
"Problem not given to solver manager.");
349 if ( !is_null(pl) ) {
354 template<
class ScalarType,
class MV,
class OP>
358 if (params_ == Teuchos::null) {
359 params_ = Teuchos::rcp(
new Teuchos::ParameterList(*getValidParameters()) );
362 params->validateParameters(*getValidParameters());
366 if (params->isParameter(
"Maximum Iterations")) {
367 maxIters_ = params->get(
"Maximum Iterations",maxIters_default_);
370 params_->set(
"Maximum Iterations", maxIters_);
371 if (maxIterTest_!=Teuchos::null)
372 maxIterTest_->setMaxIters( maxIters_ );
376 if (params->isParameter(
"Timer Label")) {
377 std::string tempLabel = params->get(
"Timer Label", label_default_);
380 if (tempLabel != label_) {
382 params_->set(
"Timer Label", label_);
383 std::string solveLabel = label_ +
": PseudoBlockTFQMRSolMgr total solve time";
384 #ifdef BELOS_TEUCHOS_TIME_MONITOR
385 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
391 if (params->isParameter(
"Verbosity")) {
392 if (Teuchos::isParameterType<int>(*params,
"Verbosity")) {
393 verbosity_ = params->get(
"Verbosity", verbosity_default_);
395 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,
"Verbosity");
399 params_->set(
"Verbosity", verbosity_);
400 if (printer_ != Teuchos::null)
401 printer_->setVerbosity(verbosity_);
405 if (params->isParameter(
"Output Style")) {
406 if (Teuchos::isParameterType<int>(*params,
"Output Style")) {
407 outputStyle_ = params->get(
"Output Style", outputStyle_default_);
409 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,
"Output Style");
413 params_->set(
"Output Style", outputStyle_);
418 if (params->isParameter(
"Output Stream")) {
419 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,
"Output Stream");
422 params_->set(
"Output Stream", outputStream_);
423 if (printer_ != Teuchos::null)
424 printer_->setOStream( outputStream_ );
429 if (params->isParameter(
"Output Frequency")) {
430 outputFreq_ = params->get(
"Output Frequency", outputFreq_default_);
434 params_->set(
"Output Frequency", outputFreq_);
435 if (outputTest_ != Teuchos::null)
436 outputTest_->setOutputFrequency( outputFreq_ );
440 if (printer_ == Teuchos::null) {
445 if (params->isParameter(
"Convergence Tolerance")) {
446 if (params->isType<MagnitudeType> (
"Convergence Tolerance")) {
447 convtol_ = params->get (
"Convergence Tolerance",
455 params_->set(
"Convergence Tolerance", convtol_);
459 if (params->isParameter(
"Implicit Tolerance Scale Factor")) {
460 if (params->isType<MagnitudeType> (
"Implicit Tolerance Scale Factor")) {
461 impTolScale_ = params->get (
"Implicit Tolerance Scale Factor",
466 impTolScale_ = params->get (
"Implicit Tolerance Scale Factor",
471 params_->set(
"Implicit Tolerance Scale Factor", impTolScale_);
475 if (params->isParameter(
"Implicit Residual Scaling")) {
476 std::string tempImpResScale = Teuchos::getParameter<std::string>( *params,
"Implicit Residual Scaling" );
479 if (impResScale_ != tempImpResScale) {
480 impResScale_ = tempImpResScale;
483 params_->set(
"Implicit Residual Scaling", impResScale_);
488 if (params->isParameter(
"Explicit Residual Scaling")) {
489 std::string tempExpResScale = Teuchos::getParameter<std::string>( *params,
"Explicit Residual Scaling" );
492 if (expResScale_ != tempExpResScale) {
493 expResScale_ = tempExpResScale;
496 params_->set(
"Explicit Residual Scaling", expResScale_);
501 if (params->isParameter(
"Explicit Residual Test")) {
502 expResTest_ = Teuchos::getParameter<bool>( *params,
"Explicit Residual Test" );
505 params_->set(
"Explicit Residual Test", expResTest_);
506 if (expConvTest_ == Teuchos::null) {
512 if (params->isParameter(
"Deflation Quorum")) {
513 defQuorum_ = params->get(
"Deflation Quorum", defQuorum_);
514 params_->set (
"Deflation Quorum", defQuorum_);
515 if (! impConvTest_.is_null ()) {
516 impConvTest_->setQuorum (defQuorum_);
518 if (! expConvTest_.is_null ()) {
519 expConvTest_->setQuorum (defQuorum_);
524 if (timerSolve_ == Teuchos::null) {
525 std::string solveLabel = label_ +
": PseudoBlockTFQMRSolMgr total solve time";
526 #ifdef BELOS_TEUCHOS_TIME_MONITOR
527 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
537 template<
class ScalarType,
class MV,
class OP>
549 Teuchos::RCP<StatusTestGenResNorm_t> tmpImpConvTest =
550 Teuchos::rcp(
new StatusTestGenResNorm_t( impTolScale_*convtol_, defQuorum_ ) );
552 impConvTest_ = tmpImpConvTest;
555 Teuchos::RCP<StatusTestGenResNorm_t> tmpExpConvTest =
556 Teuchos::rcp(
new StatusTestGenResNorm_t( convtol_, defQuorum_ ) );
557 tmpExpConvTest->defineResForm( StatusTestGenResNorm_t::Explicit,
Belos::TwoNorm );
559 expConvTest_ = tmpExpConvTest;
562 convTest_ = Teuchos::rcp(
new StatusTestCombo_t( StatusTestCombo_t::SEQ, impConvTest_, expConvTest_ ) );
567 Teuchos::RCP<StatusTestGenResNorm_t> tmpImpConvTest =
568 Teuchos::rcp(
new StatusTestGenResNorm_t( convtol_, defQuorum_ ) );
570 impConvTest_ = tmpImpConvTest;
573 expConvTest_ = impConvTest_;
574 convTest_ = impConvTest_;
576 sTest_ = Teuchos::rcp(
new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
580 StatusTestOutputFactory<ScalarType,MV,OP> stoFactory( outputStyle_ );
584 std::string solverDesc =
" Pseudo Block TFQMR ";
585 outputTest_->setSolverDesc( solverDesc );
595 template<
class ScalarType,
class MV,
class OP>
596 Teuchos::RCP<const Teuchos::ParameterList>
599 static Teuchos::RCP<const Teuchos::ParameterList> validPL;
602 if(is_null(validPL)) {
603 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
608 "The relative residual tolerance that needs to be achieved by the\n"
609 "iterative solver in order for the linear system to be declared converged.");
611 "The scale factor used by the implicit residual test when explicit residual\n"
612 "testing is used. May enable faster convergence when TFQMR bound is too loose.");
613 pl->set(
"Maximum Iterations", static_cast<int>(maxIters_default_),
614 "The maximum number of block iterations allowed for each\n"
615 "set of RHS solved.");
616 pl->set(
"Verbosity", static_cast<int>(verbosity_default_),
617 "What type(s) of solver information should be outputted\n"
618 "to the output stream.");
619 pl->set(
"Output Style", static_cast<int>(outputStyle_default_),
620 "What style is used for the solver information outputted\n"
621 "to the output stream.");
622 pl->set(
"Output Frequency", static_cast<int>(outputFreq_default_),
623 "How often convergence information should be outputted\n"
624 "to the output stream.");
625 pl->set(
"Deflation Quorum", static_cast<int>(defQuorum_default_),
626 "The number of linear systems that need to converge before they are deflated.");
627 pl->set(
"Output Stream", Teuchos::rcp(outputStream_default_,
false),
628 "A reference-counted pointer to the output stream where all\n"
629 "solver output is sent.");
630 pl->set(
"Explicit Residual Test", static_cast<bool>(expResTest_default_),
631 "Whether the explicitly computed residual should be used in the convergence test.");
632 pl->set(
"Implicit Residual Scaling", static_cast<const char *>(impResScale_default_),
633 "The type of scaling used in the implicit residual convergence test.");
634 pl->set(
"Explicit Residual Scaling", static_cast<const char *>(expResScale_default_),
635 "The type of scaling used in the explicit residual convergence test.");
636 pl->set(
"Timer Label", static_cast<const char *>(label_default_),
637 "The string to use as a prefix for the timer labels.");
645 template<
class ScalarType,
class MV,
class OP>
652 setParameters(Teuchos::parameterList(*getValidParameters()));
656 "Belos::PseudoBlockTFQMRSolMgr::solve(): Linear problem is not a valid object.");
659 "Belos::PseudoBlockTFQMRSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
663 "Belos::PseudoBlockTFQMRSolMgr::solve(): Linear problem and requested status tests are incompatible.");
668 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
669 int numCurrRHS = numRHS2Solve;
671 std::vector<int> currIdx( numRHS2Solve );
672 for (
int i=0; i<numRHS2Solve; ++i) {
673 currIdx[i] = startPtr+i;
677 problem_->setLSIndex( currIdx );
681 Teuchos::ParameterList plist;
684 outputTest_->reset();
687 bool isConverged =
true;
692 Teuchos::RCP<PseudoBlockTFQMRIter<ScalarType,MV,OP> > block_tfqmr_iter =
697 #ifdef BELOS_TEUCHOS_TIME_MONITOR
698 Teuchos::TimeMonitor slvtimer(*timerSolve_);
701 while ( numRHS2Solve > 0 ) {
704 std::vector<int> convRHSIdx;
705 std::vector<int> currRHSIdx( currIdx );
706 currRHSIdx.resize(numCurrRHS);
709 block_tfqmr_iter->resetNumIters();
712 outputTest_->resetNumCalls();
715 Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitPrecResVec())), currIdx );
720 block_tfqmr_iter->initializeTFQMR(newstate);
726 block_tfqmr_iter->iterate();
733 if ( convTest_->getStatus() ==
Passed ) {
736 std::vector<int> convIdx = expConvTest_->convIndices();
740 if (convIdx.size() == currRHSIdx.size())
744 problem_->updateSolution( block_tfqmr_iter->getCurrentUpdate(), true );
747 problem_->setCurrLS();
751 std::vector<int> unconvIdx( currRHSIdx.size() );
752 for (
unsigned int i=0; i<currRHSIdx.size(); ++i) {
754 for (
unsigned int j=0; j<convIdx.size(); ++j) {
755 if (currRHSIdx[i] == convIdx[j]) {
762 currRHSIdx[have++] = currRHSIdx[i];
765 unconvIdx.resize(have);
766 currRHSIdx.resize(have);
769 problem_->setLSIndex( currRHSIdx );
779 defstate.
Rtilde = MVT::CloneView( *currentState.
Rtilde, unconvIdx);
780 defstate.
U = MVT::CloneView( *currentState.
U, unconvIdx );
781 defstate.
AU = MVT::CloneView( *currentState.
AU, unconvIdx );
782 defstate.
V = MVT::CloneView( *currentState.
V, unconvIdx );
783 defstate.
W = MVT::CloneView( *currentState.
W, unconvIdx );
784 defstate.
D = MVT::CloneView( *currentState.
D, unconvIdx );
787 for (std::vector<int>::iterator uIter = unconvIdx.begin(); uIter != unconvIdx.end(); uIter++)
789 defstate.
alpha.push_back( currentState.
alpha[ *uIter ] );
790 defstate.
eta.push_back( currentState.
eta[ *uIter ] );
791 defstate.
rho.push_back( currentState.
rho[ *uIter ] );
792 defstate.
tau.push_back( currentState.
tau[ *uIter ] );
793 defstate.
theta.push_back( currentState.
theta[ *uIter ] );
796 block_tfqmr_iter->initializeTFQMR(defstate);
803 else if ( maxIterTest_->getStatus() ==
Passed ) {
817 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
818 "Belos::PseudoBlockTFQMRSolMgr::solve(): Invalid return from PseudoBlockTFQMRIter::iterate().");
821 catch (
const std::exception &e) {
822 printer_->stream(
Errors) <<
"Error! Caught std::exception in PseudoBlockTFQMRIter::iterate() at iteration "
823 << block_tfqmr_iter->getNumIters() << std::endl
824 << e.what() << std::endl;
830 problem_->updateSolution( block_tfqmr_iter->getCurrentUpdate(), true );
833 problem_->setCurrLS();
836 startPtr += numCurrRHS;
837 numRHS2Solve -= numCurrRHS;
838 if ( numRHS2Solve > 0 ) {
839 numCurrRHS = numRHS2Solve;
840 currIdx.resize( numCurrRHS );
841 for (
int i=0; i<numCurrRHS; ++i)
842 { currIdx[i] = startPtr+i; }
845 if (defQuorum_ > numCurrRHS) {
846 if (impConvTest_ != Teuchos::null)
847 impConvTest_->setQuorum( numCurrRHS );
848 if (expConvTest_ != Teuchos::null)
849 expConvTest_->setQuorum( numCurrRHS );
853 problem_->setLSIndex( currIdx );
856 currIdx.resize( numRHS2Solve );
867 #ifdef BELOS_TEUCHOS_TIME_MONITOR
872 Teuchos::TimeMonitor::summarize( printer_->stream(
TimingDetails) );
876 numIters_ = maxIterTest_->getNumIters();
889 const std::vector<MagnitudeType>* pTestValues = NULL;
891 pTestValues = expConvTest_->getTestValue();
892 if (pTestValues == NULL || pTestValues->size() < 1) {
893 pTestValues = impConvTest_->getTestValue();
898 pTestValues = impConvTest_->getTestValue();
900 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
901 "Belos::PseudoBlockTFQMRSolMgr::solve(): The implicit convergence test's "
902 "getTestValue() method returned NULL. Please report this bug to the "
903 "Belos developers.");
904 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
905 "Belos::TMQMRSolMgr::solve(): The implicit convergence test's "
906 "getTestValue() method returned a vector of length zero. Please report "
907 "this bug to the Belos developers.");
912 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
922 template<
class ScalarType,
class MV,
class OP>
925 std::ostringstream oss;
926 oss <<
"Belos::PseudoBlockTFQMRSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<
">";