13#ifndef CG_IMPLEMENTATION_HH
14#define CG_IMPLEMENTATION_HH
19#include "algorithm/opt_aux/src/include/Fmin.h"
21#include "boost/timer/timer.hpp"
31 template <
class X,
class Xstar,
class Derived>
52 theta += (1-qAq)/std::fabs(qPq);
53 if(
verbose > 0 ) std::cout <<
"Regularization: Computed theta: " <<
theta << std::endl;
55 if(
verbose > 0 ) std::cout <<
"Regularization: Updating theta from " << oldTheta <<
" to " <<
theta << std::endl;
60 r.axpy(-alpha*
theta,Pq);
67 template <
class X,
class Xstar,
class>
79 template <
class X,
class Xstar,
class Derived, CGImplementationType impl>
128 std::cout <<
"Matrix-Vector time: " << mvTimer.format()
129 <<
"dual pairings : " << dpTimer.format()
130 <<
"vector ops : " << apTimer.format()
131 <<
"preconditioner : " << prTimer.format() <<
'\n';
135 boost::timer::cpu_timer mvTimer;
136 boost::timer::cpu_timer dpTimer;
137 boost::timer::cpu_timer apTimer;
138 boost::timer::cpu_timer prTimer;
143 template <
typename... Args>
155 CGFminModel(
double quadraticPart_,
double linearPart_,
double omegaL_,
156 double dndn_,
double dnd_,
double dd_)
163 double normSquared =
dndn + t*
dnd + t*t*
dd;
174 template <
class POperator,
class Vector>
180 template <
class Operator,
class Rhs,
class DualPairing>
183 Rhs Ad(rhs), Adn(rhs);
186 double dAd = dp(d,Ad);
187 double lin = dp(d,rhs) +
nu*dp(d,Adn);
189 Rhs Pd(rhs), Pdn(rhs);
202 return Fmin(0.,1.,
model,1e-3);
221 template<
class X,
class Xstar, CGImplementationType impl = CGImplementationType::STANDARD,
class TimerPolicy = DoNotMeasureTime,
class Functor = DoNotAlwaysRegularize>
223 :
public Dune::InverseOperator<X,Xstar>
227 enum class Result { Converged,
Failed, EncounteredNonConvexity, TruncatedAtNonConvexity };
241 : CG_Detail::ChooseRegularization<
X,Xstar,
CGBase<
X,Xstar,impl,TimerPolicy>,impl>::type(eps_,verbose_),
242 op(op_), prec(prec_), dp(dp_), terminate(terminate_), verbose(verbose_), eps(eps_)
246 : CG_Detail::ChooseRegularization<
X,Xstar,
CGBase<
X,Xstar,impl,TimerPolicy>,impl>::type(eps_,verbose_),
247 op(op_), prec(prec_), dp(dp_), terminate(terminate_), verbose(verbose_), eps(eps_), f(f_)
253 Dune::InverseOperatorResult res;
263 virtual void apply(
X& u, Xstar&b,
Real tolerance, Dune::InverseOperatorResult& res)
269 virtual void apply(
X& u, Xstar& b, Dune::InverseOperatorResult& res)
277 result = Result::Failed;
278 while( result != Result::Converged && result != Result::TruncatedAtNonConvexity )
288 std::cout <<
"=== rate=" << res.conv_rate
289 <<
", T=" << res.elapsed
290 <<
", TIT=" << res.elapsed/step
291 <<
", IT=" << step << std::endl;
297 int cgLoop (
X& u, Xstar& b, Dune::InverseOperatorResult& res)
302 result = Result::Failed;
303 res.converged =
false;
310 op.applyscaleadd(-1,u,r);
311 std::unique_ptr<X> rq(
new X(u)); *rq = 0;
316 std::unique_ptr<X> q(
new X(*rq));
322 Real alpha = 0, beta = 0, energyNorm2 = 0;
323 Real sigma = std::abs(dp(*rq,r));
324 double const sigma0 = sigma;
327 std::cout <<
"=== Kaskade7 IterateType::CG" << std::endl;
329 this->printHeader(std::cout);
330 this->printOutput(std::cout,(
double)0,sigma0);
335 if(!std::is_same<Functor,DoNotAlwaysRegularize>::value)
341 double dHd = dp(*q,Hd);
343 double initialThetaGuess = 1./tau - dHd/sigma;
344 std::cout <<
"CG: TAU = " << tau << std::endl;
345 std::cout <<
"CG: INITIAL GUESS FOR THETA = " << initialThetaGuess << std::endl;
350 for ( step = 1; step<=maxNoiterations; step++ )
358 Real qAq = dp(*q,Aq);
359 Real qPq = dp(*q,Pq);
361 this->regularize(qAq,qPq);
364 energyNorm2 += alpha*qAq;
367 if( std::fabs(qAq) < eps*eps )
369 if( verbose > 0 ) std::cout << pre <<
"Terminating due to numerically almost vanishing step." << std::endl;
370 result = Result::Converged;
371 res.converged =
true;
379 std::cout << pre <<
"Direction of negative curvature encountered in standard IterateType::CG implementation!" << std::endl;
380 std::cout << pre <<
"Either something is wrong with your operator or you should use TCG, RCG or HCG. Terminating IterateType::CG!" << std::endl;
389 if( step == 1 ) u.axpy(1.0,*q);
390 if( verbose > 0 ) std::cout << pre <<
"Truncating at nonconvexity in iteration " << step <<
": " << qAq << std::endl;
391 result = Result::TruncatedAtNonConvexity;
397 this->updateRegularization(qAq,qPq);
398 if( verbose > 0 ) std::cout << pre <<
"Regularizing at nonconvexity in iteration " << step <<
"." << std::endl;
399 result = Result::EncounteredNonConvexity;
413 result = Result::Converged;
414 res.converged =
true;
420 this->adjustResidual(r,alpha,Pq);
429 double sigmaNew = std::abs(dp(*rq,r));
431 if (verbose>1) this->printOutput(std::cout,(
double)step,std::abs(sigmaNew),std::abs(sigma));
433 beta = sigmaNew/sigma;
445 if (verbose>0) this->printOutput(std::cout,(
double)step,std::abs(sigma));
446 res.iterations = step;
447 res.reduction = std::sqrt(std::abs(sigma)/sigma0);
448 res.conv_rate = pow(res.reduction,1.0/step);
449 res.elapsed = watch.elapsed();
454 bool encounteredNonConvexity()
const {
return result==Result::EncounteredNonConvexity || result==Result::TruncatedAtNonConvexity; }
463 virtual Dune::SolverCategory::Category
category()
const override
465 return Dune::SolverCategory::sequential;
469 Dune::LinearOperator<X,Xstar>& op;
470 Dune::Preconditioner<X,Xstar>& prec;
475 double eps, energyNorm2;
476 std::string pre = std::string(
"KASKADE IterateType::PCG: ");
regularized preconditioned conjugate gradient method
virtual void apply(X &u, Xstar &b, Real tolerance, Dune::InverseOperatorResult &res)
ScalarTraits< typenameGetScalar< X >::type >::Real Real
the real field type corresponding to X::field_type or X::Scalar
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
CGBase(Dune::LinearOperator< X, Xstar > &op_, Dune::Preconditioner< X, Xstar > &prec_, DualPairing< X, Xstar > const &dp_, PCGTerminationCriterion< Real > &terminate_, Functor f_, int verbose_=0, double eps_=1e-15)
bool encounteredNonConvexity() const
virtual void apply(X &u, Xstar &b, Dune::InverseOperatorResult &res)
void apply(X &u, Xstar &b)
CGBase(Dune::LinearOperator< X, Xstar > &op_, Dune::Preconditioner< X, Xstar > &prec_, DualPairing< X, Xstar > const &dp_, PCGTerminationCriterion< Real > &terminate_, int verbose_=0, double eps_=1e-15)
Set up conjugate gradient solver with termination criterion.
int cgLoop(X &u, Xstar &b, Dune::InverseOperatorResult &res)
double getSolutionEnergyNormEstimate()
Abstract base class for dual pairing of and its dual space .
virtual void setTolerance(Real tol)=0
set requested tolerance
virtual void clear()=0
re-initializes the termination criterion for a new IterateType::CG run
virtual int getMaxIterationSteps()=0
get the maximum number of allowed iteration steps
virtual void addStepQuantities(Real stepLength, Real qAq, Real qPq, Real rPINVr)=0
addStepQuantities supplies algorithmic quantities to the termination criterion
virtual bool minimalDecreaseAchieved()
Helper class for working with (real or complex) scalar field types.
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
Dune::FieldVector< Scalar, dim > Vector
void init(Operator const &A, Rhs const &rhs, Vector const &d, DualPairing const &dp)
AlwaysRegularizeWithThetaGuess(POperator const &P_, Vector const &dn_, double nu_, double omegaL_)
std::conditional<(impl==CGImplementationType::STANDARD||impl==CGImplementationType::TRUNCATED), NoRegularization< X, Xstar, Derived >, Regularization< X, Xstar, Derived > >::type type
void regularize(double &, double)
void adjustResidual(Xstar &, double, Xstar const &)
void initializeRegularization()
void updateRegularization(double, double)
NoRegularization(double, int)
ScalarTraits< typenameGetScalar< X >::type >::Real Real
void initializeRegularization()
void regularize(double &qAq, double qPq)
void updateRegularization(double qAq, double qPq)
void adjustResidual(Xstar &r, double alpha, Xstar const &Pq)
Regularization(double eps_, int verbose_)
CGFminModel & operator=(CGFminModel const &)=default
CGFminModel(double quadraticPart_, double linearPart_, double omegaL_, double dndn_, double dnd_, double dd_)
CGFminModel(CGFminModel const &)=default
double operator()(double t)
void init(const Args &...)