这到底是什么意思?我不应该使用for循环吗?我需要另一个元组吗?
对于上下文:我正在尝试使用Huen的方法来求解dydt = y /(((t + 1)** 2),步长为h = 0.2,位于t = 0,0.2,0.4,0.6
#import libraries
import numpy as np
import matplotlib.pyplot as plt
def dydt(t,y):
dfdt = y / ((t + 1) ** 2)
return dfdt
def IVPsolver2(dydt_fun, y0, t0, t1, t2, tf, h):
n = 50 #points
h = (tf-t0)/(n-1) #step size
t = np.linspace(t0,t1,t2,tf,n)
y = np.zeros(n) #preallocate zeros
yp = np.zeros(n)
m = np.zeros(n)
mc = np.zeros(n)
yp[0] = y0 #first yp at y0
y[0] = y0 #y is 0
t[0] = 0 #t is 0
for i in range(0,n-1):
m[i] = dydt_fun(t[i-1],y[i-1]) #calculating slope
yp[i] = y[i] + m[i]*h #calculating predicted y at slope y
mc[i] = dydt_fun(t[i+1],yp[i]) #slope corrector, 2 step
t[i+1] = t[i] + h #t going by stepsize
y[i+1] = y[i] + ((m[i]+mc[i])/2)*h #corrected y
return t, y
def main(): #plotting
x2, y2 = IVPsolver2(dydt, 1, 0, 0.2, 0.4, 0.6, 0.2)
plt.plot(x2,y2, 'o', mfc = 'purple')
return
main()
答案 0 :(得分:3)
问题出在您的np.linspace
语句上。这是linspace
的文档。语法为:numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
。因此,您只需要给出起点和终点以及所需的间隔数即可。因此,将程序更改为此:
import numpy as np
import matplotlib.pyplot as plt
def dydt(t,y):
dfdt = y / ((t + 1) ** 2)
return dfdt
def IVPsolver2(dydt_fun, y0, t0, t1, t2, tf, h):
n = 50 #points
h = (tf-t0)/(n-1) #step size
t = np.linspace(t0,tf,n) # <----- see change here ----
y = np.zeros(n) #preallocate zeros
yp = np.zeros(n)
m = np.zeros(n)
mc = np.zeros(n)
yp[0] = y0 #first yp at y0
y[0] = y0 #y is 0
t[0] = 0 #t is 0
for i in range(0,n-1):
m[i] = dydt_fun(t[i-1],y[i-1]) #calculating slope
yp[i] = y[i] + m[i]*h #calculating predicted y at slope y
mc[i] = dydt_fun(t[i+1],yp[i]) #slope corrector, 2 step
t[i+1] = t[i] + h #t going by stepsize
y[i+1] = y[i] + ((m[i]+mc[i])/2)*h #corrected y
return t, y
def main(): #plotting
x2, y2 = IVPsolver2(dydt, 1, 0, 0.2, 0.4, 0.6, 0.2)
plt.plot(x2,y2, 'o', mfc = 'purple')
plt.show()
return
main()
您的程序给出以下信息:
您可以根据需要使用linspace进行游戏。
答案 1 :(得分:2)
Karl Heun的梯形方法(出版于1900年)是一种单步方法。这意味着在y[i+1]
的计算中,您仅在时间y[i]
使用数据t[i]
,循环中应该没有y[i-1]
。
此外,不需要yp, m, mp
作为数组,因为仅在步骤中使用局部局部值,而在其他任何地方均不使用
对于接口,接受任意时间数组将是有意义的,因为单步方法特别适合具有可变步长(即使传递的数组在特定情况下具有恒定的步长)。然后,这还允许以类似于odeint
的方式从返回值中删除时间数组。
def IVPsolver2(dydt_fun, y0, t):
y = np.zeros(len(t)) #preallocate zeros
y[0] = y0 #y is 0
for i in range(0,len(t)-1):
h = t[i+1] - t[i];
m = dydt_fun(t[i],y[i]) #calculating slope
yp = y[i] + m*h #calculating predicted y at slope y
mc = dydt_fun(t[i+1],yp) #slope corrector, 2 step
y[i+1] = y[i] + ((m+mc)/2)*h #corrected y
return y
如果您希望将时间数组构造保留在过程内,则仅传递t0, tf, h
并使用
t = np.arange(t0,tf+0.1*h, h);
增加的最终值需要在数组中具有接近tf
的值,这是由于算术序列构造中的舍入误差并非总是自动的,即使tf
是精确算术序列的元素。
最后,您可以将此方法两次应用于给定的采样时间序列,并使用更密集的序列以提供更精确的解决方案
x1 = np.linspace(0,1,5+1);
y1 = IVPsolver2(dydt, 1, x1);
x2 = np.linspace(0,1,5*10+1);
y2 = IVPsolver2(dydt, 1, x2);
xe = np.linspace(t0,tf,152);
ye = np.exp(1-1/(1+xe));
plt.plot(xe,ye,c='lightgray', lw=6)
plt.plot(x2,y2, 'o', mfc = 'purple', ms=2)
plt.plot(x1,y1, '-o', mfc = 'red', ms=4)
plt.show()