fix: leapfrog 模式缺少边界反弹,粒子穿透地板

问题:leapfrog 模式的主循环直接调用 leapfrog_staggered_step,
未经过 apply_motion_update,因此 Limit_in_box(边界反弹)
从未被执行。粒子超出 z<-20 后被 wrap_position 回绕到顶端,
导致物理行为完全错误。

修复:
1. 在预热和记录两个循环中,leapfrog 路径后显式调用
   Limit_in_box(与 apply_motion_update 内的非 leapfrog 路径一致)
2. 移除 apply_motion_update 末尾重复的 Limit_in_box 调用
   (统一到主循环中执行)
This commit is contained in:
2026-06-18 09:28:38 +08:00
parent 974216332c
commit 80b7467421
2 changed files with 8 additions and 6 deletions
+6 -4
View File
@@ -1798,10 +1798,6 @@ def apply_motion_update(x, y, z, vx, vy, vz, dt, m, g, b):
x, y, z, vx, vy, vz = Leapfrog_Method(x, y, z, vx, vy, vz, dt, m, g, b) x, y, z, vx, vy, vz = Leapfrog_Method(x, y, z, vx, vy, vz, dt, m, g, b)
else: else:
raise ValueError(f"未知算法: {METHOD}") raise ValueError(f"未知算法: {METHOD}")
x, vx = Limit_in_box(x, X_MIN, X_MAX, vx)
y, vy = Limit_in_box(y, Y_MIN, Y_MAX, vy)
z, vz = Limit_in_box(z, Z_MIN, Z_MAX, vz)
return x, y, z, vx, vy, vz return x, y, z, vx, vy, vz
@@ -1870,6 +1866,9 @@ def run_simulation(save_trajectory=0):
x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B) x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B)
else: else:
x, y, z, vx, vy, vz = apply_motion_update(x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B) x, y, z, vx, vy, vz = apply_motion_update(x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B)
x, vx = Limit_in_box(x, X_MIN, X_MAX, vx)
y, vy = Limit_in_box(y, Y_MIN, Y_MAX, vy)
z, vz = Limit_in_box(z, Z_MIN, Z_MAX, vz)
x, y, z = wrap_position(x, y, z) x, y, z = wrap_position(x, y, z)
x, y, z, vx, vy, vz = apply_fixed_constraints(x, y, z, vx, vy, vz) x, y, z, vx, vy, vz = apply_fixed_constraints(x, y, z, vx, vy, vz)
print( print(
@@ -1924,6 +1923,9 @@ def run_simulation(save_trajectory=0):
x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B) x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B)
else: else:
x, y, z, vx, vy, vz = apply_motion_update(x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B) x, y, z, vx, vy, vz = apply_motion_update(x, y, z, vx, vy, vz, DT, ATOM_MASSES, G, B)
x, vx = Limit_in_box(x, X_MIN, X_MAX, vx)
y, vy = Limit_in_box(y, Y_MIN, Y_MAX, vy)
z, vz = Limit_in_box(z, Z_MIN, Z_MAX, vz)
x, y, z = wrap_position(x, y, z) x, y, z = wrap_position(x, y, z)
x, y, z, vx, vy, vz = apply_fixed_constraints(x, y, z, vx, vy, vz) x, y, z, vx, vy, vz = apply_fixed_constraints(x, y, z, vx, vy, vz)
+2 -2
View File
@@ -6,7 +6,7 @@
# 每步用 0/1 单独开关,1=执行,0=跳过 # 每步用 0/1 单独开关,1=执行,0=跳过
# 依赖关系:抽帧依赖模拟结果,绘图依赖模拟+抽帧 # 依赖关系:抽帧依赖模拟结果,绘图依赖模拟+抽帧
step_simulate: 1 # 运行物理模拟 → output/trajectory.txt step_simulate: 1 # 运行物理模拟 → output/trajectory.txt
step_sample: 1 # 抽帧 → output/display.txt step_sample: 0 # 抽帧 → output/display.txt
step_plot: 1 # 绘制轨迹/能量图 → output/trajectory_plots.png step_plot: 1 # 绘制轨迹/能量图 → output/trajectory_plots.png
step_plot_wave: 0 # 绘制波形能量动画 step_plot_wave: 0 # 绘制波形能量动画
plot_wave_save_gif: 0 # 输出波形 GIF(需 step_plot_wave=1 plot_wave_save_gif: 0 # 输出波形 GIF(需 step_plot_wave=1
@@ -71,7 +71,7 @@ warmup_steps: 0 # 默认 0(立即开始记录)
T_total: 10.0 T_total: 10.0
# 抽帧间隔(每 NSTEP 步取一帧用于动画) # 抽帧间隔(每 NSTEP 步取一帧用于动画)
NSTEP: 100 NSTEP: 10
# ── 时间步长 ────────────────────────────────── # ── 时间步长 ──────────────────────────────────
DT: 0.001 # 时间步长 (s) DT: 0.001 # 时间步长 (s)