Belos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosPseudoBlockCGSolMgr.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_PSEUDO_BLOCK_CG_SOLMGR_HPP
11 #define BELOS_PSEUDO_BLOCK_CG_SOLMGR_HPP
12 
17 #include "BelosCGIteration.hpp"
18 #include "BelosConfigDefs.hpp"
19 #include "BelosTypes.hpp"
20 
21 #include "BelosLinearProblem.hpp"
22 #include "BelosSolverManager.hpp"
23 
25 #include "BelosCGIter.hpp"
28 #include "BelosStatusTestCombo.hpp"
30 #include "BelosOutputManager.hpp"
31 #include "Teuchos_LAPACK.hpp"
32 #ifdef BELOS_TEUCHOS_TIME_MONITOR
33 #include "Teuchos_TimeMonitor.hpp"
34 #endif
35 
55 namespace Belos {
56 
58 
59 
67  PseudoBlockCGSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
68  {}};
69 
70 
71  // Partial specialization for unsupported ScalarType types.
72  // This contains a stub implementation.
73  template<class ScalarType, class MV, class OP,
74  const bool supportsScalarType =
77  public Details::SolverManagerRequiresLapack<ScalarType, MV, OP,
78  Belos::Details::LapackSupportsScalar<ScalarType>::value>
79  {
80  static const bool scalarTypeIsSupported =
83 
84  public:
86  base_type ()
87  {}
90  base_type ()
91  {}
92  virtual ~PseudoBlockCGSolMgr () = default;
93 
96  };
97 
98 
99  template<class ScalarType, class MV, class OP>
100  class PseudoBlockCGSolMgr<ScalarType, MV, OP, true> :
101  public Details::SolverManagerRequiresLapack<ScalarType, MV, OP, true>
102  {
103  private:
109 
110  public:
111 
113 
114 
121 
139 
141  virtual ~PseudoBlockCGSolMgr() = default;
142 
146  }
148 
150 
151 
152  const LinearProblem<ScalarType,MV,OP>& getProblem() const override {
153  return *problem_;
154  }
155 
158  Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override;
159 
163 
170  return Teuchos::tuple(timerSolve_);
171  }
172 
173 
184  MagnitudeType achievedTol() const override {
185  return achievedTol_;
186  }
187 
189  int getNumIters() const override {
190  return numIters_;
191  }
192 
196  bool isLOADetected() const override { return false; }
197 
201  ScalarType getConditionEstimate() const {return condEstimate_;}
202  Teuchos::ArrayRCP<MagnitudeType> getEigenEstimates() const {return eigenEstimates_;}
203 
206  getResidualStatusTest() const { return convTest_; }
207 
209 
211 
212 
214  void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) override { problem_ = problem; }
215 
217  void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
218 
220 
222 
223 
227  void reset( const ResetType type ) override { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
229 
231 
232 
250  ReturnType solve() override;
251 
253 
256 
258  std::string description() const override;
259 
261  private:
262  // Compute the condition number estimate
263  void compute_condnum_tridiag_sym(Teuchos::ArrayView<MagnitudeType> diag,
266  ScalarType & lambda_min,
267  ScalarType & lambda_max,
268  ScalarType & ConditionNumber );
269 
270  // Linear problem.
272 
273  // Output manager.
276 
277  // Status test.
282 
283  // Current parameter list.
285 
292 
293  // Default solver values.
294  static constexpr int maxIters_default_ = 1000;
295  static constexpr bool assertPositiveDefiniteness_default_ = true;
296  static constexpr bool showMaxResNormOnly_default_ = false;
297  static constexpr int verbosity_default_ = Belos::Errors;
298  static constexpr int outputStyle_default_ = Belos::General;
299  static constexpr int outputFreq_default_ = -1;
300  static constexpr int defQuorum_default_ = 1;
301  static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ = false;
302  static constexpr const char * resScale_default_ = "Norm of Initial Residual";
303  static constexpr const char * label_default_ = "Belos";
304  static constexpr bool genCondEst_default_ = false;
305 
306  // Current solver values.
307  MagnitudeType convtol_,achievedTol_;
308  int maxIters_, numIters_;
309  int verbosity_, outputStyle_, outputFreq_, defQuorum_;
310  bool assertPositiveDefiniteness_, showMaxResNormOnly_;
312  std::string resScale_;
314  ScalarType condEstimate_;
316 
318 
319  // Timers.
320  std::string label_;
322 
323  // Internal state variables.
324  bool isSet_;
325  };
326 
327 
328 // Empty Constructor
329 template<class ScalarType, class MV, class OP>
331  outputStream_(Teuchos::rcpFromRef(std::cout)),
332  convtol_(DefaultSolverParameters::convTol),
333  maxIters_(maxIters_default_),
334  numIters_(0),
335  verbosity_(verbosity_default_),
336  outputStyle_(outputStyle_default_),
337  outputFreq_(outputFreq_default_),
338  defQuorum_(defQuorum_default_),
339  assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
340  showMaxResNormOnly_(showMaxResNormOnly_default_),
341  foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
342  resScale_(resScale_default_),
343  genCondEst_(genCondEst_default_),
344  condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
345  label_(label_default_),
346  isSet_(false)
347 {}
348 
349 // Basic Constructor
350 template<class ScalarType, class MV, class OP>
354  problem_(problem),
355  outputStream_(Teuchos::rcpFromRef(std::cout)),
356  convtol_(DefaultSolverParameters::convTol),
357  maxIters_(maxIters_default_),
358  numIters_(0),
359  verbosity_(verbosity_default_),
360  outputStyle_(outputStyle_default_),
361  outputFreq_(outputFreq_default_),
362  defQuorum_(defQuorum_default_),
363  assertPositiveDefiniteness_(assertPositiveDefiniteness_default_),
364  showMaxResNormOnly_(showMaxResNormOnly_default_),
365  foldConvergenceDetectionIntoAllreduce_(foldConvergenceDetectionIntoAllreduce_default_),
366  resScale_(resScale_default_),
367  genCondEst_(genCondEst_default_),
368  condEstimate_(-Teuchos::ScalarTraits<ScalarType>::one()),
369  label_(label_default_),
370  isSet_(false)
371 {
373  problem_.is_null (), std::invalid_argument,
374  "Belos::PseudoBlockCGSolMgr two-argument constructor: "
375  "'problem' is null. You must supply a non-null Belos::LinearProblem "
376  "instance when calling this constructor.");
377 
378  if (! pl.is_null ()) {
379  // Set the parameters using the list that was passed in.
380  setParameters (pl);
381  }
382 }
383 
384 template<class ScalarType, class MV, class OP>
385 void
388 {
390  using Teuchos::parameterList;
391  using Teuchos::RCP;
392  using Teuchos::rcp;
393 
394  RCP<const ParameterList> defaultParams = this->getValidParameters ();
395 
396  // Create the internal parameter list if one doesn't already exist.
397  // Belos' solvers treat the input ParameterList to setParameters as
398  // a "delta" -- that is, a change from the current state -- so the
399  // default parameter list (if the input is null) should be empty.
400  // This explains also why Belos' solvers copy parameters one by one
401  // from the input list to the current list.
402  //
403  // Belos obfuscates the latter, because it takes the input parameter
404  // list by RCP, rather than by (nonconst) reference. The latter
405  // would make more sense, given that it doesn't actually keep the
406  // input parameter list.
407  //
408  // Note, however, that Belos still correctly triggers the "used"
409  // field of each parameter in the input list. While isParameter()
410  // doesn't (apparently) trigger the "used" flag, get() certainly
411  // does.
412 
413  if (params_.is_null ()) {
414  // Create an empty list with the same name as the default list.
415  params_ = parameterList (defaultParams->name ());
416  } else {
417  params->validateParameters (*defaultParams);
418  }
419 
420  // Check for maximum number of iterations
421  if (params->isParameter ("Maximum Iterations")) {
422  maxIters_ = params->get ("Maximum Iterations", maxIters_default_);
423 
424  // Update parameter in our list and in status test.
425  params_->set ("Maximum Iterations", maxIters_);
426  if (! maxIterTest_.is_null ()) {
427  maxIterTest_->setMaxIters (maxIters_);
428  }
429  }
430 
431  // Check if positive definiteness assertions are to be performed
432  if (params->isParameter ("Assert Positive Definiteness")) {
433  assertPositiveDefiniteness_ =
434  params->get ("Assert Positive Definiteness",
435  assertPositiveDefiniteness_default_);
436 
437  // Update parameter in our list.
438  params_->set ("Assert Positive Definiteness", assertPositiveDefiniteness_);
439  }
440 
441  if (params->isParameter("Fold Convergence Detection Into Allreduce")) {
442  foldConvergenceDetectionIntoAllreduce_ = params->get("Fold Convergence Detection Into Allreduce",
443  foldConvergenceDetectionIntoAllreduce_default_);
444  }
445 
446  // Check to see if the timer label changed.
447  if (params->isParameter ("Timer Label")) {
448  const std::string tempLabel = params->get ("Timer Label", label_default_);
449 
450  // Update parameter in our list and solver timer
451  if (tempLabel != label_) {
452  label_ = tempLabel;
453  params_->set ("Timer Label", label_);
454  const std::string solveLabel =
455  label_ + ": PseudoBlockCGSolMgr total solve time";
456 #ifdef BELOS_TEUCHOS_TIME_MONITOR
457  timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
458 #endif
459  }
460  }
461 
462  // Check for a change in verbosity level
463  if (params->isParameter ("Verbosity")) {
464  if (Teuchos::isParameterType<int> (*params, "Verbosity")) {
465  verbosity_ = params->get ("Verbosity", verbosity_default_);
466  } else {
467  verbosity_ = (int) Teuchos::getParameter<Belos::MsgType> (*params, "Verbosity");
468  }
469 
470  // Update parameter in our list.
471  params_->set ("Verbosity", verbosity_);
472  if (! printer_.is_null ()) {
473  printer_->setVerbosity (verbosity_);
474  }
475  }
476 
477  // Check for a change in output style
478  if (params->isParameter ("Output Style")) {
479  if (Teuchos::isParameterType<int> (*params, "Output Style")) {
480  outputStyle_ = params->get ("Output Style", outputStyle_default_);
481  } else {
482  // FIXME (mfh 29 Jul 2015) What if the type is wrong?
483  outputStyle_ = (int) Teuchos::getParameter<Belos::OutputType> (*params, "Output Style");
484  }
485 
486  // Reconstruct the convergence test if the explicit residual test
487  // is not being used.
488  params_->set ("Output Style", outputStyle_);
489  outputTest_ = Teuchos::null;
490  }
491 
492  // output stream
493  if (params->isParameter ("Output Stream")) {
494  outputStream_ = params->get<RCP<std::ostream> > ("Output Stream");
495 
496  // Update parameter in our list.
497  params_->set ("Output Stream", outputStream_);
498  if (! printer_.is_null ()) {
499  printer_->setOStream (outputStream_);
500  }
501  }
502 
503  // frequency level
504  if (verbosity_ & Belos::StatusTestDetails) {
505  if (params->isParameter ("Output Frequency")) {
506  outputFreq_ = params->get ("Output Frequency", outputFreq_default_);
507  }
508 
509  // Update parameter in out list and output status test.
510  params_->set ("Output Frequency", outputFreq_);
511  if (! outputTest_.is_null ()) {
512  outputTest_->setOutputFrequency (outputFreq_);
513  }
514  }
515 
516  // Condition estimate
517  if (params->isParameter ("Estimate Condition Number")) {
518  genCondEst_ = params->get ("Estimate Condition Number", genCondEst_default_);
519  }
520 
521  // Create output manager if we need to.
522  if (printer_.is_null ()) {
523  printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_));
524  }
525 
526  // Convergence
527  using StatusTestCombo_t = Belos::StatusTestCombo<ScalarType, MV, OP>;
528  using StatusTestResNorm_t = Belos::StatusTestGenResNorm<ScalarType, MV, OP>;
529 
530  // Check for convergence tolerance
531  if (params->isParameter ("Convergence Tolerance")) {
532  if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
533  convtol_ = params->get ("Convergence Tolerance",
534  static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
535  }
536  else {
537  convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
538  }
539 
540  // Update parameter in our list and residual tests.
541  params_->set ("Convergence Tolerance", convtol_);
542  if (! convTest_.is_null ()) {
543  convTest_->setTolerance (convtol_);
544  }
545  }
546 
547  if (params->isParameter ("Show Maximum Residual Norm Only")) {
548  showMaxResNormOnly_ = params->get<bool> ("Show Maximum Residual Norm Only");
549 
550  // Update parameter in our list and residual tests
551  params_->set ("Show Maximum Residual Norm Only", showMaxResNormOnly_);
552  if (! convTest_.is_null ()) {
553  convTest_->setShowMaxResNormOnly (showMaxResNormOnly_);
554  }
555  }
556 
557  // Check for a change in scaling, if so we need to build new residual tests.
558  bool newResTest = false;
559  {
560  // "Residual Scaling" is the old parameter name; "Implicit
561  // Residual Scaling" is the new name. We support both options for
562  // backwards compatibility.
563  std::string tempResScale = resScale_;
564  bool implicitResidualScalingName = false;
565  if (params->isParameter ("Residual Scaling")) {
566  tempResScale = params->get<std::string> ("Residual Scaling");
567  }
568  else if (params->isParameter ("Implicit Residual Scaling")) {
569  tempResScale = params->get<std::string> ("Implicit Residual Scaling");
570  implicitResidualScalingName = true;
571  }
572 
573  // Only update the scaling if it's different.
574  if (resScale_ != tempResScale) {
575  const Belos::ScaleType resScaleType =
576  convertStringToScaleType (tempResScale);
577  resScale_ = tempResScale;
578 
579  // Update parameter in our list and residual tests, using the
580  // given parameter name.
581  if (implicitResidualScalingName) {
582  params_->set ("Implicit Residual Scaling", resScale_);
583  }
584  else {
585  params_->set ("Residual Scaling", resScale_);
586  }
587 
588  if (! convTest_.is_null ()) {
589  try {
590  convTest_->defineScaleForm (resScaleType, Belos::TwoNorm);
591  }
592  catch (std::exception& e) {
593  // Make sure the convergence test gets constructed again.
594  newResTest = true;
595  }
596  }
597  }
598  }
599 
600  // Get the deflation quorum, or number of converged systems before deflation is allowed
601  if (params->isParameter ("Deflation Quorum")) {
602  defQuorum_ = params->get ("Deflation Quorum", defQuorum_);
603  params_->set ("Deflation Quorum", defQuorum_);
604  if (! convTest_.is_null ()) {
605  convTest_->setQuorum( defQuorum_ );
606  }
607  }
608 
609  // Create status tests if we need to.
610 
611  // Basic test checks maximum iterations and native residual.
612  if (maxIterTest_.is_null ()) {
613  maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP> (maxIters_));
614  }
615 
616  // Implicit residual test, using the native residual to determine if convergence was achieved.
617  if (convTest_.is_null () || newResTest) {
618  convTest_ = rcp (new StatusTestResNorm_t (convtol_, defQuorum_, showMaxResNormOnly_));
619  convTest_->defineScaleForm (convertStringToScaleType (resScale_), Belos::TwoNorm);
620  }
621 
622  if (sTest_.is_null () || newResTest) {
623  sTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::OR, maxIterTest_, convTest_));
624  }
625 
626  if (outputTest_.is_null () || newResTest) {
627  // Create the status test output class.
628  // This class manages and formats the output from the status test.
629  StatusTestOutputFactory<ScalarType,MV,OP> stoFactory (outputStyle_);
630  outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_,
632 
633  // Set the solver string for the output test
634  const std::string solverDesc = " Pseudo Block CG ";
635  outputTest_->setSolverDesc (solverDesc);
636  }
637 
638  // Create the timer if we need to.
639  if (timerSolve_.is_null ()) {
640  const std::string solveLabel =
641  label_ + ": PseudoBlockCGSolMgr total solve time";
642 #ifdef BELOS_TEUCHOS_TIME_MONITOR
643  timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
644 #endif
645  }
646 
647  // Inform the solver manager that the current parameters were set.
648  isSet_ = true;
649 }
650 
651 
652 template<class ScalarType, class MV, class OP>
655 {
657  using Teuchos::parameterList;
658  using Teuchos::RCP;
659 
660  if (validParams_.is_null()) {
661  // Set all the valid parameters and their default values.
662  RCP<ParameterList> pl = parameterList ();
663  pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
664  "The relative residual tolerance that needs to be achieved by the\n"
665  "iterative solver in order for the linear system to be declared converged.");
666  pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
667  "The maximum number of block iterations allowed for each\n"
668  "set of RHS solved.");
669  pl->set("Assert Positive Definiteness", static_cast<bool>(assertPositiveDefiniteness_default_),
670  "Whether or not to assert that the linear operator\n"
671  "and the preconditioner are indeed positive definite.");
672  pl->set("Verbosity", static_cast<int>(verbosity_default_),
673  "What type(s) of solver information should be outputted\n"
674  "to the output stream.");
675  pl->set("Output Style", static_cast<int>(outputStyle_default_),
676  "What style is used for the solver information outputted\n"
677  "to the output stream.");
678  pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
679  "How often convergence information should be outputted\n"
680  "to the output stream.");
681  pl->set("Deflation Quorum", static_cast<int>(defQuorum_default_),
682  "The number of linear systems that need to converge before\n"
683  "they are deflated. This number should be <= block size.");
684  pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
685  "A reference-counted pointer to the output stream where all\n"
686  "solver output is sent.");
687  pl->set("Show Maximum Residual Norm Only", static_cast<bool>(showMaxResNormOnly_default_),
688  "When convergence information is printed, only show the maximum\n"
689  "relative residual norm when the block size is greater than one.");
690  pl->set("Implicit Residual Scaling", resScale_default_,
691  "The type of scaling used in the residual convergence test.");
692  pl->set("Estimate Condition Number", static_cast<bool>(genCondEst_default_),
693  "Whether or not to estimate the condition number of the preconditioned system.");
694  // We leave the old name as a valid parameter for backwards
695  // compatibility (so that validateParametersAndSetDefaults()
696  // doesn't raise an exception if it encounters "Residual
697  // Scaling"). The new name was added for compatibility with other
698  // solvers, none of which use "Residual Scaling".
699  pl->set("Residual Scaling", resScale_default_,
700  "The type of scaling used in the residual convergence test. This "
701  "name is deprecated; the new name is \"Implicit Residual Scaling\".");
702  pl->set("Timer Label", static_cast<const char *>(label_default_),
703  "The string to use as a prefix for the timer labels.");
704  pl->set("Fold Convergence Detection Into Allreduce",static_cast<bool>(foldConvergenceDetectionIntoAllreduce_default_),
705  "Merge the allreduce for convergence detection with the one for CG.\n"
706  "This saves one all-reduce, but incurs more computation.");
707  validParams_ = pl;
708  }
709  return validParams_;
710 }
711 
712 
713 // solve()
714 template<class ScalarType, class MV, class OP>
716 {
717  const char prefix[] = "Belos::PseudoBlockCGSolMgr::solve: ";
718 
719  // Set the current parameters if they were not set before.
720  // NOTE: This may occur if the user generated the solver manager with the default constructor and
721  // then didn't set any parameters using setParameters().
722  if (!isSet_) { setParameters( params_ ); }
723 
725  (! problem_->isProblemSet (), PseudoBlockCGSolMgrLinearProblemFailure,
726  prefix << "The linear problem to solve is not ready. You must call "
727  "setProblem() on the Belos::LinearProblem instance before telling the "
728  "Belos solver to solve it.");
729 
730  // Create indices for the linear systems to be solved.
731  int startPtr = 0;
732  int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
733  int numCurrRHS = numRHS2Solve;
734 
735  std::vector<int> currIdx( numRHS2Solve ), currIdx2( numRHS2Solve );
736  for (int i=0; i<numRHS2Solve; ++i) {
737  currIdx[i] = startPtr+i;
738  currIdx2[i]=i;
739  }
740 
741  // Inform the linear problem of the current linear system to solve.
742  problem_->setLSIndex( currIdx );
743 
745  // Parameter list (iteration)
747 
748  plist.set("Assert Positive Definiteness",assertPositiveDefiniteness_);
749  if(genCondEst_) plist.set("Max Size For Condest",maxIters_);
750 
751  // Reset the status test.
752  outputTest_->reset();
753 
754  // Assume convergence is achieved, then let any failed convergence set this to false.
755  bool isConverged = true;
756 
758  // Pseudo-Block CG solver
760  if (numRHS2Solve == 1) {
761  plist.set("Fold Convergence Detection Into Allreduce",
762  foldConvergenceDetectionIntoAllreduce_);
763  block_cg_iter =
764  Teuchos::rcp (new CGIter<ScalarType,MV,OP> (problem_, printer_, outputTest_, convTest_, plist));
765  if (state_.is_null() || Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType, MV> >(state_).is_null())
767  } else {
768  block_cg_iter =
769  Teuchos::rcp (new PseudoBlockCGIter<ScalarType,MV,OP> (problem_, printer_, outputTest_, plist));
770  if (state_.is_null() || Teuchos::rcp_dynamic_cast<PseudoBlockCGIterationState<ScalarType, MV> >(state_).is_null())
772  }
773 
774  // Setup condition estimate
775  block_cg_iter->setDoCondEst(genCondEst_);
776  bool condEstPerf = false;
777 
778  // Enter solve() iterations
779  {
780 #ifdef BELOS_TEUCHOS_TIME_MONITOR
781  Teuchos::TimeMonitor slvtimer(*timerSolve_);
782 #endif
783 
784  while ( numRHS2Solve > 0 ) {
785 
786  // Reset the active / converged vectors from this block
787  std::vector<int> convRHSIdx;
788  std::vector<int> currRHSIdx( currIdx );
789  currRHSIdx.resize(numCurrRHS);
790 
791  // Reset the number of iterations.
792  block_cg_iter->resetNumIters();
793 
794  // Reset the number of calls that the status test output knows about.
795  outputTest_->resetNumCalls();
796 
797  // Get the current residual for this block of linear systems.
798  Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
799 
800  // Get a new state struct and initialize the solver.
801  block_cg_iter->initializeCG(state_, R_0);
802 
803  while(true) {
804 
805  // tell block_gmres_iter to iterate
806  try {
807 
808  block_cg_iter->iterate();
809 
811  //
812  // check convergence first
813  //
815  if ( convTest_->getStatus() == Passed ) {
816 
817  // Figure out which linear systems converged.
818  std::vector<int> convIdx = Teuchos::rcp_dynamic_cast<StatusTestGenResNorm<ScalarType,MV,OP> >(convTest_)->convIndices();
819 
820  // If the number of converged linear systems is equal to the
821  // number of current linear systems, then we are done with this block.
822  if (convIdx.size() == currRHSIdx.size())
823  break; // break from while(1){block_cg_iter->iterate()}
824 
825  // Inform the linear problem that we are finished with this current linear system.
826  problem_->setCurrLS();
827 
828  // Reset currRHSIdx to have the right-hand sides that are left to converge for this block.
829  int have = 0;
830  for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
831  bool found = false;
832  for (unsigned int j=0; j<convIdx.size(); ++j) {
833  if (currRHSIdx[i] == convIdx[j]) {
834  found = true;
835  break;
836  }
837  }
838  if (!found) {
839  currIdx2[have] = currIdx2[i];
840  currRHSIdx[have++] = currRHSIdx[i];
841  }
842  }
843  currRHSIdx.resize(have);
844  currIdx2.resize(have);
845 
846  // Compute condition estimate if the very first linear system in the block has converged.
847  if (currRHSIdx[0] != 0 && genCondEst_ && !condEstPerf)
848  {
849  // Compute the estimate.
850  ScalarType l_min, l_max;
851  Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
852  Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
853  compute_condnum_tridiag_sym(diag,offdiag,eigenEstimates_,l_min,l_max,condEstimate_);
854 
855  // Make sure not to do more condition estimate computations for this solve.
856  block_cg_iter->setDoCondEst(false);
857  condEstPerf = true;
858  }
859 
860  // Set the remaining indices after deflation.
861  problem_->setLSIndex( currRHSIdx );
862 
863  // Get the current residual vector.
864  std::vector<MagnitudeType> norms;
865  R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
866  for (int i=0; i<have; ++i) { currIdx2[i] = i; }
867 
868  // Set the new state and initialize the solver.
869  block_cg_iter->initializeCG(state_, R_0);
870  }
871 
873  //
874  // check for maximum iterations
875  //
877  else if ( maxIterTest_->getStatus() == Passed ) {
878  // we don't have convergence
879  isConverged = false;
880  break; // break from while(1){block_cg_iter->iterate()}
881  }
882 
884  //
885  // we returned from iterate(), but none of our status tests Passed.
886  // something is wrong, and it is probably our fault.
887  //
889 
890  else {
891  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
892  "Belos::PseudoBlockCGSolMgr::solve(): Invalid return from PseudoBlockCGIter::iterate().");
893  }
894  }
895  catch (const StatusTestNaNError& e) {
896  // A NaN was detected in the solver. Set the solution to zero and return unconverged.
897  achievedTol_ = MT::one();
898  Teuchos::RCP<MV> X = problem_->getLHS();
899  MVT::MvInit( *X, SCT::zero() );
900  printer_->stream(Warnings) << "Belos::PseudoBlockCGSolMgr::solve(): Warning! NaN has been detected!"
901  << std::endl;
902  return Unconverged;
903  }
904  catch (const std::exception &e) {
905  printer_->stream(Errors) << "Error! Caught std::exception in PseudoBlockCGIter::iterate() at iteration "
906  << block_cg_iter->getNumIters() << std::endl
907  << e.what() << std::endl;
908  throw;
909  }
910  }
911 
912  // Inform the linear problem that we are finished with this block linear system.
913  problem_->setCurrLS();
914 
915  // Update indices for the linear systems to be solved.
916  startPtr += numCurrRHS;
917  numRHS2Solve -= numCurrRHS;
918 
919  if ( numRHS2Solve > 0 ) {
920 
921  numCurrRHS = numRHS2Solve;
922  currIdx.resize( numCurrRHS );
923  currIdx2.resize( numCurrRHS );
924  for (int i=0; i<numCurrRHS; ++i)
925  { currIdx[i] = startPtr+i; currIdx2[i] = i; }
926 
927  // Set the next indices.
928  problem_->setLSIndex( currIdx );
929  }
930  else {
931  currIdx.resize( numRHS2Solve );
932  }
933 
934  }// while ( numRHS2Solve > 0 )
935 
936  }
937 
938  // print final summary
939  sTest_->print( printer_->stream(FinalSummary) );
940 
941  // print timing information
942 #ifdef BELOS_TEUCHOS_TIME_MONITOR
943  // Calling summarize() can be expensive, so don't call unless the
944  // user wants to print out timing details. summarize() will do all
945  // the work even if it's passed a "black hole" output stream.
946  if (verbosity_ & TimingDetails)
947  Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
948 #endif
949 
950  // get iteration information for this solve
951  numIters_ = maxIterTest_->getNumIters();
952 
953  // Save the convergence test value ("achieved tolerance") for this
954  // solve.
955  const std::vector<MagnitudeType>* pTestValues = convTest_->getTestValue();
956  if (pTestValues != NULL && pTestValues->size () > 0) {
957  achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
958  }
959 
960  // Do condition estimate, if needed
961  if (genCondEst_ && !condEstPerf) {
962  ScalarType l_min, l_max;
963  Teuchos::ArrayView<MagnitudeType> diag = block_cg_iter->getDiag();
964  Teuchos::ArrayView<MagnitudeType> offdiag = block_cg_iter->getOffDiag();
965  compute_condnum_tridiag_sym(diag,offdiag,eigenEstimates_,l_min,l_max,condEstimate_);
966  condEstPerf = true;
967  }
968 
969  if (! isConverged) {
970  return Unconverged; // return from PseudoBlockCGSolMgr::solve()
971  }
972  return Converged; // return from PseudoBlockCGSolMgr::solve()
973 }
974 
975 // This method requires the solver manager to return a std::string that describes itself.
976 template<class ScalarType, class MV, class OP>
978 {
979  std::ostringstream oss;
980  oss << "Belos::PseudoBlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
981  oss << "{";
982  oss << "}";
983  return oss.str();
984 }
985 
986 
987 template<class ScalarType, class MV, class OP>
988 void
993  ScalarType & lambda_min,
994  ScalarType & lambda_max,
995  ScalarType & ConditionNumber )
996 {
998 
999  /* Copied from az_cg.c: compute_condnum_tridiag_sym */
1000  /* diag == ScalarType vector of size N, containing the diagonal
1001  elements of A
1002  offdiag == ScalarType vector of size N-1, containing the offdiagonal
1003  elements of A. Note that A is supposed to be symmatric
1004  */
1005  int info = 0;
1006  const int N = diag.size ();
1007  ScalarType scalar_dummy;
1008  std::vector<MagnitudeType> mag_dummy(4*N);
1009  char char_N = 'N';
1011 
1012  lambdas.resize(N, 0.0);
1013  lambda_min = STS::one ();
1014  lambda_max = STS::one ();
1015  if( N > 2 ) {
1016  lapack.PTEQR (char_N, N, diag.getRawPtr (), offdiag.getRawPtr (),
1017  &scalar_dummy, 1, &mag_dummy[0], &info);
1019  (info < 0, std::logic_error, "Belos::PseudoBlockCGSolMgr::"
1020  "compute_condnum_tridiag_sym: LAPACK's _PTEQR failed with info = "
1021  << info << " < 0. This suggests there might be a bug in the way Belos "
1022  "is calling LAPACK. Please report this to the Belos developers.");
1023  for (int k = 0; k < N; k++) {
1024  lambdas[k] = diag[N - 1 - k];
1025  }
1026  lambda_min = Teuchos::as<ScalarType> (diag[N-1]);
1027  lambda_max = Teuchos::as<ScalarType> (diag[0]);
1028  }
1029 
1030  // info > 0 means that LAPACK's eigensolver didn't converge. This
1031  // is unlikely but may be possible. In that case, the best we can
1032  // do is use the eigenvalues that it computes, as long as lambda_max
1033  // >= lambda_min.
1034  if (STS::real (lambda_max) < STS::real (lambda_min)) {
1035  ConditionNumber = STS::one ();
1036  }
1037  else {
1038  // It's OK for the condition number to be Inf.
1039  ConditionNumber = lambda_max / lambda_min;
1040  }
1041 
1042 } /* compute_condnum_tridiag_sym */
1043 
1044 
1045 
1046 
1047 
1048 } // end Belos namespace
1049 
1050 #endif /* BELOS_PSEUDO_BLOCK_CG_SOLMGR_HPP */
ScaleType convertStringToScaleType(const std::string &scaleType)
Convert the given string to its ScaleType enum value.
Definition: BelosTypes.cpp:74
Collection of types and exceptions used within the Belos solvers.
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)
Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > problem_
ScaleType
The type of scaling to use on the residual norm value.
Definition: BelosTypes.hpp:88
PseudoBlockCGSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
This class implements the preconditioned Conjugate Gradient (CG) iteration.
Definition: BelosCGIter.hpp:94
T & get(ParameterList &l, const std::string &name)
Pure virtual base class which augments the basic interface for a conjugate gradient linear solver ite...
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)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
A factory class for generating StatusTestOutput objects.
PseudoBlockCGSolMgrLinearProblemFailure is thrown when the linear problem is not setup (i...
size_type size() const
An implementation of StatusTestResNorm using a family of residual norms.
ScalarType getConditionEstimate() const
Gets the estimated condition number.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void PTEQR(const char &COMPZ, const OrdinalType &n, MagnitudeType *D, MagnitudeType *E, ScalarType *Z, const OrdinalType &ldz, MagnitudeType *WORK, OrdinalType *info) const
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()
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state_
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
A factory class for generating StatusTestOutput objects.
const LinearProblem< ScalarType, MV, OP > & getProblem() const override
Return a reference to the linear problem being solved by this solver manager.
Traits class which defines basic operations on multivectors.
The Belos::PseudoBlockCGSolMgr provides a powerful and fully-featured solver manager over the pseudo-...
Belos::StatusTest for logically combining several status tests.
void resize(const size_type n, const T &val=T())
bool isParameter(const std::string &name) const
const int N
This class implements the pseudo-block CG iteration, where the basic CG algorithm is performed on all...
Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP > > convTest_
A Belos::StatusTest class for specifying a maximum number of iterations.
Structure to contain pointers to PseudoBlockCGIteration state variables.
ResetType
How to reset the solver.
Definition: BelosTypes.hpp:174
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. ...
Teuchos::RCP< StatusTest< ScalarType, MV, OP > > sTest_
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)
Teuchos::ArrayRCP< MagnitudeType > getEigenEstimates() const
Teuchos::RCP< const Teuchos::ParameterList > validParams_
List of valid parameters and their default values.
Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP > > getResidualStatusTest() const
Return the residual status test.
A linear system to solve, and its associated information.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Class which describes the linear problem to be solved by the iterative solver.
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve...
Teuchos::RCP< SolverManager< ScalarType, MV, OP > > clone() const override
clone for Inverted Injection (DII)
int getNumIters() const override
Get the iteration count for the most recent call to solve().
Type traits class that says whether Teuchos::LAPACK has a valid implementation for the given ScalarTy...
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem) override
Set the linear problem that needs to be solved.
ReturnType
Whether the Belos solve converged for all linear systems.
Definition: BelosTypes.hpp:123
T * getRawPtr() const
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
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.
PseudoBlockCGSolMgrLinearProblemFailure(const std::string &what_arg)
Structure to contain pointers to CGIteration state variables.
Definition: BelosCGIter.hpp:54
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
void reset(const ResetType type) override
Performs a reset of the solver manager specified by the ResetType. This informs the solver manager th...
bool isType(const std::string &name) const
Teuchos::RCP< StatusTestMaxIters< ScalarType, MV, OP > > maxIterTest_
Teuchos::RCP< OutputManager< ScalarType > > printer_
A class for extending the status testing capabilities of Belos via logical combinations.
virtual ~PseudoBlockCGSolMgr()=default
Class which defines basic traits for the operator type.
Belos concrete class for performing the pseudo-block CG iteration.
Parent class to all Belos exceptions.
Definition: BelosTypes.hpp:28
Default parameters common to most Belos solvers.
Definition: BelosTypes.hpp:251
Base class for Belos::SolverManager subclasses which normally can only compile with ScalarType types ...
typename Teuchos::ScalarTraits< ScalarType >::magnitudeType MagnitudeType
Belos header file which uses auto-configuration information to include necessary C++ headers...
Teuchos::RCP< StatusTestOutput< ScalarType, MV, OP > > outputTest_
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP > > getResidualStatusTest() const