0

I have noticed strange behavior of WhenEvent in the case where the body of WhenEvent is satisfied in the first step. For example,

NDSolve[{y'[x] == y[x], y[0] == 1, 
  WhenEvent[
   y[x] > 1, {"StopIntegration"}]}, y, {x, 0, 
  10}]

integrates equation until x=10 (and not x=0). However, if I put

NDSolve[{y'[x] == y[x], y[0] == 1, 
  WhenEvent[
   y[x] > 1 || (x > 2 && y[x] > 1), {"StopIntegration"}]}, y, {x, 0, 
  10}]

domain of integration will be 1.43*10^-14., while I would expect that domain is either 0 or 1. This is just an example of the more complicated ParametricNDSolve that I am working with. I would like to understand why is this happening and how could I require that if the body is satisfied in the first step, domain of integration becomes 0 or 1 or some other arbitrary number that I want.

  • 1
    (1) An "event" is a *change* in a condition from False to True. If the condition starts in the True state, then it is not an event for it to remain true. (2) The conditions y[x] > 1, y[x] == 1, and y[x] < 1 are each a special form of y[x] == 1. They each detect y[x] *crossing* the value 1 in one of three ways: increasing, either increasing or decreasing, or decreasing, respectively. This is in the docs under "Details and Options." Starting at the value 1, y[x] cannot *cross* it. – Michael E2 Nov 01 '20 at 20:40
  • thanks for this. but do you have any suggestion how to go around the issue i.e. I am working with family of ODEs with ParametricNDSolve and I would like to know for what parameter values WhenEvent condition is falsified from the start. – Thela Hun Ginjeet Nov 01 '20 at 20:48
  • I should maybe explain one more point, but it does not apply here. "Increasing" means y[x] was below 1 before the step and y[x] was above 1 after the step. Similarly for "decreasing." When the step (change in x) is negative, this definition of "increasing" means the slope (y'[x]) is negative. Likewise for "decreasing." – Michael E2 Nov 01 '20 at 20:49
  • Maybe: psol = ParametricNDSolveValue[sys, vars, params,...]; trial[paramvals_] := If[<test paramvals for WhenEvent condition>, $Failed, psol[paramvals]] and test parameter settings by calling trial[] on them, which would call psol only when appropriate. – Michael E2 Nov 01 '20 at 20:53
  • 1
    Related/duplicate: https://mathematica.stackexchange.com/questions/39374/inconsistent-behavior-of-whenevent – Michael E2 Nov 01 '20 at 21:12
  • 1
    See also https://mathematica.stackexchange.com/questions/123550/whenevent-applied-at-initial-time – Chris K Nov 02 '20 at 00:08

1 Answers1

2

I don't recommend this hack, but it is a way to make > mean greater than in WhenEvent:

NDSolve[{y'[x] == y[x], y[0] == 1, 
  WhenEvent[
   EvenQ[0] && y[x] > 1,  (* A && B is a special form in which B is treated 
                             as a regular boolean propostion  *)
   {"StopIntegration"}]},
 y, {x, 0, 10}]

[There are several special-case forms of an event A that are described in the docs for WhenEvent. It is not always treated strictly as a logical proposition. With the hack above, you lose the advantage of these special cases.]

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • For the event, you should be able to use any expression logically equivalent to y[x] > 1 as long as it does not have the head Greater or Less (nor is one of the other special cases). For instance, Identity[y[x] > 1] works. – Michael E2 Nov 01 '20 at 23:10