ppm3d.F
源码路径:LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d_common\ppm3d.F。
Mars 运行参与度:条件经过 + 历史兼容。ppm3d 是串行 advtrac.F90 中 iadv=11/16/17/18 的 PPM 三维 tracer 输送内核;但 infotrac_init 的最终白名单只允许 iadv=10/14/0,Mars 标准配置通常无法到达 PPM 分支。并行 advtrac_p.F90 在 vlspltgen_p 后 GOTO 1234,跳过 PPM/Prather/advn 等旧分支。因此本页主要用于理解保留源码、历史配置或本地补丁下的串行 PPM 路径。
文件定位
ppm3d.F 是 NASA/GSFC Transport Core Version 4.5 的 fixed-form Fortran 77 代码,核心算法来自 Lin and Rood 的多维 flux-form semi-Lagrangian transport。它不是 LMDZ 原生网格上的直接例程:串行 advtrac 先通过 interpre 把 LMDZ 层序、风和质量通量变成 PPM core 需要的格式,调用 ppm3d 后再由 interpost 写回。
公开入口和内部例程
| 例程 | 源码位置 | 职责 |
|---|---|---|
ppm3d |
line 65 | 主入口。一次调用更新 Q(IMR,JNP,NLAY,NC) 一个时间步,内部执行水平 E-W、水平 N-S 和垂直 split。 |
FZPPM |
line 762 | 垂直 PPM 输送,使用主例程由水平散度反推的垂直质量通量。 |
xtp, ytp |
line 932, 1125 | E-W 和 N-S 水平输送。 |
fxppm, fyppm |
line 1049, 1273 | 水平 PPM 抛物线重构和界面通量积分。 |
xmist, ymist |
line 1109, 1191 | 4 阶参考斜率和单调性预限制。 |
xadv, yadv |
line 1442, 1352 | cross-term 修正。 |
lmtppm |
line 1534 | PPM 抛物线单调/半单调/正定约束。 |
qckxyz |
line 1686 | FZPPM 后的负值检查和填充。 |
filns, filew, filcr |
line 1895, 1981, 1793 | N-S、E-W 和对角方向负值填充。 |
zflip |
line 2058 | 通用垂直翻转工具;LMDZ 的 interpre/interpost 未直接调用。 |
LMDZ 调用边界
串行 advtrac.F90 的 PPM 分支:
adaptdt(iadv, dtbon, n, ...)
-> vertical CFL warning check
-> interpre(q -> qppm, winds/pressure/flux)
-> repeat n substeps:
ppm3d(1, qppm, psppm, psppm, unatppm, vnatppm, fluxwppm,
dtbon, IORD, JORD, KORD, 1, iim, jjp1, 2, llm,
apppm, bpppm, 0.01, 6400000, fill, dum, 220.)
-> interpost(qppm -> q)
LMDZ 逐 tracer 调用 ppm3d,所以 NC=1。四种 iadv 映射为:
iadv |
IORD/JORD/KORD |
含义 |
|---|---|---|
| 11 | 2/2/2 |
水平 Van Leer + 垂直 PPM 兼容分支;但 ppm3d 内部会把 KORD 至少抬到 3。 |
| 16 | 3/3/3 |
Monotonic PPM。 |
| 17 | 4/4/4 |
Semi-monotonic PPM,允许过冲。 |
| 18 | 5/5/5 |
Positive-definite PPM,仅防止负值。 |
fill 由 advtrac 传入 .true.,会启用 qckxyz 负值填充。dum 是 ppm3d 的形式参数,源码中声明但未发现实际使用;LMDZ 仍传入 .true. 以保持旧接口。
主例程状态和限制
ppm3d 在首次调用或时间步改变时维护若干静态状态:
| 状态 | 作用 |
|---|---|
NSTEP |
每次调用自增;首次调用时执行网格/参数初始化,也传给 qckxyz 诊断输出。 |
NDT0 |
保存上次时间步;当 NDT 变化时重算 DTDX/DTDY/JS0/JN0/IML。 |
Jmax=361, kmax=150 |
静态数组上限;若 JNP 或 NLAY 超过则 stop。 |
cross=.true. |
主水平段启用 xadv/yadv cross-term 修正;但 qckxyz 调用时传入 .false.。 |
参数检查包括:NLAY >= 6、JNP >= NLAY、j1=2 时 IMR 必须为偶数、Jmax/Kmax 足够大。当前 LMDZ 调用使用 j1=2、AE=6400000、PT=0.01。
数据流
Q mixing ratio at t
-> delp1 = DAP + DBK * PS1
-> DQ = Q * delp1
-> horizontal split on each k:
A2C -> CRX/CRY -> mass fluxes -> cross terms -> xtp -> ytp
-> vertical mass flux W from horizontal DPI
-> FZPPM vertical split
-> qckxyz fill if requested
-> Q = DQ / delp2
DPI 是水平质量散度的中间量。垂直质量通量 W 不由外部输入独立决定,而由水平散度和混合 sigma-P 坐标的 DBK 递推得到:
column_div = sum_k DPI(k)
PS2 = PS1 + column_div
W(k) = W(k-1) + DPI(k) - DBK(k) * column_div
W(NLAY) = 0
因此 PPM 垂直输送和水平输送是耦合的,不能只拿 FZPPM 独立复现完整结果。
水平段
水平段对每个垂直层处理:
A2C把 C-grid wind 转成 Courant 数系数CRX/CRY。- 内联计算 E-W 与 N-S 质量通量,累积
DPI。 - 若
cross=.true.,调用xadv/yadv计算 cross-term,并叠加到 tracer。 xtp做 E-W 输送,低纬度可走 PPM,高 CFL 高纬度可切到 FFSL 或 Van Leer。ytp做 N-S 输送,并在极区用RCAP把跨极通量均匀分配给极点经度。
xtp 的 E-W 方向支持 Eulerian 和 Semi-Lagrangian 路径;ytp 的 N-S 方向没有 FFSL,因此源码注释说明时间步主要受 meridional transport 限制。
垂直段
垂直段先把水平散度转成 W 和新层厚 delp2,再调用 FZPPM。FZPPM 的输入 DQ 是水平段后的 tracer 密度,不是原始混合比。
FZPPM 对每个纬向切片执行:
- 计算非均匀层厚下的单调参考斜率。
- 构造顶、底和内部界面值
AL/AR。 - 根据
KORD-3调用lmtppm施加全单调、半单调或正定约束。 - 按
WZ符号选择上/下游抛物线积分得到界面通量。 - 用通量散度更新
DQ。
主例程里 KRD=max(3,KORD),所以 LMDZ iadv=11 传入的 KORD=2 实际按 3 处理。
负值填充
qckxyz 在垂直输送后运行,依次尝试:
filns -> filew -> filcr -> vertical fill
LMDZ 调用 qckxyz(...,.false.,IC,NSTEP),所以顶层和内部层的 filcr 被跳过;底层的 filcr 在源码中仍无条件调用。若底层负值无法从上层补偿,会打印 Mass source from the ground=,这代表 tracer 质量守恒已被填充算法破坏。
Mars 可达性
| 路径 | 当前行为 | 是否到达 ppm3d |
|---|---|---|
串行 advtrac + iadv=11/16/17/18 |
源码存在完整调用链 | 理论上是 |
标准 infotrac_init |
当前版本只放行 10/14/0 |
通常否,初始化会 abort |
并行 advtrac_p |
vlspltgen_p 后 GOTO 1234 跳过旧 scheme-specific 代码 |
否 |
| Mars 1D/testphys | 通过转发接口使用 tracer 状态,不调用 ppm3d |
否 |
这意味着 ppm3d 对 Mars wiki 的价值主要是解释保留源码和历史/本地补丁风险,而不是标准 Mars 主线的常规执行路径。
复现检查点
- 先确认
traceur.def能否产生iadv=11/16/17/18,再确认是否绕过了infotrac_init白名单。 - 串行复现必须同时复现
interpre的地面气压计算、经向风取反、垂直层序翻转和interpost的周期闭合。 adaptdt只按水平 CFL 分割子步;垂直 CFL 只在advtrac中打印 warning。Jmax/kmax是源码内静态上限,高分辨率或高层数配置需要先检查。- 负值填充会改变 tracer 质量;一旦日志出现地面质量源,应把它作为数值不守恒信号处理。
- 并行构建里不要从
advtrac_p下方保留的 PPM 代码推断可达性;那段被GOTO 1234跳过。