Belos  Version of the Day
 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:
129  using MagnitudeType = typename Teuchos::ScalarTraits<ScalarType>::magnitudeType;
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 
296  Teuchos::RCP<std::ostream> outputStream_;
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 
342  MagnitudeType convtol_;
343 
345  MagnitudeType orthoKappa_;
346 
352  MagnitudeType achievedTol_;
353 
355  int maxIters_;
356 
358  int numIters_;
359 
361  int blockSize_, verbosity_, outputStyle_, outputFreq_;
362  bool adaptiveBlockSize_, showMaxResNormOnly_, useSingleReduction_;
363  std::string orthoType_, resScale_;
364  bool assertPositiveDefiniteness_;
365  bool foldConvergenceDetectionIntoAllreduce_;
366 
368 
370  std::string label_;
371 
373  Teuchos::RCP<Teuchos::Time> timerSolve_;
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...
Class which manages the output and verbosity of the Belos solvers.
bool is_null(const boost::shared_ptr< T > &p)
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)
This class implements the preconditioned Conjugate Gradient (CG) iteration.
Definition: BelosCGIter.hpp:94
T & get(const std::string &name, T def_value)
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.
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.
BlockCGSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
Traits class which defines basic operations on multivectors.
Belos::StatusTest for logically combining several status tests.
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)
NormType convertStringToNormType(const std::string &normType)
Convert the given string to its NormType enum value.
Definition: BelosTypes.cpp:56
A linear system to solve, and its associated information.
Class which describes the linear problem to be solved by the iterative solver.
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
int getNumIters() const override
Get the iteration count for the most recent call 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.
bool isType(const std::string &name) const
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...
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...
Stub implementation of BlockCGIter, for ScalarType types for which Teuchos::LAPACK does NOT have a va...
bool is_null() const
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.

Generated on Fri Feb 21 2025 09:24:40 for Belos by doxygen 1.8.5