# How can I get WhenEvent to recognize criterion I specify?

Using NDSolve I want to solve a differential equation till a quantity which is a function of the dependent variables reaches a certain value. My functions and criteria are complicated, but I am able to reproduce the error with a simple DE:

a[t_] := x[t]^2
NDSolve[{x'[t] == Sin[t]^2, x[0] == 0,
WhenEvent[a[t] == 1, "StopIntegration"]}, {x}, {t, 0, 10}]


Here is the error message I get:

NDSolve::nbnum1: "The function value x[0.00205297]^2==1 is not True or False when the arguments are {0.00205297,5.40788*10^-9,4.21468*10^-6}."

Any Ideas would be great

-

Need to evaluate it

a[t_] := x[t]^2
NDSolve[{x'[t] == Sin[t]^2, x[0] == 0,
WhenEvent[Evaluate[a[t] == 1], "StopIntegration"]}, {x}, {t, 0, 10}]


Notice the attribute HoldAll on the function WhenEvent

?? WhenEvent
Attributes[WhenEvent]={HoldAll,Protected}


-

Nasser has shown you a minimal change which will solve your problem. I still would like to add two suggestions which might make your life easier when dealing with more complicated cases:

# reformulate stopping criterion

in another answer which might be of interest I am postulating that it often pays off to try to be as precise as possible when formulating your problem to be solved with Mathematica, and I believe this is also such a case. You are writing your stopping condition as a function of t, but actually it is a function of x[t]. It's exactly that "hiding" of the real dependence which makes the WhenEvent not work without the Evaluate. If you rewrite the stopping criterion as a function of x[t], no Evaluate is necessary, and I think the code also reflects more correctly what the actual dependencies are:

a[x_] := x^2
NDSolve[{x'[t] == Sin[t]^2, x[0] == 0,
WhenEvent[a[x[t]] == 1, "StopIntegration"]}, {x}, {t, 0, 10}]


# make criterion numerically robust

while the above does work, I'm not sure whether or not the WhenEvent will actually work might depend on the step sizes taken by the solver: if these happen to be too large in the area where the stopping condition is met the event might be overseen. In principle, as the symbolic form is known, NDSolve could be written to take such problems into account and detect the event nevertheless. The documentation of WhenEvent and the answer to this question seems to indicate that this might indeed be done since version 9, but I probably wouldn't count on that: I know that the older way of doing things like that with Method -> "EventLocator" did not always detect such cases. It's fairly simple to rewrite the WhenEvent so that it will work without dependencies on such advanced event detection or step sizes for the given example, e.g.:

a[x_] := x^2
sol = First[
x /. NDSolve[{x'[t] == Sin[t]^2, x[0] == 0,
WhenEvent[a[x[t]] >= 1, "StopIntegration"]}, {x}, {t, 0, 10}]]


it might, on the other hand not be necessary anymore...

-
I get the same error with this line (notice that phi(x,t) is my unknown function in NDSolve): WhenEvent[\[Phi][x, t] == 0, TsingE = t; Print[TsingE]; "StopIntegration"] I reckon is the same error, but doesnt' go away with any of your solutions. – usumdelphini Mar 20 '14 at 19:21
@usumdelphini: it is difficult to analyze what's going wrong without seeing the actual code. If the above suggestions don't help for your case I'd suggest to write a new question with giving more details, especially a working example will always help wonders to generate useful answers... – Albert Retey Mar 21 '14 at 10:34