Anasazi Version of the Day
Loading...
Searching...
No Matches
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
23
25#include "AnasaziBasicSort.hpp"
34#include "Teuchos_BLAS.hpp"
35#include "Teuchos_LAPACK.hpp"
36#include "Teuchos_TimeMonitor.hpp"
37#include "Teuchos_FancyOStream.hpp"
38
39
53namespace Anasazi {
54
55
88template<class ScalarType, class MV, class OP>
89class BlockDavidsonSolMgr : public SolverManager<ScalarType,MV,OP> {
90
91 private:
94 typedef Teuchos::ScalarTraits<ScalarType> SCT;
95 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
96 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
97
98 public:
99
101
102
128 BlockDavidsonSolMgr( const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
129 Teuchos::ParameterList &pl );
130
134
136
137
140 return *problem_;
141 }
142
144 int getNumIters() const {
145 return numIters_;
146 }
147
155 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
156 return Teuchos::tuple(_timerSolve, _timerRestarting, _timerLocking);
157 }
158
160
162
163
186
188 void setGlobalStatusTest(const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &global);
189
191 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > & getGlobalStatusTest() const;
192
194 void setLockingStatusTest(const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &locking);
195
197 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > & getLockingStatusTest() const;
198
200 void setDebugStatusTest(const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &debug);
201
203 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > & getDebugStatusTest() const;
204
206
207 private:
208 Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
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
225 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > globalTest_;
226 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > lockingTest_;
227 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > debugTest_;
228
229 Teuchos::RCP<OutputManager<ScalarType> > printer_;
230};
231
232
233// Constructor
234template<class ScalarType, class MV, class OP>
236 const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
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.
368 Teuchos::RCP<Teuchos::FancyOStream> osp;
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()
393template<class ScalarType, class MV, class OP>
396
397 typedef SolverUtils<ScalarType,MV,OP> msutils;
398
399 const int nev = problem_->getNEV();
400
401#ifdef TEUCHOS_DEBUG
402 Teuchos::RCP<Teuchos::FancyOStream>
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
410 Teuchos::RCP<BasicSort<MagnitudeType> > sorter = Teuchos::rcp( new BasicSort<MagnitudeType>(whch_) );
411
413 // Status tests
414 //
415 // convergence
416 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > convtest;
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 }
423 Teuchos::RCP<StatusTestWithOrdering<ScalarType,MV,OP> > ordertest
424 = Teuchos::rcp( new StatusTestWithOrdering<ScalarType,MV,OP>(convtest,sorter,nev) );
425 // locking
426 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > locktest;
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
436 Teuchos::Array<Teuchos::RCP<StatusTest<ScalarType,MV,OP> > > alltests;
437 alltests.push_back(ordertest);
438 if (locktest != Teuchos::null) alltests.push_back(locktest);
439 if (debugTest_ != Teuchos::null) alltests.push_back(debugTest_);
440
441 Teuchos::RCP<StatusTestCombo<ScalarType,MV,OP> > combotest
443 // printing StatusTest
444 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputtest;
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
454 Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho;
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
465 Teuchos::ParameterList plist;
466 plist.set("Block Size",blockSize_);
467 plist.set("Num Blocks",numBlocks_);
468
470 // BlockDavidson solver
471 Teuchos::RCP<BlockDavidson<ScalarType,MV,OP> > bd_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();
569 Teuchos::LAPACK<int,ScalarType> lapack;
570 Teuchos::BLAS<int,ScalarType> blas;
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
644 Teuchos::SerialDenseMatrix<int,ScalarType> S(curdim,curdim);
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
693 Teuchos::SerialDenseMatrix<int,ScalarType> Sr(Teuchos::View,S,curdim,newdim);
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)) {
764 Teuchos::SerialDenseMatrix<int,ScalarType> R(Teuchos::Copy,Sr,newdim,newdim);
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 //
878 Teuchos::SerialDenseMatrix<int,ScalarType> S(curdim,curdim);
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
922 Teuchos::SerialDenseMatrix<int,ScalarType> copySu(Su);
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 {
1003 Teuchos::Array<Teuchos::RCP<const MV> > against;
1004 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummyC;
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
1084 Teuchos::Array< Teuchos::RCP<const MV> > aux;
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
1232template <class ScalarType, class MV, class OP>
1233void
1235 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &global)
1236{
1237 globalTest_ = global;
1238}
1239
1240template <class ScalarType, class MV, class OP>
1241const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &
1243{
1244 return globalTest_;
1245}
1246
1247template <class ScalarType, class MV, class OP>
1248void
1250 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &debug)
1251{
1252 debugTest_ = debug;
1253}
1254
1255template <class ScalarType, class MV, class OP>
1256const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &
1258{
1259 return debugTest_;
1260}
1261
1262template <class ScalarType, class MV, class OP>
1263void
1265 const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &locking)
1266{
1267 lockingTest_ = locking;
1268}
1269
1270template <class ScalarType, class MV, class OP>
1271const Teuchos::RCP< StatusTest<ScalarType,MV,OP> > &
1273{
1274 return lockingTest_;
1275}
1276
1277} // end Anasazi namespace
1278
1279#endif /* ANASAZI_BLOCKDAVIDSON_SOLMGR_HPP */
Basic implementation of the Anasazi::OrthoManager class.
Basic implementation of the Anasazi::SortManager class.
Implementation of the block Davidson method.
Anasazi header file which uses auto-configuration information to include necessary C++ headers.
Abstract base class which defines the interface required by an eigensolver and status test class to c...
Abstract class definition for Anasazi Output Managers.
Abstract class definition for Anasazi output stream.
Orthogonalization manager based on the SVQB technique described in "A Block Orthogonalization Procedu...
Pure virtual base class which describes the basic interface for a solver manager.
Class which provides internal utilities for the Anasazi solvers.
Status test for forming logical combinations of other status tests.
Special StatusTest for printing status tests.
A status test for testing the norm of the eigenvectors residuals.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
Types and exceptions used within Anasazi solvers and interfaces.
An exception class parent to all Anasazi exceptions.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using (potentially)...
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
The BlockDavidsonSolMgr provides a powerful solver manager over the BlockDavidson eigensolver.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getGlobalStatusTest() const
Get the status test defining global convergence.
BlockDavidsonSolMgr(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, Teuchos::ParameterList &pl)
Basic constructor for BlockDavidsonSolMgr.
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &debug)
Set the status test for debugging.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getDebugStatusTest() const
Get the status test for debugging.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
void setLockingStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &locking)
Set the status test defining locking.
int getNumIters() const
Get the iteration count for the most recent call to solve().
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getLockingStatusTest() const
Get the status test defining locking.
void setGlobalStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &global)
Set the status test defining global convergence.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver's iterate() routine until ...
This class implements a Block Davidson iteration, a preconditioned iteration for solving linear Hermi...
This class defines the interface required by an eigensolver and status test class to compute solution...
Traits class which defines basic operations on multivectors.
Virtual base class which defines basic traits for the operator type.
Output managers remove the need for the eigensolver to know any information about the required output...
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using the SVQB iter...
The Anasazi::SolverManager is a templated virtual base class that defines the basic interface that an...
Anasazi's templated, static class providing utilities for the solvers.
Status test for forming logical combinations of other status tests.
A special StatusTest for printing other status tests.
A status test for testing the norm of the eigenvectors residuals.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
Common interface of stopping criteria for Anasazi's solvers.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.
ReturnType
Enumerated type used to pass back information from a solver manager.
ResType
Enumerated type used to specify which residual norm used by residual norm status tests.
Structure to contain pointers to BlockDavidson state variables.
int curDim
The current dimension of the solver.
Teuchos::RCP< const MV > V
The basis for the Krylov space.
Teuchos::RCP< const MV > X
The current eigenvectors.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > KK
The current projected K matrix.
Teuchos::RCP< const MV > R
The current residual vectors.
Teuchos::RCP< const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > > T
The current Ritz values. This vector is a copy of the internal data.
Teuchos::RCP< const MV > KX
The image of the current eigenvectors under K.
Teuchos::RCP< const MV > MX
The image of the current eigenvectors under M, or Teuchos::null if M was not specified.
Struct for storing an eigenproblem solution.
Teuchos::RCP< MV > Evecs
The computed eigenvectors.
std::vector< int > index
An index into Evecs to allow compressed storage of eigenvectors for real, non-Hermitian problems.
int numVecs
The number of computed eigenpairs.
Teuchos::RCP< MV > Espace
An orthonormal basis for the computed eigenspace.
std::vector< Value< ScalarType > > Evals
The computed eigenvalues.
Output managers remove the need for the eigensolver to know any information about the required output...