Search code examples
pythonpython-3.xspyderdifferential-equationsrunge-kutta

I'm seeing "TypeError: 'tuple' object does not support item assignment" on spyder


What exactly does this mean? Should I not use a for loop? Do I need another tuple?

For context: I'm trying to use Huen's method to solve dydt=y/((t+1)**2) with step size h=0.2 at 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()

Solution

  • The issue is with your np.linspace statement. Here is doc for linspace. The syntax is: numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0). So you only need to give the starting and ending points, and the number of intervals you would like. So after changing your program to this:

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

    Your program gives this:

    enter image description here

    You can play with linspace as you like, to fit your criteria.