leapfrog_p 时间步调度

源码范围:

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\leapfrog_p.F

Mars 运行参与度:条件经过。Mars 并行 GCM 经过 dyn3dpar/gcm.F -> leapfrog_p;串行 Mars GCM 经过 dyn3d/leapfrog.F,MARS phymars/nogcm.F90 只作边界背景,不属于 COMMON 源码。

调度职责

本页只说明并行 leapfrog_p 的时间步状态机:forward/leapf/purmats/apphys/apdiss/lafinTrue_itauitau 推进、history/restart 写出和最终停止。入口数组、SAVE 工作区、SetDistrib、halo/swap 和 root gather 的状态约定见 leapfrog_p 状态约定dyn3dpar/leapfrog_p

leapfrog_p 仍沿用串行 Matsuno/leapfrog 思路,但阶段转换发生在 OpenMP parallel 区内部。并行差异主要是:输出/restart 写出前需要 gather,physics 前后需要 band/halo 切换;这些并行通信并不改变 itau/forward/leapf 的时间步语义。

终止步数

237-250 行计算 itaufin

条件 结果
nday >= 0 itaufin = nday * day_step
nday < 0 itaufin = -nday,按动力步数运行
less1day 覆盖为 int(fractday * day_step)
ndynstep > 0 最终覆盖为 ndynstep

随后 itaufinp1 = itaufin + 1itau 从 0 开始,physics 初值为 .TRUE.,但 iflag_phys==0iflag_phys==2 会关闭 physics 调度。

停止不是正常跑出循环:非 purmats 分支在 itau == itaufinp1finalize_parallel 后调用 abort_gcm(modname,'Simulation finished',0)purmats 分支在 forward 半步后检查同一条件并停止。

两个 label

主循环由 label 1 和 label 2 组成:

label 源码位置 作用
1 约 405 行前后 Matsuno forward 入口,设置 forward=.TRUE., leapf=.FALSE., dt=dtvr
2 417 行 backward 或 leapfrog 阶段入口,重新计算日期、门控标志、动力/物理/耗散/输出,然后在步末决定下一个阶段。

label 2 每次进入都会把 apphys/statcl/conser/apdiss 先清零,再按 purmats 和当前 itau/forward 计算门控。随后 685 行把 True_itau=True_itau+1,用于日志输出“实际进入计算段的迭代次数”。因此:

日期刷新

432-446 行只有在 leapf 为真时刷新 jD_cur/jH_cur

jD_cur = jD_ref + day_ini - day_ref + (itau+1)/day_step
Mars:     jH_cur = jH_ref + hour_ini   + mod(itau+1,day_step)/day_step
non-Mars: jH_cur = jH_ref + start_time + mod(itau+1,day_step)/day_step

jH_cur > 1.0,则日期进一日并把小时减 1。Forward/backward Matsuno 段不会在这里刷新日期;Mars restart 写出还有单独的 time_0 小数修正,见 leapfrog_p 状态约定dynredem-restart

门控标志

454-471 行重新计算 apphys/conser/apdiss

分支 conser apdiss apphys
purmats MOD(itau,iconser)==0 .AND. forward MOD(itau,dissip_period)==0 .AND. .NOT.forward MOD(itau,iphysiq)==0 .AND. .NOT.forward .AND. physics
purmats MOD(itau,iconser)==0 MOD(itau+1,dissip_period)==0 .AND. .NOT.forward MOD(itau+1,iphysiq)==0 .AND. physics

随后还有两个覆盖:

并行版还有一个串行页容易漏掉的细节:487-488 行再次把 statcl=.FALSE.conser=.FALSE.,注释说明并行版不向 stdout 输出 control variables。因此 conser 的周期逻辑存在,但在当前并行实现中被强制关闭,不应把它解释成会实际触发 sortvarc 控制量输出。

lafin 与 physics

851-855 行在进入 physics 前设置 lafin

分支 最后一次 physics 标志
purmats itau == itaufin .AND. .NOT.forward
purmats itau + 1 == itaufin

只有 apphys 为真时才调用 physics。并行 physics 调度在 calfis_p(lafin,jD_cur,jH_cur,...) 后通过 tendency halo merge 和 addfi_p(dtphys,leapf,forward,...) 回写状态。这里的 lafin 是传给 physics 的“最终调用”语义,不是主循环退出条件;真正退出仍由 itaufinp1 或最终阶段写出后的状态转换决定。

非 purmats 状态机

purmats 分支从 1621 行开始,使用 Matsuno + leapfrog:

  1. 步末若 forward .OR. leapf,执行 itau = itau + 1。Backward Matsuno 段不增加 itau
  2. itau == itaufinp1,结束并 abort_gcm(...,0)
  3. MOD(itau,iperiod)==0 .OR. itau==itaufin,写 dynav/zonal 平均输出;itau==itaufiniav=1
  4. MOD(itau,iecri)==0,只在 leapf 或 backward Matsuno 阶段写 instant history;forward Matsuno 阶段不写。
  5. restart 门控先设 lrestart=.false.,最终步必写;否则 ecritstart>0MOD(itau,ecritstart)==0 时写。
  6. 阶段转换:
    • MOD(itau,iperiod)==0:回 label 1,下一轮从 forward 开始。
    • MOD(itau-1,iperiod)==0 且当前是 forward:转 backward,forward=.FALSE., leapf=.FALSE., 回 label 2。
    • MOD(itau-1,iperiod)==0 且当前不是 forward:进入第一个 leapfrog,leapf=.TRUE., dt=2*dtvr, 回 label 2。
    • 其他情况:常规 leapfrog,leapf=.TRUE., dt=2*dtvr, 回 label 2。

这意味着 iperiod 同时控制 Matsuno restart 周期和 dynav/zonal 平均输出门。iecri 控制 instant history,但还要经过“只在 LF 或 backward Matsuno 输出”的额外阶段过滤。

purmats 状态机

purmats 分支从 1873 行后开始,只在 forward/backward Matsuno 之间往返:

  1. 若当前 forward,先 itau=itau+1,再 forward=.FALSE.
  2. forward 半步结束后若 itau==itaufinp1,停止。
  3. 否则回 label 2 执行 backward 半步。
  4. backward 半步负责 dynav/history/restart 写出。
  5. 写出和 restart 检查后设置 forward=.TRUE.,回 label 1。

purmats 下没有常规 leapf=.TRUE. 的 leapfrog 阶段;apphysapdiss 都要求 .NOT.forward,因此只落在 backward 半步。

输出和 restart 门控

并行版两个分支的输出门控基本一致,但写出前需要 gather 到 root:

输出 purmats purmats 并行写出约束
bilan_dyn_p / dynav MOD(itau,iperiod)==0 .OR. itau==itaufin 同左,只在 backward 半步 ok_dynzonok_dyn_ave 后触发;dynav 前 gather 全场。
instant history MOD(itau,iecri)==0leapf 或 backward Matsuno MOD(itau,iecri)==0,发生在 backward 半步 ok_dyn_ins 时 gather 后 rank 0 调 writehist
restart itau==itaufinecritstart>0 且整除 同左,只在 backward 半步 master 调 dynredem1_p;Mars 与非 Mars 时间实参不同。

Mars restart 时间在两个分支不同:

复现要点

  1. 先判断 purmats,因为 itauapphysapdiss 和阶段转换规则都随它改变。
  2. purmats 下 backward 阶段不递增 itau;forward 和 leapfrog 阶段才递增。
  3. apphyspurmatsitau+1purmatsitau 且必须是 backward 半步。
  4. lafin 只传给 physics,不能当作主循环退出标志。
  5. conser 在并行版最终被强制清零;排查控制量 stdout 输出时不要照串行路径推断。
  6. True_itau 适合对应日志迭代号,itau 适合对应模型时间、输出和 restart 门控。
  7. 输出/restart 发生在阶段转换前;若输出缺字段,先查 Gather_Field 和 root-only 写出,再查时间门控。

待确认

相关页面