C01_gather_3Dxyz Test ===================== .. raw:: html
.. container:: ap-lang ap-lang-zh .. rubric:: 测试目标 本页说明 ``tests/007_gather/C01_gather_3Dxyz`` 中的参考测试。该测试覆盖 :doc:`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 分解、边界交换、粒子沉积或场推进。 .. rubric:: 程序结构 - ``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 缓存。 .. rubric:: 运行方式 .. code-block:: bash 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`` 的结果。 .. rubric:: 输出字段 - ``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。 .. rubric:: 坐标约定 C01 内部使用下面的 cell-centered 坐标偏移: .. code-block:: fortran x = par(1,p) + 0.5 y = par(2,p) + 0.5 z = par(3,p) + 0.5 因此 Python 解析参考值也在 :math:`(par_1+0.5, par_2+0.5, par_3+0.5)` 处计算。这个测试同时检查该 ``+0.5`` 坐标约定是否被正确使用。 .. rubric:: 测试算例 .. list-table:: :header-rows: 1 :widths: 16 38 32 14 * - 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 使用的参考更新为 .. math:: \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. .. rubric:: 参考图 .. figure:: ../../images/tests/007_gather/C01_gather_3Dxyz/c01_ref_vs_num.png :align: center :figclass: ap-figure-equal-height ap-figure-wide ``exact`` case 的场值对比。横轴为粒子位置处的解析场分量值,纵轴为 C01 gather 得到的同一分量值。每个点代表一个粒子的一个 ``Ex/Ey/Ez/Bx/By/Bz`` 分量;点越贴近虚线,说明 gather 越接近解析值。 .. figure:: ../../images/tests/007_gather/C01_gather_3Dxyz/c01_convergence.png :align: center :figclass: ap-figure-equal-height ap-figure-wide ``convergence`` case 的误差随网格间距变化。横轴为 ``h=1/N``,纵轴为 gather 场分量相对解析值的误差。``L2`` 汇总所有粒子和六个场分量, ``Linf`` 是最大单分量误差。 .. figure:: ../../images/tests/007_gather/C01_gather_3Dxyz/c01_push_displacement.png :align: center :figclass: ap-figure-equal-height ap-figure-wide ``push`` case 的粒子单步位移。每条线段从推进前 ``(x0,y0)`` 指向推进后 ``(x1,y1)``,用于观察 fused gather-push 的位移方向和量级。 .. rubric:: 参考运行结果 .. code-block:: text exact max_abs error : 8.882e-16 convergence min order : 1.936 fused push max_abs error: 2.776e-17 result : PASS .. container:: ap-lang ap-lang-en .. rubric:: Test Goal This page documents the reference test under ``tests/007_gather/C01_gather_3Dxyz``. The test covers two interfaces from :doc:`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. .. rubric:: 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. .. rubric:: Run Command .. code-block:: bash 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``. .. rubric:: 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. .. rubric:: Coordinate Convention C01 uses the following cell-centered shift: .. code-block:: fortran x = par(1,p) + 0.5 y = par(2,p) + 0.5 z = par(3,p) + 0.5 Therefore Python evaluates references at :math:`(par_1+0.5, par_2+0.5, par_3+0.5)`. The test also checks that this ``+0.5`` convention is used consistently. .. rubric:: Test Cases .. list-table:: :header-rows: 1 :widths: 16 38 32 14 * - 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 .. math:: \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. .. rubric:: Reference Figures .. figure:: ../../images/tests/007_gather/C01_gather_3Dxyz/c01_ref_vs_num.png :align: center :figclass: ap-figure-equal-height ap-figure-wide ``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``. .. figure:: ../../images/tests/007_gather/C01_gather_3Dxyz/c01_convergence.png :align: center :figclass: ap-figure-equal-height ap-figure-wide ``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. .. figure:: ../../images/tests/007_gather/C01_gather_3Dxyz/c01_push_displacement.png :align: center :figclass: ap-figure-equal-height ap-figure-wide ``push`` one-step displacement. Each segment goes from ``(x0,y0)`` before the step to ``(x1,y1)`` after the step. .. rubric:: Reference Result .. code-block:: text exact max_abs error : 8.882e-16 convergence min order : 1.936 fused push max_abs error: 2.776e-17 result : PASS