C01_gather_3Dxyz Test

测试目标

本页说明 tests/007_gather/C01_gather_3Dxyz 中的参考测试。该测试覆盖 C01_gather_3Dxyz 提供的两个接口:

  • sub_C01_gather_3Dxyz:把 cell-centered 三维 Cartesian 电磁场 Ex,Ey,Ez,Bx,By,Bz gather 到单个粒子位置。

  • sub_C01_gather_3Dxyz_push:在同一个粒子循环中完成 gather、Boris 速度更新和位置推进。

测试重点是局部验证 C01 的三线性插值和 fused gather-push。它回答三个问题:

  • 网格场为三线性解析函数时,C01 是否能精确还原粒子位置处的解析场值?

  • 网格场为光滑但非三线性函数时,网格加密后 gather 误差是否下降?

  • B=0 时,fused gather-push 是否等价于一次解析电场加速?

该测试不是完整 PIC 回路测试;不覆盖 MPI 分解、边界交换、粒子沉积或场推进。

程序结构

  • source_f90/main.f90 构造三组人造场和粒子,调用 C01,并写出 CSV。

  • source_py/analyze.py 读取 CSV,独立计算解析参考值,统计误差并生成图片。

  • make.sh 使用 gfortran -cpp -O2 -fdefault-real-8 -fopenmp 编译测试程序。

  • run.sh 依次执行清理、编译、Fortran 测试和 Python 后处理。

  • clean.sh 删除 build/、output/ 和 Python 缓存。

运行方式

cd tests/007_gather/C01_gather_3Dxyz
bash run.sh

run.sh 会生成 output/*.csv、output/summary.json 和 output/figures/*.png。文档中的静态图是从一次参考运行复制到 docs/source/images/tests/007_gather/C01_gather_3Dxyz 的结果。

输出字段

  • output/c01_exact.csv:每个粒子的 px,py,pz 和 C01 gather 得到的 Ex,Ey,Ez,Bx,By,Bz。

  • output/c01_convergence.csv:网格数 n、网格间距 h、物理坐标 x,y,z 和六个 gather 场分量。

  • output/c01_push.csv:推进前后的粒子位置和速度,即 x0,y0,z0,vx0,vy0,vz0 与 x1,y1,z1,vx1,vy1,vz1。

  • output/summary.json:三个 case 的最大误差、收敛阶和 PASS/FAIL。

坐标约定

C01 内部使用下面的 cell-centered 坐标偏移:

x = par(1,p) + 0.5
y = par(2,p) + 0.5
z = par(3,p) + 0.5

因此 Python 解析参考值也在 \((par_1+0.5, par_2+0.5, par_3+0.5)\) 处计算。这个测试同时检查该 +0.5 坐标约定是否被正确使用。

测试算例

Case

设置

主要检查

判据

exact

在网格点上填入六个不同的三线性解析场分量,并放置 60 个非整数位置粒子。

三线性插值对三线性函数应精确,所以 C01 gather 值应等于粒子位置解析值。

最大绝对误差 < 1e-11。

convergence

使用 N=12,24,48 三套网格,填入同一个光滑解析场,并在相同物理位置放置 125 个粒子。

光滑场不是三线性函数,误差不为零;但网格加密后误差应下降。

最小观测收敛阶 > 1.75。

push

设置 16 个粒子,电场为三线性解析场,磁场设为 B=0,调用 fused gather-push。

B=0 时 Boris 推进退化为纯电场加速,可直接写出解析参考更新。

更新后 x,v 最大绝对误差 < 1e-11。

source_py/analyze.py 不调用 C01;它只读取 Fortran 输出并独立计算参考答案。 push case 使用的参考更新为

\[\mathbf{v}^{n+1}=\mathbf{v}^{n}+\frac{q}{m}\mathbf{E}\Delta t,\qquad \mathbf{x}^{n+1}=\mathbf{x}^{n}+\mathbf{v}^{n+1}\Delta t.\]

参考图

../../_images/c01_ref_vs_num.png

exact case 的场值对比。横轴为粒子位置处的解析场分量值,纵轴为 C01 gather 得到的同一分量值。每个点代表一个粒子的一个 Ex/Ey/Ez/Bx/By/Bz 分量;点越贴近虚线,说明 gather 越接近解析值。

../../_images/c01_convergence.png

convergence case 的误差随网格间距变化。横轴为 h=1/N,纵轴为 gather 场分量相对解析值的误差。L2 汇总所有粒子和六个场分量, Linf 是最大单分量误差。

../../_images/c01_push_displacement.png

push case 的粒子单步位移。每条线段从推进前 (x0,y0) 指向推进后 (x1,y1),用于观察 fused gather-push 的位移方向和量级。

参考运行结果

exact max_abs error      : 8.882e-16
convergence min order   : 1.936
fused push max_abs error: 2.776e-17
result                  : PASS

Test Goal

This page documents the reference test under tests/007_gather/C01_gather_3Dxyz. The test covers two interfaces from C01_gather_3Dxyz:

  • sub_C01_gather_3Dxyz: gathers cell-centered 3D Cartesian electromagnetic fields Ex,Ey,Ez,Bx,By,Bz to one particle.

  • sub_C01_gather_3Dxyz_push: performs gather, Boris velocity update, and position advance in one particle loop.

The test locally verifies C01 trilinear interpolation and fused gather-push. It checks whether trilinear grid fields are reproduced exactly at particle positions, whether smooth-field gather errors decrease under refinement, and whether B=0 fused gather-push matches one analytic electric acceleration step. It does not test a full PIC loop, MPI decomposition, boundary exchange, deposition, or field solve.

Program Structure

  • source_f90/main.f90 constructs three synthetic field/particle cases, calls C01, and writes CSV files.

  • source_py/analyze.py reads the CSV files, computes independent analytic references, computes errors, and saves figures.

  • make.sh compiles with gfortran -cpp -O2 -fdefault-real-8 -fopenmp.

  • run.sh performs cleanup, build, Fortran execution, and Python postprocessing.

  • clean.sh removes build/, output/, and Python cache files.

Run Command

cd tests/007_gather/C01_gather_3Dxyz
bash run.sh

run.sh writes output/*.csv, output/summary.json, and output/figures/*.png. The static figures below are copied from one reference run into docs/source/images/tests/007_gather/C01_gather_3Dxyz.

Output Fields

  • output/c01_exact.csv: particle px,py,pz and gathered Ex,Ey,Ez,Bx,By,Bz.

  • output/c01_convergence.csv: grid size n, grid spacing h, physical coordinates x,y,z, and gathered field components.

  • output/c01_push.csv: particle position/velocity before and after the step: x0,y0,z0,vx0,vy0,vz0 and x1,y1,z1,vx1,vy1,vz1.

  • output/summary.json: errors, convergence order, and PASS/FAIL for the three cases.

Coordinate Convention

C01 uses the following cell-centered shift:

x = par(1,p) + 0.5
y = par(2,p) + 0.5
z = par(3,p) + 0.5

Therefore Python evaluates references at \((par_1+0.5, par_2+0.5, par_3+0.5)\). The test also checks that this +0.5 convention is used consistently.

Test Cases

Case

Setup

Main check

Criterion

exact

Six different trilinear analytic field components are sampled on grid nodes; 60 particles are placed at non-integer positions.

Trilinear interpolation should reproduce the analytic value at each particle.

Max absolute error < 1e-11.

convergence

Grids N=12,24,48 use the same smooth analytic field; 125 particles stay at fixed physical positions.

The field is not trilinear, so the error is nonzero but should decrease under mesh refinement.

Minimum observed order > 1.75.

push

16 particles, trilinear electric field, and B=0; fused gather-push is called.

With B=0, Boris reduces to a directly checkable electric acceleration step.

Max absolute error in updated x,v < 1e-11.

source_py/analyze.py does not call C01; it reads Fortran output and computes independent references. In the push case the reference is

\[\mathbf{v}^{n+1}=\mathbf{v}^{n}+\frac{q}{m}\mathbf{E}\Delta t,\qquad \mathbf{x}^{n+1}=\mathbf{x}^{n}+\mathbf{v}^{n+1}\Delta t.\]

Reference Figures

../../_images/c01_ref_vs_num.png

exact field comparison. x-axis: analytic field component at the particle. y-axis: the same component gathered by C01. Each point is one particle-component pair from Ex/Ey/Ez/Bx/By/Bz.

../../_images/c01_convergence.png

convergence error versus grid spacing. x-axis: h=1/N. y-axis: error of gathered field components against the analytic field. L2 uses all particles/components; Linf is the largest single component error.

../../_images/c01_push_displacement.png

push one-step displacement. Each segment goes from (x0,y0) before the step to (x1,y1) after the step.

Reference Result

exact max_abs error      : 8.882e-16
convergence min order   : 1.936
fused push max_abs error: 2.776e-17
result                  : PASS