odeint_event
→tupleodeint_event(func: Callable[..., object], y0: State, t0: float | Tensor, event_fn: Callable[..., Tensor], reverse_time: bool = False, odeint_interface: Callable[..., object] = odeint, kwargs: object = {})Integrate from t0 until an event fires.
The convenience form of odeint(..., event_fn=...) for the common case
where there is no output grid at all — you have a starting time and a
condition, and want to know when the condition is met.
Parameters
funccallablef(t, y) -> dy/dt.y0Tensort0.t0float or Tensorevent_fncallableg(t, y) returning a single-element tensor. The solve ends the
moment its sign changes; a value of exactly zero at t0 fires
immediately.reverse_timebool= Falseodeint_interfacecallable= odeintodeint_adjoint to get the event
solve at constant memory.**kwargsobject= {}odeint_interface — rtol, atol, method,
options.Returns
tuple(event_t, solution); event_t is a 0-D tensor and
solution has shape (2, *y0.shape) — the state at t0 and
the state at the event.
Raises
ValueErroroptions["step_size"], or
if event_fn does not return a single-element tensor.RuntimeErrorNotes
The event time itself is located by bisecting the interpolant of the step that brackets it, so it costs event-function calls but no extra right-hand-side evaluations.
event_t is differentiable, though bisection itself is not: the event
time is pinned by g(t*, y(t*)) = 0, and differentiating that identity
routes its gradient onto the state at the event, which does carry a graph.
Expect total derivatives -- the state at the event moves with the event
time, so differentiating solution[-1] accounts for that too.
Examples
A body falling from rest hits the ground at \sqrt{2h/g}:
>>> import lucid, lucid.diffeq as diffeq
>>> y0 = lucid.tensor([10.0, 0.0], dtype=lucid.float64) # height, velocity
>>> def fall(t, y):
... return lucid.stack([y[1], lucid.tensor(-9.8, dtype=y.dtype)], dim=0)
>>> event_t, sol = diffeq.odeint_event(
... fall, y0, 0.0, event_fn=lambda t, y: y[0]
... )
>>> abs(float(event_t.item()) - (2 * 10.0 / 9.8) ** 0.5) < 1e-6
TrueSee Also
- lucid.diffeq.odeint—Takes
event_fndirectly alongside an output grid.