SolverState<double> PCGSolver::solve(const LinearOperator<double>& A, const Vector<double>& b, Vector<double>& x) const { if (precFactory_.ptr().get() == 0) { return solveUnprec(A, b, x); } else { SolverState<double> rtn; Preconditioner<double> prec = precFactory_.createPreconditioner(A); if (prec.isIdentity()) { rtn = solveUnprec(A, b, x); } else if (prec.isTwoSided()) { LinearOperator<double> P = prec.left(); LinearOperator<double> Q = prec.right(); LinearOperator<double> PAQ = P*A*Q; Vector<double> Pb = P*b; Vector<double> y; rtn = solveUnprec(PAQ, Pb, y); x = Q*y; } else if (prec.hasRight()) { LinearOperator<double> Q = prec.right(); LinearOperator<double> AQ = A*Q; Vector<double> y; rtn = solveUnprec(AQ, b, y); x = Q*y; } else if (prec.hasLeft()) { LinearOperator<double> P = prec.left(); LinearOperator<double> PA = P*A; Vector<double> Pb = P*b; rtn = solveUnprec(PA, Pb, x); } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Inconsistent preconditioner state " "in PGCSolver::solve()"); } return rtn; } }
SolverState<double> BelosSolver::solve(const LinearOperator<double>& A, const Vector<double>& rhs, Vector<double>& soln) const { typedef Anasazi::SimpleMV MV; typedef LinearOperator<double> OP; typedef Belos::LinearProblem<double, MV, OP> LP; TEUCHOS_TEST_FOR_EXCEPT(!A.ptr().get()); TEUCHOS_TEST_FOR_EXCEPT(!rhs.ptr().get()); if (!soln.ptr().get()) { soln = rhs.copy(); /* KRL 8 Jun 2012: set x0 to zero to workaround bug in Belos */ soln.zero(); } if (rhs.norm2()==0.0) { soln.zero(); SolverStatusCode code = SolveConverged; SolverState<double> state(code, "Detected trivial solution", 0, 0.0); return state; } RCP<OP> APtr = rcp(new LinearOperator<double>(A)); RCP<MV> bPtr = rcp(new MV(1)); (*bPtr)[0] = rhs; RCP<MV> ansPtr = rcp(new MV(1)); (*ansPtr)[0] = soln; RCP<LP> prob = rcp(new LP(APtr, ansPtr, bPtr)); TEUCHOS_TEST_FOR_EXCEPT(!prob->setProblem()); if (pf_.ptr().get()) { Preconditioner<double> P = pf_.createPreconditioner(A); if (P.hasLeft()) { prob->setLeftPrec(rcp(new OP(P.left()))); } if (P.hasRight()) { prob->setRightPrec(rcp(new OP(P.right()))); } } if (!hasSolver_) { ParameterList plist = parameters(); RCP<ParameterList> belosList = rcp(&plist, false); std::string solverType = parameters().get<string>("Method"); if (solverType=="GMRES") { solver_=rcp(new Belos::BlockGmresSolMgr<double, MV, OP>(prob, belosList)); } else if (solverType=="CG") { solver_=rcp(new Belos::BlockCGSolMgr<double, MV, OP>(prob, belosList)); } else if (solverType=="TFQMR") { solver_=rcp(new Belos::TFQMRSolMgr<double, MV, OP>(prob, belosList)); } else if (solverType=="GCRODR") { solver_=rcp(new Belos::GCRODRSolMgr<double, MV, OP>(prob, belosList)); hasSolver_ = true; // only cache recycling solvers } else if (solverType=="RCG") { solver_=rcp(new Belos::RCGSolMgr<double, MV, OP>(prob, belosList)); hasSolver_ = true; // only cache recycling solvers } else { TEUCHOS_TEST_FOR_EXCEPT(!(solverType=="GMRES" || solverType=="CG")); } } else // reset problem { solver_->setProblem( prob ); } Belos::ReturnType rtn = solver_->solve(); int numIters = solver_->getNumIters(); double resid = solver_->achievedTol(); SolverStatusCode code = SolveFailedToConverge; if (rtn==Belos::Converged) code = SolveConverged; SolverState<double> state(code, "Belos solver completed", numIters, resid); return state; }
SolverState<double> BelosSolver::solve(const LinearOperator<double>& A, const Vector<double>& rhs, Vector<double>& soln) const { typedef Thyra::MultiVectorBase<double> MV; typedef Thyra::LinearOpBase<double> OP; typedef Belos::LinearProblem<double, MV, OP> LP; TEST_FOR_EXCEPT(!A.ptr().get()); TEST_FOR_EXCEPT(!rhs.ptr().get()); /* get Thyra objects */ RCP<OP> APtr = A.ptr(); RCP<MV> bPtr = rhs.ptr(); if (!soln.ptr().get()) soln = rhs.copy(); RCP<MV> ansPtr = soln.ptr(); RCP<LP> prob = rcp(new LP(APtr, ansPtr, bPtr)); TEST_FOR_EXCEPT(!prob->setProblem()); if (pf_.ptr().get()) { Preconditioner<double> P = pf_.createPreconditioner(A); if (P.hasLeft()) { prob->setLeftPrec(P.left().ptr()); } if (P.hasRight()) { prob->setRightPrec(P.right().ptr()); } } ParameterList plist = parameters(); RCP<ParameterList> belosList = rcp(&plist, false); RCP<Belos::SolverManager<double, MV, OP> > solver ; std::string solverType = parameters().get<string>("Method"); if (solverType=="GMRES") { solver=rcp(new Belos::BlockGmresSolMgr<double, MV, OP>(prob, belosList)); } else if (solverType=="CG") { solver=rcp(new Belos::BlockCGSolMgr<double, MV, OP>(prob, belosList)); } else { TEST_FOR_EXCEPT(!(solverType=="GMRES" || solverType=="CG")); } Belos::ReturnType rtn = solver->solve(); int numIters = solver->getNumIters(); double resid = -1.0; SolverStatusCode code = SolveFailedToConverge; if (rtn==Belos::Converged) code = SolveConverged; SolverState<double> state(code, "Belos solver completed", numIters, resid); return state; }