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

Sympy简化相对论粒子运动ODE后Scipy数值求解的符号替换问题

问题解决方法

问题根源

你当前的代码中将vx直接赋值为smp.diff(x,t),这就导致后续所有用到vx的位置都会被自动替换为x的一阶导数符号,因此最终求解得到的加速度表达式中自然不会保留vx、vy、vz作为独立变量,而是直接保留导数符号。

修正步骤

1. 调整符号定义,解绑速度和位置导数的绑定

不要将位置、速度、场分量定义为时间的函数,直接定义为普通实值符号,仅保留加速度为待求解的符号:

import sympy as smp
import numpy as np

# 定义常数符号
t, m, q, c = smp.symbols('t m q c', real=True)
# 定义独立输入变量:位置、速度、电磁场分量
x, y, z, vx, vy, vz, Ex, Ey, Ez, Bx, By, Bz = smp.symbols('x y z vx vy vz E_x E_y E_z B_x B_y B_z', real=True)
# 定义待求解的加速度分量符号
ax, ay, az = smp.symbols('a_x a_y a_z', real=True)

2. 用独立速度符号定义动量和运动方程

直接用vx,vy,vz计算洛伦兹因子和动量,求时间导数时手动应用链式法则替换:

v = smp.Matrix([vx, vy, vz])
a = smp.Matrix([ax, ay, az])

# 定义洛伦兹因子
gamma = 1 / smp.sqrt(1 - (v.norm()/c)**2)
# 动量对时间求导,应用链式法则:dp/dt = m*gamma*a + m*gamma**3*(v·a)/c² * v
dp_dt = m * gamma * a + m * gamma**3 * (v.dot(a))/c**2 * v
# 洛伦兹力
F = q * (smp.Matrix([Ex, Ey, Ez]) + v.cross(smp.Matrix([Bx, By, Bz])))

# 运动方程:dp_dt = F
eqs = [dp_dt[i] - F[i] for i in range(3)]

3. 求解加速度分量并生成数值函数

求解得到的ax,ay,az表达式仅包含你定义的普通符号,没有导数项,直接生成lambdify函数即可:

# 求解加速度分量
sols = smp.solve(eqs, (ax, ay, az), simplify=False, rational=False)

# 生成数值函数
input_params = (c, m, q, x, y, z, vx, vy, vz, Ex, Ey, Ez, Bx, By, Bz)
dvx_dt_f = smp.lambdify(input_params, sols[ax], modules='numpy')
dvy_dt_f = smp.lambdify(input_params, sols[ay], modules='numpy')
dvz_dt_f = smp.lambdify(input_params, sols[az], modules='numpy')

4. 调整数值积分函数

注意如果电磁场是随位置/时间变化的,需要在dSdt中先根据当前的位置、时间计算出瞬时场值,再传入加速度函数:

from scipy.integrate import odeint

# 示例:假设是恒定均匀场,实际使用时替换为你的场函数
E_field = (1e5, 0, 0)
B_field = (0, 0, 1)
# 物理常数
c_val = 3e8
m_val = 9.1e-31
q_val = 1.6e-19

def dSdt(S, t):
    vx, x, vy, y, vz, z = S
    # 计算当前时刻的电磁场值,这里用恒定场示例
    Ex_val, Ey_val, Ez_val = E_field
    Bx_val, By_val, Bz_val = B_field
    # 计算加速度
    ax = dvx_dt_f(c_val, m_val, q_val, x, y, z, vx, vy, vz, Ex_val, Ey_val, Ez_val, Bx_val, By_val, Bz_val)
    ay = dvy_dt_f(c_val, m_val, q_val, x, y, z, vx, vy, vz, Ex_val, Ey_val, Ez_val, Bx_val, By_val, Bz_val)
    az = dvz_dt_f(c_val, m_val, q_val, x, y, z, vx, vy, vz, Ex_val, Ey_val, Ez_val, Bx_val, By_val, Bz_val)
    return [ax, vx, ay, vy, az, vz]

# 示例初值:[vx0, x0, vy0, y0, vz0, z0]
S0 = [0, 0, 1e6, 0, 0, 0]
t_arr = np.linspace(0, 1e-8, 1000)
sol = odeint(dSdt, S0, t_arr)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:06:01