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.F90iadv=12iadv=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 内核;它在文件内完成:

子例程清单

子例程 源码行 作用
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 通量计算和更新;极点行用 SSUMaire/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=1mode=2 的区别只在 advnx 的 E-W 通量公式中直接生效。三个重构子例程内部各自有 save modedata mode/1/,不读取主例程实参;advnyadvnz 也没有 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 前保持经向一致。工作数组 zqzm 分别复制 qmasse,后续各方向子例程在 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. 从相邻格点差分构造界面候选值。
  2. 使用 1/12 系数做 4 阶中心修正。
  3. 将界面值夹在相邻格点的 min/max 之间。
  4. 若相邻斜率变号,认为格点处有极值,界面左右值退化为格点中心值。
  5. 在方向边界处用周期或一阶退化处理。

方向差异:

方向 接口值 边界处理
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/qdu_m。当 mode=1 时,通量公式是分段线性;当 mode 不是 1 时,源码进入抛物线修正公式。若 |u_m| > masseladvplus 标记该界面为 CFL>1,常规通量先置零,再在 n0 > 1 时进入 semi-Lagrangian 累加:沿经向逐格点扣减 masse,完整跨越的格点直接累计 q*masse,最后一个未完整跨越的格点按同一 sigma 公式补足。

注意:源码条件是 if(n0.gt.1),不是 n0.gt.0。因此只有一个 CFL>1 点时不会进入特殊累加,细节页将其列为复现风险。

N-S: advny

advny 使用 qs/qnv_m,没有 mode 分支。普通格点按 masse + v_m(ij) - v_m(ij-iip1) 更新。北极和南极行单独处理:

这让极点行保持同一个 tracer 值,但质量按格点面积分布。

垂直: advnz

advnz 使用 qh/qbw_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_pGOTO 1234,旧分支不可达 否。
旧 Mars/generic iniadvtrac 仅支持旧 iadv=1..4,不映射到 12/13 否。

因此本页主要用于理解保留的历史输送格式、读懂旧配置或本地补丁下的串行路径。不要从 advn.F 存在推断 Mars 默认会执行该格式。

复现检查点

  1. 先确认 tracer 初始化是否允许 iadv=12/13;标准 infotrac_init 会拒绝它们。
  2. 若只复现 advn.F 单元测试,需要传入与 LMDZ 一致的 ip1jmp1/ip1jm/iip1/iim/llm 维度和 comgeom 极点面积。
  3. 水平质量通量进入 advn 后会乘 0.5*pdt,垂直通量乘 pdt
  4. masse 实参不会被主例程最终写回;内部工作质量 zm 只用于本次 split。
  5. mode=2 只改变 E-W advnx,N-S 和垂直方向仍按抛物线公式运行。
  6. 检查 CFL>1 时要特别注意 n0.gt.1 条件和 prt_level > 9 诊断。
  7. 极点行在进入 split 前会按 q*masse 质量平均,N-S 更新后又按面积重新分配质量。

相关页面

待确认