使用MATLAB ODE45和Python计算相同的结果

使用MATLAB ODE45和Python计算相同的结果,python,matlab,scipy,ode,orbital-mechanics,Python,Matlab,Scipy,Ode,Orbital Mechanics,我试图理解如何在Python中获得与在MATLAB中相同的结果。附件是我尝试的源代码,结果对于两种不同的方法是不正确的。在代码的底部是MATLAB的预期结果。对此问题的任何帮助都将不胜感激 从scipy.integrate导入ode 从scipy导入集成 将numpy作为np导入 def功能2(x,mu): x、 y,z=x r1=np.sqrt((x+mu)**2+(y**2)+(z**2)) r2=np.sqrt((x-(1-mu))**2+(y**2)+(z**2)) u1_x=1-(1-

我试图理解如何在Python中获得与在MATLAB中相同的结果。附件是我尝试的源代码,结果对于两种不同的方法是不正确的。在代码的底部是MATLAB的预期结果。对此问题的任何帮助都将不胜感激

从scipy.integrate导入ode
从scipy导入集成
将numpy作为np导入
def功能2(x,mu):
x、 y,z=x
r1=np.sqrt((x+mu)**2+(y**2)+(z**2))
r2=np.sqrt((x-(1-mu))**2+(y**2)+(z**2))
u1_x=1-(1-mu)*(1/(r1**3)-3*((x+mu)**2)/(r1**5))-\
mu*(1/(r2**3)-3*((x-(1-mu))**2/(r2**5))
u2_y=1-(1-mu)*(1/(r1**3))-3*y**2/(r1**5)-\
mu*(1/r2**3-3*y**2/r2**5)
u3_z=(-1)*(1-亩)*(1/r1**3)-3*z**2/r1**5-亩*\
(1/r2**3-3*z**2/r2**5)
u1_y=3*(1-mu)*y*(x+mu)/r1**5+\
3*mu*y*(z-(1-mu))/r2**5
u1_z=3*(1-mu)*z*(x+mu)/r1**5+\
3*mu*z*(x-(1-mu))/r2**5
u2_z=3*(1-mu)*y*z/r1**5+3*mu*y*z/r2**5
u3_y=u2_z
u2_x=u1_y
u3_x=u1_z
gmatrix=np.数组([[u1_x,u1_y,u1_z],
[u2_x,u2_y,u2_z],
[u3_x,u3_y,u3_z]]
返回gmatrix
def功能(t、y、mu):
x=y[36:39]
GMatrix=function2(x,mu)
OxO=np.零([3,3])
Ind=np.标识(3)
K=np.数组([[0,2,0],-2,0,0],[0,0,0]]
Df=np.bmat([[OxO[0],Ind[0]],
[OxO[1],Ind[1]],
[OxO[2],Ind[2]],
[GMatrix[0],K[0]],
[GMatrix[1],K[1]],
[GMatrix[2],K[2]]
Df=np.重塑(Df,(6,6))
A_temp=np.挤压(np.阵列(y))
A_temp=A_temp.flatten()
B_temp=[0]*42
对于范围内的i(len(A_temp)):
B_temp[i]=A_temp[i]
B_temp=B_temp[:-6]
B_temp=np.数组(B_temp)
A=B_温度重塑(6,6)
DfA=np.matmul(Df,A)
a=[0]*36
b=np.挤压(np.阵列(DfA))
b=b.展平()
对于范围内的i(len(b)):
a[i]=b[i]
r1=np.sqrt((μ+y[36])**2+(y[37]**2)+(y[38]**2))
r2=np.sqrt((1-mu-y[36])**2+(y[37]**2)+(y[38]**2))
m1=1亩
m2=亩
c=[y[39],
y[40],
y[41],
y[36]+2*y[40]+m1*(-mu-y[36])/(r1**3)+m2*(1-mu-y[36])/(r2**3),
y[37]-2*y[39]-m1*(y[37])/(r1**3)-m2*y[37]/(r2**3),
-m1*y[38]/(r1**3)-m2*y[38]/(r2**3)]
ydot=a+c
返回伊多
集成ODE的
驱动程序

如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
t0=0
tf=1.450000000000000
mu=3.054248395728148e-06
x_n=[1.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0, 0, 0, 0, 0, 0, 1.0,
0.9919755553772727, 0.0, -0.0018716577540106951,
0.0, -0.0117506137115032, 0.0]
#冰毒=‘亚当斯’
meth='bdf'
r=ode(函数)。设置积分器('vode',方法=meth,rtol=1e-13,
atol=1e-22,
_雅可比数=假)
r、 设置初始值(x_n,t0)。设置参数(mu)
r、 整合(tf)
温度=r.y
index2=[41,40,39,38,37,36]
temp=np.delete(temp,index2)
温度=温度整形(6,6)
时间=[t0,tf]
状态=集成。求解_ivp(fun=lambda t,y:
函数(t,x_n,mu),
t_span=时间,y0=x_n,方法='LSODA',密集输出=真,
rtol=1e-13,atol=1e-22)
新时间=状态。t
new_temp=states.y[:,-1]
index2=[41,40,39,38,37,36]
新温度=np.删除(新温度,index2)
新温度=新温度重塑(6,6)
打印(新温度)
打印(临时)
期望的解决方案//MATLAB ode45和ode113相同的结果

这是我正在编写的一系列脚本中的一部分,我不希望我的代码是在MATLAB中编写的。我知道MATLAB的答案是正确的,因为最终解决方案提供了我试图创建的理想轨道。我还应该注意到,MATLAB似乎使用了自适应步长,而不是像Python中那样创建的预定义时间序列
np.linspace(start,end,step)

建议的方法是ivp_解算器rk45,稠密_out=true

然而,这种方法也不能提供正确的结果。 以下是该方法的结果:

更新:当我用MATLAB使用的第一个时间步长在纸上手动计算RK45时,我得到了相同的答案。另外,当我强制时间序列使用第一个时间间隔时,我得到了与使用dense out的solve_ivp->RK45相同的答案。然而,即使使用MATLAB中相同的完整时间序列,我得到的结果也不同于MATLAB

@Lutz Lehmann在对各种不同的方法进行了一些研究和测试之后,您认为r.只集成一次是正确的。为了在每个点进行积分,需要一个回路。此外,我还能够获得ode并将_ivp解为相同的答案(尽管这是错误的答案)。当使用solve_ivp时,我必须做以下操作,这与使用ode时给出的答案相同

r=integrate.solve_ivp(fun=lambda t,y:function(t,y,mu),
t_span=时间,y0=y,方法='RK45',密集_输出=True,
rtol=1e-13,atol=1e-22)
i=0
而r.t[i]while r.t < tf: r.integrate(tf)