caladvtrac 到 tracer advection 循环
输入范围
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d\caladvtrac.F
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d\advtrac.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\advtrac_p.F90
Mars 运行参与度:条件经过。Mars 3D 动力步在 forward .OR. leapf 时会进入 tracer 输送;串行链路经过 caladvtrac,并行链路直接从 leapfrog_p 调 advtrac_p。实际是否输送单个 tracer 由 infotrac_init 生成的 iadv(:) 和 iapp_tracvl 累计步门控决定。
入口位置
串行 leapfrog.F 在 caldyn 之后、addfi/integrd 之前调用 caladvtrac:
leapfrog
-> caldyn
-> if forward OR leapf:
caladvtrac(q,pbaru,pbarv,p,masse,dq,teta,flxw,pk)
-> addfi
-> integrd
并行 leapfrog_p.F 在相同时间推进位置调用 advtrac_p,没有 caladvtrac_p 包装层:
leapfrog_p
-> caldyn_p
-> if forward OR leapf:
advtrac_p(pbaru,pbarv,p,masse,q,iapptrac,teta,flxw,pk)
-> integrd_p
因此串行 caladvtrac 的 dq 计算和 Earth 水汽后处理不能直接套用到并行路径;并行版在 advtrac_p 内部处理 qminimum_p、halo 和守恒重标定。
数据约定
| 变量 | 维度 | 来源 | 使用 |
|---|---|---|---|
q |
(ip1jmp1,llm,nqtot) |
prognostic tracer mixing ratio/state | advtrac/advtrac_p 原地更新。 |
pbaru, pbarv |
U/V staggered mass flux | caldyn/caldyn_p |
在 advtrac* 中累计到 pbaruc/pbarvc,第 iapp_tracvl 步用于输送。 |
p |
(ip1jmp1,llmp1) |
pression 生成的层界压力 |
Earth dq/qminimum、饱和路径 vlspltqs。 |
masse |
(ip1jmp1,llm) |
caldyn/caldyn_p 质量 |
初次累计时复制到 massem,也是守恒重标定的质量权重。 |
dq |
(ip1jmp1,llm,nqtot) |
串行 caladvtrac 输出 |
仅 Earth 水汽物理 tendency 路径使用;Mars 路径不计算。 |
flxw |
(ip1jmp1,llm) |
advtrac* 输出 |
诊断/离线 mass flux;等于累计垂直通量 wg/iapp_tracvl。 |
teta, pk |
(ip1jmp1,llm) |
动力状态 | 传给饱和水汽 split 路径。 |
nqtot 来自 infotrac,是动力数组的总 tracer 维度;若 moments 格式扩展存在,它可能大于真实 tracer 数。当前标准初始化会把可运行 iadv 限制到 0/10/14,因此 Mars 标准路径通常不会进入 PPM、Prather 或 advn 保留分支。
串行流程
1. 进入 caladvtrac
caladvtrac 先根据 force_conserv_tracer 可选保存每个 tracer 的全局总量:
if force_conserv_tracer:
for iq = 1..nqtot:
totaltracer_old(iq) = planetary_tracer_amount_from_mass(masse,q(:,:,iq))
这个保存发生在调用 advtrac 之前。Mars 若在 run.def 中开启 force_conserv_tracer,会走这条路径;默认值由 conf_gcm 设为 .false.。
2. Earth 专用 dq 快照
只有 planet_type=="earth" 时,caladvtrac 把 q(:,:,1:nqtot) 复制到 dq,后续用于计算物理侧水汽/liquid tendency。Mars 的 planet_type=="mars" 不进入此分支,dq 不在这里被构造成输送 tendency。
3. 调用 advtrac
advtrac 内部有持久状态:
| 状态 | 属性 | 作用 |
|---|---|---|
iadvtr |
SAVE, 初值 0 |
已累计的动力步数;返回给 caladvtrac 的 iapptrac。 |
pbaruc, pbarvc |
SAVE |
累计水平质量通量。 |
massem |
SAVE |
本轮 tracer advection 开始时的空气质量。 |
每次调用都会把当前步的 pbaru/pbarv 加到 pbaruc/pbarvc。当 iadvtr==0 时复制 masse 到 massem,表示这轮 tracer 输送使用的初始质量。随后 iadvtr=iadvtr+1,并把 iapptrac=iadvtr 传回调用者。
4. iapp_tracvl 门控
只有当 iadvtr == iapp_tracvl 时才真正输送 tracer。iapp_tracvl 在 conf_gcm.F90 中默认等于 iperiod,再由 getin("iapp_tracvl") 覆盖。
未达到门控步时:
advtrac:
只累计 pbaruc/pbarvc 和 iadvtr
caladvtrac:
if Earth: dq = 0
if Mars: 不做 dq 后处理
达到门控步时:
groupe(massem,pbaruc,pbarvc) -> pbarug,pbarvg,wg
flxw = wg / iapp_tracvl
检查 DP/P 是否超过 0.5
计算并按 day_step 输出 CFL[xyz]max
massbar(massem) -> massebx/masseby
按 iadv(iq) 循环输送父 tracer
清零 iadvtr,下一轮重新累计
flxw 是平均到单个动力步的垂直质量通量诊断;下游不要把它再除以 iapp_tracvl。
nqperes/iadv 循环
串行 advtrac 只循环 iq=1,nqperes,也就是由 infotrac_init 判定为直接由空气输送的父 tracer。子 tracer 的处理由 Van Leer family 逻辑通过父子比例递归完成,而不是在顶层 advtrac 对全部 nqtot 逐个直接调用内核。
iadv(iq) |
当前分支 | 当前标准可达性 |
|---|---|---|
0 |
cycle,不输送 |
可达。 |
10 |
vlsplt(q,2.,massem,wg,pbarug,pbarvg,dtvr,iq) |
Mars 标准主路径。 |
14 |
vlspltqs(q,2.,massem,wg,pbarug,pbarvg,dtvr,p,pk,teta,iq) |
仅 iq==1 可通过白名单。 |
12, 13 |
adaptdt -> advn(...,mode=1/2) |
源码保留;infotrac_init 标准白名单阻断。 |
20 |
pentes_ini |
源码保留;白名单阻断。 |
30 |
adaptdt -> prather |
源码保留;白名单阻断。 |
11, 16, 17, 18 |
adaptdt -> interpre -> ppm3d -> interpost |
源码保留;白名单阻断。 |
infotrac_init 的关键约束是:
iadv只能是0、10或14,其他值会abort_gcm。iadv==14只允许第一个 tracer。- 子 tracer 必须使用
iadv==10。 - 子 tracer 的父 tracer 只能使用
10或14。
这解释了为什么 advtrac.F90 内仍有 PPM/Prather/advn 分支,但当前 Mars 标准运行不会自然进入这些分支。
并行流程差异
advtrac_p 把串行 caladvtrac 的部分职责内联进并行调度:
- 可选保存
totaltracer_old(:),调用planetary_tracer_amount_from_mass_p。 - 按
ij_begin/ij_end、pole_nord/pole_sud计算 U/V 局部范围,累计pbaruc/pbarvc。 iadvtr==0时复制本地masse到massem。iadvtr==iapp_tracvl时调用groupe_p,随后注册pbarug/pbarvg/massem/wg/teta_tmp/p_tmp/pk_tmp/q的 halo。- 切换到
jj_nb_vanleer分布,调用vlspltgen_p(q,iadv,...)。 - 源码中保留的旧分支在
GOTO 1234后不可达。 - Earth 条件下调用
qminimum_p(q,2,finmasse);Mars 不进入。 - 若开启
force_conserv_tracer,按并行总量比值重标定本地q(ij_begin:ij_end,:,:)。 - 对
q和flxw注册jj_nb_caldynhalo,并切回 caldyn 分布。 iadvtr=0,下一轮重新累计。
并行 leapfrog_p 中还有一个 adjust 计时逻辑:当 iapptrac==iapp_tracvl 且处于 forward/leapf、物理步数超过 2、AdjustCount>30 时触发 timer average。这使用的是 advtrac_p 返回的 iapptrac,不是额外的输送开关。
Mars 边界
Mars 3D 标准路径的主要事实:
conf_gcm会读取planet_type、iapp_tracvl和force_conserv_tracer;Mars 运行通常设置planet_type=="mars"。caladvtrac中 Earth 专用dq、qminimum和水汽 tendency 构造不会在 Mars 分支执行。- Mars tracer 输送仍会使用 COMMON
advtrac/advtrac_p的质量通量累计、iapp_tracvl门控、Van Leer split 和可选守恒重标定。 flxw是 tracer 输送轮次产生的垂直质量通量平均值,可被离线/诊断路径使用。- 若
force_conserv_tracer=.true.,每次实际 tracer advection 后会把每个 tracer 乘以old_total/new_total;若new_total极小或为 0,源码没有在此处显式防护,需由配置和 tracer 物理约束避免。
复现顺序
- 从
run.def记录iperiod、iapp_tracvl、force_conserv_tracer、planet_type、offline。 - 从
traceur.def经infotrac_init得到nqtot、nqperes、iadv(:)、父子 tracer 表。 - 在每个动力步保存进入
caladvtrac/advtrac_p的pbaru/pbarv/masse/q;不要只保存第iapp_tracvl步。 - 对第 1 个累计步复制
masse -> massem,对每步累加pbaruc/pbarvc。 - 到第
iapp_tracvl步,执行groupe/groupe_p得到pbarug/pbarvg/wg,并设置flxw=wg/iapp_tracvl。 - 按
iq=1..nqperes与iadv(iq)进入 Van Leer 或饱和路径;当前 Mars 标准只应看到0/10/14。 - 若并行,必须复现
jj_nb_vanleerhalo、band 范围、极点 rank 和返回jj_nb_caldyn的 halo。 - 若开启
force_conserv_tracer,最后按质量积分总量比值整体重标定q。
已确认源码点
| 文件 | 行数 | 关键点 |
|---|---|---|
dyn3d/caladvtrac.F |
139 | 串行 wrapper、Earth dq/qminimum、force_conserv_tracer 前后总量。 |
dyn3d/advtrac.F90 |
407 | iadvtr 累计、iapp_tracvl 门控、nqperes/iadv 循环、CFL 诊断。 |
dyn3dpar/advtrac_p.F90 |
531 | 并行累计、halo、vlspltgen_p 当前可达路径、GOTO 1234 后旧分支不可达。 |
dyn3d/leapfrog.F |
- | forward .OR. leapf 时调用 caladvtrac。 |
dyn3dpar/leapfrog_p.F |
- | forward .OR. leapf 时直接调用 advtrac_p。 |
dyn3d_common/infotrac.F90 |
- | iadv 白名单、nqperes 和父子 tracer 约束。 |
待确认
- 目标 Mars 生产
traceur.def中iadv的实际分布是否全部为10或0,以及是否存在父子 tracer family。 force_conserv_tracer在 Mars 生产中是否启用;源码默认关闭,但运行配置可覆盖。- 当某个 tracer 总量接近 0 时,守恒重标定是否需要运行侧保护或物理侧最小值约束。