8

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!

keanhy14
  • 469
  • 2
  • 9
  • By the way your code doesn't work well... – Ulrich Neumann Dec 10 '19 at 09:19
  • @UlrichNeumann OP's code works as illustrated in v11.3. – xzczd Dec 10 '19 at 09: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 09: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
  • @xzczd Thanks for your profound explanation! That means the solutions found in Options of WhenEvent aren't valid anymore? – Ulrich Neumann Dec 10 '19 at 11:16
  • @UlrichNeumann The explanation therein is consistent with mine, if I've understood it correctly. As mentioned there: "The gist of the docs is that an event is triggered when the value of A changes from False to True…… The form Mod[..] == 0 is another special case " But the emphasis is a little different, and we just can't use the solution there mechanically. – xzczd Dec 10 '19 at 11:33
  • @xzczd In v12 it seems to be necessary to use event[t]//Evaluate, in the link event[t] was sufficient. – Ulrich Neumann Dec 10 '19 at 12:14
  • @UlrichNeumann I think this is the specialness of Mod[…] == 0, which is not discussed in detail in that answer. – xzczd Dec 10 '19 at 12:24

1 Answers1

11

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]}]]
xzczd
  • 65,995
  • 9
  • 163
  • 468
  • Thanks for your explanation of the Detail in the docs, and it really works! – keanhy14 Dec 10 '19 at 10:07
  • @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 05: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 06:07
  • You have thought about this more than I have. Do you plan to report it to Wolfram, Inc.? – bbgodfrey Dec 11 '19 at 12:04
  • @bbgodfrey I haven't thought out a good way to summarize these, or perhaps I should file every example as a separate report? Something funnier: WhenEvent[Mod[t, 2 \[Pi]] == 0 && t > (2 Pi - 10^-6) // Evaluate, Sow[t]] works, but WhenEvent[Mod[t, 2 \[Pi]] == 0 && t > (2 Pi - 10^-6), Sow[t]] doesn't work. – xzczd Dec 11 '19 at 12:44
  • Perhaps, Evaluate turns Mod[t, 2 \[Pi]] == 0 && t > (2 Pi - 10^-6) into a single pred in the eyes of WhenEvent. – bbgodfrey Dec 11 '19 at 12:50
  • @bbgodfrey This seems to be related to the FullForm of 2 Pi - 10^-6, With[{number = 2 Pi - 10^-6}, WhenEvent[Mod[t, 2 \[Pi]] == 0 && t > number, Sow@t]] again works 囧 . – xzczd Dec 11 '19 at 12:59
  • But, not if number = 2 Pi - 10^-6 is included as a local variable in Block instead. – bbgodfrey Dec 11 '19 at 13:11
  • 1
    @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