42 #ifndef BELOS_PSEUDO_BLOCK_STOCHASTIC_CG_ITER_HPP
43 #define BELOS_PSEUDO_BLOCK_STOCHASTIC_CG_ITER_HPP
60 #include "Teuchos_BLAS.hpp"
61 #include "Teuchos_SerialDenseMatrix.hpp"
62 #include "Teuchos_SerialDenseVector.hpp"
63 #include "Teuchos_SerialDenseHelpers.hpp"
64 #include "Teuchos_ScalarTraits.hpp"
65 #include "Teuchos_ParameterList.hpp"
66 #include "Teuchos_TimeMonitor.hpp"
85 template<
class ScalarType,
class MV,
class OP>
95 typedef Teuchos::ScalarTraits<ScalarType>
SCT;
109 Teuchos::ParameterList ¶ms );
219 TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
220 "Belos::PseudoBlockStochasticCGIter::setBlockSize(): Cannot use a block size that is not one.");
231 inline Teuchos::SerialDenseVector<int,ScalarType>& normal() {
235 const double p0 = -0.322232431088;
236 const double p1 = -1.0;
237 const double p2 = -0.342242088547;
238 const double p3 = -0.204231210245e-1;
239 const double p4 = -0.453642210148e-4;
240 const double q0 = 0.993484626060e-1;
241 const double q1 = 0.588581570495;
242 const double q2 = 0.531103462366;
243 const double q3 = 0.103537752850;
244 const double q4 = 0.38560700634e-2;
248 Teuchos::randomSyncedMatrix( randvec_ );
250 for (
int i=0; i<numRHS_; i++)
253 r=0.5*randvec_[i] + 1.0;
256 if(r < 0.5) y=std::sqrt(-2.0 * log(r));
257 else y=std::sqrt(-2.0 * log(1.0 - r));
259 p = p0 + y * (p1 + y* (p2 + y * (p3 + y * p4)));
260 q = q0 + y * (q1 + y* (q2 + y * (q3 + y * q4)));
262 if(r < 0.5) z = (p / q) - y;
263 else z = y - (p / q);
265 randvec_[i] = Teuchos::as<ScalarType,double>(z);
274 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > lp_;
275 const Teuchos::RCP<OutputManager<ScalarType> > om_;
276 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > stest_;
296 bool assertPositiveDefiniteness_;
311 Teuchos::RCP<MV> AP_;
317 Teuchos::SerialDenseVector<int,ScalarType> randvec_;
323 template<
class ScalarType,
class MV,
class OP>
327 Teuchos::ParameterList ¶ms ):
334 assertPositiveDefiniteness_( params.get(
"Assert Positive Definiteness", true) )
341 template <
class ScalarType,
class MV,
class OP>
345 Teuchos::RCP<const MV> lhsMV = lp_->getCurrLHSVec();
346 Teuchos::RCP<const MV> rhsMV = lp_->getCurrRHSVec();
347 TEUCHOS_TEST_FOR_EXCEPTION((lhsMV==Teuchos::null && rhsMV==Teuchos::null),std::invalid_argument,
348 "Belos::PseudoBlockStochasticCGIter::initialize(): Cannot initialize state storage!");
351 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
354 int numRHS = MVT::GetNumberVecs(*tmp);
359 if (Teuchos::is_null(R_) || MVT::GetNumberVecs(*R_)!=numRHS_) {
360 R_ = MVT::Clone( *tmp, numRHS_ );
361 Z_ = MVT::Clone( *tmp, numRHS_ );
362 P_ = MVT::Clone( *tmp, numRHS_ );
363 AP_ = MVT::Clone( *tmp, numRHS_ );
364 Y_ = MVT::Clone( *tmp, numRHS_ );
368 randvec_.size( numRHS_ );
372 std::string errstr(
"Belos::BlockPseudoStochasticCGIter::initialize(): Specified multivectors must have a consistent length and width.");
375 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
376 const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
378 if (!Teuchos::is_null(newstate.
R)) {
380 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate.
R) != MVT::GetGlobalLength(*R_),
381 std::invalid_argument, errstr );
382 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.
R) != numRHS_,
383 std::invalid_argument, errstr );
386 if (newstate.
R != R_) {
388 MVT::MvAddMv( one, *newstate.
R, zero, *newstate.
R, *R_ );
394 if ( lp_->getLeftPrec() != Teuchos::null ) {
395 lp_->applyLeftPrec( *R_, *Z_ );
396 if ( lp_->getRightPrec() != Teuchos::null ) {
397 Teuchos::RCP<MV> tmp2 = MVT::Clone( *Z_, numRHS_ );
398 lp_->applyRightPrec( *Z_, *tmp2 );
402 else if ( lp_->getRightPrec() != Teuchos::null ) {
403 lp_->applyRightPrec( *R_, *Z_ );
408 MVT::MvAddMv( one, *Z_, zero, *Z_, *P_ );
412 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::is_null(newstate.
R),std::invalid_argument,
413 "Belos::StochasticCGIter::initialize(): CGStateIterState does not have initial residual.");
423 template <
class ScalarType,
class MV,
class OP>
429 if (initialized_ ==
false) {
435 std::vector<int> index(1);
436 std::vector<ScalarType> rHz( numRHS_ ), rHz_old( numRHS_ ), pAp( numRHS_ );
437 Teuchos::SerialDenseMatrix<int, ScalarType> alpha( numRHS_,numRHS_ ), beta( numRHS_,numRHS_ ), zeta(numRHS_,numRHS_);
440 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
441 const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
444 Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
447 MVT::MvDot( *R_, *Z_, rHz );
449 if ( assertPositiveDefiniteness_ )
450 for (i=0; i<numRHS_; ++i)
451 TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(rHz[i]) < zero,
453 "Belos::PseudoBlockStochasticCGIter::iterate(): negative value for r^H*M*r encountered!" );
458 while (stest_->checkStatus(
this) !=
Passed) {
464 lp_->applyOp( *P_, *AP_ );
467 MVT::MvDot( *P_, *AP_, pAp );
469 Teuchos::SerialDenseVector<int,ScalarType>& z = normal();
471 for (i=0; i<numRHS_; ++i) {
472 if ( assertPositiveDefiniteness_ )
474 TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(pAp[i]) <= zero,
476 "Belos::PseudoBlockStochasticCGIter::iterate(): non-positive value for p^H*A*p encountered!" );
478 alpha(i,i) = rHz[i] / pAp[i];
481 zeta(i,i) = z[i] / Teuchos::ScalarTraits<ScalarType>::squareroot(pAp[i]);
487 MVT::MvTimesMatAddMv( one, *P_, alpha, one, *cur_soln_vec );
488 lp_->updateSolution();
491 MVT::MvTimesMatAddMv( one, *P_, zeta, one, *Y_);
496 for (i=0; i<numRHS_; ++i) {
502 MVT::MvTimesMatAddMv( -one, *AP_, alpha, one, *R_ );
507 if ( lp_->getLeftPrec() != Teuchos::null ) {
508 lp_->applyLeftPrec( *R_, *Z_ );
509 if ( lp_->getRightPrec() != Teuchos::null ) {
510 Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, numRHS_ );
511 lp_->applyRightPrec( *Z_, *tmp );
515 else if ( lp_->getRightPrec() != Teuchos::null ) {
516 lp_->applyRightPrec( *R_, *Z_ );
522 MVT::MvDot( *R_, *Z_, rHz );
523 if ( assertPositiveDefiniteness_ )
524 for (i=0; i<numRHS_; ++i)
525 TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(rHz[i]) < zero,
527 "Belos::PseudoBlockStochasticCGIter::iterate(): negative value for r^H*M*r encountered!" );
530 for (i=0; i<numRHS_; ++i) {
531 beta(i,i) = rHz[i] / rHz_old[i];
533 Teuchos::RCP<const MV> Z_i = MVT::CloneView( *Z_, index );
534 Teuchos::RCP<MV> P_i = MVT::CloneViewNonConst( *P_, index );
535 MVT::MvAddMv( one, *Z_i, beta(i,i), *P_i, *P_i );