42 #ifndef ANASAZI_LOBPCG_SOLMGR_HPP
43 #define ANASAZI_LOBPCG_SOLMGR_HPP
70 #include "Teuchos_FancyOStream.hpp"
172 template<
class ScalarType,
class MV,
class OP>
241 return Teuchos::tuple(_timerSolve, _timerLocking);
301 std::string whch_, ortho_;
303 MagnitudeType convtol_, locktol_;
304 int maxIters_, numIters_;
306 bool relconvtol_, rellocktol_;
314 enum ResType convNorm_, lockNorm_;
328 template<
class ScalarType,
class MV,
class OP>
335 convtol_(
MT::prec()),
344 verbosity_(Anasazi::
Errors),
348 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
349 , _timerSolve(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: LOBPCGSolMgr::solve()")),
350 _timerLocking(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: LOBPCGSolMgr locking"))
356 TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument,
"Problem does not contain initial vectors to clone from.");
362 whch_ = pl.
get(
"Which",whch_);
364 std::invalid_argument,
"Anasazi::LOBPCGSolMgr: Invalid sorting string.");
367 ortho_ = pl.
get(
"Orthogonalization",ortho_);
368 if (ortho_ !=
"DGKS" && ortho_ !=
"SVQB") {
373 convtol_ = pl.
get(
"Convergence Tolerance",convtol_);
374 relconvtol_ = pl.
get(
"Relative Convergence Tolerance",relconvtol_);
375 strtmp = pl.
get(
"Convergence Norm",std::string(
"2"));
377 convNorm_ = RES_2NORM;
379 else if (strtmp ==
"M") {
380 convNorm_ = RES_ORTH;
384 "Anasazi::LOBPCGSolMgr: Invalid Convergence Norm.");
389 useLocking_ = pl.
get(
"Use Locking",useLocking_);
390 rellocktol_ = pl.
get(
"Relative Locking Tolerance",rellocktol_);
392 locktol_ = convtol_/10;
393 locktol_ = pl.
get(
"Locking Tolerance",locktol_);
394 strtmp = pl.
get(
"Locking Norm",std::string(
"2"));
396 lockNorm_ = RES_2NORM;
398 else if (strtmp ==
"M") {
399 lockNorm_ = RES_ORTH;
403 "Anasazi::LOBPCGSolMgr: Invalid Locking Norm.");
407 maxIters_ = pl.
get(
"Maximum Iterations",maxIters_);
410 blockSize_ = pl.
get(
"Block Size",problem_->getNEV());
412 "Anasazi::LOBPCGSolMgr: \"Block Size\" must be strictly positive.");
416 maxLocked_ = pl.
get(
"Max Locked",problem_->getNEV());
421 if (maxLocked_ == 0) {
425 "Anasazi::LOBPCGSolMgr: \"Max Locked\" must be positive.");
427 std::invalid_argument,
428 "Anasazi::LOBPCGSolMgr: Not enough storage space for requested number of eigenpairs.");
431 lockQuorum_ = pl.
get(
"Locking Quorum",lockQuorum_);
433 std::invalid_argument,
434 "Anasazi::LOBPCGSolMgr: \"Locking Quorum\" must be strictly positive.");
438 fullOrtho_ = pl.
get(
"Full Ortho",fullOrtho_);
442 osProc_ = pl.
get(
"Output Processor", osProc_);
446 osp_ = Teuchos::getParameter<Teuchos::RCP<Teuchos::FancyOStream> >(pl,
"Output Stream");
454 if (Teuchos::isParameterType<int>(pl,
"Verbosity")) {
455 verbosity_ = pl.
get(
"Verbosity", verbosity_);
457 verbosity_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,
"Verbosity");
462 recover_ = pl.
get(
"Recover",recover_);
466 state_ = Teuchos::getParameter<Teuchos::RCP<Anasazi::LOBPCGState<ScalarType,MV> > >(pl,
"Init");
472 template<
class ScalarType,
class MV,
class OP>
478 const int nev = problem_->getNEV();
500 if (globalTest_ == Teuchos::null) {
504 convtest = globalTest_;
511 if (lockingTest_ == Teuchos::null) {
515 locktest = lockingTest_;
521 if (locktest != Teuchos::null) alltests.
push_back(locktest);
522 if (debugTest_ != Teuchos::null) alltests.
push_back(debugTest_);
523 if (maxtest != Teuchos::null) alltests.
push_back(maxtest);
528 if ( printer->isVerbosity(
Debug) ) {
538 if (ortho_==
"SVQB") {
540 }
else if (ortho_==
"DGKS") {
543 TEUCHOS_TEST_FOR_EXCEPTION(ortho_!=
"SVQB"&&ortho_!=
"DGKS",std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): Invalid orthogonalization type.");
549 plist.
set(
"Block Size",blockSize_);
550 plist.
set(
"Full Ortho",fullOrtho_);
558 if (probauxvecs != Teuchos::null) {
566 int curNumLocked = 0;
569 lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
571 std::vector<MagnitudeType> lockvals;
581 if (fullOrtho_ ==
false && recover_ ==
true) {
582 workMV = MVT::Clone(*problem_->getInitVec(),2*3*blockSize_);
584 else if (useLocking_) {
585 if (problem_->getM() != Teuchos::null) {
586 workMV = MVT::Clone(*problem_->getInitVec(),4*blockSize_);
589 workMV = MVT::Clone(*problem_->getInitVec(),2*blockSize_);
596 problem_->setSolution(sol);
599 if (state_ != Teuchos::null) {
600 lobpcg_solver->initialize(*state_);
605 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
612 lobpcg_solver->iterate();
619 if (debugTest_ != Teuchos::null && debugTest_->getStatus() ==
Passed) {
620 throw AnasaziError(
"Anasazi::LOBPCGSolMgr::solve(): User-specified debug status test returned Passed.");
627 else if (ordertest->getStatus() ==
Passed || (maxtest != Teuchos::null && maxtest->getStatus() ==
Passed) ) {
638 else if (locktest != Teuchos::null && locktest->getStatus() ==
Passed) {
640 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
646 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() non-positive.");
648 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() not consistent with whichVecs().");
650 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: locking not deactivated.");
652 int numnew = locktest->howMany();
653 std::vector<int> indnew = locktest->whichVecs();
656 if (curNumLocked + numnew > maxLocked_) {
657 numnew = maxLocked_ - curNumLocked;
658 indnew.resize(numnew);
663 bool hadP = lobpcg_solver->hasP();
667 printer->print(
Debug,
"Locking vectors: ");
668 for (
unsigned int i=0; i<indnew.size(); i++) {printer->stream(
Debug) <<
" " << indnew[i];}
669 printer->print(
Debug,
"\n");
671 std::vector<MagnitudeType> newvals(numnew);
676 newvecs = MVT::CloneView(*lobpcg_solver->getRitzVectors(),indnew);
678 std::vector<Value<ScalarType> > allvals = lobpcg_solver->getRitzValues();
679 for (
int i=0; i<numnew; i++) {
680 newvals[i] = allvals[indnew[i]].realpart;
685 std::vector<int> indlock(numnew);
686 for (
int i=0; i<numnew; i++) indlock[i] = curNumLocked+i;
687 MVT::SetBlock(*newvecs,indlock,*lockvecs);
688 newvecs = Teuchos::null;
691 lockvals.insert(lockvals.end(),newvals.begin(),newvals.end());
692 curNumLocked += numnew;
695 std::vector<int> indlock(curNumLocked);
696 for (
int i=0; i<curNumLocked; i++) indlock[i] = i;
698 if (probauxvecs != Teuchos::null) {
706 ordertest->setAuxVals(lockvals);
715 std::vector<int> bsind(blockSize_);
716 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
717 newstateX = MVT::CloneViewNonConst(*workMV,bsind);
718 MVT::SetBlock(*state.
X,bsind,*newstateX);
720 if (state.
MX != Teuchos::null) {
721 std::vector<int> block3(blockSize_);
722 for (
int i=0; i<blockSize_; i++) block3[i] = 2*blockSize_+i;
723 newstateMX = MVT::CloneViewNonConst(*workMV,block3);
724 MVT::SetBlock(*state.
MX,bsind,*newstateMX);
730 MVT::MvRandom(*newX);
732 if (newstateMX != Teuchos::null) {
734 OPT::Apply(*problem_->getM(),*newX,*newMX);
741 ortho->projectAndNormalizeMat(*newstateX,curauxvecs,dummyC,Teuchos::null,newstateMX);
746 std::vector<int> block2(blockSize_);
747 for (
int i=0; i<blockSize_; i++) block2[i] = blockSize_+i;
748 newstateP = MVT::CloneViewNonConst(*workMV,block2);
749 MVT::SetBlock(*state.
P,bsind,*newstateP);
751 if (state.
MP != Teuchos::null) {
752 std::vector<int> block4(blockSize_);
753 for (
int i=0; i<blockSize_; i++) block4[i] = 3*blockSize_+i;
754 newstateMP = MVT::CloneViewNonConst(*workMV,block4);
755 MVT::SetBlock(*state.
MP,bsind,*newstateMP);
761 ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
765 ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
770 newstate.
X = newstateX;
771 newstate.
MX = newstateMX;
772 newstate.
P = newstateP;
773 newstate.
MP = newstateMP;
774 lobpcg_solver->initialize(newstate);
777 if (curNumLocked == maxLocked_) {
779 combotest->removeTest(locktest);
783 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): Invalid return from lobpcg_solver::iterate().");
792 if (fullOrtho_==
true || recover_==
false) {
796 printer->stream(
Warnings) <<
"Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
797 <<
"Will not try to recover." << std::endl;
800 printer->stream(
Warnings) <<
"Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
801 <<
"Full orthogonalization is off; will try to recover." << std::endl;
808 int localsize = lobpcg_solver->hasP() ? 3*blockSize_ : 2*blockSize_;
809 bool hasM = problem_->getM() != Teuchos::null;
811 std::vector<int> recind(localsize);
812 for (
int i=0; i<localsize; i++) recind[i] = i;
813 restart = MVT::CloneViewNonConst(*workMV,recind);
816 std::vector<int> recind(localsize);
817 for (
int i=0; i<localsize; i++) recind[i] = localsize+i;
818 Krestart = MVT::CloneViewNonConst(*workMV,recind);
831 std::vector<int> blk1(blockSize_);
832 for (
int i=0; i < blockSize_; i++) blk1[i] = i;
833 MVT::SetBlock(*curstate.
X,blk1,*restart);
837 MVT::SetBlock(*curstate.
MX,blk1,*Mrestart);
843 std::vector<int> blk2(blockSize_);
844 for (
int i=0; i < blockSize_; i++) blk2[i] = blockSize_+i;
845 MVT::SetBlock(*curstate.
H,blk2,*restart);
849 MVT::SetBlock(*curstate.
MH,blk2,*Mrestart);
853 if (localsize == 3*blockSize_) {
854 std::vector<int> blk3(blockSize_);
855 for (
int i=0; i < blockSize_; i++) blk3[i] = 2*blockSize_+i;
856 MVT::SetBlock(*curstate.
P,blk3,*restart);
860 MVT::SetBlock(*curstate.
MP,blk3,*Mrestart);
867 if (curNumLocked > 0) {
868 std::vector<int> indlock(curNumLocked);
869 for (
int i=0; i<curNumLocked; i++) indlock[i] = i;
873 if (probauxvecs != Teuchos::null) {
877 int rank = ortho->projectAndNormalizeMat(*restart,Q,dummyC,Teuchos::null,Mrestart);
878 if (rank < blockSize_) {
880 printer->stream(
Errors) <<
"Error! Recovered basis only rank " << rank <<
". Block size is " << blockSize_ <<
".\n"
881 <<
"Recovery failed." << std::endl;
885 if (rank < localsize) {
887 std::vector<int> redind(localsize);
888 for (
int i=0; i<localsize; i++) redind[i] = i;
890 restart = MVT::CloneViewNonConst(*restart,redind);
891 Krestart = MVT::CloneViewNonConst(*Krestart,redind);
900 std::vector<MagnitudeType> theta(localsize);
904 MVT::MvTransMv(1.0,*restart,*Mrestart,MM);
907 OPT::Apply(*problem_->getOperator(),*restart,*Krestart);
910 MVT::MvTransMv(1.0,*restart,*Krestart,KK);
912 msutils::directSolver(localsize,KK,Teuchos::rcpFromRef(MM),S,theta,rank,1);
913 if (rank < blockSize_) {
914 printer->stream(
Errors) <<
"Error! Recovered basis of rank " << rank <<
" produced only " << rank <<
"ritz vectors.\n"
915 <<
"Block size is " << blockSize_ <<
".\n"
916 <<
"Recovery failed." << std::endl;
924 std::vector<int> order(rank);
926 sorter->sort( theta, Teuchos::rcpFromRef(order),rank );
929 msutils::permuteVectors(order,curS);
938 std::vector<int> bsind(blockSize_);
939 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
940 newX = MVT::CloneViewNonConst(*Krestart,bsind);
942 MVT::MvTimesMatAddMv(1.0,*restart,S1,0.0,*newX);
945 theta.resize(blockSize_);
946 newstate.
T = Teuchos::rcpFromRef(theta);
948 lobpcg_solver->initialize(newstate);
952 <<
"Anasazi::LOBPCGSolMgr::solve() caught unexpected exception from Anasazi::LOBPCG::iterate() at iteration " << lobpcg_solver->getNumIters() << std::endl
953 << err.what() << std::endl
954 <<
"Anasazi::LOBPCGSolMgr::solve() returning Unconverged with no solutions." << std::endl;
960 sol.
numVecs = ordertest->howMany();
962 sol.
Evecs = MVT::Clone(*problem_->getInitVec(),sol.
numVecs);
965 std::vector<MagnitudeType> vals(sol.
numVecs);
968 std::vector<int> which = ordertest->whichVecs();
972 std::vector<int> inlocked(0), insolver(0);
973 for (
unsigned int i=0; i<which.size(); i++) {
975 TEUCHOS_TEST_FOR_EXCEPTION(which[i] >= blockSize_,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): positive indexing mistake from ordertest.");
976 insolver.push_back(which[i]);
980 TEUCHOS_TEST_FOR_EXCEPTION(which[i] < -curNumLocked,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): negative indexing mistake from ordertest.");
981 inlocked.push_back(which[i] + curNumLocked);
988 if (insolver.size() > 0) {
990 int lclnum = insolver.size();
991 std::vector<int> tosol(lclnum);
992 for (
int i=0; i<lclnum; i++) tosol[i] = i;
994 MVT::SetBlock(*v,tosol,*sol.
Evecs);
996 std::vector<Value<ScalarType> > fromsolver = lobpcg_solver->getRitzValues();
997 for (
unsigned int i=0; i<insolver.size(); i++) {
998 vals[i] = fromsolver[insolver[i]].realpart;
1003 if (inlocked.size() > 0) {
1004 int solnum = insolver.size();
1006 int lclnum = inlocked.size();
1007 std::vector<int> tosol(lclnum);
1008 for (
int i=0; i<lclnum; i++) tosol[i] = solnum + i;
1010 MVT::SetBlock(*v,tosol,*sol.
Evecs);
1012 for (
unsigned int i=0; i<inlocked.size(); i++) {
1013 vals[i+solnum] = lockvals[inlocked[i]];
1019 std::vector<int> order(sol.
numVecs);
1020 sorter->sort( vals, Teuchos::rcpFromRef(order), sol.
numVecs);
1022 for (
int i=0; i<sol.
numVecs; i++) {
1023 sol.
Evals[i].realpart = vals[i];
1024 sol.
Evals[i].imagpart = MT::zero();
1036 lobpcg_solver->currentStatus(printer->stream(
FinalSummary));
1039 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1045 problem_->setSolution(sol);
1046 printer->stream(
Debug) <<
"Returning " << sol.
numVecs <<
" eigenpairs to eigenproblem." << std::endl;
1049 numIters_ = lobpcg_solver->getNumIters();
1058 template <
class ScalarType,
class MV,
class OP>
1063 globalTest_ = global;
1066 template <
class ScalarType,
class MV,
class OP>
1073 template <
class ScalarType,
class MV,
class OP>
1081 template <
class ScalarType,
class MV,
class OP>
1088 template <
class ScalarType,
class MV,
class OP>
1093 lockingTest_ = locking;
1096 template <
class ScalarType,
class MV,
class OP>
1100 return lockingTest_;
Pure virtual base class which describes the basic interface for a solver manager. ...
std::vector< Value< ScalarType > > Evals
The computed eigenvalues.
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.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getDebugStatusTest() const
Get the status test for debugging.
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...
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
This class provides the Locally Optimal Block Preconditioned Conjugate Gradient (LOBPCG) iteration...
Virtual base class which defines basic traits for the operator type.
Teuchos::RCP< MV > Evecs
The computed eigenvectors.
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver's iterate() routine until ...
Status test for forming logical combinations of other status tests.
Teuchos::RCP< const MultiVector > H
The current preconditioned residual vectors.
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.
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...
Implementation of the locally-optimal block preconditioned conjugate gradient (LOBPCG) method...
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's templated, static class providing utilities for the solvers.
bool isParameter(const std::string &name) const
int numVecs
The number of computed eigenpairs.
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)
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getGlobalStatusTest() const
Get the status test defining global convergence.
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)
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...
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...
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...
Struct for storing an eigenproblem solution.
void setLockingStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &locking)
Set the status test defining locking.
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.
void push_back(const value_type &x)
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.
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.
void setGlobalStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &global)
Set the status test defining global convergence.
virtual ~LOBPCGSolMgr()
Destructor.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Teuchos::RCP< const MultiVector > MP
The image of the current search direction under M, or Teuchos::null if M was not specified.
int getNumIters() const
Get the iteration count for the most recent call to solve().
Common interface of stopping criteria for Anasazi's solvers.
A status test for testing the norm of the eigenvectors residuals.
Basic implementation of the Anasazi::OrthoManager class.
User interface for the LOBPCG eigensolver.
Structure to contain pointers to Anasazi state variables.
Teuchos::RCP< const MultiVector > X
The current eigenvectors.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
Class which provides internal utilities for the Anasazi solvers.