我在spyder上看到“ TypeError:'tuple'对象不支持项目分配”

时间:2019-11-22 05:07:02

标签: python python-3.x spyder differential-equations runge-kutta

这到底是什么意思?我不应该使用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()

2 个答案:

答案 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()

您的程序给出以下信息:

enter image description here

您可以根据需要使用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()

plot of the numerical solutions