calfis_p 与 call_physiq 接口约定
输入范围
dynphy_lonlat\calfis_p.F: L939-1079(call_physiq 调用和 nsplit_phys 循环)
dynphy_lonlat\phytitan.old\callphysiq_mod.F90: L1-97(Titan 参考实现)
dynphy_lonlat\phyvenus\callphysiq_mod.F90: L1-100(Venus 参考实现)
dyn3d_common\infotrac.F90: L5-26, L667-770(nqtot/tname/niadv 定义与初始化)
Mars 运行参与度:条件经过。Mars 并行 GCM 在 apphys=.TRUE. 时经过 calfis_p → call_physiq → physiq。Mars 的 callphysiq_mod 不在 COMMON 树中(位于 Mars 物理目录),但接口签名与 Titan/Venus 版本一致。
例程定位
本页聚焦 calfis_p 调用 call_physiq 时的接口约定:哪些参数被传入、哪些被返回、nqtot/tname/niadv 的语义、以及 nsplit_phys 时间分割机制。网格映射细节见 calfis-p-grid-mapping;整体调用链见 leapfrog-p-physics-coupling。
call_physiq 签名
SUBROUTINE call_physiq(klon, llm, nqtot, tname, &
debut_split, lafin_split, &
jD_cur, jH_cur_split, zdt_split, &
zplev_omp, zplay_omp, &
zpk_omp, zphi_omp, zphis_omp, &
presnivs_omp, &
zufi_omp, zvfi_omp, zrfi_omp, ztfi_omp, zqfi_omp,&
flxwfi_omp, pducov, &
zdufi_omp, zdvfi_omp, zdtfi_omp, zdqfi_omp, zdpsrf_omp)参数分类
| 类别 | 参数 | 维度 | INTENT | 说明 |
|---|---|---|---|---|
| 维度 | klon |
scalar | IN | 当前 OpenMP 线程的物理列数(= klon_omp) |
| 维度 | llm |
scalar | IN | 垂直层数 |
| 维度 | nqtot |
scalar | IN | tracer 总数(含高阶矩、水汽、液水) |
| 标识 | tname(nqtot) |
1D char | IN | tracer 短名称,用于物理内部按名分派 |
| 控制 | debut_split |
scalar | IN | 是否为第一个 split(物理首次初始化) |
| 控制 | lafin_split |
scalar | IN | 是否为最后一个 split(物理收尾操作) |
| 时间 | jD_cur |
scalar | IN | 当前 Julian 日 |
| 时间 | jH_cur_split |
scalar | IN | split 内的 Julian 小时(日内分数) |
| 时间 | zdt_split |
scalar | IN | 单个 split 的时间步长 = dtphys/nsplit_phys |
| 气压 | zplev_omp(klon,llm+1) |
2D | IN | 层界气压 (Pa) |
| 气压 | zplay_omp(klon,llm) |
2D | IN | 中层气压 (Pa) |
| 气压 | zpk_omp(klon,llm) |
2D | IN | Exner 函数值 |
| 位势 | zphi_omp(klon,llm) |
2D | IN | 相对地表的中层位势 |
| 位势 | zphis_omp(klon) |
1D | IN | 地表位势 |
| 参考 | presnivs_omp(llm) |
1D | IN | 各层近似参考气压 |
| 风场 | zufi_omp(klon,llm) |
2D | IN | 自然纬向风 (m/s) |
| 风场 | zvfi_omp(klon,llm) |
2D | IN | 自然经向风 (m/s) |
| 风场 | zrfi_omp(klon,llm) |
2D | IN | 相对涡度 (s⁻¹) |
| 热力 | ztfi_omp(klon,llm) |
2D | IN | 温度 (K) |
| tracer | zqfi_omp(klon,llm,nqtot) |
3D | IN | 混合比 (*/kg air) |
| 垂直 | flxwfi_omp(klon,llm) |
2D | IN | 下界面垂直质量通量 (kg/s) |
| 动力 | pducov(nbp_lon+1,nbp_lat,llm) |
3D | IN | 动力协变 U tendency |
| 输出 | zdufi_omp(klon,llm) |
2D | OUT | 纬向风 tendency (*/s) |
| 输出 | zdvfi_omp(klon,llm) |
2D | OUT | 经向风 tendency (*/s) |
| 输出 | zdtfi_omp(klon,llm) |
2D | OUT | 温度 tendency (K/s) |
| 输出 | zdqfi_omp(klon,llm,nqtot) |
3D | OUT | tracer tendency (*/s) |
| 输出 | zdpsrf_omp(klon) |
1D | OUT | 地表气压 tendency (Pa/s) |
nqtot / tname / niadv 的关系
nqtot(tracer 总数)
nqtot 由 infotrac_init 计算,包含所有需要输送的 tracer:基本示踪物、高阶矩、水汽、液水等。它是动力和物理共享的 tracer 维度上限。
tname(tracer 名称数组)
tname(nqtot) 在 infotrac_init 中填充,每个 tracer 对应一个短字符串(如 "H2O_vap"、"dust_1" 等)。物理侧通过 tname 按名查找特定 tracer 以执行 specialized 过程(如辐射吸收、微物理)。
niadv(动力-物理 tracer 映射)
niadv(nqtot) 建立了动力 tracer 索引到物理 tracer 索引的对应关系:
! infotrac_init 中:
niadv(:) = 0
DO iq = 1, nqtot
! ... 对每个有 iadv(iq) > 0 的 tracer:
niadv(iiq) = iq
ENDDOniadv 的设计目的是允许动力和物理使用不同的 tracer 排序。然而在当前 calfis_p 中:
- scatter 阶段按
iq=1,nqtot顺序直接复制pq(:,:,:,iq)→zqfi(:,:,:,iq) - gather 阶段同样按
iq=1,nqtot直接复制zdqfi(:,:,:,iq)→pdqfi(:,:,:,iq) niadv在calfis_p中未被使用
这意味着当前实现假设动力和物理使用相同的 tracer 排序。如果未来引入不同排序,需要在 scatter/gather 中加入 niadv 重映射。
nsplit_phys 时间分割
zdt_split = dtphys / nsplit_phys
DO isplit = 1, nsplit_phys
jH_cur_split = jH_cur + (isplit-1) * dtvr / (daysec * nsplit_phys)
debut_split = debut .AND. isplit == 1
lafin_split = lafin .AND. isplit == nsplit_phys
CALL call_physiq(klon, llm, nqtot, tname, ...)
! 用当前 tendency 更新状态(给下一个 split 用)
zufi_omp = zufi_omp + zdufi_omp * zdt_split
zvfi_omp = zvfi_omp + zdvfi_omp * zdt_split
ztfi_omp = ztfi_omp + zdtfi_omp * zdt_split
zqfi_omp = zqfi_omp + zdqfi_omp * zdt_split
! 累积 tendency
zdufic_omp = zdufic_omp + zdufi_omp
! ... 同理其他
ENDDO
! 平均 tendency
zdufi_omp = zdufic_omp / nsplit_phys
! ... 同理其他关键语义:
nsplit_phys由control_mod提供,允许物理时间步内细分。- 每个 split 后,物理输入状态被当前 tendency 更新(前向 Euler),使下一个 split 看到更新后的场。
- 最终输出的 tendency 是所有 split 的平均值。
debut_split只在第一个 split 为真(触发物理初始化);lafin_split只在最后一个 split 为真(触发物理收尾)。
pducov 的特殊处理
pducov 是唯一的"非 OMP 切片"参数:
REAL, INTENT(IN) :: pducov(nbp_lon+1, nbp_lat, llm)它的维度是 nbp_lon+1 × nbp_lat(物理侧全局网格维度),而不是 klon_omp。在 calfis_p 的 call_physiq 调用中,pducov 被原样传入而未按 OMP 线程切片。这意味着每个 OMP 线程的物理调用都接收完整的 pducov 数组。
这个设计的可能原因:
- 物理参数化可能需要全局视野的协变风 tendency 信息(如潮汐摩擦)。
pducov可能只在特定行星物理中被使用(Titan/Venus),Mars 物理可能忽略此参数。
callphysiq_mod 内部分派
Titan 和 Venus 的 callphysiq_mod 实现相同模式:
firstcall时验证planet_type匹配。- 直接转发到
physiq_mod:physiq(行星特定的物理包)。 - Titan 版向
physiq传递zrfi_omp(涡度),Venus 版不传(注释掉了plevmoy/tmoy)。
Mars 的 callphysiq_mod 不在 COMMON 树中,位于 Mars 物理目录。根据 COMMON 中 calfis_p.F 的注释代码块(L957-L1066),旧版曾按 planet_type 分支直接调用不同签名的 physiq,现已被统一的 call_physiq 接口替代。
约定约束总结
| 约定项 | 约束 |
|---|---|
| klon 一致性 | call_physiq 的 klon 必须等于调用方的 klon_omp |
| nqtot 一致性 | 动力和物理必须使用相同的 nqtot 值 |
| tname 稳定性 | tname 在运行期间不变;物理按名查找 tracer |
| tendency 单位 | 所有输出 tendency 为 */s(每秒变化率) |
| tendency 维度 | 输出 tendency 的 tracer 维与输入 zqfi 对齐(nqtot) |
| 状态更新 | 物理可以假定输入状态是上一步物理输出更新后的值 |
| pducov 范围 | 物理侧不应假定 pducov 与 klon_omp 有直接索引关系 |
复现要点
- Mars 物理的
callphysiq_mod接口必须与 COMMON 中calfis_p的调用签名严格匹配。修改接口时需要同步更新 Mars 物理目录中的callphysiq_mod。 niadv当前未使用意味着 tracer 在动力和物理间的排序必须一致。如果引入新的 tracer 类型,需确认infotrac_init产生的排序与物理侧预期一致。nsplit_phys > 1时,split 间的状态更新是前向 Euler(一阶),这在大 tendency 或小 split 数时可能引入误差。pducov的全局维度传递意味着它不能被 OMP 线程安全地按列访问——物理侧如果读取此数组需要注意线程安全。
相关页面
- calfis_p 模块页
- calfis_p 格点映射
- calfis_p 并行 transfer 架构
- calfis_p 日期与行星分支
- leapfrog_p 物理耦合
- infotrac Mars 使用关系
- infotrac 状态约定
待确认
- Mars 物理目录中
callphysiq_mod的实际实现是否与 Titan/Venus 签名完全一致。 pducov在 Mars 物理中是否被实际使用,以及其全局维度传递是否导致 OMP 竞争。nsplit_phys在 Mars 配置中的典型值(通常为 1)。niadv未使用是否会在某些 tracer 配置下导致排序不一致。