37static auto i_control = [](
auto dt,
auto eps,
unsigned embedded_order,
unsigned order)
39 using value_type = std::decay_t<
decltype(dt[0])>;
40 return dt[0]*pow( eps[0], -1./(value_type)embedded_order);
43static auto pi_control = [](
auto dt,
auto eps,
unsigned embedded_order,
unsigned order)
45 using value_type = std::decay_t<
decltype(dt[0])>;
47 return i_control( dt, eps, embedded_order, order);
48 value_type m_k1 = -0.8, m_k2 = 0.31;
49 value_type factor = pow( eps[0], m_k1/(value_type)embedded_order)
50 * pow( eps[1], m_k2/(value_type)embedded_order);
71static auto pid_control = [](
auto dt,
auto eps,
unsigned embedded_order,
unsigned order)
73 using value_type = std::decay_t<
decltype(dt[0])>;
75 return i_control( dt, eps, embedded_order, order);
77 return pi_control( dt, eps, embedded_order, order);
78 value_type m_k1 = -0.58, m_k2 = 0.21, m_k3 = -0.1;
80 value_type factor = pow( eps[0], m_k1/(value_type)embedded_order)
81 * pow( eps[1], m_k2/(value_type)embedded_order)
82 * pow( eps[2], m_k3/(value_type)embedded_order);
87static auto ex_control = [](
auto dt,
auto eps,
unsigned embedded_order,
unsigned order)
89 using value_type = std::decay_t<
decltype(dt[0])>;
91 return i_control( dt, eps, embedded_order, order);
92 value_type m_k1 = -0.367, m_k2 = 0.268;
93 value_type factor = pow( eps[0], m_k1/(value_type)embedded_order)
94 * pow( eps[0]/eps[1], m_k2/(value_type)embedded_order);
98static auto im_control = [](
auto dt,
auto eps,
unsigned embedded_order,
unsigned order)
100 using value_type = std::decay_t<
decltype(dt[0])>;
102 return i_control( dt, eps, embedded_order, order);
103 value_type m_k1 = -0.98, m_k2 = -0.95;
104 value_type factor = pow( eps[0], m_k1/(value_type)embedded_order)
105 * pow( eps[0]/eps[1], m_k2/(value_type)embedded_order);
106 return dt[0]*dt[0]/dt[1]*factor;
109static auto imex_control = [](
auto dt,
auto eps,
unsigned embedded_order,
unsigned order)
111 using value_type = std::decay_t<
decltype(dt[0])>;
112 value_type h1 =
ex_control( dt, eps, embedded_order, order);
113 value_type h2 =
im_control( dt, eps, embedded_order, order);
115 return fabs( h1) < fabs( h2) ? h1 : h2;
122template<
class value_type>
126 Tolerance( value_type rtol, value_type atol, value_type size) :
127 m_rtol(rtol*sqrt(size)), m_atol( atol*sqrt(size)){}
129 void operator()( value_type u0, value_type&
delta)
const{
133 value_type m_rtol, m_atol;
231template<
class Stepper>
244 template<
class ...StepperParams>
246 m_next(m_stepper.copyable()), m_delta(m_stepper.copyable())
252 template<
class ...Params>
256 *
this =
Adaptive( std::forward<Params>(ps)...);
273 class ControlFunction =
value_type (std::array<value_type,3>,
274 std::array< value_type,3>,
unsigned ,
unsigned),
282 ControlFunction control,
290 m_stepper.step( std::forward<ODE>(ode), t0, u0, m_t_next, m_next, dt,
294 m_size), u0, m_delta);
295 m_eps0 = norm( m_delta);
297 if( m_eps0 > reject_limit || std::isnan( m_eps0) )
300 dt = control( std::array<value_type,3>{m_dt0, 0, m_dt2},
301 std::array<value_type,3>{m_eps0, m_eps1, m_eps2},
302 m_stepper.embedded_order(),
304 if( fabs( dt) > 0.9*fabs(m_dt0))
308 m_failed =
true; m_nfailed++;
320 dt = control( std::array<value_type,3>{m_dt0, m_dt1, m_dt2},
321 std::array<value_type,3>{m_eps0, m_eps1, m_eps2},
322 m_stepper.embedded_order(),
325 if( fabs(dt) > 100*fabs(m_dt0))
368 void reset_history(){
369 m_eps1 = m_eps2 = 1.;
372 bool m_failed =
false;
373 unsigned m_nfailed = 0;
374 unsigned m_nsteps = 0;
377 value_type m_size, m_eps0 = 1, m_eps1=1, m_eps2=1;
379 value_type m_dt0 = 0., m_dt1 = 0., m_dt2 = 0.;
498template<
class ContainerType>
530 template<
class Adaptive,
class ODE,
class ErrorNorm =
532 ControlFunction =
value_type(std::array<value_type,3>,
533 std::array<value_type,3>,
unsigned,
unsigned)>
537 ControlFunction control,
547 m_step = [=, cap = std::tuple<Adaptive, ODE>(std::forward<Adaptive>(adapt),
548 std::forward<ODE>(ode)) ](
auto t0,
auto y0,
auto& t,
549 auto&
y,
auto& dt)
mutable
551 std::get<0>(cap).step( std::get<1>(cap), t0, y0, t,
y, dt, control, norm,
552 rtol, atol, reject_limit);
558 template<
class ...Params>
603 template<
class Domain>
606 const ContainerType& u0,
626template<
class ContainerType>
627void AdaptiveTimeloop<ContainerType>::do_integrate(
628 value_type& t_current,
629 const ContainerType& u0,
635 value_type deltaT = t1-t_current;
638 value_type& dt_current = m_dt_current.data();
640 dt_current =
forward ? 1e-6 : -1e-6;
641 if( (dt_current < 0 &&
forward) || ( dt_current > 0 && !
forward) )
642 throw dg::Error(
dg::Message(
_ping_)<<
"Error in AdaptiveTimeloop: Timestep has wrong sign! You cannot change direction mid-step: dt "<<dt_current);
645 while( (
forward && t_current < t1) || (!
forward && t_current > t1))
648 &&( (
forward && t_current + dt_current > t1)
649 || (!
forward && t_current + dt_current < t1) ) )
650 dt_current = t1-t_current;
652 &&( (
forward && dt_current > deltaT)
653 || (!
forward && dt_current < deltaT) ) )
657 m_step( t_current, u1, t_current, u1, dt_current);
663 if( !std::isfinite(dt_current) || fabs(dt_current) < 1e-9*fabs(deltaT))
665 value_type dt_current0 = dt_current;
672template<
class ContainerType>
673template<
class Domain>
676 const ContainerType& u0,
684 value_type t_current = t0, dt_current = dt;
686 ContainerType& current(u1);
691 dt_current =
forward ? 1e-6 : -1e-6;
693 ContainerType last( u0);
694 while( (
forward && t_current < t1) || (!
forward && t_current > t1))
699 if( (
forward && t_current+dt_current > t1) || (!
forward && t_current +
701 dt_current = t1-t_current;
704 m_step( t_current, current, t_current, current, dt_current);
710 if( !std::isfinite(dt_current) || fabs(dt_current) < 1e-9*fabs(t1-t0))
712 if( !domain.contains( current) )
721 for(
int j=0; j<j_max; j++)
723 if( fabs(t1-t0) < eps_root*fabs(t1) + eps_root)
727 dt_current = (t1-t0)/2.;
729 value_type failed = t_current;
735 m_step( t_current, current, t_current, current, dt_current);
736 if( failed == t_current)
738 dt_current = (t1-t0)/4.;
743 if( domain.contains( current) )
753 if( (j_max - 1) == j)
class intended for the use in throw statements
Definition: exceptions.h:83
void append(const Message &message)
Appends a message verbatim to the what string.
Definition: exceptions.h:101
small class holding a stringstream
Definition: exceptions.h:29
#define _ping_
Definition: exceptions.h:12
#define DG_DEVICE
Expands to __host__ __device__ if compiled with nvcc else is empty.
Definition: functions.h:9
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition: blas1.h:164
OutputType reduce(const ContainerType &x, OutputType zero, BinaryOp binary_op, UnaryOp unary_op=UnaryOp())
Custom (transform) reduction
Definition: blas1.h:139
void subroutine(Subroutine f, ContainerType &&x, ContainerTypes &&... xs)
; Customizable and generic blas1 function
Definition: blas1.h:618
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)
Binary reproducible Euclidean dot product between two vectors
Definition: blas1.h:87
@ forward
forward derivative (cell to the right and current cell)
Definition: enums.h:98
Operator< real_type > delta(unsigned n)
Create the unit matrix.
Definition: operator.h:514
static auto ex_control
Definition: adaptive.h:87
static auto imex_control
h_{n+1} = |ex_control| < |im_control| ? ex_control : im_control
Definition: adaptive.h:109
static auto pid_control
Definition: adaptive.h:71
static auto l2norm
Compute using dg::blas1::dot.
Definition: adaptive.h:22
to
Switch for the Timeloop integrate function.
Definition: ode.h:17
static auto i_control
Definition: adaptive.h:37
static auto pi_control
Definition: adaptive.h:43
static auto fast_l2norm
Compute using naive summation.
Definition: adaptive.h:33
static auto im_control
Definition: adaptive.h:98
@ exact
match the ending exactly
@ at_least
integrate to the end or further
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition: tensor_traits.h:38
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
An abstract ODE integrator.
Runge-Kutta explicit ODE-integrators.
Driver class for adaptive timestep ODE integration.
Definition: adaptive.h:233
const stepper_type & stepper() const
Read access to internal stepper.
Definition: adaptive.h:264
unsigned & nfailed()
Set total number of failed steps.
Definition: adaptive.h:346
void step(ODE &&ode, value_type t0, const container_type &u0, value_type &t1, container_type &u1, value_type &dt, ControlFunction control, ErrorNorm norm, value_type rtol, value_type atol, value_type reject_limit=2)
Semi-implicit adaptive step.
Definition: adaptive.h:276
stepper_type & stepper()
Allow write access to internal stepper.
Definition: adaptive.h:262
const unsigned & nfailed() const
Get total number of failed steps.
Definition: adaptive.h:342
Stepper stepper_type
Definition: adaptive.h:234
unsigned & nsteps()
Re-set total number of step calls.
Definition: adaptive.h:354
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: adaptive.h:253
typename Stepper::container_type container_type
the type of the vector class in use by Stepper
Definition: adaptive.h:235
typename Stepper::value_type value_type
the value type of the time variable defined by Stepper (float or double)
Definition: adaptive.h:236
const unsigned & nsteps() const
Get total number of step calls.
Definition: adaptive.h:350
const value_type & get_error() const
Get the latest error norm relative to solution vector.
Definition: adaptive.h:364
bool failed() const
Return true if the last stepsize in step was rejected.
Definition: adaptive.h:338
Adaptive(StepperParams &&...ps)
Allocate workspace and construct stepper.
Definition: adaptive.h:245
Integrate using a while loop.
Definition: adaptive.h:500
AdaptiveTimeloop()=default
no allocation
AdaptiveTimeloop(Adaptive &&adapt, ODE &&ode, ControlFunction control, ErrorNorm norm, value_type rtol, value_type atol, value_type reject_limit=2)
Bind the step function of a dg::Adaptive object.
Definition: adaptive.h:534
virtual AdaptiveTimeloop * clone() const
Abstract copy method that returns a copy of *this on the heap.
Definition: adaptive.h:614
dg::get_value_type< ContainerType > value_type
Definition: adaptive.h:501
AdaptiveTimeloop(std::function< void(value_type, const ContainerType &, value_type &, ContainerType &, value_type &)> step)
Construct using a std::function.
Definition: adaptive.h:512
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: adaptive.h:559
void set_dt(value_type dt)
Set initial time-guess in integrate function.
Definition: adaptive.h:575
void integrate_in_domain(value_type t0, const ContainerType &u0, value_type &t1, ContainerType &u1, value_type dt, Domain &&domain, value_type eps_root)
Integrate a differential equation within an integration domain.
ContainerType container_type
Definition: adaptive.h:502
T & data() const
Get write access to the data on the heap.
Definition: memory.h:187
The domain that contains all points.
Definition: adaptive.h:467
bool contains(T &t) const
always true
Definition: adaptive.h:470
Definition: functors.h:116
Definition: subroutines.h:82
Abstract timeloop independent of stepper and ODE.
Definition: ode.h:60