advn 调度顺序、mode 分支和 advtrac 调用关系

输入范围

dyn3d_common\advn.F: L4-139(advn 主例程)
dyn3d_common\advn.F: L141-257(advnqx)
dyn3d_common\advn.F: L258-352(advnqy)
dyn3d_common\advn.F: L354-468(advnqz)
dyn3d_common\advn.F: L470-733(advnx)
dyn3d_common\advn.F: L735-863(advny)
dyn3d_common\advn.F: L865-977(advnz)
dyn3d\advtrac.F90: L250-269(iadv=12/13 调用点)
dyn3dpar\advtrac_p.F90(advn 代码存在但不可达)

Mars 运行参与度:条件经过advn 是 F. Hourdin 的"pseudo amont"(伪上游)advection 方案,由串行 advtraciadv=12/13 时调用。当前 infotrac_init 白名单只允许 iadv=10/14/0,因此 Mars 默认配置下 advn 路径不可达。并行 advtrac_p 中 advn 代码存在但被 GOTO 1234 跳过。

例程定位

advn 是 978 行的 Fortran 77 输送方案,包含 7 个子例程。它使用 x-y-z-y-x 五步 directional splitting,每步先做界面重构(advnq*)再做通量更新(advn*)。scheme 有两个 mode:mode=1(分段线性)和 mode=2(抛物线修正),对应 iadv=12iadv=13

advn 签名

SUBROUTINE advn(q,masse,w,pbaru,pbarv,pdt,mode)
参数 类型 方向 说明
q real(ip1jmp1,llm) INOUT tracer 混合比
masse real(ip1jmp1,llm) INOUT 格点空气质量(被通量散度更新)
w real(ip1jmp1,llm) IN 垂直质量通量
pbaru real(ip1jmp1,llm) IN E-W 质量通量
pbarv real(ip1jm,llm) IN N-S 质量通量
pdt real IN 时间步长(秒)
mode integer IN 1=分段线性,2=抛物线修正

预处理

advn 主例程在 split 之前做三项准备:

  1. 质量通量缩放mu = pbaru * 0.5*pdtmv = pbarv * 0.5*pdtmw = w * pdt。水平方向用 0.5 系数(leapfrog mid-time-level),垂直方向用 1.0(forward)。
  2. 极区平均:对每层 l,计算南北极的 mass-weighted 平均 tracer 值 qpn/qps,然后均匀赋给极点所有经度格。
  3. 工作数组复制zq = q, zm = masse,后续 split 在 zq/zm 上操作。

x-y-z-y-x Split 顺序

advn 使用对称五步 split:

1. advnqx → advnx    (E-W 重构 + E-W 通量更新)
2. advnqy → advny    (N-S 重构 + N-S 通量更新)
3. advnqz → advnz    (垂直重构 + 垂直通量更新)
4. advnqy → advny    (N-S 重构 + N-S 通量更新)
5. advnqx → advnx    (E-W 重构 + E-W 通量更新)

这是经典的 Strang splitting:首尾两步各做半时间步(隐含在 0.5 系数中),中间三步各做全时间步。每步的通量更新同时修改 zqzm(质量和 tracer 都被更新),因此后续步骤基于已更新的场工作。

后处理:q = zq 拷回,做经向周期包裹 q(ij+iim,l) = q(ij,l)

重构子例程

advnqx:E-W 界面重构

SUBROUTINE advnqx(q,qg,qd)

输出 qg(gauche=left)和 qd(droite=right)是界面重构值的两侧。

advnqy:N-S 界面重构

SUBROUTINE advnqy(q,qs,qn)

结构同 advnqx,但在 N-S 方向。qs(south)和 qn(north)是界面值。

advnqz:垂直界面重构

SUBROUTINE advnqz(q,qh,qb)

通量更新子例程

advnx:E-W 通量和更新

SUBROUTINE advnx(q,qg,qd,masse,u_m,mode)

核心逻辑:基于重构界面值和质量通量计算 tracer 通量 u_mq,然后更新 qmasse

Sigma 参数zsigd = (q-qg)/(qd-qg)zsigg = 1-zsigd。若 |qd-qg| < prec(prec=1e-15),退化为 1 阶 zsigd=zsigg=0.5, qd=qg=q

通量计算(按风向选择上游格点参数):

极区 Semi-Lagrangian(CFL>1):当 |u_m| > masse 时,标记 ladvplus。对这些格点:

  1. 累加完全穿越格点的全部质量 q*masse
  2. 最后部分穿越格点使用 mode 对应的分段线性/抛物线插值。
  3. 诊断输出穿越格点数量(若 prt_level > 9)。

通量散度更新

new_m  = masse(ij,l) + u_m(ij-1,l) - u_m(ij,l)
q(ij,l)= (q(ij,l)*masse(ij,l) + u_mq(ij-1,l) - u_mq(ij,l)) / new_m
masse(ij,l) = new_m

经向周期包裹:u_mq(ij,l) = u_mq(ij-iim,l)q(ij-iim,l) = q(ij,l)

advny:N-S 通量和更新

SUBROUTINE advny(q,qs,qn,masse,v_m)

结构同 advnx,但使用 zsign/zsigs(north/south 方向)。使用 mode=2 的抛物线通量公式(无 mode 分支)。

极区处理

convpn  = Σ v_mq(j=1)        ! 进入北极的总 tracer 通量
convmpn = Σ v_m(j=1)          ! 进入北极的总质量通量
new_m   = massen + convmpn
q(pole) = (q(pole)*massen + convpn) / new_m
masse(ij) = new_m * aire(ij) / apoln    ! 按面积分配

南极类似,使用 ip1jm-iim 行。

advnz:垂直通量和更新

SUBROUTINE advnz(q,qh,qb,masse,w_m)

结构同 advnx,使用 zsigb/zsigh(bottom/top 方向,对应 x 的 d/g)。使用 mode=2 的抛物线通量公式。

边界w_mq(ij,llm+1)=0, w_mq(ij,1)=0(无通量穿过大气顶/底)。

更新

new_m  = masse(ij,l) + w_m(ij,l+1) - w_m(ij,l)
q(ij,l)= (q(ij,l)*masse(ij,l) + w_mq(ij,l+1) - w_mq(ij,l)) / new_m
masse(ij,l) = new_m

advtrac 调用关系

串行路径

advtrac.F90 在 iadv=12iadv=13 时调用 advn:

iadv mode 调用 说明
12 1 call advn(q, massem, wg, pbarug, pbarvg, dtbon, 1) 分段线性
13 2 call advn(q, massem, wg, pbarug, pbarvg, dtbon, 2) 抛物线修正

两个路径都使用 adaptdt 做自适应子步长,循环 do indice=1,n 调用 advn。

并行路径

advtrac_p.F90 中 advn 的代码存在(PPM 分支之后),但被 GOTO 1234 完全跳过。并行构建中所有 tracer 输送由 vlspltgen_p 处理。

infotrac_init 白名单

当前 infotrac_init 只允许 iadv=10/14/0,因此 iadv=12/13 路径在初始化阶段就会被 abort。advn 在当前 COMMON 中属于历史遗留但未删除的状态,和 PPM 路径类似。

与 vlsplt 和 ppm3d 的关系

特征 advn vlsplt ppm3d
Split 顺序 x-y-z-y-x (5步) x-y-z-y-x (5步) x-y-z (3步)
重构方式 4阶中心+单调 Van Leer PPM 抛物线
极区 CFL>1 Semi-Lagrangian 累加 无特殊处理 FFSL 切换
质量更新 内联(同时更新 q 和 masse) 外部 外部(delp1/delp2)
mode 参数 1/2(线性/抛物线) IORD/JORD/KORD
当前可达性 不可达(iadv=12/13 被阻止) 可达(iadv=10/14) 不可达(iadv=11/16/17/18 被阻止)

advn 和 vlsplt 使用相同的 x-y-z-y-x Strang splitting,但 advn 的极区处理更复杂(CFL>1 时做 Semi-Lagrangian 累加),且同时更新质量和 tracer(内联守恒),而 vlsplt 使用外部质量场。

复现要点

  1. advn 的 mode 参数在三个重构子例程(advnqx/advnqy/advnqz)中有各自的 save mode 声明,但这些局部 mode 固定为 1,不受主例程传入的 mode 影响。只有 advnx 使用传入的 mode 做分支。这意味着重构总是 4 阶的,mode 只影响通量计算。
  2. prec 精度阈值因平台而异:CRAY 用 1e-24,其他平台用 1e-15(advnx/advny)或 1e-13(advnz)。低于此阈值时退化为 1 阶。
  3. advnx 的 Semi-Lagrangian 累加(L602-705)只在 n0 > 1(有 CFL>1 格点)时执行,且会打印诊断信息。复现时需要 prt_level > 9 才能看到穿越格点数。
  4. advny 的极区质量分配使用 aire(ij)/apoln(格点面积与极冠总面积之比),保证极点各经度格的质量按面积比例分配。
  5. 水平通量缩放 0.5 和垂直通量缩放 1.0 反映了 leapfrog 时间离散:水平风是 mid-time-level 值,垂直通量是 forward 值。

相关页面

待确认