You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python蛙跳法计算地球轨道能量溢出及结果异常问题

地球轨道仿真能量计算问题

编辑补充:目前我已得到地球轨道仿真的相关绘图,但总能量结果不符合预期,请问总能量是否应当在0值附近振荡?
感谢解答!

总能量随时间变化曲线E(t)

我目前正在完成数值方法课程作业的b部分题目:地球轨道仿真题目说明
目标是修改a部分已完成的代码,使其能够输出地球轨道的动能与势能,但运行时出现如下报错:

(8.12).py:31: RuntimeWarning: overflow encountered in multiply
  z_vec[i+1,:]=z_vec[i,:] + h*f(z_half_step, t_vec[i])

目前编写的动能、势能求解代码存在明显错误,核心问题是不知道如何正确修改a部分的代码来实现势能与动能的计算。

a部分可正常运行的代码

以下a部分代码运行后可得到5年周期内略偏离正圆的地球运行轨迹:

import matplotlib.pyplot as plt
import numpy as np
import scipy.integrate as spi


"""a"""


G = 6.6738*10**-11
M = 1.9891*10**30
h = 3600
y = 1.4710*10**11
vx = 3.0287*10**4

def LeapFrog(f, t_start, t_stop, z0, h):

    t_vec = np.arange(t_start, t_stop, h) 
    n = len(t_vec)
    d = len(z0)  
    z_vec = np.zeros((n, d))
    z_vec[0,:] = z0
    z_half_step=z_vec[0 , :] + (1/2)*h*f(z0,t_vec[0]) 
    
    
    for i in range(0, n - 1):
        z_vec[i+1,:]=z_vec[i,:] + h*f(z_half_step, t_vec[i])
        z_half_step += h*f(z_vec[i+1,:], t_vec[i])   


    return t_vec, z_vec, 


def f(z,t):   #dz/dt
    
    x=z[0]
    y=z[1] 
    vx=z[2] 
    vy=z[3] 
    r=np.sqrt(x**2+y**2)

    dz=np.zeros(4)
    
    dz[0]=vx 
    dz[1]=vy
    dz[2]=-G*M*x/r**3
    dz[3]=-G*M*y/r**3

    return dz

t_start = 0
t_stop = 24*365*h*5 #5 years
z0 = np.array([0,y,vx,0])
t_vec, z_vec = LeapFrog(f, t_start, t_stop, z0, h)



figure, ax = plt.subplots()

plt.title("Orbit of the Earth")
plt.plot(0,0,'yo', label = 'Sun positon')  
plt.plot(z_vec[:,0],z_vec[:,1], 'g', markersize=1, label='Earth trajectory')
ax.set_aspect('equal')

ax.set(xlim=(-1.55*10**11, 1.55*10**11), ylim = (-1.55*10**11, 1.55*10**11))
a_circle = plt.Circle((0, 0), 1.4710*10**11, fill=False,color='r')
ax.add_artist(a_circle)
ax.set_aspect('equal')

legend = plt.legend(['Sun position','Earths 5-year trajectory','Perfect circle'],loc='center left', bbox_to_anchor=(1, 0.5))

plt.show()



"""
We can see that the trajectory of the earth for 5 years is very slightly non-circular.
"""

b部分错误代码

完成b部分时错误修改了dz[2]和dz[3]项,导致代码无法正常运行,错误代码如下:

"""b"""

m = 5.9722*10**24
def f(z,t):   #dz/dt

    x=z[0]
    y=z[1] 
    vx=z[2] 
    vy=z[3] 
    r=np.sqrt(x**2+y**2)

    dz=np.zeros(4)

    dz[0]=vx 
    dz[1]=vy
    dz[2]=-G*M*m/r
    dz[3]=0.5*m*y**2

    return dz

t_start = 0
t_stop = 24*365*h*5 #5 years
z0 = np.array([0,y,vx,0])
LeapFrog(f, t_start, t_stop, z0, h)

解答

总能量取值说明

地球绕太阳公转属于束缚轨道,总能量(动能+引力势能)恒为负值,不会在0附近振荡:

  • 动能计算公式为 $E_k=\frac{1}{2}m(v_x2+v_y2)$,恒为正
  • 引力势能计算公式为 $E_p=-\frac{GMm}{r}$(以无穷远为势能零点),恒为负
    束缚轨道下引力势能的绝对值始终大于动能,因此总能量为负。你用的蛙跳法(Leapfrog)是辛积分器,总能量只会在真实值附近做小幅度的有界振荡,不会出现无限制漂移。如果总能量在0附近甚至为正,要么是能量计算逻辑错误,要么是数值仿真发散,轨道已经变成非束缚的抛物线/双曲线轨道。

报错与代码错误原因

核心错误是误将能量计算写进了运动方程的导数项。
你a部分写的运动方程f(z,t)是完全正确的,描述的是万有引力产生的加速度,不需要做任何修改。动能和势能是仿真得到位置、速度结果后,通过后处理计算的导出量,不是用来更新轨道运动状态的变量。你错误替换了加速度项dz[2]和dz[3],相当于完全改乱了地球的受力规则,导致数值计算快速发散,才会触发数值溢出的RuntimeWarning。

正确实现方法

不需要改动a部分的Leapfrog积分函数、运动方程f(z,t),只需要在跑完轨道仿真、得到t_vec和z_vec之后,追加以下后处理代码即可计算能量:

# 地球质量
m = 5.9722*10**24
# 从仿真结果中提取位置、速度序列
x = z_vec[:, 0]
y = z_vec[:, 1]
vx = z_vec[:, 2]
vy = z_vec[:, 3]
r = np.sqrt(x**2 + y**2)
# 分别计算动能、势能、总能量
Ek = 0.5 * m * (vx**2 + vy**2)
Ep = -G * M * m / r
E_total = Ek + Ep

# 可选:绘制能量随时间变化曲线
plt.figure(figsize=(10,6))
plt.plot(t_vec, Ek, label='动能')
plt.plot(t_vec, Ep, label='引力势能')
plt.plot(t_vec, E_total, label='总能量')
plt.xlabel('仿真时间 (s)')
plt.ylabel('能量 (J)')
plt.legend()
plt.grid(alpha=0.3)
plt.show()

注:蛙跳法的速度定义在半时间步上,如果追求更高精度,可以用半时间步的速度值计算动能,不过以1小时为步长仿真地球轨道时,直接用整步输出的速度计算的能量误差完全可以满足课程作业要求。


内容的提问来源于stack exchange,提问作者Grayham_T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:09:36