# Triggering WhenEvent as a result of WhenEvent

I'm attempting to solve a dead-simple differential equation with events:

y[t] /. First@DSolve[
{y[0] == 0, y'[0] == 0, y''[t] == 0,
WhenEvent[t == 1, y'[t] -> y'[t] + 1],
WhenEvent[t == 2, y'[t] -> y'[t] - 1],
WhenEvent[y[t] == 0, y'[t] -> 0],
WhenEvent[y'[t] > 1/2, y'[t] -> y'[t] - 1/2]},
y[t], {t, 0, 4}]


The result is not what I expected, the y'[t] > 1/2 event does't trigger:

$$\begin{cases} 0 & 0\leq t\leq 1 \\ t-1 & 1

I can work around this condition with a hack which includes the change in y'[t] whenever it may change accordingly:

y[t] /. First@DSolve[
{y[0] == 0, y'[0] == 0, y''[t] == 0,
WhenEvent[t == 1, y'[t] -> y'[t] + 1 + If[-1/2 < y'[t] < 1/2, -1/2, 0]],
WhenEvent[t == 2, y'[t] -> y'[t] - 1],
WhenEvent[y[t] == 0, y'[t] -> 0]},
y[t], {t, 0, 4}]


$$\begin{cases} 0 & 0\leq t\leq 1 \\ \frac{t-1}{2} & 1

This is the answer I expected.

Is there a way to make the first differential equation specification work like the second does, and if not, should this be considered a bug?

• I always assumed that WhenEvents would be triggered only by the differential equations, not by another WhenEvent. Otherwise I could imagine an infinite loop between different events could occur. But I couldn't find this in the documentation. – Chris K Jun 10 at 8:25
• @ChrisK This also came to my mind. Such a limitation would prevent solving a large family of well-behaved systems, though. Sadly static reasoning about sensibility of an input is not realistic, so if the non-recursion is really a feature, it should be clearly documented. – kirma Jun 10 at 8:33
• @kirma Do you plan to report this matter as a bug? – bbgodfrey Jun 10 at 15:12
• @kirma Great. There seem to be several interrelated bugs here. I just added a sentence on "DetectionMethod" -> "Sign" to the answer, which identifies still another problem. I can email to you my notebook, if you wish. – bbgodfrey Jun 10 at 16:50
• @kirma I shall clean up the notebook and send it to you in a few hours. Thanks. – bbgodfrey Jun 10 at 19:48

This is more an extended comment than an answer. I first tried as a work-around to set the "DetectionMethod" option in WhenEvent, but doing so caused DSolve not to evaluate. (Even "DetectionMethod" -> "Sign" causes DSolve not to execute, even though "Sign" is the default detection method!) I then tried introducing a discrete variable,

DSolveValue[{y[0] == 0, y'[0] == 0, a[0] == 0, y''[t] == 0,
WhenEvent[t == 1, {y'[t] -> y'[t] + 1, a[t] -> 1}],
WhenEvent[t == 2, y'[t] -> y'[t] - 1],
WhenEvent[y[t] == 0, y'[t] -> 0],
WhenEvent[a[t] == 1, {[y'[t] -> y'[t] - 1/2, a[t] -> 0}]},
y[t], {t, 0, 4}, DiscreteVariables -> {a}]


but doing so yielded the same result first presented in the question.

I then investigated how NDSolve would handle the same equations.

NDSolveValue[{y[0] == 0, y'[0] == 0, y''[t] == 0,
WhenEvent[t == 1, y'[t] -> y'[t] + 1],
WhenEvent[t == 2, y'[t] -> y'[t] - 1],
WhenEvent[y[t] == 0, y'[t] -> 0],
WhenEvent[y'[t] > 1/2, y'[t] -> y'[t] - 1/2]},
y[t], {t, 0, 4}];
Plot[%, {t, 0, 4}, AxesLabel -> {t, y}, ImageSize -> Large, LabelStyle -> {Bold, Black, 15}]


which is numerically the same as the DSolve answer. The "DetectionMethod" option in WhenEvent does not prevent NDSolve from evaluating, but it does not give the desired answer either. However, introducing a discrete variable,

NDSolveValue[{y[0] == 0, y'[0] == 0, a[0] == 0, y''[t] == 0,
WhenEvent[t == 1, {y'[t] -> y'[t] + 1, a[t] -> 1}],
WhenEvent[t == 2, y'[t] -> y]'[t] - 1],
WhenEvent[y[t] == 0, y'[t] -> 0],
WhenEvent[a[t] == 1, {y'[t] -> y'[t] - 1/2, a[t] -> 0}]},
y[t], {t, 0, 4}, DiscreteVariables -> {a}]

Plot[%, {t, 0, 4}, AxesLabel -> {t, y}, ImageSize -> Large, LabelStyle -> {Bold, Black, 15}]


now produces the desired answer. That DSolve and NDSolve yield different answers for the same equations and the same options does seem like a bug to me.