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{
130 delta = delta/ ( m_rtol*fabs(u0) + m_atol);
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>
544 template<
class Adaptive,
class ODE,
class ErrorNorm =
546 ControlFunction =
value_type(std::array<value_type,3>,
547 std::array<value_type,3>,
unsigned,
unsigned)>
551 ControlFunction control,
561 m_step = [=, cap = std::tuple<Adaptive, ODE>(std::forward<Adaptive>(adapt),
562 std::forward<ODE>(ode)) ](
auto t0,
const auto& y0,
auto& t,
563 auto&
y,
auto& dt)
mutable
565 std::get<0>(cap).step( std::get<1>(cap), t0, y0, t,
y, dt, control, norm,
566 rtol, atol, reject_limit);
572 template<
class ...Params>
617 template<
class Domain>
620 const ContainerType& u0,
635 virtual value_type do_dt( )
const {
return m_dt_current;}
640template<
class ContainerType>
641void AdaptiveTimeloop<ContainerType>::do_integrate(
642 value_type& t_current,
643 const ContainerType& u0,
649 value_type deltaT = t1-t_current;
652 value_type& dt_current = m_dt_current;
654 dt_current =
forward ? 1e-6 : -1e-6;
655 if( (dt_current < 0 &&
forward) || ( dt_current > 0 && !
forward) )
656 throw dg::Error(
dg::Message(
_ping_)<<
"Error in AdaptiveTimeloop: Timestep has wrong sign! You cannot change direction mid-step: dt "<<dt_current);
659 while( (
forward && t_current < t1) || (!
forward && t_current > t1))
662 &&( (
forward && t_current + dt_current > t1)
663 || (!
forward && t_current + dt_current < t1) ) )
664 dt_current = t1-t_current;
666 &&( (
forward && dt_current > deltaT)
667 || (!
forward && dt_current < deltaT) ) )
671 m_step( t_current, u1, t_current, u1, dt_current);
677 if( !std::isfinite(dt_current) || fabs(dt_current) < 1e-9*fabs(deltaT))
679 value_type dt_current0 = dt_current;
686template<
class ContainerType>
687template<
class Domain>
690 const ContainerType& u0,
698 value_type t_current = t0, dt_current = dt;
700 ContainerType& current(u1);
705 dt_current =
forward ? 1e-6 : -1e-6;
707 ContainerType last( u0);
708 while( (
forward && t_current < t1) || (!
forward && t_current > t1))
713 if( (
forward && t_current+dt_current > t1) || (!
forward && t_current +
715 dt_current = t1-t_current;
718 m_step( t_current, current, t_current, current, dt_current);
724 if( !std::isfinite(dt_current) || fabs(dt_current) < 1e-9*fabs(t1-t0))
726 if( !domain.contains( current) )
735 for(
int j=0; j<j_max; j++)
737 if( fabs(t1-t0) < eps_root*fabs(t1) + eps_root)
741 dt_current = (t1-t0)/2.;
743 value_type failed = t_current;
749 m_step( t_current, current, t_current, current, dt_current);
750 if( failed == t_current)
752 dt_current = (t1-t0)/4.;
757 if( domain.contains( current) )
767 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
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition blas1.h:243
OutputType reduce(const ContainerType &x, OutputType zero, BinaryOp binary_op, UnaryOp unary_op=UnaryOp())
Custom (transform) reduction
Definition blas1.h:215
void subroutine(Subroutine f, ContainerType &&x, ContainerTypes &&... xs)
; Customizable and generic blas1 function
Definition blas1.h:677
auto dot(const ContainerType1 &x, const ContainerType2 &y)
Binary reproducible Euclidean dot product between two vectors
Definition blas1.h:153
@ forward
forward derivative (cell to the right and current cell)
Definition enums.h:98
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition tensor_traits.h:45
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
#define DG_DEVICE
Expands to __host__ __device__ if compiled with nvcc else is empty.
Definition dg_doc.h:378
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:548
virtual AdaptiveTimeloop * clone() const
Abstract copy method that returns a copy of *this on the heap.
Definition adaptive.h:628
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:526
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition adaptive.h:573
void set_dt(value_type dt)
Set initial time-guess in integrate function.
Definition adaptive.h:589
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
The domain that contains all points.
Definition adaptive.h:467
bool contains(T &t) const
always true
Definition adaptive.h:470
Definition subroutines.h:73
Abstract timeloop independent of stepper and ODE.
Definition ode.h:60