# WhenEvent for equation defined outside NDSolve

Say i want to use WhenEvent to specify a value of R[s] when my function Dsonic[s]==-3. For some reason i get an error message. Seems that mathematica cannot read my function. Here is my code. Thank you

q0 = 5.3;
ε0 = 2.2;
Γ = 5/3;
μ = 0.001;
ψ0 = 40;
l = μ/2;
Ω0 = 10.112;

h0[s_] := Sqrt[1 - (R[s]* μ)/(l^2 + R[s]^2)]
U0[s_] := (4 π ψ0 (ε0^2 - h0[s]^2 (q0 Δ0[s]^(1 - Γ) + 1)^2))^(1/2)
sM0[s_] := Δ0[s] + q0 Δ0[s]^(2 - Γ)
sG[s_] := sM0[s]/U0[s]
Dsonic[s_] := (-(-1 + Γ) ε0^2 + (-2 + Γ) ε0^2 (q0 Δ0[s]^(1 - Γ) + 1) +
h0[s]^2 (q0 Δ0[s]^(1 - Γ) + 1)^3)
dΔ0[s_] := (q0 Δ0[s] +
Δ0[s]^Γ) ε0^2 (-2 R[s]^2 + (l^2 + R[s]^2) F[s]) Δ0[s]^(2 Γ)

dF[s_] := F[s]*Dsonic[s] + (F[s]^2 (h0[s]^2 - sM0[s]))/(
4 π R[s]^2 sG[s]^2)*Dsonic[s]

Rinit = 0.05;
ξinit = 1.8;
Δinit = ((ξinit - 1)/q0)^(1/(1 - Γ));
Finit = 1.2;
smax = 0.0002233658;
sol = NDSolve[{F'[s] == dF[s], Δ0'[s] == dΔ0[s]*Dsonic[s],
R'[s] == Dsonic[s],  F[0] == Finit, Δ0[0] == Δinit, R[0] == Rinit,
WhenEvent[Dsonic[s] == -3, Print[R[s]]]}, {F, Δ0, R}, {s, 0,
smax}];

ParametricPlot[{R[s], Dsonic[s]} /. sol, {s, 0, smax},
AspectRatio -> Full]


Use Evaluate:

WhenEvent[Evaluate[Dsonic[s] == -3], Print[R[s]]]


WhenEvent is a bit tricky in that the event is constructed from the code. Any state variables must be literally present in the code. If they appear in a function, use Evaluate or inject the code with something like With[]. Another alternative is to make the state variables arguments of the function Dsonic.

Appendix

Alternative 1:

With[{evt = Dsonic[s] == -3},
sol = NDSolve[{F'[s] == dF[s], \[CapitalDelta]0'[s] ==
d\[CapitalDelta]0[s]*Dsonic[s], R'[s] == Dsonic[s],
F[0] == Finit, \[CapitalDelta]0[0] == \[CapitalDelta]init,
R[0] == Rinit, WhenEvent[evt, Print[R[s]]]}, {F, \[CapitalDelta]0,
R}, {s, 0, smax}]
]


Alternative 2:

(* rather a lot of code refactoring to add arguments to
*    h0[], U0[], sM0[], sG[], Dsonic[], d\[CapitalDelta]0[], dF[]
* for the state variables F[s], \[CapitalDelta]0[s], R[s]
*)
(* coding left as an exercise for the reader *)

• I am not quite sure i understand the alternative. But this works so thank you very much Feb 17 at 18:07
• @Agaph You're welcome. Added the With[] alternative to the answer, assuming you meant that alternative. Feb 17 at 21:02
• Thank you again. I have been doing the last tedious method which really counter productive and I try to avoid it but didn't know how till you answered. The expressions are quite large. This is just a working example so i can answer my question Feb 19 at 18:26