实例 1:使用SymPIC模拟Landau阻尼
1 简介
Landau阻尼是一种等离子体中常见的波-粒子相互作用现象,即静电波在等离子体或相似的环境中的阻尼。对于其更具体的描述,可以参考 Wiki百科 或任意一本等离子体教材。
2 参数设置
Landau阻尼本质上是一种静电现象,但采用电磁PIC也可以模拟,不过要注意的是初始电荷守恒的问题。考虑一个一维的等离子体体,其背景为不可移动的离子,初始时电场和密度有一个静电扰动,随后该静电波含时演化,由于波与粒子相互作用而被阻尼掉。具体参数参考文章 Physics of Plasmas 22, 112504 (2015)。 可按如下设置 SymPIC 的配置文件。
(
begin (
defmacro many-define lst
(
cons '
begin (
map (lambda (x)
(cons 'define x))
lst)))
;定义一个用于生成大量define语句的宏
(
many-define (REAL_DX
2.40000000000000006e-04)
;设置格子宽度为2.4e-4m,该参数用于真实单位换算
(REAL_MU0 (
* 4 m_pi
9.99999999999999955e-08))
;该参数设置磁导率为4e-7pi用于真实单位换算,其中m_pi为内建的pi常数值
(REAL_NE
1.20000000000000000e+16)
;设置真实参考数密度为1.2e16/m^3用于单位换算
(REAL_ME
9.10000000000000006e-31)
(REAL_E
1.59999999999999991e-19)
;设置电子质量和净电荷分别为9.1e-31kg和1.6e-19C用于单位换算
(REAL_C
2.99792458000000000e+08)
;设置光速用于单位换算
(DELTAT
5.00000000000000000e-01)
;设置\Delta t=0.5\Delta x/c
(E (
* REAL_E (
sqrt (
/ REAL_MU0 REAL_ME REAL_DX))))
;归一化的电子净电荷
(CONST_E_DENSITY (
* REAL_NE REAL_DX REAL_DX REAL_DX))
;归一化的参考数密度
(NPG0
512)
; 每格采样点数
(NPM0 (
/ CONST_E_DENSITY NPG0))
; 每采样点代表的真实粒子数
(XMAX
8)
(YMAX
1)
(ZMAX
1)
; 设置每个最小计算单元的三维大小,以格数为单位
(NUM_N_HILBERT
5)
(NUM_N_HILBERT_DIMENSION
1)
(HILBERT_DIR
0)
; 设置Hilbert填充曲线阶数为5,维数为1,扩展方向为0,即x方向,总的模拟区域为256x1x1
(NUM_SPEC
1)
; 设置粒子种数为1
(NUM_TIMESTEP
15001)
(NUM_DUMP_TIMESTEP
100)
; 设置总时间步数为15000,每100步输出一次
(gen_simulate_B
(lambda (x)
(runc "x/(E*REAL_C/REAL_DX*REAL_ME/REAL_E)"))
)
(gen_simulate_E
(lambda (x)
(runc "x/(E*REAL_C*REAL_C/REAL_DX*REAL_ME/REAL_E)"))
)
; 此二函数用于生成归一化的电磁场,其中runc是一个用于将中缀表达式转为s-expression的前缀表达式的宏
(USE_CHECKPOINT
1)
(NUM_CHECKPOINT_TIMESTEP
5000)
; 使用checkpoint,每5000步输出一次checkpoint
(GET_INIT_FILTER_KROOK
(lambda x
0)
)
(GET_INIT_FILTER_E
(lambda x
0)
)
(GET_INIT_FILTER_B
(lambda x
0)
)
(GET_INIT_TEMPERATURE_DIST
(lambda x
1)
)
(NUM_PROCESS
2)
; 设置总MPI进程数为2
(NUM_MAX_RUNTIME
1)
(NUM_RUNTIME
1)
; 设置总runtime数为1
(GET_DEV_TYPE
(lambda (x r)
1)
)
; 使用1号runtime OpenMP
(GET_DEV_ID
(lambda (x r)
0)
)
; 使用0号设备id
(E_0
-1)
(M_0
1)
; E_0与M_0为电子的相对电荷与质量
(GET_MASS
(lambda (i)
(case i (0 (* M_0 NPM0)) (else 1)))
)
; 设置第0种粒子质量为M_0*NPM0
(GET_CHARGE
(lambda (i)
(case i (0 (* E_0 E NPM0)) (else 0)))
)
; 设置第0种粒子电荷为E*M_0*NPM0
(USE_INIT_EB0
1)
; 使用初条件场
(USE_FILTER
0)
; 不使用电磁场过滤
(USE_NP_BOUNDARY
0)
; 不使用非周期边界
(USE_NON_UNI_DENSITY
1)
; 不使用非均匀粒子
(USE_NON_UNI_TEMPERATURE
0)
; 不使用非均匀温度
(USE_INIT_EXT_EB
0)
; 不使用外场
(USE_INIT_V0
0)
; 不使用初始漂移Maxwell分布
(CAL_FUN_ONE_PARA
(
lambda (s x)
(
define s1 (
string->symbol s))
(
if (symbol-binded? s1)
((
eval (
string->symbol s)) x)
(begin
(write-string (multi-concat "Warning: symbol " s1 " is unbounded\n") current-error-port)
(car 0))
)
)
)
(GET_GRID_CACHE_LEN
(lambda (i)
(case i (0 640) (else 0)))
)
; 设置每格第i种粒子预分配空间可存的粒子数
(GET_CU_CACHE_LEN
(lambda (i)
12800)
)
; 设置每Compute Unit第i种粒子用于排序等分配的空间可存的粒子数
(GET_INIT_LOAD
(lambda (i)
NPG0)
)
; 设置初始化时第i种粒子每格采样点参考值
(USE_NON_UNI_CACHE_DIST
0)
(GET_NON_UNI_CACHE_DIST
(lambda x
0)
)
(N_MODE
1)
(E_AMP (gen_simulate_E (
* 1.08000000000000000e+05)))
(GET_INIT_DENSITY_DIST
(lambda (i z y x)
(- 1 (* E_AMP (/ (* 2 m_pi N_MODE) (* X_ALL E_0 E NPM0 NPG0)) (sin (/ (* N_MODE x m_pi 2) X_ALL)))))
)
; 初始电场振幅为108kV/m
(X_ALL (
* XMAX (arithmetic-shift
1 NUM_N_HILBERT)))
; 计算模拟区域x方向为256个格点
(GET_INIT_E0
(lambda (z y x l)
(case l (0 (* E_AMP (cos (/ (* N_MODE x m_pi 2) X_ALL)))) (else 0)))
)
(GET_INIT_B0
(lambda (z y x l)
0)
)
; 此二函数用于设置初始电磁场
(GET_INIT_E
(lambda (z y x l)
0)
)
(GET_INIT_B
(lambda (z y x l)
0)
)
; 此二函数用于设置不变的外电磁场
(GET_INIT_VT
(lambda (i)
1.00000000000000006e-01)
)
; 设置电子热速度为0.07c
(GET_VAR
(
lambda (s)
(
define s1 (
string->symbol s))
(
if (symbol-binded? s1)
(
eval (
string->symbol s))
(begin
(write-string (multi-concat "Warning: symbol " s1 " is unbounded\n") current-error-port)
0)
)
)
)
; 此函数用于动态加载变量
; 以下参数用于其它无关选项
(GET_INIT_V0_x
(lambda x
0)
)
(GET_INIT_V0_y
(lambda x
0)
)
(GET_INIT_V0_z
(lambda x
0)
)
(USE_KGM
0)
(USE_DM
0)
(USE_TORI
0)
(USE_PROFILE
0)
(USE_LHCD_INPUT
0)
(USE_NON_UNI_CACHE_DIST
0)
(GET_NUM_LOCAL_THREAD_FROM_GLOBAL_TID
(lambda x
x)
)
(GET_NPM
(lambda (i)
1)
))
)
3 运行
在sympic运行时,需要设置环境变量STDLIB指向stdlib.scm的位置。在SymPIC的根目录下,执行以下命令以设置该环境变量:
$ export STDLIB=$PWD/stdlib.scm
$ export SYMPIC_DIR=$PWD
将第二节2中的参数保存成文件landau_damping.ss,假设系统中共有4个CPU线程,则使用以下命令运行:
$ export OMP_NUM_THREADS=2
$ mpirun -n 2 $SYMPIC_DIR/sympic landau_damping.ss
运行完毕后,会生成tmpEN, tmpEB和tmpJ这三个文件。可以在python中查看Landau阻尼效果。使用
$ ipython --pylab
启动matplotlib,然后在终端中运行
In [1]: execfile('path-to-SymPIC-dir/cgapsio/pygapsio.py')
In [2]: tEB=GAPS_IO_Load('tmpEB')
In [3]: tEB=reshape(tEB,[len(tEB)/2,2,256,3])
In [4]: ftEB=fftn(tEB[:,0,:,0],axes=[1])
In [5]: plot(log(abs(real(ftEB[:,1]))));
如一切正常,类似下图的静电波模式为1的振幅含时演化将被画出。
![](ld1.png)