动力-物理接口

源码范围:LMDZ.COMMON-6.3/LMDZ.COMMON/libf/dynphy_lonlatlibf/phy_common,并串联 dyn3d/leapfrog.Fdyn3dpar/leapfrog_p.Fdyn3d/addfi.Fdyn3dpar/addfi_p.F 的调用边界。 Mars 运行参与度:条件经过。Mars 3D GCM 启用物理时经过本主题覆盖的初始化和 calfis/calfis_p -> call_physiq -> addfi/addfi_p 接口;Mars 1D/testphys 路径只使用其中的接口兼容层和物理侧网格/垂直层初始化。

主题定位

本页回答一个问题:动力网格上的 ps/p/pk/teta/q/u/v/phi/flxw 如何进入 Mars physics,又如何以 tendency 形式回到动力状态。

接口拆成三层:

责任 主要页面
初始化层 建立物理列分布、几何、垂直层和动力-物理索引。 inigeomphy_mod, parallel-physics-grid-distribution, mod_interface_dyn_phys
每步调用层 把动力状态转为物理列,调用 call_physiq,把 tendency 放回动力网格。 calfis, calfis_p, dyn-phys-grid-transforms
写回状态层 addfi/addfi_p 将 tendency 乘以 dtphys 加到 prognostic state,并刷新 pressure/mass/Exner。 leapfrog-physics-coupling, leapfrog-p-physics-coupling, addfi-serial-parallel

总体调用链

串行 GCM physics 步:

gcm/conf_gcm/iniconst/inigeom/iniphysiq
  -> COMMON inigeomphy
       -> init_physics_distribution
       -> init_interface_dyn_phys
       -> init_regular_lonlat / init_geometry / init_vertical_layers

leapfrog
  -> apphys gate
  -> pression / exner_* / geopot
  -> calfis(lafin,jD_cur,jH_cur,...)
       -> gr_dyn_fi and manual wind/tracer mapping
       -> call_physiq, optionally split by nsplit_phys
       -> gr_fi_dyn and manual tendency writeback
  -> addfi(dtphys,...)
  -> pression / massdair / exner_*

并行 GCM physics 步:

gcm_p/init_parallel/set_bands
  -> iniphysiq
       -> inigeomphy
            -> init_physics_distribution
                 -> init_grid_phy_lmdz
                 -> Init_phys_lmdz_para
                      -> init_phys_lmdz_mpi_data
                      -> init_phys_lmdz_omp_data
                 -> dimphy:Init_dimphy(klon_omp, nbp_lev)
            -> init_interface_dyn_phys(index_i/index_j)
            -> init_geometry(klon_omp, ...)
            -> init_vertical_layers(...)

leapfrog_p
  -> apphys gate
  -> pression_p / exner_*_p / geopot_p
  -> SetDistrib(jj_Nb_Physic)
  -> calfis_p(lafin,jD_cur,jH_cur,...)
       -> rank-level动力格点到klon_mpi物理列
       -> OpenMP切片到klon_omp
       -> call_physiq, optionally split by nsplit_phys
       -> OpenMP gather回klon_mpi
       -> MPI wind tendency boundary exchange
       -> tendency写回动力网格
  -> SetDistrib(jj_Nb_Physic_bis)
  -> tendency halo and tmp add-back
  -> addfi_p(dtphys,...)
  -> pression_p / massdair_p / exner_*_p
  -> SetDistrib(jj_Nb_Caldyn)

calfis/calfis_p 只产生每秒 tendency;真正修改 ucov/vcov/teta/q/ps 的位置是 addfi/addfi_paddfi* 之后必须刷新 p/masse/pk,否则后续动力、输出或 restart 会看到与新 ps 不一致的派生状态。

初始化约定

Mars physics 初始化先进入 MARS 侧 iniphysiq,再调用 COMMON 的 inigeomphyinigeomphy 的输出不是单个返回值,而是写入一组物理侧公共模块:

状态 写入者 使用位置 关键边界
klon_glo, nbp_lon/lat/lev init_grid_phy_lmdz 全局物理网格转换、XIOS、debug 写场 klon_glo 是全局物理列数,两极各压缩成单列。
klon_mpi 和 rank 分布表 init_phys_lmdz_mpi_data MPI transfer、calfis_p、XIOS/write_field 当前 MPI rank 的物理列数,不等于全局列数。
klon_omp 和 thread 切片 init_phys_lmdz_omp_data Mars physics、OMP transfer、calfis_p 当前 OpenMP 线程的物理列数。
dimphy:klon/klev Init_dimphy Mars physics 例程 dimphy:klon 等于 klon_omp,不是 klon_gloklon_mpi
index_i/index_j Init_interface_dyn_phys calfis_p, gr_dyn_fi_p, gr_fi_dyn_p 长度为 klon_mpi,把 rank 级物理列映射到动力 (i,j)
longitude/latitude/cell_area init_geometry physics、diagfi、XIOS、archive 工具链 每个 OMP 线程只持有自己的 klon_omp 几何切片。
ap/bp/aps/bps/presnivs/pseudoalt init_vertical_layers physics、输出轴、Mars utility 从动力侧 comvert_mod 显式复制到物理侧 vertical_layers_mod

这条链只建立分布和静态几何。每个 physics 步的 ps/teta/q/u/v/phi/flxw 仍由 calfis/calfis_p 从动力状态重新映射。

串行接口

串行 calfis 使用全局 lon-lat 规则把动力网格压缩成物理列:

  1. 北极和南极各为一个物理列。
  2. 中间纬圈按非重复经度展开。
  3. gr_dyn_fi 转换标量场,风场用 cu/cv 和极点 cos/sin 投影转换为自然风。
  4. tpot2t 把位温转为 physics 温度。
  5. nsplit_phys 分段调用 call_physiq,每段使用 dtphys/nsplit_phys
  6. 物理返回的温度、风、tracer、surface pressure tendency 被累计、平均,再用 gr_fi_dyn 或显式循环写回动力 tendency 数组。

串行 tracer 写回使用 niadv(iq) 连接 physics tracer 和动力 tracer 序号。排查 tracer 顺序差异时,串行路径要同时看 infotracnqtot/tname/niadv

并行接口

并行 calfis_p 的职责比串行多三件事:rank 分布、OpenMP 切片和跨 rank tendency 边界。

动力格点到物理列

calfis_p 先以 klon=klon_mpi 工作。普通列通过 index_i/index_j 读取动力格点:

zpsrf(ig) = ps(index_i(ig), index_j(ig))
zpk(ig,l) = pk(index_i(ig), index_j(ig), l)
zqfi(ig,l,iq) = q(index_i(ig), index_j(ig), l, iq)

gr_dyn_fi_pgr_fi_dyn_p 也使用同一映射。极点列仍是单列,写回动力网格时要扩展成整条极点行。

OpenMP 物理调用

rank 级 z*(klon_mpi,...) 数组准备好后,源码按 klon_omp_begin/end 手写循环复制到当前线程的 *_omp(klon_omp,...)。随后局部 klon 改为 klon_ompcall_physiq(klon,...) 看到的是当前线程的物理列数。

这一段不调用 mod_phys_lmdz_transfert_parascatter/gather 泛型。原因是 calfis_p 的映射源是动力二维网格 (iip1,jjp1),目标是 rank 内物理列;phy_common 通用 transfer 的映射对象是 klon_glo -> klon_mpi -> klon_omp 的物理列数组,两者不是同一类搬运。

tendency 边界和 addfi_p 前处理

calfis_p 返回前已经把 tendency 写回动力网格,但并行 leapfrog_p 还要做一次 physics band 后处理:

  1. 保存非北极 rank 起始纬圈的 dufi/dvfi/dtetafi/dqfi/dpfi_tmp
  2. 切换到 jj_nb_Physic_bis
  3. 对 physics tendency 注册 halo request 并等待完成。
  4. 切回 jj_nb_Physic
  5. _tmp 加回起始纬圈。

只有完成这一步后,addfi_p 才把 tendency 加到状态。因此并行差异要分成三段定位:calfis_p 列映射和 call_physiq 输出、leapfrog_p tendency halo、addfi_p 状态写回。

call_physiq 约定

COMMON 侧不实现 Mars physics 过程本体,但它负责提供一致的入口实参:

实参组 来源 说明
klon,llm,nqtot,tname 物理分布、动力垂直层、tracer 初始化 klon 在并行 OMP 内为 klon_omp
jD_cur,jH_cur leapfrog* 日期逻辑 并行 Mars physics 日期在 leapfrog_p 中按当前 itau 计算。
zplev,zplay,zpk pression*、Exner、preff*(ppk/cpp)**(1/kappa) pressure 层和 Exner/温度转换输入。
ztfi,zqfi,zufi,zvfi,zrfi calfis* 转换 physics 使用的温度、tracer、自然风和涡度。
zphi,zphis,flxwfi geopot* 和 grid transform 位势、地表位势和垂直质量通量。
zdufi/zdvfi/zdtfi/zdqfi/zdpsrf call_physiq 输出 每秒 tendency,之后由 calfis*addfi* 分别映射/加回。

nsplit_phys 分段时,COMMON 侧在每个 split 后先用 tendency 更新 physics 输入列,再累计平均 tendency。最后一个 split 才接收 lafin_split=.TRUE.

transfer 边界

物理侧通用 transfer 已由 mod_phys_lmdz_mpi_transfertmod_phys_lmdz_omp_transfertmod_phys_lmdz_transfert_para 覆盖。它们服务于物理侧数组在全局、rank 和 thread 之间的 scatter/gather/bcast/reduce。

本主题需要区分三类通信:

通信/搬运 实现位置 是否是 calfis_p 主搬运
物理侧通用 bcast/scatter/gather/reduce_sum phy_common/mod_phys_lmdz_*_transfert.F90 否。供 physics 公共层和输出/helper 使用。
动力网格到物理列映射 calfis_p, gr_dyn_fi_p, gr_fi_dyn_p 是。由 index_i/index_j 和手写 OMP 循环驱动。
wind tendency 跨 rank 交换 calfis_pMPI_ISSEND/IRECV/WAITALL 是。只服务于 pdvfi 等跨纬带回填 stencil。

不要把 calfis_p 的手写 scatter/gather 描述成直接调用 mod_phys_lmdz_transfert_para。两者共享 klon_mpi/klon_omp 维度概念,但调用路径和映射关系不同。

与物理几何和垂直层的关系

inigeomphy 同时初始化水平几何和垂直层副本:

Mars physics、diagfi/stats、XIOS 输出和 archive utility 可能使用这些物理侧状态。若出现输出坐标、面积或压力轴问题,先确认 iniconst/disvert/inigeom/iniphysiq -> inigeomphy 顺序,而不是直接查每步 calfis_p

串并行差异表

方面 串行 并行
调度入口 leapfrog -> calfis -> addfi leapfrog_p -> SetDistrib(jj_Nb_Physic) -> calfis_p -> halo -> addfi_p
物理列规模 全局 ngridmx rank 级 klon_mpi,线程级 klon_omp
列映射 固定 lon-lat 展开 index_i/index_j
OMP rank 级共享数组 + threadprivate *_omp 工作区
MPI physics tendency halo + calfis_p wind exchange
tracer 写回 使用 niadv(iq) 当前 calfis_piq=1,nqtot 直接写回
状态写回 addfi 后刷新 p/masse/pk addfi_p 后刷新 p/masse/pk,并受 band/halo 影响

复现检查表

  1. 确认 conf_gcm 已设置 iphysiq/iflag_phys/nsplit_phys,并且当前时间步 apphys=.TRUE.
  2. 确认 physics 前已刷新 p/pk/phi,并记录 jD_cur/jH_cur
  3. 串行路径检查 gr_dyn_fi/gr_fi_dyn 的极点和周期端点规则。
  4. 并行路径检查 SetDistrib(jj_Nb_Physic)index_i/index_jklon_mpi/klon_ompdimphy:klon 是否一致。
  5. 对 physics 内部差异,先确认 call_physiq 入口看到的是温度 ztfi 而不是动力位温 teta
  6. 对 tendency 差异,区分 calfis* 输出、并行 halo 合并、addfi* 加回三步。
  7. 对 pressure/mass 不一致,检查 addfi*pression*/massdair*/exner_* 是否执行。
  8. 对输出几何或垂直坐标,检查 inigeomphy -> init_geometry/init_vertical_layers,不要只看每步 calfis*

易混点

待确认

相关页面