You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将字典作为参数传递给Scipy的solve_ivp求解常微分方程组

错误根源

你遇到的报错来自两个低级错误,以及对solve_ivp参数规则的不熟悉:

  1. 你直接传入args=morris_lecar2_defaults,这里传的是函数本身,没有加括号调用,所以solve_ivp拿到的是函数对象,不是你预期的参数字典。
  2. solve_ivp的args参数要求传入可迭代对象,迭代得到的元素会按顺序作为额外位置参数传递给微分方程函数。哪怕你只需要传1个参数,也要把它包装成单元素元组,否则直接传字典会被拆分为多个键值参数,导致函数入参不匹配。
  3. 额外注意:你的微分函数定义名为morris_lecar2,调用solve_ivp时写的是Morris_Lecar2,大小写不匹配,也会触发调用错误。
  4. 你传入的初始状态(-20, 1, 0.001)是3个值,但你的微分方程只解V、N两个变量,维度不匹配也会后续报错。

直接修正写法

按照规则调整调用代码即可正常运行:

import numpy as np
from scipy.integrate import solve_ivp

# 你的参数生成函数和微分函数不变
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"]))
    N_inf = 0.5*(1 + np.tanh((V - p["V_3"])/p["V_4"]))
    tau_N = 1/(p["phi"]*np.cosh((V - p["V_3"])/(2*p["V_4"])))
    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)) 

# 调整调用代码
p = morris_lecar2_defaults()
# 按需修改参数,比如p["I_ext"] = 40,不需要动其他参数
sol_2 = solve_ivp(
    morris_lecar2, 
    t_span=(0, 1000), 
    y0=(-20, 0.01), # 修正为2维初始状态
    args=(p,) # 参数字典包为单元素元组
)

更规范的大参数管理方案

如果参数数量多,担心写错字典键名,可以用dataclass定义参数类,IDE能自动补全属性,还能做参数校验,比纯字典更易用:

from dataclasses import dataclass
import numpy as np
from scipy.integrate import solve_ivp

@dataclass
class MorrisLecarParams:
    # 所有参数自带默认值,修改时只需指定要改的参数即可
    C_M: float = 20
    g_K: float = 8
    g_L: float = 2
    V_Ca: float = 120
    V_K: float = -80
    V_L: float = -60
    V_1: float = -1.2
    V_2: float = 18
    g_Ca: float = 4.0
    phi: float = 1/15
    V_3: float = 12
    V_4: float = 17.4
    I_ext: float = 30

def morris_lecar2(t, u, p: MorrisLecarParams):
    (V, N) = u
    M_inf = 0.5*(1 + np.tanh((V - p.V_1)/p.V_2))
    N_inf = 0.5*(1 + np.tanh((V - p.V_3)/p.V_4))
    tau_N = 1/(p.phi * np.cosh((V - p.V_3)/(2*p.V_4)))
    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)) 

# 调用示例:只修改刺激电流,其他参数用默认值
p = MorrisLecarParams(I_ext=50)
sol_2 = solve_ivp(morris_lecar2, (0, 1000), (-20, 0.01), args=(p,))

内容的提问来源于stack exchange,提问作者ConsistentC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:24:02