# 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. – Ulrich Neumann Dec 10 '19 at 8:57
• By the way your code doesn't work well... – Ulrich Neumann Dec 10 '19 at 9:19
• @UlrichNeumann OP's code works as illustrated in v11.3. – xzczd Dec 10 '19 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. – Ulrich Neumann Dec 10 '19 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. – xzczd Dec 10 '19 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. – xzczd Dec 10 '19 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. – bbgodfrey Dec 11 '19 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. – xzczd Dec 11 '19 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. – xzczd Dec 11 '19 at 13:41