42 #ifndef BELOS_PSEUDO_BLOCK_CG_SOLMGR_HPP
43 #define BELOS_PSEUDO_BLOCK_CG_SOLMGR_HPP
63 #include "Teuchos_BLAS.hpp"
64 #include "Teuchos_LAPACK.hpp"
65 #ifdef BELOS_TEUCHOS_TIME_MONITOR
66 #include "Teuchos_TimeMonitor.hpp"
113 template<
class ScalarType,
class MV,
class OP,
114 const bool supportsScalarType =
118 Belos::Details::LapackSupportsScalar<ScalarType>::value>
120 static const bool scalarTypeIsSupported =
130 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
135 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> >
140 template<
class ScalarType,
class MV,
class OP>
147 typedef Teuchos::ScalarTraits<ScalarType> SCT;
148 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
149 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
179 const Teuchos::RCP<Teuchos::ParameterList> &pl );
185 Teuchos::RCP<SolverManager<ScalarType, MV, OP> >
clone ()
const override {
199 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters()
const override;
210 Teuchos::Array<Teuchos::RCP<Teuchos::Time> >
getTimers()
const {
211 return Teuchos::tuple(timerSolve_);
245 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> >
257 void setParameters(
const Teuchos::RCP<Teuchos::ParameterList> ¶ms )
override;
298 std::string description()
const override;
303 void compute_condnum_tridiag_sym(Teuchos::ArrayView<MagnitudeType> diag,
304 Teuchos::ArrayView<MagnitudeType> offdiag,
305 ScalarType & lambda_min,
306 ScalarType & lambda_max,
307 ScalarType & ConditionNumber );
310 Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
313 Teuchos::RCP<OutputManager<ScalarType> > printer_;
314 Teuchos::RCP<std::ostream> outputStream_;
317 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
318 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
319 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > convTest_;
320 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
323 Teuchos::RCP<Teuchos::ParameterList> params_;
330 mutable Teuchos::RCP<const Teuchos::ParameterList> validParams_;
333 static constexpr
int maxIters_default_ = 1000;
334 static constexpr
bool assertPositiveDefiniteness_default_ =
true;
335 static constexpr
bool showMaxResNormOnly_default_ =
false;
338 static constexpr
int outputFreq_default_ = -1;
339 static constexpr
int defQuorum_default_ = 1;
340 static constexpr
const char * resScale_default_ =
"Norm of Initial Residual";
341 static constexpr
const char * label_default_ =
"Belos";
342 static constexpr std::ostream * outputStream_default_ = &std::cout;
343 static constexpr
bool genCondEst_default_ =
false;
346 MagnitudeType convtol_,achievedTol_;
347 int maxIters_, numIters_;
348 int verbosity_, outputStyle_, outputFreq_, defQuorum_;
349 bool assertPositiveDefiniteness_, showMaxResNormOnly_;
350 std::string resScale_;
352 ScalarType condEstimate_;
356 Teuchos::RCP<Teuchos::Time> timerSolve_;
364 template<
class ScalarType,
class MV,
class OP>
366 outputStream_(Teuchos::rcp(outputStream_default_,false)),
368 maxIters_(maxIters_default_),
370 verbosity_(verbosity_default_),
371 outputStyle_(outputStyle_default_),
372 outputFreq_(outputFreq_default_),
373 defQuorum_(defQuorum_default_),
374 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
375 showMaxResNormOnly_(showMaxResNormOnly_default_),
376 resScale_(resScale_default_),
377 genCondEst_(genCondEst_default_),
378 condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
379 label_(label_default_),
384 template<
class ScalarType,
class MV,
class OP>
387 const Teuchos::RCP<Teuchos::ParameterList> &pl ) :
389 outputStream_(Teuchos::rcp(outputStream_default_,false)),
391 maxIters_(maxIters_default_),
393 verbosity_(verbosity_default_),
394 outputStyle_(outputStyle_default_),
395 outputFreq_(outputFreq_default_),
396 defQuorum_(defQuorum_default_),
397 assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
398 showMaxResNormOnly_(showMaxResNormOnly_default_),
399 resScale_(resScale_default_),
400 genCondEst_(genCondEst_default_),
401 condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
402 label_(label_default_),
405 TEUCHOS_TEST_FOR_EXCEPTION(
406 problem_.is_null (), std::invalid_argument,
407 "Belos::PseudoBlockCGSolMgr two-argument constructor: "
408 "'problem' is null. You must supply a non-null Belos::LinearProblem "
409 "instance when calling this constructor.");
411 if (! pl.is_null ()) {
417 template<
class ScalarType,
class MV,
class OP>
422 using Teuchos::ParameterList;
423 using Teuchos::parameterList;
427 RCP<const ParameterList> defaultParams = this->getValidParameters ();
446 if (params_.is_null ()) {
448 params_ = parameterList (defaultParams->name ());
450 params->validateParameters (*defaultParams);
454 if (params->isParameter (
"Maximum Iterations")) {
455 maxIters_ = params->get (
"Maximum Iterations", maxIters_default_);
458 params_->set (
"Maximum Iterations", maxIters_);
459 if (! maxIterTest_.is_null ()) {
460 maxIterTest_->setMaxIters (maxIters_);
465 if (params->isParameter (
"Assert Positive Definiteness")) {
466 assertPositiveDefiniteness_ =
467 params->get (
"Assert Positive Definiteness",
468 assertPositiveDefiniteness_default_);
471 params_->set (
"Assert Positive Definiteness", assertPositiveDefiniteness_);
475 if (params->isParameter (
"Timer Label")) {
476 const std::string tempLabel = params->get (
"Timer Label", label_default_);
479 if (tempLabel != label_) {
481 params_->set (
"Timer Label", label_);
482 const std::string solveLabel =
483 label_ +
": PseudoBlockCGSolMgr total solve time";
484 #ifdef BELOS_TEUCHOS_TIME_MONITOR
485 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
491 if (params->isParameter (
"Verbosity")) {
492 if (Teuchos::isParameterType<int> (*params,
"Verbosity")) {
493 verbosity_ = params->get (
"Verbosity", verbosity_default_);
495 verbosity_ = (int) Teuchos::getParameter<Belos::MsgType> (*params,
"Verbosity");
499 params_->set (
"Verbosity", verbosity_);
500 if (! printer_.is_null ()) {
501 printer_->setVerbosity (verbosity_);
506 if (params->isParameter (
"Output Style")) {
507 if (Teuchos::isParameterType<int> (*params,
"Output Style")) {
508 outputStyle_ = params->get (
"Output Style", outputStyle_default_);
511 outputStyle_ = (int) Teuchos::getParameter<Belos::OutputType> (*params,
"Output Style");
516 params_->set (
"Output Style", outputStyle_);
517 outputTest_ = Teuchos::null;
521 if (params->isParameter (
"Output Stream")) {
522 outputStream_ = params->get<RCP<std::ostream> > (
"Output Stream");
525 params_->set (
"Output Stream", outputStream_);
526 if (! printer_.is_null ()) {
527 printer_->setOStream (outputStream_);
533 if (params->isParameter (
"Output Frequency")) {
534 outputFreq_ = params->get (
"Output Frequency", outputFreq_default_);
538 params_->set (
"Output Frequency", outputFreq_);
539 if (! outputTest_.is_null ()) {
540 outputTest_->setOutputFrequency (outputFreq_);
545 if (params->isParameter (
"Estimate Condition Number")) {
546 genCondEst_ = params->get (
"Estimate Condition Number", genCondEst_default_);
550 if (printer_.is_null ()) {
559 if (params->isParameter (
"Convergence Tolerance")) {
560 if (params->isType<MagnitudeType> (
"Convergence Tolerance")) {
561 convtol_ = params->get (
"Convergence Tolerance",
569 params_->set (
"Convergence Tolerance", convtol_);
570 if (! convTest_.is_null ()) {
575 if (params->isParameter (
"Show Maximum Residual Norm Only")) {
576 showMaxResNormOnly_ = params->get<
bool> (
"Show Maximum Residual Norm Only");
579 params_->set (
"Show Maximum Residual Norm Only", showMaxResNormOnly_);
580 if (! convTest_.is_null ()) {
581 convTest_->setShowMaxResNormOnly (showMaxResNormOnly_);
586 bool newResTest =
false;
591 std::string tempResScale = resScale_;
592 bool implicitResidualScalingName =
false;
593 if (params->isParameter (
"Residual Scaling")) {
594 tempResScale = params->get<std::string> (
"Residual Scaling");
596 else if (params->isParameter (
"Implicit Residual Scaling")) {
597 tempResScale = params->get<std::string> (
"Implicit Residual Scaling");
598 implicitResidualScalingName =
true;
602 if (resScale_ != tempResScale) {
605 resScale_ = tempResScale;
609 if (implicitResidualScalingName) {
610 params_->set (
"Implicit Residual Scaling", resScale_);
613 params_->set (
"Residual Scaling", resScale_);
616 if (! convTest_.is_null ()) {
620 catch (std::exception& e) {
629 if (params->isParameter (
"Deflation Quorum")) {
630 defQuorum_ = params->get (
"Deflation Quorum", defQuorum_);
631 params_->set (
"Deflation Quorum", defQuorum_);
632 if (! convTest_.is_null ()) {
633 convTest_->setQuorum( defQuorum_ );
640 if (maxIterTest_.is_null ()) {
645 if (convTest_.is_null () || newResTest) {
646 convTest_ = rcp (
new StatusTestResNorm_t (convtol_, defQuorum_, showMaxResNormOnly_));
650 if (sTest_.is_null () || newResTest) {
651 sTest_ = rcp (
new StatusTestCombo_t (StatusTestCombo_t::OR, maxIterTest_, convTest_));
654 if (outputTest_.is_null () || newResTest) {
658 outputTest_ = stoFactory.
create (printer_, sTest_, outputFreq_,
662 const std::string solverDesc =
" Pseudo Block CG ";
663 outputTest_->setSolverDesc (solverDesc);
667 if (timerSolve_.is_null ()) {
668 const std::string solveLabel =
669 label_ +
": PseudoBlockCGSolMgr total solve time";
670 #ifdef BELOS_TEUCHOS_TIME_MONITOR
671 timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
680 template<
class ScalarType,
class MV,
class OP>
681 Teuchos::RCP<const Teuchos::ParameterList>
684 using Teuchos::ParameterList;
685 using Teuchos::parameterList;
688 if (validParams_.is_null()) {
690 RCP<ParameterList> pl = parameterList ();
692 "The relative residual tolerance that needs to be achieved by the\n"
693 "iterative solver in order for the linear system to be declared converged.");
694 pl->set(
"Maximum Iterations", static_cast<int>(maxIters_default_),
695 "The maximum number of block iterations allowed for each\n"
696 "set of RHS solved.");
697 pl->set(
"Assert Positive Definiteness", static_cast<bool>(assertPositiveDefiniteness_default_),
698 "Whether or not to assert that the linear operator\n"
699 "and the preconditioner are indeed positive definite.");
700 pl->set(
"Verbosity", static_cast<int>(verbosity_default_),
701 "What type(s) of solver information should be outputted\n"
702 "to the output stream.");
703 pl->set(
"Output Style", static_cast<int>(outputStyle_default_),
704 "What style is used for the solver information outputted\n"
705 "to the output stream.");
706 pl->set(
"Output Frequency", static_cast<int>(outputFreq_default_),
707 "How often convergence information should be outputted\n"
708 "to the output stream.");
709 pl->set(
"Deflation Quorum", static_cast<int>(defQuorum_default_),
710 "The number of linear systems that need to converge before\n"
711 "they are deflated. This number should be <= block size.");
712 pl->set(
"Output Stream", Teuchos::rcp(outputStream_default_,
false),
713 "A reference-counted pointer to the output stream where all\n"
714 "solver output is sent.");
715 pl->set(
"Show Maximum Residual Norm Only", static_cast<bool>(showMaxResNormOnly_default_),
716 "When convergence information is printed, only show the maximum\n"
717 "relative residual norm when the block size is greater than one.");
718 pl->set(
"Implicit Residual Scaling", resScale_default_,
719 "The type of scaling used in the residual convergence test.");
720 pl->set(
"Estimate Condition Number", static_cast<bool>(genCondEst_default_),
721 "Whether or not to estimate the condition number of the preconditioned system.");
727 pl->set(
"Residual Scaling", resScale_default_,
728 "The type of scaling used in the residual convergence test. This "
729 "name is deprecated; the new name is \"Implicit Residual Scaling\".");
730 pl->set(
"Timer Label", static_cast<const char *>(label_default_),
731 "The string to use as a prefix for the timer labels.");
739 template<
class ScalarType,
class MV,
class OP>
742 const char prefix[] =
"Belos::PseudoBlockCGSolMgr::solve: ";
747 if (!isSet_) { setParameters( params_ ); }
749 Teuchos::BLAS<int,ScalarType> blas;
751 TEUCHOS_TEST_FOR_EXCEPTION
753 prefix <<
"The linear problem to solve is not ready. You must call "
754 "setProblem() on the Belos::LinearProblem instance before telling the "
755 "Belos solver to solve it.");
759 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
760 int numCurrRHS = numRHS2Solve;
762 std::vector<int> currIdx( numRHS2Solve ), currIdx2( numRHS2Solve );
763 for (
int i=0; i<numRHS2Solve; ++i) {
764 currIdx[i] = startPtr+i;
769 problem_->setLSIndex( currIdx );
773 Teuchos::ParameterList plist;
775 plist.set(
"Assert Positive Definiteness",assertPositiveDefiniteness_);
776 if(genCondEst_) plist.set(
"Max Size For Condest",maxIters_);
779 outputTest_->reset();
782 bool isConverged =
true;
786 Teuchos::RCP<CGIteration<ScalarType,MV,OP> > block_cg_iter;
787 if (numRHS2Solve == 1) {
798 #ifdef BELOS_TEUCHOS_TIME_MONITOR
799 Teuchos::TimeMonitor slvtimer(*timerSolve_);
802 bool first_time=
true;
803 while ( numRHS2Solve > 0 ) {
804 if(genCondEst_ && first_time) block_cg_iter->setDoCondEst(
true);
805 else block_cg_iter->setDoCondEst(
false);
808 std::vector<int> convRHSIdx;
809 std::vector<int> currRHSIdx( currIdx );
810 currRHSIdx.resize(numCurrRHS);
813 block_cg_iter->resetNumIters();
816 outputTest_->resetNumCalls();
819 Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
824 block_cg_iter->initializeCG(newState);
831 block_cg_iter->iterate();
838 if ( convTest_->getStatus() ==
Passed ) {
845 if (convIdx.size() == currRHSIdx.size())
849 problem_->setCurrLS();
853 std::vector<int> unconvIdx(currRHSIdx.size());
854 for (
unsigned int i=0; i<currRHSIdx.size(); ++i) {
856 for (
unsigned int j=0; j<convIdx.size(); ++j) {
857 if (currRHSIdx[i] == convIdx[j]) {
863 currIdx2[have] = currIdx2[i];
864 currRHSIdx[have++] = currRHSIdx[i];
867 currRHSIdx.resize(have);
868 currIdx2.resize(have);
871 problem_->setLSIndex( currRHSIdx );
874 std::vector<MagnitudeType> norms;
875 R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
876 for (
int i=0; i<have; ++i) { currIdx2[i] = i; }
881 block_cg_iter->initializeCG(defstate);
889 else if ( maxIterTest_->getStatus() ==
Passed ) {
903 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
904 "Belos::PseudoBlockCGSolMgr::solve(): Invalid return from PseudoBlockCGIter::iterate().");
907 catch (
const std::exception &e) {
908 printer_->stream(
Errors) <<
"Error! Caught std::exception in PseudoBlockCGIter::iterate() at iteration "
909 << block_cg_iter->getNumIters() << std::endl
910 << e.what() << std::endl;
916 problem_->setCurrLS();
919 startPtr += numCurrRHS;
920 numRHS2Solve -= numCurrRHS;
922 if ( numRHS2Solve > 0 ) {
924 numCurrRHS = numRHS2Solve;
925 currIdx.resize( numCurrRHS );
926 currIdx2.resize( numCurrRHS );
927 for (
int i=0; i<numCurrRHS; ++i)
928 { currIdx[i] = startPtr+i; currIdx2[i] = i; }
931 problem_->setLSIndex( currIdx );
934 currIdx.resize( numRHS2Solve );
946 #ifdef BELOS_TEUCHOS_TIME_MONITOR
951 Teuchos::TimeMonitor::summarize( printer_->stream(
TimingDetails) );
955 numIters_ = maxIterTest_->getNumIters();
959 const std::vector<MagnitudeType>* pTestValues = convTest_->getTestValue();
960 if (pTestValues != NULL && pTestValues->size () > 0) {
961 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
966 ScalarType l_min, l_max;
967 Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
968 Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
969 compute_condnum_tridiag_sym(diag,offdiag,l_min,l_max,condEstimate_);
979 template<
class ScalarType,
class MV,
class OP>
982 std::ostringstream oss;
983 oss <<
"Belos::PseudoBlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<
">";
990 template<
class ScalarType,
class MV,
class OP>
994 Teuchos::ArrayView<MagnitudeType> offdiag,
995 ScalarType & lambda_min,
996 ScalarType & lambda_max,
997 ScalarType & ConditionNumber )
999 typedef Teuchos::ScalarTraits<ScalarType> STS;
1008 ScalarType scalar_dummy;
1009 MagnitudeType mag_dummy;
1011 Teuchos::LAPACK<int,ScalarType> lapack;
1012 const int N = diag.size ();
1014 lambda_min = STS::one ();
1015 lambda_max = STS::one ();
1017 lapack.STEQR (char_N, N, diag.getRawPtr (), offdiag.getRawPtr (),
1018 &scalar_dummy, 1, &mag_dummy, &info);
1019 TEUCHOS_TEST_FOR_EXCEPTION
1020 (info < 0, std::logic_error,
"Belos::PseudoBlockCGSolMgr::"
1021 "compute_condnum_tridiag_sym: LAPACK's _STEQR failed with info = "
1022 << info <<
" < 0. This suggests there might be a bug in the way Belos "
1023 "is calling LAPACK. Please report this to the Belos developers.");
1024 lambda_min = Teuchos::as<ScalarType> (diag[0]);
1025 lambda_max = Teuchos::as<ScalarType> (diag[N-1]);
1032 if (STS::real (lambda_max) < STS::real (lambda_min)) {
1033 ConditionNumber = STS::one ();
1037 ConditionNumber = lambda_max / lambda_min;