Belos  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosGCRODRSolMgr.hpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Belos: Block Linear Solvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 //@HEADER
41 
42 #ifndef BELOS_GCRODR_SOLMGR_HPP
43 #define BELOS_GCRODR_SOLMGR_HPP
44 
48 
49 #include "BelosConfigDefs.hpp"
51 #include "BelosSolverManager.hpp"
52 #include "BelosLinearProblem.hpp"
53 #include "BelosTypes.hpp"
54 
55 #include "BelosGCRODRIter.hpp"
56 #include "BelosBlockFGmresIter.hpp"
59 #include "BelosStatusTestCombo.hpp"
61 #include "BelosOutputManager.hpp"
62 #include "Teuchos_BLAS.hpp" // includes Teuchos_ConfigDefs.hpp
63 #include "Teuchos_LAPACK.hpp"
64 #include "Teuchos_as.hpp"
65 #ifdef BELOS_TEUCHOS_TIME_MONITOR
66 # include "Teuchos_TimeMonitor.hpp"
67 #endif // BELOS_TEUCHOS_TIME_MONITOR
68 #if defined(HAVE_TEUCHOSCORE_CXX11)
69 # include <type_traits>
70 #endif // defined(HAVE_TEUCHOSCORE_CXX11)
71 
79 namespace Belos {
80 
82 
83 
91  public:
92  GCRODRSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg) {}
93  };
94 
102  public:
103  GCRODRSolMgrOrthoFailure(const std::string& what_arg) : BelosError(what_arg) {}
104  };
105 
113  public:
114  GCRODRSolMgrLAPACKFailure(const std::string& what_arg) : BelosError(what_arg) {}
115  };
116 
124  public:
125  GCRODRSolMgrRecyclingFailure(const std::string& what_arg) : BelosError(what_arg) {}
126  };
127 
129 
154  template<class ScalarType, class MV, class OP,
155  const bool lapackSupportsScalarType =
157  class GCRODRSolMgr :
158  public Details::SolverManagerRequiresLapack<ScalarType,MV,OP>
159  {
160  static const bool requiresLapack =
162  typedef Details::SolverManagerRequiresLapack<ScalarType, MV, OP,
163  requiresLapack> base_type;
164 
165  public:
167  base_type ()
168  {}
171  base_type ()
172  {}
173  virtual ~GCRODRSolMgr () {}
174  };
175 
179  template<class ScalarType, class MV, class OP>
180  class GCRODRSolMgr<ScalarType, MV, OP, true> :
181  public Details::SolverManagerRequiresLapack<ScalarType, MV, OP, true>
182  {
183 
184 #if defined(HAVE_TEUCHOSCORE_CXX11)
185 # if defined(HAVE_TEUCHOS_COMPLEX)
186  #if defined(HAVE_TEUCHOS_LONG_DOUBLE)
187  static_assert (std::is_same<ScalarType, std::complex<float> >::value ||
188  std::is_same<ScalarType, std::complex<double> >::value ||
189  std::is_same<ScalarType, Kokkos::complex<double> >::value ||
190  std::is_same<ScalarType, float>::value ||
191  std::is_same<ScalarType, double>::value ||
192  std::is_same<ScalarType, long double>::value,
193  "Belos::GCRODRSolMgr: ScalarType must be one of the four "
194  "types (S,D,C,Z) supported by LAPACK or long double (largely not impl'd).");
195  #else
196  static_assert (std::is_same<ScalarType, std::complex<float> >::value ||
197  std::is_same<ScalarType, std::complex<double> >::value ||
198  std::is_same<ScalarType, Kokkos::complex<double> >::value ||
199  std::is_same<ScalarType, float>::value ||
200  std::is_same<ScalarType, double>::value,
201  "Belos::GCRODRSolMgr: ScalarType must be one of the four "
202  "types (S,D,C,Z) supported by LAPACK.");
203  #endif
204 # else
205  #if defined(HAVE_TEUCHOS_LONG_DOUBLE)
206  static_assert (std::is_same<ScalarType, float>::value ||
207  std::is_same<ScalarType, double>::value ||
208  std::is_same<ScalarType, long double>::value,
209  "Belos::GCRODRSolMgr: ScalarType must be float, double or long double. "
210  "Complex arithmetic support is currently disabled. To "
211  "enable it, set Teuchos_ENABLE_COMPLEX=ON.");
212  #else
213  static_assert (std::is_same<ScalarType, float>::value ||
214  std::is_same<ScalarType, double>::value,
215  "Belos::GCRODRSolMgr: ScalarType must be float or double. "
216  "Complex arithmetic support is currently disabled. To "
217  "enable it, set Teuchos_ENABLE_COMPLEX=ON.");
218  #endif
219 # endif // defined(HAVE_TEUCHOS_COMPLEX)
220 #endif // defined(HAVE_TEUCHOSCORE_CXX11)
221 
222  private:
226  typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
229 
230  public:
232 
233 
239  GCRODRSolMgr();
240 
295 
297  virtual ~GCRODRSolMgr() {};
298 
302  }
304 
306 
307 
310  const LinearProblem<ScalarType,MV,OP>& getProblem() const override {
311  return *problem_;
312  }
313 
316  Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override;
317 
321  return params_;
322  }
323 
330  return Teuchos::tuple(timerSolve_);
331  }
332 
338  MagnitudeType achievedTol() const override {
339  return achievedTol_;
340  }
341 
343  int getNumIters() const override {
344  return numIters_;
345  }
346 
349  bool isLOADetected() const override { return false; }
350 
352 
354 
355 
357  void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) override {
358  problem_ = problem;
359  }
360 
362  void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params ) override;
363 
365 
367 
368 
372  void reset( const ResetType type ) override {
373  if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) {
374  bool set = problem_->setProblem();
375  if (!set)
376  throw "Could not set problem.";
377  }
378  else if (type & Belos::RecycleSubspace) {
379  keff = 0;
380  }
381  }
383 
385 
386 
413  ReturnType solve() override;
414 
416 
418 
420  std::string description() const override;
421 
423 
424  private:
425 
426  // Called by all constructors; Contains init instructions common to all constructors
427  void init();
428 
429  // Initialize solver state storage
430  void initializeStateStorage();
431 
432  // Compute updated recycle space given existing recycle space and newly generated Krylov space
433  void buildRecycleSpace2(Teuchos::RCP<GCRODRIter<ScalarType,MV,OP> > gcrodr_iter);
434 
435  // Computes harmonic eigenpairs of projected matrix created during the priming solve.
436  // HH is the projected problem from the initial cycle of Gmres, it is (at least) of dimension m+1 x m.
437  // PP contains the harmonic eigenvectors corresponding to the recycledBlocks eigenvalues of smallest magnitude.
438  // The return value is the number of vectors needed to be stored, recycledBlocks or recycledBlocks+1.
439  int getHarmonicVecs1(int m,
442 
443  // Computes harmonic eigenpairs of projected matrix created during one cycle.
444  // HH is the total block projected problem from the GCRO-DR algorithm, it is (at least) of dimension keff+m+1 x keff+m.
445  // VV is the Krylov vectors from the projected GMRES algorithm, which has (at least) m+1 vectors.
446  // PP contains the harmonic eigenvectors corresponding to the recycledBlocks eigenvalues of smallest magnitude.
447  // The return value is the number of vectors needed to be stored, recycledBlocks or recycledBlocks+1.
448  int getHarmonicVecs2(int keff, int m,
450  const Teuchos::RCP<const MV>& VV,
452 
453  // Sort list of n floating-point numbers and return permutation vector
454  void sort(std::vector<MagnitudeType>& dlist, int n, std::vector<int>& iperm);
455 
456  // Lapack interface
458 
459  // Linear problem.
461 
462  // Output manager.
464  Teuchos::RCP<std::ostream> outputStream_;
465 
466  // Status test.
470  Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > expConvTest_, impConvTest_;
472 
477 
478  // Current parameter list.
480 
481  // Default solver values.
482  static constexpr double orthoKappa_default_ = 0.0;
483  static constexpr int maxRestarts_default_ = 100;
484  static constexpr int maxIters_default_ = 1000;
485  static constexpr int numBlocks_default_ = 50;
486  static constexpr int blockSize_default_ = 1;
487  static constexpr int recycledBlocks_default_ = 5;
488  static constexpr int verbosity_default_ = Belos::Errors;
489  static constexpr int outputStyle_default_ = Belos::General;
490  static constexpr int outputFreq_default_ = -1;
491  static constexpr const char * impResScale_default_ = "Norm of Preconditioned Initial Residual";
492  static constexpr const char * expResScale_default_ = "Norm of Initial Residual";
493  static constexpr const char * label_default_ = "Belos";
494  static constexpr const char * orthoType_default_ = "ICGS";
495 
496  // Current solver values.
497  MagnitudeType convTol_, orthoKappa_, achievedTol_;
498  int maxRestarts_, maxIters_, numIters_;
499  int verbosity_, outputStyle_, outputFreq_;
500  std::string orthoType_;
501  std::string impResScale_, expResScale_;
502 
504  // Solver State Storage
506  //
507  // The number of blocks and recycle blocks (m and k, respectively)
508  int numBlocks_, recycledBlocks_;
509  // Current size of recycled subspace
510  int keff;
511  //
512  // Residual vector
513  Teuchos::RCP<MV> r_;
514  //
515  // Search space
516  Teuchos::RCP<MV> V_;
517  //
518  // Recycled subspace and its image
519  Teuchos::RCP<MV> U_, C_;
520  //
521  // Updated recycle space and its image
522  Teuchos::RCP<MV> U1_, C1_;
523  //
524  // Storage used in constructing harmonic Ritz values/vectors
530  std::vector<ScalarType> tau_;
531  std::vector<ScalarType> work_;
533  std::vector<int> ipiv_;
535 
536  // Timers.
537  std::string label_;
538  Teuchos::RCP<Teuchos::Time> timerSolve_;
539 
540  // Internal state variables.
541  bool isSet_;
542 
543  // Have we generated or regenerated a recycle space yet this solve?
544  bool builtRecycleSpace_;
545  };
546 
547 
548 // Empty Constructor
549 template<class ScalarType, class MV, class OP>
551  achievedTol_(0.0),
552  numIters_(0)
553 {
554  init ();
555 }
556 
557 
558 // Basic Constructor
559 template<class ScalarType, class MV, class OP>
563  achievedTol_(0.0),
564  numIters_(0)
565 {
566  // Initialize local pointers to null, and initialize local variables
567  // to default values.
568  init ();
569 
571  problem == Teuchos::null, std::invalid_argument,
572  "Belos::GCRODRSolMgr constructor: The solver manager's "
573  "constructor needs the linear problem argument 'problem' "
574  "to be non-null.");
575  problem_ = problem;
576 
577  // Set the parameters using the list that was passed in. If null,
578  // we defer initialization until a non-null list is set (by the
579  // client calling setParameters(), or by calling solve() -- in
580  // either case, a null parameter list indicates that default
581  // parameters should be used).
582  if (! pl.is_null ()) {
583  setParameters (pl);
584  }
585 }
586 
587 // Common instructions executed in all constructors
588 template<class ScalarType, class MV, class OP>
590  outputStream_ = Teuchos::rcpFromRef(std::cout);
592  orthoKappa_ = orthoKappa_default_;
593  maxRestarts_ = maxRestarts_default_;
594  maxIters_ = maxIters_default_;
595  numBlocks_ = numBlocks_default_;
596  recycledBlocks_ = recycledBlocks_default_;
597  verbosity_ = verbosity_default_;
598  outputStyle_ = outputStyle_default_;
599  outputFreq_ = outputFreq_default_;
600  orthoType_ = orthoType_default_;
601  impResScale_ = impResScale_default_;
602  expResScale_ = expResScale_default_;
603  label_ = label_default_;
604  isSet_ = false;
605  builtRecycleSpace_ = false;
606  keff = 0;
607  r_ = Teuchos::null;
608  V_ = Teuchos::null;
609  U_ = Teuchos::null;
610  C_ = Teuchos::null;
611  U1_ = Teuchos::null;
612  C1_ = Teuchos::null;
613  PP_ = Teuchos::null;
614  HP_ = Teuchos::null;
615  H2_ = Teuchos::null;
616  R_ = Teuchos::null;
617  H_ = Teuchos::null;
618  B_ = Teuchos::null;
619 }
620 
621 template<class ScalarType, class MV, class OP>
622 void
625 {
626  using Teuchos::isParameterType;
627  using Teuchos::getParameter;
628  using Teuchos::null;
630  using Teuchos::parameterList;
631  using Teuchos::RCP;
632  using Teuchos::rcp;
633  using Teuchos::rcp_dynamic_cast;
634  using Teuchos::rcpFromRef;
638 
639  // The default parameter list contains all parameters that
640  // GCRODRSolMgr understands, and none that it doesn't understand.
641  RCP<const ParameterList> defaultParams = getValidParameters();
642 
643  // Create the internal parameter list if one doesn't already exist.
644  //
645  // (mfh 28 Feb 2011, 10 Mar 2011) At the time this code was written,
646  // ParameterList did not have validators or validateParameters().
647  // This is why the code below carefully validates the parameters one
648  // by one and fills in defaults. This code could be made a lot
649  // shorter by using validators. To do so, we would have to define
650  // appropriate validators for all the parameters. (This would more
651  // or less just move all that validation code out of this routine
652  // into to getValidParameters().)
653  //
654  // For an analogous reason, GCRODRSolMgr defines default parameter
655  // values as class data, as well as in the default ParameterList.
656  // This redundancy could be removed by defining the default
657  // parameter values only in the default ParameterList (which
658  // documents each parameter as well -- handy!).
659  if (params_.is_null()) {
660  params_ = parameterList (*defaultParams);
661  } else {
662  // A common case for setParameters() is for it to be called at the
663  // beginning of the solve() routine. This follows the Belos
664  // pattern of delaying initialization until the last possible
665  // moment (when the user asks Belos to perform the solve). In
666  // this common case, we save ourselves a deep copy of the input
667  // parameter list.
668  if (params_ != params) {
669  // Make a deep copy of the input parameter list. This allows
670  // the caller to modify or change params later, without
671  // affecting the behavior of this solver. This solver will then
672  // only change its internal parameters if setParameters() is
673  // called again.
674  params_ = parameterList (*params);
675  }
676 
677  // Fill in any missing parameters and their default values. Also,
678  // throw an exception if the parameter list has any misspelled or
679  // "extra" parameters. If you don't like this behavior, you'll
680  // want to replace the line of code below with your desired
681  // validation scheme. Note that Teuchos currently only implements
682  // two options:
683  //
684  // 1. validateParameters() requires that params_ has all the
685  // parameters that the default list has, and none that it
686  // doesn't have.
687  //
688  // 2. validateParametersAndSetDefaults() fills in missing
689  // parameters in params_ using the default list, but requires
690  // that any parameter provided in params_ is also in the
691  // default list.
692  //
693  // Here is an easy way to ignore any "extra" or misspelled
694  // parameters: Make a deep copy of the default list, fill in any
695  // "missing" parameters from the _input_ list, and then validate
696  // the input list using the deep copy of the default list. We
697  // show this in code:
698  //
699  // RCP<ParameterList> defaultCopy = parameterList (*getValidParameters ());
700  // defaultCopy->validateParametersAndSetDefaults (params);
701  // params->validateParametersAndSetDefaults (defaultCopy);
702  //
703  // This method is not entirely robust, because the input list may
704  // have incorrect validators set for existing parameters in the
705  // default list. This would then cause "validation" of the
706  // default list to throw an exception. As a result, we've chosen
707  // for now to be intolerant of misspellings and "extra" parameters
708  // in the input list.
709  params_->validateParametersAndSetDefaults (*defaultParams);
710  }
711 
712  // Check for maximum number of restarts.
713  if (params->isParameter ("Maximum Restarts")) {
714  maxRestarts_ = params->get("Maximum Restarts", maxRestarts_default_);
715 
716  // Update parameter in our list.
717  params_->set ("Maximum Restarts", maxRestarts_);
718  }
719 
720  // Check for maximum number of iterations
721  if (params->isParameter ("Maximum Iterations")) {
722  maxIters_ = params->get ("Maximum Iterations", maxIters_default_);
723 
724  // Update parameter in our list and in status test.
725  params_->set ("Maximum Iterations", maxIters_);
726  if (! maxIterTest_.is_null())
727  maxIterTest_->setMaxIters (maxIters_);
728  }
729 
730  // Check for the maximum number of blocks.
731  if (params->isParameter ("Num Blocks")) {
732  numBlocks_ = params->get ("Num Blocks", numBlocks_default_);
733  TEUCHOS_TEST_FOR_EXCEPTION(numBlocks_ <= 0, std::invalid_argument,
734  "Belos::GCRODRSolMgr: The \"Num Blocks\" parameter must "
735  "be strictly positive, but you specified a value of "
736  << numBlocks_ << ".");
737  // Update parameter in our list.
738  params_->set ("Num Blocks", numBlocks_);
739  }
740 
741  // Check for the maximum number of blocks.
742  if (params->isParameter ("Num Recycled Blocks")) {
743  recycledBlocks_ = params->get ("Num Recycled Blocks",
744  recycledBlocks_default_);
745  TEUCHOS_TEST_FOR_EXCEPTION(recycledBlocks_ <= 0, std::invalid_argument,
746  "Belos::GCRODRSolMgr: The \"Num Recycled Blocks\" "
747  "parameter must be strictly positive, but you specified "
748  "a value of " << recycledBlocks_ << ".");
749  TEUCHOS_TEST_FOR_EXCEPTION(recycledBlocks_ >= numBlocks_, std::invalid_argument,
750  "Belos::GCRODRSolMgr: The \"Num Recycled Blocks\" "
751  "parameter must be less than the \"Num Blocks\" "
752  "parameter, but you specified \"Num Recycled Blocks\" "
753  "= " << recycledBlocks_ << " and \"Num Blocks\" = "
754  << numBlocks_ << ".");
755  // Update parameter in our list.
756  params_->set("Num Recycled Blocks", recycledBlocks_);
757  }
758 
759  // Check to see if the timer label changed. If it did, update it in
760  // the parameter list, and create a new timer with that label (if
761  // Belos was compiled with timers enabled).
762  if (params->isParameter ("Timer Label")) {
763  std::string tempLabel = params->get ("Timer Label", label_default_);
764 
765  // Update parameter in our list and solver timer
766  if (tempLabel != label_) {
767  label_ = tempLabel;
768  params_->set ("Timer Label", label_);
769  std::string solveLabel = label_ + ": GCRODRSolMgr total solve time";
770 #ifdef BELOS_TEUCHOS_TIME_MONITOR
771  timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel);
772 #endif
773  if (ortho_ != Teuchos::null) {
774  ortho_->setLabel( label_ );
775  }
776  }
777  }
778 
779  // Check for a change in verbosity level
780  if (params->isParameter ("Verbosity")) {
781  if (isParameterType<int> (*params, "Verbosity")) {
782  verbosity_ = params->get ("Verbosity", verbosity_default_);
783  } else {
784  verbosity_ = (int) getParameter<Belos::MsgType> (*params, "Verbosity");
785  }
786  // Update parameter in our list.
787  params_->set ("Verbosity", verbosity_);
788  // If the output manager (printer_) is null, then we will
789  // instantiate it later with the correct verbosity.
790  if (! printer_.is_null())
791  printer_->setVerbosity (verbosity_);
792  }
793 
794  // Check for a change in output style
795  if (params->isParameter ("Output Style")) {
796  if (isParameterType<int> (*params, "Output Style")) {
797  outputStyle_ = params->get ("Output Style", outputStyle_default_);
798  } else {
799  outputStyle_ = (int) getParameter<OutputType> (*params, "Output Style");
800  }
801 
802  // Update parameter in our list.
803  params_->set ("Output Style", outputStyle_);
804  // We will (re)instantiate the output status test afresh below.
805  outputTest_ = null;
806  }
807 
808  // Get the output stream for the output manager.
809  //
810  // While storing the output stream in the parameter list (either as
811  // an RCP or as a nonconst reference) is convenient and safe for
812  // programming, it makes it impossible to serialize the parameter
813  // list, read it back in from the serialized representation, and get
814  // the same output stream as before. This is because output streams
815  // may be arbitrary constructed objects.
816  //
817  // In case the user tried reading in the parameter list from a
818  // serialized representation and the output stream can't be read
819  // back in, we set the output stream to point to std::cout. This
820  // ensures reasonable behavior.
821  if (params->isParameter ("Output Stream")) {
822  try {
823  outputStream_ = getParameter<RCP<std::ostream> > (*params, "Output Stream");
824  } catch (InvalidParameter&) {
825  outputStream_ = rcpFromRef (std::cout);
826  }
827  // We assume that a null output stream indicates that the user
828  // doesn't want to print anything, so we replace it with a "black
829  // hole" stream that prints nothing sent to it. (We can't use a
830  // null output stream, since the output manager always sends
831  // things it wants to print to the output stream.)
832  if (outputStream_.is_null()) {
833  outputStream_ = rcp (new Teuchos::oblackholestream);
834  }
835  // Update parameter in our list.
836  params_->set ("Output Stream", outputStream_);
837  // If the output manager (printer_) is null, then we will
838  // instantiate it later with the correct output stream.
839  if (! printer_.is_null()) {
840  printer_->setOStream (outputStream_);
841  }
842  }
843 
844  // frequency level
845  if (verbosity_ & Belos::StatusTestDetails) {
846  if (params->isParameter ("Output Frequency")) {
847  outputFreq_ = params->get ("Output Frequency", outputFreq_default_);
848  }
849 
850  // Update parameter in out list and output status test.
851  params_->set("Output Frequency", outputFreq_);
852  if (! outputTest_.is_null())
853  outputTest_->setOutputFrequency (outputFreq_);
854  }
855 
856  // Create output manager if we need to, using the verbosity level
857  // and output stream that we fetched above. We do this here because
858  // instantiating an OrthoManager using OrthoManagerFactory requires
859  // a valid OutputManager.
860  if (printer_.is_null()) {
861  printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_));
862  }
863 
864  // Get the orthogonalization manager name ("Orthogonalization").
865  //
866  // Getting default values for the orthogonalization manager
867  // parameters ("Orthogonalization Parameters") requires knowing the
868  // orthogonalization manager name. Save it for later, and also
869  // record whether it's different than before.
871  bool changedOrthoType = false;
872  if (params->isParameter ("Orthogonalization")) {
873  const std::string& tempOrthoType =
874  params->get ("Orthogonalization", orthoType_default_);
875  // Ensure that the specified orthogonalization type is valid.
876  if (! factory.isValidName (tempOrthoType)) {
877  std::ostringstream os;
878  os << "Belos::GCRODRSolMgr: Invalid orthogonalization name \""
879  << tempOrthoType << "\". The following are valid options "
880  << "for the \"Orthogonalization\" name parameter: ";
881  factory.printValidNames (os);
882  throw std::invalid_argument (os.str());
883  }
884  if (tempOrthoType != orthoType_) {
885  changedOrthoType = true;
886  orthoType_ = tempOrthoType;
887  // Update parameter in our list.
888  params_->set ("Orthogonalization", orthoType_);
889  }
890  }
891 
892  // Get any parameters for the orthogonalization ("Orthogonalization
893  // Parameters"). If not supplied, the orthogonalization manager
894  // factory will supply default values.
895  //
896  // NOTE (mfh 12 Jan 2011) For the sake of backwards compatibility,
897  // if params has an "Orthogonalization Constant" parameter and the
898  // DGKS orthogonalization manager is to be used, the value of this
899  // parameter will override DGKS's "depTol" parameter.
900  //
901  // Users must supply the orthogonalization manager parameters as a
902  // sublist (supplying it as an RCP<ParameterList> would make the
903  // resulting parameter list not serializable).
904  RCP<ParameterList> orthoParams;
905  { // The nonmember function sublist() returns an RCP<ParameterList>,
906  // which is what we want here.
907  using Teuchos::sublist;
908  // Abbreviation to avoid typos.
909  const std::string paramName ("Orthogonalization Parameters");
910 
911  try {
912  orthoParams = sublist (params_, paramName, true);
913  } catch (InvalidParameter&) {
914  // We didn't get the parameter list from params, so get a
915  // default parameter list from the OrthoManagerFactory. Modify
916  // params_ so that it has the default parameter list, and set
917  // orthoParams to ensure it's a sublist of params_ (and not just
918  // a copy of one).
919  params_->set (paramName, factory.getDefaultParameters (orthoType_));
920  orthoParams = sublist (params_, paramName, true);
921  }
922  }
923  TEUCHOS_TEST_FOR_EXCEPTION(orthoParams.is_null(), std::logic_error,
924  "Failed to get orthogonalization parameters. "
925  "Please report this bug to the Belos developers.");
926 
927  // Instantiate a new MatOrthoManager subclass instance if necessary.
928  // If not necessary, then tell the existing instance about the new
929  // parameters.
930  if (ortho_.is_null() || changedOrthoType) {
931  // We definitely need to make a new MatOrthoManager, since either
932  // we haven't made one yet, or we've changed orthogonalization
933  // methods. Creating the orthogonalization manager requires that
934  // the OutputManager (printer_) already be initialized.
935  ortho_ = factory.makeMatOrthoManager (orthoType_, null, printer_,
936  label_, orthoParams);
937  } else {
938  // If the MatOrthoManager implements the ParameterListAcceptor
939  // mix-in interface, we can propagate changes to its parameters
940  // without reinstantiating the MatOrthoManager.
941  //
942  // We recommend that all MatOrthoManager subclasses implement
943  // Teuchos::ParameterListAcceptor, but do not (yet) require this.
944  typedef Teuchos::ParameterListAcceptor PLA;
945  RCP<PLA> pla = rcp_dynamic_cast<PLA> (ortho_);
946  if (pla.is_null()) {
947  // Oops, it's not a ParameterListAcceptor. We have to
948  // reinstantiate the MatOrthoManager in order to pass in the
949  // possibly new parameters.
950  ortho_ = factory.makeMatOrthoManager (orthoType_, null, printer_,
951  label_, orthoParams);
952  } else {
953  pla->setParameterList (orthoParams);
954  }
955  }
956 
957  // The DGKS orthogonalization accepts a "Orthogonalization Constant"
958  // parameter (also called kappa in the code, but not in the
959  // parameter list). If its value is provided in the given parameter
960  // list, and its value is positive, use it. Ignore negative values.
961  //
962  // NOTE (mfh 12 Jan 2011) This overrides the "depTol" parameter that
963  // may have been specified in "Orthogonalization Parameters". We
964  // retain this behavior for backwards compatibility.
965  if (params->isParameter ("Orthogonalization Constant")) {
966  MagnitudeType orthoKappa = orthoKappa_default_;
967  if (params->isType<MagnitudeType> ("Orthogonalization Constant")) {
968  orthoKappa = params->get ("Orthogonalization Constant", orthoKappa);
969  }
970  else {
971  orthoKappa = params->get ("Orthogonalization Constant", orthoKappa_default_);
972  }
973 
974  if (orthoKappa > 0) {
975  orthoKappa_ = orthoKappa;
976  // Update parameter in our list.
977  params_->set("Orthogonalization Constant", orthoKappa_);
978  // Only DGKS currently accepts this parameter.
979  if (orthoType_ == "DGKS" && ! ortho_.is_null()) {
980  typedef DGKSOrthoManager<ScalarType, MV, OP> ortho_man_type;
981  // This cast should always succeed; it's a bug
982  // otherwise. (If the cast fails, then orthoType_
983  // doesn't correspond to the OrthoManager subclass
984  // instance that we think we have, so we initialized the
985  // wrong subclass somehow.)
986  rcp_dynamic_cast<ortho_man_type>(ortho_)->setDepTol (orthoKappa_);
987  }
988  }
989  }
990 
991  // Convergence
992  typedef Belos::StatusTestCombo<ScalarType,MV,OP> StatusTestCombo_t;
993  typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP> StatusTestResNorm_t;
994 
995  // Check for convergence tolerance
996  if (params->isParameter("Convergence Tolerance")) {
997  if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
998  convTol_ = params->get ("Convergence Tolerance",
999  static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
1000  }
1001  else {
1002  convTol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
1003  }
1004 
1005  // Update parameter in our list and residual tests.
1006  params_->set ("Convergence Tolerance", convTol_);
1007  if (! impConvTest_.is_null())
1008  impConvTest_->setTolerance (convTol_);
1009  if (! expConvTest_.is_null())
1010  expConvTest_->setTolerance (convTol_);
1011  }
1012 
1013  // Check for a change in scaling, if so we need to build new residual tests.
1014  if (params->isParameter ("Implicit Residual Scaling")) {
1015  std::string tempImpResScale =
1016  getParameter<std::string> (*params, "Implicit Residual Scaling");
1017 
1018  // Only update the scaling if it's different.
1019  if (impResScale_ != tempImpResScale) {
1020  ScaleType impResScaleType = convertStringToScaleType (tempImpResScale);
1021  impResScale_ = tempImpResScale;
1022 
1023  // Update parameter in our list and residual tests
1024  params_->set("Implicit Residual Scaling", impResScale_);
1025  // NOTE (mfh 28 Feb 2011) StatusTestImpResNorm only lets you
1026  // call defineScaleForm() once. The code below attempts to call
1027  // defineScaleForm(); if the scale form has already been
1028  // defined, it constructs a new StatusTestImpResNorm instance.
1029  // StatusTestImpResNorm really should not expose the
1030  // defineScaleForm() method, since it's serving an
1031  // initialization purpose; all initialization should happen in
1032  // the constructor whenever possible. In that case, the code
1033  // below could be simplified into a single (re)instantiation.
1034  if (! impConvTest_.is_null()) {
1035  try {
1036  impConvTest_->defineScaleForm (impResScaleType, Belos::TwoNorm);
1037  }
1038  catch (StatusTestError&) {
1039  // Delete the convergence test so it gets constructed again.
1040  impConvTest_ = null;
1041  convTest_ = null;
1042  }
1043  }
1044  }
1045  }
1046 
1047  if (params->isParameter("Explicit Residual Scaling")) {
1048  std::string tempExpResScale =
1049  getParameter<std::string> (*params, "Explicit Residual Scaling");
1050 
1051  // Only update the scaling if it's different.
1052  if (expResScale_ != tempExpResScale) {
1053  ScaleType expResScaleType = convertStringToScaleType (tempExpResScale);
1054  expResScale_ = tempExpResScale;
1055 
1056  // Update parameter in our list and residual tests
1057  params_->set("Explicit Residual Scaling", expResScale_);
1058  // NOTE (mfh 28 Feb 2011) See note above on the (re)construction
1059  // of StatusTestImpResNorm.
1060  if (! expConvTest_.is_null()) {
1061  try {
1062  expConvTest_->defineScaleForm (expResScaleType, Belos::TwoNorm);
1063  }
1064  catch (StatusTestError&) {
1065  // Delete the convergence test so it gets constructed again.
1066  expConvTest_ = null;
1067  convTest_ = null;
1068  }
1069  }
1070  }
1071  }
1072  //
1073  // Create iteration stopping criteria ("status tests") if we need
1074  // to, by combining three different stopping criteria.
1075  //
1076  // First, construct maximum-number-of-iterations stopping criterion.
1077  if (maxIterTest_.is_null())
1078  maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP> (maxIters_));
1079 
1080  // Implicit residual test, using the native residual to determine if
1081  // convergence was achieved.
1082  if (impConvTest_.is_null()) {
1083  impConvTest_ = rcp (new StatusTestResNorm_t (convTol_));
1084  impConvTest_->defineScaleForm (convertStringToScaleType (impResScale_),
1085  Belos::TwoNorm);
1086  }
1087 
1088  // Explicit residual test once the native residual is below the tolerance
1089  if (expConvTest_.is_null()) {
1090  expConvTest_ = rcp (new StatusTestResNorm_t (convTol_));
1091  expConvTest_->defineResForm (StatusTestResNorm_t::Explicit, Belos::TwoNorm);
1092  expConvTest_->defineScaleForm (convertStringToScaleType (expResScale_),
1093  Belos::TwoNorm);
1094  }
1095  // Convergence test first tests the implicit residual, then the
1096  // explicit residual if the implicit residual test passes.
1097  if (convTest_.is_null()) {
1098  convTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::SEQ,
1099  impConvTest_,
1100  expConvTest_));
1101  }
1102  // Construct the complete iteration stopping criterion:
1103  //
1104  // "Stop iterating if the maximum number of iterations has been
1105  // reached, or if the convergence test passes."
1106  sTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::OR,
1107  maxIterTest_,
1108  convTest_));
1109  // Create the status test output class.
1110  // This class manages and formats the output from the status test.
1111  StatusTestOutputFactory<ScalarType,MV,OP> stoFactory (outputStyle_);
1112  outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_,
1114 
1115  // Set the solver string for the output test
1116  std::string solverDesc = " GCRODR ";
1117  outputTest_->setSolverDesc( solverDesc );
1118 
1119  // Create the timer if we need to.
1120  if (timerSolve_.is_null()) {
1121  std::string solveLabel = label_ + ": GCRODRSolMgr total solve time";
1122 #ifdef BELOS_TEUCHOS_TIME_MONITOR
1123  timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
1124 #endif
1125  }
1126 
1127  // Inform the solver manager that the current parameters were set.
1128  isSet_ = true;
1129 }
1130 
1131 
1132 template<class ScalarType, class MV, class OP>
1135 {
1136  using Teuchos::ParameterList;
1137  using Teuchos::parameterList;
1138  using Teuchos::RCP;
1139 
1140  static RCP<const ParameterList> validPL;
1141  if (is_null(validPL)) {
1142  RCP<ParameterList> pl = parameterList ();
1143 
1144  // Set all the valid parameters and their default values.
1145  pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
1146  "The relative residual tolerance that needs to be achieved by the\n"
1147  "iterative solver in order for the linear system to be declared converged.");
1148  pl->set("Maximum Restarts", static_cast<int>(maxRestarts_default_),
1149  "The maximum number of cycles allowed for each\n"
1150  "set of RHS solved.");
1151  pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
1152  "The maximum number of iterations allowed for each\n"
1153  "set of RHS solved.");
1154  // mfh 25 Oct 2010: "Block Size" must be 1 because GCRODR is
1155  // currently not a block method: i.e., it does not work on
1156  // multiple right-hand sides at once.
1157  pl->set("Block Size", static_cast<int>(blockSize_default_),
1158  "Block Size Parameter -- currently must be 1 for GCRODR");
1159  pl->set("Num Blocks", static_cast<int>(numBlocks_default_),
1160  "The maximum number of vectors allowed in the Krylov subspace\n"
1161  "for each set of RHS solved.");
1162  pl->set("Num Recycled Blocks", static_cast<int>(recycledBlocks_default_),
1163  "The maximum number of vectors in the recycled subspace." );
1164  pl->set("Verbosity", static_cast<int>(verbosity_default_),
1165  "What type(s) of solver information should be outputted\n"
1166  "to the output stream.");
1167  pl->set("Output Style", static_cast<int>(outputStyle_default_),
1168  "What style is used for the solver information outputted\n"
1169  "to the output stream.");
1170  pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
1171  "How often convergence information should be outputted\n"
1172  "to the output stream.");
1173  pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
1174  "A reference-counted pointer to the output stream where all\n"
1175  "solver output is sent.");
1176  pl->set("Implicit Residual Scaling", static_cast<const char *>(impResScale_default_),
1177  "The type of scaling used in the implicit residual convergence test.");
1178  pl->set("Explicit Residual Scaling", static_cast<const char *>(expResScale_default_),
1179  "The type of scaling used in the explicit residual convergence test.");
1180  pl->set("Timer Label", static_cast<const char *>(label_default_),
1181  "The string to use as a prefix for the timer labels.");
1182  {
1184  pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
1185  "The type of orthogonalization to use. Valid options: " +
1186  factory.validNamesString());
1187  RCP<const ParameterList> orthoParams =
1188  factory.getDefaultParameters (orthoType_default_);
1189  pl->set ("Orthogonalization Parameters", *orthoParams,
1190  "Parameters specific to the type of orthogonalization used.");
1191  }
1192  pl->set("Orthogonalization Constant",static_cast<MagnitudeType>(orthoKappa_default_),
1193  "When using DGKS orthogonalization: the \"depTol\" constant, used "
1194  "to determine whether another step of classical Gram-Schmidt is "
1195  "necessary. Otherwise ignored.");
1196  validPL = pl;
1197  }
1198  return validPL;
1199 }
1200 
1201 // initializeStateStorage
1202 template<class ScalarType, class MV, class OP>
1204 
1205  ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
1206 
1207  // Check if there is any multivector to clone from.
1208  Teuchos::RCP<const MV> rhsMV = problem_->getRHS();
1209  if (rhsMV == Teuchos::null) {
1210  // Nothing to do
1211  return;
1212  }
1213  else {
1214 
1215  // Initialize the state storage
1216  TEUCHOS_TEST_FOR_EXCEPTION(static_cast<ptrdiff_t>(numBlocks_) > MVT::GetGlobalLength(*rhsMV),std::invalid_argument,
1217  "Belos::GCRODRSolMgr::initializeStateStorage(): Cannot generate a Krylov basis with dimension larger the operator!");
1218 
1219  // If the subspace has not been initialized before, generate it using the RHS from lp_.
1220  if (U_ == Teuchos::null) {
1221  U_ = MVT::Clone( *rhsMV, recycledBlocks_+1 );
1222  }
1223  else {
1224  // Generate U_ by cloning itself ONLY if more space is needed.
1225  if (MVT::GetNumberVecs(*U_) < recycledBlocks_+1) {
1226  Teuchos::RCP<const MV> tmp = U_;
1227  U_ = MVT::Clone( *tmp, recycledBlocks_+1 );
1228  }
1229  }
1230 
1231  // If the subspace has not been initialized before, generate it using the RHS from lp_.
1232  if (C_ == Teuchos::null) {
1233  C_ = MVT::Clone( *rhsMV, recycledBlocks_+1 );
1234  }
1235  else {
1236  // Generate C_ by cloning itself ONLY if more space is needed.
1237  if (MVT::GetNumberVecs(*C_) < recycledBlocks_+1) {
1238  Teuchos::RCP<const MV> tmp = C_;
1239  C_ = MVT::Clone( *tmp, recycledBlocks_+1 );
1240  }
1241  }
1242 
1243  // If the subspace has not been initialized before, generate it using the RHS from lp_.
1244  if (V_ == Teuchos::null) {
1245  V_ = MVT::Clone( *rhsMV, numBlocks_+1 );
1246  }
1247  else {
1248  // Generate V_ by cloning itself ONLY if more space is needed.
1249  if (MVT::GetNumberVecs(*V_) < numBlocks_+1) {
1250  Teuchos::RCP<const MV> tmp = V_;
1251  V_ = MVT::Clone( *tmp, numBlocks_+1 );
1252  }
1253  }
1254 
1255  // If the subspace has not been initialized before, generate it using the RHS from lp_.
1256  if (U1_ == Teuchos::null) {
1257  U1_ = MVT::Clone( *rhsMV, recycledBlocks_+1 );
1258  }
1259  else {
1260  // Generate U1_ by cloning itself ONLY if more space is needed.
1261  if (MVT::GetNumberVecs(*U1_) < recycledBlocks_+1) {
1262  Teuchos::RCP<const MV> tmp = U1_;
1263  U1_ = MVT::Clone( *tmp, recycledBlocks_+1 );
1264  }
1265  }
1266 
1267  // If the subspace has not been initialized before, generate it using the RHS from lp_.
1268  if (C1_ == Teuchos::null) {
1269  C1_ = MVT::Clone( *rhsMV, recycledBlocks_+1 );
1270  }
1271  else {
1272  // Generate C1_ by cloning itself ONLY if more space is needed.
1273  if (MVT::GetNumberVecs(*C1_) < recycledBlocks_+1) {
1274  Teuchos::RCP<const MV> tmp = C1_;
1275  C1_ = MVT::Clone( *tmp, recycledBlocks_+1 );
1276  }
1277  }
1278 
1279  // Generate r_ only if it doesn't exist
1280  if (r_ == Teuchos::null)
1281  r_ = MVT::Clone( *rhsMV, 1 );
1282 
1283  // Size of tau_ will change during computation, so just be sure it starts with appropriate size
1284  tau_.resize(recycledBlocks_+1);
1285 
1286  // Size of work_ will change during computation, so just be sure it starts with appropriate size
1287  work_.resize(recycledBlocks_+1);
1288 
1289  // Size of ipiv_ will change during computation, so just be sure it starts with appropriate size
1290  ipiv_.resize(recycledBlocks_+1);
1291 
1292  // Generate H2_ only if it doesn't exist, otherwise resize it.
1293  if (H2_ == Teuchos::null)
1294  H2_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( numBlocks_+recycledBlocks_+2, numBlocks_+recycledBlocks_+1 ) );
1295  else {
1296  if ( (H2_->numRows() != numBlocks_+recycledBlocks_+2) || (H2_->numCols() != numBlocks_+recycledBlocks_+1) )
1297  H2_->reshape( numBlocks_+recycledBlocks_+2, numBlocks_+recycledBlocks_+1 );
1298  }
1299  H2_->putScalar(zero);
1300 
1301  // Generate R_ only if it doesn't exist, otherwise resize it.
1302  if (R_ == Teuchos::null)
1303  R_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( recycledBlocks_+1, recycledBlocks_+1 ) );
1304  else {
1305  if ( (R_->numRows() != recycledBlocks_+1) || (R_->numCols() != recycledBlocks_+1) )
1306  R_->reshape( recycledBlocks_+1, recycledBlocks_+1 );
1307  }
1308  R_->putScalar(zero);
1309 
1310  // Generate PP_ only if it doesn't exist, otherwise resize it.
1311  if (PP_ == Teuchos::null)
1312  PP_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( numBlocks_+recycledBlocks_+2, recycledBlocks_+1 ) );
1313  else {
1314  if ( (PP_->numRows() != numBlocks_+recycledBlocks_+2) || (PP_->numCols() != recycledBlocks_+1) )
1315  PP_->reshape( numBlocks_+recycledBlocks_+2, recycledBlocks_+1 );
1316  }
1317 
1318  // Generate HP_ only if it doesn't exist, otherwise resize it.
1319  if (HP_ == Teuchos::null)
1320  HP_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( numBlocks_+recycledBlocks_+2, numBlocks_+recycledBlocks_+1 ) );
1321  else {
1322  if ( (HP_->numRows() != numBlocks_+recycledBlocks_+2) || (HP_->numCols() != numBlocks_+recycledBlocks_+1) )
1323  HP_->reshape( numBlocks_+recycledBlocks_+2, numBlocks_+recycledBlocks_+1 );
1324  }
1325 
1326  } // end else
1327 }
1328 
1329 
1330 // solve()
1331 template<class ScalarType, class MV, class OP>
1333  using Teuchos::RCP;
1334  using Teuchos::rcp;
1335 
1336  // Set the current parameters if they were not set before.
1337  // NOTE: This may occur if the user generated the solver manager with the default constructor and
1338  // then didn't set any parameters using setParameters().
1339  if (!isSet_) { setParameters( params_ ); }
1340 
1341  ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
1342  ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
1343  std::vector<int> index(numBlocks_+1);
1344 
1345  TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null,GCRODRSolMgrLinearProblemFailure, "Belos::GCRODRSolMgr::solve(): Linear problem is not a valid object.");
1346 
1347  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(),GCRODRSolMgrLinearProblemFailure,"Belos::GCRODRSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
1348 
1349  // Create indices for the linear systems to be solved.
1350  int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
1351  std::vector<int> currIdx(1);
1352  currIdx[0] = 0;
1353 
1354  // Inform the linear problem of the current linear system to solve.
1355  problem_->setLSIndex( currIdx );
1356 
1357  // Check the number of blocks and change them is necessary.
1358  ptrdiff_t dim = MVT::GetGlobalLength( *(problem_->getRHS()) );
1359  if (static_cast<ptrdiff_t>(numBlocks_) > dim) {
1360  numBlocks_ = Teuchos::as<int>(dim);
1361  printer_->stream(Warnings) <<
1362  "Warning! Requested Krylov subspace dimension is larger than operator dimension!" << std::endl <<
1363  " The maximum number of blocks allowed for the Krylov subspace will be adjusted to " << numBlocks_ << std::endl;
1364  params_->set("Num Blocks", numBlocks_);
1365  }
1366 
1367  // Assume convergence is achieved, then let any failed convergence set this to false.
1368  bool isConverged = true;
1369 
1370  // Initialize storage for all state variables
1371  initializeStateStorage();
1372 
1374  // Parameter list
1375  Teuchos::ParameterList plist;
1376 
1377  plist.set("Num Blocks",numBlocks_);
1378  plist.set("Recycled Blocks",recycledBlocks_);
1379 
1381  // GCRODR solver
1382 
1383  RCP<GCRODRIter<ScalarType,MV,OP> > gcrodr_iter;
1384  gcrodr_iter = rcp( new GCRODRIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,ortho_,plist) );
1385  // Number of iterations required to generate initial recycle space (if needed)
1386  int prime_iterations = 0;
1387 
1388  // Enter solve() iterations
1389  {
1390 #ifdef BELOS_TEUCHOS_TIME_MONITOR
1391  Teuchos::TimeMonitor slvtimer(*timerSolve_);
1392 #endif
1393 
1394  while ( numRHS2Solve > 0 ) {
1395 
1396  // Set flag indicating recycle space has not been generated this solve
1397  builtRecycleSpace_ = false;
1398 
1399  // Reset the status test.
1400  outputTest_->reset();
1401 
1403  // Initialize recycled subspace for GCRODR
1404 
1405  // If there is a subspace to recycle, recycle it, otherwise generate the initial recycled subspace.
1406  if (keff > 0) {
1408  "Belos::GCRODRSolMgr::solve(): Requested size of recycled subspace is not consistent with the current recycle subspace.");
1409 
1410  printer_->stream(Debug) << " Now solving RHS index " << currIdx[0] << " using recycled subspace of dimension " << keff << std::endl << std::endl;
1411  // Compute image of U_ under the new operator
1412  index.resize(keff);
1413  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1414  RCP<const MV> Utmp = MVT::CloneView( *U_, index );
1415  RCP<MV> Ctmp = MVT::CloneViewNonConst( *C_, index );
1416  problem_->apply( *Utmp, *Ctmp );
1417 
1418  RCP<MV> U1tmp = MVT::CloneViewNonConst( *U1_, index );
1419 
1420  // Orthogonalize this block
1421  // Get a matrix to hold the orthonormalization coefficients.
1423  int rank = ortho_->normalize(*Ctmp, rcp(&Rtmp,false));
1424  // Throw an error if we could not orthogonalize this block
1425  TEUCHOS_TEST_FOR_EXCEPTION(rank != keff,GCRODRSolMgrOrthoFailure,"Belos::GCRODRSolMgr::solve(): Failed to compute orthonormal basis for initial recycled subspace.");
1426 
1427  // U_ = U_*R^{-1}
1428  // First, compute LU factorization of R
1429  int info = 0;
1430  ipiv_.resize(Rtmp.numRows());
1431  lapack.GETRF(Rtmp.numRows(),Rtmp.numCols(),Rtmp.values(),Rtmp.stride(),&ipiv_[0],&info);
1432  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, GCRODRSolMgrLAPACKFailure,"Belos::GCRODRSolMgr::solve(): LAPACK _GETRF failed to compute an LU factorization.");
1433 
1434  // Now, form inv(R)
1435  int lwork = Rtmp.numRows();
1436  work_.resize(lwork);
1437  lapack.GETRI(Rtmp.numRows(),Rtmp.values(),Rtmp.stride(),&ipiv_[0],&work_[0],lwork,&info);
1438  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, GCRODRSolMgrLAPACKFailure,"Belos::GCRODRSolMgr::solve(): LAPACK _GETRI failed to invert triangular matrix.");
1439 
1440  // U_ = U1_; (via a swap)
1441  MVT::MvTimesMatAddMv( one, *Utmp, Rtmp, zero, *U1tmp );
1442  std::swap(U_, U1_);
1443 
1444  // Must reinitialize after swap
1445  index.resize(keff);
1446  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1447  Ctmp = MVT::CloneViewNonConst( *C_, index );
1448  Utmp = MVT::CloneView( *U_, index );
1449 
1450  // Compute C_'*r_
1452  problem_->computeCurrPrecResVec( &*r_ );
1453  MVT::MvTransMv( one, *Ctmp, *r_, Ctr );
1454 
1455  // Update solution ( x += U_*C_'*r_ )
1456  RCP<MV> update = MVT::Clone( *problem_->getCurrLHSVec(), 1 );
1457  MVT::MvInit( *update, 0.0 );
1458  MVT::MvTimesMatAddMv( one, *Utmp, Ctr, one, *update );
1459  problem_->updateSolution( update, true );
1460 
1461  // Update residual norm ( r -= C_*C_'*r_ )
1462  MVT::MvTimesMatAddMv( -one, *Ctmp, Ctr, one, *r_ );
1463 
1464  // We recycled space from previous call
1465  prime_iterations = 0;
1466 
1467  }
1468  else {
1469 
1470  // Do one cycle of Gmres to "prime the pump" if there is no subspace to recycle
1471  printer_->stream(Debug) << " No recycled subspace available for RHS index " << currIdx[0] << std::endl << std::endl;
1472 
1473  Teuchos::ParameterList primeList;
1474 
1475  // Tell the block solver that the block size is one.
1476  primeList.set("Num Blocks",numBlocks_);
1477  primeList.set("Recycled Blocks",0);
1478 
1479  // Create GCRODR iterator object to perform one cycle of GMRES.
1480  RCP<GCRODRIter<ScalarType,MV,OP> > gcrodr_prime_iter;
1481  gcrodr_prime_iter = rcp( new GCRODRIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,ortho_,primeList) );
1482 
1483  // Create the first block in the current Krylov basis (residual).
1484  problem_->computeCurrPrecResVec( &*r_ );
1485  index.resize( 1 ); index[0] = 0;
1486  RCP<MV> v0 = MVT::CloneViewNonConst( *V_, index );
1487  MVT::SetBlock(*r_,index,*v0); // V(:,0) = r
1488 
1489  // Set the new state and initialize the solver.
1491  index.resize( numBlocks_+1 );
1492  for (int ii=0; ii<(numBlocks_+1); ++ii) { index[ii] = ii; }
1493  newstate.V = MVT::CloneViewNonConst( *V_, index );
1494  newstate.U = Teuchos::null;
1495  newstate.C = Teuchos::null;
1496  newstate.H = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::View, *H2_, numBlocks_+1, numBlocks_, recycledBlocks_+1, recycledBlocks_+1 ) );
1497  newstate.B = Teuchos::null;
1498  newstate.curDim = 0;
1499  gcrodr_prime_iter->initialize(newstate);
1500 
1501  // Perform one cycle of GMRES
1502  bool primeConverged = false;
1503  try {
1504  gcrodr_prime_iter->iterate();
1505 
1506  // Check convergence first
1507  if ( convTest_->getStatus() == Passed ) {
1508  // we have convergence
1509  primeConverged = true;
1510  }
1511  }
1512  catch (const GCRODRIterOrthoFailure &e) {
1513  // Try to recover the most recent least-squares solution
1514  gcrodr_prime_iter->updateLSQR( gcrodr_prime_iter->getCurSubspaceDim() );
1515 
1516  // Check to see if the most recent least-squares solution yielded convergence.
1517  sTest_->checkStatus( &*gcrodr_prime_iter );
1518  if (convTest_->getStatus() == Passed)
1519  primeConverged = true;
1520  }
1521  catch (const StatusTestNaNError& e) {
1522  // A NaN was detected in the solver. Set the solution to zero and return unconverged.
1523  achievedTol_ = MT::one();
1524  Teuchos::RCP<MV> X = problem_->getLHS();
1525  MVT::MvInit( *X, SCT::zero() );
1526  printer_->stream(Warnings) << "Belos::GCRODRSolMgr::solve(): Warning! NaN has been detected!"
1527  << std::endl;
1528  return Unconverged;
1529  }
1530  catch (const std::exception &e) {
1531  printer_->stream(Errors) << "Error! Caught exception in GCRODRIter::iterate() at iteration "
1532  << gcrodr_prime_iter->getNumIters() << std::endl
1533  << e.what() << std::endl;
1534  throw;
1535  }
1536  // Record number of iterations in generating initial recycle spacec
1537  prime_iterations = gcrodr_prime_iter->getNumIters();
1538 
1539  // Update the linear problem.
1540  RCP<MV> update = gcrodr_prime_iter->getCurrentUpdate();
1541  problem_->updateSolution( update, true );
1542 
1543  // Get the state.
1544  newstate = gcrodr_prime_iter->getState();
1545  int p = newstate.curDim;
1546 
1547  // Compute harmonic Ritz vectors
1548  // NOTE: The storage for the harmonic Ritz vectors (PP) is made one column larger
1549  // just in case we split a complex conjugate pair.
1550  // NOTE: Generate a recycled subspace only if we have enough vectors. If we converged
1551  // too early, move on to the next linear system and try to generate a subspace again.
1552  if (recycledBlocks_ < p+1) {
1553  int info = 0;
1554  RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > PPtmp = rcp (new Teuchos::SerialDenseMatrix<int,ScalarType> ( Teuchos::View, *PP_, p, recycledBlocks_+1 ) );
1555  // getHarmonicVecs1 assumes PP has recycledBlocks_+1 columns available
1556  keff = getHarmonicVecs1( p, *newstate.H, *PPtmp );
1557  // Hereafter, only keff columns of PP are needed
1558  PPtmp = rcp (new Teuchos::SerialDenseMatrix<int,ScalarType> ( Teuchos::View, *PP_, p, keff ) );
1559  // Now get views into C, U, V
1560  index.resize(keff);
1561  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1562  RCP<MV> Ctmp = MVT::CloneViewNonConst( *C_, index );
1563  RCP<MV> Utmp = MVT::CloneViewNonConst( *U_, index );
1564  RCP<MV> U1tmp = MVT::CloneViewNonConst( *U1_, index );
1565  index.resize(p);
1566  for (int ii=0; ii < p; ++ii) { index[ii] = ii; }
1567  RCP<const MV> Vtmp = MVT::CloneView( *V_, index );
1568 
1569  // Form U (the subspace to recycle)
1570  // U = newstate.V(:,1:p) * PP;
1571  MVT::MvTimesMatAddMv( one, *Vtmp, *PPtmp, zero, *U1tmp );
1572 
1573  // Form orthonormalized C and adjust U so that C = A*U
1574 
1575  // First, compute [Q, R] = qr(H*P);
1576 
1577  // Step #1: Form HP = H*P
1578  Teuchos::SerialDenseMatrix<int,ScalarType> Htmp( Teuchos::View, *H2_, p+1, p, recycledBlocks_+1,recycledBlocks_+1);
1580  HPtmp.multiply( Teuchos::NO_TRANS, Teuchos::NO_TRANS, one, Htmp, *PPtmp, zero );
1581 
1582  // Step #1.5: Perform workspace size query for QR
1583  // factorization of HP. On input, lwork must be -1.
1584  // _GEQRF will put the workspace size in work_[0].
1585  int lwork = -1;
1586  tau_.resize (keff);
1587  lapack.GEQRF (HPtmp.numRows (), HPtmp.numCols (), HPtmp.values (),
1588  HPtmp.stride (), &tau_[0], &work_[0], lwork, &info);
1590  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve:"
1591  " LAPACK's _GEQRF failed to compute a workspace size.");
1592 
1593  // Step #2: Compute QR factorization of HP
1594  //
1595  // NOTE (mfh 17 Apr 2014) LAPACK promises that the value of
1596  // work_[0] after the workspace query will fit in int. This
1597  // justifies the cast. We call real() first because
1598  // static_cast from std::complex to int doesn't work.
1599  lwork = std::abs (static_cast<int> (Teuchos::ScalarTraits<ScalarType>::real (work_[0])));
1600  work_.resize (lwork); // Allocate workspace for the QR factorization
1601  lapack.GEQRF (HPtmp.numRows (), HPtmp.numCols (), HPtmp.values (),
1602  HPtmp.stride (), &tau_[0], &work_[0], lwork, &info);
1604  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve:"
1605  " LAPACK's _GEQRF failed to compute a QR factorization.");
1606 
1607  // Step #3: Explicitly construct Q and R factors
1608  // NOTE: The upper triangular part of HP is copied into R and HP becomes Q.
1610  for (int ii = 0; ii < keff; ++ii) {
1611  for (int jj = ii; jj < keff; ++jj) {
1612  Rtmp(ii,jj) = HPtmp(ii,jj);
1613  }
1614  }
1615  // NOTE (mfh 17 Apr 2014): Teuchos::LAPACK's wrapper for
1616  // UNGQR dispatches to the correct Scalar-specific routine.
1617  // It calls {S,D}ORGQR if Scalar is real, and {C,Z}UNGQR if
1618  // Scalar is complex.
1619  lapack.UNGQR (HPtmp.numRows (), HPtmp.numCols (), HPtmp.numCols (),
1620  HPtmp.values (), HPtmp.stride (), &tau_[0], &work_[0],
1621  lwork, &info);
1623  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve: "
1624  "LAPACK's _UNGQR failed to construct the Q factor.");
1625 
1626  // Now we have [Q,R] = qr(H*P)
1627 
1628  // Now compute C = V(:,1:p+1) * Q
1629  index.resize (p + 1);
1630  for (int ii = 0; ii < (p+1); ++ii) {
1631  index[ii] = ii;
1632  }
1633  Vtmp = MVT::CloneView( *V_, index ); // need new view into V (p+1 vectors now; needed p above)
1634  MVT::MvTimesMatAddMv( one, *Vtmp, HPtmp, zero, *Ctmp );
1635 
1636  // Finally, compute U = U*R^{-1}.
1637  // This unfortuntely requires me to form R^{-1} explicitly and execute U = U * R^{-1}, as
1638  // backsolve capabilities don't exist in the Belos::MultiVec class
1639 
1640  // Step #1: First, compute LU factorization of R
1641  ipiv_.resize(Rtmp.numRows());
1642  lapack.GETRF(Rtmp.numRows(),Rtmp.numCols(),Rtmp.values(),Rtmp.stride(),&ipiv_[0],&info);
1644  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve: "
1645  "LAPACK's _GETRF failed to compute an LU factorization.");
1646 
1647  // FIXME (mfh 17 Apr 2014) We have to compute the explicit
1648  // inverse of R here because Belos::MultiVecTraits doesn't
1649  // have a triangular solve (where the triangular matrix is
1650  // globally replicated and the "right-hand side" is the
1651  // distributed MultiVector).
1652 
1653  // Step #2: Form inv(R)
1654  lwork = Rtmp.numRows();
1655  work_.resize(lwork);
1656  lapack.GETRI(Rtmp.numRows(),Rtmp.values(),Rtmp.stride(),&ipiv_[0],&work_[0],lwork,&info);
1658  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve: "
1659  "LAPACK's _GETRI failed to invert triangular matrix.");
1660 
1661  // Step #3: Let U = U * R^{-1}
1662  MVT::MvTimesMatAddMv( one, *U1tmp, Rtmp, zero, *Utmp );
1663 
1664  printer_->stream(Debug)
1665  << " Generated recycled subspace using RHS index " << currIdx[0]
1666  << " of dimension " << keff << std::endl << std::endl;
1667 
1668  } // if (recycledBlocks_ < p+1)
1669 
1670  // Return to outer loop if the priming solve converged, set the next linear system.
1671  if (primeConverged) {
1672  // Inform the linear problem that we are finished with this block linear system.
1673  problem_->setCurrLS();
1674 
1675  // Update indices for the linear systems to be solved.
1676  numRHS2Solve -= 1;
1677  if (numRHS2Solve > 0) {
1678  currIdx[0]++;
1679  problem_->setLSIndex (currIdx); // Set the next indices
1680  }
1681  else {
1682  currIdx.resize (numRHS2Solve);
1683  }
1684 
1685  continue;
1686  }
1687  } // if (keff > 0) ...
1688 
1689  // Prepare for the Gmres iterations with the recycled subspace.
1690 
1691  // Set the current number of recycled blocks and subspace dimension with the GCRO-DR iteration.
1692  gcrodr_iter->setSize( keff, numBlocks_ );
1693 
1694  // Reset the number of iterations.
1695  gcrodr_iter->resetNumIters(prime_iterations);
1696 
1697  // Reset the number of calls that the status test output knows about.
1698  outputTest_->resetNumCalls();
1699 
1700  // Compute the residual after the priming solve, it will be the first block in the current Krylov basis.
1701  problem_->computeCurrPrecResVec( &*r_ );
1702  index.resize( 1 ); index[0] = 0;
1703  RCP<MV> v0 = MVT::CloneViewNonConst( *V_, index );
1704  MVT::SetBlock(*r_,index,*v0); // V(:,0) = r
1705 
1706  // Set the new state and initialize the solver.
1708  index.resize( numBlocks_+1 );
1709  for (int ii=0; ii<(numBlocks_+1); ++ii) { index[ii] = ii; }
1710  newstate.V = MVT::CloneViewNonConst( *V_, index );
1711  index.resize( keff );
1712  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1713  newstate.C = MVT::CloneViewNonConst( *C_, index );
1714  newstate.U = MVT::CloneViewNonConst( *U_, index );
1715  newstate.B = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::View, *H2_, keff, numBlocks_, 0, keff ) );
1716  newstate.H = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::View, *H2_, numBlocks_+1, numBlocks_, keff, keff ) );
1717  newstate.curDim = 0;
1718  gcrodr_iter->initialize(newstate);
1719 
1720  // variables needed for inner loop
1721  int numRestarts = 0;
1722  while(1) {
1723 
1724  // tell gcrodr_iter to iterate
1725  try {
1726  gcrodr_iter->iterate();
1727 
1729  //
1730  // check convergence first
1731  //
1733  if ( convTest_->getStatus() == Passed ) {
1734  // we have convergence
1735  break; // break from while(1){gcrodr_iter->iterate()}
1736  }
1738  //
1739  // check for maximum iterations
1740  //
1742  else if ( maxIterTest_->getStatus() == Passed ) {
1743  // we don't have convergence
1744  isConverged = false;
1745  break; // break from while(1){gcrodr_iter->iterate()}
1746  }
1748  //
1749  // check for restarting, i.e. the subspace is full
1750  //
1752  else if ( gcrodr_iter->getCurSubspaceDim() == gcrodr_iter->getMaxSubspaceDim() ) {
1753 
1754  // Update the recycled subspace even if we have hit the maximum number of restarts.
1755 
1756  // Update the linear problem.
1757  RCP<MV> update = gcrodr_iter->getCurrentUpdate();
1758  problem_->updateSolution( update, true );
1759 
1760  buildRecycleSpace2(gcrodr_iter);
1761 
1762  printer_->stream(Debug)
1763  << " Generated new recycled subspace using RHS index "
1764  << currIdx[0] << " of dimension " << keff << std::endl
1765  << std::endl;
1766 
1767  // NOTE: If we have hit the maximum number of restarts then quit
1768  if (numRestarts >= maxRestarts_) {
1769  isConverged = false;
1770  break; // break from while(1){gcrodr_iter->iterate()}
1771  }
1772  numRestarts++;
1773 
1774  printer_->stream(Debug)
1775  << " Performing restart number " << numRestarts << " of "
1776  << maxRestarts_ << std::endl << std::endl;
1777 
1778  // Create the restart vector (first block in the current Krylov basis)
1779  problem_->computeCurrPrecResVec( &*r_ );
1780  index.resize( 1 ); index[0] = 0;
1781  RCP<MV> v00 = MVT::CloneViewNonConst( *V_, index );
1782  MVT::SetBlock(*r_,index,*v00); // V(:,0) = r
1783 
1784  // Set the new state and initialize the solver.
1785  GCRODRIterState<ScalarType,MV> restartState;
1786  index.resize( numBlocks_+1 );
1787  for (int ii=0; ii<(numBlocks_+1); ++ii) { index[ii] = ii; }
1788  restartState.V = MVT::CloneViewNonConst( *V_, index );
1789  index.resize( keff );
1790  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1791  restartState.U = MVT::CloneViewNonConst( *U_, index );
1792  restartState.C = MVT::CloneViewNonConst( *C_, index );
1793  restartState.B = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::View, *H2_, keff, numBlocks_, 0, keff ) );
1794  restartState.H = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::View, *H2_, numBlocks_+1, numBlocks_, keff, keff ) );
1795  restartState.curDim = 0;
1796  gcrodr_iter->initialize(restartState);
1797 
1798 
1799  } // end of restarting
1800 
1802  //
1803  // we returned from iterate(), but none of our status tests Passed.
1804  // something is wrong, and it is probably our fault.
1805  //
1807 
1808  else {
1810  true, std::logic_error, "Belos::GCRODRSolMgr::solve: "
1811  "Invalid return from GCRODRIter::iterate().");
1812  }
1813  }
1814  catch (const GCRODRIterOrthoFailure &e) {
1815  // Try to recover the most recent least-squares solution
1816  gcrodr_iter->updateLSQR( gcrodr_iter->getCurSubspaceDim() );
1817 
1818  // Check to see if the most recent least-squares solution yielded convergence.
1819  sTest_->checkStatus( &*gcrodr_iter );
1820  if (convTest_->getStatus() != Passed)
1821  isConverged = false;
1822  break;
1823  }
1824  catch (const std::exception& e) {
1825  printer_->stream(Errors)
1826  << "Error! Caught exception in GCRODRIter::iterate() at iteration "
1827  << gcrodr_iter->getNumIters() << std::endl << e.what() << std::endl;
1828  throw;
1829  }
1830  }
1831 
1832  // Compute the current solution.
1833  // Update the linear problem.
1834  RCP<MV> update = gcrodr_iter->getCurrentUpdate();
1835  problem_->updateSolution( update, true );
1836 
1837  // Inform the linear problem that we are finished with this block linear system.
1838  problem_->setCurrLS();
1839 
1840  // If we didn't build a recycle space this solve but ran at least k iterations,
1841  // force build of new recycle space
1842 
1843  if (!builtRecycleSpace_) {
1844  buildRecycleSpace2(gcrodr_iter);
1845  printer_->stream(Debug)
1846  << " Generated new recycled subspace using RHS index " << currIdx[0]
1847  << " of dimension " << keff << std::endl << std::endl;
1848  }
1849 
1850  // Update indices for the linear systems to be solved.
1851  numRHS2Solve -= 1;
1852  if (numRHS2Solve > 0) {
1853  currIdx[0]++;
1854  problem_->setLSIndex (currIdx); // Set the next indices
1855  }
1856  else {
1857  currIdx.resize (numRHS2Solve);
1858  }
1859  } // while (numRHS2Solve > 0)
1860  }
1861 
1862  sTest_->print (printer_->stream (FinalSummary)); // print final summary
1863 
1864  // print timing information
1865 #ifdef BELOS_TEUCHOS_TIME_MONITOR
1866  // Calling summarize() can be expensive, so don't call unless the
1867  // user wants to print out timing details. summarize() will do all
1868  // the work even if it's passed a "black hole" output stream.
1869  if (verbosity_ & TimingDetails)
1870  Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
1871 #endif // BELOS_TEUCHOS_TIME_MONITOR
1872 
1873  // get iteration information for this solve
1874  numIters_ = maxIterTest_->getNumIters ();
1875 
1876  // Save the convergence test value ("achieved tolerance") for this
1877  // solve. This solver (unlike BlockGmresSolMgr) always has two
1878  // residual norm status tests: an explicit and an implicit test.
1879  // The master convergence test convTest_ is a SEQ combo of the
1880  // implicit resp. explicit tests. If the implicit test never
1881  // passes, then the explicit test won't ever be executed. This
1882  // manifests as expConvTest_->getTestValue()->size() < 1. We deal
1883  // with this case by using the values returned by
1884  // impConvTest_->getTestValue().
1885  {
1886  const std::vector<MagnitudeType>* pTestValues = expConvTest_->getTestValue();
1887  if (pTestValues == NULL || pTestValues->size() < 1) {
1888  pTestValues = impConvTest_->getTestValue();
1889  }
1890  TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1891  "Belos::GCRODRSolMgr::solve(): The implicit convergence test's getTestValue() "
1892  "method returned NULL. Please report this bug to the Belos developers.");
1893  TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1894  "Belos::GCRODRSolMgr::solve(): The implicit convergence test's getTestValue() "
1895  "method returned a vector of length zero. Please report this bug to the "
1896  "Belos developers.");
1897 
1898  // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
1899  // achieved tolerances for all vectors in the current solve(), or
1900  // just for the vectors from the last deflation?
1901  achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
1902  }
1903 
1904  return isConverged ? Converged : Unconverged; // return from solve()
1905 }
1906 
1907 // Given existing recycle space and Krylov space, build new recycle space
1908 template<class ScalarType, class MV, class OP>
1910 
1911  MagnitudeType one = Teuchos::ScalarTraits<MagnitudeType>::one();
1912  ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
1913 
1914  std::vector<MagnitudeType> d(keff);
1915  std::vector<ScalarType> dscalar(keff);
1916  std::vector<int> index(numBlocks_+1);
1917 
1918  // Get the state
1919  GCRODRIterState<ScalarType,MV> oldState = gcrodr_iter->getState();
1920  int p = oldState.curDim;
1921 
1922  // insufficient new information to update recycle space
1923  if (p<1) return;
1924 
1925  // Take the norm of the recycled vectors
1926  {
1927  index.resize(keff);
1928  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1929  Teuchos::RCP<MV> Utmp = MVT::CloneViewNonConst( *U_, index );
1930  d.resize(keff);
1931  dscalar.resize(keff);
1932  MVT::MvNorm( *Utmp, d );
1933  for (int i=0; i<keff; ++i) {
1934  d[i] = one / d[i];
1935  dscalar[i] = (ScalarType)d[i];
1936  }
1937  MVT::MvScale( *Utmp, dscalar );
1938  }
1939 
1940  // Get view into current "full" upper Hessnburg matrix
1942 
1943  // Insert D into the leading keff x keff block of H2
1944  for (int i=0; i<keff; ++i) {
1945  (*H2tmp)(i,i) = d[i];
1946  }
1947 
1948  // Compute the harmoic Ritz pairs for the generalized eigenproblem
1949  // getHarmonicVecs2 assumes PP has recycledBlocks_+1 columns available
1950  int keff_new;
1951  {
1952  Teuchos::SerialDenseMatrix<int,ScalarType> PPtmp( Teuchos::View, *PP_, p+keff, recycledBlocks_+1 );
1953  keff_new = getHarmonicVecs2( keff, p, *H2tmp, oldState.V, PPtmp );
1954  }
1955 
1956  // Code to form new U, C
1957  // U = [U V(:,1:p)] * P; (in two steps)
1958 
1959  // U(:,1:keff) = matmul(U(:,1:keff_old),PP(1:keff_old,1:keff)) (step 1)
1960  Teuchos::RCP<MV> U1tmp;
1961  {
1962  index.resize( keff );
1963  for (int ii=0; ii<keff; ++ii) { index[ii] = ii; }
1964  Teuchos::RCP<const MV> Utmp = MVT::CloneView( *U_, index );
1965  index.resize( keff_new );
1966  for (int ii=0; ii<keff_new; ++ii) { index[ii] = ii; }
1967  U1tmp = MVT::CloneViewNonConst( *U1_, index );
1968  Teuchos::SerialDenseMatrix<int,ScalarType> PPtmp( Teuchos::View, *PP_, keff, keff_new );
1969  MVT::MvTimesMatAddMv( one, *Utmp, PPtmp, zero, *U1tmp );
1970  }
1971 
1972  // U(:,1:keff) = U(:,1:keff) + matmul(V(:,1:m-k),PP(keff_old+1:m-k+keff_old,1:keff)) (step 2)
1973  {
1974  index.resize(p);
1975  for (int ii=0; ii < p; ii++) { index[ii] = ii; }
1976  Teuchos::RCP<const MV> Vtmp = MVT::CloneView( *V_, index );
1977  Teuchos::SerialDenseMatrix<int,ScalarType> PPtmp( Teuchos::View, *PP_, p, keff_new, keff );
1978  MVT::MvTimesMatAddMv( one, *Vtmp, PPtmp, one, *U1tmp );
1979  }
1980 
1981  // Form HP = H*P
1982  Teuchos::SerialDenseMatrix<int,ScalarType> HPtmp( Teuchos::View, *HP_, p+keff+1, keff_new );
1983  {
1984  Teuchos::SerialDenseMatrix<int,ScalarType> PPtmp( Teuchos::View, *PP_, p+keff, keff_new );
1985  HPtmp.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,one,*H2tmp,PPtmp,zero);
1986  }
1987 
1988  // Workspace size query for QR factorization of HP (the worksize will be placed in work_[0])
1989  int info = 0, lwork = -1;
1990  tau_.resize (keff_new);
1991  lapack.GEQRF (HPtmp.numRows (), HPtmp.numCols (), HPtmp.values (),
1992  HPtmp.stride (), &tau_[0], &work_[0], lwork, &info);
1994  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve: "
1995  "LAPACK's _GEQRF failed to compute a workspace size.");
1996 
1997  // NOTE (mfh 18 Apr 2014) LAPACK promises that the value of work_[0]
1998  // after the workspace query will fit in int. This justifies the
1999  // cast. We call real() first because static_cast from std::complex
2000  // to int doesn't work.
2001  lwork = std::abs (static_cast<int> (Teuchos::ScalarTraits<ScalarType>::real (work_[0])));
2002  work_.resize (lwork); // Allocate workspace for the QR factorization
2003  lapack.GEQRF (HPtmp.numRows (), HPtmp.numCols (), HPtmp.values (),
2004  HPtmp.stride (), &tau_[0], &work_[0], lwork, &info);
2006  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve: "
2007  "LAPACK's _GEQRF failed to compute a QR factorization.");
2008 
2009  // Explicitly construct Q and R factors
2010  // NOTE: The upper triangular part of HP is copied into R and HP becomes Q.
2011  Teuchos::SerialDenseMatrix<int,ScalarType> Rtmp( Teuchos::View, *R_, keff_new, keff_new );
2012  for(int i=0;i<keff_new;i++) { for(int j=i;j<keff_new;j++) Rtmp(i,j) = HPtmp(i,j); }
2013 
2014  // NOTE (mfh 18 Apr 2014): Teuchos::LAPACK's wrapper for UNGQR
2015  // dispatches to the correct Scalar-specific routine. It calls
2016  // {S,D}ORGQR if Scalar is real, and {C,Z}UNGQR if Scalar is
2017  // complex.
2018  lapack.UNGQR (HPtmp.numRows (), HPtmp.numCols (), HPtmp.numCols (),
2019  HPtmp.values (), HPtmp.stride (), &tau_[0], &work_[0],
2020  lwork, &info);
2022  info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve: "
2023  "LAPACK's _UNGQR failed to construct the Q factor.");
2024 
2025  // Form orthonormalized C and adjust U accordingly so that C = A*U
2026  // C = [C V] * Q;
2027 
2028  // C(:,1:keff) = matmul(C(:,1:keff_old),QQ(1:keff_old,1:keff))
2029  {
2030  Teuchos::RCP<MV> C1tmp;
2031  {
2032  index.resize(keff);
2033  for (int i=0; i < keff; i++) { index[i] = i; }
2034  Teuchos::RCP<const MV> Ctmp = MVT::CloneView( *C_, index );
2035  index.resize(keff_new);
2036  for (int i=0; i < keff_new; i++) { index[i] = i; }
2037  C1tmp = MVT::CloneViewNonConst( *C1_, index );
2038  Teuchos::SerialDenseMatrix<int,ScalarType> PPtmp( Teuchos::View, *HP_, keff, keff_new );
2039  MVT::MvTimesMatAddMv( one, *Ctmp, PPtmp, zero, *C1tmp );
2040  }
2041  // Now compute C += V(:,1:p+1) * Q
2042  {
2043  index.resize( p+1 );
2044  for (int i=0; i < p+1; ++i) { index[i] = i; }
2045  Teuchos::RCP<const MV> Vtmp = MVT::CloneView( *V_, index );
2046  Teuchos::SerialDenseMatrix<int,ScalarType> PPtmp( Teuchos::View, *HP_, p+1, keff_new, keff, 0 );
2047  MVT::MvTimesMatAddMv( one, *Vtmp, PPtmp, one, *C1tmp );
2048  }
2049  }
2050 
2051  // C_ = C1_; (via a swap)
2052  std::swap(C_, C1_);
2053 
2054  // Finally, compute U_ = U_*R^{-1}
2055  // First, compute LU factorization of R
2056  ipiv_.resize(Rtmp.numRows());
2057  lapack.GETRF(Rtmp.numRows(),Rtmp.numCols(),Rtmp.values(),Rtmp.stride(),&ipiv_[0],&info);
2058  TEUCHOS_TEST_FOR_EXCEPTION(info != 0,GCRODRSolMgrLAPACKFailure,"Belos::GCRODRSolMgr::solve(): LAPACK _GETRF failed to compute an LU factorization.");
2059 
2060  // Now, form inv(R)
2061  lwork = Rtmp.numRows();
2062  work_.resize(lwork);
2063  lapack.GETRI(Rtmp.numRows(),Rtmp.values(),Rtmp.stride(),&ipiv_[0],&work_[0],lwork,&info);
2064  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, GCRODRSolMgrLAPACKFailure,"Belos::GCRODRSolMgr::solve(): LAPACK _GETRI failed to compute an LU factorization.");
2065 
2066  {
2067  index.resize(keff_new);
2068  for (int i=0; i < keff_new; i++) { index[i] = i; }
2069  Teuchos::RCP<MV> Utmp = MVT::CloneViewNonConst( *U_, index );
2070  MVT::MvTimesMatAddMv( one, *U1tmp, Rtmp, zero, *Utmp );
2071  }
2072 
2073  // Set the current number of recycled blocks and subspace dimension with the GCRO-DR iteration.
2074  if (keff != keff_new) {
2075  keff = keff_new;
2076  gcrodr_iter->setSize( keff, numBlocks_ );
2077  // Important to zero this out before next cyle
2078  Teuchos::SerialDenseMatrix<int,ScalarType> b1( Teuchos::View, *H2_, recycledBlocks_+2, 1, 0, recycledBlocks_ );
2079  b1.putScalar(zero);
2080  }
2081 
2082 }
2083 
2084 
2085 // Compute the harmonic eigenpairs of the projected, dense system.
2086 template<class ScalarType, class MV, class OP>
2087 int GCRODRSolMgr<ScalarType,MV,OP,true>::getHarmonicVecs1(int m,
2090  int i, j;
2091  bool xtraVec = false;
2092  ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
2093 
2094  // Real and imaginary eigenvalue components
2095  std::vector<MagnitudeType> wr(m), wi(m);
2096 
2097  // Real and imaginary (right) eigenvectors; Don't zero out matrix when constructing
2099 
2100  // Magnitude of harmonic Ritz values
2101  std::vector<MagnitudeType> w(m);
2102 
2103  // Sorted order of harmonic Ritz values, also used for GEEV
2104  std::vector<int> iperm(m);
2105 
2106  // Output info
2107  int info = 0;
2108 
2109  // Set flag indicating recycle space has been generated this solve
2110  builtRecycleSpace_ = true;
2111 
2112  // Solve linear system: H_m^{-H}*e_m
2115  e_m[m-1] = one;
2116  lapack.GESV(m, 1, HHt.values(), HHt.stride(), &iperm[0], e_m.values(), e_m.stride(), &info);
2117  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve(): LAPACK GESV failed to compute a solution.");
2118 
2119  // Compute H_m + d*H_m^{-H}*e_m*e_m^H
2120  ScalarType d = HH(m, m-1) * HH(m, m-1);
2122  for( i=0; i<m; ++i )
2123  harmHH(i, m-1) += d * e_m[i];
2124 
2125  // Revise to do query for optimal workspace first
2126  // Create simple storage for the left eigenvectors, which we don't care about.
2127  const int ldvl = 1;
2128  ScalarType* vl = 0;
2129 
2130  // Size of workspace and workspace for GEEV
2131  int lwork = -1;
2132  std::vector<ScalarType> work(1);
2133  std::vector<MagnitudeType> rwork(2*m);
2134 
2135  // First query GEEV for the optimal workspace size
2136  lapack.GEEV('N', 'V', m, harmHH.values(), harmHH.stride(), &wr[0], &wi[0],
2137  vl, ldvl, vr.values(), vr.stride(), &work[0], lwork, &rwork[0], &info);
2138 
2139  lwork = std::abs (static_cast<int> (Teuchos::ScalarTraits<ScalarType>::real (work[0])));
2140  work.resize( lwork );
2141 
2142  lapack.GEEV('N', 'V', m, harmHH.values(), harmHH.stride(), &wr[0], &wi[0],
2143  vl, ldvl, vr.values(), vr.stride(), &work[0], lwork, &rwork[0], &info);
2144  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, GCRODRSolMgrLAPACKFailure,"Belos::GCRODRSolMgr::solve(): LAPACK GEEV failed to compute eigensolutions.");
2145 
2146  // Construct magnitude of each harmonic Ritz value
2147  for( i=0; i<m; ++i )
2148  w[i] = Teuchos::ScalarTraits<MagnitudeType>::squareroot( wr[i]*wr[i] + wi[i]*wi[i] );
2149 
2150  // Construct magnitude of each harmonic Ritz value
2151  this->sort(w, m, iperm);
2152 
2153  const bool scalarTypeIsComplex = Teuchos::ScalarTraits<ScalarType>::isComplex;
2154 
2155  // Select recycledBlocks_ smallest eigenvectors
2156  for( i=0; i<recycledBlocks_; ++i ) {
2157  for( j=0; j<m; j++ ) {
2158  PP(j,i) = vr(j,iperm[i]);
2159  }
2160  }
2161 
2162  if(!scalarTypeIsComplex) {
2163 
2164  // Determine exact size for PP (i.e., determine if we need to store an additional vector)
2165  if (wi[iperm[recycledBlocks_-1]] != 0.0) {
2166  int countImag = 0;
2167  for ( i=0; i<recycledBlocks_; ++i ) {
2168  if (wi[iperm[i]] != 0.0)
2169  countImag++;
2170  }
2171  // Check to see if this count is even or odd:
2172  if (countImag % 2)
2173  xtraVec = true;
2174  }
2175 
2176  if (xtraVec) { // we need to store one more vector
2177  if (wi[iperm[recycledBlocks_-1]] > 0.0) { // I picked the "real" component
2178  for( j=0; j<m; ++j ) { // so get the "imag" component
2179  PP(j,recycledBlocks_) = vr(j,iperm[recycledBlocks_-1]+1);
2180  }
2181  }
2182  else { // I picked the "imag" component
2183  for( j=0; j<m; ++j ) { // so get the "real" component
2184  PP(j,recycledBlocks_) = vr(j,iperm[recycledBlocks_-1]-1);
2185  }
2186  }
2187  }
2188 
2189  }
2190 
2191  // Return whether we needed to store an additional vector
2192  if (xtraVec) {
2193  return recycledBlocks_+1;
2194  }
2195  else {
2196  return recycledBlocks_;
2197  }
2198 
2199 }
2200 
2201 // Compute the harmonic eigenpairs of the projected, dense system.
2202 template<class ScalarType, class MV, class OP>
2203 int GCRODRSolMgr<ScalarType,MV,OP,true>::getHarmonicVecs2(int keffloc, int m,
2205  const Teuchos::RCP<const MV>& VV,
2207  int i, j;
2208  int m2 = HH.numCols();
2209  bool xtraVec = false;
2210  ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
2211  ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
2212  std::vector<int> index;
2213 
2214  // Real and imaginary eigenvalue components
2215  std::vector<MagnitudeType> wr(m2), wi(m2);
2216 
2217  // Magnitude of harmonic Ritz values
2218  std::vector<MagnitudeType> w(m2);
2219 
2220  // Real and imaginary (right) eigenvectors; Don't zero out matrix when constructing
2222 
2223  // Sorted order of harmonic Ritz values
2224  std::vector<int> iperm(m2);
2225 
2226  // Set flag indicating recycle space has been generated this solve
2227  builtRecycleSpace_ = true;
2228 
2229  // Form matrices for generalized eigenproblem
2230 
2231  // B = H2' * H2; Don't zero out matrix when constructing
2233  B.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,one,HH,HH,zero);
2234 
2235  // A_tmp = | C'*U 0 |
2236  // | V_{m+1}'*U I |
2237  Teuchos::SerialDenseMatrix<int,ScalarType> A_tmp( keffloc+m+1, keffloc+m );
2238 
2239  // A_tmp(1:keffloc,1:keffloc) = C' * U;
2240  index.resize(keffloc);
2241  for (i=0; i<keffloc; ++i) { index[i] = i; }
2242  Teuchos::RCP<const MV> Ctmp = MVT::CloneView( *C_, index );
2243  Teuchos::RCP<const MV> Utmp = MVT::CloneView( *U_, index );
2244  Teuchos::SerialDenseMatrix<int,ScalarType> A11( Teuchos::View, A_tmp, keffloc, keffloc );
2245  MVT::MvTransMv( one, *Ctmp, *Utmp, A11 );
2246 
2247  // A_tmp(keffloc+1:m-k+keffloc+1,1:keffloc) = V' * U;
2248  Teuchos::SerialDenseMatrix<int,ScalarType> A21( Teuchos::View, A_tmp, m+1, keffloc, keffloc );
2249  index.resize(m+1);
2250  for (i=0; i < m+1; i++) { index[i] = i; }
2251  Teuchos::RCP<const MV> Vp = MVT::CloneView( *VV, index );
2252  MVT::MvTransMv( one, *Vp, *Utmp, A21 );
2253 
2254  // A_tmp(keffloc+1:m-k+keffloc,keffloc+1:m-k+keffloc) = eye(m-k);
2255  for( i=keffloc; i<keffloc+m; i++ ) {
2256  A_tmp(i,i) = one;
2257  }
2258 
2259  // A = H2' * A_tmp;
2260  Teuchos::SerialDenseMatrix<int,ScalarType> A( m2, A_tmp.numCols() );
2261  A.multiply( Teuchos::TRANS, Teuchos::NO_TRANS, one, HH, A_tmp, zero );
2262 
2263  // Compute k smallest harmonic Ritz pairs
2264  // SUBROUTINE DGGEVX( BALANC, JOBVL, JOBVR, SENSE, N, A, LDA, B, LDB,
2265  // ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, ILO,
2266  // IHI, LSCALE, RSCALE, ABNRM, BBNRM, RCONDE,
2267  // RCONDV, WORK, LWORK, IWORK, BWORK, INFO )
2268  // MLP: 'SCALING' in DGGEVX generates incorrect eigenvalues. Therefore, only permuting
2269  char balanc='P', jobvl='N', jobvr='V', sense='N';
2270  int ld = A.numRows();
2271  int lwork = 6*ld;
2272  int ldvl = ld, ldvr = ld;
2273  int info = 0,ilo = 0,ihi = 0;
2274  MagnitudeType abnrm = 0.0, bbnrm = 0.0;
2275  ScalarType *vl = 0; // This is never referenced by dggevx if jobvl == 'N'
2276  std::vector<ScalarType> beta(ld);
2277  std::vector<ScalarType> work(lwork);
2278  std::vector<MagnitudeType> rwork(lwork);
2279  std::vector<MagnitudeType> lscale(ld), rscale(ld);
2280  std::vector<MagnitudeType> rconde(ld), rcondv(ld);
2281  std::vector<int> iwork(ld+6);
2282  int *bwork = 0; // If sense == 'N', bwork is never referenced
2283  //lapack.GGEVX(balanc, jobvl, jobvr, sense, ld, A.values(), ld, B.values(), ld, &wr[0], &wi[0],
2284  // &beta[0], vl, ldvl, vr.values(), ldvr, &ilo, &ihi, &lscale[0], &rscale[0],
2285  // &abnrm, &bbnrm, &rconde[0], &rcondv[0], &work[0], lwork, &iwork[0], bwork, &info);
2286  lapack.GGEVX(balanc, jobvl, jobvr, sense, ld, A.values(), ld, B.values(), ld, &wr[0], &wi[0],
2287  &beta[0], vl, ldvl, vr.values(), ldvr, &ilo, &ihi, &lscale[0], &rscale[0],
2288  &abnrm, &bbnrm, &rconde[0], &rcondv[0], &work[0], lwork, &rwork[0],
2289  &iwork[0], bwork, &info);
2290  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, GCRODRSolMgrLAPACKFailure, "Belos::GCRODRSolMgr::solve(): LAPACK GGEVX failed to compute eigensolutions.");
2291 
2292  // Construct magnitude of each harmonic Ritz value
2293  // NOTE : Forming alpha/beta *should* be okay here, given assumptions on construction of matrix pencil above
2294  for( i=0; i<ld; i++ ) {
2295  w[i] = Teuchos::ScalarTraits<MagnitudeType>::squareroot (wr[i]*wr[i] + wi[i]*wi[i]) /
2297  }
2298 
2299  // Construct magnitude of each harmonic Ritz value
2300  this->sort(w,ld,iperm);
2301 
2302  const bool scalarTypeIsComplex = Teuchos::ScalarTraits<ScalarType>::isComplex;
2303 
2304  // Select recycledBlocks_ smallest eigenvectors
2305  for( i=0; i<recycledBlocks_; i++ ) {
2306  for( j=0; j<ld; j++ ) {
2307  PP(j,i) = vr(j,iperm[ld-recycledBlocks_+i]);
2308  }
2309  }
2310 
2311  if(!scalarTypeIsComplex) {
2312 
2313  // Determine exact size for PP (i.e., determine if we need to store an additional vector)
2314  if (wi[iperm[ld-recycledBlocks_]] != 0.0) {
2315  int countImag = 0;
2316  for ( i=ld-recycledBlocks_; i<ld; i++ ) {
2317  if (wi[iperm[i]] != 0.0)
2318  countImag++;
2319  }
2320  // Check to see if this count is even or odd:
2321  if (countImag % 2)
2322  xtraVec = true;
2323  }
2324 
2325  if (xtraVec) { // we need to store one more vector
2326  if (wi[iperm[ld-recycledBlocks_]] > 0.0) { // I picked the "real" component
2327  for( j=0; j<ld; j++ ) { // so get the "imag" component
2328  PP(j,recycledBlocks_) = vr(j,iperm[ld-recycledBlocks_]+1);
2329  }
2330  }
2331  else { // I picked the "imag" component
2332  for( j=0; j<ld; j++ ) { // so get the "real" component
2333  PP(j,recycledBlocks_) = vr(j,iperm[ld-recycledBlocks_]-1);
2334  }
2335  }
2336  }
2337 
2338  }
2339 
2340  // Return whether we needed to store an additional vector
2341  if (xtraVec) {
2342  return recycledBlocks_+1;
2343  }
2344  else {
2345  return recycledBlocks_;
2346  }
2347 
2348 }
2349 
2350 
2351 // This method sorts list of n floating-point numbers and return permutation vector
2352 template<class ScalarType, class MV, class OP>
2353 void GCRODRSolMgr<ScalarType,MV,OP,true>::sort(std::vector<MagnitudeType>& dlist, int n, std::vector<int>& iperm) {
2354  int l, r, j, i, flag;
2355  int RR2;
2356  MagnitudeType dRR, dK;
2357 
2358  // Initialize the permutation vector.
2359  for(j=0;j<n;j++)
2360  iperm[j] = j;
2361 
2362  if (n <= 1) return;
2363 
2364  l = n / 2 + 1;
2365  r = n - 1;
2366  l = l - 1;
2367  dRR = dlist[l - 1];
2368  dK = dlist[l - 1];
2369 
2370  RR2 = iperm[l - 1];
2371  while (r != 0) {
2372  j = l;
2373  flag = 1;
2374 
2375  while (flag == 1) {
2376  i = j;
2377  j = j + j;
2378 
2379  if (j > r + 1)
2380  flag = 0;
2381  else {
2382  if (j < r + 1)
2383  if (dlist[j] > dlist[j - 1]) j = j + 1;
2384 
2385  if (dlist[j - 1] > dK) {
2386  dlist[i - 1] = dlist[j - 1];
2387  iperm[i - 1] = iperm[j - 1];
2388  }
2389  else {
2390  flag = 0;
2391  }
2392  }
2393  }
2394  dlist[i - 1] = dRR;
2395  iperm[i - 1] = RR2;
2396 
2397  if (l == 1) {
2398  dRR = dlist [r];
2399  RR2 = iperm[r];
2400  dK = dlist[r];
2401  dlist[r] = dlist[0];
2402  iperm[r] = iperm[0];
2403  r = r - 1;
2404  }
2405  else {
2406  l = l - 1;
2407  dRR = dlist[l - 1];
2408  RR2 = iperm[l - 1];
2409  dK = dlist[l - 1];
2410  }
2411  }
2412  dlist[0] = dRR;
2413  iperm[0] = RR2;
2414 }
2415 
2416 
2417 template<class ScalarType, class MV, class OP>
2419  std::ostringstream out;
2420  out << "Belos::GCRODRSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
2421  out << "{";
2422  out << "Ortho Type: \"" << orthoType_ << "\"";
2423  out << ", Num Blocks: " <<numBlocks_;
2424  out << ", Num Recycle Blocks: " << recycledBlocks_;
2425  out << ", Max Restarts: " << maxRestarts_;
2426  out << "}";
2427  return out.str ();
2428 }
2429 
2430 } // namespace Belos
2431 
2432 #endif /* BELOS_GCRODR_SOLMGR_HPP */
ScaleType convertStringToScaleType(const std::string &scaleType)
Convert the given string to its ScaleType enum value.
Definition: BelosTypes.cpp:106
ScalarType * values() const
Collection of types and exceptions used within the Belos solvers.
Partial specialization for ScalarType types for which Teuchos::LAPACK has a valid implementation...
Belos&#39;s basic output manager for sending information of select verbosity levels to the appropriate ou...
GCRODRSolMgrLAPACKFailure(const std::string &what_arg)
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:120
Exception thrown to signal error in a status test during Belos::StatusTest::checkStatus().
T & get(const std::string &name, T def_value)
GCRODRSolMgrLAPACKFailure is thrown when a nonzero value is retuned from an LAPACK call...
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static RCP< Time > getNewCounter(const std::string &name)
bool is_null(const std::shared_ptr< T > &p)
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
static T squareroot(T x)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
A factory class for generating StatusTestOutput objects.
Teuchos::RCP< const Teuchos::ParameterList > getDefaultParameters(const std::string &name) const
Default parameters for the given MatOrthoManager subclass.
An implementation of StatusTestResNorm using a family of residual norms.
GCRODRSolMgrLinearProblemFailure is thrown when the linear problem is not setup (i.e.
GCRODRSolMgrRecyclingFailure(const std::string &what_arg)
This class implements the GCRODR iteration, where a single-std::vector Krylov subspace is constructed...
static const double convTol
Default convergence tolerance.
Definition: BelosTypes.hpp:293
Belos::StatusTest class for specifying a maximum number of iterations.
int curDim
The current dimension of the reduction.
static std::string name()
A factory class for generating StatusTestOutput objects.
std::string validNamesString() const
List (as a string) of recognized MatOrthoManager names.
Traits class which defines basic operations on multivectors.
Belos::StatusTest for logically combining several status tests.
bool isParameter(const std::string &name) const
A Belos::StatusTest class for specifying a maximum number of iterations.
GCRODRSolMgrOrthoFailure(const std::string &what_arg)
Teuchos::RCP< SolverManager< ScalarType, MV, OP > > clone() const override
clone for Inverted Injection (DII)
ResetType
How to reset the solver.
Definition: BelosTypes.hpp:206
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< MV > V
The current Krylov basis.
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 isValidName(const std::string &name) const
Whether this factory recognizes the MatOrthoManager with the given name.
Teuchos::RCP< MV > U
The recycled subspace and its projection.
std::ostream & printValidNames(std::ostream &out) const
Print all recognized MatOrthoManager names to the given ostream.
A linear system to solve, and its associated information.
GCRODRSolMgrOrthoFailure is thrown when the orthogonalization manager is unable to generate orthonorm...
Class which describes the linear problem to be solved by the iterative solver.
GCRODRIterOrthoFailure is thrown when the GCRODRIter object is unable to compute independent directio...
Implementation of the GCRODR (Recycling GMRES) iterative linear solver.
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:155
Belos concrete class for performing the GCRO-DR iteration.
Structure to contain pointers to GCRODRIter state variables.
MagnitudeType achievedTol() const override
Tolerance achieved by the last solve() invocation.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
void reset(const ResetType type) override
Performs a reset of the solver manager specified by the ResetType. This informs the solver manager th...
void setParameters(const Teuchos::RCP< Teuchos::ParameterList > &params) override
Set the parameters the solver manager should use to solve the linear problem.
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem) override
Set the linear problem that needs to be solved.
GCRODRSolMgrRecyclingFailure is thrown when any problem occurs in using/creating the recycling subspa...
static magnitudeType magnitude(T a)
OrdinalType numCols() const
GCRODRSolMgrLinearProblemFailure(const std::string &what_arg)
GCRODRSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
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.
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const override
Get a parameter list containing the current parameters for this object.
Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > B
The projection of the Krylov subspace against the recycled subspace.
bool isType(const std::string &name) const
An implementation of the Belos::MatOrthoManager that performs orthogonalization using (potentially) m...
const LinearProblem< ScalarType, MV, OP > & getProblem() const override
Get current linear problem being solved for in this object.
A class for extending the status testing capabilities of Belos via logical combinations.
int getNumIters() const override
Get the iteration count for the most recent call to solve().
Class which defines basic traits for the operator type.
Teuchos::RCP< MV > C
Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > H
The current Hessenberg matrix.
Parent class to all Belos exceptions.
Definition: BelosTypes.hpp:60
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...
bool isLOADetected() const override
Return whether a loss of accuracy was detected by this solver during the most current solve...
OrdinalType stride() const
OrdinalType numRows() const
Belos concrete class for performing the block, flexible GMRES iteration.
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 Wed Apr 17 2024 09:24:01 for Belos by doxygen 1.8.5