简体   繁体   中英

How to fix this error: unsupported operand type(s) for ** or pow(): 'tuple' and 'int'

I am trying to solve an ODE with two variables. I do not understand why or how I have created a tuple here. The function f should be f = 10 - x - (4xy / 1+x^2) Could anyone help with this?

def RK_step(f, g, x, y, t, dt):
    
    x_new = x + dt*f(x + 0.5*dt*f(x, y, t), y + 0.5*dt*f(x, y, t), t + 0.5*dt)
    y_new = y + dt*g(x + 0.5*dt*f(x, y, t), y + 0.5*dt*g(x, y, t), t + 0.5*dt)
    
    return x_new, y_new

def RK_method(f, g, x, y, dt, n):
    
    x_array = [x]
    y_array = [y]
    for i in range(1,n+1):
        t = i*dt
        x_array.append(RK_step(f, g, x_array[-1], y_array[-1], t, dt))
        y_array.append(RK_step(f, g, x_array[-1], y_array[-1], t, dt))
      
    return x_array, y_array


def f(x, y, t):
    return 10 - x - ((4*x*y) / (1 + (x**2)))

def g(x, y, t):
    return 4*x*(1- (y / (1 + x**2)))

T = 100
dt = 0.1
n = int(T/dt)
x_initial = 0
y_initial = 1

x_RK = RK_method(f, g, x_initial, y_initial, dt, n)
y_RK = RK_method(f, g, x_initial, y_initial, dt, n)
t = np.linspace(0,T,n+1)
plt.plot(t,x_RK)
plt.plot(t,y_RK)
plt.legend(['Runge-Kutta with $dt = ${}'.format(dt)]);

<ipython-input-7-530b1d126979> in f(x, y, t)
     56 
     57 def f(x, y, t):
---> 58     return (10 - (x - ((4*x*y) / (1 + (x**2)))))
     59 
     60 def g(x, y, t):

TypeError: unsupported operand type(s) for ** or pow(): 'tuple' and 'int'

Here:

x_array.append(RK_step(f, g, x_array[-1], y_array[-1], t, dt))
y_array.append(RK_step(f, g, x_array[-1], y_array[-1], t, dt))

RK_step returns a tuple. You are putting a tuple into x_array and into y_array .

If you want to split the tuple between x_array and y_array , then you want something like this:

x,y = RK_step(f, g, x_array[-1], y_array[-1], t, dt)
x_array.append(x)
y_array.append(y)

You are computing the same values multiple times, unnecessarily. You can streamline this and at the same time remove the error by changing your code for the midpoint method to

def RK_step(f, g, x, y, t, dt):
    # compute only once
    f0, g0 = f(x, y, t), g(x, y, t)
    # note the remaining duplicated operations in the arguments
    x_new = x + dt*f(x + 0.5*dt*f0, y + 0.5*dt*g0, t + 0.5*dt)
    #            there is a typo     ----------^ in the original code
    y_new = y + dt*g(x + 0.5*dt*f0, y + 0.5*dt*g0, t + 0.5*dt)
    
    return x_new, y_new

def RK_method(f, g, x, y, dt, n):
    
    x_array = [x]
    y_array = [y]
    for i in range(1,n+1):
        t = i*dt
        # call the RK2 step only once, use all of the returned values
        x,y = RK_step(f, g, x, y, t, dt)
        x_array.append(x)
        y_array.append(y)
      
    return x_array, y_array


def f(x, y, t):
    return 10 - x - ((4*x*y) / (1 + (x**2)))

def g(x, y, t):
    return 4*x*(1- (y / (1 + x**2)))

T = 100
dt = 0.1
n = int(T/dt)
x_initial = 0
y_initial = 1

# call the integration procedure only once, use all of the returned values
x_RK,y_RK = RK_method(f, g, x_initial, y_initial, dt, n)
# do not rely on floating point arithmetic being accidentally correct
t = np.arange(n+1)*dt
plt.plot(t,x_RK)
plt.plot(t,y_RK)
plt.legend(['Runge-Kutta with $dt = ${}'.format(dt)]);

resulting in the plot

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM