python - 如何用python求解非线性DE的9方程组?

标签 python physics ode

我正在拼命地尝试求解(并显示图形)一个由九个非线性微分方程组成的系统,该方程模拟了回旋镖的路径。系统如下:

enter image description here

左侧所有字母都是变量,其他字母要么是常量,要么是已知函数,具体取决于 v_G 和 w_z

我尝试过使用scipy.odeint,但没有得出结论性的结果(我有this issue,但解决方法不起作用。)

我开始认为问题与以下事实有关:这些方程是非线性的,或者分母中的函数可能会导致 scipy 求解器根本无法处理的奇点。不过,我对这类数学知识并不熟悉。 我必须用Python来解决这组方程有什么可能性?

编辑:抱歉,如果我不够清楚。由于它模拟了回旋镖的路径,因此我的目标不是分析解决该系统(即我不关心每个函数的数学表达式),而是获取特定时间范围内每个函数的值(例如,从t1 = 0s到t2 = 15s,每个值之间的间隔为0.01s),以显示每个函数的图形和回旋镖质心的图形(X,Y,Z为其坐标)。

这是我尝试过的代码:

import scipy.integrate as spi
import numpy as np

#Constants

I3 = 10**-3
lamb = 1
L = 5*10**-1
mu = I3
m = 0.1
Cz = 0.5
rho = 1.2
S = 0.03*0.4
Kz = 1/2*rho*S*Cz
g = 9.81

#Initial conditions

omega0 = 20*np.pi
V0 = 25
Psi0 = 0
theta0 = np.pi/2
phi0 = 0
psi0 = -np.pi/9
X0 = 0
Y0 = 0
Z0 = 1.8

INPUT = (omega0, V0, Psi0, theta0, phi0, psi0, X0, Y0, Z0) #initial conditions 


def diff_eqs(t, INP):  
    '''The main set of equations'''

    Y=np.zeros((9))

    Y[0] = (1/I3) * (Kz*L*(INP[1]**2+(L*INP[0])**2))
    Y[1] = -(lamb/m)*INP[1]
    Y[2] = -(1/(m * INP[1])) * ( Kz*L*(INP[1]**2+(L*INP[0])**2) + m*g) + (mu/I3)/INP[0]
    Y[3] = (1/(I3*INP[0]))*(-mu*INP[0]*np.sin(INP[6]))
    Y[4] = (1/(I3*INP[0]*np.sin(INP[3]))) * (mu*INP[0]*np.cos(INP[5]))
    Y[5] = -np.cos(INP[3])*Y[4]
    Y[6] = INP[1]*(-np.cos(INP[5])*np.cos(INP[4]) + np.sin(INP[5])*np.sin(INP[4])*np.cos(INP[3]))
    Y[7] = INP[1]*(-np.cos(INP[5])*np.sin(INP[4]) - np.sin(INP[5])*np.cos(INP[4])*np.cos(INP[3]))
    Y[8] = INP[1]*(-np.sin(INP[5])*np.sin(INP[3]))


    return Y   # For odeint



t_start = 0.0
t_end = 20
t_step = 0.01
t_range = np.arange(t_start, t_end, t_step)

RES = spi.odeint(diff_eqs, INPUT, t_range)

但是,我不断遇到如图所示的相同问题 here尤其是错误消息:

Excess work done on this call (perhaps wrong Dfun type)

我不太确定这意味着什么,但看起来求解器在求解系统时遇到了麻烦。无论如何,当我尝试通过 XYZ 坐标显示 3D 路径时,我只得到 3 或 4 个点,其中应该有 2000 之类的值。

所以我的问题是: - 我的代码是否做错了什么? - 如果没有,是否有其他可能更复杂的工具来解决这个系统? - 如果没有,是否有可能从这个 ODE 系统中得到我想要的东西?

提前致谢

最佳答案

有几个问题:

  • 如果我复制代码,它不会运行
  • 您提到的解决方法不适用于 odeint,给定的 解决方案使用ode
  • odeint 的 scipy 引用说:“对于新代码,请使用 scipy.integrate.solve_ivp 求解微分方程。”
  • 调用RES = spi.odeint(diff_eqs, INPUT, t_range)应该是 与函数头 def diff_eqs(t, INP) 一致。注意 顺序:RES = spi.odeint(diff_eqs,t_range, INPUT)

也存在一些关于数学公式的问题:

  • 看看你图片上的第三个公式。它没有趋势项,以零开头 - 这意味着什么?
  • 很难检查您是否已将公式正确翻译成代码,因为代码并不严格遵循公式。

下面我尝试了使用 scipysolve_ivp 的解决方案。在情况 A 中,我能够运行钟摆,但在情况 B 中,无法找到对回旋镖有意义的解决方案。所以检查一下数学,我猜数学表达式有些错误。

对于图形,使用 pandas 将所有变量绘制在一起(参见下面的代码)。

import scipy.integrate as spi
import numpy as np
import pandas as pd

def diff_eqs_boomerang(t,Y):   
    INP = Y
    dY = np.zeros((9))
    dY[0] = (1/I3) * (Kz*L*(INP[1]**2+(L*INP[0])**2))
    dY[1] = -(lamb/m)*INP[1]
    dY[2] = -(1/(m * INP[1])) * ( Kz*L*(INP[1]**2+(L*INP[0])**2) + m*g) + (mu/I3)/INP[0]
    dY[3] = (1/(I3*INP[0]))*(-mu*INP[0]*np.sin(INP[6]))
    dY[4] = (1/(I3*INP[0]*np.sin(INP[3]))) * (mu*INP[0]*np.cos(INP[5]))
    dY[5] = -np.cos(INP[3])*INP[4]
    dY[6] = INP[1]*(-np.cos(INP[5])*np.cos(INP[4]) + np.sin(INP[5])*np.sin(INP[4])*np.cos(INP[3]))
    dY[7] = INP[1]*(-np.cos(INP[5])*np.sin(INP[4]) - np.sin(INP[5])*np.cos(INP[4])*np.cos(INP[3]))
    dY[8] = INP[1]*(-np.sin(INP[5])*np.sin(INP[3]))
    return dY   

def diff_eqs_pendulum(t,Y): 
    dY = np.zeros((3))
    dY[0] =  Y[1]
    dY[1] = -Y[0]
    dY[2] =  Y[0]*Y[1]
    return dY

t_start, t_end = 0.0, 12.0

case = 'A'

if case == 'A':         # pendulum
    Y = np.array([0.1, 1.0, 0.0]); 
    Yres = spi.solve_ivp(diff_eqs_pendulum, [t_start, t_end], Y, method='RK45', max_step=0.01)

if case == 'B':          # boomerang
    Y = np.array([omega0, V0, Psi0, theta0, phi0, psi0, X0, Y0, Z0])
    print('Y initial:'); print(Y); print()
    Yres = spi.solve_ivp(diff_eqs_boomerang, [t_start, t_end], Y, method='RK45', max_step=0.01)

#---- graphics ---------------------
yy = pd.DataFrame(Yres.y).T
tt = np.linspace(t_start,t_end,yy.shape[0])
with plt.style.context('fivethirtyeight'): 
    plt.figure(1, figsize=(20,5))
    plt.plot(tt,yy,lw=8, alpha=0.5);
    plt.grid(axis='y')
    for j in range(3):
        plt.fill_between(tt,yy[j],0, alpha=0.2, label='y['+str(j)+']')
    plt.legend(prop={'size':20})

enter image description here

关于python - 如何用python求解非线性DE的9方程组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54162591/

相关文章:

python - 在 emacs Python 模式下,如何为文档字符串和代码设置不同的自动填充宽度?

python - 是否有用于分析 python 代码的工具?

c++ - 可变重力下的摄像机旋转和方向

python - 如何从日期中减去一天?

python - 当我使用带有 python 扩展的 VScode 调试 TensorFlow 程序时,出现 ImportError : libcudart. so.7.5?

algorithm - 检测体素或体素组是否仍连接到对象的其余部分

algorithm - 台球AI

Matlab - 求解三阶微分方程

python - 在 Sympy 中查找微分方程的阶

python - 通过 scipy.integrate.ode 使用自适应步长