001_Two-stream Example
概述与物理设置
本示例演示如何将多个 AlgoPlasma 组件组合成一个面向具体问题的静电 粒子网格(particle-in-cell, PIC)程序。算例采用二维空间和三维速度 (2D3V),研究周期区域中的电子双流不稳定性。两束等权电子沿 \(x\) 方向以 \(\pm3v_{te}\) 反向漂移,固定、均匀的正电荷背景维持初始电中性, 其中 \(v_{te}=\sqrt{k_{\mathrm B}T_e/m_e}\) 是每束 Maxwell 速度分布 单个分量的标准差。
第一束电子由 I01 在每个网格单元中规则布置粒子并采样速度;第二束复制其位置, 同时反转三个速度分量,从而形成保持对称性的静启动。随后对两束电子施加纵向位移
当前设置取 \(\delta_0=0.005\) 和 \((m_x,m_y)=(2,1)\),对应一阶 近似下幅度为 0.5% 的密度扰动。指定单一斜模态既提供了明确的线性增长率比较对象, 也同时检验二维沉积、场求解和插值过程中 \(x\)、\(y\) 两个方向的耦合。
参数 |
取值 |
|---|---|
模型 |
二维静电、三维速度(2D3V)PIC |
归一化计算域 |
\(L_x\times L_y=64\lambda_{De}\times64\lambda_{De}\) |
网格 |
\(64\times64\),\(\Delta x=\Delta y=\lambda_{De}\) |
电子束 |
两束等权 Maxwell 分布,漂移速度 \(\pm3v_{te}\) |
宏粒子 |
每束每单元 64 个(\(8\times8\)),总数 524,288 |
时间步长与终止时刻 |
\(\Delta t=0.05\,\omega_{pe}^{-1}\),\(\omega_{pe}t_{\max}=40\) (800 步) |
初始扰动 |
\(\delta_0=0.005\),模态 \((m_x,m_y)=(2,1)\) |
边界条件 |
粒子和场在 \(x\)、\(y\) 方向均为周期性 |
Poisson 求解容差 |
\(10^{-10}\) |
实现与计算流程
程序结构。 应用层仅包含三个 Fortran 源文件;编译、运行和后处理由独立脚本完成。
文件 |
职责 |
|---|---|
|
初始化 MPI,组织静电 PIC 时间循环,并控制诊断输出时刻。 |
|
定义网格、粒子数、归一化参数、时间步长、扰动和输出频率。 |
|
管理算例数组,并封装 AlgoPlasma 组件调用、周期边界和粒子位置更新。 |
|
选择本示例使用的 AlgoPlasma 源文件,并链接 MPI 与 HYPRE。 |
|
配置、编译和运行算例,或删除生成的编译文件、结果与图片。 |
|
读取粒子和电场输出,计算增长率、理论解和能量诊断,并生成参考图。 |
AlgoPlasma 组件调用。 应用程序按照下表组合九组库例程。
组件 |
调用例程 |
作用 |
|---|---|---|
初始化粒子位置和 Maxwell 速度分布。 |
||
将粒子电荷沉积到网格。 |
||
构造并求解周期 Poisson 方程。 |
||
重构三维势数组并计算网格电场。 |
||
将网格电场插值到粒子位置。 |
||
推进粒子速度。 |
||
输出粒子和电场二进制数据。 |
AlgoPlasma 提供各阶段的数值操作,而应用层程序保留对数据结构、执行顺序、粒子位置更新、
周期边界和输出频率的控制。完整主程序如下;算例相关的数组管理和接口细节被集中在
two_stream_case 模块中,因此主循环保持简短、明确。
1program two_stream_2d
2 use mpi
3 use omp_lib
4 use two_stream_parameters
5 use two_stream_case
6 implicit none
7 integer :: step, ierr, nproc
8
9 call mpi_init(ierr)
10 call mpi_comm_size(mpi_comm_world,nproc,ierr)
11 write(*,'(A,I0,A,I0)') 'MPI ranks: ',nproc,', OpenMP threads: ',omp_get_max_threads()
12 call initialize_case ! sub_I01_par_distribute_equilibrium
13 call update_electric_field ! sub_B01_scatter_3Dxyz, sub_D02_hypre_3Dxyz_bc_A, sub_D02_hypre_3Dxyz_bc_fortran, sub_D05_phi1d_to_phi3d, sub_D06_phi_to_E
14 call push_velocities(initial_half_push) ! sub_C01_gather_3Dxyz, sub_A01_Boris_3Dxyz
15 call write_fields(0) ! sub_F04_field_output_3d_bin
16 call write_particles(0) ! sub_F02_par_output
17
18 do step=1,nt
19 call push_velocities(full_push) ! sub_C01_gather_3Dxyz, sub_A01_Boris_3Dxyz
20 call move_particles(dt) ! Application-specific position update and periodic boundaries
21 call update_electric_field ! sub_B01_scatter_3Dxyz, sub_D02_hypre_3Dxyz_bc_A, sub_D02_hypre_3Dxyz_bc_fortran, sub_D05_phi1d_to_phi3d, sub_D06_phi_to_E
22
23 if (step==1 .or. mod(step,field_stride)==0) call write_fields(step) ! sub_F04_field_output_3d_bin
24 if (step==1 .or. mod(step,particle_stride)==0) call write_particles(step) ! sub_F02_par_output
25 end do
26
27 call finalize_case ! sub_D02_hypre_3Dxyz_bc_fortran
28 call mpi_finalize(ierr)
29end program two_stream_2d
编译、运行与输出
本示例需要 GNU Fortran、CMake、MPI、HYPRE 3.1 或更高版本,以及 NumPy、
SciPy 和 Matplotlib。一种已经测试通过的 HYPRE 安装方式是从
HYPRE GitHub 仓库 下载源码,
并将 hypre/ 目录与 algoplasma/ 目录平行放置:
parent/
├── algoplasma/
└── hypre/
然后编译并安装 HYPRE:
cd hypre/src
./configure
make install -j 8
其中 -j 8 表示使用 8 个 CPU 核心并行编译。安装完成后,进入本示例目录运行:
cd ../../algoplasma/examples/001_two_stream_2d
./run.sh
在上述平行目录结构下,run.sh 会自动使用 hypre/src/hypre 下的
HYPRE 安装路径。如果 HYPRE 安装在其他位置,可显式指定安装前缀:
HYPRE_ROOT=/path/to/hypre/src/hypre ./run.sh
如果已经位于 AlgoPlasma 仓库根目录,则通常直接执行:
cd examples/001_two_stream_2d
bash run.sh
run.sh 依次完成 CMake 配置、并行编译、单进程计算和 Python 后处理。
当前示例仅支持一个 MPI 进程。程序将数据写入以下目录:
output/Ex和output/Ey:初始步、第 1 步及其后每 5 步的电场快照;output/par01:初始步、第 1 步及其后每 50 步的粒子快照;figures:plot.py生成的两张参考图片。
清理全部编译与运行产物可执行:
./clean.sh
参考结果
相空间演化。 为直接观察粒子与指定斜模态之间的相位关联,结果采用沿波矢方向的坐标
这种表示对垂直于 \(\boldsymbol{k}\) 的空间方向进行投影,因而比常规的 \(x-v_x\) 图更直接地揭示所激发模态的速度调制和粒子混合。初始两束电子位于 \(v_{\parallel}\simeq\pm2.68v_{te}\);在 \(\omega_{pe}t=17.5\) 时形成明显的相位相关调制,在 \(\omega_{pe}t=25\) 时展宽并混合,表明不稳定性 已进入非线性饱和阶段。
\(\omega_{pe}t=0\)、17.5 和 25 时沿波矢方向的电子相空间分布。
电场增长与能量平衡。 第二张图的 (a) 显示
在 \(\omega_{pe}t=22.5\) 时的空间分布。倾斜条纹对应所激发的 \((2,1)\) 模态。图 (b) 跟踪该模态的幅值 \(2|\widehat{E}_{\parallel}(2,1)|\)。在 \(10\leq\omega_{pe}t\leq19\) 区间对其对数进行最小二乘拟合,得到 \(\gamma_{\mathrm{PIC}}=0.2603\,\omega_{pe}\) 和 \(R^2=0.9836\)。
图中的理论值通过求解对称双 Maxwell 电子束的 Vlasov–Poisson 色散关系获得:
其中 \(v_{d,\parallel}=v_dk_x/k\)。数值求根给出 \(\gamma_{\mathrm{th}}=0.2616\,\omega_{pe}\),与 PIC 结果相差约 0.48%。 图 (c) 表明电场能的增加与粒子动能的减少相互对应;整个计算中最大相对总能量误差为 0.0183%。这些结果共同验证了组合程序能够再现预期的线性增长、非线性相空间演化和 良好的全局能量守恒。
双流不稳定性示例的电场结构、模态增长和能量平衡。(a) 在 \(\omega_{pe}t=22.5\) 时的平行电场;(b) \((2,1)\) 模态幅值及 PIC 拟合与动理学理论比较;(c) 场能、粒子动能和相对总能量误差。
Overview and Physical Setup
This example shows how several AlgoPlasma components can be assembled into an application-specific electrostatic particle-in-cell (PIC) program. It considers the electron two-stream instability in two spatial and three velocity dimensions (2D3V) with periodic boundaries. Two equally weighted electron populations drift in opposite directions along \(x\) at \(\pm3v_{te}\), while a uniform, immobile positive background maintains initial charge neutrality. Here \(v_{te}=\sqrt{k_{\mathrm B}T_e/m_e}\) is the standard deviation of one velocity component in each Maxwellian beam.
I01 places the first population regularly within each grid cell and samples its velocities. The second population copies those positions and reverses all three velocity components, producing a symmetry-preserving quiet start. Both populations are then displaced longitudinally by
The present setup uses \(\delta_0=0.005\) and \((m_x,m_y)=(2,1)\), corresponding to a 0.5% first-order density perturbation. Seeding one oblique mode provides an unambiguous target for the linear-growth comparison while exercising coupling in both spatial directions during deposition, field solution, and interpolation.
Parameter |
Value |
|---|---|
Model |
Two-dimensional electrostatic, three-velocity (2D3V) PIC |
Normalized domain |
\(L_x\times L_y=64\lambda_{De}\times64\lambda_{De}\) |
Grid |
\(64\times64\), with \(\Delta x=\Delta y=\lambda_{De}\) |
Electron populations |
Two equally weighted Maxwellians drifting at \(\pm3v_{te}\) |
Macroparticles |
64 per cell per beam (\(8\times8\)), 524,288 in total |
Time step and duration |
\(\Delta t=0.05\,\omega_{pe}^{-1}\) and \(\omega_{pe}t_{\max}=40\) (800 steps) |
Initial perturbation |
\(\delta_0=0.005\), mode \((m_x,m_y)=(2,1)\) |
Boundary conditions |
Periodic for particles and fields in \(x\) and \(y\) |
Poisson-solver tolerance |
\(10^{-10}\) |
Implementation and Workflow
Program structure. The application layer contains only three Fortran source files; separate scripts handle configuration, execution, and post-processing.
File |
Responsibility |
|---|---|
|
Initializes MPI, defines the electrostatic PIC time loop, and controls diagnostic output times. |
|
Defines the grid, particle count, normalized parameters, time step, perturbation, and output cadence. |
|
Manages example arrays and wraps AlgoPlasma calls, periodic boundaries, and the particle-position update. |
|
Selects the AlgoPlasma sources used here and links MPI and HYPRE. |
|
Configure, build, and run the example, or remove generated build, output, and figure files. |
|
Reads particle and field output, evaluates growth, theory, and energy diagnostics, and generates the reference figures. |
AlgoPlasma component calls. The application combines nine groups of library routines.
Component |
Called routine |
Role |
|---|---|---|
Initialize particle positions and Maxwellian velocities. |
||
Deposit particle charge onto the grid. |
||
Assemble and solve the periodic Poisson problem. |
||
Reconstruct the three-dimensional potential array and evaluate the grid electric field. |
||
Interpolate grid fields to particle positions. |
||
Advance particle velocities. |
||
Write particle and electric-field data in binary form. |
AlgoPlasma supplies the numerical operations at each stage, while the
application retains control of data structures, execution order, particle
position updates, periodic boundaries, and output cadence. The complete
driver is shown below. Example-specific array management and interface
details remain in two_stream_case, leaving the main loop short and
explicit.
1program two_stream_2d
2 use mpi
3 use omp_lib
4 use two_stream_parameters
5 use two_stream_case
6 implicit none
7 integer :: step, ierr, nproc
8
9 call mpi_init(ierr)
10 call mpi_comm_size(mpi_comm_world,nproc,ierr)
11 write(*,'(A,I0,A,I0)') 'MPI ranks: ',nproc,', OpenMP threads: ',omp_get_max_threads()
12 call initialize_case ! sub_I01_par_distribute_equilibrium
13 call update_electric_field ! sub_B01_scatter_3Dxyz, sub_D02_hypre_3Dxyz_bc_A, sub_D02_hypre_3Dxyz_bc_fortran, sub_D05_phi1d_to_phi3d, sub_D06_phi_to_E
14 call push_velocities(initial_half_push) ! sub_C01_gather_3Dxyz, sub_A01_Boris_3Dxyz
15 call write_fields(0) ! sub_F04_field_output_3d_bin
16 call write_particles(0) ! sub_F02_par_output
17
18 do step=1,nt
19 call push_velocities(full_push) ! sub_C01_gather_3Dxyz, sub_A01_Boris_3Dxyz
20 call move_particles(dt) ! Application-specific position update and periodic boundaries
21 call update_electric_field ! sub_B01_scatter_3Dxyz, sub_D02_hypre_3Dxyz_bc_A, sub_D02_hypre_3Dxyz_bc_fortran, sub_D05_phi1d_to_phi3d, sub_D06_phi_to_E
22
23 if (step==1 .or. mod(step,field_stride)==0) call write_fields(step) ! sub_F04_field_output_3d_bin
24 if (step==1 .or. mod(step,particle_stride)==0) call write_particles(step) ! sub_F02_par_output
25 end do
26
27 call finalize_case ! sub_D02_hypre_3Dxyz_bc_fortran
28 call mpi_finalize(ierr)
29end program two_stream_2d
Build, Run, and Outputs
The example requires GNU Fortran, CMake, MPI, HYPRE 3.1 or later, NumPy,
SciPy, and Matplotlib. One tested HYPRE setup is to download HYPRE from
the HYPRE GitHub repository and
place the hypre/ directory next to the algoplasma/ directory:
parent/
├── algoplasma/
└── hypre/
Then build and install HYPRE with:
cd hypre/src
./configure
make install -j 8
Here -j 8 uses 8 CPU cores for parallel compilation. After installation,
enter this example and run:
cd ../../algoplasma/examples/001_two_stream_2d
./run.sh
With the sibling-directory layout above, run.sh automatically uses the
HYPRE installation under hypre/src/hypre. If HYPRE is installed
elsewhere, pass the installation prefix explicitly:
HYPRE_ROOT=/path/to/hypre/src/hypre ./run.sh
If you are already inside the AlgoPlasma repository, the usual command is:
cd examples/001_two_stream_2d
bash run.sh
run.sh performs CMake configuration, a parallel build, the single-rank
calculation, and Python post-processing in sequence. The present example
supports one MPI rank. Generated files are organized as follows:
output/Exandoutput/Ey: electric-field snapshots at the initial and first steps, then every five steps;output/par01: particle snapshots at the initial and first steps, then every fifty steps;figures: the two reference figures generated byplot.py.
Remove all build and run products with:
./clean.sh
Reference Results
Phase-space evolution. To expose phase correlation with the seeded oblique mode, the distribution is plotted in coordinates aligned with the wave vector:
This projection removes the spatial direction perpendicular to \(\boldsymbol{k}\) and therefore reveals the selected mode’s velocity modulation and particle mixing more directly than a conventional \(x-v_x\) plot. The two populations initially lie near \(v_{\parallel}\simeq\pm2.68v_{te}\). A phase-correlated modulation is distinct at \(\omega_{pe}t=17.5\); by \(\omega_{pe}t=25\), the populations have broadened and mixed as the instability enters nonlinear saturation.
Electron phase-space distributions in wave-aligned coordinates at \(\omega_{pe}t=0\), 17.5, and 25.
Field growth and energy balance. Panel (a) of the second figure shows
at \(\omega_{pe}t=22.5\); the oblique bands follow the seeded \((2,1)\) mode. Panel (b) tracks its amplitude \(2|\widehat{E}_{\parallel}(2,1)|\). A least-squares fit to its logarithm over \(10\leq\omega_{pe}t\leq19\) gives \(\gamma_{\mathrm{PIC}}=0.2603\,\omega_{pe}\) with \(R^2=0.9836\).
The theoretical curve is obtained by solving the Vlasov–Poisson dispersion relation for two symmetric drifting Maxwellians,
where \(v_{d,\parallel}=v_dk_x/k\). Numerical root finding gives \(\gamma_{\mathrm{th}}=0.2616\,\omega_{pe}\), differing from the PIC result by approximately 0.48%. Panel (c) shows the corresponding transfer between field and particle kinetic energies. The maximum relative total-energy error over the run is 0.0183%. Together, these diagnostics show the expected linear growth, nonlinear phase-space evolution, and good global energy conservation of the assembled workflow.
Electric-field structure, mode growth, and energy balance in the two-stream example. (a) Parallel electric field at \(\omega_{pe}t=22.5\). (b) Amplitude of the \((2,1)\) mode, compared with a PIC fit and kinetic theory. (c) Field energy, particle kinetic energy, and relative total-energy error.