Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AnasaziBlockDavidsonSolMgr.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Anasazi: Block Eigensolvers Package
4 //
5 // Copyright 2004 NTESS and the Anasazi contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef ANASAZI_BLOCKDAVIDSON_SOLMGR_HPP
11 #define ANASAZI_BLOCKDAVIDSON_SOLMGR_HPP
12 
17 #include "AnasaziConfigDefs.hpp"
18 #include "AnasaziTypes.hpp"
19 
20 #include "AnasaziEigenproblem.hpp"
21 #include "AnasaziSolverManager.hpp"
22 #include "AnasaziSolverUtils.hpp"
23 
24 #include "AnasaziBlockDavidson.hpp"
25 #include "AnasaziBasicSort.hpp"
32 #include "AnasaziOutputManager.hpp"
34 #include "Teuchos_BLAS.hpp"
35 #include "Teuchos_LAPACK.hpp"
36 #include "Teuchos_TimeMonitor.hpp"
37 #include "Teuchos_FancyOStream.hpp"
38 
39 
53 namespace Anasazi {
54 
55 
88 template<class ScalarType, class MV, class OP>
89 class BlockDavidsonSolMgr : public SolverManager<ScalarType,MV,OP> {
90 
91  private:
95  typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
97 
98  public:
99 
101 
102 
130 
132  virtual ~BlockDavidsonSolMgr() {};
134 
136 
137 
140  return *problem_;
141  }
142 
144  int getNumIters() const {
145  return numIters_;
146  }
147 
156  return Teuchos::tuple(_timerSolve, _timerRestarting, _timerLocking);
157  }
158 
160 
162 
163 
185  ReturnType solve();
186 
189 
192 
195 
198 
201 
204 
206 
207  private:
209 
210  std::string whch_, ortho_;
211 
212  MagnitudeType convtol_, locktol_;
213  int maxRestarts_;
214  bool useLocking_;
215  bool relconvtol_, rellocktol_;
216  int blockSize_, numBlocks_, numIters_;
217  int maxLocked_;
218  int lockQuorum_;
219  bool inSituRestart_;
220  int numRestartBlocks_;
221  enum ResType convNorm_, lockNorm_;
222 
223  Teuchos::RCP<Teuchos::Time> _timerSolve, _timerRestarting, _timerLocking;
224 
228 
230 };
231 
232 
233 // Constructor
234 template<class ScalarType, class MV, class OP>
237  Teuchos::ParameterList &pl ) :
238  problem_(problem),
239  whch_("SR"),
240  ortho_("SVQB"),
241  convtol_(MT::prec()),
242  maxRestarts_(20),
243  useLocking_(false),
244  relconvtol_(true),
245  rellocktol_(true),
246  blockSize_(0),
247  numBlocks_(0),
248  numIters_(0),
249  maxLocked_(0),
250  lockQuorum_(1),
251  inSituRestart_(false),
252  numRestartBlocks_(1)
253 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
254  , _timerSolve(Teuchos::TimeMonitor::getNewTimer("Anasazi: BlockDavidsonSolMgr::solve()")),
255  _timerRestarting(Teuchos::TimeMonitor::getNewTimer("Anasazi: BlockDavidsonSolMgr restarting")),
256  _timerLocking(Teuchos::TimeMonitor::getNewTimer("Anasazi: BlockDavidsonSolMgr locking"))
257 #endif
258 {
259  TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
260  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set.");
261  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric.");
262  TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from.");
263 
264  std::string strtmp;
265 
266  // which values to solve for
267  whch_ = pl.get("Which",whch_);
268  TEUCHOS_TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR",std::invalid_argument, "Invalid sorting string.");
269 
270  // which orthogonalization to use
271  ortho_ = pl.get("Orthogonalization",ortho_);
272  if (ortho_ != "DGKS" && ortho_ != "SVQB") {
273  ortho_ = "SVQB";
274  }
275 
276  // convergence tolerance
277  convtol_ = pl.get("Convergence Tolerance",convtol_);
278  relconvtol_ = pl.get("Relative Convergence Tolerance",relconvtol_);
279  strtmp = pl.get("Convergence Norm",std::string("2"));
280  if (strtmp == "2") {
281  convNorm_ = RES_2NORM;
282  }
283  else if (strtmp == "M") {
284  convNorm_ = RES_ORTH;
285  }
286  else {
287  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
288  "Anasazi::BlockDavidsonSolMgr: Invalid Convergence Norm.");
289  }
290 
291  // locking tolerance
292  useLocking_ = pl.get("Use Locking",useLocking_);
293  rellocktol_ = pl.get("Relative Locking Tolerance",rellocktol_);
294  // default: should be less than convtol_
295  locktol_ = convtol_/10;
296  locktol_ = pl.get("Locking Tolerance",locktol_);
297  strtmp = pl.get("Locking Norm",std::string("2"));
298  if (strtmp == "2") {
299  lockNorm_ = RES_2NORM;
300  }
301  else if (strtmp == "M") {
302  lockNorm_ = RES_ORTH;
303  }
304  else {
305  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
306  "Anasazi::BlockDavidsonSolMgr: Invalid Locking Norm.");
307  }
308 
309  // maximum number of restarts
310  maxRestarts_ = pl.get("Maximum Restarts",maxRestarts_);
311 
312  // block size: default is nev()
313  blockSize_ = pl.get("Block Size",problem_->getNEV());
314  TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
315  "Anasazi::BlockDavidsonSolMgr: \"Block Size\" must be strictly positive.");
316  numBlocks_ = pl.get("Num Blocks",2);
317  TEUCHOS_TEST_FOR_EXCEPTION(numBlocks_ <= 1, std::invalid_argument,
318  "Anasazi::BlockDavidsonSolMgr: \"Num Blocks\" must be >= 1.");
319 
320  // max locked: default is nev(), must satisfy maxLocked_ + blockSize_ >= nev
321  if (useLocking_) {
322  maxLocked_ = pl.get("Max Locked",problem_->getNEV());
323  }
324  else {
325  maxLocked_ = 0;
326  }
327  if (maxLocked_ == 0) {
328  useLocking_ = false;
329  }
330  TEUCHOS_TEST_FOR_EXCEPTION(maxLocked_ < 0, std::invalid_argument,
331  "Anasazi::BlockDavidsonSolMgr: \"Max Locked\" must be positive.");
332  TEUCHOS_TEST_FOR_EXCEPTION(maxLocked_ + blockSize_ < problem_->getNEV(),
333  std::invalid_argument,
334  "Anasazi::BlockDavidsonSolMgr: Not enough storage space for requested number of eigenpairs.");
335  TEUCHOS_TEST_FOR_EXCEPTION(static_cast<ptrdiff_t>(numBlocks_)*blockSize_ + maxLocked_ > MVT::GetGlobalLength(*problem_->getInitVec()),
336  std::invalid_argument,
337  "Anasazi::BlockDavidsonSolMgr: Potentially impossible orthogonality requests. Reduce basis size or locking size.");
338 
339  if (useLocking_) {
340  lockQuorum_ = pl.get("Locking Quorum",lockQuorum_);
341  TEUCHOS_TEST_FOR_EXCEPTION(lockQuorum_ <= 0,
342  std::invalid_argument,
343  "Anasazi::BlockDavidsonSolMgr: \"Locking Quorum\" must be strictly positive.");
344  }
345 
346  // restart size
347  numRestartBlocks_ = pl.get("Num Restart Blocks",numRestartBlocks_);
348  TEUCHOS_TEST_FOR_EXCEPTION(numRestartBlocks_ <= 0, std::invalid_argument,
349  "Anasazi::BlockDavidsonSolMgr: \"Num Restart Blocks\" must be strictly positive.");
350  TEUCHOS_TEST_FOR_EXCEPTION(numRestartBlocks_ >= numBlocks_, std::invalid_argument,
351  "Anasazi::BlockDavidsonSolMgr: \"Num Restart Blocks\" must be strictly less than \"Num Blocks\".");
352 
353  // restarting technique: V*Q or applyHouse(V,H,tau)
354  if (pl.isParameter("In Situ Restarting")) {
355  if (Teuchos::isParameterType<bool>(pl,"In Situ Restarting")) {
356  inSituRestart_ = pl.get("In Situ Restarting",inSituRestart_);
357  } else {
358  inSituRestart_ = ( Teuchos::getParameter<int>(pl,"In Situ Restarting") != 0 );
359  }
360  }
361 
362  // Output manager
363  // Create a formatted output stream to print to.
364  // See if user requests output processor.
365  int osProc = pl.get("Output Processor", 0);
366 
367  // If not passed in by user, it will be chosen based upon operator type.
369 
370  // output stream
371  if (pl.isParameter("Output Stream")) {
372  osp = Teuchos::getParameter<Teuchos::RCP<Teuchos::FancyOStream> >(pl,"Output Stream");
373  }
374  else {
375  osp = OutputStreamTraits<OP>::getOutputStream (*problem_->getOperator(), osProc);
376  }
377 
378  // verbosity
379  int verbosity = Anasazi::Errors;
380  if (pl.isParameter("Verbosity")) {
381  if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
382  verbosity = pl.get("Verbosity", verbosity);
383  } else {
384  verbosity = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
385  }
386  }
387  printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity,osp) );
388 
389 }
390 
391 
392 // solve()
393 template<class ScalarType, class MV, class OP>
394 ReturnType
396 
397  typedef SolverUtils<ScalarType,MV,OP> msutils;
398 
399  const int nev = problem_->getNEV();
400 
401 #ifdef TEUCHOS_DEBUG
403  out = Teuchos::getFancyOStream(Teuchos::rcpFromRef(printer_->stream(Debug)));
404  out->setShowAllFrontMatter(false).setShowProcRank(true);
405  *out << "Entering Anasazi::BlockDavidsonSolMgr::solve()\n";
406 #endif
407 
409  // Sort manager
411 
413  // Status tests
414  //
415  // convergence
417  if (globalTest_ == Teuchos::null) {
418  convtest = Teuchos::rcp( new StatusTestResNorm<ScalarType,MV,OP>(convtol_,nev,convNorm_,relconvtol_) );
419  }
420  else {
421  convtest = globalTest_;
422  }
424  = Teuchos::rcp( new StatusTestWithOrdering<ScalarType,MV,OP>(convtest,sorter,nev) );
425  // locking
427  if (useLocking_) {
428  if (lockingTest_ == Teuchos::null) {
429  locktest = Teuchos::rcp( new StatusTestResNorm<ScalarType,MV,OP>(locktol_,lockQuorum_,lockNorm_,rellocktol_) );
430  }
431  else {
432  locktest = lockingTest_;
433  }
434  }
435  // for a non-short-circuited OR test, the order doesn't matter
437  alltests.push_back(ordertest);
438  if (locktest != Teuchos::null) alltests.push_back(locktest);
439  if (debugTest_ != Teuchos::null) alltests.push_back(debugTest_);
440 
443  // printing StatusTest
445  if ( printer_->isVerbosity(Debug) ) {
446  outputtest = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer_,combotest,1,Passed+Failed+Undefined ) );
447  }
448  else {
449  outputtest = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer_,combotest,1,Passed ) );
450  }
451 
453  // Orthomanager
455  if (ortho_=="SVQB") {
456  ortho = Teuchos::rcp( new SVQBOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
457  } else if (ortho_=="DGKS") {
458  ortho = Teuchos::rcp( new BasicOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
459  } else {
460  TEUCHOS_TEST_FOR_EXCEPTION(ortho_!="SVQB"&&ortho_!="DGKS",std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): Invalid orthogonalization type.");
461  }
462 
464  // Parameter list
466  plist.set("Block Size",blockSize_);
467  plist.set("Num Blocks",numBlocks_);
468 
470  // BlockDavidson solver
472  = Teuchos::rcp( new BlockDavidson<ScalarType,MV,OP>(problem_,sorter,printer_,outputtest,ortho,plist) );
473  // set any auxiliary vectors defined in the problem
474  Teuchos::RCP< const MV > probauxvecs = problem_->getAuxVecs();
475  if (probauxvecs != Teuchos::null) {
476  bd_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(probauxvecs) );
477  }
478 
480  // Storage
481  //
482  // lockvecs will contain eigenvectors that have been determined "locked" by the status test
483  int curNumLocked = 0;
484  Teuchos::RCP<MV> lockvecs;
485  // lockvecs is used to hold the locked eigenvectors, as well as for temporary storage when locking.
486  // when locking, we will lock some number of vectors numnew, where numnew <= maxlocked - curlocked
487  // we will produce numnew random vectors, which will go into the space with the new basis.
488  // we will also need numnew storage for the image of these random vectors under A and M;
489  // columns [curlocked+1,curlocked+numnew] will be used for this storage
490  if (maxLocked_ > 0) {
491  lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
492  }
493  std::vector<MagnitudeType> lockvals;
494  //
495  // Restarting occurs under two scenarios: when the basis is full and after locking.
496  //
497  // For the former, a new basis of size blockSize*numRestartBlocks is generated using the current basis
498  // and the most significant primitive Ritz vectors (projected eigenvectors).
499  // [S,L] = eig(KK)
500  // S = [Sr St] // some for "r"estarting, some are "t"runcated
501  // newV = V*Sr
502  // KK_new = newV'*K*newV = Sr'*V'*K*V*Sr = Sr'*KK*Sr
503  // Therefore, the only multivector operation needed is for the generation of newV.
504  //
505  // * If the multiplication is explicit, it requires a workspace of blockSize*numRestartBlocks vectors.
506  // This space must be specifically allocated for that task, as we don't have any space of that size.
507  // It (workMV) will be allocated at the beginning of solve()
508  // * Optionally, the multiplication can be performed implicitly, via a Householder QR factorization of
509  // Sr. This can be done in situ, using the basis multivector contained in the solver. This requires
510  // that we cast away the const on the multivector returned from getState(). Workspace for this approach
511  // is a single vector. the solver's internal storage must be preserved (X,MX,KX,R), requiring us to
512  // allocate this vector.
513  //
514  // For the latter (restarting after locking), the new basis is the same size as existing basis. If numnew
515  // vectors are locked, they are deflated from the current basis and replaced with randomly generated
516  // vectors.
517  // [S,L] = eig(KK)
518  // S = [Sl Su] // partitioned: "l"ocked and "u"nlocked
519  // newL = V*Sl = X(locked)
520  // defV = V*Su
521  // augV = rand(numnew) // orthogonal to oldL,newL,defV,auxvecs
522  // newV = [defV augV]
523  // Kknew = newV'*K*newV = [Su'*KK*Su defV'*K*augV]
524  // [augV'*K*defV augV'*K*augV]
525  // locked = [oldL newL]
526  // Clearly, this operation is more complicated than the previous.
527  // Here is a list of the significant computations that need to be performed:
528  // - newL will be put into space in lockvecs, but will be copied from getState().X at the end
529  // - defV,augV will be stored in workspace the size of the current basis.
530  // - If inSituRestart==true, we compute defV in situ in bd_solver::V_ and
531  // put augV at the end of bd_solver::V_
532  // - If inSituRestart==false, we must have curDim vectors available for
533  // defV and augV; we will allocate a multivector (workMV) at the beginning of solve()
534  // for this purpose.
535  // - M*augV and K*augV are needed; they will be stored in lockvecs. As a result, newL will
536  // not be put into lockvecs until the end.
537  //
538  // Therefore, we must allocate workMV when ((maxRestarts_ > 0) || (useLocking_ == true)) && inSituRestart == false
539  // It will be allocated to size (numBlocks-1)*blockSize
540  //
541  Teuchos::RCP<MV> workMV;
542  if (inSituRestart_ == false) {
543  // we need storage space to restart, either if we may lock or if may restart after a full basis
544  if (useLocking_==true || maxRestarts_ > 0) {
545  workMV = MVT::Clone(*problem_->getInitVec(),(numBlocks_-1)*blockSize_);
546  }
547  else {
548  // we will never need to restart.
549  workMV = Teuchos::null;
550  }
551  }
552  else { // inSituRestart_ == true
553  // we will restart in situ, if we need to restart
554  // three situation remain:
555  // - never restart => no space needed
556  // - only restart for locking (i.e., never restart full) => no space needed
557  // - restart for full basis => need one vector
558  if (maxRestarts_ > 0) {
559  workMV = MVT::Clone(*problem_->getInitVec(),1);
560  }
561  else {
562  workMV = Teuchos::null;
563  }
564  }
565 
566  // some consts and utils
567  const ScalarType ONE = SCT::one();
568  const ScalarType ZERO = SCT::zero();
571 
572  // go ahead and initialize the solution to nothing in case we throw an exception
574  sol.numVecs = 0;
575  problem_->setSolution(sol);
576 
577  int numRestarts = 0;
578 
579  // enter solve() iterations
580  {
581 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
582  Teuchos::TimeMonitor slvtimer(*_timerSolve);
583 #endif
584 
585  // tell bd_solver to iterate
586  while (1) {
587  try {
588  bd_solver->iterate();
589 
591  //
592  // check user-specified debug test; if it passed, return an exception
593  //
595  if (debugTest_ != Teuchos::null && debugTest_->getStatus() == Passed) {
596  throw AnasaziError("Anasazi::BlockDavidsonSolMgr::solve(): User-specified debug status test returned Passed.");
597  }
599  //
600  // check convergence next
601  //
603  else if (ordertest->getStatus() == Passed ) {
604  // we have convergence
605  // ordertest->whichVecs() tells us which vectors from lockvecs and solver state are the ones we want
606  // ordertest->howMany() will tell us how many
607  break;
608  }
610  //
611  // check for restarting before locking: if we need to lock, it will happen after the restart
612  //
614  else if ( bd_solver->getCurSubspaceDim() == bd_solver->getMaxSubspaceDim() ) {
615 
616 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
617  Teuchos::TimeMonitor restimer(*_timerRestarting);
618 #endif
619 
620  if ( numRestarts >= maxRestarts_ ) {
621  break; // break from while(1){bd_solver->iterate()}
622  }
623  numRestarts++;
624 
625  printer_->stream(IterationDetails) << " Performing restart number " << numRestarts << " of " << maxRestarts_ << std::endl << std::endl;
626 
627  BlockDavidsonState<ScalarType,MV> state = bd_solver->getState();
628  int curdim = state.curDim;
629  int newdim = numRestartBlocks_*blockSize_;
630 
631 # ifdef TEUCHOS_DEBUG
632  {
633  std::vector<Value<ScalarType> > ritzvalues = bd_solver->getRitzValues();
634  *out << "Ritz values from solver:\n";
635  for (unsigned int i=0; i<ritzvalues.size(); i++) {
636  *out << ritzvalues[i].realpart << " ";
637  }
638  *out << "\n";
639  }
640 # endif
641 
642  //
643  // compute eigenvectors of the projected problem
645  std::vector<MagnitudeType> theta(curdim);
646  int rank = curdim;
647 # ifdef TEUCHOS_DEBUG
648  {
649  std::stringstream os;
650  os << "KK before HEEV...\n"
651  << printMat(*state.KK) << "\n";
652  *out << os.str();
653  }
654 # endif
655  int info = msutils::directSolver(curdim,*state.KK,Teuchos::null,S,theta,rank,10);
656  TEUCHOS_TEST_FOR_EXCEPTION(info != 0 ,std::logic_error,
657  "Anasazi::BlockDavidsonSolMgr::solve(): error calling SolverUtils::directSolver."); // this should never happen
658  TEUCHOS_TEST_FOR_EXCEPTION(rank != curdim,std::logic_error,
659  "Anasazi::BlockDavidsonSolMgr::solve(): direct solve did not compute all eigenvectors."); // this should never happen
660 
661 # ifdef TEUCHOS_DEBUG
662  {
663  std::stringstream os;
664  *out << "Ritz values from heev(KK):\n";
665  for (unsigned int i=0; i<theta.size(); i++) *out << theta[i] << " ";
666  os << "\nRitz vectors from heev(KK):\n"
667  << printMat(S) << "\n";
668  *out << os.str();
669  }
670 # endif
671 
672  //
673  // sort the eigenvalues (so that we can order the eigenvectors)
674  {
675  std::vector<int> order(curdim);
676  sorter->sort(theta,Teuchos::rcpFromRef(order),curdim);
677  //
678  // apply the same ordering to the primitive ritz vectors
679  msutils::permuteVectors(order,S);
680  }
681 # ifdef TEUCHOS_DEBUG
682  {
683  std::stringstream os;
684  *out << "Ritz values from heev(KK) after sorting:\n";
685  std::copy(theta.begin(), theta.end(), std::ostream_iterator<ScalarType>(*out, " "));
686  os << "\nRitz vectors from heev(KK) after sorting:\n"
687  << printMat(S) << "\n";
688  *out << os.str();
689  }
690 # endif
691  //
692  // select the significant primitive ritz vectors
694 # ifdef TEUCHOS_DEBUG
695  {
696  std::stringstream os;
697  os << "Significant primitive Ritz vectors:\n"
698  << printMat(Sr) << "\n";
699  *out << os.str();
700  }
701 # endif
702  //
703  // generate newKK = Sr'*KKold*Sr
704  Teuchos::SerialDenseMatrix<int,ScalarType> newKK(newdim,newdim);
705  {
706  Teuchos::SerialDenseMatrix<int,ScalarType> KKtmp(curdim,newdim),
707  KKold(Teuchos::View,*state.KK,curdim,curdim);
708  int teuchosRet;
709  // KKtmp = KKold*Sr
710  teuchosRet = KKtmp.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,KKold,Sr,ZERO);
711  TEUCHOS_TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error,
712  "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply.");
713  // newKK = Sr'*KKtmp = Sr'*KKold*Sr
714  teuchosRet = newKK.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,Sr,KKtmp,ZERO);
715  TEUCHOS_TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error,
716  "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply.");
717  // make it Hermitian in memory
718  for (int j=0; j<newdim-1; ++j) {
719  for (int i=j+1; i<newdim; ++i) {
720  newKK(i,j) = SCT::conjugate(newKK(j,i));
721  }
722  }
723  }
724 # ifdef TEUCHOS_DEBUG
725  {
726  std::stringstream os;
727  os << "Sr'*KK*Sr:\n"
728  << printMat(newKK) << "\n";
729  *out << os.str();
730  }
731 # endif
732 
733  // prepare new state
735  rstate.curDim = newdim;
736  rstate.KK = Teuchos::rcpFromRef(newKK);
737  //
738  // we know that newX = newV*Sr(:,1:bS) = oldV*S(:1:bS) = oldX
739  // the restarting preserves the Ritz vectors and residual
740  // for the Ritz values, we want all of the values associated with newV.
741  // these have already been placed at the beginning of theta
742  rstate.X = state.X;
743  rstate.KX = state.KX;
744  rstate.MX = state.MX;
745  rstate.R = state.R;
746  rstate.T = Teuchos::rcp( new std::vector<MagnitudeType>(theta.begin(),theta.begin()+newdim) );
747 
748  if (inSituRestart_ == true) {
749 # ifdef TEUCHOS_DEBUG
750  *out << "Beginning in-situ restart...\n";
751 # endif
752  //
753  // get non-const pointer to solver's basis so we can work in situ
754  Teuchos::RCP<MV> solverbasis = Teuchos::rcp_const_cast<MV>(state.V);
755  //
756  // perform Householder QR of Sr = Q [D;0], where D is unit diag.
757  // WARNING: this will overwrite Sr; however, we do not need Sr anymore after this
758  std::vector<ScalarType> tau(newdim), work(newdim);
759  int geqrf_info;
760  lapack.GEQRF(curdim,newdim,Sr.values(),Sr.stride(),&tau[0],&work[0],work.size(),&geqrf_info);
761  TEUCHOS_TEST_FOR_EXCEPTION(geqrf_info != 0,std::logic_error,
762  "Anasazi::BlockDavidsonSolMgr::solve(): error calling GEQRF during restarting.");
763  if (printer_->isVerbosity(Debug)) {
765  for (int j=0; j<newdim; j++) {
766  R(j,j) = SCT::magnitude(R(j,j)) - 1.0;
767  for (int i=j+1; i<newdim; i++) {
768  R(i,j) = ZERO;
769  }
770  }
771  printer_->stream(Debug) << "||Triangular factor of Sr - I||: " << R.normFrobenius() << std::endl;
772  }
773  //
774  // perform implicit oldV*Sr
775  // this actually performs oldV*[Sr Su*M] = [newV truncV], for some unitary M
776  // we are actually interested in only the first newdim vectors of the result
777  {
778  std::vector<int> curind(curdim);
779  for (int i=0; i<curdim; i++) curind[i] = i;
780  Teuchos::RCP<MV> oldV = MVT::CloneViewNonConst(*solverbasis,curind);
781  msutils::applyHouse(newdim,*oldV,Sr,tau,workMV);
782  }
783  //
784  // put the new basis into the state for initialize()
785  // the new basis is contained in the the first newdim columns of solverbasis
786  // initialize() will recognize that pointer bd_solver.V_ == pointer rstate.V, and will neglect the copy.
787  rstate.V = solverbasis;
788  }
789  else { // inSituRestart == false)
790 # ifdef TEUCHOS_DEBUG
791  *out << "Beginning ex-situ restart...\n";
792 # endif
793  // newV = oldV*Sr, explicitly. workspace is in workMV
794  std::vector<int> curind(curdim), newind(newdim);
795  for (int i=0; i<curdim; i++) curind[i] = i;
796  for (int i=0; i<newdim; i++) newind[i] = i;
797  Teuchos::RCP<const MV> oldV = MVT::CloneView(*state.V,curind);
798  Teuchos::RCP<MV> newV = MVT::CloneViewNonConst(*workMV ,newind);
799 
800  MVT::MvTimesMatAddMv(ONE,*oldV,Sr,ZERO,*newV);
801  //
802  // put the new basis into the state for initialize()
803  rstate.V = newV;
804  }
805 
806  //
807  // send the new state to the solver
808  bd_solver->initialize(rstate);
809  } // end of restarting
811  //
812  // check locking if we didn't converge or restart
813  //
815  else if (locktest != Teuchos::null && locktest->getStatus() == Passed) {
816 
817 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
818  Teuchos::TimeMonitor lcktimer(*_timerLocking);
819 #endif
820 
821  //
822  // get current state
823  BlockDavidsonState<ScalarType,MV> state = bd_solver->getState();
824  const int curdim = state.curDim;
825 
826  //
827  // get number,indices of vectors to be locked
828  TEUCHOS_TEST_FOR_EXCEPTION(locktest->howMany() <= 0,std::logic_error,
829  "Anasazi::BlockDavidsonSolMgr::solve(): status test mistake: howMany() non-positive.");
830  TEUCHOS_TEST_FOR_EXCEPTION(locktest->howMany() != (int)locktest->whichVecs().size(),std::logic_error,
831  "Anasazi::BlockDavidsonSolMgr::solve(): status test mistake: howMany() not consistent with whichVecs().");
832  // we should have room to lock vectors; otherwise, locking should have been deactivated
833  TEUCHOS_TEST_FOR_EXCEPTION(curNumLocked == maxLocked_,std::logic_error,
834  "Anasazi::BlockDavidsonSolMgr::solve(): status test mistake: locking not deactivated.");
835  //
836  // don't lock more than maxLocked_; we didn't allocate enough space.
837  std::vector<int> tmp_vector_int;
838  if (curNumLocked + locktest->howMany() > maxLocked_) {
839  // just use the first of them
840  tmp_vector_int.insert(tmp_vector_int.begin(),locktest->whichVecs().begin(),locktest->whichVecs().begin()+maxLocked_-curNumLocked);
841  }
842  else {
843  tmp_vector_int = locktest->whichVecs();
844  }
845  const std::vector<int> lockind(tmp_vector_int);
846  const int numNewLocked = lockind.size();
847  //
848  // generate indices of vectors left unlocked
849  // curind = [0,...,curdim-1] = UNION( lockind, unlockind )
850  const int numUnlocked = curdim-numNewLocked;
851  tmp_vector_int.resize(curdim);
852  for (int i=0; i<curdim; i++) tmp_vector_int[i] = i;
853  const std::vector<int> curind(tmp_vector_int); // curind = [0 ... curdim-1]
854  tmp_vector_int.resize(numUnlocked);
855  std::set_difference(curind.begin(),curind.end(),lockind.begin(),lockind.end(),tmp_vector_int.begin());
856  const std::vector<int> unlockind(tmp_vector_int); // unlockind = [0 ... curdim-1] - lockind
857  tmp_vector_int.clear();
858 
859  //
860  // debug printing
861  if (printer_->isVerbosity(Debug)) {
862  printer_->print(Debug,"Locking vectors: ");
863  for (unsigned int i=0; i<lockind.size(); i++) {printer_->stream(Debug) << " " << lockind[i];}
864  printer_->print(Debug,"\n");
865  printer_->print(Debug,"Not locking vectors: ");
866  for (unsigned int i=0; i<unlockind.size(); i++) {printer_->stream(Debug) << " " << unlockind[i];}
867  printer_->print(Debug,"\n");
868  }
869 
870  //
871  // we need primitive ritz vectors/values:
872  // [S,L] = eig(oldKK)
873  //
874  // this will be partitioned as follows:
875  // locked: Sl = S(lockind) // we won't actually need Sl
876  // unlocked: Su = S(unlockind)
877  //
879  std::vector<MagnitudeType> theta(curdim);
880  {
881  int rank = curdim;
882  int info = msutils::directSolver(curdim,*state.KK,Teuchos::null,S,theta,rank,10);
883  TEUCHOS_TEST_FOR_EXCEPTION(info != 0 ,std::logic_error,
884  "Anasazi::BlockDavidsonSolMgr::solve(): error calling SolverUtils::directSolver."); // this should never happen
885  TEUCHOS_TEST_FOR_EXCEPTION(rank != curdim,std::logic_error,
886  "Anasazi::BlockDavidsonSolMgr::solve(): direct solve did not compute all eigenvectors."); // this should never happen
887  //
888  // sort the eigenvalues (so that we can order the eigenvectors)
889  std::vector<int> order(curdim);
890  sorter->sort(theta,Teuchos::rcpFromRef(order),curdim);
891  //
892  // apply the same ordering to the primitive ritz vectors
893  msutils::permuteVectors(order,S);
894  }
895  //
896  // select the unlocked ritz vectors
897  // the indexing in unlockind is relative to the ordered primitive ritz vectors
898  // (this is why we ordered theta,S above)
899  Teuchos::SerialDenseMatrix<int,ScalarType> Su(curdim,numUnlocked);
900  for (int i=0; i<numUnlocked; i++) {
901  blas.COPY(curdim, S[unlockind[i]], 1, Su[i], 1);
902  }
903 
904 
905  //
906  // newV has the following form:
907  // newV = [defV augV]
908  // - defV will be of size curdim - numNewLocked, and contain the generated basis: defV = oldV*Su
909  // - augV will be of size numNewLocked, and contain random directions to make up for the lost space
910  //
911  // we will need a pointer to defV below to generate the off-diagonal block of newKK
912  // go ahead and setup pointer to augV
913  //
914  Teuchos::RCP<MV> defV, augV;
915  if (inSituRestart_ == true) {
916  //
917  // get non-const pointer to solver's basis so we can work in situ
918  Teuchos::RCP<MV> solverbasis = Teuchos::rcp_const_cast<MV>(state.V);
919  //
920  // perform Householder QR of Su = Q [D;0], where D is unit diag.
921  // work on a copy of Su, since we need Su below to build newKK
923  std::vector<ScalarType> tau(numUnlocked), work(numUnlocked);
924  int info;
925  lapack.GEQRF(curdim,numUnlocked,copySu.values(),copySu.stride(),&tau[0],&work[0],work.size(),&info);
926  TEUCHOS_TEST_FOR_EXCEPTION(info != 0,std::logic_error,
927  "Anasazi::BlockDavidsonSolMgr::solve(): error calling GEQRF during restarting.");
928  if (printer_->isVerbosity(Debug)) {
929  Teuchos::SerialDenseMatrix<int,ScalarType> R(Teuchos::Copy,copySu,numUnlocked,numUnlocked);
930  for (int j=0; j<numUnlocked; j++) {
931  R(j,j) = SCT::magnitude(R(j,j)) - 1.0;
932  for (int i=j+1; i<numUnlocked; i++) {
933  R(i,j) = ZERO;
934  }
935  }
936  printer_->stream(Debug) << "||Triangular factor of Su - I||: " << R.normFrobenius() << std::endl;
937  }
938  //
939  // perform implicit oldV*Su
940  // this actually performs oldV*[Su Sl*M] = [defV lockV], for some unitary M
941  // we are actually interested in only the first numUnlocked vectors of the result
942  {
943  Teuchos::RCP<MV> oldV = MVT::CloneViewNonConst(*solverbasis,curind);
944  msutils::applyHouse(numUnlocked,*oldV,copySu,tau,workMV);
945  }
946  std::vector<int> defind(numUnlocked), augind(numNewLocked);
947  for (int i=0; i<numUnlocked ; i++) defind[i] = i;
948  for (int i=0; i<numNewLocked; i++) augind[i] = numUnlocked+i;
949  defV = MVT::CloneViewNonConst(*solverbasis,defind);
950  augV = MVT::CloneViewNonConst(*solverbasis,augind);
951  }
952  else { // inSituRestart == false)
953  // defV = oldV*Su, explicitly. workspace is in workMV
954  std::vector<int> defind(numUnlocked), augind(numNewLocked);
955  for (int i=0; i<numUnlocked ; i++) defind[i] = i;
956  for (int i=0; i<numNewLocked; i++) augind[i] = numUnlocked+i;
957  Teuchos::RCP<const MV> oldV = MVT::CloneView(*state.V,curind);
958  defV = MVT::CloneViewNonConst(*workMV,defind);
959  augV = MVT::CloneViewNonConst(*workMV,augind);
960 
961  MVT::MvTimesMatAddMv(ONE,*oldV,Su,ZERO,*defV);
962  }
963 
964  //
965  // lockvecs will be partitioned as follows:
966  // lockvecs = [curlocked augTmp ...]
967  // - augTmp will be used for the storage of M*augV and K*augV
968  // later, the locked vectors (stored in state.X and referenced via const MV view newLocked)
969  // will be moved into lockvecs on top of augTmp when it is no longer needed as workspace.
970  // - curlocked will be used in orthogonalization of augV
971  //
972  // newL is the new locked vectors; newL = oldV*Sl = RitzVectors(lockind)
973  // we will not produce them, but instead retrieve them from RitzVectors
974  //
975  Teuchos::RCP<const MV> curlocked, newLocked;
976  Teuchos::RCP<MV> augTmp;
977  {
978  // setup curlocked
979  if (curNumLocked > 0) {
980  std::vector<int> curlockind(curNumLocked);
981  for (int i=0; i<curNumLocked; i++) curlockind[i] = i;
982  curlocked = MVT::CloneView(*lockvecs,curlockind);
983  }
984  else {
985  curlocked = Teuchos::null;
986  }
987  // setup augTmp
988  std::vector<int> augtmpind(numNewLocked);
989  for (int i=0; i<numNewLocked; i++) augtmpind[i] = curNumLocked+i;
990  augTmp = MVT::CloneViewNonConst(*lockvecs,augtmpind);
991  // setup newLocked
992  newLocked = MVT::CloneView(*bd_solver->getRitzVectors(),lockind);
993  }
994 
995  //
996  // generate augV and perform orthogonalization
997  //
998  MVT::MvRandom(*augV);
999  //
1000  // orthogonalize it against auxvecs, defV, and all locked vectors (new and current)
1001  // use augTmp as storage for M*augV, if hasM
1002  {
1005  if (probauxvecs != Teuchos::null) against.push_back(probauxvecs);
1006  if (curlocked != Teuchos::null) against.push_back(curlocked);
1007  against.push_back(newLocked);
1008  against.push_back(defV);
1009  if (problem_->getM() != Teuchos::null) {
1010  OPT::Apply(*problem_->getM(),*augV,*augTmp);
1011  }
1012  ortho->projectAndNormalizeMat(*augV,against,dummyC,Teuchos::null,augTmp);
1013  }
1014 
1015  //
1016  // form newKK
1017  //
1018  // newKK = newV'*K*newV = [Su'*KK*Su defV'*K*augV]
1019  // [augV'*K*defV augV'*K*augV]
1020  //
1021  // first, generate the principal submatrix, the projection of K onto the unlocked portion of oldV
1022  //
1023  Teuchos::SerialDenseMatrix<int,ScalarType> newKK(curdim,curdim);
1024  {
1025  Teuchos::SerialDenseMatrix<int,ScalarType> KKtmp(curdim,numUnlocked),
1026  KKold(Teuchos::View,*state.KK,curdim,curdim),
1027  KK11(Teuchos::View,newKK,numUnlocked,numUnlocked);
1028  int teuchosRet;
1029  // KKtmp = KKold*Su
1030  teuchosRet = KKtmp.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,KKold,Su,ZERO);
1031  TEUCHOS_TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error,
1032  "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply.");
1033  // KK11 = Su'*KKtmp = Su'*KKold*Su
1034  teuchosRet = KK11.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,Su,KKtmp,ZERO);
1035  TEUCHOS_TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error,
1036  "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply.");
1037  }
1038  //
1039  // project the stiffness matrix on augV
1040  {
1041  OPT::Apply(*problem_->getOperator(),*augV,*augTmp);
1042  Teuchos::SerialDenseMatrix<int,ScalarType> KK12(Teuchos::View,newKK,numUnlocked,numNewLocked,0,numUnlocked),
1043  KK22(Teuchos::View,newKK,numNewLocked,numNewLocked,numUnlocked,numUnlocked);
1044  MVT::MvTransMv(ONE,*defV,*augTmp,KK12);
1045  MVT::MvTransMv(ONE,*augV,*augTmp,KK22);
1046  }
1047  //
1048  // done with defV,augV
1049  defV = Teuchos::null;
1050  augV = Teuchos::null;
1051  //
1052  // make it hermitian in memory (fill in KK21)
1053  for (int j=0; j<curdim; ++j) {
1054  for (int i=j+1; i<curdim; ++i) {
1055  newKK(i,j) = SCT::conjugate(newKK(j,i));
1056  }
1057  }
1058  //
1059  // we are done using augTmp as storage
1060  // put newLocked into lockvecs, new values into lockvals
1061  augTmp = Teuchos::null;
1062  {
1063  std::vector<Value<ScalarType> > allvals = bd_solver->getRitzValues();
1064  for (int i=0; i<numNewLocked; i++) {
1065  lockvals.push_back(allvals[lockind[i]].realpart);
1066  }
1067 
1068  std::vector<int> indlock(numNewLocked);
1069  for (int i=0; i<numNewLocked; i++) indlock[i] = curNumLocked+i;
1070  MVT::SetBlock(*newLocked,indlock,*lockvecs);
1071  newLocked = Teuchos::null;
1072 
1073  curNumLocked += numNewLocked;
1074  std::vector<int> curlockind(curNumLocked);
1075  for (int i=0; i<curNumLocked; i++) curlockind[i] = i;
1076  curlocked = MVT::CloneView(*lockvecs,curlockind);
1077  }
1078  // add locked vecs as aux vecs, along with aux vecs from problem
1079  // add lockvals to ordertest
1080  // disable locktest if curNumLocked == maxLocked
1081  {
1082  ordertest->setAuxVals(lockvals);
1083 
1085  if (probauxvecs != Teuchos::null) aux.push_back(probauxvecs);
1086  aux.push_back(curlocked);
1087  bd_solver->setAuxVecs(aux);
1088 
1089  if (curNumLocked == maxLocked_) {
1090  // disabled locking now
1091  combotest->removeTest(locktest);
1092  }
1093  }
1094 
1095  //
1096  // prepare new state
1098  rstate.curDim = curdim;
1099  if (inSituRestart_) {
1100  // data is already in the solver's memory
1101  rstate.V = state.V;
1102  }
1103  else {
1104  // data is in workspace and will be copied to solver memory
1105  rstate.V = workMV;
1106  }
1107  rstate.KK = Teuchos::rcpFromRef(newKK);
1108  //
1109  // pass new state to the solver
1110  bd_solver->initialize(rstate);
1111  } // end of locking
1113  //
1114  // we returned from iterate(), but none of our status tests Passed.
1115  // something is wrong, and it is probably our fault.
1116  //
1118  else {
1119  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): Invalid return from bd_solver::iterate().");
1120  }
1121  }
1122  catch (const AnasaziError &err) {
1123  printer_->stream(Errors)
1124  << "Anasazi::BlockDavidsonSolMgr::solve() caught unexpected exception from Anasazi::BlockDavidson::iterate() at iteration " << bd_solver->getNumIters() << std::endl
1125  << err.what() << std::endl
1126  << "Anasazi::BlockDavidsonSolMgr::solve() returning Unconverged with no solutions." << std::endl;
1127  return Unconverged;
1128  }
1129  }
1130 
1131  // clear temp space
1132  workMV = Teuchos::null;
1133 
1134  sol.numVecs = ordertest->howMany();
1135  if (sol.numVecs > 0) {
1136  sol.Evecs = MVT::Clone(*problem_->getInitVec(),sol.numVecs);
1137  sol.Espace = sol.Evecs;
1138  sol.Evals.resize(sol.numVecs);
1139  std::vector<MagnitudeType> vals(sol.numVecs);
1140 
1141  // copy them into the solution
1142  std::vector<int> which = ordertest->whichVecs();
1143  // indices between [0,blockSize) refer to vectors/values in the solver
1144  // indices between [-curNumLocked,-1] refer to locked vectors/values [0,curNumLocked)
1145  // everything has already been ordered by the solver; we just have to partition the two references
1146  std::vector<int> inlocked(0), insolver(0);
1147  for (unsigned int i=0; i<which.size(); i++) {
1148  if (which[i] >= 0) {
1149  TEUCHOS_TEST_FOR_EXCEPTION(which[i] >= blockSize_,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): positive indexing mistake from ordertest.");
1150  insolver.push_back(which[i]);
1151  }
1152  else {
1153  // sanity check
1154  TEUCHOS_TEST_FOR_EXCEPTION(which[i] < -curNumLocked,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): negative indexing mistake from ordertest.");
1155  inlocked.push_back(which[i] + curNumLocked);
1156  }
1157  }
1158 
1159  TEUCHOS_TEST_FOR_EXCEPTION(insolver.size() + inlocked.size() != (unsigned int)sol.numVecs,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): indexing mistake.");
1160 
1161  // set the vecs,vals in the solution
1162  if (insolver.size() > 0) {
1163  // set vecs
1164  int lclnum = insolver.size();
1165  std::vector<int> tosol(lclnum);
1166  for (int i=0; i<lclnum; i++) tosol[i] = i;
1167  Teuchos::RCP<const MV> v = MVT::CloneView(*bd_solver->getRitzVectors(),insolver);
1168  MVT::SetBlock(*v,tosol,*sol.Evecs);
1169  // set vals
1170  std::vector<Value<ScalarType> > fromsolver = bd_solver->getRitzValues();
1171  for (unsigned int i=0; i<insolver.size(); i++) {
1172  vals[i] = fromsolver[insolver[i]].realpart;
1173  }
1174  }
1175 
1176  // get the vecs,vals from locked storage
1177  if (inlocked.size() > 0) {
1178  int solnum = insolver.size();
1179  // set vecs
1180  int lclnum = inlocked.size();
1181  std::vector<int> tosol(lclnum);
1182  for (int i=0; i<lclnum; i++) tosol[i] = solnum + i;
1183  Teuchos::RCP<const MV> v = MVT::CloneView(*lockvecs,inlocked);
1184  MVT::SetBlock(*v,tosol,*sol.Evecs);
1185  // set vals
1186  for (unsigned int i=0; i<inlocked.size(); i++) {
1187  vals[i+solnum] = lockvals[inlocked[i]];
1188  }
1189  }
1190 
1191  // sort the eigenvalues and permute the eigenvectors appropriately
1192  {
1193  std::vector<int> order(sol.numVecs);
1194  sorter->sort(vals,Teuchos::rcpFromRef(order),sol.numVecs);
1195  // store the values in the Eigensolution
1196  for (int i=0; i<sol.numVecs; i++) {
1197  sol.Evals[i].realpart = vals[i];
1198  sol.Evals[i].imagpart = MT::zero();
1199  }
1200  // now permute the eigenvectors according to order
1201  msutils::permuteVectors(sol.numVecs,order,*sol.Evecs);
1202  }
1203 
1204  // setup sol.index, remembering that all eigenvalues are real so that index = {0,...,0}
1205  sol.index.resize(sol.numVecs,0);
1206  }
1207  }
1208 
1209  // print final summary
1210  bd_solver->currentStatus(printer_->stream(FinalSummary));
1211 
1212  // print timing information
1213 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1214  if ( printer_->isVerbosity( TimingDetails ) ) {
1215  Teuchos::TimeMonitor::summarize( printer_->stream( TimingDetails ) );
1216  }
1217 #endif
1218 
1219  problem_->setSolution(sol);
1220  printer_->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
1221 
1222  // get the number of iterations taken for this call to solve().
1223  numIters_ = bd_solver->getNumIters();
1224 
1225  if (sol.numVecs < nev) {
1226  return Unconverged; // return from BlockDavidsonSolMgr::solve()
1227  }
1228  return Converged; // return from BlockDavidsonSolMgr::solve()
1229 }
1230 
1231 
1232 template <class ScalarType, class MV, class OP>
1233 void
1235  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &global)
1236 {
1237  globalTest_ = global;
1238 }
1239 
1240 template <class ScalarType, class MV, class OP>
1243 {
1244  return globalTest_;
1245 }
1246 
1247 template <class ScalarType, class MV, class OP>
1248 void
1251 {
1252  debugTest_ = debug;
1253 }
1254 
1255 template <class ScalarType, class MV, class OP>
1258 {
1259  return debugTest_;
1260 }
1261 
1262 template <class ScalarType, class MV, class OP>
1263 void
1265  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &locking)
1266 {
1267  lockingTest_ = locking;
1268 }
1269 
1270 template <class ScalarType, class MV, class OP>
1273 {
1274  return lockingTest_;
1275 }
1276 
1277 } // end Anasazi namespace
1278 
1279 #endif /* ANASAZI_BLOCKDAVIDSON_SOLMGR_HPP */
ScalarType * values() const
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
Pure virtual base class which describes the basic interface for a solver manager. ...
std::vector< Value< ScalarType > > Evals
The computed eigenvalues.
void setLockingStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &locking)
Set the status test defining locking.
ResType
Enumerated type used to specify which residual norm used by residual norm status tests.
A special StatusTest for printing other status tests.
BlockDavidsonSolMgr(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, Teuchos::ParameterList &pl)
Basic constructor for BlockDavidsonSolMgr.
This class defines the interface required by an eigensolver and status test class to compute solution...
Teuchos::RCP< const MV > R
The current residual vectors.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > KK
The current projected K matrix.
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
SerialBandDenseMatrixPrinter< OrdinalType, ScalarType > printMat(const SerialBandDenseMatrix< OrdinalType, ScalarType > &obj)
basic_FancyOStream & setShowProcRank(const bool showProcRank)
T & get(const std::string &name, T def_value)
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Virtual base class which defines basic traits for the operator type.
Teuchos::RCP< MV > Evecs
The computed eigenvectors.
Status test for forming logical combinations of other status tests.
Teuchos::RCP< const MV > KX
The image of the current eigenvectors under K.
The Anasazi::SolverManager is a templated virtual base class that defines the basic interface that an...
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getDebugStatusTest() const
Get the status test for debugging.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Basic implementation of the Anasazi::SortManager class.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using the SVQB iter...
An exception class parent to all Anasazi exceptions.
Output managers remove the need for the eigensolver to know any information about the required output...
This class implements a Block Davidson iteration, a preconditioned iteration for solving linear Hermi...
ScalarTraits< ScalarType >::magnitudeType normFrobenius() const
Implementation of the block Davidson method.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
Anasazi&#39;s templated, static class providing utilities for the solvers.
bool isParameter(const std::string &name) const
int numVecs
The number of computed eigenpairs.
int getNumIters() const
Get the iteration count for the most recent call to solve().
void COPY(const OrdinalType &n, const ScalarType *x, const OrdinalType &incx, ScalarType *y, const OrdinalType &incy) const
Teuchos::RCP< MV > Espace
An orthonormal basis for the computed eigenspace.
Abstract class definition for Anasazi Output Managers.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Abstract base class which defines the interface required by an eigensolver and status test class to c...
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)
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
ReturnType
Enumerated type used to pass back information from a solver manager.
Output managers remove the need for the eigensolver to know any information about the required output...
Teuchos::RCP< const MV > V
The basis for the Krylov space.
A status test for testing the norm of the eigenvectors residuals.
Traits class which defines basic operations on multivectors.
std::vector< int > index
An index into Evecs to allow compressed storage of eigenvectors for real, non-Hermitian problems...
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getLockingStatusTest() const
Get the status test defining locking.
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
Orthogonalization manager based on the SVQB technique described in &quot;A Block Orthogonalization Procedu...
Struct for storing an eigenproblem solution.
int curDim
The current dimension of the solver.
void push_back(const value_type &x)
void GEQRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, ScalarType *TAU, ScalarType *WORK, const OrdinalType &lwork, OrdinalType *info) const
Structure to contain pointers to BlockDavidson state variables.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getGlobalStatusTest() const
Get the status test defining global convergence.
Special StatusTest for printing status tests.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &debug)
Set the status test for debugging.
Teuchos::RCP< const MV > X
The current eigenvectors.
Teuchos::RCP< const MV > MX
The image of the current eigenvectors under M, or Teuchos::null if M was not specified.
Status test for forming logical combinations of other status tests.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using (potentially)...
Types and exceptions used within Anasazi solvers and interfaces.
Abstract class definition for Anasazi output stream.
The BlockDavidsonSolMgr provides a powerful solver manager over the BlockDavidson eigensolver...
Common interface of stopping criteria for Anasazi&#39;s solvers.
A status test for testing the norm of the eigenvectors residuals.
Basic implementation of the Anasazi::OrthoManager class.
void setGlobalStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &global)
Set the status test defining global convergence.
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver&#39;s iterate() routine until ...
OrdinalType stride() const
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
Teuchos::RCP< const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > > T
The current Ritz values. This vector is a copy of the internal data.
Class which provides internal utilities for the Anasazi solvers.