void PseudoBlockCGIter<ScalarType,MV,OP>::iterate() { // // Allocate/initialize data structures // if (initialized_ == false) { initialize(); } // Allocate memory for scalars. int i=0; std::vector<int> index(1); std::vector<ScalarType> rHz( numRHS_ ), rHz_old( numRHS_ ), pAp( numRHS_ ); Teuchos::SerialDenseMatrix<int, ScalarType> alpha( numRHS_,numRHS_ ), beta( numRHS_,numRHS_ ); // Create convenience variables for zero and one. const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one(); const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero(); // Get the current solution std::vector. Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec(); // Compute first <r,z> a.k.a. rHz MVT::MvDot( *R_, *Z_, rHz ); if ( assertPositiveDefiniteness_ ) for (i=0; i<numRHS_; ++i) TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(rHz[i]) < zero, CGIterateFailure, "Belos::PseudoBlockCGIter::iterate(): negative value for r^H*M*r encountered!" ); //////////////////////////////////////////////////////////////// // Iterate until the status test tells us to stop. // while (stest_->checkStatus(this) != Passed) { // Increment the iteration iter_++; // Multiply the current direction std::vector by A and store in AP_ lp_->applyOp( *P_, *AP_ ); // Compute alpha := <R_,Z_> / <P_,AP_> MVT::MvDot( *P_, *AP_, pAp ); for (i=0; i<numRHS_; ++i) { if ( assertPositiveDefiniteness_ ) // Check that pAp[i] is a positive number! TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(pAp[i]) <= zero, CGIterateFailure, "Belos::PseudoBlockCGIter::iterate(): non-positive value for p^H*A*p encountered!" ); alpha(i,i) = rHz[i] / pAp[i]; } // // Update the solution std::vector x := x + alpha * P_ // MVT::MvTimesMatAddMv( one, *P_, alpha, one, *cur_soln_vec ); lp_->updateSolution(); // // Save the denominator of beta before residual is updated [ old <R_, Z_> ] // for (i=0; i<numRHS_; ++i) { rHz_old[i] = rHz[i]; } // // Compute the new residual R_ := R_ - alpha * AP_ // MVT::MvTimesMatAddMv( -one, *AP_, alpha, one, *R_ ); // // Compute beta := [ new <R_, Z_> ] / [ old <R_, Z_> ], // and the new direction std::vector p. // if ( lp_->getLeftPrec() != Teuchos::null ) { lp_->applyLeftPrec( *R_, *Z_ ); if ( lp_->getRightPrec() != Teuchos::null ) { Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, numRHS_ ); lp_->applyRightPrec( *Z_, *tmp ); Z_ = tmp; } } else if ( lp_->getRightPrec() != Teuchos::null ) { lp_->applyRightPrec( *R_, *Z_ ); } else { Z_ = R_; } // MVT::MvDot( *R_, *Z_, rHz ); if ( assertPositiveDefiniteness_ ) for (i=0; i<numRHS_; ++i) TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(rHz[i]) < zero, CGIterateFailure, "Belos::PseudoBlockCGIter::iterate(): negative value for r^H*M*r encountered!" ); // // Update the search directions. for (i=0; i<numRHS_; ++i) { beta(i,i) = rHz[i] / rHz_old[i]; index[0] = i; Teuchos::RCP<const MV> Z_i = MVT::CloneView( *Z_, index ); Teuchos::RCP<MV> P_i = MVT::CloneViewNonConst( *P_, index ); MVT::MvAddMv( one, *Z_i, beta(i,i), *P_i, *P_i ); } // } // end while (sTest_->checkStatus(this) != Passed) }
void BlockCGIter<ScalarType,MV,OP>::iterate() { // // Allocate/initialize data structures // if (initialized_ == false) { initialize(); } // Allocate data needed for LAPACK work. int info = 0; //char UPLO = 'U'; //(void) UPLO; // silence "unused variable" compiler warnings bool uplo = true; Teuchos::LAPACK<int,ScalarType> lapack; // Allocate memory for scalars. Teuchos::SerialDenseMatrix<int,ScalarType> alpha( blockSize_, blockSize_ ); Teuchos::SerialDenseMatrix<int,ScalarType> beta( blockSize_, blockSize_ ); Teuchos::SerialDenseMatrix<int,ScalarType> rHz( blockSize_, blockSize_ ), rHz_old( blockSize_, blockSize_ ), pAp( blockSize_, blockSize_ ); Teuchos::SerialSymDenseMatrix<int,ScalarType> pApHerm(Teuchos::View, uplo, pAp.values(), blockSize_, blockSize_); // Create dense spd solver. Teuchos::SerialSpdDenseSolver<int,ScalarType> lltSolver; // Create convenience variables for zero and one. const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one(); // Get the current solution std::vector. Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec(); // Check that the current solution std::vector has blockSize_ columns. TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != blockSize_, CGIterateFailure, "Belos::BlockCGIter::iterate(): current linear system does not have the right number of vectors!" ); int rank = ortho_->normalize( *P_, Teuchos::null ); TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,CGIterationOrthoFailure, "Belos::BlockCGIter::iterate(): Failed to compute initial block of orthonormal direction vectors."); //////////////////////////////////////////////////////////////// // Iterate until the status test tells us to stop. // while (stest_->checkStatus(this) != Passed) { // Increment the iteration iter_++; // Multiply the current direction std::vector by A and store in Ap_ lp_->applyOp( *P_, *AP_ ); // Compute alpha := <P_,R_> / <P_,AP_> // 1) Compute P^T * A * P = pAp and P^T * R // 2) Compute the Cholesky Factorization of pAp // 3) Back and forward solves to compute alpha // MVT::MvTransMv( one, *P_, *R_, alpha ); MVT::MvTransMv( one, *P_, *AP_, pAp ); // Compute Cholesky factorization of pAp lltSolver.setMatrix( Teuchos::rcp(&pApHerm, false) ); lltSolver.factorWithEquilibration( true ); info = lltSolver.factor(); TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure, "Belos::BlockCGIter::iterate(): Failed to compute Cholesky factorization using LAPACK routine POTRF."); // Compute alpha by performing a back and forward solve with the Cholesky factorization in pAp. lltSolver.setVectors( Teuchos::rcp( &alpha, false ), Teuchos::rcp( &alpha, false ) ); info = lltSolver.solve(); TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure, "Belos::BlockCGIter::iterate(): Failed to compute alpha using Cholesky factorization (POTRS)."); // // Update the solution std::vector X := X + alpha * P_ // MVT::MvTimesMatAddMv( one, *P_, alpha, one, *cur_soln_vec ); lp_->updateSolution(); // // Compute the new residual R_ := R_ - alpha * AP_ // MVT::MvTimesMatAddMv( -one, *AP_, alpha, one, *R_ ); // // Compute the new preconditioned residual, Z_. if ( lp_->getLeftPrec() != Teuchos::null ) { lp_->applyLeftPrec( *R_, *Z_ ); if ( lp_->getRightPrec() != Teuchos::null ) { Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, blockSize_ ); lp_->applyRightPrec( *Z_, *tmp ); Z_ = tmp; } } else if ( lp_->getRightPrec() != Teuchos::null ) { lp_->applyRightPrec( *R_, *Z_ ); } else { Z_ = R_; } // // Compute beta := <AP_,Z_> / <P_,AP_> // 1) Compute AP_^T * Z_ // 2) Compute the Cholesky Factorization of pAp (already have) // 3) Back and forward solves to compute beta // Compute <AP_,Z> MVT::MvTransMv( -one, *AP_, *Z_, beta ); // lltSolver.setVectors( Teuchos::rcp( &beta, false ), Teuchos::rcp( &beta, false ) ); info = lltSolver.solve(); TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure, "Belos::BlockCGIter::iterate(): Failed to compute beta using Cholesky factorization (POTRS)."); // // Compute the new direction vectors P_ = Z_ + P_ * beta // Teuchos::RCP<MV> Pnew = MVT::CloneCopy( *Z_ ); MVT::MvTimesMatAddMv(one, *P_, beta, one, *Pnew); P_ = Pnew; // Compute orthonormal block of new direction vectors. rank = ortho_->normalize( *P_, Teuchos::null ); TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,CGIterationOrthoFailure, "Belos::BlockCGIter::iterate(): Failed to compute block of orthonormal direction vectors."); } // end while (sTest_->checkStatus(this) != Passed) }