Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
AnasaziTraceMinBaseSolMgr.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Anasazi: Block Eigensolvers Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef ANASAZI_TraceMinBase_SOLMGR_HPP
00030 #define ANASAZI_TraceMinBase_SOLMGR_HPP
00031 
00036 #include "AnasaziBasicOrthoManager.hpp"
00037 #include "AnasaziBasicOutputManager.hpp"
00038 #include "AnasaziBasicSort.hpp"
00039 #include "AnasaziConfigDefs.hpp"
00040 #include "AnasaziEigenproblem.hpp"
00041 #include "AnasaziICGSOrthoManager.hpp"
00042 #include "AnasaziSolverManager.hpp"
00043 #include "AnasaziSolverUtils.hpp"
00044 #include "AnasaziStatusTestCombo.hpp"
00045 #include "AnasaziStatusTestOutput.hpp"
00046 #include "AnasaziStatusTestResNorm.hpp"
00047 #include "AnasaziStatusTestSpecTrans.hpp"
00048 #include "AnasaziStatusTestWithOrdering.hpp"
00049 #include "AnasaziSVQBOrthoManager.hpp"
00050 #include "AnasaziTraceMinBase.hpp"
00051 #include "AnasaziTraceMinTypes.hpp"
00052 #include "AnasaziTypes.hpp"
00053 
00054 #include "Teuchos_TimeMonitor.hpp"
00055 #ifdef TEUCHOS_DEBUG
00056 #  include <Teuchos_FancyOStream.hpp>
00057 #endif
00058 #ifdef HAVE_MPI
00059 #include <mpi.h>
00060 #endif
00061 
00062 using Teuchos::RCP;
00063 using Teuchos::rcp;
00064 
00065 namespace Anasazi {
00066 namespace Experimental {
00067 
00068 
00101 template<class ScalarType, class MV, class OP>
00102 class TraceMinBaseSolMgr : public SolverManager<ScalarType,MV,OP> {
00103 
00104   private:
00105     typedef MultiVecTraits<ScalarType,MV> MVT;
00106     typedef MultiVecTraitsExt<ScalarType,MV> MVText;
00107     typedef OperatorTraits<ScalarType,MV,OP> OPT;
00108     typedef Teuchos::ScalarTraits<ScalarType> SCT;
00109     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00110     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00111     
00112   public:
00113 
00115 
00116 
00158   TraceMinBaseSolMgr( const RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
00159                              Teuchos::ParameterList &pl );
00160 
00162   virtual ~TraceMinBaseSolMgr() {};
00164   
00166 
00167 
00169   const Eigenproblem<ScalarType,MV,OP>& getProblem() const {
00170     return *problem_;
00171   }
00172 
00174   int getNumIters() const { 
00175     return numIters_; 
00176   }
00177 
00185    Teuchos::Array<RCP<Teuchos::Time> > getTimers() const {
00186      return Teuchos::tuple(_timerSolve, _timerRestarting, _timerLocking);
00187    }
00188 
00190 
00192 
00193     
00217   ReturnType solve();
00218 
00220   void setGlobalStatusTest(const RCP< StatusTest<ScalarType,MV,OP> > &global);
00221 
00223   const RCP< StatusTest<ScalarType,MV,OP> > & getGlobalStatusTest() const;
00224 
00226   void setLockingStatusTest(const RCP< StatusTest<ScalarType,MV,OP> > &locking);
00227 
00229   const RCP< StatusTest<ScalarType,MV,OP> > & getLockingStatusTest() const;
00230 
00232   void setDebugStatusTest(const RCP< StatusTest<ScalarType,MV,OP> > &debug);
00233 
00235   const RCP< StatusTest<ScalarType,MV,OP> > & getDebugStatusTest() const;
00236 
00238 
00239   protected:
00240   RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
00241 
00242   int numIters_;
00243 
00244   // Block variables
00245   int blockSize_, numBlocks_, numRestartBlocks_;
00246 
00247   // Output variables
00248   RCP<BasicOutputManager<ScalarType> > printer_;
00249 
00250   // Convergence variables
00251   MagnitudeType convTol_;
00252   bool relConvTol_;
00253   enum ResType convNorm_;
00254 
00255   // Locking variables
00256   MagnitudeType lockTol_;
00257   int maxLocked_, lockQuorum_;
00258   bool useLocking_, relLockTol_;
00259   enum ResType lockNorm_;
00260 
00261   // Shifting variables
00262   enum WhenToShiftType whenToShift_;
00263   MagnitudeType traceThresh_, shiftTol_;
00264   enum HowToShiftType howToShift_;
00265   bool useMultipleShifts_, relShiftTol_, considerClusters_;
00266   std::string shiftNorm_;
00267   
00268   // Other variables
00269   int maxKrylovIter_;
00270   std::string ortho_, which_;
00271   enum SaddleSolType saddleSolType_;
00272   bool projectAllVecs_, projectLockedVecs_, computeAllRes_, useRHSR_;
00273 
00274   // Timers
00275   RCP<Teuchos::Time> _timerSolve, _timerRestarting, _timerLocking;
00276 
00277   // Status tests
00278   RCP<StatusTest<ScalarType,MV,OP> > globalTest_;
00279   RCP<StatusTest<ScalarType,MV,OP> > lockingTest_; 
00280   RCP<StatusTest<ScalarType,MV,OP> > debugTest_;
00281 
00282   // TraceMin specific functions
00283   void copyPartOfState(const TraceMinBaseState<ScalarType,MV>& oldState, TraceMinBaseState<ScalarType,MV>& newState, const std::vector<int> indToCopy) const;
00284 
00285   void setParameters(Teuchos::ParameterList &pl) const;
00286 
00287   void printParameters(std::ostream &os) const;
00288 
00289   virtual RCP< TraceMinBase<ScalarType,MV,OP> > createSolver( 
00290             const RCP<SortManager<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > &sorter,
00291             const RCP<StatusTest<ScalarType,MV,OP> >      &outputtest,
00292             const RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
00293             Teuchos::ParameterList &plist
00294           ) =0;
00295 
00296   virtual bool needToRestart(const RCP< TraceMinBase<ScalarType,MV,OP> > solver) =0;
00297 
00298   virtual bool performRestart(int &numRestarts, RCP< TraceMinBase<ScalarType,MV,OP> > solver) =0;
00299 };
00300 
00301 
00304 // Constructor
00305 template<class ScalarType, class MV, class OP>
00306 TraceMinBaseSolMgr<ScalarType,MV,OP>::TraceMinBaseSolMgr( 
00307         const RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
00308         Teuchos::ParameterList &pl ) : 
00309   problem_(problem)
00310 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
00311   , _timerSolve(Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinBaseSolMgr::solve()")),
00312   _timerRestarting(Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinBaseSolMgr restarting")),
00313   _timerLocking(Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinBaseSolMgr locking"))
00314 #endif
00315 {
00316   TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null,              std::invalid_argument, "Problem not given to solver manager.");
00317   TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(),              std::invalid_argument, "Problem not set.");
00318   TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isHermitian(),               std::invalid_argument, "Problem not symmetric.");
00319   TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from.");
00320 
00321   std::string strtmp;
00322 
00324   // Block parameters
00325 
00326   // TODO: the default is different for TraceMin and TraceMin-Davidson
00327   // block size: default is nev()
00328 //  blockSize_ = pl.get("Block Size",problem_->getNEV());
00329 //  TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
00330 //                     "Anasazi::TraceMinBaseSolMgr: \"Block Size\" must be strictly positive.");
00331 
00332   // TODO: add Num Blocks as a parameter to both child classes, since they have different default values
00333 //  numBlocks_ = pl.get("Num Blocks",5);
00334 //  TEUCHOS_TEST_FOR_EXCEPTION(numBlocks_ < 2, std::invalid_argument,
00335 //                     "Anasazi::TraceMinBaseSolMgr: \"Num Blocks\" must be >= 2.");
00336 
00338   // Output parameters
00339 
00340   // output stream
00341   std::string fntemplate = "";
00342   bool allProcs = false;
00343   if (pl.isParameter("Output on all processors")) {
00344     if (Teuchos::isParameterType<bool>(pl,"Output on all processors")) {
00345       allProcs = pl.get("Output on all processors",allProcs);
00346     } else {
00347       allProcs = ( Teuchos::getParameter<int>(pl,"Output on all processors") != 0 );
00348     }
00349   }
00350   fntemplate = pl.get("Output filename template",fntemplate);
00351   int MyPID;
00352 # ifdef HAVE_MPI
00353     // Initialize MPI
00354     int mpiStarted = 0;
00355     MPI_Initialized(&mpiStarted);
00356     if (mpiStarted) MPI_Comm_rank(MPI_COMM_WORLD, &MyPID);
00357     else MyPID=0;
00358 # else 
00359     MyPID = 0;
00360 # endif
00361   if (fntemplate != "") {
00362     std::ostringstream MyPIDstr;
00363     MyPIDstr << MyPID;
00364     // replace %d in fntemplate with MyPID
00365     int pos, start=0;
00366     while ( (pos = fntemplate.find("%d",start)) != -1 ) {
00367       fntemplate.replace(pos,2,MyPIDstr.str());
00368       start = pos+2;
00369     }
00370   }
00371   RCP<ostream> osp;
00372   if (fntemplate != "") {
00373     osp = rcp( new std::ofstream(fntemplate.c_str(),std::ios::out | std::ios::app) );
00374     if (!*osp) {
00375       osp = Teuchos::rcpFromRef(std::cout);
00376       std::cout << "Anasazi::TraceMinBaseSolMgr::constructor(): Could not open file for write: " << fntemplate << std::endl;
00377     }
00378   }
00379   else {
00380     osp = Teuchos::rcpFromRef(std::cout);
00381   }
00382   // Output manager
00383   int verbosity = Anasazi::Errors;
00384   if (pl.isParameter("Verbosity")) {
00385     if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
00386       verbosity = pl.get("Verbosity", verbosity);
00387     } else {
00388       verbosity = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
00389     }
00390   }
00391   if (allProcs) {
00392     // print on all procs
00393     printer_ = rcp( new BasicOutputManager<ScalarType>(verbosity,osp,MyPID) );
00394   }
00395   else {
00396     // print only on proc 0
00397     printer_ = rcp( new BasicOutputManager<ScalarType>(verbosity,osp,0) );
00398   }
00399 
00400   // TODO: Add restart parameters to TraceMin-Davidson
00401 
00403   // Convergence parameters
00404   convTol_ = pl.get("Convergence Tolerance",MT::prec());
00405   TEUCHOS_TEST_FOR_EXCEPTION(convTol_ < 0, std::invalid_argument,
00406                      "Anasazi::TraceMinBaseSolMgr: \"Convergence Tolerance\" must be nonnegative.");
00407 
00408   relConvTol_ = pl.get("Relative Convergence Tolerance",true);
00409   strtmp = pl.get("Convergence Norm",std::string("2"));
00410   if (strtmp == "2") {
00411     convNorm_ = RES_2NORM;
00412   }
00413   else if (strtmp == "M") {
00414     convNorm_ = RES_ORTH;
00415   }
00416   else {
00417     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, 
00418         "Anasazi::TraceMinBaseSolMgr: Invalid Convergence Norm.");
00419   }
00420 
00422   // Locking parameters
00423   useLocking_ = pl.get("Use Locking",true);
00424   relLockTol_ = pl.get("Relative Locking Tolerance",true);
00425   lockTol_ = pl.get("Locking Tolerance",convTol_/10);
00426 
00427   TEUCHOS_TEST_FOR_EXCEPTION(relConvTol_ != relLockTol_, std::invalid_argument,
00428          "Anasazi::TraceMinBaseSolMgr: \"Relative Convergence Tolerance\" and \"Relative Locking Tolerance\" have different values.  If you set one, you should always set the other.");
00429 
00430   TEUCHOS_TEST_FOR_EXCEPTION(lockTol_ < 0, std::invalid_argument,
00431                      "Anasazi::TraceMinBaseSolMgr: \"Locking Tolerance\" must be nonnegative.");
00432 
00433   strtmp = pl.get("Locking Norm",std::string("2"));
00434   if (strtmp == "2") {
00435     lockNorm_ = RES_2NORM;
00436   }
00437   else if (strtmp == "M") {
00438     lockNorm_ = RES_ORTH;
00439   }
00440   else {
00441     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, 
00442         "Anasazi::TraceMinBaseSolMgr: Invalid Locking Norm.");
00443   }
00444 
00445   // max locked: default is nev(), must satisfy maxLocked_ + blockSize_ >= nev
00446   if (useLocking_) {
00447     maxLocked_ = pl.get("Max Locked",problem_->getNEV());
00448     TEUCHOS_TEST_FOR_EXCEPTION(maxLocked_ <= 0, std::invalid_argument,
00449            "Anasazi::TraceMinBaseSolMgr: \"Max Locked\" must be strictly positive.");
00450   }
00451   else {
00452     maxLocked_ = 0;
00453   }
00454 
00455   if (useLocking_) {
00456     lockQuorum_ = pl.get("Locking Quorum",1);
00457     TEUCHOS_TEST_FOR_EXCEPTION(lockQuorum_ <= 0, std::invalid_argument,
00458                        "Anasazi::TraceMinBaseSolMgr: \"Locking Quorum\" must be strictly positive.");
00459   }
00460 
00462   // Ritz shift parameters
00463 
00464   // When to shift - what triggers a shift?
00465   strtmp = pl.get("When To Shift", "Always");
00466 
00467   if(strtmp == "Never")
00468     whenToShift_ = NEVER_SHIFT;
00469   else if(strtmp == "After Trace Levels")
00470     whenToShift_ = SHIFT_WHEN_TRACE_LEVELS;
00471   else if(strtmp == "Residual Becomes Small")
00472     whenToShift_ = SHIFT_WHEN_RESID_SMALL;
00473   else if(strtmp == "Always")
00474     whenToShift_ = ALWAYS_SHIFT;
00475   else
00476     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
00477            "Anasazi::TraceMinBaseSolMgr: Invalid value for \"When To Shift\"; valid options are \"Never\", \"After Trace Levels\", \"Residual Becomes Small\", \"Always\".");  
00478 
00479 
00480   // How small does the % change in trace have to get before shifting?
00481   traceThresh_ = pl.get("Trace Threshold", 0.02);
00482 
00483   TEUCHOS_TEST_FOR_EXCEPTION(traceThresh_ < 0, std::invalid_argument,
00484                        "Anasazi::TraceMinBaseSolMgr: \"Trace Threshold\" must be nonnegative.");
00485 
00486   // Shift threshold - if the residual of an eigenpair is less than this, then shift
00487   shiftTol_ = pl.get("Shift Tolerance", 0.1);
00488 
00489   TEUCHOS_TEST_FOR_EXCEPTION(shiftTol_ < 0, std::invalid_argument,
00490                        "Anasazi::TraceMinBaseSolMgr: \"Shift Tolerance\" must be nonnegative.");
00491 
00492   // Use relative convergence tolerance - scale by eigenvalue?
00493   relShiftTol_ = pl.get("Relative Shift Tolerance", true);
00494 
00495   // Which norm to use in determining whether to shift
00496   shiftNorm_ = pl.get("Shift Norm", "2");
00497 
00498   TEUCHOS_TEST_FOR_EXCEPTION(shiftNorm_ != "2" && shiftNorm_ != "M", std::invalid_argument,
00499          "Anasazi::TraceMinBaseSolMgr: Invalid value for \"Shift Norm\"; valid options are \"2\" and \"M\".");  
00500 
00501   // How to choose shift
00502   strtmp = pl.get("How To Choose Shift", "Adjusted Ritz Values");
00503   
00504   if(strtmp == "Largest Converged")
00505     howToShift_ = LARGEST_CONVERGED_SHIFT;
00506   else if(strtmp == "Adjusted Ritz Values")
00507     howToShift_ = ADJUSTED_RITZ_SHIFT;
00508   else if(strtmp == "Ritz Values")
00509     howToShift_ = RITZ_VALUES_SHIFT;
00510   else
00511     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
00512            "Anasazi::TraceMinBaseSolMgr: Invalid value for \"How To Choose Shift\"; valid options are \"Largest Converged\", \"Adjusted Ritz Values\", \"Ritz Values\".");
00513 
00514   // Consider clusters - if all eigenvalues are in one cluster, it's not expecially safe to shift
00515   considerClusters_ = pl.get("Consider Clusters", true);
00516 
00517   // Use multiple shifts
00518   useMultipleShifts_ = pl.get("Use Multiple Shifts", true);
00519 
00521   // Other parameters
00522 
00523   // which orthogonalization to use
00524   ortho_ = pl.get("Orthogonalization", "SVQB");
00525   TEUCHOS_TEST_FOR_EXCEPTION(ortho_ != "DGKS" && ortho_ != "SVQB" && ortho_ != "ICGS", std::invalid_argument,
00526          "Anasazi::TraceMinBaseSolMgr: Invalid value for \"Orthogonalization\"; valid options are \"DGKS\", \"SVQB\", \"ICGS\".");  
00527 
00528   strtmp = pl.get("Saddle Solver Type", "Projected Krylov");
00529   
00530   if(strtmp == "Projected Krylov")
00531     saddleSolType_ = PROJECTED_KRYLOV_SOLVER;
00532   else if(strtmp == "Schur Complement")
00533     saddleSolType_ = SCHUR_COMPLEMENT_SOLVER;
00534   else if(strtmp == "Block Diagonal Preconditioned Minres")
00535     saddleSolType_ = BD_PREC_MINRES;
00536   else
00537     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
00538            "Anasazi::TraceMinBaseSolMgr: Invalid value for \"Saddle Solver Type\"; valid options are \"Projected Krylov\", \"Schur Complement\", and \"Block Diagonal Preconditioned Minres\".");
00539 
00540   projectAllVecs_ = pl.get("Project All Vectors", true);
00541   projectLockedVecs_ = pl.get("Project Locked Vectors", true);
00542   computeAllRes_ = pl.get("Compute All Residuals", true);
00543   useRHSR_ = pl.get("Use Residual as RHS", true);
00544 
00545   TEUCHOS_TEST_FOR_EXCEPTION(projectLockedVecs_ && ! projectAllVecs_, std::invalid_argument,
00546          "Anasazi::TraceMinBaseSolMgr: If you want to project out the locked vectors, you should really project out ALL the vectors of X.");
00547 
00548   // Maximum number of inner iterations
00549   maxKrylovIter_ = pl.get("Maximum Krylov Iterations", 1000);
00550   TEUCHOS_TEST_FOR_EXCEPTION(maxKrylovIter_ < 1, std::invalid_argument,
00551          "Anasazi::TraceMinBaseSolMgr: \"Maximum Krylov Iterations\" must be greater than 0.");
00552      
00553   // Which eigenvalues we want to get
00554   which_ = pl.get("Which", "SM");
00555   TEUCHOS_TEST_FOR_EXCEPTION(which_ != "SM" && which_ != "LM", std::invalid_argument,
00556          "Anasazi::TraceMinBaseSolMgr: Invalid value for \"Which\"; valid options are \"SM\" and \"LM\".");
00557 
00558   // Test whether we are shifting without an operator K
00559   // This is a really bad idea
00560   TEUCHOS_TEST_FOR_EXCEPTION(problem_->getOperator() == Teuchos::null && whenToShift_ != NEVER_SHIFT, std::invalid_argument,
00561          "Anasazi::TraceMinBaseSolMgr: It is an exceptionally bad idea to use Ritz shifts when finding the largest eigenpairs of a standard eigenvalue problem.  If we don't use Ritz shifts, it may take extra iterations to converge, but we NEVER have to solve a single linear system.  Using Ritz shifts forces us to solve systems of the form (I + sigma A)x=f, and it probably doesn't benefit us enough to outweigh the extra cost.  We may add support for this feature in the future, but for now, please set \"When To Shift\" to \"Never\".");
00562 
00563 #ifdef BELOS_PSEUDO_BLOCK_GMRES_SOLMGR_HPP
00564   // Test whether we are using a projected preconditioner with multiple Ritz shifts
00565   // We can't currently do this for reasons that are complicated and are explained in the user manual
00566   TEUCHOS_TEST_FOR_EXCEPTION(problem_->getPrec() != Teuchos::null && saddleSolType_ == PROJECTED_KRYLOV_SOLVER && useMultipleShifts_, std::invalid_argument,
00567          "Anasazi::TraceMinBaseSolMgr: When you use the projected Krylov solver with preconditioning, the preconditioner must be projected as well.  In theory, if the preconditioner is SPD, the projected preconditioner will be SPSD, but in practice, it can have small negative eigenvalues, presumably due to machine arithmetic.  This means we can't use TraceMin's built-in MINRES, and we are forced to use Belos for now.  When you use multiple Ritz shifts, you are essentially using a different operator to solve each linear system.  Belos can't handle this right now, but we're working on a solution.  For now, please set \"Use Multiple Shifts\" to false.");
00568 #else
00569   // Test whether we are using a projected preconditioner without Belos.
00570   // P Prec P should be positive definite if Prec is positive-definite, 
00571   // but it tends not to be in practice, presumably due to machine arithmetic
00572   // As a result, we have to use pseudo-block gmres for now.
00573   // Make sure it's available.
00574   TEUCHOS_TEST_FOR_EXCEPTION(problem_->getPrec() != Teuchos::null && saddleSolType_ == PROJECTED_KRYLOV_SOLVER, std::invalid_argument,
00575          "Anasazi::TraceMinBaseSolMgr: When you use the projected Krylov solver with preconditioning, the preconditioner must be projected as well.  In theory, if the preconditioner is SPD, the projected preconditioner will be SPSD, but in practice, it can have small negative eigenvalues, presumably due to machine arithmetic.  This means we can't use TraceMin's built-in MINRES, and we are forced to use Belos for now.  You didn't install Belos.  You have three options to correct this problem:\n1. Reinstall Trilinos with Belos enabled (Recommended)\n2. Don't use a preconditioner\n3. Choose a different method for solving the saddle-point problem");
00576 
00577 
00578 #endif
00579 
00580   
00581 }
00582 
00583 
00586 // solve()
00587 template<class ScalarType, class MV, class OP>
00588 ReturnType 
00589 TraceMinBaseSolMgr<ScalarType,MV,OP>::solve() 
00590 {
00591   typedef SolverUtils<ScalarType,MV,OP> msutils;
00592 
00593   const int nev = problem_->getNEV();
00594 
00595 #ifdef TEUCHOS_DEBUG
00596     RCP<Teuchos::FancyOStream>
00597       out = Teuchos::getFancyOStream(Teuchos::rcpFromRef(printer_->stream(Debug)));
00598     out->setShowAllFrontMatter(false).setShowProcRank(true);
00599     *out << "Entering Anasazi::TraceMinBaseSolMgr::solve()\n";
00600 #endif
00601 
00603   // Sort manager
00604   RCP<BasicSort<MagnitudeType> > sorter = rcp( new BasicSort<MagnitudeType>("SM") );
00605 
00607   // Handle the spectral transformation if necessary
00608   // TODO: Make sure we undo this before returning...
00609   if(which_ == "LM")
00610   {
00611     RCP<const OP> swapHelper = problem_->getOperator();
00612     problem_->setOperator(problem_->getM());
00613     problem_->setM(swapHelper);
00614     problem_->setProblem();
00615   } 
00616 
00618   // Status tests
00619   //
00620   // convergence
00621   RCP<StatusTest<ScalarType,MV,OP> > convtest;
00622   if (globalTest_ == Teuchos::null) {
00623     if(which_ == "SM")
00624       convtest = rcp( new StatusTestResNorm<ScalarType,MV,OP>(convTol_,nev,convNorm_,relConvTol_) );
00625     else
00626       convtest = rcp( new StatusTestSpecTrans<ScalarType,MV,OP>(convTol_,nev,convNorm_,relConvTol_,true,problem_->getOperator()) );
00627   }
00628   else {
00629     convtest = globalTest_;
00630   }
00631   RCP<StatusTestWithOrdering<ScalarType,MV,OP> > ordertest 
00632     = rcp( new StatusTestWithOrdering<ScalarType,MV,OP>(convtest,sorter,nev) );
00633   // locking
00634   RCP<StatusTest<ScalarType,MV,OP> > locktest;
00635   if (useLocking_) {
00636     if (lockingTest_ == Teuchos::null) {
00637       if(which_ == "SM")
00638         locktest = rcp( new StatusTestResNorm<ScalarType,MV,OP>(lockTol_,lockQuorum_,lockNorm_,relLockTol_) );
00639       else
00640         locktest = rcp( new StatusTestSpecTrans<ScalarType,MV,OP>(lockTol_,lockQuorum_,lockNorm_,relLockTol_,true,problem_->getOperator()) );
00641     }
00642     else {
00643       locktest = lockingTest_;
00644     }
00645   }
00646   // for a non-short-circuited OR test, the order doesn't matter
00647   Teuchos::Array<RCP<StatusTest<ScalarType,MV,OP> > > alltests;
00648   alltests.push_back(ordertest);
00649   if (locktest != Teuchos::null) alltests.push_back(locktest);
00650   if (debugTest_ != Teuchos::null) alltests.push_back(debugTest_);
00651 
00652   RCP<StatusTestCombo<ScalarType,MV,OP> > combotest
00653     = rcp( new StatusTestCombo<ScalarType,MV,OP>( StatusTestCombo<ScalarType,MV,OP>::OR, alltests) );
00654   // printing StatusTest
00655   RCP<StatusTestOutput<ScalarType,MV,OP> > outputtest;
00656   if ( printer_->isVerbosity(Debug) ) {
00657     outputtest = rcp( new StatusTestOutput<ScalarType,MV,OP>( printer_,combotest,1,Passed+Failed+Undefined ) );
00658   }
00659   else {
00660     outputtest = rcp( new StatusTestOutput<ScalarType,MV,OP>( printer_,combotest,1,Passed ) );
00661   }
00662 
00664   // Orthomanager
00665   RCP<MatOrthoManager<ScalarType,MV,OP> > ortho; 
00666   if (ortho_=="SVQB") {
00667     ortho = rcp( new SVQBOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
00668   } else if (ortho_=="DGKS") {
00669     ortho = rcp( new BasicOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
00670   } else if (ortho_=="ICGS") {
00671     ortho = rcp( new ICGSOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
00672   } else {
00673     TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::TraceMinBaseSolMgr::solve(): Invalid orthogonalization type.");
00674   }
00675 
00677   // Parameter list
00678   Teuchos::ParameterList plist;
00679   setParameters(plist);
00680 
00682   // TraceMinBase solver
00683   RCP<TraceMinBase<ScalarType,MV,OP> > tm_solver 
00684     = createSolver(sorter,outputtest,ortho,plist);
00685   // set any auxiliary vectors defined in the problem
00686   RCP< const MV > probauxvecs = problem_->getAuxVecs();
00687   if (probauxvecs != Teuchos::null) {
00688     tm_solver->setAuxVecs( Teuchos::tuple< RCP<const MV> >(probauxvecs) );
00689   }
00690 
00692   // Storage
00693   // 
00694   // lockvecs will contain eigenvectors that have been determined "locked" by the status test
00695   int curNumLocked = 0;
00696   RCP<MV> lockvecs;
00697   // lockvecs is used to hold the locked eigenvectors, as well as for temporary storage when locking.
00698   // when locking, we will lock some number of vectors numnew, where numnew <= maxlocked - curlocked
00699   // we will produce numnew random vectors, which will go into the space with the new basis.
00700   // we will also need numnew storage for the image of these random vectors under A and M; 
00701   // columns [curlocked+1,curlocked+numnew] will be used for this storage
00702   if (maxLocked_ > 0) {
00703     lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
00704   }
00705   std::vector<MagnitudeType> lockvals;
00706   //
00707   // Restarting occurs under two scenarios: when the basis is full and after locking.
00708   //
00709   // For the former, a new basis of size blockSize*numRestartBlocks is generated using the current basis
00710   // and the most significant primitive Ritz vectors (projected eigenvectors).
00711   //     [S,L] = eig(KK)
00712   //     S = [Sr St]   // some for "r"estarting, some are "t"runcated
00713   //     newV = V*Sr
00714   //     KK_new = newV'*K*newV = Sr'*V'*K*V*Sr = Sr'*KK*Sr
00715   //  Therefore, the only multivector operation needed is for the generation of newV.
00716   //
00717   //  * If the multiplication is explicit, it requires a workspace of blockSize*numRestartBlocks vectors. 
00718   //    This space must be specifically allocated for that task, as we don't have any space of that size.
00719   //    It (workMV) will be allocated at the beginning of solve()
00720   //  * Optionally, the multiplication can be performed implicitly, via a Householder QR factorization of 
00721   //    Sr. This can be done in situ, using the basis multivector contained in the solver. This requires
00722   //    that we cast away the const on the multivector returned from getState(). Workspace for this approach
00723   //    is a single vector. the solver's internal storage must be preserved (X,MX,KX,R), requiring us to 
00724   //    allocate this vector.
00725   //
00726   // For the latter (restarting after locking), the new basis is the same size as existing basis. If numnew
00727   // vectors are locked, they are deflated from the current basis and replaced with randomly generated 
00728   // vectors.
00729   //     [S,L] = eig(KK)
00730   //     S = [Sl Su]  // partitioned: "l"ocked and "u"nlocked
00731   //     newL = V*Sl = X(locked)
00732   //     defV = V*Su
00733   //     augV = rand(numnew)  // orthogonal to oldL,newL,defV,auxvecs
00734   //     newV = [defV augV]
00735   //     Kknew = newV'*K*newV = [Su'*KK*Su    defV'*K*augV]
00736   //                            [augV'*K*defV augV'*K*augV]
00737   //     locked = [oldL newL]
00738   // Clearly, this operation is more complicated than the previous.
00739   // Here is a list of the significant computations that need to be performed:
00740   // - newL will be put into space in lockvecs, but will be copied from getState().X at the end
00741   // - defV,augV will be stored in workspace the size of the current basis.
00742   // - M*augV and K*augV are needed; they will be stored in lockvecs. As a result, newL will
00743   //   not be put into lockvecs until the end.
00744   //
00745   // Therefore, we must allocate workMV when ((maxRestarts_ > 0) || (useLocking_ == true)) && inSituRestart == false
00746   // It will be allocated to size (numBlocks-1)*blockSize
00747   //
00748 
00749   // some consts and utils
00750   const ScalarType ONE = SCT::one();
00751   const ScalarType ZERO = SCT::zero();
00752 
00753   // go ahead and initialize the solution to nothing in case we throw an exception
00754   Eigensolution<ScalarType,MV> sol;
00755   sol.numVecs = 0;
00756   problem_->setSolution(sol);
00757 
00758   int numRestarts = 0;
00759 
00760   // enter solve() iterations
00761   {
00762 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
00763     Teuchos::TimeMonitor slvtimer(*_timerSolve);
00764 #endif
00765 
00766     // tell tm_solver to iterate
00767     while (1) {
00768       try {
00769         tm_solver->iterate();
00770 
00772         //
00773         //
00775         if (debugTest_ != Teuchos::null && debugTest_->getStatus() == Passed) {
00776           throw AnasaziError("Anasazi::TraceMinBaseSolMgr::solve(): User-specified debug status test returned Passed.");
00777         }
00779         //
00780         // check convergence next
00781         //
00783         else if (ordertest->getStatus() == Passed ) {
00784           // we have convergence
00785           // ordertest->whichVecs() tells us which vectors from lockvecs and solver state are the ones we want
00786           // ordertest->howMany() will tell us how many
00787           break;
00788         }
00790         //
00791         // check locking if we didn't converge or restart
00792         //
00794         else if (locktest != Teuchos::null && locktest->getStatus() == Passed) {
00795 
00796 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
00797           Teuchos::TimeMonitor lcktimer(*_timerLocking);
00798 #endif
00799 
00800           // 
00801           // get current state
00802           TraceMinBaseState<ScalarType,MV> state = tm_solver->getState();
00803           const int curdim = state.curDim;
00804 
00805           //
00806           // get number,indices of vectors to be locked
00807           TEUCHOS_TEST_FOR_EXCEPTION(locktest->howMany() <= 0,std::logic_error,
00808               "Anasazi::TraceMinBaseSolMgr::solve(): status test mistake: howMany() non-positive.");
00809           TEUCHOS_TEST_FOR_EXCEPTION(locktest->howMany() != (int)locktest->whichVecs().size(),std::logic_error,
00810               "Anasazi::TraceMinBaseSolMgr::solve(): status test mistake: howMany() not consistent with whichVecs().");
00811           // we should have room to lock vectors; otherwise, locking should have been deactivated
00812           TEUCHOS_TEST_FOR_EXCEPTION(curNumLocked == maxLocked_,std::logic_error,
00813               "Anasazi::TraceMinBaseSolMgr::solve(): status test mistake: locking not deactivated.");
00814           //
00815           // don't lock more than maxLocked_; we didn't allocate enough space.
00816           std::vector<int> tmp_vector_int;
00817           if (curNumLocked + locktest->howMany() > maxLocked_) {
00818             // just use the first of them
00819             tmp_vector_int.insert(tmp_vector_int.begin(),locktest->whichVecs().begin(),locktest->whichVecs().begin()+maxLocked_-curNumLocked);
00820           }
00821           else {
00822             tmp_vector_int = locktest->whichVecs();
00823           }
00824 
00825           const std::vector<int> lockind(tmp_vector_int);
00826           const int numNewLocked = lockind.size();
00827           //
00828           // generate indices of vectors left unlocked
00829           // curind = [0,...,curdim-1] = UNION( lockind, unlockind )
00830           const int numUnlocked = curdim-numNewLocked;
00831           tmp_vector_int.resize(curdim);
00832           for (int i=0; i<curdim; i++) tmp_vector_int[i] = i;
00833           const std::vector<int> curind(tmp_vector_int);       // curind = [0 ... curdim-1]
00834           tmp_vector_int.resize(numUnlocked); 
00835           std::set_difference(curind.begin(),curind.end(),lockind.begin(),lockind.end(),tmp_vector_int.begin());
00836           const std::vector<int> unlockind(tmp_vector_int);    // unlockind = [0 ... curdim-1] - lockind
00837           tmp_vector_int.clear();
00838 
00839           //
00840           // debug printing
00841           if (printer_->isVerbosity(Debug)) {
00842             printer_->print(Debug,"Locking vectors: ");
00843             for (unsigned int i=0; i<lockind.size(); i++) {printer_->stream(Debug) << " " << lockind[i];}
00844             printer_->print(Debug,"\n");
00845             printer_->print(Debug,"Not locking vectors: ");
00846             for (unsigned int i=0; i<unlockind.size(); i++) {printer_->stream(Debug) << " " << unlockind[i];}
00847             printer_->print(Debug,"\n");
00848           }
00849 
00850           // Copy eigenvalues we want to lock into lockvals
00851           std::vector<Value<ScalarType> > allvals = tm_solver->getRitzValues();
00852           for (int i=0; i<numNewLocked; i++) {
00853             lockvals.push_back(allvals[lockind[i]].realpart);
00854           }
00855 
00856           // Copy vectors we want to lock into lockvecs
00857           RCP<const MV> newLocked = MVT::CloneView(*tm_solver->getRitzVectors(),lockind);
00858           std::vector<int> indlock(numNewLocked);
00859           for (int i=0; i<numNewLocked; i++) indlock[i] = curNumLocked+i;
00860           MVT::SetBlock(*newLocked,indlock,*lockvecs);
00861 
00862           // Tell the StatusTestWithOrdering that things have been locked
00863           // This is VERY important
00864           // If this set of lines is removed, the code does not terminate correctly
00865           ordertest->setAuxVals(lockvals);
00866 
00867           // Set the auxiliary vectors so that we remain orthogonal to the ones we locked
00868           // Remember to include any aux vecs provided by the user
00869           curNumLocked += numNewLocked;
00870 
00871           if(ordertest->getStatus() == Passed)  break;
00872 
00873           std::vector<int> curlockind(curNumLocked);
00874           for (int i=0; i<curNumLocked; i++) curlockind[i] = i;
00875           RCP<const MV> curlocked = MVT::CloneView(*lockvecs,curlockind);
00876 
00877           Teuchos::Array< RCP<const MV> > aux;
00878           if (probauxvecs != Teuchos::null) aux.push_back(probauxvecs);
00879           aux.push_back(curlocked);
00880           tm_solver->setAuxVecs(aux);
00881 
00882           // Disable locking if we have locked the maximum number of things
00883           printer_->stream(Debug) << "curNumLocked: " << curNumLocked << std::endl;
00884           printer_->stream(Debug) << "maxLocked: " << maxLocked_ << std::endl;
00885           if (curNumLocked == maxLocked_) {
00886             // disabled locking now
00887             combotest->removeTest(locktest);
00888             locktest = Teuchos::null;
00889             printer_->stream(Debug) << "Removed locking test\n";
00890           }
00891 
00892           int newdim = numRestartBlocks_*blockSize_;
00893           TraceMinBaseState<ScalarType,MV> newstate;
00894           if(newdim <= numUnlocked)
00895           {
00896             std::vector<int> desiredSubscripts(newdim);
00897             for(int i=0; i<newdim; i++)
00898             {
00899               desiredSubscripts[i] = unlockind[i];
00900               printer_->stream(Debug) << "desiredSubscripts[" << i << "] = " << desiredSubscripts[i] << std::endl;
00901             }
00902 
00903             copyPartOfState(state, newstate, desiredSubscripts);
00904           }
00905           else
00906           {
00907             // TODO: Come back to this and make it more efficient
00908 
00909             // Replace the converged eigenvectors with random ones
00910             int nrandom = newdim-numUnlocked;
00911   
00912             RCP<const MV> helperMV;
00913             RCP<MV> totalV = MVT::Clone(*tm_solver->getRitzVectors(),newdim);
00914 
00915             // Holds old things that we're keeping
00916             tmp_vector_int.resize(numUnlocked);
00917             for(int i=0; i<numUnlocked; i++) tmp_vector_int[i] = i;
00918             RCP<MV> oldV = MVT::CloneViewNonConst(*totalV,tmp_vector_int);
00919 
00920             // Copy over the old things
00921             helperMV = MVT::CloneView(*state.V,unlockind);
00922             MVT::Assign(*helperMV,*oldV);
00923 
00924             // Holds random vectors we're generating
00925             tmp_vector_int.resize(nrandom);
00926             for(int i=0; i<nrandom; i++) tmp_vector_int[i] = i+numUnlocked;
00927             RCP<MV> newV = MVT::CloneViewNonConst(*totalV,tmp_vector_int);
00928 
00929             // Create random things
00930             MVT::MvRandom(*newV);
00931 
00932             newstate.V = totalV;
00933             newstate.curDim = newdim;
00934 
00935             // Copy Ritz shifts
00936             RCP< std::vector<ScalarType> > helperRS = rcp( new std::vector<ScalarType>(blockSize_) );
00937             for(unsigned int i=0; i<(unsigned int)blockSize_; i++) 
00938             {
00939               if(i < unlockind.size() && unlockind[i] < blockSize_)
00940                 (*helperRS)[i] = (*state.ritzShifts)[unlockind[i]];
00941               else
00942                 (*helperRS)[i] = ZERO;
00943             }
00944             newstate.ritzShifts  = helperRS;
00945           }
00946 
00947           // Determine the largest safe shift
00948           newstate.largestSafeShift = std::abs(lockvals[0]);
00949           for(size_t i=0; i<lockvals.size(); i++)
00950             newstate.largestSafeShift = std::max(std::abs(lockvals[i]), newstate.largestSafeShift);
00951 
00952           // Prepare new state, removing converged vectors
00953           // TODO: Init will perform some unnecessary calculations; look into it
00954           // TODO: The residual norms should be part of the state
00955           newstate.NEV = state.NEV - numNewLocked;
00956           tm_solver->initialize(newstate);
00957         } // end of locking
00959         //
00960         // check for restarting before locking: if we need to lock, it will happen after the restart
00961         //
00963         else if ( needToRestart(tm_solver) ) {
00964           // if performRestart returns false, we exceeded the maximum number of restarts
00965           if(performRestart(numRestarts, tm_solver) == false)
00966             break;
00967         } // end of restarting
00969         //
00970         // we returned from iterate(), but none of our status tests Passed.
00971         // something is wrong, and it is probably our fault.
00972         //
00974         else {
00975           TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::TraceMinBaseSolMgr::solve(): Invalid return from tm_solver::iterate().");
00976         }
00977       }
00978       catch (const AnasaziError &err) {
00979         printer_->stream(Errors) 
00980           << "Anasazi::TraceMinBaseSolMgr::solve() caught unexpected exception from Anasazi::TraceMinBase::iterate() at iteration " << tm_solver->getNumIters() << std::endl
00981           << err.what() << std::endl
00982           << "Anasazi::TraceMinBaseSolMgr::solve() returning Unconverged with no solutions." << std::endl;
00983         return Unconverged;
00984       }
00985     }
00986 
00987     sol.numVecs = ordertest->howMany();
00988     if (sol.numVecs > 0) {
00989       sol.Evecs = MVT::Clone(*problem_->getInitVec(),sol.numVecs);
00990       sol.Espace = sol.Evecs;
00991       sol.Evals.resize(sol.numVecs);
00992       std::vector<MagnitudeType> vals(sol.numVecs);
00993 
00994       // copy them into the solution
00995       std::vector<int> which = ordertest->whichVecs();
00996       // indices between [0,blockSize) refer to vectors/values in the solver
00997       // indices between [-curNumLocked,-1] refer to locked vectors/values [0,curNumLocked)
00998       // everything has already been ordered by the solver; we just have to partition the two references
00999       std::vector<int> inlocked(0), insolver(0);
01000       for (unsigned int i=0; i<which.size(); i++) {
01001         if (which[i] >= 0) {
01002           TEUCHOS_TEST_FOR_EXCEPTION(which[i] >= blockSize_,std::logic_error,"Anasazi::TraceMinBaseSolMgr::solve(): positive indexing mistake from ordertest.");
01003           insolver.push_back(which[i]);
01004         }
01005         else {
01006           // sanity check
01007           TEUCHOS_TEST_FOR_EXCEPTION(which[i] < -curNumLocked,std::logic_error,"Anasazi::TraceMinBaseSolMgr::solve(): negative indexing mistake from ordertest.");
01008           inlocked.push_back(which[i] + curNumLocked);
01009         }
01010       }
01011 
01012       TEUCHOS_TEST_FOR_EXCEPTION(insolver.size() + inlocked.size() != (unsigned int)sol.numVecs,std::logic_error,"Anasazi::TraceMinBaseSolMgr::solve(): indexing mistake.");
01013 
01014       // set the vecs,vals in the solution
01015       if (insolver.size() > 0) {
01016         // set vecs
01017         int lclnum = insolver.size();
01018         std::vector<int> tosol(lclnum);
01019         for (int i=0; i<lclnum; i++) tosol[i] = i;
01020         RCP<const MV> v = MVT::CloneView(*tm_solver->getRitzVectors(),insolver);
01021         MVT::SetBlock(*v,tosol,*sol.Evecs);
01022         // set vals
01023         std::vector<Value<ScalarType> > fromsolver = tm_solver->getRitzValues();
01024         for (unsigned int i=0; i<insolver.size(); i++) {
01025           vals[i] = fromsolver[insolver[i]].realpart;
01026         }
01027       }
01028 
01029       // get the vecs,vals from locked storage
01030       if (inlocked.size() > 0) {
01031         int solnum = insolver.size();
01032         // set vecs
01033         int lclnum = inlocked.size();
01034         std::vector<int> tosol(lclnum);
01035         for (int i=0; i<lclnum; i++) tosol[i] = solnum + i;
01036         RCP<const MV> v = MVT::CloneView(*lockvecs,inlocked);
01037         MVT::SetBlock(*v,tosol,*sol.Evecs);
01038         // set vals
01039         for (unsigned int i=0; i<inlocked.size(); i++) {
01040           vals[i+solnum] = lockvals[inlocked[i]];
01041         }
01042       }
01043 
01044       // undo the spectral transformation if necessary
01045       // if we really passed the solver Bx = \lambda A x, invert the eigenvalues
01046       if(which_ == "LM")
01047       {
01048         for(size_t i=0; i<vals.size(); i++)
01049           vals[i] = ONE/vals[i];
01050       }
01051 
01052       // sort the eigenvalues and permute the eigenvectors appropriately
01053       {
01054         std::vector<int> order(sol.numVecs);
01055         sorter->sort(vals,Teuchos::rcpFromRef(order),sol.numVecs);
01056         // store the values in the Eigensolution
01057         for (int i=0; i<sol.numVecs; i++) {
01058           sol.Evals[i].realpart = vals[i];
01059           sol.Evals[i].imagpart = MT::zero();
01060         }
01061         // now permute the eigenvectors according to order
01062         msutils::permuteVectors(sol.numVecs,order,*sol.Evecs);
01063       }
01064 
01065       // setup sol.index, remembering that all eigenvalues are real so that index = {0,...,0}
01066       sol.index.resize(sol.numVecs,0);
01067     }
01068   }
01069 
01070   // print final summary
01071   tm_solver->currentStatus(printer_->stream(FinalSummary));
01072 
01073   printParameters(printer_->stream(FinalSummary));
01074 
01075   // print timing information
01076 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
01077   if ( printer_->isVerbosity( TimingDetails ) ) {
01078     Teuchos::TimeMonitor::summarize( printer_->stream( TimingDetails ) );
01079   }
01080 #endif
01081 
01082   problem_->setSolution(sol);
01083   printer_->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
01084 
01085   // get the number of iterations taken for this call to solve().
01086   numIters_ = tm_solver->getNumIters();
01087 
01088   if (sol.numVecs < nev) {
01089     return Unconverged; // return from TraceMinBaseSolMgr::solve() 
01090   }
01091   return Converged; // return from TraceMinBaseSolMgr::solve() 
01092 }
01093 
01094 
01095 template <class ScalarType, class MV, class OP>
01096 void 
01097 TraceMinBaseSolMgr<ScalarType,MV,OP>::setGlobalStatusTest(
01098     const RCP< StatusTest<ScalarType,MV,OP> > &global) 
01099 {
01100   globalTest_ = global;
01101 }
01102 
01103 template <class ScalarType, class MV, class OP>
01104 const RCP< StatusTest<ScalarType,MV,OP> > & 
01105 TraceMinBaseSolMgr<ScalarType,MV,OP>::getGlobalStatusTest() const 
01106 {
01107   return globalTest_;
01108 }
01109 
01110 template <class ScalarType, class MV, class OP>
01111 void 
01112 TraceMinBaseSolMgr<ScalarType,MV,OP>::setDebugStatusTest(
01113     const RCP< StatusTest<ScalarType,MV,OP> > &debug)
01114 {
01115   debugTest_ = debug;
01116 }
01117 
01118 template <class ScalarType, class MV, class OP>
01119 const RCP< StatusTest<ScalarType,MV,OP> > & 
01120 TraceMinBaseSolMgr<ScalarType,MV,OP>::getDebugStatusTest() const
01121 {
01122   return debugTest_;
01123 }
01124 
01125 template <class ScalarType, class MV, class OP>
01126 void 
01127 TraceMinBaseSolMgr<ScalarType,MV,OP>::setLockingStatusTest(
01128     const RCP< StatusTest<ScalarType,MV,OP> > &locking) 
01129 {
01130   lockingTest_ = locking;
01131 }
01132 
01133 template <class ScalarType, class MV, class OP>
01134 const RCP< StatusTest<ScalarType,MV,OP> > & 
01135 TraceMinBaseSolMgr<ScalarType,MV,OP>::getLockingStatusTest() const 
01136 {
01137   return lockingTest_;
01138 }
01139 
01140 template <class ScalarType, class MV, class OP>
01141 void TraceMinBaseSolMgr<ScalarType,MV,OP>::copyPartOfState(const TraceMinBaseState<ScalarType,MV>& oldState, TraceMinBaseState<ScalarType,MV>& newState, const std::vector<int> indToCopy) const
01142 {
01143   const ScalarType ONE = Teuchos::ScalarTraits<MagnitudeType>::one();
01144   const ScalarType ZERO = Teuchos::ScalarTraits<MagnitudeType>::zero();
01145 
01146   newState.curDim = indToCopy.size();
01147   std::vector<int> fullIndices(oldState.curDim);
01148   for(int i=0; i<oldState.curDim; i++) fullIndices[i] = i;
01149 
01150   // Initialize with X.  
01151   // Note that we didn't compute enough vectors of X, but we can very easily using the Ritz vectors.
01152   // That's why they're part of the state.
01153   // Note that there will ALWAYS be enough vectors
01154 
01155   // Helpful vectors for computing views and whatnot
01156   std::vector<int> oldIndices;
01157   std::vector<int> newIndices;
01158   for(int i=0; i<newState.curDim; i++)
01159   {
01160     if(indToCopy[i] < blockSize_)
01161       oldIndices.push_back(indToCopy[i]);
01162     else
01163       newIndices.push_back(indToCopy[i]);
01164   }
01165 
01166   int olddim = oldIndices.size();
01167   int newdim = newIndices.size();
01168 
01169   // If there are no new vectors being copied
01170   if(computeAllRes_)
01171   {
01172     newState.V  = MVT::CloneView(*oldState.X, indToCopy);
01173     newState.R  = MVT::CloneView(*oldState.R, indToCopy);
01174     newState.X = newState.V;
01175 
01176     if(problem_->getOperator() != Teuchos::null)
01177     {
01178       newState.KV = MVT::CloneView(*oldState.KX, indToCopy);
01179       newState.KX = newState.KV;
01180     }
01181     else
01182     {
01183       newState.KV = Teuchos::null;
01184       newState.KX = Teuchos::null;
01185     }
01186 
01187     if(problem_->getM() != Teuchos::null)
01188     {
01189       newState.MopV = MVT::CloneView(*oldState.MX, indToCopy);
01190       newState.MX = newState.MopV;
01191     }
01192     else
01193     {
01194       newState.MopV = Teuchos::null;
01195       newState.MX = Teuchos::null;
01196     }
01197   }
01198   else if(newdim == 0)
01199   {
01200     std::vector<int> blockind(blockSize_);
01201     for(int i=0; i<blockSize_; i++)
01202       blockind[i] = i;
01203 
01204     // Initialize with X
01205     newState.V  = MVT::CloneView(*oldState.X, blockind);
01206     newState.KV = MVT::CloneView(*oldState.KX, blockind);
01207     newState.R  = MVT::CloneView(*oldState.R, blockind);
01208     newState.X = MVT::CloneView(*newState.V, blockind);
01209     newState.KX = MVT::CloneView(*newState.KV, blockind);
01210 
01211     if(problem_->getM() != Teuchos::null)
01212     {
01213       newState.MopV = MVT::CloneView(*oldState.MX, blockind);
01214       newState.MX = MVT::CloneView(*newState.MopV, blockind);
01215     }
01216     else
01217     {
01218       newState.MopV = Teuchos::null;
01219       newState.MX = Teuchos::null;
01220     }
01221   }
01222   else
01223   {
01224     // More helpful vectors
01225     std::vector<int> oldPart(olddim);
01226     for(int i=0; i<olddim; i++) oldPart[i] = i;
01227     std::vector<int> newPart(newdim);
01228     for(int i=0; i<newdim; i++) newPart[i] = olddim+i;
01229 
01230     // Helpful multivectors for views and whatnot
01231     RCP<MV> helper = MVT::Clone(*oldState.V,newState.curDim);
01232     RCP<MV> oldHelper = MVT::CloneViewNonConst(*helper,oldPart);
01233     RCP<MV> newHelper = MVT::CloneViewNonConst(*helper,newPart);
01234     RCP<const MV> viewHelper;
01235 
01236     // Get the parts of the Ritz vectors we are interested in.
01237     Teuchos::SerialDenseMatrix<int,ScalarType> newRV(oldState.curDim,newdim);
01238     for(int r=0; r<oldState.curDim; r++)
01239     {
01240       for(int c=0; c<newdim; c++)
01241         newRV(r,c) = (*oldState.RV)(r,newIndices[c]);
01242     }
01243 
01244     // We're going to compute X as V*RitzVecs
01245     viewHelper = MVT::CloneView(*oldState.V,fullIndices);
01246     MVT::MvTimesMatAddMv(ONE,*viewHelper,newRV,ZERO,*newHelper);
01247     viewHelper = MVT::CloneView(*oldState.X,oldIndices);
01248     MVT::Assign(*viewHelper,*oldHelper);
01249     newState.V = MVT::CloneCopy(*helper);
01250 
01251     // Also compute KX as KV*RitzVecs
01252     viewHelper = MVT::CloneView(*oldState.KV,fullIndices);
01253     MVT::MvTimesMatAddMv(ONE,*viewHelper,newRV,ZERO,*newHelper);
01254     viewHelper = MVT::CloneView(*oldState.KX,oldIndices);
01255     MVT::Assign(*viewHelper,*oldHelper);
01256     newState.KV = MVT::CloneCopy(*helper);
01257 
01258     // Do the same with MX if necessary
01259     if(problem_->getM() != Teuchos::null)
01260     {
01261       viewHelper = MVT::CloneView(*oldState.MopV,fullIndices);
01262       MVT::MvTimesMatAddMv(ONE,*viewHelper,newRV,ZERO,*newHelper);
01263       viewHelper = MVT::CloneView(*oldState.MX,oldIndices);
01264       MVT::Assign(*viewHelper,*oldHelper);
01265       newState.MopV = MVT::CloneCopy(*helper);
01266     }
01267     else
01268       newState.MopV = newState.V;
01269 
01270     // Get X, MX, KX
01271     std::vector<int> blockVec(blockSize_);
01272     for(int i=0; i<blockSize_; i++) blockVec[i] = i;
01273     newState.X = MVT::CloneView(*newState.V,blockVec);
01274     newState.KX = MVT::CloneView(*newState.KV,blockVec);
01275     newState.MX = MVT::CloneView(*newState.MopV,blockVec);
01276 
01277     // Update the residuals
01278     if(blockSize_-oldIndices.size() > 0)
01279     {
01280       // There are vectors we have not computed the residual for yet
01281       newPart.resize(blockSize_-oldIndices.size());
01282       helper = MVT::Clone(*oldState.V,blockSize_);
01283       oldHelper = MVT::CloneViewNonConst(*helper,oldPart);
01284       newHelper = MVT::CloneViewNonConst(*helper,newPart);
01285 
01286       RCP<MV> scaledMV = MVT::CloneCopy(*newState.MX,newPart);
01287       RCP<const MV> localKV = MVT::CloneView(*newState.KX,newPart);
01288       std::vector<ScalarType> scalarVec(blockSize_-oldIndices.size());
01289       for(unsigned int i=0; i<(unsigned int)blockSize_-oldIndices.size(); i++) scalarVec[i] = (*oldState.T)[newPart[i]];
01290       MVT::MvScale(*scaledMV,scalarVec);
01291             
01292       helper = MVT::Clone(*oldState.V,blockSize_);
01293       oldHelper = MVT::CloneViewNonConst(*helper,oldPart);
01294       newHelper = MVT::CloneViewNonConst(*helper,newPart);
01295       MVT::MvAddMv(ONE,*localKV,-ONE,*scaledMV,*newHelper);
01296       viewHelper = MVT::CloneView(*oldState.R,oldIndices);
01297       MVT::Assign(*viewHelper,*oldHelper);
01298       newState.R = MVT::CloneCopy(*helper);
01299     }
01300     else
01301       newState.R = oldState.R;
01302   }
01303 
01304   // Since we are setting V:=X, V is orthonormal
01305   newState.isOrtho = true;
01306 
01307   // Get the first eigenvalues
01308   RCP< std::vector<ScalarType> > helperT = rcp( new std::vector<ScalarType>(newState.curDim) );
01309   for(int i=0; i<newState.curDim; i++) (*helperT)[i] = (*oldState.T)[indToCopy[i]];
01310   newState.T  = helperT;
01311 
01312   // X'KX is diag(T)
01313   RCP< Teuchos::SerialDenseMatrix<int,ScalarType> > newKK = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(newState.curDim,newState.curDim) );
01314   for(int i=0; i<newState.curDim; i++)
01315     (*newKK)(i,i) = (*newState.T)[i];
01316   newState.KK = newKK;
01317 
01318   // The associated Ritz vectors are I
01319   RCP< Teuchos::SerialDenseMatrix<int,ScalarType> > newRV = rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(newState.curDim,newState.curDim) );
01320   for(int i=0; i<newState.curDim; i++)
01321     (*newRV)(i,i) = ONE;
01322   newState.RV = newRV;
01323 
01324   // Get the Ritz shifts
01325   RCP< std::vector<ScalarType> > helperRS = rcp( new std::vector<ScalarType>(blockSize_) );
01326   for(int i=0; i<blockSize_; i++) 
01327   {
01328     if(indToCopy[i] < blockSize_)
01329       (*helperRS)[i] = (*oldState.ritzShifts)[indToCopy[i]];
01330     else
01331       (*helperRS)[i] = ZERO;
01332   }
01333   newState.ritzShifts  = helperRS;
01334 }
01335 
01336 
01337 template <class ScalarType, class MV, class OP>
01338 void TraceMinBaseSolMgr<ScalarType,MV,OP>::setParameters(Teuchos::ParameterList &pl) const
01339 {
01340   pl.set("Block Size", blockSize_);
01341   pl.set("Num Blocks", numBlocks_);
01342   pl.set("Num Restart Blocks", numRestartBlocks_);
01343   pl.set("When To Shift", whenToShift_);
01344   pl.set("Trace Threshold", traceThresh_);
01345   pl.set("Shift Tolerance", shiftTol_);
01346   pl.set("Relative Shift Tolerance", relShiftTol_);
01347   pl.set("Shift Norm", shiftNorm_);
01348   pl.set("How To Choose Shift", howToShift_);
01349   pl.set("Consider Clusters", considerClusters_);
01350   pl.set("Use Multiple Shifts", useMultipleShifts_);
01351   pl.set("Saddle Solver Type", saddleSolType_);
01352   pl.set("Project All Vectors", projectAllVecs_);
01353   pl.set("Project Locked Vectors", projectLockedVecs_);
01354   pl.set("Compute All Residuals", computeAllRes_);
01355   pl.set("Use Residual as RHS", useRHSR_);
01356   pl.set("Maximum Krylov Iterations", maxKrylovIter_);
01357 }
01358 
01359 
01360 template <class ScalarType, class MV, class OP>
01361 void TraceMinBaseSolMgr<ScalarType,MV,OP>::printParameters(std::ostream &os) const
01362 {
01363   os << "\n\n\n";
01364   os << "========================================\n";
01365   os << "========= TraceMin parameters ==========\n";
01366   os << "========================================\n";
01367   os << "=========== Block parameters ===========\n";
01368   os << "Block Size: " << blockSize_ << std::endl;
01369   os << "Num Blocks: " << numBlocks_ << std::endl;
01370   os << "Num Restart Blocks: " << numRestartBlocks_ << std::endl;
01371   os << "======== Convergence parameters ========\n";
01372   os << "Convergence Tolerance: " << convTol_ << std::endl;
01373   os << "Relative Convergence Tolerance: " << relConvTol_ << std::endl;
01374   os << "========== Locking parameters ==========\n";
01375   os << "Use Locking: " << useLocking_ << std::endl;
01376   os << "Locking Tolerance: " << lockTol_ << std::endl;
01377   os << "Relative Locking Tolerance: " << relLockTol_ << std::endl;
01378   os << "Max Locked: " << maxLocked_ << std::endl;
01379   os << "Locking Quorum: " << lockQuorum_ << std::endl;
01380   os << "========== Shifting parameters =========\n";
01381   os << "When To Shift: ";
01382   if(whenToShift_ == NEVER_SHIFT) os << "Never\n";
01383   else if(whenToShift_ == SHIFT_WHEN_TRACE_LEVELS) os << "After Trace Levels\n";
01384   else if(whenToShift_ == SHIFT_WHEN_RESID_SMALL) os << "Residual Becomes Small\n";
01385   else if(whenToShift_ == ALWAYS_SHIFT) os << "Always\n";
01386   os << "Consider Clusters: " << considerClusters_ << std::endl;
01387   os << "Trace Threshohld: " << traceThresh_ << std::endl;
01388   os << "Shift Tolerance: " << shiftTol_ << std::endl;
01389   os << "Relative Shift Tolerance: " << relShiftTol_ << std::endl;
01390   os << "How To Choose Shift: ";
01391   if(howToShift_ == LARGEST_CONVERGED_SHIFT) os << "Largest Converged\n";
01392   else if(howToShift_ == ADJUSTED_RITZ_SHIFT) os << "Adjusted Ritz Values\n";
01393   else if(howToShift_ == RITZ_VALUES_SHIFT) os << "Ritz Values\n";
01394   os << "Use Multiple Shifts: " << useMultipleShifts_ << std::endl;
01395   os << "=========== Other parameters ===========\n";
01396   os << "Orthogonalization: " << ortho_ << std::endl;
01397   os << "Saddle Solver Type: ";
01398   if(saddleSolType_ == PROJECTED_KRYLOV_SOLVER) os << "Projected Krylov\n";
01399   else if(saddleSolType_ == SCHUR_COMPLEMENT_SOLVER) os << "Schur Complement\n";
01400   os << "Project All Vectors: " << projectAllVecs_ << std::endl;
01401   os << "Project Locked Vectors: " << projectLockedVecs_ << std::endl;
01402   os << "Compute All Residuals: " << computeAllRes_ << std::endl;
01403   os << "========================================\n\n\n";
01404 }
01405 
01406 
01407 }} // end Anasazi namespace
01408 
01409 #endif /* ANASAZI_TraceMinBase_SOLMGR_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends