3

Can a time-based WhenEvent be triggered at the initial time within NDSolve? As a minimal example, a pulse is to be applied every integer time t, but NDSolve skips the initial pulse at t=0:

sol = NDSolve[{x'[t] == -x[t], x[0] == 0, WhenEvent[Mod[t, 1], x[t] -> x[t] + 1]},
  x, {t, 0, 1}][[1]];
Plot[x[t] /. sol, {t, 0, 1}]

enter image description here

One possible solution is to give the initial values just before t=0:

sol = NDSolve[{x'[t] == -x[t], x[-$MachineEpsilon] == 0,
  WhenEvent[Mod[t, 1], x[t] -> x[t] + 1]}, x, {t, 0, 1}][[1]];
Plot[x[t] /. sol, {t, 0, 1}]

enter image description here

but this leaves me slightly uneasy, because in general, the system will vary in the small time between t=-$MachineEpsilon and t=0. Also x[0]/.sol yields 0. instead of 1. even with this hack.

Is there a better way for such a time-based WhenEvent to be triggered at the initial time?

Chris K
  • 20,207
  • 3
  • 39
  • 74
  • 1
    Similar to your approach you can create a separate WhenEvent : WhenEvent[ t == $MachineEpsilon , .. ] Obviously for this example you could just set initial condition x[0]=1, you might want to come up with a not-so-trivial example. – george2079 Aug 09 '16 at 21:45
  • I don't think so. Unless you consider an initial condition an "event." :) – Michael E2 Aug 09 '16 at 21:45

2 Answers2

3

You could back up the initial condition so that t == 0 becomes an event, or you could effectively have a discrete variable be a switch to "turn on" the ODE at t == 0:

{sol} = NDSolve[{x'[t] == -x[t], x[-0.5] == 0, 
    WhenEvent[Mod[t, 1], x[t] -> x[t] + 1]}, x, {t, 0, 10}];
Plot[x[t] /. sol, {t, 0, 10}]

Mathematica graphics

A switch is a better way to keep the derivative x'[t] equal to zero until the first event:

{sol} = NDSolve[{x'[t] == a[t] (1 + 2 x[t] - x[t]^2), x[-1/2] == 0, 
    a[-1/2] == 0, WhenEvent[Mod[t, 1], x[t] -> x[t] + 1], 
    WhenEvent[t == 0, a[t] -> 1]},
   x, {t, 0, 10}, 
   DiscreteVariables -> {a}];
Plot[x[t] /. sol, {t, 0, 10}, PlotRange -> All]

Mathematica graphics

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • BTW, the simpler NDSolve[{x'[t] == UnitStep[t] (1 + 2 x[t] - x[t]^2), x[-1/2] == 0, WhenEvent[Mod[t, 1], x[t] -> x[t] + 1]}, x, {t, 0, 10}] fails to integrate, but I don't know why.... – Michael E2 Aug 09 '16 at 22:10
2

I have a simple mind, so I wonder why you can't just code the initial impulse into the initial condition.

sol =
  NDSolve[{x'[t] == -x[t], x[0] == 1, WhenEvent[Mod[t, 1], x[t] -> 1]},
    x, {t, 0, 3}][[1]];
Plot[x[t] /. sol, {t, 0, 3}]

plot

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
  • That's the obvious solution, but my real problem algorithmically generates the arguments for NDSolve within a function, so I'd have to parse out the user-supplied WhenEvents and then apply them to the user-supplied initial conditions. That's why I'm looking for a simpler solution that applies the WhenEvents at the initial time. – Chris K Aug 10 '16 at 13:45