leapfrog_p 输出、诊断和 restart

源码范围:

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\leapfrog_p.F
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\dynredem_p.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\inithist_p.F
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\bilan_dyn_p.F

Mars 运行参与度:条件经过。Mars 并行 GCM 使用 dyn3dpar/gcm.F -> leapfrog_p,只有开启动力 history、dynav、zonal diagnostic 或写 restart.nc 时才进入本页描述的 I/O 路径。

调度位置

leapfrog_p 的输出段位于阶段计算之后、状态机跳回 label 1/2 之前。非 purmats 分支在 itau 已由 forward 或 leapfrog 阶段推进后写出;purmats 分支只在 backward 半步写出。两个分支都先处理平均/纬向诊断,再处理 instant history 和 Grads,最后判断 restart。

输出 purmats 源码位置 purmats 源码位置 门控
zonal diagnostic 1677-1685 1910-1918 MOD(itau,iperiod)==0 .OR. itau==itaufinok_dynzon
dynav 平均输出 1687-1708 1920-1941 同一 iperiod/itaufin 门,且 ok_dyn_ave
instant history 1715-1785 1946-2010 MOD(itau,iecri)==0;非 purmats 还要求 leapf 或 backward Matsuno
restart 1804-1838 2029-2060 itau==itaufinecritstart>0 且整除

iperiod 同时影响 Matsuno restart 周期和 dynav/zonal 输出周期;iecri 只控制 instant history。排查缺步时不要把这两个频率混用。

dynav 和 zonal diagnostic

平均输出门打开后,ok_dynzon 在 IOIPSL 编译条件下调用:

bilan_dyn_p(2, dtvr*iperiod, dtvr*day_step*periodav,
            ps, masse, pk, pbaru, pbarv, teta, phi, ucov, vcov, q)

bilan_dyn_p 自己在并行子域上建 dynzon history domain,内部通过 halo request 补齐 ucov/vcov/q/flux_u/flux_v 等边界,按 dt_cum/dt_app 累积到周期后由 OMP MASTER 写出。因此 bilan_dyn_p 不是简单 root-only dump,它保留并行局部纬向切片语义。

ok_dyn_ave 的 dynav 路径不同:leapfrog_p 在 master 段内先对 vcov/ucov/teta/pk/phi/q/masse/ps/phisGather_Field(...,0),再由 mpi_rank==0writedynav(itau,...)。当前源码没有实际调用 writedynav_p;并行主循环选择 gather 到 root 后复用串行写例程。

instant history 和 Grads

instant history 的 iecri 门打开后,先把位温转换为温度相关的 tsurpk,再调用 geopot_p 重算 phi,并由 ucov/cuvcov/cv 构造 unat/vnat。随后:

这意味着 history 文件缺字段时,先查 ok_dyn_ins/CPP_IOIPSL/iecri 和阶段过滤;字段错位或缺全局带时,再查 Gather_Field 和当前 SetDistrib 状态。

restart 写出

restart 判断分两步避免 ecritstart==0 时取模除零:

lrestart = .false.
if (itau == itaufin) lrestart = .true.
else if (ecritstart > 0 .and. MOD(itau,ecritstart) == 0) lrestart = .true.

写出时调用 dynredem1_p("restart.nc", time, vcov, ucov, teta, q, masse, ps)dynredem1_p 内部先 Gather_Field 状态数组和 tracer,再只让 mpi_rank==0 打开 NetCDF、追加 tempsTime record,并重写 controledynredem0_p 创建文件骨架时同样只有 root 定义维度、控制数组、controle_descriptor、坐标和变量。

Mars 与非 Mars 的 time 实参不同:

分支 Mars time 非 Mars time
purmats, ecritstart>0 REAL(itau)/REAL(day_step)+time_0-floor(time_0) JH_cur
purmats, 最终且 ecritstart==0 REAL(itau)/REAL(day_step)-(day_end-day_ini)+time_0-floor(time_0) JH_cur
purmats, ecritstart>0 REAL(itau)/REAL(day_step) JH_cur
purmats, 最终且 ecritstart==0 REAL(itau)/REAL(day_step)-(day_end-day_ini) JH_cur

purmats Mars 分支没有加 time_0-floor(time_0),而非 purmats Mars 分支会加;这是 当前源码事实,设计意图需要维护者确认。

初始化边界

本页的写出段依赖 gcm.F 早先完成输出文件初始化:

因此 leapfrog_p 负责“何时写”和“写前如何 gather/root”,gcm.F 的 rank-0 初始化和 dynredem0_p 负责“文件结构是否已经定义”。若改回 _p 初始化例程,需要同步检查后续是否仍 gather 后复用串行写例程。

复现要点

  1. 先确认当前分支是非 purmats 还是 purmats,因为 itau 推进和 Mars restart 时间实参不同。
  2. ok_dynzonbilan_dyn_p 并行局部累积;ok_dyn_aveok_dyn_insleapfrog_p 中 gather 后 root 写。
  3. writehist_p/writedynav_p 存在,但当前主循环实际调用的是 gather 后的 writehist/writedynav
  4. dynredem1_p 自己再 gather restart 字段,root 写 NetCDF;排查并行 restart 要同时看调用前分布和 dynredem1_p 内部 gather。
  5. Mars 并行 restart 不应套用串行页的单一时间公式,必须区分 purmatsecritstart

待确认

相关页面