观潮 · 模式预报与气象 AI 观察
obs_nudge 开了却零效果:不是 WRF 的 bug,是观测文件记录格式写错了
这是一个完整的排障案例:观测 nudged(Nudging)技术在 d02 上完全不起作用,obs_coef_wind 已经调到正常值的 100 倍,多天累积下来仍然逐比特完全一致——不是"效果很小",是"和关掉 nudging 一模一样"。
最后定位到的原因不在 WRF,而在提问者自己的观测文件转换程序:写了 FORMAT 105 的头,却只输出了 FORMAT 104 的数据。WRF 读到头之后按 105 去读一个 217 字符的行,实际给的只有 145 字符。
症状:所有"正常"信号都对,唯独效果是零
提问者的配置情况:
- d01:
dx = 15 km,grid_fdda = 1,grid nudging 朝 MSM+FNL hybrid analysis 做,这部分是正常工作的,和无 nudging 的基线相比能测出差异。 - 想在两个域上都加地面站点(AMEDAS,日本)观测 nudging,用相同的
OBS_DOMAIN101/OBS_DOMAIN201配对。按指南的说法,跨域用相同内容是可以的,因为 WRF 会忽略域外的观测。 obs_coef_wind = 6.0e-2, 6.0e-2,注释里写明是故意设成正常值的 100 倍用于诊断。
验证方法是把这次的 d02 输出和另一份其他设置完全相同、只把 obs_nudge_opt 设成 0,0(仅 d01 做 grid nudging、不做任何 obs nudging)的运行做对比:提取 ~150 个 AMEDAS 站点的 10 米风,算 bias/RMSE/MAE。结果两个算例逐比特一致。
「逐比特一致」这个结果本身就是最强的线索
提问者这次的验证设计很值得学。他不是看某个站的某个时刻差多少,而是:
- 提取约 150 个 AMEDAS 站点的 10 米风,逐站逐小时做对比;
- 与
obs_nudge_opt=0,0的基线算例比较 bias/RMSE/MAE; - 结论是聚合统计量匹配到 16 位有效数字,逐站逐小时的原始时间序列完全相同。
他的推理是:模式的动力学是混沌的。只要 nudging 施加了任何非零扰动,哪怕传播得不完美,也应该在双精度上出现极小的非零偏离。 逐位完全一致意味着 nudging 项在数学上根本没有进入状态更新。
这个判据比"NSTA > 0"强得多。NSTA > 0 只说明 WRF 认为它在处理站点,不说明它写进去了。而且他也特意做了对照:d01 的 grid_fdda = 1 朝 MSM+FNL hybrid analysis 的 grid nudging 是正常的,和基线能测出差异——这就把"模式本身有问题"和"观测 nudging 这一路有问题"分开了。
另外一个设计细节:他故意把 obs_coef_wind 设成 6.0e-2 s⁻¹(正常值的 100 倍,e 折叠时间约 17 秒)。这是个很激进的诊断值——如果 nudging 真的在工作,这么大的系数应该产生肉眼可见的强烈约束。系数放大 100 倍还完全没效果,基本排除了"系数太小、效果被淹没"这一类解释。
六项排查全部通过,这才暴露了真正的方向
提问者做的排查很完整,六项都过了:
检查项 · 日志证据
观测文件被正确打开 · `opening first fdda obs file, fonc=01 inest= 1` / `inest= 2` 都出现
ERROB 被调用 · `rsl.error` 里 `CALL ERROB` 对 INEST=1 和 INEST=2 都有,`NSTA` 始终 > 0(d01 约 130、d02 约 120)
nudging 初始化块正常 · `OBSERVATION NUDGING IS ACTIVATED FOR MESH 2` / `END SETUP DESCRIPTION ... MESH 2` 正确打印,`TWINDO (hrs) = 0.500` 等确认了d02 的逐域 namelist 值被正确读取
调用链手工核对 · 追踪 `wrf_fddaobs_in` → `in4dob` → … → `fddaobs_driver` → `errob`/`nudob`(在 `module_fddaobs_rtfdda.F`),并手工把 `SUBROUTINE nudob(...)` 的哑参数列表和实际 `CALL nudob(...)` 的实参列表抽出来做了逐位置比对
站点循环没有卡住 · `n=n+njcsnd`(遍历 NSTAT 个观测的循环增量)存在且正确,没有反复处理同一个站点
水平权重设置 · `rindx` 在 d01 打印为 2.0(30 km / 15 km dx,正确),d02 的水平权重设置看起来也一致
到这里,提问者的结论是:既然所有检查都过了,还有什么能导致 nudging 倾向项对模式状态零影响——即使系数是正常值的 100 倍、跨越多天?
真正的原因:FORMAT 104 的数据配了 FORMAT 105 的头
提问者自己追踪到了根因,并明确说明这不是 WRF 的 bug,是他自己观测文件生成程序里的格式不匹配。
wrf_fddaobs_in.F 的 in4dob 例程中,数据记录的结构按 is_sound 分支:
`is_sound` · 对应观测类型 · 数据格式
`.TRUE.` · 高空/探空(upper-air/sounding) · **FORMAT 104**,6 个变量/QC 对
`.FALSE.` · 地面、单层(surface, single-level) · **FORMAT 105**,9 个变量/QC 对
FORMAT 105 的 9 个变量依次是:SLP(海平面气压)、参考高度、气压、温度、U、V、RH、地面气压、降水。
他们的问题具体是:转换程序正确写了 is_sound=.FALSE. 的头(因为观测确实是地面站),但每条记录只输出了 6 个变量/QC 对的数据——也就是 FORMAT 104 的内容配在了 FORMAT 105 的头下面。WRF 读到头,看到 is_sound=F,于是期待一个 217 字符的 FORMAT 105 数据行,而实际给的行只有 145 字符。
定位手段是在 ERROB 里的 VAROBS/ERRF 周围加了临时打印语句。
修复方式是把转换程序改成输出完整的 9 对 FORMAT 105 记录(用不到的槽位填标准缺失值 -888888)。改完之后 innovation 变得物理上合理,nudging 前后的对比也恢复正常。
具体怎么改:缺失值怎么填
FORMAT 105 需要 9 个变量/QC 对,而提问者的原始文件只有 6 个。用不到的槽位必须填值,不能留空——标准缺失值是 -888888。
修复后他做了两项确认:
确认项 · 修复前的状态 · 修复后
innovation(观测减模式) · 物理上不合理 · 变得物理上合理
nudging 前后对比 · 与关掉 nudging 完全一致 · 恢复正常
第二项是关键:"恢复正常"意味着 nudging 真的进了状态更新,而不只是数值上出现了非零差异。
排查这个症状应该先看什么
提问者在最后给了一条很具体的经验:
> 对于碰到"明明有 NSTA>0 但就是零效果"这个症状、并且用的是地面观测的人:在往其他任何地方查之前,先检查你数据行的字节长度与in4dob对你is_sound设置所期望的是否一致(地面 105,探空 104)——这个失效模式不产生任何诊断信息。
这一条值得单独强调:这个失效模式不产生任何诊断信息。这解释了为什么提问者前面六项检查全都正常——因为 WRF 侧确实一切正常,它只是没拿到足够长的数据行,然后静默地什么都没做。
一个值得单独记住的坑
提问者在排查过程中还踩到了另一个坑,值得单独列出来:
auxinput11_interval_s = 60, 60原来写成了单值而不是逐域给值。obs_rinxy/obs_twindo/obs_ionf同样原来给的是单值而不是逐域。
这两个他都在提问后按 Brian Reen 的《A Brief Guide to Observation Nudging in WRF》里记载的 pitfall 修正了。也就是说,同一个案例里其实有两个独立的问题——观测文件格式(真正的根因)和 namelist 逐域值写法(一个会被检查出来的配置错误)。
作者承认的限制
提问者的六项排查全过,但这个「全过」本身有局限。 他手工比对了 nudob(...) 的 84 个实参/哑参列表,这一步工作量极大也极可靠,但它验证的是接口接线,而不是数据内容。格式长度问题恰好属于"接线全对、数据不对"这一类,所以他的排查方式在原理上就查不出这个问题。
「零效果」有多种可能原因,帖子只覆盖了一种。 提问者在提问时其实还问了另一个方向:grid_fdda 在父域 + feedback=1 + 子域 obs_nudge_opt 之间是否存在已知交互。这个问题在帖子里没有得到回答。也就是说,如果有人的症状同样是零效果、但观测文件行长度是对的,那么这个帖子的经验不适用。
论坛回复不是 WRF 官方支持渠道的正式文档。 提问者和答复者都是论坛用户,解决方案是提问者在自己环境里验证过的,换一个观测体系(比如不是地面单层站)FORMAT 的具体内容会不同。
另外,这条经验的可复现性有边界:提问者验证的是"FORMAT 104 内容 + FORMAT 105 头"这个特定组合。如果你的症状同样是零效果,但文件行长度对得上,那大概率是另一个原因,得继续往 grid_fdda 与 feedback=1 的交互、或者观测文件里缺变量这些方向查——提问者在提问时其实也问到了 grid_fdda 在父域 + feedback=1 + 子域 obs_nudge_opt 之间是否存在已知交互,但这个问题的答案在帖子里没有被回答。
一句话判断
"nudging 开了没效果但所有日志都正常"这类问题的排查优先级应该是:先量数据行字节长度,再查调用链——因为格式不匹配是唯一一种能骗过全部常规检查、且完全不产生诊断信息的失效模式。这次是提问者自己在 VAROBS/ERRF 加打印才定位到的,WRF 侧给不出任何提示。