odeint
is a Python wrapper for C code which calls LSODA (a Fortran subroutine) which calls C code to call my Python callback representing dy/dt. LSODA doesn't pass the Python exception, and jumping from one bit of the C code to another is troublesome to implement.
I have found a satisfactory solution in just using ode
instead of odeint
. I find ode
to be more complicated to get started using, but it behaves the right way when an exception is thrown in Python. The fake_odeint()
function below is a start at making a function that works like odeint
well enough for my purposes so that I can swap it out in my existing code. The downside to using ode
instead of odeint
is that LSODA gets called once per timestep; this call happens in C with odeint
and more slowly in Python in ode
.
import numpy as np
from scipy.integrate import ode
def fake_odeint(func, y0, t, Dfun=None):
ig = ode(func, Dfun)
ig.set_integrator('lsoda',
method='adams')
ig.set_initial_value(y0, t=0.)
y = []
for tt in t:
y.append(ig.integrate(tt))
return np.array(y)
I looked into the mechanics of how Fortran, C, and Python code are used to allow odeint
to communicate with LSODA in this SO question.