How do I define and use variables within WhenEvent in NDSolve

Hi!

I’m having a really bizarre issue with WhenEvent–when I define a variable as some equation involving the variables that are defined and used in NDSolve, I get the following error: NDSolve::nbnum1: The function value Abs[x[t]-y[t]]>0.01 is not True or False when the arguments are {0.,0.3,0.2,0.3,0.2}.

However, when I input the equation as it is (not previously defined as a variable), the solver runs fine. Here’s a simplified version of my code.

variable = Sqrt[Abs[x[t] - y[t]]^2]
times = {};
Print["Current time step in ODE solution ="];
Monitor[
  s = NDSolve[{x'[t] == x[t], y'[t] == y[t], y[0] == 0.2, x[0] == 0.3,
      WhenEvent[variable > 0.01, Print[2]]}, {x[t], y[t]}, {t, 0, 
     tAnneal}, Method -> {"EquationSimplification" -> "Residual"}, 
    EvaluationMonitor :> AppendTo[times, t]], times[[-1]] ];

This version throws an error. However, when I input

times = {};
Print["Current time step in ODE solution ="];
Monitor[
  s = NDSolve[{x'[t] == x[t], y'[t] == y[t], y[0] == 0.2, x[0] == 0.3,
      WhenEvent[Sqrt[Abs[x[t] - y[t]]^2] > 0.01, Print[2]]}, {x[t], 
     y[t]}, {t, 0, tAnneal}, 
    Method -> {"EquationSimplification" -> "Residual"}, 
    EvaluationMonitor :> AppendTo[times, t]], times[[-1]] ];

it works fine. This is an issue for me because I have a big datastructure with such equations for many different variables, and I need to be able to call an element of that list rather than writing in the equation itself.

Thank you for any help you all can give me!
Kaden

Use:

With[{variable = variable}, WhenEvent[variable > 0.01, Print[2]]]

or

WhenEvent[Evaluate[variable > 0.01], Print[2]]

NDSolve makes a literal analysis of the code, replacing occurrences of state variables like x[t] and y[t] by symbols that represent their values at each time step. Since WhenEvent has the attribute HoldAll, the code in the first argument of WhenEvent[variable > 0.1,...] is literally the unevaluated variable > 0.1. So when NDSolve sets up the internal handler for the event, there appear to be no instances of x[t] or y[t] to be replaced, Later variable is evaluated, but the values have been mapped to internal variables. The expressions x[t] etc. remain x[t] etc., and you get an error “Abs[x[t]-y[t]]>0.01 is not True or False”.

The trick above in both cases above is to replace the unevaluated variable with its value.

Thank you so much! I figured there was something wrong about the order in which it replaced x[t] vs other variables but I had no idea how to fix it. I really appreciate it!

You’re welcome!