guide_p_mod.F90

源码路径:LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\guide_p_mod.F90

Mars 运行参与度:接口兼容 + 条件边界。当前源码中 leapfrog_p.Fguide_p_mod:guide_main 的活动调用位于 #ifdef CPP_IOIPSLplanet_type=="earth" 的分支内;Mars/generic 并行入口的 ok_guide 初始化路径调用 relaxetat0("relax.nc"),generic 时间推进还有 inline attenua u-wind nudging,均不经过本模块的 NetCDF guide 输入链。

文件定位

guide_p_mod 是并行动力目录中的 nudging/guide 模块,和串行 guide_mod 对应。它公开 guide_main(itau,ucov,vcov,teta,q,masse,ps),内部封装配置读取、NetCDF 输入、压力层插值、松弛系数、状态叠加和 guide_ins.nc 输出。

并行版的核心区别不是输入文件分块读取,而是读入后只处理本 rank 的局部纬向带,并在 V 网格或 staggered 压力需要相邻行时显式做 halo。

公开入口和私有例程

符号 类型 调用方 职责
guide_main subroutine leapfrog_p.F 的 Earth/IOIPSL ok_guide 分支 建立本地 U/V 范围,按频率读取/插值 guide 输入,把 forcing 加到并行动力状态。

主要私有例程和串行版同名:

例程 并行职责
guide_init 读取 guide 参数,解析 guide_plevs,分配全局尺寸 guide 数组和并行额外 pnat 场。
guide_read / guide_read2D 每个 MPI rank 读取完整 NetCDF 输入场;并行版额外支持 P.ncPRES
guide_interp jjb_u:jje_u / jjb_v:jje_v 本地纬向段插值,并用 Register_SwapFieldHallo 补 halo。
guide_addfield hsize==ip1jm 区分 V 网格和 U/scalar 网格,只处理 ijb_v:ije_vijb_u:ije_u
guide_zonave 只在本地纬向段计算和填回纬向平均。
guide_out gather_field 到 root,只有 mpi_rank==0guide_ins.nc

并行状态

guide_p_mod 保存两组并行边界:

状态 来源 用途
ijb_u/ije_u, jjb_u/jje_u parallel_lmdz:ij_begin/jj_begin U、T、Q、Ps、scalar 网格本地范围。
ijb_v/ije_v, jjb_v/jje_v 同上,若 pole_sud 则缩短末行 V 网格本地范围。
jjn_u/jjn_v, ijn_u/ijn_v 上述范围长度 传给 pres2levq_sat 和本地循环。

这些边界在每次 guide_main 开头重设。源码中注释掉了 AllGather_Field(ucov/vcov/teta/ps/q),所以正常路径依赖 guide_read 全场输入、guide_interp 本地切片和状态局部写回,而不是每步先 allgather 动力状态。

guide_plevs

并行版新增 guide_plevs,并兼容旧的 guide_modele

guide_plevs 输入压力层 额外文件/数组
0 纯压力层,apnc(l)
1 混合层,apnc(l)+bpnc(l)*psnat(i,j) apbp.nc, psnat
2 逐格点压力,pnat(i,j,l) P.nc:PRES, pnat1/pnat2

guide_plevs=2 是串行 guide_mod 没有的能力。它让 T/Q/U/V 的输入压力可随水平格点和层变化;V 网格计算前需要对 pnat 做 halo,避免用不到相邻纬向行。

输入和插值流程

guide_readguide_read2D 并不做并行 I/O 分块。每个 rank 打开同一组文件并读完整场,然后 guide_interp 才按本地范围访问:

read complete unat/vnat/tnat/qnat/psnat/pnat
  -> local model pressure on jjb_u:jje_u
  -> pext halo
  -> massbar_p -> plunc/plvnc
  -> pres2lev on local slices
  -> write Xgui on ijb_u:ije_u or ijb_v:ije_v

关键通信点:

T/Q/U 的 pres2lev 传入 iip1,jjn_u;V 的 pres2lev 传入 iip1,jjn_v。湿度相对湿度转换调用 q_sat(iip1*jjn_u*llm,...),只覆盖本地 U/scalar 范围。

状态叠加

并行版和串行版同样按 U、T、P、Q、V 顺序处理,但只写本地段:

变量 本地范围 后续动作
U ijb_u:ije_u guide_addfield(ip1jmp1,...) 后写 ucov
T ijb_u:ije_u teta
Ps ijb_u:ije_u ps 后调用 pression_pmassdair_p
Q ijb_u:ije_u q
V ijb_v:ije_v guide_addfield(ip1jm,...) 后写 vcov

ini_anal 分支和串行版有同一疑点:源码把 V 初态写为 ugui2,不是 vgui2。并行版形式是 vcov(ijb_v:ije_v,:)=ugui2(ijb_v:ije_v,:)

输出诊断

guide_out(varname,hsize,vsize,field,factt) 是并行版最明显的 I/O 差异:

CALL gather_field(field, iip1*hsize, vsize, 0)
IF (mpi_rank /= 0) RETURN

因此只有 root 创建和写 guide_ins.ncfactt 是形式参数,但 当前源码体内没有使用它;forcing 量级仍由调用点传入 f_add/factt 决定。

并行输出还和串行版存在两个源码级差异:

Mars 边界

并行 guide 模块在 Mars 文档中的价值主要是边界和接口兼容:

路径 当前源码行为 是否经过 guide_p_mod
Earth + IOIPSL + ok_guide leapfrog_p 的 OMP master 调 guide_main,随后 barrier
Mars planet_type=="mars" leapfrog_p 不调 guide_main
Generic + ok_guide gcm.F 初始化读 relax.ncleapfrog_p 中还有 inline attenua

因此并行 Mars 排错时,ok_guide 本身不足以说明进入 guide_p_mod。应先确认 planet_typeCPP_IOIPSL、运行入口和是否有本地补丁。

相关页面