【发布时间】:2017-01-25 19:52:59
【问题描述】:
我正在尝试使用 ODEINT 求解单个一阶 ODE。以下是代码。我希望在 3 个时间点获得 3 个 y 值。我正在努力解决的问题是能够通过 mt 和 nt 的第 n 个值来计算 dydt。我认为 ODEINT 会传递 mt 和 nt 的所有 3 个值,而不是仅传递第 0、第 1 或第 2 个值,具体取决于迭代。因此,我收到此错误:
RuntimeError: func(4)返回的数组大小与y0(1)的大小不匹配。
有趣的是,如果我将初始条件(并且应该是)单个值替换为:a0= [2]*4,则代码有效,但给了我一个 4X4 矩阵作为解决方案,这似乎不正确。
mt = np.array([3,7,4,2]) # Array of constants
nt = np.array([5,1,9,3]) # Array of constants
c1,c2,c3 = [-0.3,1.4,-0.5] # co-efficients
para = [mt,nt] # Packing parameters
#Test ODE function
def test (y,t,extra):
m,n = extra
dydt = c1*c2*m - c1*y - c3*n
return dydt
a0= [2] # Initial Condition
tspan = range(len(mt)) # Define tspan
#Solving the ODE
yt= odeint(test, a0,tspan,args=(para,))
#Plotting the ODE
plt.plot(tspan,yt,'g')
plt.title('Multiple Parameters Test')
plt.xlabel('Time')
plt.ylabel('Magnitude')
一阶微分方程为:
dy/dt = c1*(c2*mt-y(t)) - c3*nt
这个方程代表了我正在尝试建模的小鼠内分泌系统的一部分。该系统类似于双罐系统,其中第一个罐接收特定激素[以未知速率],但我们的传感器将在特定时间间隔(1 秒)检测到该水平(mt)。然后这个罐子送入第二个罐子,在那里这种激素(y) 的水平被另一个传感器检测到。我使用单独的变量标记了水平,因为检测水平的传感器彼此独立并且没有相互校准。 'c2' 可以被认为是显示两个级别之间相关性的系数。此外,这种激素从罐 1 到罐 2 的转移是扩散驱动的。这种激素被生化过程进一步消耗(类似于第二个水箱的排水阀)。目前尚不清楚哪些参数会影响消耗;但是,另一个传感器可以检测到在特定时间间隔(在这种情况下也是 1 秒)消耗的激素 (nt) 的量。
因此,mt 和 nt 是特定时间点的激素浓度/水平。虽然代码中只有 4 个元素的长度,但这些数组在我的研究中要长得多。所有传感器都以 1 秒的间隔报告浓度 - 因此tspan 由相隔 1 秒的时间点组成。
目标是用数学方法确定第二个水箱 (y) 中这种激素的浓度,然后根据实验数据优化这些系数的值。我能够将这些数组 mt 和 nt 传递给定义的 ODE,并在 MATLAB 中使用 ODE45 求解,没有任何问题。我在尝试在 Python 中复制代码时遇到了这个 RunTimeError。
【问题讨论】:
-
如果您遵循变量的定义和传递方式,您会看到
test()中的m变为mt。mt是一个长度为 4 的 numpy 数组,所以c1*c2*m也是一个长度为 4 的 numpy 数组(c3*n也是如此)。那么dydt是一个长度为 4 的数组。所以实际上,你是从test()返回一个长度为 4 的数组。 -
是的,我意识到 - 。如何更正此问题,以便“test()”仅采用 mt 和 nt 的一个值 - 第 n 次迭代的第 n 个值 - 并仅返回一个值而不是长度为 4 的数组?
-
第n次迭代是什么意思?
-
odeint 将调用函数
test4 次以获得tspan中的4 个点,对吧?我认为 ODE 对test的每次调用都将被称为迭代 - 不是吗? -
您能否澄清(在问题中)您要解决的问题?我的解释是你有一个一阶微分方程
dy/dt = c1*c2*m(t) - c1*y - c3*n(t),但函数m(t)和n(t)仅在离散时间值 t=0、1、2、3 时才知道。如果是这种情况,你必须决定如何为任意t定义m(t)和n(t)。如果你不能这样做,那么你就没有一个定义明确的微分方程。如果我的理解不正确,请在问题中更详细地解释数学问题。
标签: python-2.7 scipy odeint