leapfrog_p 状态约定
源码范围:
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\gcm.F
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\leapfrog_p.F
Mars 运行参与度:条件经过。Mars 并行 GCM 构建经过 dyn3dpar/gcm.F -> leapfrog_p;串行 Mars GCM 和 MARS phymars/nogcm.F90 不经过本并行主循环。当前 COMMON 源码已删除 COMMON nogcm,本页只讨论 dyn3dpar 并行入口。
入口调用点
dyn3dpar/gcm.F 在完成 conf_gcm、MPI/OMP 初始化、band/halo 初始化、tracer 分配、dynetat0 或 iniacademic、iniconst/inigeom/inidissip、iniphysiq、history/restart 初始化后进入 OpenMP parallel 区:
gcm.F 556: c$OMP PARALLEL DEFAULT(SHARED)
gcm.F 567: CALL leapfrog_p(ucov,vcov,teta,ps,masse,phis,q,time_0)
gcm.F 569: c$OMP END PARALLEL
源码 557-564 行保留了 temps_mod 和 logic_mod 的 OpenMP COPYIN 注释,说明这些状态曾经或应当作为 threadprivate 复制对象处理;当前实际 parallel directive 是 DEFAULT(SHARED),没有启用这些 COPYIN 行。
入口实参
leapfrog_p 的入口形状在源码 7-8 行:
SUBROUTINE leapfrog_p(ucov,vcov,teta,ps,masse,phis,q,time_0)| 实参 | 维度 | 读写 | 含义 |
|---|---|---|---|
ucov |
ip1jmp1,llm |
inout | U 网格纬向 covariant wind。 |
vcov |
ip1jm,llm |
inout | V 网格经向 covariant wind。 |
teta |
ip1jmp1,llm |
inout | 位温。 |
ps |
ip1jmp1 |
inout | 地表压力,Pa。 |
masse |
ip1jmp1,llm |
inout | 层空气质量,由 p/pressure 同步更新。 |
phis |
ip1jmp1 |
inout | 地表位势。 |
q |
ip1jmp1,llm,nqtot |
inout | advected tracer;第三维来自 infotrac:nqtot。 |
time_0 |
scalar | in | 源码注释写 “not used”,但 Mars restart 分支实际用 time_0-floor(time_0) 修正 restart 时间。 |
这些数组仍使用全局 COMMON 维度形状,而不是显式局部数组形状。并行局部范围由 parallel_lmdz 的 ij_begin/ij_end、jj_* 分布和 SetDistrib 当前状态解释。
主要 USE 依赖
| 依赖 | 行号 | 用途 |
|---|---|---|
parallel_lmdz |
15 | 当前 rank/thread 的局部范围、SetDistrib、Gather_Field 等并行基础。 |
times, Bands |
16, 18 | adaptive bands 的计时和 jj_Nb_* 分布。 |
mod_hallo |
17 | halo/swap 请求对象、Register_*, SendRequest, WaitRequest。 |
Write_Field, Write_Field_p |
19-20 | 调试/输出写场 helper。 |
infotrac:nqtot |
23 | 决定 q/dq/dqfi/dqfi_tmp 的 tracer 维度。 |
guide_p_mod:guide_main |
24 | generic guide/nudging 条件分支。 |
control_mod |
26-31 | nday/day_step/iperiod/iphysiq/dissip_period/ok_dyn*/ecritstart 等调度和输出控制。 |
comvert_mod |
35 | ap/bp/pressure_exner/presnivs,用于 pressure/Exner。 |
comconst_mod |
36-37 | daysec/dtvr/dtphys/dtdiss/cpp/iflag_top_bound/pi 等。 |
logic_mod |
38-39 | forward/leapf/apphys/apdiss/purmats/conser/ok_guide 等时间步门控。 |
temps_mod |
40-41 | itaufin/day_ini/day_ref/start_time/dt/hour_ini/day_end 等时间状态。 |
cpdet_mod, sponge_mod_p, comuforc_h |
32-34 | cp(T)、sponge/top-bound 和 guide forcing 支撑。 |
入口工作数组
leapfrog_p 大量工作数组是 SAVE 状态,跨调用保留;这与 OpenMP parallel 区共同存在时要特别小心。
| 数组 | 维度 | 作用 |
|---|---|---|
p, pks, pk, pkf |
ip1jmp1,llmp1 或 ip1jmp1,llm |
层界 pressure、地表和层中 Exner。 |
phi, w, temp, tsurpk |
ip1jmp1,llm |
位势、垂直速度、温度和 cp(T) 相关缓存。 |
pbaru, pbarv, flxw |
ip1jmp1/ip1jm,llm |
caldyn 给 tracer 和输出使用的质量通量。 |
ucovm1/vcovm1/tetam1/psm1/massem1 |
与状态数组同形 | 上一时间层状态,供 leapfrog/integrd 使用。 |
du/dv/dteta/dp/dq |
与状态数组同形;dq allocatable |
动力 tendency。 |
dufi/dvfi/dtetafi/dpfi/dqfi |
与状态数组同形;dqfi allocatable |
physics tendency。 |
dudis/dvdis/dtetadis |
wind/theta 形状 | dissipation tendency。 |
dvfi_tmp/dufi_tmp/dtetafi_tmp/dpfi_tmp/dqfi_tmp |
iip1 局部经向切片;dqfi_tmp allocatable |
physics band 切换前后暂存本 rank 非极点切片。 |
ecin/ecin0/dtetaecdt/vcont/ucont/vnat/unat |
与风/温度形状 | 耗散守恒修正和诊断。 |
dq, dqfi, dqfi_tmp 在 262-272 行只由 OpenMP master 在线程第一次调用时分配,然后 barrier 同步。它们的第三维固定为当前 nqtot,因此 infotrac_init 必须在 gcm.F 调用 leapfrog_p 前完成。
初始化约定
进入主循环前,leapfrog_p 先建立运行终止步和初始 thermodynamic state:
- 237-250 行由
nday/day_step/less1day/fractday/ndynstep计算itaufin和itaufinp1。 - 252-254 行设
itau=0,并由iflag_phys推出局部physics布尔值;iflag_phys==0或2时 physics 关闭。 - 262-272 行按
nqtot分配 tracer tendency 数组。 - 278-296 行 master 清零 dissipation、physics、top-bound、tracer 和 mass-flux tendency。
- 298-303 行由
pression(ap,bp,ps,p)和pressure_exner选择exner_hyb或exner_milieu初始化p/pks/pk/pkf。
这个初始化发生在并行区内部,但多处由 c$OMP MASTER 包裹。复现并行问题时要同时检查 master-only 初始化、barrier 和后续各线程看到的共享状态。
并行边界状态
虽然入口实参是全局形状,运行时只应操作当前分布对应的局部范围:
gcm.F在进入leapfrog_p前已SetDistrib(jj_Nb_Caldyn)。leapfrog_p内在首次调整和阶段切换时多次SetDistrib,例如 596 行回到jj_nb_caldyn,1001/1042/1075 行在 physics 前后切换jj_nb_Physic与jj_nb_Physic_bis。- 输出和 restart 前会
Gather_Field,如 1691-1701、1764-1773 行,把字段收集到 root/rank 0 写出。 - physics tendency 在
calfis_p后通过Register_Hallo/SendRequest/WaitRequest合并边界,再用_tmp数组叠加回本 rank 切片。
因此 leapfrog_p 的状态约定不是“全局数组直接全局写”,而是“全局形状数组 + 当前 band/halo 约定 + root gather 写出”。
Mars 边界
Mars 并行 GCM 经过本页路径时,关注点是 planet_type=="mars" 下的日期和 restart 时间:
leapfrog_p的 physics 日期仍按 Mars/generic 分支构造jD_cur/jH_cur。- Mars restart 分支没有统一使用
JH_cur。中途 restart 在 1822-1830 行使用REAL(itau)/REAL(day_step)+time_0-floor(time_0)或再减day_end-day_ini;最终分支在 2047-2053 行使用REAL(itau)/REAL(day_step)或再减day_end-day_ini。JH_cur是非 Mars fallback 分支。 - 这也是为什么
time_0不能简单按源码入口注释理解为 “not used”。
复现检查表
- 确认
dyn3dpar/gcm.F已完成infotrac_init和q分配,nqtot与traceur.def一致。 - 确认进入
leapfrog_p前当前分布是jj_Nb_Caldyn。 - 检查
dq/dqfi/dqfi_tmp是否首次调用时按当前nqtot分配;长进程复用时尤其要小心SAVE firstcall。 - 对 pressure/masse 问题,先查
ps -> pression -> p -> massdair_p的刷新顺序。 - 对 physics tendency 问题,检查
SetDistrib(jj_nb_Physic)、calfis_p、Register_Hallo和_tmp回填。 - 对输出或 restart 问题,确认
Gather_Field已在 root 写出前执行,且 Mars restart 时间分支按time_0修正。
待确认
- 源码注释称
time_0 ! not used,但 Mars restart 分支实际使用time_0-floor(time_0);注释与代码不一致。 gcm.F中logic_mod/temps_mod的 OpenMPCOPYIN行被注释,当前 shared/threadprivate 语义需结合编译选项和模块声明确认。SAVE工作数组和 allocatable tracer tendency 在同一进程内多次调用leapfrog_p时是否需要重分配,源码未显式处理nqtot变化。