我正在尝试使用弹簧质量耦合系统编写程序。解决使用ODE的问题

时间:2019-04-15 10:35:02

标签: python numpy runge-kutta

我正在尝试使用弹簧质量耦合系统编写程序。解决使用ODE的问题

import numpy as np
import matplotlib.pyplot as plt

kitchen1 = 2.0
kitchen2 = 2.0
money1 = 2.0
money2 = 2.0
walk1 = 5.0
walk2 = 5.0
Lenon1 = 2.0
Lenon2 = 2.0

def f1(x1, v1, x2, v2, t):
return v1

def f2 (x1, v1, x2, v2, t):
    return ((-kitchen1/money1)*(x1-Lenon1)) + (kitchen2/money1*(x2-x1-walk1- Lenon2))

def f3(x1, v1, x2, v2, t):
return v2

def f4(x1, v1, x2, v2, t):
     return (-kitchen2/money2) * (x2-x1-walk1-Lenon2)

def rk4_gen(x1_arr, v1_arr, x2_arr, v2_arr, t_arr, h):
x1, v1, x2, v2, t  = t_arr[0], x1_arr[0], v1_arr[0], x2_arr[0], v2_arr[0]

for i in range(1,len(t)):
    t, h = t[i-1], t[i]-t[i-1]  

    k11 = h*f1(x1, v1, x2, v2, t)
    k12 = h*f2(x1, v1, x2, v2, t)
    k13 = h*f3(x1, v1, x2, v2, t)
    k14 = h*f4(x1, v1, x2, v2, t)


    k21 = h*f1(x1+k11/2.0, v1+k12/2.0,x2+k13/2.0,v2+k14/2.0, t+h/2.0)
    k22 = h*f2(x1+k11/2.0, v1+k12/2.0,x2+k13/2.0,v2+k14/2.0, t+h/2.0)
    k23 = h*f3(x1+k11/2.0, v1+k12/2.0,x2+k13/2.0,v2+k14/2.0, t+h/2.0)
    k24 = h*f4(x1+k11/2.0, v1+k12/2.0,x2+k13/2.0,v2+k14/2.0, t+h/2.0)

    k31 = h*f1(x1+k21/2.0, v1+k22/2.0,x2+k23/2.0,v2+k24/2.0, t+h/2.0)
    k32 = h*f2(x1+k21/2.0, v1+k22/2.0,x2+k23/2.0,v2+k24/2.0, t+h/2.0)
    k33 = h*f3(x1+k21/2.0, v1+k22/2.0,x2+k23/2.0,v2+k24/2.0, t+h/2.0)
    k34 = h*f4(x1+k21/2.0, v1+k22/2.0,x2+k23/2.0,v2+k24/2.0, t+h/2.0)

    k41 = h*f1(x1+k31, v1+k32,x2+k33,v2+k34, t+h)
    k42 = h*f2(x1+k31, v1+k32,x2+k33,v2+k34, t+h)
    k43 = h*f3(x1+k31, v1+k32,x2+k33,v2+k34, t+h)
    k44 = h*f4(x1+k31, v1+k32,x2+k33,v2+k34, t+h)


    x1 = x1 + (k11 + 2*k12 + 2*k13 + k14)/6.0
    v1 = v1 + (k21 + 2*k22 + 2*k23 + k24)/6.0
    x2 = x2 + (k31 + 2*k32 + 2*k33 + k34)/6.0
    v2 = v2 + (k41 + 2*k42 + 2*k43 + k44)/6.0

    x1_arr[i], v1_arr[i], x2_arr[i], v2_arr[i] = x1, v1, x2, v2  

return x1_arr, v1_arr , x2_arr , v2_arr, t_arr 

def grafik_ciz(t,y,x_baslik,y_baslik,baslik):
plt.figure(figsize = [12, 9])
plt.plot(t,y)
plt.xlabel(x_baslik)
plt.ylabel(y_baslik)
plt.title(baslik)
plt.grid()
plt.show()

ti = 0 
tf = 20 
x1 = 2 
v1 = 0
x2 = 15 
v2 = 0
h = 0.5

t = np.arange(ti,tf+h,h) 
x1 = np.zeros(len(t))
v1 = np.zeros(len(t))
x2 = np.zeros(len(t))
v2 = np.zeros(len(t))


x1[0] = x1i
v1[0] = v1i
x2[0] = x2i
v2[0] = v2i

x1 = rk4_gen(x1_arr, v1_arr, x2_arr, v2_arr, t_arr, h
print x1

使用四阶Runge-Kutta方法

我需要绘制一个图表,显示x和y随时间的变化,从t = 0到t = 20。

错误m.ValueError:太多值无法解压缩

到目前为止,这是我的代码,但图中没有显示任何内容。

我认为,此错误是t = np.arange(ti,tf+h,h)
我需要绘制一个图表,显示x1和v1随时间的变化,从t = 0到t = 20。

1 个答案:

答案 0 :(得分:0)

除了在正确实施算法,使用一致的函数接口,使用正确的函数名称等方面存在许多错误之外。

您报告的问题是,您在执行单个RK4步骤时不会解压缩传递给rk4_gen的数组。您可以做的太多更改就是重命名in

def rk4_gen(t_arr, x1_arr, v1_arr, x2_arr, v2_arr, h):

(为什么要通过h?在每一步中您都可以计算出正确的h=t[i]-t[i-1])。然后初始化运行变量

    t, x1, v1, x2, v2 = t_arr[0], x1_arr[0], v1_arr[0], x2_arr[0], v2_arr[0]

执行(更正的)RK4步骤,并在每个步骤结束时将计算值保存到数组中

def rk4_gen(x1_arr, v1_arr, x2_arr, v2_arr, t_arr, h):
    t, x1, v1, x2, v2 = t_arr[0], x1_arr[0], v1_arr[0], x2_arr[0], v2_arr[0]

    for i in range(1,len(t_arr)):
        # Do the RK4 step, it is from i-1 to i
        t, h = t_arr[i-1], t_arr[i]-t_arr[i-1]
        k11 = h*f1(...)
        ...
        v2 = v_2+(k14+2*k24+2*k34+k44)/6.0
        x1_arr[i], v1_arr[i], x2_arr[i], v2_arr[i] = x1, v1, x2, v2

    return x1_arr, v1_arr , x2_arr , v2_arr, t_arr 

还请注意,您的精加工计算具有k个值,它们的顺序相反。


您可以使用scipy.integrate方法以更紧凑的方式解决此问题,例如

from scipy.integrate import solve_ivp

def spring_ode(t,u):
    x1,v1,x2,v2 = u
    a1 = ((-kitchen1/money1)*(x1-Lenon1)) + (kitchen2/money1*(x2-x1-walk1- Lenon2))
    a2 = (-kitchen2/money2) * (x2-x1-walk1-Lenon2)
    return [v1,a1,v2,a2]

res = solve_ivp(spring_ode, [ti,tf], [x1i,v1i,x2i,v2i], dense_output=True, rtol=1e-12, atol=1e-14)

h=0.02
t = np.arange(ti,tf+h/2,h) 
u = res.sol(t)
x1,v1,x2,v2 = u
plt.figure(figsize = [8, 5])
plt.plot(t,x1,t,x2); plt.legend(["$x_1$","$x_2$"])
plt.grid(); plt.show()

及其结果图

enter image description here