# Inconsistent behavior of WhenEvent[ ]

Consider the following simple example:

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

Clearly WhenEvent[] is missing the x[t] > 2 occurrence. This may happens (my interpretation) if the event detection routine checks for the occurrence of the first part of the AND clause and then for the other AND components, instead of checking them as an OR event trigger. As the Abs[x[t]] > 1 event isn't fired again between 1 and 2, the rest of the AND clause doesn't get tested again.

In testing this interpretation, we can reverse the clause:

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

which now works as expected. Of course this isn't a proof.

But the strange thing is that reverting to the first version, but encapsulating the clause in a function, also works as expected:

clause[p_] := Abs[p] > 1 && p > 2
sol = NDSolve[{x''[t] == 1, x'[0] == 0, x[0] == 0,
WhenEvent[clause[x[t]], {x'[t] -> -3 x'[t]}]}, x[t], {t, 0, 4}];
Plot[x[t] /. sol[[1]], {t, 0, 4}]

So, what is the moral? Always put your WhenEvent[] clause as a function?

-
Even weirder: try WhenEvent[Null;Abs[x[t]]>1&&x[t]>2,{x'[t]->-3x'[t]}].. –  Silvia Dec 24 '13 at 18:28
@Silvia That's crazy. Perhaps the WhenEvent[ ] thing isn't mature enough –  belisarius Dec 24 '13 at 19:25

From WhenEvent:

Examples of events and how $t_a$ is determined include:
...
f == 0 && pred -- f crosses zero and pred is True

I believe that the same special case is applied to And for froms f > 0 && pred, etc.

So

WhenEvent[Abs[x[t]] > 1 && x[t] > 2, {x'[t] -> -3 x'[t]}]

means the event will be triggered when Abs[x[t]] crosses 1 and x[t] > 2, which is never.

Next,

WhenEvent[x[t] > 2 && Abs[x[t]] > 1, {x'[t] -> -3 x'[t]}]

means the event will be triggered when x[t] crosses 2 and Abs[x[t]] > 1, which will be whenever x[t] crosses 2.

Finally, both

WhenEvent[clause[x[t]], {x'[t] -> -3 x'[t]}]
WhenEvent[Null; Abs[x[t]] > 1 && x[t] > 2, {x'[t] -> -3x'[t]}]

do not have the head And, so the special case is not applied; they will trigger an event whenever they change from False to True.

-
I've read the docs, but I understood them as a simple application of logic. Your interpretation (probably correct) seems dangerous because you have to be sure to cover all the possible timelines with OR clauses ... or just encapsulate the whole thing as a function which is probably worse from the performance POV –  belisarius Dec 25 '13 at 4:23
@belisarius It could be that only crossings, such as f == 0, were meant to be special-cased, and you've found a bug. Clearly f == 0 has to be a special case, and one would want to allow conditions to be placed on which crossings trigger events. But && here seems to behave logically like "when", and that's unintuitive. –  Michael E2 Dec 25 '13 at 4:42
@belisarius Practically speaking, the Equal statements are never true. The solver looks for a change in sign (or a crossing). Try it with clause[p_] := p == 2 && Abs[p] > 1. –  Michael E2 Dec 25 '13 at 5:01
There is a saying in Spanish. I don't really know if it makes sense in English "Among firefighters we will not step on the hose." –  belisarius Dec 25 '13 at 5:13
@belisarius I didn't mean that either. I just meant I don't think my friends will understand it. :) –  Michael E2 Dec 25 '13 at 5:16