Search code examples
pythonscipyodeodeint

Issue with odeint Python


I am trying to use odeint but I have a parameter that changes values with every time step. My function is:

def f(y, t, k1, k2, Pr):
    return k1*(Pr-k2)*y

Where Pr is a pandas series that contains float values, of which I have observed values. And t is a list of integer years from 1961 to 2014. I wrote the following code for odeint:

y0 = 120000
k1 = 0.2
k2 = -.4
y = odeint(f, y0, t, args = (k1, k2, Pr, ))

But it gives the following error:

RuntimeError: The size of the array returned by func (54) does not match the size of y0 (1).

Solution

  • As indicated by the error message, Pr is being passed in as a vector of length 54, instead of the values one-by-one. Inferring that Pr is a NumPy vector, this would mean the output of f is the result of applying the return value elementwise to Pr.

    To fix this, you can instead use a function that produces a Pr value from a time input. Again assuming that Pr[k] corresponds to t[k], the simplest version of this function could be:

    def get_Pr(time: float):
        t_index = sum(t <= time) - 1 
        return Pr[t_index]
    

    Then modify f as follows:

    def f(y, t, k1, k2):
        this_pr = get_Pr(t)
        return k1*(this_pr-k2)*y
    

    edit: ...and then don't pass Pr in as an arg to scipy.odeint, since f gets the value in a different way.