Belos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
20 #include "BelosLinearProblem.hpp"
21 #include "BelosSolverManager.hpp"
22 
23 #include "BelosCGIter.hpp"
24 #include "BelosCGSingleRedIter.hpp"
25 #include "BelosBlockCGIter.hpp"
29 #include "BelosStatusTestCombo.hpp"
31 #include "BelosOutputManager.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 
61 namespace Belos {
62 
64 
65 
73  BlockCGSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
74  {}};
75 
76  template<class ScalarType, class MV, class OP,
77  const bool lapackSupportsScalarType =
79  class BlockCGSolMgr :
80  public Details::SolverManagerRequiresLapack<ScalarType,MV,OP>
81  {
82  static const bool requiresLapack =
85 
86  public:
88  base_type ()
89  {}
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>
102  class BlockCGSolMgr<ScalarType, MV, OP, true> :
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:
131 
132  public:
133 
135 
136 
142  BlockCGSolMgr();
143 
182 
184  virtual ~BlockCGSolMgr() = default;
185 
189  }
191 
193 
194 
195  const LinearProblem<ScalarType,MV,OP>& getProblem() const override {
196  return *problem_;
197  }
198 
201  Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override;
202 
206 
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 
292 
297 
303 
306 
309 
312 
315 
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 
343 
346 
353 
356 
359 
361  int blockSize_, verbosity_, outputStyle_, outputFreq_;
362  bool adaptiveBlockSize_, showMaxResNormOnly_, useSingleReduction_;
363  std::string orthoType_, resScale_;
366 
368 
370  std::string label_;
371 
374 
376  bool isSet_;
377  };
378 
379 
380 // Empty Constructor
381 template<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
406 template<class ScalarType, class MV, class OP>
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 
442 template<class ScalarType, class MV, class OP>
443 void
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) {
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) {
647  const Belos::ScaleType resScaleType =
648  convertStringToScaleType (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 {
656  NormType normType = Belos::TwoNorm;
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 
682  NormType normType = Belos::TwoNorm;
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.
701  StatusTestOutputFactory<ScalarType,MV,OP> stoFactory( outputStyle_ );
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 
729 template<class ScalarType, class MV, class OP>
732 {
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()
789 template<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 
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.
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 
858  RCP<CGIteration<ScalarType,MV,OP> > block_cg_iter;
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_) {
866  block_cg_iter =
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())
871 
872  }
873  else {
874  block_cg_iter =
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())
879  }
880  } else {
881  block_cg_iter =
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())
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.
926  using conv_test_type = StatusTestGenResNorm<ScalarType, MV, OP>;
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) {
953  currIdx2[have] = currIdx2[i];
954  currRHSIdx[have++] = currRHSIdx[i];
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.
1018  startPtr += numCurrRHS;
1019  numRHS2Solve -= numCurrRHS;
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  {
1071  using conv_test_type = StatusTestGenResNorm<ScalarType, MV, OP>;
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.
1098 template<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 */
static const double orthoKappa
DGKS orthogonalization constant.
Definition: BelosTypes.hpp:267
ScaleType convertStringToScaleType(const std::string &scaleType)
Convert the given string to its ScaleType enum value.
Definition: BelosTypes.cpp:74
Structure to contain pointers to BlockCGIteration state variables.
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve...
Collection of types and exceptions used within the Belos solvers.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Belos&#39;s basic output manager for sending information of select verbosity levels to the appropriate ou...
int maxIters_
Maximum iteration count (read from parameter list).
Class which manages the output and verbosity of the Belos solvers.
bool is_null(const boost::shared_ptr< T > &p)
bool isSet_
Whether or not the parameters have been set (via setParameters()).
Teuchos::RCP< Teuchos::ParameterList > params_
Current parameter list.
Teuchos::RCP< StatusTestOutput< ScalarType, MV, OP > > outputTest_
Output &quot;status test&quot; that controls all the other status tests.
ScaleType
The type of scaling to use on the residual norm value.
Definition: BelosTypes.hpp:88
Teuchos::RCP< SolverManager< ScalarType, MV, OP > > clone() const override
clone for Inverted Injection (DII)
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state_
This class implements the preconditioned Conjugate Gradient (CG) iteration.
Definition: BelosCGIter.hpp:94
T & get(ParameterList &l, const std::string &name)
Belos concrete class for performing the conjugate-gradient (CG) iteration.
static RCP< Time > getNewCounter(const std::string &name)
bool is_null(const std::shared_ptr< T > &p)
Structure to contain pointers to CGSingleRedIteration state variables.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
A factory class for generating StatusTestOutput objects.
Belos concrete class for performing the block conjugate-gradient (CG) iteration.
An implementation of StatusTestResNorm using a family of residual norms.
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem) override
Set the linear problem that needs to be solved.
std::string label_
Prefix label for all the timers.
The Belos::BlockCGSolMgr provides a powerful and fully-featured solver manager over the CG and BlockC...
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static const double convTol
Default convergence tolerance.
Definition: BelosTypes.hpp:261
Belos::StatusTest class for specifying a maximum number of iterations.
static std::string name()
BlockCGSolMgrLinearProblemFailure(const std::string &what_arg)
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
BlockCGSolMgrLinearProblemFailure is thrown when the linear problem is not setup (i.e.
A factory class for generating StatusTestOutput objects.
Teuchos::RCP< MatOrthoManager< ScalarType, MV, OP > > ortho_
Orthogonalization manager.
BlockCGSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
Teuchos::RCP< StatusTestMaxIters< ScalarType, MV, OP > > maxIterTest_
Maximum iteration count stopping criterion.
Traits class which defines basic operations on multivectors.
Belos::StatusTest for logically combining several status tests.
Teuchos::RCP< StatusTest< ScalarType, MV, OP > > sTest_
Aggregate stopping criterion.
virtual ~BlockCGSolMgr()=default
bool isParameter(const std::string &name) const
A Belos::StatusTest class for specifying a maximum number of iterations.
ResetType
How to reset the solver.
Definition: BelosTypes.hpp:174
void reset(const ResetType type) override
Performs a reset of the solver manager specified by the ResetType. This informs the solver manager th...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Pure virtual base class which describes the basic interface for a solver manager. ...
Belos concrete class for performing a single-reduction conjugate-gradient (CG) iteration.
static void summarize(Ptr< const Comm< int > > comm, std::ostream &out=std::cout, const bool alwaysWriteLocal=false, const bool writeGlobalStats=true, const bool writeZeroTimers=true, const ECounterSetOp setOp=Intersection, const std::string &filter="", const bool ignoreZeroTimers=false)
bool is_null(const RCP< T > &p)
NormType convertStringToNormType(const std::string &normType)
Convert the given string to its NormType enum value.
Definition: BelosTypes.cpp:56
typename Teuchos::ScalarTraits< ScalarType >::magnitudeType MagnitudeType
A linear system to solve, and its associated information.
Class which describes the linear problem to be solved by the iterative solver.
MagnitudeType achievedTol_
Tolerance achieved by the last solve() invocation.
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
Type traits class that says whether Teuchos::LAPACK has a valid implementation for the given ScalarTy...
ReturnType
Whether the Belos solve converged for all linear systems.
Definition: BelosTypes.hpp:123
Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP > > convTest_
Convergence stopping criterion.
int getNumIters() const override
Get the iteration count for the most recent call to solve().
Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > problem_
The linear problem to solve.
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
NormType
The type of vector norm to compute.
Definition: BelosTypes.hpp:65
Teuchos::RCP< StatusTestOutput< ScalarType, MV, OP > > create(const Teuchos::RCP< OutputManager< ScalarType > > &printer, Teuchos::RCP< StatusTest< ScalarType, MV, OP > > test, int mod, int printStates)
Create the StatusTestOutput object specified by the outputStyle.
Structure to contain pointers to CGIteration state variables.
Definition: BelosCGIter.hpp:54
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
MagnitudeType convtol_
Convergence tolerance (read from parameter list).
bool isType(const std::string &name) const
Teuchos::RCP< Teuchos::Time > timerSolve_
Solve timer.
An implementation of the Belos::MatOrthoManager that performs orthogonalization using (potentially) m...
A class for extending the status testing capabilities of Belos via logical combinations.
const LinearProblem< ScalarType, MV, OP > & getProblem() const override
Return a reference to the linear problem being solved by this solver manager.
Class which defines basic traits for the operator type.
Parent class to all Belos exceptions.
Definition: BelosTypes.hpp:28
Default parameters common to most Belos solvers.
Definition: BelosTypes.hpp:251
This class implements the preconditioned single-reduction Conjugate Gradient (CG) iteration...
Teuchos::RCP< OutputManager< ScalarType > > printer_
Output manager, that handles printing of different kinds of messages.
Base class for Belos::SolverManager subclasses which normally can only compile with ScalarType types ...
Belos header file which uses auto-configuration information to include necessary C++ headers...
int numIters_
Number of iterations taken by the last solve() invocation.
static const bool requiresLapack
Teuchos::RCP< std::ostream > outputStream_
Output stream to which the output manager prints.
MagnitudeType orthoKappa_
Orthogonalization parameter (read from parameter list).
Stub implementation of BlockCGIter, for ScalarType types for which Teuchos::LAPACK does NOT have a va...
Teuchos::RCP< Belos::MatOrthoManager< Scalar, MV, OP > > makeMatOrthoManager(const std::string &ortho, const Teuchos::RCP< const OP > &M, const Teuchos::RCP< OutputManager< Scalar > > &, const std::string &label, const Teuchos::RCP< Teuchos::ParameterList > &params)
Return an instance of the specified MatOrthoManager subclass.