dyn3d_common/advn.F
源码路径:LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d_common\advn.F
Mars 运行参与度:条件经过 + 历史兼容。advn 是 F. Hourdin 的 pseudo amont tracer advection 内核,串行 dyn3d/advtrac.F90 在 iadv=12 和 iadv=13 时调用;但 infotrac_init 最终只放行 iadv=10/14/0,Mars 标准配置通常在初始化阶段阻断 12/13。并行 dyn3dpar/advtrac_p.F90 中保留的 advn 分支位于 GOTO 1234 之后,不可达。
文件角色
advn.F 是一个 977 行 Fortran 77 文件,包含主例程 advn 和六个方向子例程。它与 vlsplt 同样采用 x-y-z-y-x 的 directional split,但不是外部调用短小 advx/advy/advz 内核;它在文件内完成:
- 界面值重构:
advnqx/advnqy/advnqz。 - 质量加权 tracer 通量计算:
advnx/advny/advnz。 - 同步更新工作质量场
zm/masse和 tracer 混合比zq/q。 - 极区或边界特殊处理:E-W CFL>1 的 semi-Lagrangian 累加、N-S 极点面积加权、垂直顶底无通量。
子例程清单
| 子例程 | 源码行 | 作用 |
|---|---|---|
advn |
4 | 主调度:预处理通量、极点均一化、复制工作数组,执行 x-y-z-y-x split,再写回 q。 |
advnqx |
141 | E-W 方向界面重构,含 4 阶修正、单调约束、极值退化和经向周期包裹。 |
advnqy |
258 | N-S 方向界面重构,极点行强制退化为原格点值。 |
advnqz |
354 | 垂直方向界面重构,顶层和底层边界退化为 1 阶。 |
advnx |
470 | E-W 通量计算和质量/tracer 更新;唯一使用主例程 mode 参数。 |
advny |
735 | N-S 通量计算和更新;极点行用 SSUM 和 aire/apol* 重新分配质量。 |
advnz |
865 | 垂直通量计算和更新;w_mq(:,1) 与 w_mq(:,llm+1) 置零。 |
调用入口和 mode
串行 advtrac.F90 对每个 tracer 的 iadv(iq) 分支如下:
iadv |
advn mode |
上游处理 | 调用 |
|---|---|---|---|
12 |
1 |
adaptdt(iadv, dtbon, n, pbarug, massem) 后循环 n 次 |
call advn(q(1,1,iq), massem, wg, pbarug, pbarvg, dtbon, 1) |
13 |
2 |
同上 | call advn(q(1,1,iq), massem, wg, pbarug, pbarvg, dtbon, 2) |
mode=1 和 mode=2 的区别只在 advnx 的 E-W 通量公式中直接生效。三个重构子例程内部各自有 save mode 和 data mode/1/,不读取主例程实参;advny 和 advnz 也没有 mode 分支,始终使用抛物线式通量公式。
并行 advtrac_p.F90 先调用 vlspltgen_p(q,iadv,2.,...),随后 GOTO 1234,因此后续 iadv=12/13 分支虽然有 stop 'advtrac : schema non parallelise' 和 call advn(...) 文本,但当前源码控制流不会到达。
主例程数据流
advn(q,masse,w,pbaru,pbarv,pdt,mode) 的实参含义:
| 参数 | 维度 | 读写 | 说明 |
|---|---|---|---|
q |
ip1jmp1,llm |
INOUT | tracer 混合比;主例程开始复制到 zq,结束写回。 |
masse |
ip1jmp1,llm |
IN | 输入气柱质量;复制到工作数组 zm,原实参本身不写回。 |
w |
ip1jmp1,llm |
IN | 垂直质量通量;转换成 mw(:,1:llm),并把 mw(:,llm+1)=0。 |
pbaru |
ip1jmp1,llm |
IN | E-W 质量通量,乘 0.5*pdt 后进入 mu。 |
pbarv |
ip1jm,llm |
IN | N-S 质量通量,乘 0.5*pdt 后进入 mv。 |
pdt |
scalar | IN | 当前子步长。 |
mode |
scalar | IN | 只影响 advnx 的通量公式:1 为分段线性,2 为抛物线修正。 |
主例程先设置:
zzpbar = 0.5 * pdt
zzw = pdt
mu = pbaru * zzpbar
mv = pbarv * zzpbar
mw = w * zzw
mw(:,llm+1) = 0
随后把南北极点同一纬圈内的 q*masse 做质量平均,使极点行在 split 前保持经向一致。工作数组 zq 和 zm 分别复制 q 与 masse,后续各方向子例程在 zm 上更新质量,在 zq 上更新混合比。
核心 split 顺序是:
advnqx -> advnx
advnqy -> advny
advnqz -> advnz
advnqy -> advny
advnqx -> advnx
这是一条对称的 x-y-z-y-x 顺序。E-W 和 N-S 通量用半步水平质量通量 0.5*pdt,垂直通量用整步 pdt。结束时 zq 写回 q,并重新复制每行周期边界 q(ij+iim,l)=q(ij,l)。
界面重构
三个 advnq* 子例程共用同一思路:
- 从相邻格点差分构造界面候选值。
- 使用
1/12系数做 4 阶中心修正。 - 将界面值夹在相邻格点的
min/max之间。 - 若相邻斜率变号,认为格点处有极值,界面左右值退化为格点中心值。
- 在方向边界处用周期或一阶退化处理。
方向差异:
| 方向 | 接口值 | 边界处理 |
|---|---|---|
| E-W | qg/qd |
经向周期复制;GOTO 8888 跳过一段旧的极值传播补丁。 |
| N-S | qs/qn |
南北极点行强制 qs=qn=q。 |
| 垂直 | qh/qb |
顶底边界 zqw(:,2)=q(:,1)、zqw(:,llm)=q(:,llm)。 |
通量更新
advnx/advny/advnz 都先把中心值相对上下游界面值的位置转成 sigma 参数,再用 |flux_mass|/cell_mass 决定通量积分长度。
E-W: advnx
advnx 使用 qg/qd 和 u_m。当 mode=1 时,通量公式是分段线性;当 mode 不是 1 时,源码进入抛物线修正公式。若 |u_m| > masse,ladvplus 标记该界面为 CFL>1,常规通量先置零,再在 n0 > 1 时进入 semi-Lagrangian 累加:沿经向逐格点扣减 masse,完整跨越的格点直接累计 q*masse,最后一个未完整跨越的格点按同一 sigma 公式补足。
注意:源码条件是 if(n0.gt.1),不是 n0.gt.0。因此只有一个 CFL>1 点时不会进入特殊累加,细节页将其列为复现风险。
N-S: advny
advny 使用 qs/qn 和 v_m,没有 mode 分支。普通格点按 masse + v_m(ij) - v_m(ij-iip1) 更新。北极和南极行单独处理:
- 用
SSUM汇总穿过极冠边界的 tracer 通量和质量通量。 - 先更新极点代表格的
q。 - 再按
aire(ij)/apoln或aire(ij)/apols把新质量分配给极点行各经向格。
这让极点行保持同一个 tracer 值,但质量按格点面积分布。
垂直: advnz
advnz 使用 qh/qb 和 w_m。垂直方向的 prec 在非 CRAY 平台为 1.e-13,比水平的 1.e-15 更宽松;zsigb 还会被裁剪到 [0,1]。顶底通量强制:
w_mq(:,1) = 0
w_mq(:,llm+1) = 0
然后每层按 masse + w_m(:,l+1) - w_m(:,l) 更新质量和 tracer。
静态状态和诊断
| 状态 | 位置 | 说明 |
|---|---|---|
testcpu |
主例程 save |
默认 .false.;CRAY 条件下可打印 split 时间。 |
temps1/temps2/temps3 |
主例程 save |
CRAY timing 累计量,当前普通构建不活跃。 |
qmin/qmax |
主例程 data |
只服务已注释的 minmaxq 调试调用。 |
prec |
advnx/advny/advnz |
平台相关阈值;水平非 CRAY 为 1.e-15,垂直非 CRAY 为 1.e-13。 |
局部 mode |
advnqx/advnqy/advnqz |
固定 1,不受主例程 mode 实参影响。 |
Mars 可达性
| 路径 | 源码事实 | 当前 Mars 标准可达性 |
|---|---|---|
串行 advtrac + iadv=12 |
调用 advn(...,mode=1) |
通常否,infotrac_init 白名单阻断。 |
串行 advtrac + iadv=13 |
调用 advn(...,mode=2) |
通常否,infotrac_init 白名单阻断。 |
并行 advtrac_p |
vlspltgen_p 后 GOTO 1234,旧分支不可达 |
否。 |
旧 Mars/generic iniadvtrac |
仅支持旧 iadv=1..4,不映射到 12/13 |
否。 |
因此本页主要用于理解保留的历史输送格式、读懂旧配置或本地补丁下的串行路径。不要从 advn.F 存在推断 Mars 默认会执行该格式。
复现检查点
- 先确认 tracer 初始化是否允许
iadv=12/13;标准infotrac_init会拒绝它们。 - 若只复现
advn.F单元测试,需要传入与 LMDZ 一致的ip1jmp1/ip1jm/iip1/iim/llm维度和comgeom极点面积。 - 水平质量通量进入
advn后会乘0.5*pdt,垂直通量乘pdt。 masse实参不会被主例程最终写回;内部工作质量zm只用于本次 split。mode=2只改变 E-Wadvnx,N-S 和垂直方向仍按抛物线公式运行。- 检查 CFL>1 时要特别注意
n0.gt.1条件和prt_level > 9诊断。 - 极点行在进入 split 前会按
q*masse质量平均,N-S 更新后又按面积重新分配质量。
相关页面
- advn 调度顺序
- advn 界面重构
- advn 通量更新
- advtrac 串并行调度
- infotrac advection scheme
- infotrac
- ppm3d
- prather
- pentes_ini
待确认
advny/advnz没有 mode 分支是否为有意设计,需要数值实验或维护者说明确认。advnz使用1.e-13阈值而水平使用1.e-15的物理/数值理由,源码未说明。n0.gt.1是否刻意跳过单个 CFL>1 点,源码注释不足。