Anasazi  Version of the Day
AnasaziLOBPCGSolMgr.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Anasazi: Block Eigensolvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef ANASAZI_LOBPCG_SOLMGR_HPP
43 #define ANASAZI_LOBPCG_SOLMGR_HPP
44 
49 #include "AnasaziConfigDefs.hpp"
50 #include "AnasaziTypes.hpp"
51 
52 #include "AnasaziEigenproblem.hpp"
53 #include "AnasaziSolverManager.hpp"
54 #include "AnasaziSolverUtils.hpp"
55 
56 #include "AnasaziLOBPCG.hpp"
57 #include "AnasaziBasicSort.hpp"
66 #include "Teuchos_BLAS.hpp"
67 #include "Teuchos_TimeMonitor.hpp"
68 
119 
120 namespace Anasazi {
121 
169 template<class ScalarType, class MV, class OP>
170 class LOBPCGSolMgr : public SolverManager<ScalarType,MV,OP> {
171 
172  private:
175  typedef Teuchos::ScalarTraits<ScalarType> SCT;
176  typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
177  typedef Teuchos::ScalarTraits<MagnitudeType> MT;
178 
179  public:
180 
182 
183 
208  LOBPCGSolMgr( const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
209  Teuchos::ParameterList &pl );
210 
212  virtual ~LOBPCGSolMgr() {};
214 
216 
217 
220  return *problem_;
221  }
222 
224  int getNumIters() const {
225  return numIters_;
226  }
227 
234  Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
235  return Teuchos::tuple(_timerSolve, _timerLocking);
236  }
237 
238 
240 
242 
243 
270  ReturnType solve();
271 
273  void setGlobalStatusTest(const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &global);
274 
276  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > & getGlobalStatusTest() const;
277 
279  void setLockingStatusTest(const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &locking);
280 
282  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > & getLockingStatusTest() const;
283 
285  void setDebugStatusTest(const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &debug);
286 
288  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > & getDebugStatusTest() const;
289 
291 
292  private:
293  Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
294 
295  std::string whch_, ortho_;
296 
297  MagnitudeType convtol_, locktol_;
298  int maxIters_, numIters_;
299  bool useLocking_;
300  bool relconvtol_, rellocktol_;
301  int blockSize_;
302  bool fullOrtho_;
303  int maxLocked_;
304  int verbosity_;
305  int lockQuorum_;
306  bool recover_;
307  Teuchos::RCP<LOBPCGState<ScalarType,MV> > state_;
308  enum ResType convNorm_, lockNorm_;
309 
310  Teuchos::RCP<Teuchos::Time> _timerSolve, _timerLocking;
311 
312  Teuchos::RCP<StatusTest<ScalarType,MV,OP> > globalTest_;
313  Teuchos::RCP<StatusTest<ScalarType,MV,OP> > lockingTest_;
314  Teuchos::RCP<StatusTest<ScalarType,MV,OP> > debugTest_;
315 };
316 
317 
318 // Constructor
319 template<class ScalarType, class MV, class OP>
321  const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
322  Teuchos::ParameterList &pl ) :
323  problem_(problem),
324  whch_("SR"),
325  ortho_("SVQB"),
326  convtol_(MT::prec()),
327  maxIters_(100),
328  numIters_(0),
329  useLocking_(false),
330  relconvtol_(true),
331  rellocktol_(true),
332  blockSize_(0),
333  fullOrtho_(true),
334  maxLocked_(0),
335  verbosity_(Anasazi::Errors),
336  lockQuorum_(1),
337  recover_(true)
338 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
339  , _timerSolve(Teuchos::TimeMonitor::getNewTimer("Anasazi: LOBPCGSolMgr::solve()")),
340  _timerLocking(Teuchos::TimeMonitor::getNewTimer("Anasazi: LOBPCGSolMgr locking"))
341 #endif
342 {
343  TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
344  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set.");
345  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric.");
346  TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from.");
347 
348 
349  std::string strtmp;
350 
351  // which values to solve for
352  whch_ = pl.get("Which",whch_);
353  TEUCHOS_TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR",
354  std::invalid_argument, "Anasazi::LOBPCGSolMgr: Invalid sorting string.");
355 
356  // which orthogonalization to use
357  ortho_ = pl.get("Orthogonalization",ortho_);
358  if (ortho_ != "DGKS" && ortho_ != "SVQB") {
359  ortho_ = "SVQB";
360  }
361 
362  // convergence tolerance
363  convtol_ = pl.get("Convergence Tolerance",convtol_);
364  relconvtol_ = pl.get("Relative Convergence Tolerance",relconvtol_);
365  strtmp = pl.get("Convergence Norm",std::string("2"));
366  if (strtmp == "2") {
367  convNorm_ = RES_2NORM;
368  }
369  else if (strtmp == "M") {
370  convNorm_ = RES_ORTH;
371  }
372  else {
373  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
374  "Anasazi::LOBPCGSolMgr: Invalid Convergence Norm.");
375  }
376 
377 
378  // locking tolerance
379  useLocking_ = pl.get("Use Locking",useLocking_);
380  rellocktol_ = pl.get("Relative Locking Tolerance",rellocktol_);
381  // default: should be less than convtol_
382  locktol_ = convtol_/10;
383  locktol_ = pl.get("Locking Tolerance",locktol_);
384  strtmp = pl.get("Locking Norm",std::string("2"));
385  if (strtmp == "2") {
386  lockNorm_ = RES_2NORM;
387  }
388  else if (strtmp == "M") {
389  lockNorm_ = RES_ORTH;
390  }
391  else {
392  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
393  "Anasazi::LOBPCGSolMgr: Invalid Locking Norm.");
394  }
395 
396  // maximum number of iterations
397  maxIters_ = pl.get("Maximum Iterations",maxIters_);
398 
399  // block size: default is nev()
400  blockSize_ = pl.get("Block Size",problem_->getNEV());
401  TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
402  "Anasazi::LOBPCGSolMgr: \"Block Size\" must be strictly positive.");
403 
404  // max locked: default is nev(), must satisfy maxLocked_ + blockSize_ >= nev
405  if (useLocking_) {
406  maxLocked_ = pl.get("Max Locked",problem_->getNEV());
407  }
408  else {
409  maxLocked_ = 0;
410  }
411  if (maxLocked_ == 0) {
412  useLocking_ = false;
413  }
414  TEUCHOS_TEST_FOR_EXCEPTION(maxLocked_ < 0, std::invalid_argument,
415  "Anasazi::LOBPCGSolMgr: \"Max Locked\" must be positive.");
416  TEUCHOS_TEST_FOR_EXCEPTION(maxLocked_ + blockSize_ < problem_->getNEV(),
417  std::invalid_argument,
418  "Anasazi::LOBPCGSolMgr: Not enough storage space for requested number of eigenpairs.");
419 
420  if (useLocking_) {
421  lockQuorum_ = pl.get("Locking Quorum",lockQuorum_);
422  TEUCHOS_TEST_FOR_EXCEPTION(lockQuorum_ <= 0,
423  std::invalid_argument,
424  "Anasazi::LOBPCGSolMgr: \"Locking Quorum\" must be strictly positive.");
425  }
426 
427  // full orthogonalization: default true
428  fullOrtho_ = pl.get("Full Ortho",fullOrtho_);
429 
430  // verbosity level
431  if (pl.isParameter("Verbosity")) {
432  if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
433  verbosity_ = pl.get("Verbosity", verbosity_);
434  } else {
435  verbosity_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
436  }
437  }
438 
439  // recover from LOBPCGRitzFailure
440  recover_ = pl.get("Recover",recover_);
441 
442  // get (optionally) an initial state
443  if (pl.isParameter("Init")) {
444  state_ = Teuchos::getParameter<Teuchos::RCP<Anasazi::LOBPCGState<ScalarType,MV> > >(pl,"Init");
445  }
446 }
447 
448 
449 // solve()
450 template<class ScalarType, class MV, class OP>
453 
454  typedef SolverUtils<ScalarType,MV,OP> msutils;
455 
456  const int nev = problem_->getNEV();
457 
458 
459 
461  // Sort manager
462  Teuchos::RCP<BasicSort<MagnitudeType> > sorter = Teuchos::rcp( new BasicSort<MagnitudeType>(whch_) );
463 
465  // Output manager
466  Teuchos::RCP<BasicOutputManager<ScalarType> > printer = Teuchos::rcp( new BasicOutputManager<ScalarType>(verbosity_) );
467 
469  // Status tests
470  //
471  // maximum number of iterations: optional test
472  Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxtest;
473  if (maxIters_ > 0) {
474  maxtest = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>(maxIters_) );
475  }
476  // convergence
477  Teuchos::RCP<StatusTest<ScalarType,MV,OP> > convtest;
478  if (globalTest_ == Teuchos::null) {
479  convtest = Teuchos::rcp( new StatusTestResNorm<ScalarType,MV,OP>(convtol_,nev,convNorm_,relconvtol_) );
480  }
481  else {
482  convtest = globalTest_;
483  }
484  Teuchos::RCP<StatusTestWithOrdering<ScalarType,MV,OP> > ordertest
485  = Teuchos::rcp( new StatusTestWithOrdering<ScalarType,MV,OP>(convtest,sorter,nev) );
486  // locking
487  Teuchos::RCP<StatusTest<ScalarType,MV,OP> > locktest;
488  if (useLocking_) {
489  if (lockingTest_ == Teuchos::null) {
490  locktest = Teuchos::rcp( new StatusTestResNorm<ScalarType,MV,OP>(locktol_,lockQuorum_,lockNorm_,rellocktol_) );
491  }
492  else {
493  locktest = lockingTest_;
494  }
495  }
496  // for a non-short-circuited OR test, the order doesn't matter
497  Teuchos::Array<Teuchos::RCP<StatusTest<ScalarType,MV,OP> > > alltests;
498  alltests.push_back(ordertest);
499  if (locktest != Teuchos::null) alltests.push_back(locktest);
500  if (debugTest_ != Teuchos::null) alltests.push_back(debugTest_);
501  if (maxtest != Teuchos::null) alltests.push_back(maxtest);
502  Teuchos::RCP<StatusTestCombo<ScalarType,MV,OP> > combotest
504  // printing StatusTest
505  Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputtest;
506  if ( printer->isVerbosity(Debug) ) {
507  outputtest = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer,combotest,1,Passed+Failed+Undefined ) );
508  }
509  else {
510  outputtest = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer,combotest,1,Passed ) );
511  }
512 
514  // Orthomanager
515  Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho;
516  if (ortho_=="SVQB") {
517  ortho = Teuchos::rcp( new SVQBOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
518  } else if (ortho_=="DGKS") {
519  ortho = Teuchos::rcp( new BasicOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
520  } else {
521  TEUCHOS_TEST_FOR_EXCEPTION(ortho_!="SVQB"&&ortho_!="DGKS",std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): Invalid orthogonalization type.");
522  }
523 
525  // Parameter list
526  Teuchos::ParameterList plist;
527  plist.set("Block Size",blockSize_);
528  plist.set("Full Ortho",fullOrtho_);
529 
531  // LOBPCG solver
532  Teuchos::RCP<LOBPCG<ScalarType,MV,OP> > lobpcg_solver
533  = Teuchos::rcp( new LOBPCG<ScalarType,MV,OP>(problem_,sorter,printer,outputtest,ortho,plist) );
534  // set any auxiliary vectors defined in the problem
535  Teuchos::RCP< const MV > probauxvecs = problem_->getAuxVecs();
536  if (probauxvecs != Teuchos::null) {
537  lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(probauxvecs) );
538  }
539 
541  // Storage
542  //
543  // lockvecs will contain eigenvectors that have been determined "locked" by the status test
544  int curNumLocked = 0;
545  Teuchos::RCP<MV> lockvecs;
546  if (useLocking_) {
547  lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
548  }
549  std::vector<MagnitudeType> lockvals;
550  // workMV will be used as work space for LOBPCGRitzFailure recovery and locking
551  // it will be partitioned in these cases as follows:
552  // for LOBPCGRitzFailure recovery:
553  // workMV = [X H P OpX OpH OpP], where OpX OpH OpP will be used for K and M
554  // total size: 2*3*blocksize
555  // for locking
556  // workMV = [X P MX MP], with MX,MP needing storage only if hasM==true
557  // total size: 2*blocksize or 4*blocksize
558  Teuchos::RCP<MV> workMV;
559  if (fullOrtho_ == false && recover_ == true) {
560  workMV = MVT::Clone(*problem_->getInitVec(),2*3*blockSize_);
561  }
562  else if (useLocking_) {
563  if (problem_->getM() != Teuchos::null) {
564  workMV = MVT::Clone(*problem_->getInitVec(),4*blockSize_);
565  }
566  else {
567  workMV = MVT::Clone(*problem_->getInitVec(),2*blockSize_);
568  }
569  }
570 
571  // initialize the solution to nothing in case we throw an exception
573  sol.numVecs = 0;
574  problem_->setSolution(sol);
575 
576  // initialize the solver if the user specified a state
577  if (state_ != Teuchos::null) {
578  lobpcg_solver->initialize(*state_);
579  }
580 
581  // enter solve() iterations
582  {
583 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
584  Teuchos::TimeMonitor slvtimer(*_timerSolve);
585 #endif
586 
587  // tell the lobpcg_solver to iterate
588  while (1) {
589  try {
590  lobpcg_solver->iterate();
591 
593  //
594  // check user-specified debug test; if it passed, return an exception
595  //
597  if (debugTest_ != Teuchos::null && debugTest_->getStatus() == Passed) {
598  throw AnasaziError("Anasazi::LOBPCGSolMgr::solve(): User-specified debug status test returned Passed.");
599  }
601  //
602  // check convergence first
603  //
605  else if (ordertest->getStatus() == Passed || (maxtest != Teuchos::null && maxtest->getStatus() == Passed) ) {
606  // we have convergence or not
607  // ordertest->whichVecs() tells us which vectors from lockvecs and solver state are the ones we want
608  // ordertest->howMany() will tell us how many
609  break;
610  }
612  //
613  // check locking if we didn't converge
614  //
616  else if (locktest != Teuchos::null && locktest->getStatus() == Passed) {
617 
618 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
619  Teuchos::TimeMonitor lcktimer(*_timerLocking);
620 #endif
621 
622  // remove the locked vectors,values from lobpcg_solver: put them in newvecs, newvals
623  TEUCHOS_TEST_FOR_EXCEPTION(locktest->howMany() <= 0,std::logic_error,
624  "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() non-positive.");
625  TEUCHOS_TEST_FOR_EXCEPTION(locktest->howMany() != (int)locktest->whichVecs().size(),std::logic_error,
626  "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() not consistent with whichVecs().");
627  TEUCHOS_TEST_FOR_EXCEPTION(curNumLocked == maxLocked_,std::logic_error,
628  "Anasazi::LOBPCGSolMgr::solve(): status test mistake: locking not deactivated.");
629  // get the indices
630  int numnew = locktest->howMany();
631  std::vector<int> indnew = locktest->whichVecs();
632 
633  // don't lock more than maxLocked_; we didn't allocate enough space.
634  if (curNumLocked + numnew > maxLocked_) {
635  numnew = maxLocked_ - curNumLocked;
636  indnew.resize(numnew);
637  }
638 
639  // the call below to lobpcg_solver->setAuxVecs() will reset the solver to unitialized with hasP() == false
640  // store the hasP() state for use below
641  bool hadP = lobpcg_solver->hasP();
642 
643  {
644  // debug printing
645  printer->print(Debug,"Locking vectors: ");
646  for (unsigned int i=0; i<indnew.size(); i++) {printer->stream(Debug) << " " << indnew[i];}
647  printer->print(Debug,"\n");
648  }
649  std::vector<MagnitudeType> newvals(numnew);
650  Teuchos::RCP<const MV> newvecs;
651  {
652  // work in a local scope, to hide the variabes needed for extracting this info
653  // get the vectors
654  newvecs = MVT::CloneView(*lobpcg_solver->getRitzVectors(),indnew);
655  // get the values
656  std::vector<Value<ScalarType> > allvals = lobpcg_solver->getRitzValues();
657  for (int i=0; i<numnew; i++) {
658  newvals[i] = allvals[indnew[i]].realpart;
659  }
660  }
661  // put newvecs into lockvecs
662  {
663  std::vector<int> indlock(numnew);
664  for (int i=0; i<numnew; i++) indlock[i] = curNumLocked+i;
665  MVT::SetBlock(*newvecs,indlock,*lockvecs);
666  newvecs = Teuchos::null;
667  }
668  // put newvals into lockvals
669  lockvals.insert(lockvals.end(),newvals.begin(),newvals.end());
670  curNumLocked += numnew;
671  // add locked vecs as aux vecs, along with aux vecs from problem
672  {
673  std::vector<int> indlock(curNumLocked);
674  for (int i=0; i<curNumLocked; i++) indlock[i] = i;
675  Teuchos::RCP<const MV> curlocked = MVT::CloneView(*lockvecs,indlock);
676  if (probauxvecs != Teuchos::null) {
677  lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(probauxvecs,curlocked) );
678  }
679  else {
680  lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(curlocked) );
681  }
682  }
683  // add locked vals to ordertest
684  ordertest->setAuxVals(lockvals);
685  // fill out the empty state in the solver
686  {
687  LOBPCGState<ScalarType,MV> state = lobpcg_solver->getState();
688  Teuchos::RCP<MV> newstateX, newstateMX, newstateP, newstateMP;
689  //
690  // workMV will be partitioned as follows: workMV = [X P MX MP],
691  //
692  // make a copy of the current X,MX state
693  std::vector<int> bsind(blockSize_);
694  for (int i=0; i<blockSize_; i++) bsind[i] = i;
695  newstateX = MVT::CloneViewNonConst(*workMV,bsind);
696  MVT::SetBlock(*state.X,bsind,*newstateX);
697 
698  if (state.MX != Teuchos::null) {
699  std::vector<int> block3(blockSize_);
700  for (int i=0; i<blockSize_; i++) block3[i] = 2*blockSize_+i;
701  newstateMX = MVT::CloneViewNonConst(*workMV,block3);
702  MVT::SetBlock(*state.MX,bsind,*newstateMX);
703  }
704  //
705  // get select part, set to random, apply M
706  {
707  Teuchos::RCP<MV> newX = MVT::CloneViewNonConst(*newstateX,indnew);
708  MVT::MvRandom(*newX);
709 
710  if (newstateMX != Teuchos::null) {
711  Teuchos::RCP<MV> newMX = MVT::CloneViewNonConst(*newstateMX,indnew);
712  OPT::Apply(*problem_->getM(),*newX,*newMX);
713  }
714  }
715 
716  Teuchos::Array<Teuchos::RCP<const MV> > curauxvecs = lobpcg_solver->getAuxVecs();
717  Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummyC;
718  // ortho X against the aux vectors
719  ortho->projectAndNormalizeMat(*newstateX,curauxvecs,dummyC,Teuchos::null,newstateMX);
720 
721  if (hadP) {
722  //
723  // get P and optionally MP, orthogonalize against X and auxiliary vectors
724  std::vector<int> block2(blockSize_);
725  for (int i=0; i<blockSize_; i++) block2[i] = blockSize_+i;
726  newstateP = MVT::CloneViewNonConst(*workMV,block2);
727  MVT::SetBlock(*state.P,bsind,*newstateP);
728 
729  if (state.MP != Teuchos::null) {
730  std::vector<int> block4(blockSize_);
731  for (int i=0; i<blockSize_; i++) block4[i] = 3*blockSize_+i;
732  newstateMP = MVT::CloneViewNonConst(*workMV,block4);
733  MVT::SetBlock(*state.MP,bsind,*newstateMP);
734  }
735 
736  if (fullOrtho_) {
737  // ortho P against the new aux vectors and new X
738  curauxvecs.push_back(newstateX);
739  ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
740  }
741  else {
742  // ortho P against the new aux vectors
743  ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
744  }
745  }
746  // set the new state
748  newstate.X = newstateX;
749  newstate.MX = newstateMX;
750  newstate.P = newstateP;
751  newstate.MP = newstateMP;
752  lobpcg_solver->initialize(newstate);
753  }
754 
755  if (curNumLocked == maxLocked_) {
756  // disable locking now; remove locking test from combo test
757  combotest->removeTest(locktest);
758  }
759  }
760  else {
761  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): Invalid return from lobpcg_solver::iterate().");
762  }
763  }
765  //
766  // check Ritz Failure
767  //
769  catch (const LOBPCGRitzFailure &re) {
770  if (fullOrtho_==true || recover_==false) {
771  // if we are already using full orthogonalization, there isn't much we can do here.
772  // the most recent information in the status tests is still valid, and can be used to extract/return the
773  // eigenpairs that have converged.
774  printer->stream(Warnings) << "Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
775  << "Will not try to recover." << std::endl;
776  break; // while(1)
777  }
778  printer->stream(Warnings) << "Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
779  << "Full orthogonalization is off; will try to recover." << std::endl;
780  // get the current "basis" from the solver, orthonormalize it, do a rayleigh-ritz, and restart with the ritz vectors
781  // if there aren't enough, break and quit with what we have
782  //
783  // workMV = [X H P OpX OpH OpP], where OpX OpH OpP will be used for K and M
784  LOBPCGState<ScalarType,MV> curstate = lobpcg_solver->getState();
785  Teuchos::RCP<MV> restart, Krestart, Mrestart;
786  int localsize = lobpcg_solver->hasP() ? 3*blockSize_ : 2*blockSize_;
787  bool hasM = problem_->getM() != Teuchos::null;
788  {
789  std::vector<int> recind(localsize);
790  for (int i=0; i<localsize; i++) recind[i] = i;
791  restart = MVT::CloneViewNonConst(*workMV,recind);
792  }
793  {
794  std::vector<int> recind(localsize);
795  for (int i=0; i<localsize; i++) recind[i] = localsize+i;
796  Krestart = MVT::CloneViewNonConst(*workMV,recind);
797  }
798  if (hasM) {
799  Mrestart = Krestart;
800  }
801  else {
802  Mrestart = restart;
803  }
804  //
805  // set restart = [X H P] and Mrestart = M*[X H P]
806  //
807  // put X into [0 , blockSize)
808  {
809  std::vector<int> blk1(blockSize_);
810  for (int i=0; i < blockSize_; i++) blk1[i] = i;
811  MVT::SetBlock(*curstate.X,blk1,*restart);
812 
813  // put MX into [0 , blockSize)
814  if (hasM) {
815  MVT::SetBlock(*curstate.MX,blk1,*Mrestart);
816  }
817  }
818  //
819  // put H into [blockSize_ , 2*blockSize)
820  {
821  std::vector<int> blk2(blockSize_);
822  for (int i=0; i < blockSize_; i++) blk2[i] = blockSize_+i;
823  MVT::SetBlock(*curstate.H,blk2,*restart);
824 
825  // put MH into [blockSize_ , 2*blockSize)
826  if (hasM) {
827  MVT::SetBlock(*curstate.MH,blk2,*Mrestart);
828  }
829  }
830  // optionally, put P into [2*blockSize,3*blockSize)
831  if (localsize == 3*blockSize_) {
832  std::vector<int> blk3(blockSize_);
833  for (int i=0; i < blockSize_; i++) blk3[i] = 2*blockSize_+i;
834  MVT::SetBlock(*curstate.P,blk3,*restart);
835 
836  // put MP into [2*blockSize,3*blockSize)
837  if (hasM) {
838  MVT::SetBlock(*curstate.MP,blk3,*Mrestart);
839  }
840  }
841  // project against auxvecs and locked vecs, and orthonormalize the basis
842  Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummyC;
843  Teuchos::Array<Teuchos::RCP<const MV> > Q;
844  {
845  if (curNumLocked > 0) {
846  std::vector<int> indlock(curNumLocked);
847  for (int i=0; i<curNumLocked; i++) indlock[i] = i;
848  Teuchos::RCP<const MV> curlocked = MVT::CloneView(*lockvecs,indlock);
849  Q.push_back(curlocked);
850  }
851  if (probauxvecs != Teuchos::null) {
852  Q.push_back(probauxvecs);
853  }
854  }
855  int rank = ortho->projectAndNormalizeMat(*restart,Q,dummyC,Teuchos::null,Mrestart);
856  if (rank < blockSize_) {
857  // quit
858  printer->stream(Errors) << "Error! Recovered basis only rank " << rank << ". Block size is " << blockSize_ << ".\n"
859  << "Recovery failed." << std::endl;
860  break;
861  }
862  // reduce multivec size if necessary
863  if (rank < localsize) {
864  localsize = rank;
865  std::vector<int> redind(localsize);
866  for (int i=0; i<localsize; i++) redind[i] = i;
867  // grab the first part of restart,Krestart
868  restart = MVT::CloneViewNonConst(*restart,redind);
869  Krestart = MVT::CloneViewNonConst(*Krestart,redind);
870  if (hasM) {
871  Mrestart = Krestart;
872  }
873  else {
874  Mrestart = restart;
875  }
876  }
877  Teuchos::SerialDenseMatrix<int,ScalarType> KK(localsize,localsize), MM(localsize,localsize), S(localsize,localsize);
878  std::vector<MagnitudeType> theta(localsize);
879  // project the matrices
880  //
881  // MM = restart^H M restart
882  MVT::MvTransMv(1.0,*restart,*Mrestart,MM);
883  //
884  // compute Krestart = K*restart
885  OPT::Apply(*problem_->getOperator(),*restart,*Krestart);
886  //
887  // KK = restart^H K restart
888  MVT::MvTransMv(1.0,*restart,*Krestart,KK);
889  rank = localsize;
890  msutils::directSolver(localsize,KK,Teuchos::rcpFromRef(MM),S,theta,rank,1);
891  if (rank < blockSize_) {
892  printer->stream(Errors) << "Error! Recovered basis of rank " << rank << " produced only " << rank << "ritz vectors.\n"
893  << "Block size is " << blockSize_ << ".\n"
894  << "Recovery failed." << std::endl;
895  break;
896  }
897  theta.resize(rank);
898  //
899  // sort the ritz values using the sort manager
900  {
901  Teuchos::BLAS<int,ScalarType> blas;
902  std::vector<int> order(rank);
903  // sort
904  sorter->sort( theta, Teuchos::rcpFromRef(order),rank ); // don't catch exception
905  // Sort the primitive ritz vectors
906  Teuchos::SerialDenseMatrix<int,ScalarType> curS(Teuchos::View,S,rank,rank);
907  msutils::permuteVectors(order,curS);
908  }
909  //
910  Teuchos::SerialDenseMatrix<int,ScalarType> S1(Teuchos::View,S,localsize,blockSize_);
911  //
912  // compute the ritz vectors: store them in Krestart
914  Teuchos::RCP<MV> newX;
915  {
916  std::vector<int> bsind(blockSize_);
917  for (int i=0; i<blockSize_; i++) bsind[i] = i;
918  newX = MVT::CloneViewNonConst(*Krestart,bsind);
919  }
920  MVT::MvTimesMatAddMv(1.0,*restart,S1,0.0,*newX);
921  // send X and theta into the solver
922  newstate.X = newX;
923  theta.resize(blockSize_);
924  newstate.T = Teuchos::rcpFromRef(theta);
925  // initialize
926  lobpcg_solver->initialize(newstate);
927  }
928  catch (const AnasaziError &err) {
929  printer->stream(Errors)
930  << "Anasazi::LOBPCGSolMgr::solve() caught unexpected exception from Anasazi::LOBPCG::iterate() at iteration " << lobpcg_solver->getNumIters() << std::endl
931  << err.what() << std::endl
932  << "Anasazi::LOBPCGSolMgr::solve() returning Unconverged with no solutions." << std::endl;
933  return Unconverged;
934  }
935  // don't catch any other exceptions
936  }
937 
938  sol.numVecs = ordertest->howMany();
939  if (sol.numVecs > 0) {
940  sol.Evecs = MVT::Clone(*problem_->getInitVec(),sol.numVecs);
941  sol.Espace = sol.Evecs;
942  sol.Evals.resize(sol.numVecs);
943  std::vector<MagnitudeType> vals(sol.numVecs);
944 
945  // copy them into the solution
946  std::vector<int> which = ordertest->whichVecs();
947  // indices between [0,blockSize) refer to vectors/values in the solver
948  // indices between [-curNumLocked,-1] refer to locked vectors/values [0,curNumLocked)
949  // everything has already been ordered by the solver; we just have to partition the two references
950  std::vector<int> inlocked(0), insolver(0);
951  for (unsigned int i=0; i<which.size(); i++) {
952  if (which[i] >= 0) {
953  TEUCHOS_TEST_FOR_EXCEPTION(which[i] >= blockSize_,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): positive indexing mistake from ordertest.");
954  insolver.push_back(which[i]);
955  }
956  else {
957  // sanity check
958  TEUCHOS_TEST_FOR_EXCEPTION(which[i] < -curNumLocked,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): negative indexing mistake from ordertest.");
959  inlocked.push_back(which[i] + curNumLocked);
960  }
961  }
962 
963  TEUCHOS_TEST_FOR_EXCEPTION(insolver.size() + inlocked.size() != (unsigned int)sol.numVecs,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): indexing mistake.");
964 
965  // set the vecs,vals in the solution
966  if (insolver.size() > 0) {
967  // set vecs
968  int lclnum = insolver.size();
969  std::vector<int> tosol(lclnum);
970  for (int i=0; i<lclnum; i++) tosol[i] = i;
971  Teuchos::RCP<const MV> v = MVT::CloneView(*lobpcg_solver->getRitzVectors(),insolver);
972  MVT::SetBlock(*v,tosol,*sol.Evecs);
973  // set vals
974  std::vector<Value<ScalarType> > fromsolver = lobpcg_solver->getRitzValues();
975  for (unsigned int i=0; i<insolver.size(); i++) {
976  vals[i] = fromsolver[insolver[i]].realpart;
977  }
978  }
979 
980  // get the vecs,vals from locked storage
981  if (inlocked.size() > 0) {
982  int solnum = insolver.size();
983  // set vecs
984  int lclnum = inlocked.size();
985  std::vector<int> tosol(lclnum);
986  for (int i=0; i<lclnum; i++) tosol[i] = solnum + i;
987  Teuchos::RCP<const MV> v = MVT::CloneView(*lockvecs,inlocked);
988  MVT::SetBlock(*v,tosol,*sol.Evecs);
989  // set vals
990  for (unsigned int i=0; i<inlocked.size(); i++) {
991  vals[i+solnum] = lockvals[inlocked[i]];
992  }
993  }
994 
995  // sort the eigenvalues and permute the eigenvectors appropriately
996  {
997  std::vector<int> order(sol.numVecs);
998  sorter->sort( vals, Teuchos::rcpFromRef(order), sol.numVecs);
999  // store the values in the Eigensolution
1000  for (int i=0; i<sol.numVecs; i++) {
1001  sol.Evals[i].realpart = vals[i];
1002  sol.Evals[i].imagpart = MT::zero();
1003  }
1004  // now permute the eigenvectors according to order
1005  msutils::permuteVectors(sol.numVecs,order,*sol.Evecs);
1006  }
1007 
1008  // setup sol.index, remembering that all eigenvalues are real so that index = {0,...,0}
1009  sol.index.resize(sol.numVecs,0);
1010  }
1011  }
1012 
1013  // print final summary
1014  lobpcg_solver->currentStatus(printer->stream(FinalSummary));
1015 
1016  // print timing information
1017 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1018  if ( printer->isVerbosity( TimingDetails ) ) {
1019  Teuchos::TimeMonitor::summarize( printer->stream( TimingDetails ) );
1020  }
1021 #endif
1022 
1023  problem_->setSolution(sol);
1024  printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
1025 
1026  // get the number of iterations performed in this call to solve.
1027  numIters_ = lobpcg_solver->getNumIters();
1028 
1029  if (sol.numVecs < nev) {
1030  return Unconverged; // return from LOBPCGSolMgr::solve()
1031  }
1032  return Converged; // return from LOBPCGSolMgr::solve()
1033 }
1034 
1035 
1036 template <class ScalarType, class MV, class OP>
1037 void
1039  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &global)
1040 {
1041  globalTest_ = global;
1042 }
1043 
1044 template <class ScalarType, class MV, class OP>
1045 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &
1047 {
1048  return globalTest_;
1049 }
1050 
1051 template <class ScalarType, class MV, class OP>
1052 void
1054  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &debug)
1055 {
1056  debugTest_ = debug;
1057 }
1058 
1059 template <class ScalarType, class MV, class OP>
1060 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &
1062 {
1063  return debugTest_;
1064 }
1065 
1066 template <class ScalarType, class MV, class OP>
1067 void
1069  const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &locking)
1070 {
1071  lockingTest_ = locking;
1072 }
1073 
1074 template <class ScalarType, class MV, class OP>
1075 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &
1077 {
1078  return lockingTest_;
1079 }
1080 
1081 } // end Anasazi namespace
1082 
1083 #endif /* ANASAZI_LOBPCG_SOLMGR_HPP */
Pure virtual base class which describes the basic interface for a solver manager. ...
static void MvRandom(MV &mv)
Replace the vectors in mv with random vectors.
static void MvTimesMatAddMv(const ScalarType alpha, const MV &A, const Teuchos::SerialDenseMatrix< int, ScalarType > &B, const ScalarType beta, MV &mv)
Update mv with .
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getLockingStatusTest() const
Get 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.
This class defines the interface required by an eigensolver and status test class to compute solution...
LOBPCGSolMgr(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, Teuchos::ParameterList &pl)
Basic constructor for LOBPCGSolMgr.
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
This class provides the Locally Optimal Block Preconditioned Conjugate Gradient (LOBPCG) iteration...
Virtual base class which defines basic traits for the operator type.
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver&#39;s iterate() routine until ...
Status test for forming logical combinations of other status tests.
Teuchos::RCP< const MultiVector > H
The current preconditioned residual vectors.
int getNumIters() const
Get the iteration count for the most recent call to solve().
The Anasazi::SolverManager is a templated virtual base class that defines the basic interface that an...
Teuchos::RCP< const MultiVector > P
The current search direction.
static void Apply(const OP &Op, const MV &x, MV &y)
Application method which performs operation y = Op*x. An OperatorError exception is thrown if there i...
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.
Implementation of the locally-optimal block preconditioned conjugate gradient (LOBPCG) method...
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package...
Teuchos::RCP< const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > > T
The current Ritz values.
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.
int numVecs
The number of computed eigenpairs.
Basic output manager for sending information of select verbosity levels to the appropriate output str...
Anasazi&#39;s basic output manager for sending information of select verbosity levels to the appropriate ...
Abstract base class which defines the interface required by an eigensolver and status test class to c...
ReturnType
Enumerated type used to pass back information from a solver manager.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
A status test for testing the norm of the eigenvectors residuals.
Traits class which defines basic operations on multivectors.
static void MvTransMv(const ScalarType alpha, const MV &A, const MV &B, Teuchos::SerialDenseMatrix< int, ScalarType > &C)
Compute C := alpha * A^H B.
Teuchos::RCP< const MultiVector > MX
The image of the current eigenvectors under M, or Teuchos::null if M was not specified.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &debug)
Set the status test for debugging.
Orthogonalization manager based on the SVQB technique described in "A Block Orthogonalization Procedu...
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
Creates a new MV that shares the selected contents of mv (shallow copy).
Struct for storing an eigenproblem solution.
void setLockingStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &locking)
Set the status test defining locking.
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
Creates a new const MV that shares the selected contents of mv (shallow copy).
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index...
Teuchos::RCP< const MultiVector > MH
The image of the current preconditioned residual vectors under M, or Teuchos::null if M was not speci...
A status test for testing the number of iterations.
Status test for testing the number of iterations.
Special StatusTest for printing status tests.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
LOBPCGRitzFailure is thrown when the LOBPCG solver is unable to continue a call to LOBPCG::iterate() ...
Status test for forming logical combinations of other status tests.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using (potentially)...
Types and exceptions used within Anasazi solvers and interfaces.
void setGlobalStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &global)
Set the status test defining global convergence.
virtual ~LOBPCGSolMgr()
Destructor.
Teuchos::RCP< const MultiVector > MP
The image of the current search direction under M, or Teuchos::null if M was not specified.
Common interface of stopping criteria for Anasazi&#39;s solvers.
A status test for testing the norm of the eigenvectors residuals.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getGlobalStatusTest() const
Get the status test defining global convergence.
Basic implementation of the Anasazi::OrthoManager class.
User interface for the LOBPCG eigensolver.
Structure to contain pointers to Anasazi state variables.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getDebugStatusTest() const
Get the status test for debugging.
Teuchos::RCP< const MultiVector > X
The current eigenvectors.
static Teuchos::RCP< MV > Clone(const MV &mv, const int numvecs)
Creates a new empty MV containing numvecs columns.
Class which provides internal utilities for the Anasazi solvers.