Pusher Learning Path
这页解决什么问题
本页面向第一次接触 A_Pusher 的读者。它不是粒子动力学教材,而是帮你把
非相对论 Boris、柱坐标 Boris、相对论 Higuera-Cary 这三套推进器跟 AlgoPlasma
里的 Fortran routine 对上号。读完后,应该知道该先看哪一页、哪些公式对应哪些代码、
以及测试为什么能说明实现是可信的。
推荐学习顺序
步骤 |
先理解什么 |
建议阅读 |
|---|---|---|
1 |
时间交错(leapfrog)和”速度 / 位置交替推进”的基本图景。 |
本页”核心图景” |
2 |
一次完整的 Cartesian Boris 速度推进( |
A01_Boris_3Dxyz 和 |
3 |
怎么调和怎么集成到自己代码里。 |
|
4 |
柱坐标 |
A02_Boris_3Drtz 和测试页 A02 测试。 |
5 |
相对论 Higuera-Cary:何时必须放弃 Boris、HC 多出来的步骤、高 |
|
6 |
怎样验证推进器在四类典型问题(gyro、纯 E 加速、ExB、ExB drift)下都通过。 |
核心图景
A_Pusher 的所有 routine 都做同一件事:把单个粒子的状态从 \(t^n\)
推进到 \(t^{n+1}\)。完整 PIC 循环里,调用方组织粒子数组、电磁场插值、
电流沉积、边界和时间步循环;推进器本身只负责一次原位状态更新。
leapfrog 时间错位。Boris 类方法假设速度存在半整数时间步 \(v^{n-1/2}\),位置存在整数时间步 \(x^n\)。 传入推进器的
v在物理上是v^{n-1/2},返回的是v^{n+1/2}。Boris 旋转三步走。在磁场不为零时:先做半步
E加速(v_neg), 再做B引起的旋转(v_prime → v_pos),最后再做半步E加速。E加速和B旋转是 算子分裂,二阶精度。k 是 Boris 参数。所有 A_Pusher 接口都需要
k = q\Delta t / (2m)而不是 原始q/m或q\Delta t / m——是把”半步加速”和”半角旋转”打包好的常数。位置更新归属不同。A01/A03 只更新
v,调用方写r = r + v*dt; A02 把位置更新放在 routine 内部,因为柱坐标位置更新涉及\theta旋转、 不是简单加法。场是在粒子位置取值。推进器接收的
E、B是 当前粒子位置 的取值, 不是网格量。怎么从网格插值到粒子位置是 gather 算子(C_Gather)的事, 不是推进器的事。数值稳定性由调用方负责。
\omega_c \Delta t \ll 1是 Boris 稳定且精确的条件 (\(\omega_c = qB/m\) 是回旋频率)。传入dt过大不会报错, 只会引入旋转角度误差。
初学者最容易混的点
k ≠ qm/2 ≠ q*dt/m。每次时间步如果
qm或dt变了,k必须重算 (k = 0.5*qm*dt)。常见错误是把k当作常数缓存。A01 vs A02 接口不同。A01 调用
sub_A01_Boris_3Dxyz(v, E, B, k)之后 要自己加r = r + v*dt;A02 调用sub_A02_Boris_3Drtz_push_v_x(x, v, E, B, k, dt)位置已经更新完,不能再加。柱坐标的场分量随 θ 变。如果在物理上是均匀 Cartesian
E_x, 在柱坐标里就是E_r = E_x\cos\theta、E_\phi = -E_x\sin\theta,每步都要重算。 直接传 Cartesian 分量给 A02 会得到错误轨迹。A03 内部转换 proper velocity,接口仍使用 lab velocity。A03 内部把
v转换为 proper velocity\gamma v再做 HC 旋转,接口仍然传入和返回 lab velocityv。初值约定与 Boris 相同,无需手动转换。r=0 在柱坐标里是奇点。A02 的 routine 自己用
tiny(1.0_4)检查并 fallback, 但调用方应避免让粒子真正穿过r=0附近——θ 在该处不连续。
建议练习
在草稿纸上把 Boris 旋转的三步推一遍,确认每步只用上一步的输出,不使用回旋频率 或
\sin\omega\Delta t的解析展开。跑 A01 测试 的 case 1, 画出
x-y轨迹和v^2(t),确认v^2守恒。用
dt翻倍后再跑一次,观察v^2是否仍守恒(应该仍守恒,但位置误差变大); 理解 Boris 的”速度模长守恒、角度有\omega\Delta t误差”。跑 A02 的 case 1,对比 A01 的位置最大误差——应该完全一致, 因为柱坐标 Boris 和 Cartesian Boris 物理上等价。
跑 A03 的 case 2(高
\gammaExB drift)。 非相对论 Boris 在这种工况下会有几千的偏差,HC 给出x \approx 0—— 理解何时必须切换到相对论 pusher。
What This Page Is For
This page is aimed at readers new to A_Pusher. It is not a textbook on
particle dynamics; it helps you connect the non-relativistic Boris,
cylindrical Boris, and relativistic Higuera-Cary schemes to the Fortran
routines in AlgoPlasma. After reading it, you should know which page to read
first, which formula maps to which code, and why the tests give you
confidence in the implementation.
Suggested Learning Order
Step |
What to understand first |
Suggested reading |
|---|---|---|
1 |
Leapfrog time staggering and the “advance velocity, then position” picture. |
“Core Mental Model” below. |
2 |
One full Cartesian Boris velocity push ( |
A01_Boris_3Dxyz and the API page of |
3 |
How to call the pushers and integrate them into your own code. |
|
4 |
What is genuinely different in cylindrical |
A02_Boris_3Drtz and its test page A02 tests. |
5 |
Relativistic Higuera-Cary: when Boris must be dropped, the extra steps in HC, and the payoff at high |
A03_Higuera_Cary_relativistic_3Dxyz and its test page A03 tests. |
6 |
How the four canonical cases (gyro, pure E acceleration, ExB, ExB drift) provide validation coverage. |
Core Mental Model
Every A_Pusher routine does the same thing: advance a single
particle’s state from \(t^n\) to \(t^{n+1}\). In a full PIC loop
the caller owns particle arrays, field interpolation, current deposition,
boundary handling, and the time loop; the pusher itself does one in-place
state update.
Leapfrog staggering. Boris-family methods place velocity at the half time step \(v^{n-1/2}\) and position at the integer step \(x^n\). The
vyou pass in is physicallyv^{n-1/2}; the returned value isv^{n+1/2}.Boris rotation in three steps. With nonzero
B: a half-step electric kick (v_neg), a magnetic rotation (v_prime → v_pos), then another half-step electric kick. TheEkick andBrotation are operator-split to second order.k is the Boris parameter. All A_Pusher interfaces want
k = q\Delta t / (2m), notq/mand notq\Delta t / m. It bundles “half kick” and “half rotation” into one number.Where the position update lives differs. A01/A03 only update
v, so the caller writesr = r + v*dt; A02 advances position inside the routine because the cylindrical position update involves a\thetarotation, not just addition.Fields are evaluated at the particle position. The
E,Binputs are the values at the current particle position, not grid arrays. Interpolating from the grid to the particle position is the job of the gather operator (C_Gather), not the pusher.Stability is the caller’s problem.
\omega_c \Delta t \ll 1is the Boris stability-and-accuracy condition (\(\omega_c = qB/m\)). Passing a too-largedtproduces no error; it just introduces rotation-angle errors.
Common Beginner Traps
k ≠ qm/2 ≠ q*dt/m. If
qmordtchanges between steps,kmust be recomputed (k = 0.5*qm*dt). A common mistake is cachingkas a constant.A01 and A02 have different interfaces. After
sub_A01_Boris_3Dxyz(v, E, B, k)the caller must addr = r + v*dt; aftersub_A02_Boris_3Drtz_push_v_x(x, v, E, B, k, dt)the position is already updated and must not be added again.Cylindrical field components depend on θ. A uniform Cartesian
E_xbecomesE_r = E_x\cos\theta,E_\phi = -E_x\sin\thetain cylindrical components, recomputed every step. Passing Cartesian components to A02 will produce a wrong trajectory.A03 converts proper velocity internally while keeping a lab-velocity interface. It converts
vto proper velocity\gamma vinternally; the interface still accepts and returns lab velocityv. The initial-value convention is the same as Boris — no manual conversion is needed.r = 0 is a coordinate singularity. A02’s routine uses a
tiny(1.0_4)fallback, but callers should avoid pushing particles truly close tor = 0;\thetais discontinuous there.
Suggested Exercises
Work through the three Boris rotation steps on paper and verify each step uses only the previous step’s output, not an analytic expansion of
\sin\omega\Delta t.Run A01 tests case 1, plot the
x-ytrajectory andv^2(t), and confirmv^2is conserved.Re-run with
dtdoubled and watchv^2stay conserved (it should) while the position error grows; that is Boris’s “exact speed, slightly wrong angle” behavior.Run A02 case 1 and compare the maximum position error against A01 — they should match, because the cylindrical Boris is physically equivalent to the Cartesian Boris.
Run A03 case 2 (high-
\gammaExB drift). Non-relativistic Boris drifts by several thousand under the same setup; HC producesx \approx 0. That is the canonical example of when you must switch to the relativistic pusher.