dyn3d/vlsplt.F
源码路径:LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d\vlsplt.F
Mars 运行参与度:条件经过。vlsplt 是串行 dyn3d/advtrac.F90 的 iadv=10 Van Leer tracer 输送主内核;infotrac_init 白名单允许 iadv=10,因此这是 Mars 标准 tracer 输送路径中应优先理解的 COMMON 串行格式。饱和水汽 iadv=14 走 vlspltqs,并行构建走 vlspltgen_p 和 vlsplt_p 主页面。
文件角色
vlsplt.F 是 1138 行 Fortran 77 串行 Van Leer split transport 文件。它包含:
vlsplt主例程:准备半步/整步质量通量,复制当前 tracer 和质量到工作数组,执行 x-y-z-y-x split,最后写回q。vlx:E-W Van Leer 通量更新,含经向周期、CFL>1 semi-Lagrangian 累加和父子 tracer 递归。vly:N-S Van Leer 通量更新,含极点几何、SSUM极冠累积和父子 tracer 递归。vlz:垂直 Van Leer 通量更新,含顶底零通量和父子 tracer 递归。minmaxq:#ifdef isminismax下的极值诊断。
本页是串行主文件页;三方向公式的展开见 vlsplt 串行 split 内核,父子 tracer 和饱和路径见 vlsplt 串行父子 tracer。
子例程清单
| 子例程 | 源码行 | 作用 |
|---|---|---|
vlsplt |
5 | 主入口;缩放质量通量、复制工作数组、调度 vlx/vly/vlz/vly/vlx。 |
vlx |
140 | E-W Van Leer 内核;周期边界、CFL>1 累加、父子 tracer 比例输送。 |
vly |
520 | N-S Van Leer 内核;极点斜率处理、SSUM 极冠收支、父子 tracer 比例输送。 |
vlz |
889 | 垂直 Van Leer 内核;顶底斜率归零、顶底零通量、父子 tracer 比例输送。 |
minmaxq |
1091 | 极值诊断;默认不参与运行,需 isminismax 编译保护。 |
调用入口
串行 advtrac.F90 在 tracer 循环中按 iadv(iq) 调度:
iadv |
串行入口 | 说明 |
|---|---|---|
10 |
call vlsplt(q,2.,massem,wg,pbarug,pbarvg,dtvr,iq) |
非饱和 Van Leer tracer;pente_max=2.。 |
14 |
call vlspltqs(q,2.,massem,wg,pbarug,pbarvg,dtvr,p,pk,teta,iq) |
饱和水汽路径,水平使用 vlxqs/vlyqs 裁剪 qsat,垂直共享 vlz。 |
advtrac 先累积水平质量通量、保存本次 advection 前的 massem,再调用 groupe 生成 pbarug/pbarvg/wg。因此 vlsplt 接收的是已经整理后的质量通量,不直接从动力 tendency 中重算 flux。
主例程数据流
vlsplt(q,pente_max,masse,w,pbaru,pbarv,pdt,iq) 的参数:
| 参数 | 维度 | 读写 | 说明 |
|---|---|---|---|
q |
ip1jmp1,llm,nqtot |
INOUT | 所有 tracer 混合比;本次只更新 iq 及其后代。 |
pente_max |
scalar | IN | Van Leer slope limiter;2. 为标准值,0 退化上游,负值走乘积斜率分支。 |
masse |
ip1jmp1,llm |
IN | 当前空气质量;复制到 zm(:,:,iq) 后在 split 内更新。 |
w |
ip1jmp1,llm |
IN | 垂直质量通量。 |
pbaru |
ip1jmp1,llm |
IN | E-W 质量通量。 |
pbarv |
ip1jm,llm |
IN | N-S 质量通量。 |
pdt |
scalar | IN | advection 时间步。 |
iq |
scalar | IN | 当前父 tracer 或普通 tracer 索引。 |
主例程先做通量缩放:
zzpbar = 0.5 * pdt
zzw = pdt
mu = pbaru * zzpbar
mv = pbarv * zzpbar
mw = w * zzw
mw(:,llm+1) = 0
水平通量使用半时间步,垂直通量使用整步。这配合后续对称 split:
vlx -> vly -> vlz -> vly -> vlx
q(:,:,iq) 和 masse 通过 SCOPY 复制到 zq(:,:,iq) 与 zm(:,:,iq)。如果 nqdesc(iq)>0,主例程也复制所有后代 tracer 的 q 到 zq,让方向内核可以按父子比例递归更新它们。
结束时,主例程把 zq(:,:,iq) 写回 q(:,:,iq),再做 E-W 周期边界复制:
q(ij+iim,l,iq) = q(ij,l,iq)
若有后代 tracer,后代也按同样方式写回和周期复制。
Van Leer 限制和三方向内核
vlx/vly/vlz 都使用相同的核心结构:
- 计算相邻差分。
- 当相邻差分同号时取中心斜率,异号时斜率置零。
- 用
pente_max * min(abs(left_diff), abs(right_diff))限制斜率。 - 基于上游质量通量计算 tracer 质量通量。
- 用守恒形式更新质量和混合比。
当 pente_max > -1.e-5 时使用标准 Van Leer 限制;当 pente_max < -1.e-5 时使用乘积/调和平均风格斜率。Mars 常规 advtrac 调用传入 2.。
vlx: E-W
vlx 在经向方向上使用连续索引,周期边界通过 iim 偏移复制。正通量从当前格点取上游值,负通量从 ij+1 取上游值。
当通量超过上游格点质量时,zdum < 0 标记 CFL>1。此时常规通量置零,随后对该界面逐格点累积:
- 完全跨越的格点贡献
q * masse。 - 最后未完全跨越的格点使用剩余质量和 Van Leer 斜率修正。
- 经向索引用
mod(...)环绕。
这段 semi-Lagrangian 累加只在 E-W 方向存在,是 vlx 相对 vly/vlz 的主要特殊性。
vly: N-S
vly 需要处理极点几何。首次调用时缓存:
sinlon/coslon和带经度权重的sinlondlon/coslondlon。- 北/南极邻近纬圈面积和
airej2/airejjm。
源码先计算极点相邻纬圈的面积加权平均 qpns/qpsn,再构造极点斜率并投影到 sin/cos 分量。但随后无条件 GOTO 8888,跳过一段旧的 fn/fs 限制器,最终把极点行 dyq 置零。因此实际运行中,极点 Van Leer 斜率被禁用。
非极点格点按标准 N-S 通量散度更新。极点行单独用 SSUM 汇总所有经度的 tracer 通量和质量通量,计算新的极点混合比,并把极点各经向格设为同一值。
vlz: vertical
vlz 在垂直方向计算 dzqw 和 dzq,顶层和底层斜率强制为零。通量界面也强制:
wq(:,1) = 0
wq(:,llm+1) = 0
随后每层按 masse + w(l+1) - w(l) 更新质量,按 q*masse + wq(l+1) - wq(l) 更新 tracer 质量。
父子 tracer 递归
vlx/vly/vlz 都是 RECURSIVE,用于处理 infotrac 中的父子 tracer。关键状态来自 infotrac:
| 变量 | 作用 |
|---|---|
nqdesc(iq) |
iq 的全部后代数,用于批量计算比例和恢复。 |
nqfils(iq) |
直接子代数,用于递归调用。 |
iqfils(ifils,iq) |
第 ifils 个子/后代 tracer 索引。 |
qperemin |
父 tracer 太小时比例置零。 |
masseqmin |
tracer 质量下限,防止除零。 |
每个方向内核在更新父 tracer 前先计算:
masseq(child) = max(masse(parent) * q(parent), masseqmin)
Ratio(child) = q(child) / q(parent) if q(parent) > qperemin
Ratio(child) = 0 otherwise
然后对直接子代递归调用同方向内核,输送 Ratio 场;父 tracer 完成质量和混合比更新后,再用:
q(child) = q(parent) * Ratio(child)
恢复所有后代。这个设计假定输送期间子/父比例守恒;物理过程若改变比例,只会在下一次 advection 前反映到新的初始比例。
与 vlspltqs 和并行版的边界
| 范围 | 页面 | 边界 |
|---|---|---|
vlsplt.F |
本页 | 串行非饱和 Van Leer,iadv=10。 |
vlspltqs.F |
vlspltqs | 饱和水汽水平裁剪 qsat,垂直共享 vlz。 |
vlsplt_p.F |
vlsplt_p | 并行 split 内核主页面,含 halo、OMP、band 范围和 _p 差异。 |
vlspltgen_p.F |
vlspltgen_p | 并行 tracer split 调度,按 iadv=10/14 调用 _p 内核。 |
串并行差异细节页说明:数值公式大体等价,但并行版增加 band、halo、OpenMP 同步和 mw(:,:,iq) 存储差异;实际 bitwise 是否一致仍需回归测试。
复现检查点
advtrac传入pente_max=2.,不要把pente_max当作运行时可随意忽略的常量。- 水平质量通量在
vlsplt内乘0.5*pdt,垂直通量乘pdt。 masse实参不直接写回;split 更新的是工作数组zm(:,:,iq),用于本次 tracer 更新。- 父子 tracer 递归使用
nqdesc和nqfils的不同语义,不能只按直接子代恢复。 - E-W CFL>1 触发 semi-Lagrangian 累加,性能和数值结果都可能偏离普通 Van Leer 路径。
- N-S 极点实际斜率为零,虽然源码中存在 sin/cos 投影和被跳过的限制器残段。
- 垂直顶底通量强制为零;如果单元测试传入非零边界通量,
vlz内部仍会清零wq。 minmaxq默认不参与运行,不能把注释掉的诊断调用当作活动逻辑。
相关页面
- vlsplt 串行父子 tracer 和饱和路径
- vlsplt 串行 split 内核
- vlsplt 串并行差异
- vlspltqs
- vlspltgen_p
- advtrac 串并行调度
- infotrac 父子 tracer 与 isotope
- advn
待确认
- Mars 当前典型配置中是否实际存在
nqdesc>0的父子 tracer 家族。 pente_max<0乘积斜率分支是否仍有生产配置使用。- E-W CFL>1 累加段在高分辨率 Mars 运行中是否被触发。