guide 压力层插值和 nudging 系数

源码范围:

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3d\guide_mod.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\guide_p_mod.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\misc\pres2lev_mod.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\misc\q_sat.F

Mars 运行参与度:接口兼容 + 条件边界。只有进入 guide_main 时才会经过本页逻辑;串行/并行 leapfrog* 中的 guide_main 调用受 CPP_IOIPSL + planet_type=="earth" 条件包围。Mars/generic ok_guide 初始化路径调用 relaxetat0("relax.nc"),不经过本页插值链。

调用时机

guide_main 首次进入时调用 guide_init,随后计算各变量的 nudging 系数:

factt = dtvr * iperiod / daysec
tau2alpha(v/u/T/P/Q, factt, tau_min_X, tau_max_X, alpha_X)

ini_anal=.TRUE.,首次调用会立刻 guide_interp(ps,teta),然后把 guide 目标场写回初始动力状态。常规运行中,只有 MOD(itau,iguide_int)==0 时才重新执行 guide_interp;两帧 guide 输入之间再用 tau=reste 做时间线性插值,后续叠加见 guide forcing 叠加到动力状态

guide_interp 总流程

guide_interp(psi,teta) 把读入的 guide 自然变量和压力层转换到 LMDZ 动力层目标场:

输入 ps/teta
  -> 构造 guide 输入压力层 plnc1/plnc2
  -> 计算模型层压力 pls,以及 U/V staggered 压力 plunc/plvnc
  -> 对 T/Q/u/v 调 pres2lev
  -> 把自然风转成 covariant 风,把温度转为位温
  -> 可选把相对湿度转为比湿

串行版全局处理 (iip1,jjp1)(iip1,jjm);并行版只处理当前本地 jjb_u:jje_ujjb_v:jje_v,并在需要跨纬向边界的压力平均前用 Register_SwapFieldHallo/SendRequest/WaitRequest 补 halo。

压力坐标构造

串行 guide_modguide_modele 二选一:

分支 guide 输入压力 plnc
guide_modele=.TRUE. apnc(l)+bpnc(l)*psnat(i,j)
guide_modele=.FALSE. apnc(l)

并行 guide_p_modguide_plevs 三选一:

guide_plevs 含义 guide 输入压力
0 纯气压层 apnc(l)
1 混合层 apnc(l)+bpnc(l)*psnat(i,j)
2 逐格点气压 pnat(i,j,l)

模型层压力先由当前 ps/teta 推导。串行版调用 pressionexner_hyb/exner_milieu,由 Exner 函数反推出层中心压力 pls=preff*(pk/cpp)**(1/kappa);并行版 guide_plevs=1 直接使用 (ap(l)+ap(l+1))/2 + ps*(bp(l)+bp(l+1))/2,其他分支调用 pression_pexner_hyb_p/exner_milieu_p

U/V staggered 压力来自质量平均:

pres2lev 插值

pres2lev(varo,varn,lmo,lmn,po,pn,ni,nj,ok_invertp) 是 COMMON misc/pres2lev_mod.F90 中的线性垂直插值:

  1. ok_invertp 为真,先把旧层压力和变量顺序倒置。
  2. 对每个新层压力 pn(k,ln) 找到旧层压力区间。
  3. 若新层在旧层范围之外,取最顶或最低旧层值。
  4. 否则按压力线性系数插值。

guide_interp 对各变量使用不同目标压力:

变量 输入变量 目标压力 输出
U unat1/2 plunc ugui1/2 = interpolated * cu
V vnat1/2 plvnc vgui1/2 = interpolated * cv
T tnat1/2 plsnc tgui1/2 = T*cpp/pk,若 guide_teta 则直接用输入
Q qnat1/2 plsnc qgui1/2,若 guide_hr 再乘饱和比湿和 0.01

U 和标量场在经向周期端复制第一个经度;U 的南北极行强制为 0。T/Q 标量场的极点值复制自相邻有效行。V 使用 jjm 纬向网格,不含标量网格的双极点行。

湿度限制

guide_hr=.TRUE.,guide 输入 Q 被解释为相对湿度百分比。guide_interp 调:

q_sat(np, temp, pres, qsat)
qgui = qgui * qsat * 0.01

其中 temp=teta*pk/cpppres=plsncq_sat.F 使用水/冰两套常数,以 temp <= 273.16 切换,先计算中间 zqsat,把它限制到 0.5,再用 zqsat/(1-retv*zqsat) 得到 kg/kg 的饱和比湿。

待确认:q_sat.F 注释写压力单位为 mb,但公式常数 611.14 和 guide 传入的 plsnc 都按 Pa 路径使用。当前页面按调用源码记录,不推断历史注释意图。

tau2alpha

tau2alpha(typ,pim,pjm,factt,taumin,taumax,alpha) 把天数单位的松弛时间转换成每步 nudging 系数:

alphamin = factt / taumax
alphamax = factt / taumin

有两类分支:

分支 行为
guide_regguide_add 先设为 alphamax;若 guide_reg,再用纬度/经度窗口的四个 tanh 因子平滑出区域权重。
默认 按 zoom 网格大小在 alphaminalphamax 之间插值;regular grid 或弱 zoom 时取 alphamin

默认分支先估算标量格点尺度 dxdys,再按 typ 得到 U 或 V staggered 尺度 dxdyu/dxdyv。首次调用用 zoom 中心 coordij(clon,clat,ilon,ilat) 得到 dxdy_min,扫描得到 dxdy_max,再计算 gamma。若不是 guide_add,最终把线性系数转为指数松弛:

alpha = 1. - exp(-alpha)

guide_add 保留 factt/tau 形式,因为后续叠加的是外部 forcing-like 场;普通 nudging 使用指数形式更接近“向目标场松弛”的权重。

串并行差异

环节 串行 guide_mod 并行 guide_p_mod
输入压力坐标 guide_modele 布尔 guide_plevs=0/1/2
工作范围 全局数组 jjb_u:jje_ujjb_v:jje_v 本地段
模型压力 pression + exner_* guide_plevs=1 直接混合层压力;其他分支 pression_p + exner_*_p
U/V staggered 压力 直接 massbar pext halo 后 massbar_p
逐格点输入压力 guide_plevs=2 使用 pnat1/2,V 网格前还需 halo
湿度转换 全局 q_sat(iip1*jjp1*llm,...) 本地 q_sat(iip1*jjn_u*llm,...)

correctbid

correctbid(iim,nl,x) 在串行和并行 guide 模块尾部都存在:如果 abs(x(i,l))>1.e10,用左右相邻点均值替换并打印 correction。源码搜索未找到活动调用,因此它是保留的局部修补 helper,不应写成 guide 主路径的一部分。

复现要点

  1. 先确认 guide_2D/guide_plevs/guide_modele/guide_hr/guide_teta,这些开关决定输入场解释。
  2. 对插值错误,先检查 invert_p 和 guide 输入压力层顺序,再查 pres2lev 的范围外取边界值逻辑。
  3. 对并行 U/V 差异,检查 pext/psnat/pnat halo 是否覆盖了本地 V 网格需要的相邻纬向行。
  4. 对 nudging 太强或太弱,先算 factt=dtvr*iperiod/daysec,再看 tau_min/maxguide_reg/guide_add 分支。
  5. 对湿度场,区分 guide 输入是相对湿度百分比还是比湿;guide_hr 会把百分比乘以 q_sat*0.01

相关页面