# WhenEvent fails in NDSolve

The code with one condition Mod[t, 2 π] == 0

data = Block[{d = 0.15, r = 0.3},
Reap[NDSolve[{x''[t] + d x'[t] - x[t] + x[t]^3 == r Cos[ t],
x[0] == 0, x'[0] == 0,
WhenEvent[Mod[t, 2 π] == 0(*&&t>50*),
Sow[{t, x[t], x'[t]}]]}, {}, {t, 0, 100},
MaxSteps -> ∞]]]


works well in v11.3, and gives the data as below

{{{}}, {{{6.28319, 0.895631,
0.418075}, {12.5664, -1.21673, -0.312119}, {18.8496, -0.405354,
0.587376}, {25.1327, -0.254392, -0.19556}, {31.4159, -0.40937,
0.151545}, {37.6991, -0.141298, 0.702613}, {43.9823, -1.09087,
1.0678}, {50.2655, -0.921924, -0.607913}, {56.5487, -0.594581,
0.48939}, {62.8319, 1.09998, -0.105309}, {69.115, 1.19792,
0.541834}, {75.3982, -1.09163, -0.417725}, {81.6814, -0.479742,
0.483879}, {87.9646, 0.846189,
0.400168}, {94.2478, -1.28112, -0.186879}}}}


However, when conditions Mod[t, 2 π] == 0&&t>50 are applied, the data for t>50 is not outputed. Somebody can explain it? Any suggestions would be much appreciated!

• Perhaps Options of WhenEvent might help. Dec 10, 2019 at 8:57
• By the way your code doesn't work well... Dec 10, 2019 at 9:19
• @UlrichNeumann OP's code works as illustrated in v11.3. Dec 10, 2019 at 9:24
• @xzczd You're right, I tried it with an event-function event[t_] := Mod[t, 2 \[Pi]] == 0 : MMA v12 evaluates {{{}}, {}} in this case. Dec 10, 2019 at 9:33
• @UlrichNeumann This can be explained in a manner similar to my answer below. Since WhenEvent has the attribute HoldAll, when this intermediate function is introduced, WhenEvent only sees a event[t], so, as mentioned in the Details and Options section of WhenEvent, it uses the strategy for pred to detect the event i.e. the event is detected only if the predicate pred becomes True, which is almost impossible, while when one directly write Mod[t, 2 Pi] == 0 or use event[t]//Evaluate to make it explicit, WhenEvent will see it and turn to the specialized strategy. Dec 10, 2019 at 11:09

I'm not sure how to explain this behavior, but I've found a solution. Just move the condition to 2nd argument of WhenEvent:
WhenEvent[Mod[t, 2 π] == 0, If[t > 50, Sow@{t, x[t], x'[t]}]]

• @keanhy14 I've removed the explanation part, because it seems to be incorrect, at least incomplete. Consider the following: WhenEvent[Mod[t, 2 \[Pi]] == 0 && Mod[t, 2 \[Pi]] == 0, Sow[{t, x[t], x'[t]}]]. The underlying issue is more intricate than I thought. You may have a look at the linked answer together with my comment there. Dec 10, 2019 at 13:46
• Consider the example beginning "Use an event y(t)==0 with the condition x(t)>0" under Scope/Events in the WhenEvent documentation, which looks somewhat like the usage in the question. It works fine. However, if y[t] = 0 is replaced by Mod[t, 2], it does not work. Referring to the Details and Options section of the documentation, even though "f == 0 && pred" is an acceptable event, evidently "Mod[t, [CapitalDelta]t] == 0 && pred" is not. Dec 11, 2019 at 5:54
• @bbgodfrey Yeah, the behavior of 3 types of condition (f==0 || f>0 || f<0, Mod[…]==0, pred that doesn't belong to the former two) is really confusing inside And: Mod[…]==0 seems never work; f == 0 && pred or f == 0 && g > 0 seems to be triggered when f == 0 changes from False to True, and pred or g>0 is True; pred1 && pred2 is triggered when either of the conditions changes from False to True, and the other one is True; there may be more. If WhenEvent is designed to behave like this, then it's really a bad design. Dec 11, 2019 at 6:07
• @bbgodfrey Yeah, and I think the underlying issue is similar: WhenEvent only sees the variable number rather than the number inside. BTW, I've filed a report with 5 confusing examples just now. If the reply from WRI isn't great, I'll post it as a separate question here. Dec 11, 2019 at 13:41