How can you pass a dictionary as parameters to solve_ivp?

  python, python-3.x, scipy

I was having difficulties trying to pass a dictionary as the parameters to Scipy’s solve_ivp to solve a system of ODEs given below. The issue is my system has many parameters (more than shown below). For convenience and to avoid making errors changing individual values from a long list e.g [20,8,2,120,-80,…,30], I would like to pass a lookup table of parameters like this dictionary:

def morris_lecar2_defaults():
    return {
        "C_M" : 20,
        "g_K" : 8,
        "g_L" : 2,
        "V_Ca" : 120,
        "V_K" : -80,
        "V_L" : -60,
        "V_1" : -1.2,
        "V_2" : 18,
        "g_Ca" : 4.0,
        "phi" : 1/15,
        "V_3" : 12,
        "V_4" : 17.4,
        "I_ext" : 30,
    }

def morris_lecar2(t, u, p):
    (V, N) = u
    M_inf = 0.5*(1 + np.tanh((V - p["V_1"])/p["V_2"])) # (2)
    N_inf = 0.5*(1 + np.tanh((V - p["V_3"])/p["V_4"])) # (3)
    tau_N = 1/(p["phi"]*np.cosh((V - p["V_3"])/(2*p["V_4"]))) # (4)
    # (1)
    dVdt = (-p["g_L"]*(V - p["V_L"]) - p["g_Ca"]*M_inf*(V - p["V_Ca"]) - p["g_K"]*N*(V - p["V_K"]) + p["I_ext"])/p["C_M"]
    dNdt = (N_inf - N)/tau_N
    return np.array((dVdt, dNdt)) 

The issue is when I pass this to Scipy’s solve_ivp routine as the optional args parameter I get the error:

Traceback (most recent call last):
  line 159, in <module>
    sol_2 = solve_ivp(Morris_Lecar2,(0, 1000), (-20, 1, 0.001), args= morris_lecar2_defaults)
  File "C:Anacondaenvstestlibsite-packagesscipyintegrate_ivpivp.py", line 542, in solve_ivp
    solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
  File "C:Anacondaenvstestlibsite-packagesscipyintegrate_ivprk.py", line 94, in __init__
    self.f = self.fun(self.t, self.y)
  File "C:Anacondaenvstestlibsite-packagesscipyintegrate_ivpbase.py", line 138, in fun
    return self.fun_single(t, y)
  File "C:Anacondaenvstestlibsite-packagesscipyintegrate_ivpbase.py", line 20, in fun_wrapped
    return np.asarray(fun(t, y), dtype=dtype)
  File "C:Anacondaenvstestlibsite-packagesscipyintegrate_ivpivp.py", line 514, in <lambda>
    fun = lambda t, x, fun=fun: fun(t, x, *args)
TypeError: Morris_Lecar2() argument after * must be an iterable, not function

The dictionary is still treated as a function object and despite several attempts to resolve this issue I’ve had no luck. What is the most pythonic yet user-friendly way to solve this large parameter set problem which satisfies solve_ivp?

Source: Python Questions

LEAVE A COMMENT