calfis_p.F
路径
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dynphy_lonlat\calfis_p.F
文件定位
calfis_p.F 定义并行动力调用物理的接口例程 calfis_p。它由 leapfrog_p 在 apphys 为真时调用,负责把并行动力网格上的 pressure、temperature、wind、tracer、geopotential 和 vertical mass flux 组织成物理列数组,调用 call_physiq,再把物理 tendency 写回动力网格。
相比串行 calfis,并行版的主要额外职责是:
- 通过 mod_interface_dyn_phys 的
index_i/index_j把klon_mpi物理列映射回动力(i,j)。 - 把 MPI rank 内的物理列再按 OpenMP 线程拆成
klon_omp段;进入线程段后局部变量klon被设为klon_omp,再调用call_physiq。 - 在物理后用 MPI 交换相邻 rank 的
zdufi/zdvfi边界,支持 wind tendency 回填时的跨纬向平均。 - 与
leapfrog_p前后的jj_Nb_Physic/jj_Nb_Physic_bishalo 处理配合,完成 tendency 在动力网格上的一致写回。
Mars 运行参与度
条件经过:Mars 并行动力启用物理时经过;串行 Mars GCM 和 Mars nogcm 不经过本文件。
源码中仍保留 Titan/Venus zonal/global mean 分支和旧式按 planet_type 调 physiq 的注释代码。本页只把非 Mars 分支作为边界记录。
定义的符号
| 符号 | 类型 | 行号 | 作用 |
|---|---|---|---|
calfis_p |
subroutine | 6 | 并行动力-物理调用接口。 |
入口参数
| 参数组 | 方向 | 说明 |
|---|---|---|
lafin,jD_cur,jH_cur |
in | 最后一次 physics 标志、当前物理日和日内时间,由 leapfrog_p 计算。 |
pucov,pvcov,pteta,pq,pmasse,pps |
in | 动力状态;pmasse 在本文件声明为 not used。 |
pp,ppk,pphis,pphi |
in | 层界 pressure、Exner、地表位势和层位势。 |
pducov,pdvcov,pdteta,pdq |
in | 动力 tendency;pdq 注释说明只服务于已注释的旧计算,当前实际不用。 |
flxw |
in | 动力网格上的垂直质量通量。 |
pdufi,pdvfi,pdhfi,pdqfi,pdpsfi |
out | physics 返回给动力的 wind、potential-temperature、tracer 和 surface-pressure tendency。 |
pq/pdq/pdqfi 的 tracer 第四维是 nqtot。niadv 被 USE infotrac 引入,但当前 calfis_p 回填 pdqfi 时直接按 iq=1,nqtot 写回,没有使用 niadv(iq) 重映射。
编译边界
本文件核心实现嵌在 CPP_PARA 和 CPP_PHYS 内:
CPP_PARA提供parallel_lmdz、AllGather_Field、OpenMP chunk、并行动力边界。CPP_PHYS提供dimphy、物理侧 MPI/OMP data、call_physiq。- 如果没有
CPP_PHYS,源码会打印calfis_p: for now can only work with parallel physics并stop。
保存工作区
| 工作区 | 维度 | 作用 |
|---|---|---|
zpsrf |
klon_mpi |
rank 内物理列 surface pressure;源码中 rank 级初始化阶段用局部变量 klon=klon_mpi。 |
zplev,zplay,zpk |
klon,llm(+1) |
层界 pressure、中层 pressure、Exner。 |
zphi,zphis |
klon,llm / klon |
相对地表的 geopotential 和地表位势。 |
zufi,zvfi,zrfi |
klon,llm |
物理侧自然风分量和 relative vorticity。 |
zteta,ztfi,zqfi |
klon,llm,(nqtot) |
位温、温度和 tracer 物理列。 |
zdufi,zdvfi,zdtfi,zdqfi,zdpsrf |
klon,... |
物理 tendency。 |
*_omp |
klon_omp,... |
当前 OpenMP 线程的物理列切片。 |
zdufic_omp/zdvfic_omp/zdtfic_omp/zdqfic_omp |
klon_omp,... |
nsplit_phys 累积 tendency。 |
du_send/dv_send/du_recv/dv_recv |
iim,llm |
MPI rank 间交换 wind tendency 边界。 |
zdufi2/zdvfi2 |
klon+iim,llm |
本 rank tendency 加下一 rank 边界后的扩展数组。 |
多数组为 SAVE,ALLOCATABLE。*_omp 和 first_omp 是 THREADPRIVATE,每个 OpenMP 线程只分配自己的物理列切片。
主要依赖
| 依赖 | 用途 |
|---|---|
| mod_interface_dyn_phys | index_i/index_j 映射物理列到动力 (i,j)。 |
| mod_phys_lmdz_para 与物理侧 data 模块 | klon_mpi/klon_omp/klon_omp_begin、极点所有权、MPI rank/size。 |
| dyn-phys-grid-transforms | gr_dyn_fi_p/gr_fi_dyn_p 标量场格点互转。 |
callphysiq_mod |
call_physiq 统一行星物理入口。 |
cpdet_mod |
tpot2t_p/t2tpot_p,支持 CP(T) 转换。 |
moyzon_mod |
Titan/Venus zonal mean 分支;Mars 主线不展开。 |
首次调用初始化
首次调用时:
- 设置
klon=klon_mpi。 - 检查
ngridmx是否等于2+(jjm-1)*iim;源码参数写为2+(jjm-1)*iim - 1/jjm,整数除法在常规jjm>1下减 0。 - 设置
unskap=1/kappa。 - 若
moyzon_ch或moyzon_mu为真,分配 zonal mean 临时数组并调用moyzon_init。 - 分配 MPI rank 级别的
z*工作区。 - Titan/Venus 分支会
AllGather_Field全局 pressure、temperature、geopotential,计算 zonal/global mean 剖面和klat。
Mars 并行动力主线需要前 5 步;第 6 步属于非 Mars 分支。
动力场到物理列
转换顺序:
zpsrf(ig0)=pps(index_i(ig0),index_j(ig0))。- 对每层复制
pp -> zplev,ppk -> zpk,pteta -> zteta。 tpot2t_p(klon,llm,zteta,ztfi,zpk)把位温变成物理温度。- 用
preff*(ppk/cpp)**(1/kappa)得到zplay。 - 对所有 tracer 复制
pq -> zqfi。 gr_dyn_fi_p把pphi和pphis转成物理列,再令zphi=zphi-zphis,物理侧接收相对地表位势。- wind 转换:
zufi用相邻两个 U 点平均并除以cu得到自然 zonal wind。- 先在动力网格上算
zrot,再用相邻 V 点平均得到zvfi,并计算zrfi。 - 北/南极由
pvcov/cv对 longitude 做cos/sin积分,得到极点自然风分量。
gr_dyn_fi_p把flxw转为flxwfi。
index_i/index_j 是所有普通物理列转换的核心;极点是单列,不能按普通纬圈展开。
OpenMP 物理调用
每个 OpenMP 线程首次进入时按 klon_omp 分配 *_omp 工作区。随后源码把局部变量 klon 改为 klon_omp,后续 call_physiq(klon,...) 的第一维就是当前线程切片长度。
offset=klon_omp_begin-1。- 从 rank 级
z*数组拷贝本线程负责的offset+1:offset+klon_omp切片。 - 若启用 zonal mean,也拷贝
zplevbar/zplaybar/zphibar/zphisbar/ztfibar/zqfibar。 - 设置
zdt_split=dtphys/nsplit_phys,清零 split 累积 tendency。 - 对
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_physiq(klon,llm,nqtot,tname,...),此处klon==klon_omp。 - 用当前 split tendency 更新
zufi_omp/zvfi_omp/ztfi_omp/zqfi_omp,并累积zdufic_omp/...。
- split 循环后把累积 tendency 除以
nsplit_phys,写回zdufi_omp/zdvfi_omp/zdtfi_omp/zdqfi_omp。 - 把 OMP 切片写回 rank 级
z*数组。
旧的 Earth/generic/Mars/Titan/Venus 直接 physiq 调用都在注释中;当前执行路径是统一 call_physiq。
MPI 边界交换
physics 结束后,calfis_p 只在 using_mpi 为真时手写一段 MPI 交换:
MPI_rank>0的 rank 将本 rank 前iim个zdufi/zdvfi列打包到du_send/dv_send,用 tag401/402发送给MPI_rank-1。MPI_rank<MPI_Size-1的 rank 从MPI_rank+1接收下一 rank 的du_recv/dv_recv。- 中间 rank 等待 4 个 request,边界 rank 等待 2 个 request。
- 每层构造
zdufi2(1:klon)=zdufi,zdufi2(klon+1:klon+iim)=du_recv,zdvfi2同理。
这段交换服务于后续 pdvfi 回填:V wind tendency 需要 ig0 和下一纬带 ig0+iim 的物理 tendency 做平均。没有下一 rank 的边界,rank 尾部的 pdvfi 会缺半个 stencil。
物理 tendency 回写
回写前先把本 rank 起始纬圈 tendency 清零;若不是南极 rank,也清零结束纬圈,避免旧值残留。随后:
gr_fi_dyn_p(1,klon,iip1,jjp1,zdpsrf,pdpsfi)写 surface-pressure tendency。t2tpot_p(klon,llm,ztfi,zteta,zpk)把 physics 后温度转回位温。pdhfi不直接用zdtfi,而是(zteta-pteta)/dtphys;极点整行用单个极点物理列扩展。pdqfi先整层清零,再按iq=1,nqtot从zdqfi写回;i==1时补周期端点iip1。pdufi使用相邻zdufi2平均后乘cu写回 covariant U tendency;极点行置 0。pdvfi使用zdvfi2(ig0)和zdvfi2(ig0+iim)平均后乘cv写回 covariant V tendency。- 近极点的
pdvfi用极点自然风 tendency 投影到各经度,再和邻近物理列平均。 firstcal=.FALSE.,之后debut变为.FALSE.。
与 leapfrog_p 的接口约定
leapfrog_p 在调用前已经把动力字段切到 physics band,并在调用后对 pdufi/pdvfi/pdhfi/pdqfi/pdpsfi 做 halo 合并,再用 addfi_p 写回动力状态。因此:
calfis_p负责“physics 列调用”和“把 tendency 放回动力网格”。leapfrog_p负责“跨 band 的字段可见性”和“把 tendency 加到 prognostic state”。calfis_p输出仍是 tendency,单位是每秒;不是已经乘过dtphys的状态增量。
Mars 路径边界
| 分支 | Mars 并行动力是否走 | 说明 |
|---|---|---|
call_physiq |
是,启用 physics 时 | Mars physics 通过统一入口使用 tname/nqtot/jD_cur/jH_cur_split。 |
nsplit_phys |
是 | 每个 split 用 dtphys/nsplit_phys,并推进 jH_cur_split。 |
moyzon_ch/moyzon_mu |
非 Mars 主线 | 源码注释说明当前用于 Titan/Venus 类 zonal mean。 |
旧式 planet_type=="mars" 直接 physiq |
不执行 | 仅保留为注释代码。 |
niadv tracer 重映射 |
不执行 | niadv 被引入但当前并行回填未使用。 |
复现检查表
- 确认
Init_interface_dyn_phys已初始化index_i/index_j,且klon_mpi/klon_omp与物理侧分布一致。 - 从
leapfrog_p确认传入字段已经处于jj_Nb_Physic分布。 - 对单列差异,先用
index_i/index_j反查动力(i,j)。 - 对 wind 差异,分别检查 covariant/natural wind 转换、极点
cos/sin投影和 MPI 边界交换。 - 对 tracer 差异,注意并行版按
iq直接写回,没有niadv映射。 - 对 split 差异,检查
nsplit_phys、jH_cur_split和 split 后 tendency averaging。 - 对 tendency 写回差异,检查
leapfrog_p后续的jj_Nb_Physic_bishalo 合并和addfi_p。
待确认
pducov被直接传入call_physiq,但未切成 OMP 局部数组;其在各行星 physics 中的实际使用需要callphysiq_mod/Mars physics 侧确认。niadv在并行版中未被使用是否为历史遗留或刻意保持 tracer 顺序一致,需要与 tracer 配置和串行calfis对照验证。moyzon_ch/moyzon_mu对 Mars 是否永远关闭需由实际运行配置确认。
相关页面
- dynphy_lonlat 总览
- calfis
- mod_interface_dyn_phys
- dyn-phys-grid-transforms
- calfis_p 动力格点到物理列映射
- calfis_p 与 call_physiq 接口约定
- calfis_p 并行 transfer 架构
- calfis_p 日期与行星分支
- leapfrog_p
- leapfrog-p-physics-coupling
- leapfrog-physics-coupling
- serial-parallel-dynamics
- mod_phys_lmdz_para
- physics_distribution_mod
- mpi-data-transfer
- omp-data-transfer