00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00033 #ifndef ANASAZI_BLOCK_DAVIDSON_HPP
00034 #define ANASAZI_BLOCK_DAVIDSON_HPP
00035
00036 #include "AnasaziTypes.hpp"
00037
00038 #include "AnasaziEigensolver.hpp"
00039 #include "AnasaziMultiVecTraits.hpp"
00040 #include "AnasaziOperatorTraits.hpp"
00041 #include "Teuchos_ScalarTraits.hpp"
00042
00043 #include "AnasaziMatOrthoManager.hpp"
00044 #include "AnasaziModalSolverUtils.hpp"
00045
00046 #include "Teuchos_LAPACK.hpp"
00047 #include "Teuchos_BLAS.hpp"
00048 #include "Teuchos_SerialDenseMatrix.hpp"
00049 #include "Teuchos_ParameterList.hpp"
00050 #include "Teuchos_TimeMonitor.hpp"
00051
00062 namespace Anasazi {
00063
00065
00066
00071 template <class ScalarType, class MV>
00072 struct BlockDavidsonState {
00077 int curDim;
00082 Teuchos::RefCountPtr<const MV> V;
00084 Teuchos::RefCountPtr<const MV> X;
00086 Teuchos::RefCountPtr<const MV> KX;
00088 Teuchos::RefCountPtr<const MV> MX;
00090 Teuchos::RefCountPtr<const MV> R;
00095 Teuchos::RefCountPtr<const MV> H;
00097 Teuchos::RefCountPtr<const std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > T;
00103 Teuchos::RefCountPtr<const Teuchos::SerialDenseMatrix<int,ScalarType> > KK;
00104 BlockDavidsonState() : curDim(0), V(Teuchos::null),
00105 X(Teuchos::null), KX(Teuchos::null), MX(Teuchos::null),
00106 R(Teuchos::null), H(Teuchos::null),
00107 T(Teuchos::null), KK(Teuchos::null) {}
00108 };
00109
00111
00113
00114
00127 class BlockDavidsonInitFailure : public AnasaziError {public:
00128 BlockDavidsonInitFailure(const std::string& what_arg) : AnasaziError(what_arg)
00129 {}};
00130
00138 class BlockDavidsonOrthoFailure : public AnasaziError {public:
00139 BlockDavidsonOrthoFailure(const std::string& what_arg) : AnasaziError(what_arg)
00140 {}};
00141
00143
00144
00145 template <class ScalarType, class MV, class OP>
00146 class BlockDavidson : public Eigensolver<ScalarType,MV,OP> {
00147 public:
00149
00150
00158 BlockDavidson( const Teuchos::RefCountPtr<Eigenproblem<ScalarType,MV,OP> > &problem,
00159 const Teuchos::RefCountPtr<SortManager<ScalarType,MV,OP> > &sorter,
00160 const Teuchos::RefCountPtr<OutputManager<ScalarType> > &printer,
00161 const Teuchos::RefCountPtr<StatusTest<ScalarType,MV,OP> > &tester,
00162 const Teuchos::RefCountPtr<MatOrthoManager<ScalarType,MV,OP> > &ortho,
00163 Teuchos::ParameterList ¶ms
00164 );
00165
00167 virtual ~BlockDavidson() {};
00169
00170
00172
00173
00197 void iterate();
00198
00220 void initialize(BlockDavidsonState<ScalarType,MV> state);
00221
00225 void initialize();
00226
00242 bool isInitialized() { return initialized_; }
00243
00255 BlockDavidsonState<ScalarType,MV> getState() const {
00256 BlockDavidsonState<ScalarType,MV> state;
00257 state.curDim = curDim_;
00258 state.V = V_;
00259 state.X = X_;
00260 state.KX = KX_;
00261 if (hasM_) {
00262 state.MX = MX_;
00263 }
00264 else {
00265 state.MX = Teuchos::null;
00266 }
00267 state.R = R_;
00268 state.H = H_;
00269 state.KK = KK_;
00270 state.T = Teuchos::rcp(new std::vector<MagnitudeType>(theta_));
00271 return state;
00272 }
00273
00275
00276
00278
00279
00281 int getNumIters() const { return(iter_); };
00282
00284 void resetNumIters() { iter_=0; };
00285
00293 Teuchos::RefCountPtr<const MV> getRitzVectors() {return X_;}
00294
00300 std::vector<Value<ScalarType> > getRitzValues() {
00301 std::vector<Value<ScalarType> > ret(curDim_);
00302 for (int i=0; i<curDim_; i++) {
00303 ret[i].realpart = theta_[i];
00304 ret[i].imagpart = ZERO;
00305 }
00306 return ret;
00307 }
00308
00316 std::vector<int> getRitzIndex() {
00317 std::vector<int> ret(curDim_,0);
00318 return ret;
00319 }
00320
00321
00327 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> getResNorms();
00328
00329
00335 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> getRes2Norms();
00336
00337
00342 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> getRitzRes2Norms() {
00343 std::vector<MagnitudeType> ret = ritz2norms_;
00344 ret.resize(curDim_);
00345 return ret;
00346 }
00347
00348
00354 int getCurSubspaceDim() const {
00355 if (!initialized_) return 0;
00356 return curDim_;
00357 }
00358
00360 int getMaxSubspaceDim() const {return blockSize_*numBlocks_;}
00361
00363
00364
00366
00367
00368
00370 const Eigenproblem<ScalarType,MV,OP>& getProblem() const { return(*problem_); };
00371
00381 void setBlockSize(int blockSize);
00382
00384 int getBlockSize() const { return(blockSize_); }
00385
00398 void setAuxVecs(const Teuchos::Array<Teuchos::RefCountPtr<const MV> > &auxvecs);
00399
00401 Teuchos::Array<Teuchos::RefCountPtr<const MV> > getAuxVecs() const {return auxVecs_;}
00402
00404
00406
00407
00417 void setSize(int blockSize, int numBlocks);
00418
00420
00422
00423
00425 void currentStatus(ostream &os);
00426
00428
00429 private:
00430
00431
00432
00433 typedef MultiVecTraits<ScalarType,MV> MVT;
00434 typedef OperatorTraits<ScalarType,MV,OP> OPT;
00435 typedef Teuchos::ScalarTraits<ScalarType> SCT;
00436 typedef typename SCT::magnitudeType MagnitudeType;
00437 const MagnitudeType ONE;
00438 const MagnitudeType ZERO;
00439 const MagnitudeType NANVAL;
00440
00441
00442
00443 struct CheckList {
00444 bool checkV;
00445 bool checkX, checkMX, checkKX;
00446 bool checkH, checkMH, checkKH;
00447 bool checkR, checkQ;
00448 bool checkKK;
00449 CheckList() : checkV(false),
00450 checkX(false),checkMX(false),checkKX(false),
00451 checkH(false),checkMH(false),checkKH(false),
00452 checkR(false),checkQ(false),checkKK(false) {};
00453 };
00454
00455
00456
00457 string accuracyCheck(const CheckList &chk, const string &where) const;
00458
00459
00460
00461 const Teuchos::RefCountPtr<Eigenproblem<ScalarType,MV,OP> > problem_;
00462 const Teuchos::RefCountPtr<SortManager<ScalarType,MV,OP> > sm_;
00463 const Teuchos::RefCountPtr<OutputManager<ScalarType> > om_;
00464 const Teuchos::RefCountPtr<StatusTest<ScalarType,MV,OP> > tester_;
00465 const Teuchos::RefCountPtr<MatOrthoManager<ScalarType,MV,OP> > orthman_;
00466
00467
00468
00469 Teuchos::RefCountPtr<OP> Op_;
00470 Teuchos::RefCountPtr<OP> MOp_;
00471 Teuchos::RefCountPtr<OP> Prec_;
00472 bool hasM_;
00473
00474
00475
00476 ModalSolverUtils<ScalarType,MV,OP> MSUtils_;
00477
00478
00479
00480 Teuchos::RefCountPtr<Teuchos::Time> timerOp_, timerMOp_, timerPrec_,
00481 timerSortEval_, timerDS_,
00482 timerLocal_, timerCompRes_,
00483 timerOrtho_;
00484
00485
00486
00487 int count_ApplyOp_, count_ApplyM_, count_ApplyPrec_;
00488
00489
00490
00491
00492
00493
00494
00495 int blockSize_;
00496
00497 int numBlocks_;
00498
00499
00500
00501
00502
00503
00504
00505 bool initialized_;
00506
00507
00508
00509
00510 int curDim_;
00511
00512
00513
00514
00515
00516 Teuchos::RefCountPtr<MV> X_, KX_, MX_, R_,
00517 H_, KH_, MH_,
00518 V_;
00519
00520
00521
00522 Teuchos::RefCountPtr<Teuchos::SerialDenseMatrix<int,ScalarType> > KK_;
00523
00524
00525 Teuchos::Array<Teuchos::RefCountPtr<const MV> > auxVecs_;
00526 int numAuxVecs_;
00527
00528
00529 int iter_;
00530
00531
00532 std::vector<MagnitudeType> theta_, Rnorms_, R2norms_, ritz2norms_;
00533
00534
00535 bool Rnorms_current_, R2norms_current_;
00536
00537 };
00538
00539
00541
00542 template <class ScalarType, class MV, class OP>
00543 BlockDavidson<ScalarType,MV,OP>::BlockDavidson(
00544 const Teuchos::RefCountPtr<Eigenproblem<ScalarType,MV,OP> > &problem,
00545 const Teuchos::RefCountPtr<SortManager<ScalarType,MV,OP> > &sorter,
00546 const Teuchos::RefCountPtr<OutputManager<ScalarType> > &printer,
00547 const Teuchos::RefCountPtr<StatusTest<ScalarType,MV,OP> > &tester,
00548 const Teuchos::RefCountPtr<MatOrthoManager<ScalarType,MV,OP> > &ortho,
00549 Teuchos::ParameterList ¶ms
00550 ) :
00551 ONE(Teuchos::ScalarTraits<MagnitudeType>::one()),
00552 ZERO(Teuchos::ScalarTraits<MagnitudeType>::zero()),
00553 NANVAL(Teuchos::ScalarTraits<MagnitudeType>::nan()),
00554
00555 problem_(problem),
00556 sm_(sorter),
00557 om_(printer),
00558 tester_(tester),
00559 orthman_(ortho),
00560 MSUtils_(om_),
00561
00562 timerOp_(Teuchos::TimeMonitor::getNewTimer("Operation Op*x")),
00563 timerMOp_(Teuchos::TimeMonitor::getNewTimer("Operation M*x")),
00564 timerPrec_(Teuchos::TimeMonitor::getNewTimer("Operation Prec*x")),
00565 timerSortEval_(Teuchos::TimeMonitor::getNewTimer("Sorting eigenvalues")),
00566 timerDS_(Teuchos::TimeMonitor::getNewTimer("Direct solve")),
00567 timerLocal_(Teuchos::TimeMonitor::getNewTimer("Local update")),
00568 timerCompRes_(Teuchos::TimeMonitor::getNewTimer("Computing residuals")),
00569 timerOrtho_(Teuchos::TimeMonitor::getNewTimer("Orthogonalization")),
00570 count_ApplyOp_(0),
00571 count_ApplyM_(0),
00572 count_ApplyPrec_(0),
00573
00574 blockSize_(0),
00575 numBlocks_(0),
00576 initialized_(false),
00577 curDim_(0),
00578 auxVecs_( Teuchos::Array<Teuchos::RefCountPtr<const MV> >(0) ),
00579 numAuxVecs_(0),
00580 iter_(0),
00581 Rnorms_current_(false),
00582 R2norms_current_(false)
00583 {
00584 TEST_FOR_EXCEPTION(problem_ == Teuchos::null,std::invalid_argument,
00585 "Anasazi::BlockDavidson::constructor: user passed null problem pointer.");
00586 TEST_FOR_EXCEPTION(sm_ == Teuchos::null,std::invalid_argument,
00587 "Anasazi::BlockDavidson::constructor: user passed null sort manager pointer.");
00588 TEST_FOR_EXCEPTION(om_ == Teuchos::null,std::invalid_argument,
00589 "Anasazi::BlockDavidson::constructor: user passed null output manager pointer.");
00590 TEST_FOR_EXCEPTION(tester_ == Teuchos::null,std::invalid_argument,
00591 "Anasazi::BlockDavidson::constructor: user passed null status test pointer.");
00592 TEST_FOR_EXCEPTION(orthman_ == Teuchos::null,std::invalid_argument,
00593 "Anasazi::BlockDavidson::constructor: user passed null orthogonalization manager pointer.");
00594 TEST_FOR_EXCEPTION(problem_->isProblemSet() == false, std::invalid_argument,
00595 "Anasazi::BlockDavidson::constructor: problem is not set.");
00596 TEST_FOR_EXCEPTION(problem_->isHermitian() == false, std::invalid_argument,
00597 "Anasazi::BlockDavidson::constructor: problem is not hermitian.");
00598
00599
00600 Op_ = problem_->getOperator();
00601 TEST_FOR_EXCEPTION(Op_ == Teuchos::null, std::invalid_argument,
00602 "Anasazi::BlockDavidson::constructor: problem provides no operator.");
00603 MOp_ = problem_->getM();
00604 Prec_ = problem_->getPrec();
00605 hasM_ = (MOp_ != Teuchos::null);
00606
00607
00608 int bs = params.get("Block Size", problem_->getNEV());
00609 int nb = params.get("Num Blocks", 2);
00610 setSize(bs,nb);
00611 }
00612
00613
00615
00616
00617 template <class ScalarType, class MV, class OP>
00618 void BlockDavidson<ScalarType,MV,OP>::setBlockSize (int blockSize)
00619 {
00620 setSize(blockSize,numBlocks_);
00621 }
00622
00623
00625
00626 template <class ScalarType, class MV, class OP>
00627 void BlockDavidson<ScalarType,MV,OP>::setSize (int blockSize, int numBlocks)
00628 {
00629
00630
00631
00632 TEST_FOR_EXCEPTION(blockSize < 1, std::invalid_argument, "Anasazi::BlockDavidson::setSize(): block size must be strictly positive.");
00633 TEST_FOR_EXCEPTION(numBlocks < 2, std::invalid_argument, "Anasazi::BlockDavidson::setSize(): num blocks must be greater than one.");
00634 if (blockSize == blockSize_ && numBlocks == numBlocks_) {
00635
00636 return;
00637 }
00638
00639 blockSize_ = blockSize;
00640 numBlocks_ = numBlocks;
00641
00642 Teuchos::RefCountPtr<const MV> tmp;
00643
00644
00645
00646
00647 if (X_ != Teuchos::null) {
00648 tmp = X_;
00649 }
00650 else {
00651 tmp = problem_->getInitVec();
00652 TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument,
00653 "Anasazi::BlockDavidson::setSize(): Eigenproblem did not specify initial vectors to clone from");
00654 }
00655
00656 TEST_FOR_EXCEPTION(numAuxVecs_+blockSize*numBlocks > MVT::GetVecLength(*tmp),std::invalid_argument,"Anasazi::BlockDavidson::setSize(): impossible subspace requirements.");
00657
00658
00660
00661
00662
00663 Rnorms_.resize(blockSize_,NANVAL);
00664 R2norms_.resize(blockSize_,NANVAL);
00665
00666
00667 om_->print(Debug," >> Allocating X_\n");
00668 X_ = MVT::Clone(*tmp,blockSize_);
00669 om_->print(Debug," >> Allocating KX_\n");
00670 KX_ = MVT::Clone(*tmp,blockSize_);
00671 if (hasM_) {
00672 om_->print(Debug," >> Allocating MX_\n");
00673 MX_ = MVT::Clone(*tmp,blockSize_);
00674 }
00675 else {
00676 MX_ = X_;
00677 }
00678 om_->print(Debug," >> Allocating R_\n");
00679 R_ = MVT::Clone(*tmp,blockSize_);
00680
00682
00683
00684 int newsd = blockSize_*numBlocks_;
00685 theta_.resize(blockSize_*numBlocks_,NANVAL);
00686 ritz2norms_.resize(blockSize_*numBlocks_,NANVAL);
00687 om_->print(Debug," >> Allocating V_\n");
00688 V_ = MVT::Clone(*tmp,newsd);
00689 KK_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(newsd,newsd) );
00690
00691 om_->print(Debug," >> done allocating.");
00692
00693 initialized_ = false;
00694 curDim_ = 0;
00695 }
00696
00697
00699
00700 template <class ScalarType, class MV, class OP>
00701 void BlockDavidson<ScalarType,MV,OP>::setAuxVecs(const Teuchos::Array<Teuchos::RefCountPtr<const MV> > &auxvecs) {
00702 typedef typename Teuchos::Array<Teuchos::RefCountPtr<const MV> >::iterator tarcpmv;
00703
00704
00705 auxVecs_ = auxvecs;
00706 numAuxVecs_ = 0;
00707 for (tarcpmv i=auxVecs_.begin(); i != auxVecs_.end(); i++) {
00708 numAuxVecs_ += MVT::GetNumberVecs(**i);
00709 }
00710
00711
00712 if (numAuxVecs_ > 0 && initialized_) {
00713 initialized_ = false;
00714 }
00715
00716 if (om_->isVerbosity( Debug ) ) {
00717 CheckList chk;
00718 chk.checkQ = true;
00719 om_->print( Debug, accuracyCheck(chk, ": in setAuxVecs()") );
00720 }
00721 }
00722
00723
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 template <class ScalarType, class MV, class OP>
00739 void BlockDavidson<ScalarType,MV,OP>::initialize(BlockDavidsonState<ScalarType,MV> state)
00740 {
00741
00742
00743 std::vector<int> bsind(blockSize_);
00744 for (int i=0; i<blockSize_; i++) bsind[i] = i;
00745
00746 Teuchos::BLAS<int,ScalarType> blas;
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 if (state.V != Teuchos::null && state.KK != Teuchos::null) {
00767 TEST_FOR_EXCEPTION( MVT::GetVecLength(*state.V) != MVT::GetVecLength(*V_),
00768 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Vector length of V not correct." );
00769 TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*state.V) < blockSize_,
00770 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Specified V must have at least block size vectors.");
00771 TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*state.V) > blockSize_*numBlocks_,
00772 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Number of vectors in V must be less than getMaxSubspaceDim().");
00773
00774 curDim_ = MVT::GetNumberVecs(*state.V);
00775
00776 curDim_ = (int)(curDim_ / blockSize_)*blockSize_;
00777
00778 TEST_FOR_EXCEPTION( curDim_ != MVT::GetNumberVecs(*state.V),
00779 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Number of vectors in V must be a multiple of getBlockSize().");
00780
00781
00782 TEST_FOR_EXCEPTION(state.KK->numRows() != curDim_ || state.KK->numCols() != curDim_, std::invalid_argument,
00783 "Anasazi::BlockDavidson::initialize(): Size of KK must be consistent with size of V.");
00784
00785 std::vector<int> nevind(curDim_);
00786 for (int i=0; i<curDim_; i++) nevind[i] = i;
00787
00788
00789 MVT::SetBlock(*state.V,nevind,*V_);
00790
00791
00792
00793 Teuchos::RefCountPtr<MV> lclV, lclKV, lclMV;
00794
00795 lclV = MVT::CloneView(*V_,nevind);
00796
00797
00798 Teuchos::RefCountPtr<Teuchos::SerialDenseMatrix<int,ScalarType> > lclKK;
00799 lclKK = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(Teuchos::View,*KK_,curDim_,curDim_) );
00800 lclKK->assign(*state.KK);
00801
00802
00803 for (int j=0; j<curDim_; j++) {
00804 for (int i=j+1; i<curDim_; i++) {
00805 (*lclKK)(i,j) = SCT::conjugate((*lclKK)(j,i));
00806 }
00807 }
00808
00809
00810 if (state.X != Teuchos::null && state.T != Teuchos::null) {
00811 TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*state.X) != blockSize_ || MVT::GetVecLength(*state.X) != MVT::GetVecLength(*X_),
00812 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Size of X must be consistent with block size and length of V.");
00813 TEST_FOR_EXCEPTION((signed int)(state.T->size()) != curDim_,
00814 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Size of T must be consistent with dimension of V.");
00815 MVT::SetBlock(*state.X,bsind,*X_);
00816 std::copy(state.T->begin(),state.T->end(),theta_.begin());
00817
00818
00819 for (int i=0; i<curDim_; i++) ritz2norms_[i] = NANVAL;
00820 }
00821 else {
00822
00823 Teuchos::SerialDenseMatrix<int,ScalarType> S(curDim_,curDim_);
00824 {
00825 Teuchos::TimeMonitor lcltimer( *timerDS_ );
00826 int rank = curDim_;
00827 MSUtils_.directSolver(curDim_, *lclKK, 0, &S, &theta_, &rank, 10);
00828
00829 TEST_FOR_EXCEPTION(rank != curDim_,BlockDavidsonInitFailure,
00830 "Anasazi::BlockDavidson::initialize(): Not enough Ritz vectors to initialize algorithm.");
00831 }
00832
00833 {
00834 Teuchos::TimeMonitor lcltimer( *timerSortEval_ );
00835
00836 std::vector<int> order(curDim_);
00837
00838
00839 sm_->sort( this, curDim_, theta_, &order );
00840
00841
00842 MSUtils_.permuteVectors(order,S);
00843 }
00844
00845 {
00846 Teuchos::BLAS<int,ScalarType> blas;
00847 Teuchos::SerialDenseMatrix<int,ScalarType> R(curDim_,curDim_), T(curDim_,curDim_);
00848
00849 for (int i=0; i<curDim_; i++) T(i,i) = theta_[i];
00850 int info = R.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,S,T,ZERO);
00851 TEST_FOR_EXCEPTION(info != 0, std::logic_error, "Anasazi::BlockDavidson::initialize(): Input error to SerialDenseMatrix::multiply.");
00852 info = R.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,-ONE,*lclKK,S,ONE);
00853 TEST_FOR_EXCEPTION(info != 0, std::logic_error, "Anasazi::BlockDavidson::initialize(): Input error to SerialDenseMatrix::multiply.");
00854 for (int i=0; i<curDim_; i++) {
00855 ritz2norms_[i] = blas.NRM2(curDim_,R[i],1);
00856 }
00857 }
00858
00859
00860 Teuchos::SerialDenseMatrix<int,ScalarType> S1(Teuchos::View,S,curDim_,blockSize_);
00861 {
00862 Teuchos::TimeMonitor lcltimer( *timerLocal_ );
00863
00864
00865 MVT::MvTimesMatAddMv( ONE, *lclV, S1, ZERO, *X_ );
00866 }
00867
00868 state.KX = Teuchos::null;
00869 state.MX = Teuchos::null;
00870 }
00871
00872
00873 lclV = Teuchos::null;
00874 lclKK = Teuchos::null;
00875
00876
00877 if ( state.KX != Teuchos::null && (!hasM_ || state.MX != Teuchos::null) ) {
00878 TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*state.KX) != blockSize_ || MVT::GetVecLength(*state.KX) != MVT::GetVecLength(*X_),
00879 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Size of KX must be consistent with block size and length of X.");
00880 if (hasM_) {
00881 TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*state.MX) != blockSize_ || MVT::GetVecLength(*state.KX) != MVT::GetVecLength(*X_),
00882 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Size of MX must be consistent with block size and length of X.");
00883 }
00884 MVT::SetBlock(*state.KX,bsind,*KX_);
00885 if (hasM_) {
00886 MVT::SetBlock(*state.MX,bsind,*MX_);
00887 }
00888 }
00889 else {
00890
00891 {
00892 Teuchos::TimeMonitor lcltimer( *timerOp_ );
00893 OPT::Apply(*Op_,*X_,*KX_);
00894 count_ApplyOp_ += blockSize_;
00895 }
00896 if (hasM_) {
00897 Teuchos::TimeMonitor lcltimer( *timerMOp_ );
00898 OPT::Apply(*MOp_,*X_,*MX_);
00899 count_ApplyM_ += blockSize_;
00900 }
00901 else {
00902 MX_ = X_;
00903 }
00904
00905
00906 state.R = Teuchos::null;
00907 }
00908
00909
00910 if (state.R != Teuchos::null) {
00911 TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*state.R) != blockSize_ || MVT::GetVecLength(*state.R) != MVT::GetVecLength(*X_),
00912 std::invalid_argument, "Anasazi::BlockDavidson::initialize(): Size of R must be consistent with block size and length of X.");
00913 MVT::SetBlock(*state.R,bsind,*R_);
00914 }
00915 else {
00916 Teuchos::TimeMonitor lcltimer( *timerCompRes_ );
00917
00918
00919 MVT::MvAddMv(ZERO,*KX_,ONE,*KX_,*R_);
00920 Teuchos::SerialDenseMatrix<int,ScalarType> T(blockSize_,blockSize_);
00921 T.putScalar(ZERO);
00922 for (int i=0; i<blockSize_; i++) T(i,i) = theta_[i];
00923 MVT::MvTimesMatAddMv(-ONE,*MX_,T,ONE,*R_);
00924
00925 }
00926
00927
00928 Rnorms_current_ = false;
00929 R2norms_current_ = false;
00930
00931
00932 initialized_ = true;
00933
00934 if (om_->isVerbosity( Debug ) ) {
00935
00936 CheckList chk;
00937 chk.checkV = true;
00938 chk.checkX = true;
00939 chk.checkKX = true;
00940 chk.checkMX = true;
00941 chk.checkR = true;
00942 chk.checkQ = true;
00943 chk.checkKK = true;
00944 om_->print( Debug, accuracyCheck(chk, ": after initialize()") );
00945 }
00946
00947
00948 if (om_->isVerbosity(Debug)) {
00949 currentStatus( om_->stream(Debug) );
00950 }
00951 else if (om_->isVerbosity(IterationDetails)) {
00952 currentStatus( om_->stream(IterationDetails) );
00953 }
00954 }
00955 else {
00956
00957
00958 Teuchos::RefCountPtr<const MV> ivec = problem_->getInitVec();
00959 TEST_FOR_EXCEPTION(ivec == Teuchos::null,std::invalid_argument,
00960 "Anasazi::BlockDavdison::initialize(): Eigenproblem did not specify initial vectors to clone from.");
00961
00962 int lclDim = MVT::GetNumberVecs(*ivec);
00963
00964 lclDim = (int)(lclDim / blockSize_)*blockSize_;
00965 bool userand = false;
00966 if (lclDim < blockSize_) {
00967
00968
00969 userand = true;
00970 lclDim = blockSize_;
00971 }
00972
00973
00974 std::vector<int> dimind(lclDim);
00975 for (int i=0; i<lclDim; i++) dimind[i] = i;
00976
00977
00978 Teuchos::RefCountPtr<MV> newMV,
00979 newKV = MVT::Clone(*ivec,lclDim),
00980 newV = MVT::Clone(*ivec,lclDim);
00981 if (userand) {
00982 MVT::MvRandom(*newV);
00983 }
00984 else {
00985
00986 MVT::SetBlock(*ivec,dimind,*newV);
00987 }
00988
00989
00990 if (hasM_) {
00991 newMV = MVT::Clone(*newV,lclDim);
00992 {
00993 Teuchos::TimeMonitor lcltimer( *timerMOp_ );
00994 OPT::Apply(*MOp_,*newV,*newMV);
00995 count_ApplyM_ += lclDim;
00996 }
00997 }
00998 else {
00999 newMV = Teuchos::null;
01000 }
01001
01002
01003 if (auxVecs_.size() > 0) {
01004 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
01005
01006 Teuchos::Array<Teuchos::RefCountPtr<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummy;
01007 int rank = orthman_->projectAndNormalize(*newV,newMV,dummy,Teuchos::null,auxVecs_);
01008 TEST_FOR_EXCEPTION(rank != lclDim,BlockDavidsonInitFailure,
01009 "Anasazi::BlockDavidson::initialize(): Couldn't generate initial basis of full rank.");
01010 }
01011 else {
01012 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
01013
01014 int rank = orthman_->normalize(*newV,newMV,Teuchos::null);
01015 TEST_FOR_EXCEPTION(rank != lclDim,BlockDavidsonInitFailure,
01016 "Anasazi::BlockDavidson::initialize(): Couldn't generate initial basis of full rank.");
01017 }
01018
01019
01020 {
01021 Teuchos::TimeMonitor lcltimer( *timerOp_ );
01022 OPT::Apply(*Op_,*newV,*newKV);
01023 count_ApplyOp_ += lclDim;
01024 }
01025
01026
01027 Teuchos::RefCountPtr< Teuchos::SerialDenseMatrix<int,ScalarType> > KK;
01028 KK = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(lclDim,lclDim) );
01029 MVT::MvTransMv(ONE,*newV,*newKV,*KK);
01030
01031
01032 newKV = newMV = Teuchos::null;
01033
01034
01035 BlockDavidsonState<ScalarType,MV> newstate;
01036 newstate.V = newV;
01037 newstate.KK = KK;
01038 initialize(newstate);
01039 }
01040 }
01041
01042
01044
01045 template <class ScalarType, class MV, class OP>
01046 void BlockDavidson<ScalarType,MV,OP>::initialize()
01047 {
01048 BlockDavidsonState<ScalarType,MV> empty;
01049 initialize(empty);
01050 }
01051
01052
01054
01055 template <class ScalarType, class MV, class OP>
01056 void BlockDavidson<ScalarType,MV,OP>::iterate ()
01057 {
01058
01059
01060 if (initialized_ == false) {
01061 initialize();
01062 }
01063
01064
01065
01066 const int searchDim = blockSize_*numBlocks_;
01067
01068 Teuchos::BLAS<int,ScalarType> blas;
01069
01070
01071
01072
01073 Teuchos::SerialDenseMatrix<int,ScalarType> S( searchDim, searchDim );
01074
01075
01077
01078
01079 while (tester_->checkStatus(this) != Passed && curDim_ < searchDim) {
01080
01081
01082 if (om_->isVerbosity(Debug)) {
01083 currentStatus( om_->stream(Debug) );
01084 }
01085 else if (om_->isVerbosity(IterationDetails)) {
01086 currentStatus( om_->stream(IterationDetails) );
01087 }
01088
01089 iter_++;
01090
01091
01092 std::vector<int> curind(blockSize_);
01093 for (int i=0; i<blockSize_; i++) curind[i] = curDim_ + i;
01094 H_ = MVT::CloneView(*V_,curind);
01095
01096
01097
01098 if (Prec_ != Teuchos::null) {
01099 Teuchos::TimeMonitor lcltimer( *timerPrec_ );
01100 OPT::Apply( *Prec_, *R_, *H_ );
01101 count_ApplyPrec_ += blockSize_;
01102 }
01103 else {
01104 std::vector<int> bsind(blockSize_);
01105 for (int i=0; i<blockSize_; i++) { bsind[i] = i; }
01106 MVT::SetBlock(*R_,bsind,*H_);
01107 }
01108
01109
01110 if (hasM_) {
01111
01112 MH_ = MX_;
01113 Teuchos::TimeMonitor lcltimer( *timerMOp_ );
01114 OPT::Apply( *MOp_, *H_, *MH_);
01115 count_ApplyM_ += blockSize_;
01116 }
01117 else {
01118 MH_ = H_;
01119 }
01120
01121
01122
01123 std::vector<int> prevind(curDim_);
01124 for (int i=0; i<curDim_; i++) prevind[i] = i;
01125 Teuchos::RefCountPtr<MV> Vprev = MVT::CloneView(*V_,prevind);
01126
01127
01128 {
01129 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
01130
01131 Teuchos::Array<Teuchos::RefCountPtr<const MV> > against = auxVecs_;
01132 against.push_back(Vprev);
01133 int rank = orthman_->projectAndNormalize(*H_,MH_,
01134 Teuchos::tuple<Teuchos::RefCountPtr<Teuchos::SerialDenseMatrix<int,ScalarType> > >(Teuchos::null),
01135 Teuchos::null,against);
01136 TEST_FOR_EXCEPTION(rank != blockSize_,BlockDavidsonOrthoFailure,
01137 "Anasazi::BlockDavidson::iterate(): unable to compute full basis for H.");
01138 }
01139
01140
01141 {
01142
01143 KH_ = KX_;
01144 Teuchos::TimeMonitor lcltimer( *timerOp_ );
01145 OPT::Apply( *Op_, *H_, *KH_);
01146 count_ApplyOp_ += blockSize_;
01147 }
01148
01149 if (om_->isVerbosity( Debug ) ) {
01150 CheckList chk;
01151 chk.checkH = true;
01152 chk.checkMH = true;
01153 chk.checkKH = true;
01154 om_->print( Debug, accuracyCheck(chk, ": after ortho H") );
01155 }
01156 else if (om_->isVerbosity( OrthoDetails ) ) {
01157 CheckList chk;
01158 chk.checkH = true;
01159 chk.checkMH = true;
01160 chk.checkKH = true;
01161 om_->print( OrthoDetails, accuracyCheck(chk,": after ortho H") );
01162 }
01163
01164
01165
01166 Teuchos::RefCountPtr<Teuchos::SerialDenseMatrix<int,ScalarType> > nextKK;
01167
01168 nextKK = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(Teuchos::View,*KK_,curDim_,blockSize_,0,curDim_) );
01169 MVT::MvTransMv(ONE,*Vprev,*KH_,*nextKK);
01170
01171 nextKK = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(Teuchos::View,*KK_,blockSize_,blockSize_,curDim_,curDim_) );
01172 MVT::MvTransMv(ONE,*H_,*KH_,*nextKK);
01173
01174
01175 nextKK = Teuchos::null;
01176 for (int i=curDim_; i<curDim_+blockSize_; i++) {
01177 for (int j=0; j<i; j++) {
01178 (*KK_)(i,j) = SCT::conjugate((*KK_)(j,i));
01179 }
01180 }
01181
01182
01183 curDim_ += blockSize_;
01184 H_ = KH_ = MH_ = Teuchos::null;
01185 Vprev = Teuchos::null;
01186
01187 if (om_->isVerbosity( Debug ) ) {
01188 CheckList chk;
01189 chk.checkKK = true;
01190 om_->print( Debug, accuracyCheck(chk, ": after expanding KK") );
01191 }
01192
01193
01194 curind.resize(curDim_);
01195 for (int i=0; i<curDim_; i++) curind[i] = i;
01196 Teuchos::RefCountPtr<const MV> curV = MVT::CloneView(*V_,curind);
01197
01198
01199 {
01200 Teuchos::TimeMonitor lcltimer(*timerDS_);
01201 int nevlocal = curDim_;
01202 int info = MSUtils_.directSolver(curDim_,*KK_,0,&S,&theta_,&nevlocal,10);
01203 TEST_FOR_EXCEPTION(info != 0,std::logic_error,"Anasazi::BlockDavidson::iterate(): direct solve returned error code.");
01204
01205 TEST_FOR_EXCEPTION(nevlocal != curDim_,std::logic_error,"Anasazi::BlockDavidson::iterate(): direct solve did not compute all eigenvectors.");
01206 }
01207
01208
01209 {
01210 Teuchos::TimeMonitor lcltimer( *timerSortEval_ );
01211
01212 std::vector<int> order(curDim_);
01213
01214
01215 sm_->sort( this, curDim_, theta_, &order );
01216
01217
01218 Teuchos::SerialDenseMatrix<int,ScalarType> curS(Teuchos::View,S,curDim_,curDim_);
01219 MSUtils_.permuteVectors(order,curS);
01220 }
01221
01222
01223 {
01224 Teuchos::BLAS<int,ScalarType> blas;
01225 Teuchos::SerialDenseMatrix<int,ScalarType> R(curDim_,curDim_), T(curDim_,curDim_);
01226 Teuchos::SerialDenseMatrix<int,ScalarType> curKK(Teuchos::View,*KK_,curDim_,curDim_),
01227 curS(Teuchos::View,S,curDim_,curDim_);
01228
01229 for (int i=0; i<curDim_; i++) T(i,i) = theta_[i];
01230 int info = R.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,curS,T,ZERO);
01231 TEST_FOR_EXCEPTION(info != 0, std::logic_error, "Anasazi::BlockDavidson::iterate(): Input error to SerialDenseMatrix::multiply.");
01232 info = R.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,-ONE,curKK,curS,ONE);
01233 TEST_FOR_EXCEPTION(info != 0, std::logic_error, "Anasazi::BlockDavidson::iterate(): Input error to SerialDenseMatrix::multiply.");
01234 for (int i=0; i<curDim_; i++) {
01235 ritz2norms_[i] = blas.NRM2(curDim_,R[i],1);
01236 }
01237 }
01238
01239
01240 Teuchos::SerialDenseMatrix<int,ScalarType> S1( Teuchos::View, S, curDim_, blockSize_ );
01241
01242
01243 {
01244 Teuchos::TimeMonitor lcltimer( *timerLocal_ );
01245 MVT::MvTimesMatAddMv(ONE,*curV,S1,ZERO,*X_);
01246 }
01247
01248
01249 {
01250 Teuchos::TimeMonitor lcltimer( *timerOp_ );
01251 OPT::Apply( *Op_, *X_, *KX_);
01252 count_ApplyOp_ += blockSize_;
01253 }
01254
01255 if (hasM_) {
01256 Teuchos::TimeMonitor lcltimer( *timerMOp_ );
01257 OPT::Apply(*MOp_,*X_,*MX_);
01258 count_ApplyM_ += blockSize_;
01259 }
01260 else {
01261 MX_ = X_;
01262 }
01263
01264
01265
01266 {
01267 Teuchos::TimeMonitor lcltimer( *timerCompRes_ );
01268
01269 MVT::MvAddMv( ONE, *KX_, ZERO, *KX_, *R_ );
01270 Teuchos::SerialDenseMatrix<int,ScalarType> T( blockSize_, blockSize_ );
01271 for (int i = 0; i < blockSize_; i++) {
01272 T(i,i) = theta_[i];
01273 }
01274 MVT::MvTimesMatAddMv( -ONE, *MX_, T, ONE, *R_ );
01275 }
01276
01277
01278 Rnorms_current_ = false;
01279 R2norms_current_ = false;
01280
01281
01282
01283 if (om_->isVerbosity( Debug ) ) {
01284
01285 CheckList chk;
01286 chk.checkV = true;
01287 chk.checkX = true;
01288 chk.checkKX = true;
01289 chk.checkMX = true;
01290 chk.checkR = true;
01291 om_->print( Debug, accuracyCheck(chk, ": after local update") );
01292 }
01293 else if (om_->isVerbosity( OrthoDetails )) {
01294 CheckList chk;
01295 chk.checkX = true;
01296 chk.checkKX = true;
01297 chk.checkMX = true;
01298 chk.checkR = true;
01299 om_->print( OrthoDetails, accuracyCheck(chk, ": after local update") );
01300 }
01301 }
01302
01303 }
01304
01305
01306
01308
01309 template <class ScalarType, class MV, class OP>
01310 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
01311 BlockDavidson<ScalarType,MV,OP>::getResNorms() {
01312 if (Rnorms_current_ == false) {
01313
01314 orthman_->norm(*R_,&Rnorms_);
01315 Rnorms_current_ = true;
01316 }
01317 return Rnorms_;
01318 }
01319
01320
01322
01323 template <class ScalarType, class MV, class OP>
01324 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
01325 BlockDavidson<ScalarType,MV,OP>::getRes2Norms() {
01326 if (R2norms_current_ == false) {
01327
01328 MVT::MvNorm(*R_,&R2norms_);
01329 R2norms_current_ = true;
01330 }
01331 return R2norms_;
01332 }
01333
01334
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361 template <class ScalarType, class MV, class OP>
01362 std::string BlockDavidson<ScalarType,MV,OP>::accuracyCheck( const CheckList &chk, const string &where ) const
01363 {
01364 stringstream os;
01365 os.precision(2);
01366 os.setf(ios::scientific, ios::floatfield);
01367 MagnitudeType tmp;
01368
01369 os << " Debugging checks: iteration " << iter_ << where << endl;
01370
01371
01372 std::vector<int> lclind(curDim_);
01373 for (int i=0; i<curDim_; i++) lclind[i] = i;
01374 Teuchos::RefCountPtr<MV> lclV,lclKV;
01375 if (initialized_) {
01376 lclV = MVT::CloneView(*V_,lclind);
01377 }
01378 if (chk.checkV && initialized_) {
01379 tmp = orthman_->orthonormError(*lclV);
01380 os << " >> Error in V^H M V == I : " << tmp << endl;
01381 for (unsigned int i=0; i<auxVecs_.size(); i++) {
01382 tmp = orthman_->orthogError(*lclV,*auxVecs_[i]);
01383 os << " >> Error in V^H M Q[" << i << "] == 0 : " << tmp << endl;
01384 }
01385 Teuchos::SerialDenseMatrix<int,ScalarType> curKK(curDim_,curDim_);
01386 Teuchos::RefCountPtr<MV> lclKV = MVT::Clone(*V_,curDim_);
01387 OPT::Apply(*Op_,*lclV,*lclKV);
01388 MVT::MvTransMv(ONE,*lclV,*lclKV,curKK);
01389 Teuchos::SerialDenseMatrix<int,ScalarType> subKK(Teuchos::View,*KK_,curDim_,curDim_);
01390 curKK -= subKK;
01391
01392 for (int j=0; j<curDim_; j++) {
01393 for (int i=j+1; i<curDim_; i++) {
01394 curKK(i,j) = curKK(j,i);
01395 }
01396 }
01397 os << " >> Error in V^H K V == KK : " << curKK.normFrobenius() << endl;
01398 }
01399
01400
01401 if (chk.checkX && initialized_) {
01402 tmp = orthman_->orthonormError(*X_);
01403 os << " >> Error in X^H M X == I : " << tmp << endl;
01404 for (unsigned int i=0; i<auxVecs_.size(); i++) {
01405 tmp = orthman_->orthogError(*X_,*auxVecs_[i]);
01406 os << " >> Error in X^H M Q[" << i << "] == 0 : " << tmp << endl;
01407 }
01408 }
01409 if (chk.checkMX && hasM_ && initialized_) {
01410 tmp = MSUtils_.errorEquality(X_.get(), MX_.get(), MOp_.get());
01411 os << " >> Error in MX == M*X : " << tmp << endl;
01412 }
01413 if (chk.checkKX && initialized_) {
01414 tmp = MSUtils_.errorEquality(X_.get(), KX_.get(), Op_.get());
01415 os << " >> Error in KX == K*X : " << tmp << endl;
01416 }
01417
01418
01419 if (chk.checkH && initialized_) {
01420 tmp = orthman_->orthonormError(*H_);
01421 os << " >> Error in H^H M H == I : " << tmp << endl;
01422 tmp = orthman_->orthogError(*H_,*lclV);
01423 os << " >> Error in H^H M V == 0 : " << tmp << endl;
01424 tmp = orthman_->orthogError(*H_,*X_);
01425 os << " >> Error in H^H M X == 0 : " << tmp << endl;
01426 for (unsigned int i=0; i<auxVecs_.size(); i++) {
01427 tmp = orthman_->orthogError(*H_,*auxVecs_[i]);
01428 os << " >> Error in H^H M Q[" << i << "] == 0 : " << tmp << endl;
01429 }
01430 }
01431 if (chk.checkKH && initialized_) {
01432 tmp = MSUtils_.errorEquality(H_.get(), KH_.get(), Op_.get());
01433 os << " >> Error in KH == K*H : " << tmp << endl;
01434 }
01435 if (chk.checkMH && hasM_ && initialized_) {
01436 tmp = MSUtils_.errorEquality(H_.get(), MH_.get(), MOp_.get());
01437 os << " >> Error in MH == M*H : " << tmp << endl;
01438 }
01439
01440
01441 if (chk.checkR && initialized_) {
01442 Teuchos::SerialDenseMatrix<int,ScalarType> xTx(blockSize_,blockSize_);
01443 MVT::MvTransMv(ONE,*X_,*R_,xTx);
01444 tmp = xTx.normFrobenius();
01445 os << " >> Error in X^H R == 0 : " << tmp << endl;
01446 }
01447
01448
01449 if (chk.checkKK && initialized_) {
01450 Teuchos::SerialDenseMatrix<int,ScalarType> tmp(curDim_,curDim_), lclKK(Teuchos::View,*KK_,curDim_,curDim_);
01451 for (int j=0; j<curDim_; j++) {
01452 for (int i=0; i<curDim_; i++) {
01453 tmp(i,j) = lclKK(i,j) - SCT::conjugate(lclKK(j,i));
01454 }
01455 }
01456 os << " >> Error in KK - KK^H == 0 : " << tmp.normFrobenius() << endl;
01457 }
01458
01459
01460 if (chk.checkQ) {
01461 for (unsigned int i=0; i<auxVecs_.size(); i++) {
01462 tmp = orthman_->orthonormError(*auxVecs_[i]);
01463 os << " >> Error in Q[" << i << "]^H M Q[" << i << "] == I : " << tmp << endl;
01464 for (unsigned int j=i+1; j<auxVecs_.size(); j++) {
01465 tmp = orthman_->orthogError(*auxVecs_[i],*auxVecs_[j]);
01466 os << " >> Error in Q[" << i << "]^H M Q[" << j << "] == 0 : " << tmp << endl;
01467 }
01468 }
01469 }
01470
01471 os << endl;
01472
01473 return os.str();
01474 }
01475
01476
01478
01479 template <class ScalarType, class MV, class OP>
01480 void
01481 BlockDavidson<ScalarType,MV,OP>::currentStatus(ostream &os)
01482 {
01483 os.setf(ios::scientific, ios::floatfield);
01484 os.precision(6);
01485 os <<endl;
01486 os <<"================================================================================" << endl;
01487 os << endl;
01488 os <<" BlockDavidson Solver Status" << endl;
01489 os << endl;
01490 os <<"The solver is "<<(initialized_ ? "initialized." : "not initialized.") << endl;
01491 os <<"The number of iterations performed is " <<iter_<<endl;
01492 os <<"The block size is " << blockSize_<<endl;
01493 os <<"The number of blocks is " << numBlocks_<<endl;
01494 os <<"The current basis size is " << curDim_<<endl;
01495 os <<"The number of auxiliary vectors is " << numAuxVecs_ << endl;
01496 os <<"The number of operations Op*x is "<<count_ApplyOp_<<endl;
01497 os <<"The number of operations M*x is "<<count_ApplyM_<<endl;
01498 os <<"The number of operations Prec*x is "<<count_ApplyPrec_<<endl;
01499
01500 os.setf(ios_base::right, ios_base::adjustfield);
01501
01502 if (initialized_) {
01503 os << endl;
01504 os <<"CURRENT EIGENVALUE ESTIMATES "<<endl;
01505 os << std::setw(20) << "Eigenvalue"
01506 << std::setw(20) << "Residual(M)"
01507 << std::setw(20) << "Residual(2)"
01508 << endl;
01509 os <<"--------------------------------------------------------------------------------"<<endl;
01510 for (int i=0; i<blockSize_; i++) {
01511 os << std::setw(20) << theta_[i];
01512 if (Rnorms_current_) os << std::setw(20) << Rnorms_[i];
01513 else os << std::setw(20) << "not current";
01514 if (R2norms_current_) os << std::setw(20) << R2norms_[i];
01515 else os << std::setw(20) << "not current";
01516 os << endl;
01517 }
01518 }
01519 os <<"================================================================================" << endl;
01520 os << endl;
01521 }
01522
01523 }
01524
01525 #endif
01526
01527