17 may
2019

Pass args for solve_ivp (new SciPy ODE API)

For solving simple ODEs using SciPy, I used to use the odeint function, with form:

scipy.integrate.odeint(func, y0, t, args=(), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None, rtol=None, atol=None, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0)[source]

where a simple function to be integrated could include additional arguments of the form:

def dy_dt(t, y, arg1, arg2):
    # processing code here

In SciPy 1.0, it seems the ode and odeint funcs have been replaced by a newer solve_ivp method.

scipy.integrate.solve_ivp(fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, **options)

However, this doesn't seem to offer an args parameter, nor any indication in the documentation as to implementing the passing of args.

Therefore, I wonder if arg passing is possible with the new API, or is this a feature that has yet to be added? (It would seem an oversight to me if this features has been intentionally removed?)

Reference: https://docs.scipy.org/doc/scipy/reference/integrate.html

COMENTARIOS

rlee827

It doesn't seem like the new function has an args parameter. As a workaround you can create a wrapper like

def wrapper(t, y):
    orig_func(t,y,hardcoded_args)

and pass that in.

Lev K.

Relatively recently there appeared a similar question on scipy's github. Their solution is to use lambda:

solve_ivp(fun=lambda t, y: fun(t, y, *args), ...)

And they argue that there is already enough overhead for this not to matter.

zahbaz

Adding to Cleb's answer, here's an example for using the lambda t,y: fun(t,y,args) method. We set up the function handle that returns the rhs of a second order homogeneous ODE with two parameters. Then we feed it to our solver, along with a couple options.

import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt


def rhs_2nd_order_ode(t, y, a, b):
    """
    2nd order ODE function handle for use with scipy.integrate.solve_ivp
    Solves u'' + au'+ bu = 0 after reducing order with y[0]=u and y[1]=u'.

    :param t: dependent variable
    :param y: independent variables
    :param a: a
    :param b: b
    :return: Returns the rhs of y[0]' = y[1] and y[1]' = -a*y[1] - b*y[0]
    """
    return [y[1], -a*y[1] - b*y[0]]


if __name__ == "__main__":
    t_span = (0, 10)
    t_eval = np.linspace(t_span[0], t_span[1], 100)
    y0 = [0, 1]
    a = 1
    b = 2
    sol = integrate.solve_ivp(lambda t,y: rhs_2nd_order_ode(t,y,a,b), t_span, y0, 
                              method='RK45', t_eval=t_eval)

    fig, ax = plt.subplots(1, 1)
    ax.plot(sol.t, sol.y[0])
    ax.set(xlabel='t',ylabel='y')

DEJA TU COMENTARIO

© 2017 website by Rubit Corporation