4 个微分方程的耦合系统 - Python
Coupled system of 4 differential equations - Python
我得到了图中4个微分方程的耦合系统。我有 4 个函数 (xG; yG ;gamma; beta) 及其导数。它们都是同一个自变量t的函数。
我正在尝试用 odeint 解决它。问题是,为了这样做,我认为我需要以每个二阶导数不依赖于其他二阶导数的方式来表达系统。这涉及到一定数量的数学,肯定会让我在某个地方出错(我试过了!)。
你知道我怎么做吗:
- 按原样求解这个微分方程组?
- 或者让 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)
您需要将所有二阶导数重写为一阶导数并一起求解 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
的表达式是
所以它(以及所有其他二阶导数)具有形式
请注意,不依赖于 xg
或 yg
。
让我们介绍两个新变量,b
和k
:
然后
成为
要求解的完整 ODE 系统是
现在所有的 ODE 都依赖于四个变量,这四个变量不是任何东西的导数。此外,由于 xg
和 yg
退化,因此也只有 6 个方程而不是 8 个。但是,可以用与 gamma
和 [=21 相同的方式重写这两个方程=] 获得完整的 8 个方程组,并将其整合在一起。
我得到了图中4个微分方程的耦合系统。我有 4 个函数 (xG; yG ;gamma; beta) 及其导数。它们都是同一个自变量t的函数。
我正在尝试用 odeint 解决它。问题是,为了这样做,我认为我需要以每个二阶导数不依赖于其他二阶导数的方式来表达系统。这涉及到一定数量的数学,肯定会让我在某个地方出错(我试过了!)。
你知道我怎么做吗:
- 按原样求解这个微分方程组?
- 或者让 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)
您需要将所有二阶导数重写为一阶导数并一起求解 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
的表达式是
所以它(以及所有其他二阶导数)具有形式
请注意,不依赖于 xg
或 yg
。
让我们介绍两个新变量,b
和k
:
然后
要求解的完整 ODE 系统是
现在所有的 ODE 都依赖于四个变量,这四个变量不是任何东西的导数。此外,由于 xg
和 yg
退化,因此也只有 6 个方程而不是 8 个。但是,可以用与 gamma
和 [=21 相同的方式重写这两个方程=] 获得完整的 8 个方程组,并将其整合在一起。