基于VPython实现地球绕日模拟:需用引力能量与速度方程(禁球坐标)
我来帮你完善这个地球绕太阳的引力模拟!你已经搭好了基础的天体对象和初始参数,接下来咱们就基于引力势能与速度的关系(通过万有引力定律推导加速度,再用数值积分更新速度和位置)完成核心逻辑,全程不用球坐标系,纯笛卡尔坐标系实现。
核心原理说明
咱们不用球坐标系,直接在笛卡尔坐标系下计算:
- 万有引力的大小遵循公式:$F = G\frac{Mm}{r^2}$,方向始终指向太阳(从地球指向太阳的单位向量)
- 根据牛顿第二定律 $F=ma$,可以推导出地球的加速度:$a = -\frac{GM\vec{r}}{r^3}$(负号表示加速度方向与$\vec{r}$相反,指向太阳)
- 用数值积分(这里用简单的欧拉法)更新速度和位置:$\vec{v} += \vec{a} \cdot dt$,$\vec{pos} += \vec{v} \cdot dt$
- 同时可以验证能量守恒:总能量 = 动能 + 引力势能,在无外力干扰的情况下总能量应该保持恒定
完整代码实现
基于你已有的代码,补全模拟循环和核心计算逻辑(这里假设你用的是VPython/GlowScript环境,因为代码里用到了sphere和vector对象):
from vpython import * import math # 初始化天体对象 earth = sphere(color=color.green, radius=10**6) sun = sphere(color=color.yellow, radius=10**7) # 设置天体质量(单位:kg) earth.mass = 5.972*10**24 sun.mass = 1.989*10**30 # 初始轨道参数 d = 1.496*10**8 # 日地距离(单位:km,注意单位统一) year_seconds = 3.154*10**7 # 一年的秒数 # 初始圆周运动速度:v = 2πd/T v = (2*math.pi*d) / year_seconds earth.velocity = vector(0.0, 0.0, -v) # 初始速度沿-z方向,形成圆周轨道 earth.pos = vector(d, 0, 0) # 地球初始位置在x轴正方向 sun.pos = vector(0, 0, 0) # 太阳固定在原点 # 模拟参数 G = 6.67430e-20 # 万有引力常数(单位:km³/(kg·s²),和km、kg、s单位匹配) dt = 50000 # 时间步长(单位:秒) t = 0.0 # 为地球添加轨迹,方便观察运动路径 earth.trail = curve(color=color.green) # 模拟主循环 while True: rate(30) # 控制模拟帧率,避免画面过快 # 计算地球到太阳的向量和距离 r_vector = earth.pos - sun.pos r_magnitude = mag(r_vector) # 计算地球的引力加速度 acceleration = -G * sun.mass * r_vector / (r_magnitude ** 3) # 更新速度和位置(欧拉法数值积分) earth.velocity += acceleration * dt earth.pos += earth.velocity * dt # 更新轨迹点 earth.trail.append(pos=earth.pos) # 可选:计算并验证总能量(取消注释即可查看) # kinetic_energy = 0.5 * earth.mass * mag(earth.velocity) ** 2 # gravitational_potential = -G * sun.mass * earth.mass / r_magnitude # total_energy = kinetic_energy + gravitational_potential # print(f"t={t/3600:.1f}h, Total Energy: {total_energy:.2e} J") t += dt
关键细节解释
- 单位统一:这里所有物理量的单位都统一为km、kg、s,所以万有引力常数G用了
6.67430e-20(对应km³/(kg·s²)),如果换成米的话要调整G的数值和天体半径、距离 - 初始速度:你用的圆周运动速度公式完全正确,因为初始轨道是圆周,引力刚好提供向心力,符合能量平衡
- 数值积分:这里用的是简单欧拉法,虽然精度不算最高,但对于基础模拟足够;如果需要更准确的轨道,可以换成半隐式欧拉法或者Verlet积分
- 能量守恒验证:取消代码里的注释后,可以看到总能量基本保持恒定,这也符合引力系统的能量守恒特性
内容的提问来源于stack exchange,提问作者user9566436




