42 #ifndef BELOS_PCPG_ITER_HPP
43 #define BELOS_PCPG_ITER_HPP
87 template <
class ScalarType,
class MV>
124 R(Teuchos::null),
Z(Teuchos::null),
125 P(Teuchos::null),
AP(Teuchos::null),
126 U(Teuchos::null),
C(Teuchos::null),
184 template<
class ScalarType,
class MV,
class OP>
315 if (!initialized_)
return 0;
321 if (!initialized_)
return 0;
345 "Belos::PCPGIter::setBlockSize(): Cannot use a block size that is not one.");
349 void setSize(
int savedBlocks );
391 bool stateStorageInitialized_;
436 template<
class ScalarType,
class MV,
class OP>
448 stateStorageInitialized_(false),
449 keepDiagonal_(false),
450 initDiagonal_(false),
458 "Belos::PCPGIter::constructor: mandatory parameter \"Saved Blocks\" is not specified.");
459 int rb = Teuchos::getParameter<int>(params,
"Saved Blocks");
462 keepDiagonal_ = params.
get(
"Keep Diagonal",
false);
465 initDiagonal_ = params.
get(
"Initialize Diagonal",
false);
473 template <
class ScalarType,
class MV,
class OP>
479 TEUCHOS_TEST_FOR_EXCEPTION(savedBlocks <= 0, std::invalid_argument,
"Belos::PCPGIter::setSize() was passed a non-positive argument for \"Num Saved Blocks\".");
481 if ( savedBlocks_ != savedBlocks) {
482 stateStorageInitialized_ =
false;
483 savedBlocks_ = savedBlocks;
484 initialized_ =
false;
493 template <
class ScalarType,
class MV,
class OP>
496 stateStorageInitialized_ =
false;
497 initialized_ =
false;
505 template <
class ScalarType,
class MV,
class OP>
508 if (!stateStorageInitialized_) {
513 if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) {
520 int newsd = savedBlocks_ ;
525 if (Z_ == Teuchos::null) {
527 Z_ = MVT::Clone( *tmp, 1 );
529 if (P_ == Teuchos::null) {
531 P_ = MVT::Clone( *tmp, 1 );
533 if (AP_ == Teuchos::null) {
535 AP_ = MVT::Clone( *tmp, 1 );
538 if (C_ == Teuchos::null) {
543 "Belos::PCPGIter::setStateSize(): linear problem does not specify multivectors to clone from.");
545 "Belos::PCPGIter::setStateSize(): prevUdim not zero and C is null.");
546 C_ = MVT::Clone( *tmp, savedBlocks_ );
550 if (MVT::GetNumberVecs(*C_) < savedBlocks_ ) {
552 C_ = MVT::Clone( *tmp, savedBlocks_ );
555 if (U_ == Teuchos::null) {
558 "Belos::PCPGIter::setStateSize(): prevUdim not zero and U is null.");
559 U_ = MVT::Clone( *tmp, savedBlocks_ );
563 if (MVT::GetNumberVecs(*U_) < savedBlocks_ ) {
565 U_ = MVT::Clone( *tmp, savedBlocks_ );
569 if (D_ == Teuchos::null) {
573 D_->shape( newsd, newsd );
576 if (D_->numRows() < newsd || D_->numCols() < newsd) {
577 D_->shapeUninitialized( newsd, newsd );
582 stateStorageInitialized_ =
true;
589 template <
class ScalarType,
class MV,
class OP>
594 "Belos::PCPGIter::initialize(): Cannot initialize state storage!");
598 std::string errstr(
"Belos::PCPGIter::initialize(): Specified multivectors must have a consistent length and width.");
600 if (newstate.
R != Teuchos::null){
603 if (newstate.
U == Teuchos::null){
609 prevUdim_ = newstate.
curDim;
610 if (newstate.
C == Teuchos::null){
611 std::vector<int> index(prevUdim_);
612 for (
int i=0; i< prevUdim_; ++i)
615 newstate.
C = MVT::Clone( *newstate.
U, prevUdim_ );
617 lp_->apply( *Ukeff, *Ckeff );
619 curDim_ = prevUdim_ ;
623 if (!stateStorageInitialized_)
630 newstate.
curDim = curDim_;
634 std::vector<int> zero_index(1);
636 if ( lp_->getLeftPrec() != Teuchos::null ) {
637 lp_->applyLeftPrec( *R_, *Z_ );
638 MVT::SetBlock( *Z_, zero_index , *P_ );
641 MVT::SetBlock( *R_, zero_index, *P_ );
644 std::vector<int> nextind(1);
645 nextind[0] = curDim_;
647 MVT::SetBlock( *P_, nextind, *newstate.
U );
650 newstate.
curDim = curDim_;
653 std::invalid_argument, errstr );
654 if (newstate.
U != U_) {
659 std::invalid_argument, errstr );
660 if (newstate.
C != C_) {
667 "Belos::PCPGIter::initialize(): PCPGStateIterState does not have initial kernel R_0.");
677 template <
class ScalarType,
class MV,
class OP>
683 if (initialized_ ==
false) {
686 const bool debug =
false;
695 std::cout <<
" Iterate Warning: begin from nonzero iter_ ?" << std::endl;
698 std::vector<int> prevInd;
704 prevInd.resize( prevUdim_ );
705 for(
int i=0; i<prevUdim_ ; i++) prevInd[i] = i;
707 Uprev = MVT::CloneView(*U_, prevInd);
708 Cprev = MVT::CloneView(*C_, prevInd);
716 "Belos::CGIter::iterate(): current linear system has more than one std::vector!" );
720 "Belos::CGIter::iterate(): mistake in initialization !" );
727 std::vector<int> curind(1);
728 std::vector<ScalarType> rnorm(MVT::GetNumberVecs(*cur_soln_vec));
731 curind[0] = curDim_ - 1;
732 P = MVT::CloneViewNonConst(*U_,curind);
733 MVT::MvTransMv( one, *Cprev, *P, CZ );
734 MVT::MvTimesMatAddMv( -one, *Uprev, CZ, one, *P );
737 MVT::MvTransMv( one, *Cprev, *P, CZ );
738 std::cout <<
" Input CZ post ortho " << std::endl;
739 CZ.
print( std::cout );
741 if( curDim_ == savedBlocks_ ){
742 std::vector<int> zero_index(1);
744 MVT::SetBlock( *P, zero_index, *P_ );
750 MVT::MvTransMv( one, *R_, *Z_, rHz );
755 while (stest_->checkStatus(
this) !=
Passed ) {
760 curind[0] = curDim_ - 1;
762 MVT::MvNorm(*R_, rnorm);
763 std::cout << iter_ <<
" " << curDim_ <<
" " << rnorm[0] << std::endl;
765 if( prevUdim_ + iter_ < savedBlocks_ ){
766 P = MVT::CloneView(*U_,curind);
767 AP = MVT::CloneViewNonConst(*C_,curind);
768 lp_->applyOp( *P, *AP );
769 MVT::MvTransMv( one, *P, *AP, pAp );
771 if( prevUdim_ + iter_ == savedBlocks_ ){
772 AP = MVT::CloneViewNonConst(*C_,curind);
773 lp_->applyOp( *P_, *AP );
774 MVT::MvTransMv( one, *P_, *AP, pAp );
776 lp_->applyOp( *P_, *AP_ );
777 MVT::MvTransMv( one, *P_, *AP_, pAp );
781 if( keepDiagonal_ && prevUdim_ + iter_ <= savedBlocks_ )
782 (*D_)(iter_ -1 ,iter_ -1 ) = pAp(0,0);
786 "Belos::CGIter::iterate(): non-positive value for p^H*A*p encountered!" );
789 alpha(0,0) = rHz(0,0) / pAp(0,0);
793 "Belos::CGIter::iterate(): non-positive value for alpha encountered!" );
796 if( curDim_ < savedBlocks_ ){
797 MVT::MvAddMv( one, *cur_soln_vec, alpha(0,0), *P, *cur_soln_vec );
799 MVT::MvAddMv( one, *cur_soln_vec, alpha(0,0), *P_, *cur_soln_vec );
805 rHz_old(0,0) = rHz(0,0);
809 if( prevUdim_ + iter_ <= savedBlocks_ ){
810 MVT::MvAddMv( one, *R_, -alpha(0,0), *AP, *R_ );
813 MVT::MvAddMv( one, *R_, -alpha(0,0), *AP_, *R_ );
818 if ( lp_->getLeftPrec() != Teuchos::null ) {
819 lp_->applyLeftPrec( *R_, *Z_ );
824 MVT::MvTransMv( one, *R_, *Z_, rHz );
826 beta(0,0) = rHz(0,0) / rHz_old(0,0);
828 if( curDim_ < savedBlocks_ ){
830 curind[0] = curDim_ - 1;
832 MVT::MvAddMv( one, *Z_, beta(0,0), *P, *Pnext );
834 MVT::MvTransMv( one, *Cprev, *Z_, CZ );
835 MVT::MvTimesMatAddMv( -one, *Uprev, CZ, one, *Pnext );
837 std::cout <<
" Check CZ " << std::endl;
838 MVT::MvTransMv( one, *Cprev, *Pnext, CZ );
839 CZ.
print( std::cout );
843 if( curDim_ == savedBlocks_ ){
844 std::vector<int> zero_index(1);
846 MVT::SetBlock( *Pnext, zero_index, *P_ );
848 Pnext = Teuchos::null;
850 MVT::MvAddMv( one, *Z_, beta(0,0), *P_, *P_ );
852 MVT::MvTransMv( one, *Cprev, *Z_, CZ );
853 MVT::MvTimesMatAddMv( -one, *Uprev, CZ, one, *P_ );
856 std::cout <<
" Check CZ " << std::endl;
857 MVT::MvTransMv( one, *Cprev, *P_, CZ );
858 CZ.
print( std::cout );
867 TEUCHOS_TEST_FOR_EXCEPTION( AP != Teuchos::null || P != Teuchos::null, std::logic_error,
"Loop recurrence violated. Please contact Belos team.");
869 if( prevUdim_ + iter_ < savedBlocks_ ) --curDim_;