calfis_p.F

路径

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dynphy_lonlat\calfis_p.F

文件定位

calfis_p.F 定义并行动力调用物理的接口例程 calfis_p。它由 leapfrog_papphys 为真时调用,负责把并行动力网格上的 pressure、temperature、wind、tracer、geopotential 和 vertical mass flux 组织成物理列数组,调用 call_physiq,再把物理 tendency 写回动力网格。

相比串行 calfis,并行版的主要额外职责是:

Mars 运行参与度

条件经过:Mars 并行动力启用物理时经过;串行 Mars GCM 和 Mars nogcm 不经过本文件。

源码中仍保留 Titan/Venus zonal/global mean 分支和旧式按 planet_typephysiq 的注释代码。本页只把非 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 第四维是 nqtotniadvUSE infotrac 引入,但当前 calfis_p 回填 pdqfi 时直接按 iq=1,nqtot 写回,没有使用 niadv(iq) 重映射。

编译边界

本文件核心实现嵌在 CPP_PARACPP_PHYS 内:

保存工作区

工作区 维度 作用
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*_ompfirst_ompTHREADPRIVATE,每个 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 主线不展开。

首次调用初始化

首次调用时:

  1. 设置 klon=klon_mpi
  2. 检查 ngridmx 是否等于 2+(jjm-1)*iim;源码参数写为 2+(jjm-1)*iim - 1/jjm,整数除法在常规 jjm>1 下减 0。
  3. 设置 unskap=1/kappa
  4. moyzon_chmoyzon_mu 为真,分配 zonal mean 临时数组并调用 moyzon_init
  5. 分配 MPI rank 级别的 z* 工作区。
  6. Titan/Venus 分支会 AllGather_Field 全局 pressure、temperature、geopotential,计算 zonal/global mean 剖面和 klat

Mars 并行动力主线需要前 5 步;第 6 步属于非 Mars 分支。

动力场到物理列

转换顺序:

  1. zpsrf(ig0)=pps(index_i(ig0),index_j(ig0))
  2. 对每层复制 pp -> zplevppk -> zpkpteta -> zteta
  3. tpot2t_p(klon,llm,zteta,ztfi,zpk) 把位温变成物理温度。
  4. preff*(ppk/cpp)**(1/kappa) 得到 zplay
  5. 对所有 tracer 复制 pq -> zqfi
  6. gr_dyn_fi_ppphipphis 转成物理列,再令 zphi=zphi-zphis,物理侧接收相对地表位势。
  7. wind 转换:
    • zufi 用相邻两个 U 点平均并除以 cu 得到自然 zonal wind。
    • 先在动力网格上算 zrot,再用相邻 V 点平均得到 zvfi,并计算 zrfi
    • 北/南极由 pvcov/cv 对 longitude 做 cos/sin 积分,得到极点自然风分量。
  8. gr_dyn_fi_pflxw 转为 flxwfi

index_i/index_j 是所有普通物理列转换的核心;极点是单列,不能按普通纬圈展开。

OpenMP 物理调用

每个 OpenMP 线程首次进入时按 klon_omp 分配 *_omp 工作区。随后源码把局部变量 klon 改为 klon_omp,后续 call_physiq(klon,...) 的第一维就是当前线程切片长度。

  1. offset=klon_omp_begin-1
  2. 从 rank 级 z* 数组拷贝本线程负责的 offset+1:offset+klon_omp 切片。
  3. 若启用 zonal mean,也拷贝 zplevbar/zplaybar/zphibar/zphisbar/ztfibar/zqfibar
  4. 设置 zdt_split=dtphys/nsplit_phys,清零 split 累积 tendency。
  5. 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/...
  6. split 循环后把累积 tendency 除以 nsplit_phys,写回 zdufi_omp/zdvfi_omp/zdtfi_omp/zdqfi_omp
  7. 把 OMP 切片写回 rank 级 z* 数组。

旧的 Earth/generic/Mars/Titan/Venus 直接 physiq 调用都在注释中;当前执行路径是统一 call_physiq

MPI 边界交换

physics 结束后,calfis_p 只在 using_mpi 为真时手写一段 MPI 交换:

  1. MPI_rank>0 的 rank 将本 rank 前 iimzdufi/zdvfi 列打包到 du_send/dv_send,用 tag 401/402 发送给 MPI_rank-1
  2. MPI_rank<MPI_Size-1 的 rank 从 MPI_rank+1 接收下一 rank 的 du_recv/dv_recv
  3. 中间 rank 等待 4 个 request,边界 rank 等待 2 个 request。
  4. 每层构造 zdufi2(1:klon)=zdufizdufi2(klon+1:klon+iim)=du_recvzdvfi2 同理。

这段交换服务于后续 pdvfi 回填:V wind tendency 需要 ig0 和下一纬带 ig0+iim 的物理 tendency 做平均。没有下一 rank 的边界,rank 尾部的 pdvfi 会缺半个 stencil。

物理 tendency 回写

回写前先把本 rank 起始纬圈 tendency 清零;若不是南极 rank,也清零结束纬圈,避免旧值残留。随后:

  1. gr_fi_dyn_p(1,klon,iip1,jjp1,zdpsrf,pdpsfi) 写 surface-pressure tendency。
  2. t2tpot_p(klon,llm,ztfi,zteta,zpk) 把 physics 后温度转回位温。
  3. pdhfi 不直接用 zdtfi,而是 (zteta-pteta)/dtphys;极点整行用单个极点物理列扩展。
  4. pdqfi 先整层清零,再按 iq=1,nqtotzdqfi 写回;i==1 时补周期端点 iip1
  5. pdufi 使用相邻 zdufi2 平均后乘 cu 写回 covariant U tendency;极点行置 0。
  6. pdvfi 使用 zdvfi2(ig0)zdvfi2(ig0+iim) 平均后乘 cv 写回 covariant V tendency。
  7. 近极点的 pdvfi 用极点自然风 tendency 投影到各经度,再和邻近物理列平均。
  8. firstcal=.FALSE.,之后 debut 变为 .FALSE.

与 leapfrog_p 的接口约定

leapfrog_p 在调用前已经把动力字段切到 physics band,并在调用后对 pdufi/pdvfi/pdhfi/pdqfi/pdpsfi 做 halo 合并,再用 addfi_p 写回动力状态。因此:

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 被引入但当前并行回填未使用。

复现检查表

  1. 确认 Init_interface_dyn_phys 已初始化 index_i/index_j,且 klon_mpi/klon_omp 与物理侧分布一致。
  2. leapfrog_p 确认传入字段已经处于 jj_Nb_Physic 分布。
  3. 对单列差异,先用 index_i/index_j 反查动力 (i,j)
  4. 对 wind 差异,分别检查 covariant/natural wind 转换、极点 cos/sin 投影和 MPI 边界交换。
  5. 对 tracer 差异,注意并行版按 iq 直接写回,没有 niadv 映射。
  6. 对 split 差异,检查 nsplit_physjH_cur_split 和 split 后 tendency averaging。
  7. 对 tendency 写回差异,检查 leapfrog_p 后续的 jj_Nb_Physic_bis halo 合并和 addfi_p

待确认

相关页面