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

Python求解洛伦兹加速度运动方程:RK4与β符号问题排查

行星磁场中带电粒子运动求解的数值方法错误分析

核心问题

  • RK4方法的迭代未正常执行,所有时间步输出的都是第一次迭代的结果
  • 修改β(电荷/质量比)的符号后,粒子轨迹未发生预期变化,似乎不受电荷符号影响

代码错误解析

1. RK4函数循环提前返回

rk4函数的for循环中,return t,p语句被放在循环内部,导致循环仅执行一次就直接返回结果,后续迭代步骤完全未运行,这是所有输出都是第一次迭代结果的直接原因。

2. β被硬编码导致符号修改无效

LzForce函数内部硬定义了β = +9.36e10,无论外部如何修改β的值,函数都会使用内部固定值,因此改变电荷符号的操作根本没有传递到运动方程中,自然不会影响粒子轨迹。

3. 额外问题:初始条件被覆盖

ForwardEuler和rk4函数都在内部重新定义了p0,覆盖了用户传入的初始条件参数,导致传入的初始值失效,不符合函数设计的预期。

物理层面说明

正常情况下,带电粒子在磁场中受洛伦兹力作用,电荷符号改变会导致洛伦兹力方向反转,粒子轨迹应呈现镜像变化。当前轨迹未变化完全是代码错误导致的,并非物理规律异常。

修正后的代码

import numpy as np
import matplotlib.pyplot as plt
from math import sin, cos

scales = np.array([1e7, 0.1, 1, 1e-5, 10, 1e-5])

def LzForce(t,p, beta):
    # 解包缩放后的状态量
    r,x,θ,y,ϕ,z = p*scales
    
    # 物理常数
    R = 60268e3  # 行星半径(米)
    g_20 = 1583e-9
    Ω = 9.74e-3    # 自转角速度(度/秒)
    B_θ = (R/r)**4*g_20*cos(θ)*sin(θ)
    B_r = 2*(R/r)**4*g_20*(0.5*(3*cos(θ)**2-1))

    # 定义运动微分方程
    drdt = x
    dxdt = r*(y**2 +(z+Ω)**2*sin(θ)**2 - beta*z*sin(θ)*B_θ)
    dθdt = y
    dydt = (-2*x*y + r*(z+Ω)**2*sin(θ)*cos(θ) + beta*r*z*sin(θ)*B_r)/r 
    dϕdt = z
    dzdt = (-2*x*(z+Ω)*sin(θ) - 2*r*y*(z+Ω)*cos(θ) + beta*(x*B_θ - r*y*B_r))/(r*sin(θ))

    return np.array([drdt,dxdt,dθdt,dydt,dϕdt,dzdt])/scales

def ForwardEuler(fun,t0,p0,tf,dt, beta):
    t = np.arange(t0,tf+dt,dt)
    p = np.zeros([len(t), len(p0)])
    p[0] = p0

    for i in range(len(t)-1):
        p[i+1,:] = p[i,:] + fun(t[i],p[i,:], beta) * dt

    return t, p
   
def rk4(fun,t0,p0,tf,dt, beta):
    t = np.arange(t0,tf+dt,dt)
    p = np.zeros([len(t), len(p0)])
    p[0] = p0
     
    for i in range(len(t)-1):
        k1 = dt * fun(t[i], p[i], beta)    
        k2 = dt * fun(t[i] + 0.5*dt, p[i] + 0.5 * k1, beta)
        k3 = dt * fun(t[i] + 0.5*dt, p[i] + 0.5 * k2, beta)
        k4 = dt * fun(t[i] + dt, p[i] + k3, beta)
        p[i+1] = p[i] + (k1 + 2*(k2 + k3) + k4)/6
    # 将return移到循环外部
    return t,p
    
# 参数设置
dt = 0.5
tf = 1000
p0 = np.array([6.6e+07, 0.0, 88.0, 0.0, 0.0, 22e-3])
t0 = 0
beta_pos = +9.36e10  # 正电荷
beta_neg = -9.36e10  # 负电荷

# 用Forward Euler求解正负电荷情况
t,p_Euler_pos = ForwardEuler(LzForce,t0,p0,tf,dt, beta_pos)
t,p_Euler_neg = ForwardEuler(LzForce,t0,p0,tf,dt, beta_neg)

# 用RK4求解正负电荷情况
t ,p_RK4_pos = rk4(LzForce,t0, p0 ,tf,dt, beta_pos)
t ,p_RK4_neg = rk4(LzForce,t0, p0 ,tf,dt, beta_neg)

# 绘制Forward Euler结果(正负电荷对比)
fig,ax=plt.subplots(2,3,figsize=(12,6))
plt.suptitle("Forward Euler 正负电荷轨迹对比", y=1.02)
for idx, (a,s_pos,s_neg) in enumerate(zip(ax.flatten(), p_Euler_pos.T, p_Euler_neg.T)):
    labels = ["r","x","θ","y","ϕ","z"]
    a.plot(t,s_pos, label=f"β={beta_pos}")
    a.plot(t,s_neg, label=f"β={beta_neg}", linestyle='--')
    a.set_xlabel('时间(秒)')
    a.set_ylabel(labels[idx])
    a.grid()
    a.legend()
plt.tight_layout(); plt.show()

# 绘制RK4结果(正负电荷对比)
fig,ax=plt.subplots(2,3,figsize=(12,6))
plt.suptitle("RK4 正负电荷轨迹对比", y=1.02)
for idx, (a,s_pos,s_neg) in enumerate(zip(ax.flatten(), p_RK4_pos.T, p_RK4_neg.T)):
    labels = ["r","x","θ","y","ϕ","z"]
    a.plot(t,s_pos, label=f"β={beta_pos}")
    a.plot(t,s_neg, label=f"β={beta_neg}", linestyle='--')
    a.set_xlabel('时间(秒)')
    a.set_ylabel(labels[idx])
    a.grid()
    a.legend()
plt.tight_layout(); plt.show()

修正后的效果

  • RK4函数的循环会完整执行所有时间步,生成正确的迭代轨迹
  • 修改β符号后,正负电荷的轨迹会呈现预期的差异,符合洛伦兹力的物理规律

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:10:27