具有多个参数的 ODEINT(与时间相关)

问题描述 投票:0回答:1

我正在尝试使用 ODEINT 求解单个一阶 ODE。以下是代码。我期望获得 3 个时间点的 3 个 y 值。我正在努力解决的问题是能够传递 mtnt 的第 n 个值来计算 dydt。我认为 ODEINT 会传递 mtnt 的所有 3 个值,而不是仅传递第 0 个、第 1 个或第 2 个值,具体取决于迭代。因此,我收到此错误:

运行时错误: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。

python-2.7 scipy odeint
1个回答
3
投票

正如我在评论中提到的,如果您想使用常微分方程对该系统进行建模,则必须对采样时间之间的

m
n
的值做出假设。一种可能的模型是使用线性插值。以下脚本使用
scipy.interpolate.interp1d
基于样本
mfunc(t)
nfunc(t)
创建函数
mt
nt

import numpy as np
from scipy.integrate import odeint
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

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

# Create linear interpolators for m(t) and n(t).
sample_times = np.arange(len(mt))
mfunc = interp1d(sample_times, mt, bounds_error=False, fill_value="extrapolate")
nfunc = interp1d(sample_times, nt, bounds_error=False, fill_value="extrapolate")

# Test ODE function
def test (y, t):
    dydt = c1*c2*mfunc(t) - c1*y - c3*nfunc(t)
    return dydt

a0 = [2]  # Initial Condition
tspan = np.linspace(0, sample_times.max(), 8*len(sample_times)+1)
#tspan = sample_times

# Solving the ODE
yt = odeint(test, a0, tspan)

# Plotting the ODE
plt.plot(tspan, yt, 'g')
plt.title('Multiple Parameters Test')
plt.xlabel('Time')
plt.ylabel('Magnitude')
plt.show()

这是脚本创建的情节:

请注意,我不是仅在

sample_times
(即时间 0、1、2 和 3)处生成解决方案,而是将
tspan
设置为更密集的点集。这显示了模型在采样时间之间的行为。

© www.soinside.com 2019 - 2024. All rights reserved.