【问题标题】:Coupled system of 4 differential equations - Python4个微分方程的耦合系统 - Python
【发布时间】:2021-03-28 08:36:18
【问题描述】:

我在图中得到了 4 个微分方程的耦合系统。我有 4 个函数(xG;yG;gamma;beta)及其衍生物。它们都是同一个自变量t的函数。

我正在尝试用 odeint 解决它。问题是,为了做到这一点,我认为我需要以每个二阶导数不依赖于其他二阶导数的方式来表达系统。这涉及大量的数学运算,肯定会在某个地方出错(我试过了!)。

你知道我该怎么做吗:

  1. 按原样求解这个微分方程组?
  2. 或者让python帮我隔离二阶导数?

我正在附上我的测试代码

谢谢

import numpy
import math
from numpy import loadtxt
from pylab import figure,  savefig
import matplotlib.pyplot as plt
# Use ODEINT to solve the differential equations defined by the vector field
from scipy.integrate import odeint



def vectorfield(w, t, p):
    """
    Defines the differential equations for the coupled system.

    Arguments:
        w :  vector of the state variables:
                  w = [Xg, Xg1 Yg, Yg1, Gamma, Gamma1, Beta, Beta1]
        t :  time
        p :  vector of the parameters:
                  p = [m, rAG, Ig,lcavo]
    """
#Xg is position ; Xg1 is the first derivative ; Xg2 is the second derivative (the same for the other functions)
        Xg, Xg1,  Yg, Yg1, Gamma, Gamma1, Beta, Beta1 = w
        Xg2=-(Ig*Gamma2*math.cos(Beta))/(rAG*m*(-math.cos(Gamma)*math.sin(Beta)+math.sin(Gamma)*math.cos(Beta)))
        Yg2=-(Ig*Gamma2*math.sin(Beta))/(rAG*m*(-math.cos(Gamma)*math.sin(Beta)+math.sin(Gamma)*math.cos(Beta)))-9.81
        Gamma2=((Beta2*lcavo*math.sin(Beta))+(Beta1**2*lcavo*math.cos(Beta))+(Xg2)-(Gamma1**2*rAG*math.cos(Gamma)))/(rAG*math.sin(Gamma))
        Beta2=((Yg2)+(Gamma2*rAG*math.cos(Gamma))-(Gamma1**2*rAG*math.sin(Gamma))+(Beta1**2*lcavo*math.sin(Beta)))/(lcavo*math.cos(Beta))
        m, rAG, Ig,lcavo, Xg2,  Yg2, Gamma2, Beta2 = p
    
    
    # Create f = (Xg', Xg1' Yg', Yg1', Gamma', Gamma1', Beta', Beta1'):
    f = [Xg1,
         Xg2,
         Yg1, 
         Yg2, 
         Gamma1, 
         Gamma2, 
         Beta1, 
         Beta2]
         
    return f

    


# Parameter values
m=2.722*10**4
rAG=2.622
Ig=3.582*10**5
lcavo=4
# Initial conditions
Xg = 0.0
Xg1 = 0
Yg = 0.0
Yg1 = 0.0
Gamma=-2.52
Gamma1=0
Beta=4.7
Beta1=0

# ODE solver parameters
abserr = 1.0e-8
relerr = 1.0e-6
stoptime = 5.0
numpoints = 250

#create the time values
t = [stoptime * float(i) / (numpoints - 1) for i in range(numpoints)]
Deltat=t[1]
# Pack up the parameters and initial conditions:
p = [m, rAG, Ig,lcavo, Xg2,  Yg2, Gamma2, Beta2]
w0 = [Xg, Xg1,  Yg, Yg1, Gamma, Gamma1, Beta, Beta1]

# Call the ODE solver.
wsol = odeint(vectorfield, w0, t, args=(p,),
              atol=abserr, rtol=relerr)

【问题讨论】:

    标签: python python-3.x scipy ode odeint


    【解决方案1】:

    您需要将所有二阶导数重写为一阶导数并一起求解 8 个 ODE:

    那么你需要所有导数的初始条件,但似乎你已经有了。 仅供参考,您的代码无法运行 (line 71: NameError: name 'Xg2' is not defined),请检查一下。

    另外,有关更多信息,请参阅solving the 2nd order ODE numerically

    编辑#1: 第一步,您需要解耦方程组。虽然你可以手动解决它,但我不推荐,所以让我们使用sympy 模块:

    import sympy as sm
    from sympy import symbols
    
    # define symbols. I assume all the variables are real-valued, this helps the solver. If not, I believe the result will be the same, but just calculated slower
    Ig, gamma, gamma1, gamma2, r, m, beta, beta1, beta2, xg2, yg2, g, l = symbols('I_g, gamma, gamma1, gamma2, r, m, beta, beta1, beta2, xg2, yg2, g, l', real = True)
    
    # define left hand sides as expressions
    # 2nd deriv of gamma
    g2 = (beta2 * l * sm.sin(beta) + beta1**2 *l *sm.cos(beta) + xg2 - gamma1**2 *r * sm.cos(gamma))/(r*sm.sin(gamma))
    # 2nd deriv of beta
    b2 = (yg2 + gamma2 * r * sm.cos(gamma) - gamma1**2 *r * sm.sin(gamma) + beta1**2 *l *sm.sin(beta))/(l*sm.cos(beta))
    # 2nd deriv of xg
    x2 = -Ig*gamma2*sm.cos(beta)/(r*m*(-sm.sin(beta)*sm.cos(gamma) + sm.sin(gamma)*sm.cos(beta)))
    # 2nd deriv of yg
    y2 = -Ig*gamma2*sm.sin(beta)/(r*m*(-sm.sin(beta)*sm.cos(gamma) + sm.sin(gamma)*sm.cos(beta))) - g
    
    # now let's solve the system of four equations to decouple second order derivs
    # gamma2 - g2 means "gamma2 - g2 = 0" to the solver. The g2 contains gamma2 by definition
    # one could define these equations the other way, but I prefer this form
    result = sm.solve([gamma2-g2,beta2-b2,xg2-x2,yg2-y2],
                      # this line tells the solver what variables we want to solve to
                      [gamma2,beta2,xg2,yg2] )
    # print the result
    # note that it is long and ugly, but you can copy-paste it as python code
    for res in result:
        print(res, result[res])
    

    现在我们已经解耦了所有二阶导数。例如,beta2 的表达式为

    所以它(以及所有其他二阶导数也)具有形式

    请注意,不依赖于 xgyg

    我们来介绍两个新变量bk

    然后 变成

    要求解的完整 ODE 系统是

    现在所有 ODE 都依赖于四个变量,这些变量不是任何事物的导数。另外,由于xgyg是退化的,所以也只有6个方程而不是8个。但是,可以用与gammabeta相同的方式重写这两个方程以获得8的完整系统方程,并将其整合在一起。

    【讨论】:

    • 感谢您的回复。但是,您编写的第一个方程是 psi 的导数,它等于 g 的导数的函数。我如何写 g 的 python 导数?
    • 这种方法不需要“导数函数”。你需要 8 个“简单”的函数。
    • 谢谢,您能提供一些更详细的信息吗?在 odeint 中,我需要定义一个定义良好的简单函数的函数。如何定义一个函数是另一个函数的导数?
    • @Francesco,SciPy 食谱页面Coupled spring-mass system 给出了将两个二阶方程系统转换为四个一阶方程系统的示例。看看是否有帮助。
    • 谢谢沃伦。这正是我作为代码基础的地方。不幸的是,该示例基于一个系统,您可以轻松地将二阶导数作为常数或时间函数或其一阶导数的函数获得。而在我的例子中,我不能轻易地获得作为常数、函数或一阶导数的函数的二阶导数:我总是在方程的两边都有二阶导数。遇到这种情况怎么办?
    猜你喜欢
    • 2013-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多