//! initialize a newly created preconditioner object void PreconditionerFactory::initializePrec(const RCP<const LinearOpSourceBase<double> > & ASrc, const RCP<const Thyra::MultiVectorBase<double> > & solnVec, PreconditionerBase<double> * prec, const ESupportSolveUse supportSolveUse) const { Preconditioner * blkPrec = dynamic_cast<Preconditioner *>(prec); blkPrec->setSourceVector(Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(solnVec)); initializePrec(ASrc,prec,supportSolveUse); }
double CMT::MLR::evaluate( const pair<ArrayXXd, ArrayXXd>& data, const Preconditioner& preconditioner) const { return -logLikelihood(preconditioner(data.first, data.second)).mean() / log(2.) - preconditioner.logJacobian(data).mean() / log(2.); }
void DefaultIterativeSolver<BasisFunctionType, ResultType>::initializeSolver( const Teuchos::RCP<Teuchos::ParameterList>& paramList, const Preconditioner<ResultType>& preconditioner) { m_impl->solverWrapper->setPreconditioner(preconditioner.get()); m_impl->solverWrapper->initializeSolver(paramList); }
double CMT::MLR::evaluate( const MatrixXd& input, const MatrixXd& output, const Preconditioner& preconditioner) const { return -logLikelihood(preconditioner(input, output)).mean() / log(2.) - preconditioner.logJacobian(input, output).mean() / log(2.); }
bool IterativeSolvers::pcg(const IRCMatrix &A, Vector &x, const Vector &b, const Preconditioner &M) { /*! Solves Ax=b using the preconditioned conjugate gradient method. */ const idx N = x.getLength(); real resid(100.0); Vector p(N), z(N), q(N); real alpha; real normr(0); real normb = norm(b); real rho(0), rho_1(0), beta(0); Vector r = b - A * x; if (normb == 0.0) normb = 1; resid = norm(r) / normb; if (resid <= IterativeSolvers::toler) { IterativeSolvers::toler = resid; IterativeSolvers::maxIter = 0; return true; } // MAIN LOOP idx i = 1; for (; i <= IterativeSolvers::maxIter; i++) { M.solveMxb(z, r); rho = dot(r, z); if (i == 1) p = z; else { beta = rho / rho_1; aypx(beta, p, z); // p = beta*p + z; } // CALCULATES q = A*p AND dp = dot(q,p) real dp = multiply_dot(A, p, q); alpha = rho / dp; normr = 0; #ifdef USES_OPENMP #pragma omp parallel for reduction(+:normr) #endif for (idx j = 0 ; j < N ; ++j) { x[j] += alpha * p[j]; // x + alpha(0) * p; r[j] -= alpha * q[j]; // r - alpha(0) * q; normr += r[j] * r[j]; } normr = sqrt(normr); resid = normr / normb; if (resid <= IterativeSolvers::toler) { IterativeSolvers::toler = resid; IterativeSolvers::maxIter = i; return true; } rho_1 = rho; } IterativeSolvers::toler = resid; return false; }
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; } }
int CG(const MMatrix &A, MVector &x, const MVector &b, const Preconditioner &M, int &max_iter, Real &tol) { Real resid; MVector p, z, q; MVector alpha(1), beta(1), rho(1), rho_1(1); MVector r = b - A*x; Real normb = norm(b); if (normb == 0.0) normb = 1; if ((resid = norm(r) / normb) <= tol){ tol = resid; max_iter = 0; return 0; } for (int i = 1; i <= max_iter; i++) { // Assign Z z = M.solve(r); rho.p_[0] = dot(r, z); // Assign P if (i == 1) p = z; else { beta.p_[0] = rho.p_[0] / rho_1.p_[0]; p = z + beta.p_[0] * p; } // Assign Q q = A*p; alpha.p_[0] = rho.p_[0] / dot(p, q); // Change X and R x += alpha.p_[0] * p; r -= alpha.p_[0] * q; // Check tol if ((resid = norm(r) / normb) <= tol) { tol = resid; max_iter = i; return 0; } rho_1.p_[0] = rho.p_[0]; } tol = resid; return 1; }
//! initialize a newly created preconditioner object void PreconditionerFactory::initializePrec(const RCP<const LinearOpSourceBase<double> > & ASrc, PreconditionerBase<double> * prec, const ESupportSolveUse supportSolveUse) const { // get the blocked linear operator LinearOp A = Teuchos::rcp_const_cast<Thyra::LinearOpBase<double> >(ASrc->getOp()); Preconditioner * blkPrec = dynamic_cast<Preconditioner *>(prec); TEUCHOS_ASSERT(blkPrec!=0); // grab the state object RCP<PreconditionerState> state = blkPrec->getStateObject(); state->setInitialized(false); // build the preconditioner const RCP<const LinearOpBase<double> > M = buildPreconditionerOperator(A,*state); // set the request handler for the setOpRequestHandler(*this,M); // must first cast that to be initialized DefaultPreconditioner<double> & dPrec = Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec); dPrec.initializeUnspecified(Teuchos::rcp_const_cast<LinearOpBase<double> >(M)); }
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; }
bool IterativeSolvers::gmres(const IRCMatrix &A, Vector &x, const Vector &b, const Preconditioner &M) { const idx N = x.getLength(); idx i, j = 1, k; Vector s(maxInnerIter + 1); Vector cs(maxInnerIter + 1); Vector sn(maxInnerIter + 1); Vector w(N); real normb = norm(M.solve(b)); Vector r = M.solve(b - A * x); real beta = norm(r); if (normb == 0.0) normb = 1; real res(norm(r) / normb); if (res <= toler) { toler = res; maxIter = 0; return true; } Vector *v = new Vector[maxInnerIter + 1]; for (idx id = 0; id < maxInnerIter + 1; ++id) v[id] = Vector(N); // CREATE HESSENBERG MATRIX NEEDED TO STORE INTERMEDIATES DenseMatrix H(maxInnerIter + 1, maxInnerIter); Vector temp(N); Vector temp2(maxInnerIter + 1); // MAIN LOOP while (j <= maxIter) { v[0] = r * (1.0 / beta); s = 0.0; s(0) = beta; // INNER ITERATIONS for (i = 0; i < maxInnerIter && j <= maxIter; i++, j++) { // CALCULATE w = M^{-1}(A*v[i]) multiply(A, v[i], temp); M.solveMxb(w, temp); // PRE-CALCULATE DOT PRODUCTS IN PARALLEL // H(k,i) = dot( v[k], w) #ifdef USES_OPENMP #pragma omp parallel for #endif for (k = 0; k <= i ; ++k) { register real dp(0); for (idx id = 0 ; id < N ; ++id) dp += w[id] * v[k][id]; H(k, i) = dp; //dot(w,v[k]); } for (k = 0; k <= i; ++k) { // w -= v[k]*H(k,i) without temporaries register real tempr = H(k, i); #ifdef USES_OPENMP #pragma omp parallel for // why is this loop so critical?? #endif for (idx id = 0 ; id < N ; ++id) w[id] -= v[k][id] * tempr; } // BELOW PARALLEL REGION CALCULATES: // H(i+1,i) = norm(w); // v[i+1] = w * (1.0 / H(i+1, i)); H(i + 1, i) = 0; real tempr(0); #ifdef USES_OPENMP #pragma omp parallel shared(tempr) #endif { #ifdef USES_OPENMP #pragma omp for reduction(+:tempr) #endif for (idx id = 0 ; id < N ; ++id) tempr += w[id] * w[id]; //norm(w); #ifdef USES_OPENMP #pragma omp single #endif { H(i + 1, i) = sqrt(tempr); tempr = (1.0 / H(i + 1, i)); } #ifdef USES_OPENMP #pragma omp for #endif for (idx id = 0 ; id < N ; ++id) v[i + 1][id] = w[id] * tempr; }// end for omp parallel for (k = 0; k < i; k++) ApplyPlaneRotation(H(k, i), H(k + 1, i), cs(k), sn(k)); GeneratePlaneRotation(H(i, i), H(i + 1, i), cs(i), sn(i)); ApplyPlaneRotation(H(i, i), H(i + 1, i), cs(i), sn(i)); ApplyPlaneRotation(s(i), s(i + 1), cs(i), sn(i)); res = fabs(s(i + 1)) / normb; if (res < toler) { // COPY S INTO temp WITHOUT RESIZING for (idx id = 0 ; id < maxInnerIter + 1 ; ++id) temp2[id] = s[id]; Update(x, i, H, temp2, v); toler = res; maxIter = j; delete [] v; return true; } }// end for i IINNER ITERATIONS // COPY S INTO temp WITHOUT RESIZING for (idx id = 0 ; id < maxInnerIter + 1 ; ++id) temp2[id] = s[id]; Update(x, maxInnerIter - 1, H, temp2, v); //multiply(A, x, temp); //r = M.solve(b - A * x); M.solveMxb(r, b - A * x); beta = norm(r); res = beta / normb; if (res < toler) { toler = res; maxIter = j; delete [] v; return true; } } toler = res; delete [] v; return false; }
// Conjugate gradient with preconditioner. /*static*/ bool ConjugateGradientSolver(const Preconditioner & preconditioner, const SparseMatrix & A, const FullVector & b, FullVector & x, float epsilon) { nvDebugCheck( A.isSquare() ); nvDebugCheck( A.width() == b.dimension() ); nvDebugCheck( A.width() == x.dimension() ); int i = 0; const int D = A.width(); const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not. FullVector r(D); // residual FullVector p(D); // search direction FullVector q(D); // FullVector s(D); // preconditioned float delta_0; float delta_old; float delta_new; float alpha; float beta; // r = b - A·x copy(b, r); sgemv(-1, A, x, 1, r); // p = M^-1 · r preconditioner.apply(r, p); //copy(r, p); delta_new = dot(r, p); delta_0 = delta_new; while (i < i_max && delta_new > epsilon*epsilon*delta_0) { i++; // q = A·p mult(A, p, q); // alpha = delta_new / p·q alpha = delta_new / dot(p, q); // x = alfa·p + x saxpy(alpha, p, x); if ((i & 31) == 0) // recompute r after 32 steps { // r = b - A·x copy(b, r); sgemv(-1, A, x, 1, r); } else { // r = r - alfa·q saxpy(-alpha, q, r); } // s = M^-1 · r preconditioner.apply(r, s); //copy(r, s); delta_old = delta_new; delta_new = dot( r, s ); beta = delta_new / delta_old; // p = s + beta·p scal(beta, p); saxpy(1, s, p); } return delta_new <= epsilon*epsilon*delta_0; }
void DefaultIterativeSolver<BasisFunctionType, ResultType>::setPreconditioner( const Preconditioner<ResultType>& preconditioner) { m_impl->solverWrapper->setPreconditioner(preconditioner.get()); }