ppm3d.F

源码路径:LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d_common\ppm3d.F

Mars 运行参与度:条件经过 + 历史兼容。ppm3d 是串行 advtrac.F90iadv=11/16/17/18 的 PPM 三维 tracer 输送内核;但 infotrac_init 的最终白名单只允许 iadv=10/14/0,Mars 标准配置通常无法到达 PPM 分支。并行 advtrac_p.F90vlspltgen_pGOTO 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,仅防止负值。

filladvtrac 传入 .true.,会启用 qckxyz 负值填充。dumppm3d 的形式参数,源码中声明但未发现实际使用;LMDZ 仍传入 .true. 以保持旧接口。

主例程状态和限制

ppm3d 在首次调用或时间步改变时维护若干静态状态:

状态 作用
NSTEP 每次调用自增;首次调用时执行网格/参数初始化,也传给 qckxyz 诊断输出。
NDT0 保存上次时间步;当 NDT 变化时重算 DTDX/DTDY/JS0/JN0/IML
Jmax=361, kmax=150 静态数组上限;若 JNPNLAY 超过则 stop。
cross=.true. 主水平段启用 xadv/yadv cross-term 修正;但 qckxyz 调用时传入 .false.

参数检查包括:NLAY >= 6JNP >= NLAYj1=2IMR 必须为偶数、Jmax/Kmax 足够大。当前 LMDZ 调用使用 j1=2AE=6400000PT=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 独立复现完整结果。

水平段

水平段对每个垂直层处理:

  1. A2C 把 C-grid wind 转成 Courant 数系数 CRX/CRY
  2. 内联计算 E-W 与 N-S 质量通量,累积 DPI
  3. cross=.true.,调用 xadv/yadv 计算 cross-term,并叠加到 tracer。
  4. xtp 做 E-W 输送,低纬度可走 PPM,高 CFL 高纬度可切到 FFSL 或 Van Leer。
  5. ytp 做 N-S 输送,并在极区用 RCAP 把跨极通量均匀分配给极点经度。

xtp 的 E-W 方向支持 Eulerian 和 Semi-Lagrangian 路径;ytp 的 N-S 方向没有 FFSL,因此源码注释说明时间步主要受 meridional transport 限制。

垂直段

垂直段先把水平散度转成 W 和新层厚 delp2,再调用 FZPPMFZPPM 的输入 DQ 是水平段后的 tracer 密度,不是原始混合比。

FZPPM 对每个纬向切片执行:

  1. 计算非均匀层厚下的单调参考斜率。
  2. 构造顶、底和内部界面值 AL/AR
  3. 根据 KORD-3 调用 lmtppm 施加全单调、半单调或正定约束。
  4. WZ 符号选择上/下游抛物线积分得到界面通量。
  5. 用通量散度更新 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_pGOTO 1234 跳过旧 scheme-specific 代码
Mars 1D/testphys 通过转发接口使用 tracer 状态,不调用 ppm3d

这意味着 ppm3d 对 Mars wiki 的价值主要是解释保留源码和历史/本地补丁风险,而不是标准 Mars 主线的常规执行路径。

复现检查点

  1. 先确认 traceur.def 能否产生 iadv=11/16/17/18,再确认是否绕过了 infotrac_init 白名单。
  2. 串行复现必须同时复现 interpre 的地面气压计算、经向风取反、垂直层序翻转和 interpost 的周期闭合。
  3. adaptdt 只按水平 CFL 分割子步;垂直 CFL 只在 advtrac 中打印 warning。
  4. Jmax/kmax 是源码内静态上限,高分辨率或高层数配置需要先检查。
  5. 负值填充会改变 tracer 质量;一旦日志出现地面质量源,应把它作为数值不守恒信号处理。
  6. 并行构建里不要从 advtrac_p 下方保留的 PPM 代码推断可达性;那段被 GOTO 1234 跳过。

相关页面