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) }
ordinal_type Stokhos::CGDivisionExpansionStrategy<ordinal_type,value_type,node_type>:: CG(const Teuchos::SerialDenseMatrix<ordinal_type, value_type> & A, Teuchos::SerialDenseMatrix<ordinal_type,value_type> & X, const Teuchos::SerialDenseMatrix<ordinal_type,value_type> & B, ordinal_type max_iter, value_type tolerance, ordinal_type prec_iter, ordinal_type order , ordinal_type m, ordinal_type PrecNum, const Teuchos::SerialDenseMatrix<ordinal_type, value_type> & M, ordinal_type diag) { ordinal_type n = A.numRows(); ordinal_type k=0; value_type resid; Teuchos::SerialDenseMatrix<ordinal_type, value_type> Ax(n,1); Ax.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, X, 0.0); Teuchos::SerialDenseMatrix<ordinal_type, value_type> r(Teuchos::Copy,B); r-=Ax; resid=r.normFrobenius(); Teuchos::SerialDenseMatrix<ordinal_type, value_type> p(r); Teuchos::SerialDenseMatrix<ordinal_type, value_type> rho(1,1); Teuchos::SerialDenseMatrix<ordinal_type, value_type> oldrho(1,1); Teuchos::SerialDenseMatrix<ordinal_type, value_type> pAp(1,1); Teuchos::SerialDenseMatrix<ordinal_type, value_type> Ap(n,1); value_type b; value_type a; while (resid > tolerance && k < max_iter){ Teuchos::SerialDenseMatrix<ordinal_type, value_type> z(r); //Solve Mz=r if (PrecNum != 0){ if (PrecNum == 1){ Stokhos::DiagPreconditioner<ordinal_type, value_type> precond(M); precond.ApplyInverse(r,z,prec_iter); } else if (PrecNum == 2){ Stokhos::JacobiPreconditioner<ordinal_type, value_type> precond(M); precond.ApplyInverse(r,z,2); } else if (PrecNum == 3){ Stokhos::GSPreconditioner<ordinal_type, value_type> precond(M,0); precond.ApplyInverse(r,z,1); } else if (PrecNum == 4){ Stokhos::SchurPreconditioner<ordinal_type, value_type> precond(M, order, m, diag); precond.ApplyInverse(r,z,prec_iter); } } rho.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, r, z, 0.0); if (k==0){ p.assign(z); rho.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, r, z, 0.0); } else { b=rho(0,0)/oldrho(0,0); p.scale(b); p+=z; } Ap.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, p, 0.0); pAp.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, p, Ap, 0.0); a=rho(0,0)/pAp(0,0); Teuchos::SerialDenseMatrix<ordinal_type, value_type> scalep(p); scalep.scale(a); X+=scalep; Ap.scale(a); r-=Ap; oldrho.assign(rho); resid=r.normFrobenius(); k++; } //std::cout << "iteration count " << k << std::endl; return 0; }
void RCGIter<ScalarType,MV,OP>::iterate() { TEUCHOS_TEST_FOR_EXCEPTION( initialized_ == false, RCGIterFailure, "Belos::RCGIter::iterate(): RCGIter class not initialized." ); // We'll need LAPACK Teuchos::LAPACK<int,ScalarType> lapack; // Create convenience variables for zero and one. ScalarType one = Teuchos::ScalarTraits<ScalarType>::one(); ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero(); // Allocate memory for scalars std::vector<int> index(1); Teuchos::SerialDenseMatrix<int,ScalarType> pAp(1,1), rTz(1,1); // Get the current solution std::vector. Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec(); // Check that the current solution std::vector only has one column. TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != 1, RCGIterFailure, "Belos::RCGIter::iterate(): current linear system has more than one std::vector!" ); // Compute the current search dimension. int searchDim = numBlocks_+1; // index of iteration within current cycle int i_ = 0; //////////////////////////////////////////////////////////////// // iterate until the status test tells us to stop. // // also break if our basis is full // Teuchos::RCP<const MV> p_ = Teuchos::null; Teuchos::RCP<MV> pnext_ = Teuchos::null; while (stest_->checkStatus(this) != Passed && curDim_+1 <= searchDim) { // Ap = A*p; index.resize( 1 ); index[0] = i_; p_ = MVT::CloneView( *P_, index ); lp_->applyOp( *p_, *Ap_ ); // d = p'*Ap; MVT::MvTransMv( one, *p_, *Ap_, pAp ); (*D_)(i_,0) = pAp(0,0); // alpha = rTz_old / pAp (*Alpha_)(i_,0) = (*rTz_old_)(0,0) / pAp(0,0); // Check that alpha is a positive number TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(pAp(0,0)) <= zero, RCGIterFailure, "Belos::RCGIter::iterate(): non-positive value for p^H*A*p encountered!" ); // x = x + (alpha * p); MVT::MvAddMv( one, *cur_soln_vec, (*Alpha_)(i_,0), *p_, *cur_soln_vec ); lp_->updateSolution(); // r = r - (alpha * Ap); MVT::MvAddMv( one, *r_, -(*Alpha_)(i_,0), *Ap_, *r_ ); std::vector<MagnitudeType> norm(1); MVT::MvNorm( *r_, norm ); //printf("i = %i\tnorm(r) = %e\n",i_,norm[0]); // z = M\r if ( lp_->getLeftPrec() != Teuchos::null ) { lp_->applyLeftPrec( *r_, *z_ ); } else if ( lp_->getRightPrec() != Teuchos::null ) { lp_->applyRightPrec( *r_, *z_ ); } else { z_ = r_; } // rTz_new = r'*z; MVT::MvTransMv( one, *r_, *z_, rTz ); // beta = rTz_new/rTz_old; (*Beta_)(i_,0) = rTz(0,0) / (*rTz_old_)(0,0); // rTz_old = rTz_new; (*rTz_old_)(0,0) = rTz(0,0); // get pointer for next p index.resize( 1 ); index[0] = i_+1; pnext_ = MVT::CloneViewNonConst( *P_, index ); if (existU_) { // mu = UTAU \ (AU'*z); Teuchos::SerialDenseMatrix<int,ScalarType> mu( Teuchos::View, *Delta_, recycleBlocks_, 1, 0, i_ ); MVT::MvTransMv( one, *AU_, *z_, mu ); char TRANS = 'N'; int info; lapack.GETRS( TRANS, recycleBlocks_, 1, LUUTAU_->values(), LUUTAU_->stride(), &(*ipiv_)[0], mu.values(), mu.stride(), &info ); TEUCHOS_TEST_FOR_EXCEPTION(info != 0, RCGIterLAPACKFailure, "Belos::RCGIter::solve(): LAPACK GETRS failed to compute a solution."); // p = -(U*mu) + (beta*p) + z (in two steps) // p = (beta*p) + z; MVT::MvAddMv( (*Beta_)(i_,0), *p_, one, *z_, *pnext_ ); // pnext = -(U*mu) + (one)*pnext; MVT::MvTimesMatAddMv( -one, *U_, mu, one, *pnext_ ); } else { // p = (beta*p) + z; MVT::MvAddMv( (*Beta_)(i_,0), *p_, one, *z_, *pnext_ ); } // Done with this view; release pointer p_ = Teuchos::null; pnext_ = Teuchos::null; // increment iteration count and dimension index i_++; iter_++; curDim_++; } // end while (statusTest == false) }
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) }
// CG int CG(const Teuchos::SerialDenseMatrix<int, double> & A, Teuchos::SerialDenseMatrix<int,double> X,const Teuchos::SerialDenseMatrix<int,double> & B, int max_iter, double tolerance, Stokhos::DiagPreconditioner<int,double> prec) { int n; int k=0; double resid; n=A.numRows(); std::cout << "A= " << A << std::endl; std::cout << "B= " << B << std::endl; Teuchos::SerialDenseMatrix<int, double> Ax(n,1); Ax.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, X, 0.0); Teuchos::SerialDenseMatrix<int, double> r(B); r-=Ax; resid=r.normFrobenius(); Teuchos::SerialDenseMatrix<int, double> rho(1,1); Teuchos::SerialDenseMatrix<int, double> oldrho(1,1); Teuchos::SerialDenseMatrix<int, double> pAp(1,1); Teuchos::SerialDenseMatrix<int, double> Ap(n,1); double b; double a; Teuchos::SerialDenseMatrix<int, double> p(r); while (resid > tolerance && k < max_iter){ Teuchos::SerialDenseMatrix<int, double> z(r); //z=M-1r // prec.ApplyInverse(r,z); rho.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, r, z, 0.0); if (k==0){ p.assign(z); rho.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, r, z, 0.0); } else { b=rho(0,0)/oldrho(0,0); p.scale(b); p+=z; } Ap.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, p, 0.0); pAp.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, p, Ap, 0.0); a=rho(0,0)/pAp(0,0); Teuchos::SerialDenseMatrix<int, double> scalep(p); scalep.scale(a); X+=scalep; Ap.scale(a); r-=Ap; oldrho.assign(rho); resid=r.normFrobenius(); k++; } std::cout << "X= " << X << std::endl; return 0; }