我正在尝试完成this,其中我必须解决五个普通问题
使用odeint
的微分方程,并复制该任务中给出的数字。
这是我的代码:
import scipy as sp
import scipy.interpolate as ip
import numpy as np
import matplotlib.pyplot as pl
d = 8.64
Mu1 = 4.95*10**2
Mu2 = 4.95*10**(-2)
vs = 0.12
vd = 1.23
w = 10**(-3)
k1 = 2.19*10**(-4)
k2 = 6.12*10**(-5)
k3 = 0.997148
k4 = 6.79*10**(-2)
p0 = 1.00
sigmas0 = 2.01
sigmad0 = 2.23
alphas0 = 2.20
alphad0 = 2.26
hs = (sigmas0-(sigmas0**(2)-k3*alphas0*(2*sigmas0-alphas0))**(1/2))/k3
cs = (alphas0-hs)/2
ps = k4*(hs**2)/cs
t_points = [ 1000, 1850, 1950, 1980, 2000, 2050, 2080, 2100, 2120, 2150, 2225, 2300, 2500, 5000 ]
y_points = [ 0.0, 0.0, 1.0, 4.0, 5.0, 8.0, 10.0, 10.5, 10.0, 8.0, 3.5, 2.0, 0.0, 0.0 ]
t1 = np.array(t_points)
y1 = np.array(y_points)
new_length = 1000
new_t = np.linspace(t1.min(), t1.max(), new_length)
new_y2 = ip.pchip_interpolate(t1, y1, new_t)
pl.plot(t_points,y_points,'o', new_t,new_y2)
pl.show()
ft = sp.interpolate.interp1d(new_t, new_y2)
def equations(x, t1):
p = x[0]
alphad = x[1]
alphas = x[2]
sigmad = x[3]
sigmas = x[4]
dpdt = (ps-p)/d + ft/Mu1
dalphaddt = (1/vd)*(k2-w*(alphad-alphas))
dalphasdt = (1/vs)*(w*(alphad-alphas)-k2)
dsigmaddt = (1/vd)*(k1-w*(sigmad-sigmas))
dsigmasdt = (1/vs)*(w*(sigmad-sigmas)-k1-(ps-p)/d*Mu2)
return [dpdt, dalphaddt, dalphasdt, dsigmaddt, dsigmasdt]
solve = sp.integrate.odeint(equations, [p0, alphad0, alphas0, sigmad0, sigmas0], t1)
似乎这部分:
dpdt = (ps-p)/d + ft/Mi1
是错误的,我不知道如何解决。
错误提示:
TypeError:/:“ interp1d”和“ float”不支持的操作数类型。
任何想法和建议都值得赞赏。
编辑:当我应用meowgoesthedog建议的更改时,出现错误:
Traceback (most recent call last):
File "<ipython-input-5-324757833872>", line 1, in <module>
runfile('E:/Data/Project 2/project2.py', wdir='E:/Data/Project 2')
File "D:\Programs\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 668, in runfile
execfile(filename, namespace)
File "D:\Programs\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "E:/Data/Project 2/project2.py", line 59, in <module>
solve = odeint(equations, [p0, alphad0, alphas0, sigmad0, sigmas0], t1)
File "D:\Programs\Anaconda3\lib\site-packages\scipy\integrate\odepack.py", line 233, in odeint
int(bool(tfirst)))
File "E:/Data/Project 2/project2.py", line 51, in equations
dpdt = (ps-p)/d + ft(t1)/Mu1
File "D:\Programs\Anaconda3\lib\site-packages\scipy\interpolate\polyint.py", line 79, in __call__
y = self._evaluate(x)
File "D:\Programs\Anaconda3\lib\site-packages\scipy\interpolate\interpolate.py", line 664, in _evaluate
below_bounds, above_bounds = self._check_bounds(x_new)
File "D:\Programs\Anaconda3\lib\site-packages\scipy\interpolate\interpolate.py", line 696, in _check_bounds
raise ValueError("A value in x_new is above the interpolation "
ValueError: A value in x_new is above the interpolation range.
`
答案 0 :(得分:1)
ynew = f(xnew) # use interpolation function returned by interp1d
它返回一个函数/可调用对象,该对象采用值x
并返回内插值f(x)
。对于您的情况"x" = t
:
dpdt = (ps-p)/d + ft(t1)/Mu1 # pass t1 to ft to obtain interpolated value
更新
此新错误是由于odeint
在f(t)
的值t
<{> 。这对于纠错是必需的,并且没有防止t_points
这样做的选项。但是,我们可以使用odeint
,在提供的样本之外外推 f(t)
:
InterpolatedUnivariateSpline
与from scipy.interpolate import InterpolatedUnivariateSpline
...
ft = InterpolatedUnivariateSpline(t1, y1, k=1)
一样,它返回具有相同签名的函数。但是,应用此修复程序后,结果将变为:
那当然是不正确的。
您已在函数外部将interp1d
声明为常量。实际上,它们是hs, cs, ps
和alpha*
变量的函数,因此必须在每次调用sigma*
时进行评估:
equation
现在,结果与练习中的图形差不多了。
您将def equations(x, t):
p = x[0]
alphad = x[1]
alphas = x[2]
sigmad = x[3]
sigmas = x[4]
hs = (sigmas-(sigmas**(2)-k3*alphas*(2*sigmas-alphas))**(1/2))/k3
cs = (alphas-hs)/2
ps = k4*(hs**2)/cs
dpdt = (ps-p)/d + ft(t)/Mu1
dalphaddt = (1/vd)*(k2-w*(alphad-alphas))
dalphasdt = (1/vs)*(w*(alphad-alphas)-k2)
dsigmaddt = (1/vd)*(k1-w*(sigmad-sigmas))
dsigmasdt = (1/vs)*(w*(sigmad-sigmas)-k1-(ps-p)/d*Mu2)
return [dpdt, dalphaddt, dalphasdt, dsigmaddt, dsigmasdt]
作为水平轴变量传递给了t1
。它只有14个元素,对于平滑输出来说太少了。改为通过odeint
:
new_t
结果现在完全符合预期!