5
$\begingroup$

I want to find for which t any of these holds: x[t] + y[t] == 0.25, x[t] + y[t] == 0.5, x[t] + y[t] == 0.75.

I did it in two steps - firstly I solved differential equations then I used FindRoot.

But I guess there might be a method to do it in one step inside NDSolveValue.

Might be StepMonitor and EvaluationMonitor of any use here to catch whenever sum x[t] + y[t] reaches some required value?

Or can it be done by other means?

nds = NDSolveValue[{y'[t] + x[t] == 1, y[t] + 2 x'[t] == 1, y[0] == 0, x[0] == 0}, {x[t], y[t]}, {t, 0, 1}]; FindRoot[# + #2 == 0.25 & @@ nds, {t, 0.5}] FindRoot[# + #2 == 0.5 & @@ nds, {t, 0.5}] FindRoot[# + #2 == 0.75 & @@ nds, {t, 0.5}] 

{t -> 0.176619} {t -> 0.376373} {t -> 0.60538} 

(It should be assumed that differential equations do not have analytical solution of course.)

$\endgroup$
0

2 Answers 2

8
$\begingroup$
  • Maybe WhenEvent.
sol = NDSolveValue[{y'[t] + x[t] == 1, y[t] + 2 x'[t] == 1, y[0] == 0, x[0] == 0, WhenEvent[x[t] + y[t] == .25, Sow@t], WhenEvent[x[t] + y[t] == .5, Sow@t], WhenEvent[x[t] + y[t] == .75, Sow@t]}, {x[t], y[t]}, {t, 0, 1}] // Reap sol//Last 

{{0.176619, 0.376373, 0.60538}}

  • reply to comment (the add a comment button does not work on my browser today) It seems that only when the switching event occur, WhenEvent takes effect.

Appended by @azerbajdzan:

Events can be entered as (evaluated) list in one WhenEvent.

NDSolveValue[{y'[t] + x[t] == 1, y[t] + 2 x'[t] == 1, y[0] == 0, x[0] == 0, WhenEvent[x[t] + y[t] == # & /@ {0.25, 0.5, 0.75} // Evaluate, Sow@t]}, {x[t], y[t]}, {t, 0, 1}] // Reap // Last 

{{0.176619, 0.376373, 0.60538}} 
$\endgroup$
3
  • $\begingroup$ I was concentrating on options of NDSolve that I forget about WhenEvent is not an option. $\endgroup$ Commented Aug 20 at 12:16
  • $\begingroup$ Why WhenEvent[Or @@ (x[t] + y[t] == # & /@ {0.25, 0.5, 0.75}), Sow@t] does not work? $\endgroup$ Commented Aug 20 at 12:16
  • $\begingroup$ It does not work with Or but with list of events as (x[t] + y[t] == # & /@ {0.25, 0.5, 0.75}) // Evaluate but Evaluate is necessary. $\endgroup$ Commented Aug 20 at 12:31
5
$\begingroup$

But I guess there might be a method to do it in one step inside NDSolveValue.

Just for fun, such a Method indeed exists, it's "EventLocator" method, but since WhenEvent is introduced in version 9, it's seldom used nowadays:

{nds, {pts}} = Reap@NDSolveValue[{y'[t] + x[t] == 1, y[t] + 2 x'[t] == 1, y[0] == 0, x[0] == 0}, {x[t], y[t]}, {t, 0, 1}, Method -> {"EventLocator", "Event" -> (x[t] + y[t] - # & /@ (Range[3]/4)), "EventAction" :> Sow[t]}]; pts (* {0.176619, 0.376373, 0.60538} *) 
$\endgroup$
4
  • $\begingroup$ Is this the same as cvgmt answer only differently written code or it uses completely different algorithm? $\endgroup$ Commented Aug 20 at 15:38
  • $\begingroup$ @azerbajdzan To be honest, I don't know. I do long suspect that WhenEvent is merely a wrapper for EventLocator, but don't find enough evidence. And it's worth pointing out that, the pre-processing of the 2 approaches are different, compare np = NDSolve`ProcessEquations; sys = {y''[t] + Sin[y[t]] == 0, y'[0] == 0, y[0] == 1}; np[sys, y, {t, 0, 10}, Method -> {"EventLocator", "Event" -> y[t]}][[1]]@"Events" and np[{sys, WhenEvent[y[t] == 0, "StopIntegration"]}, y, {t, 0, 10}][[1]]@"Events". $\endgroup$ Commented Aug 21 at 1:04
  • 1
    $\begingroup$ I'm pretty sure "EventLocator" is older. Perhaps it is kept around only for compatibility reasons. I suspect that WhenEvent[] is a non-compatible update to event handling. WRI perhaps realized there's a better way or wished to incorporate new functionality, and the new things needed a complete rewrite. NDSolve`EventLocator is a controller method which you can spelunk. As you point out, WhenEvent[] results in NDSolve`EventData[] objects stored in the state data returned by "np". I do not know whether zero-crossing events are handled identically by both. $\endgroup$ Commented Aug 21 at 18:06
  • 1
    $\begingroup$ Here's an important difference. The variable NDSolve`Self is equal to the StateData object when "EventAction" is applied. This is not the case for WhenEvent[], and I've been unable to discover a way to access the StateData inside WhenEvent[]. MWE: NDSolveValue[{y'[t] == 1, y[0] == 0}, y, {t, 0, 1}, Method -> {"EventLocator", "Event" -> {y[t] - 1/2}, "EventAction" :> (state = NDSolve`Self;)}]. Cool. I didn't know that until now. $\endgroup$ Commented Aug 21 at 18:13

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.