开头先交代一下背景:这篇文章是我在处理JRA55驱动WRF时踩了一圈回来之后的总结。如果你也正在用WRF做区域模拟,拿JRA55再分析资料当外强迫,却在WPS的ungrib这一步卡住,或者解出来的中间格式变量名全是VAR开头,那这篇内容基本就是为你写的。我会把“为什么JRA55会被当成非标准数据”“Vtable在中间起什么作用”“怎么一步步定制一份能跑的Vtable”这几件事讲透,顺带把我调试中踩过的坑一并列给你。
1. JRA55数据到底“非标准”在哪儿
1.1 先认门:JRA55是套什么样的数据
JRA55是日本气象厅做的第三代全球再分析资料,时间覆盖从1958年到现在,空间分辨率大约55公里,输出的网格是0.5625度的规则高斯网格,时间分辨率有3小时、6小时和月平均几种。因为时间跨度长、同化体系稳定,加上它在东亚区域的表现确实不错,很多人拿它来跑长时段的WRF模拟,尤其是降水个例、台风路径和区域气候变化这类研究。
用它的人多了,问题也集中暴露出来。最常见的翻车场景是:把下载好的JRA55 GRIB文件导进WPS,跑ungrib,出来的中间格式要么空荡荡,要么变量名全是VAR0、VAR1这种占位符。很多人第一反应是检查namelist.wps、检查文件路径、重新编译WPS,折腾半天之后才意识到,问题出在ungrib根本“不认识”这份数据的编码体系。
为什么说不认识?因为ungrib是一个靠编码匹配来工作的解码器,而JRA55早期的GRIB1数据,用的不是NCEP和ECMWF那种通用的GRIB参数表,而是JMA自己的本地参数表。ungrib拿着默认的Vtable.GFS去对照,里面写的是NCEP那套表号和参数号,JRA55的编码对不上,自然一个变量都认不出来。这就是大家说的“非标准数据”的实质。
1.2 ungrib不认JRA55的真正原因
ungrib的工作流程其实很老实:逐条读取GRIB记录,从每条记录里提取出参数编码和层次编码,再跑去Vtable里找匹配项。匹配上了,就按Vtable里规定的缩写把这条记录解码成WRF中间格式;匹配不上,就丢弃或者归入未知变量。
这里面最关键的一个概念是GRIB1的“表号+参数号”体系。GRIB1文件里的每个变量,都有一组编码,形如“表X参数Y”。NCEP发布GFS资料时,用的是WMO标准表里的通用编码,比如温度是参数11,U风是参数33,V风是参数34。而JRA55的GRIB1数据采用JMA本地表,温度变成了参数130,U风是131,V风是132。两边都对不上,ungrib如果把11当作温度去JRA55里找,当然是找不到的。
更麻烦的是,不只是参数号不同,级别类型也有差异。比如地面的表达方式,有的数据用的是level type 1,有的用105,有的用其他编号。Vtable里的匹配条件必须同时满足参数号和级别类型,任何一个对不上,这条记录就废了。所以处理JRA55,不能抱着“随便拿个模板改改”的心态,必须先看清数据本身的编码,再照着写。
2. Vtable是什么,定制前必须搞清楚的机制
2.1 Vtable在WPS流程里的位置
WPS由三个组件构成:geogrid负责生成模拟区域网格和静态地理数据,ungrib负责把气象驱动数据从原始格式解码成统一中间格式,metgrid负责把中间格式水平插值到模拟区域网格上。Vtable影响的是中间这步,也就是ungrib。
打个比方,ungrib像是一个翻译官,它本身不认识GFS、ERA5、JRA55这些五花八门的数据格式,它只认得GRIB编码。而你给它的那本“翻译词典”,就是Vtable。词典上写着“参数11是温度”“参数33是U风”,它才能把原始数据里的二进制记录翻译成WRF能听懂的中间格式。
所以,定制Vtable本质上不是写代码,是在写映射规则。你告诉ungrib:JRA55里编码129的字段,翻译成位势高度;编码130的字段,翻译成温度。规则写对了,后面metgrid和real才能正常干活。这个定位想清楚,后面所有步骤都是在这个框架下补细节。
如果你还没有装好WPS,建议先下载完整的WPS 4.x源码包,按标准流程编译好。注意一定要保留ungrib/Variable_Tables这个目录,里面那些官方模板后面大有用处,不一定要照搬,但可以当作命名和格式的参考。安装环节不需要特殊配置,只要编译器版本和netCDF依赖没问题就行。有朋友问过可否跳过Variable_Tables直接用默认模板,答案是不建议,定制Vtable这件事逃不掉。
2.2 把Vtable的每一列读明白
Vtable文件结构不复杂。文件第一行只有两个词:GRIB1或者GRIB2,表示后面的字段行按哪套规则解读。如果数据是GRIB1,就写GRIB1;是GRIB2,就写GRIB2。这一行写错,后面匹配全乱套。
对GRIB1版本来说,字段行从左到右依次是:
变量缩写 描述 单位 表号 参数号 级别类型 级别值举个例子,官方Vtable.GFS里常见这一行:
TT Temperature K 1 11 100 *意思是:任何GRIB1记录,只要表号是1、参数号是11、级别类型是100(等压面)、级别值任意,就把它解码成名为TT的温度场,单位是K。
对GRIB2版本,字段行的差别在于定位变量的方式从“表号+参数号”变成了“discipline+category+parameter”三连。格式长这样:
变量缩写 描述 单位 discipline category parameter 级别类型 级别值比如温度在GRIB2标准编码里通常是discipline 0、category 0、parameter 0,对应的字段行是:
TT Temperature K 0 0 0 100 *理解这个格式之后,你会明白一个核心逻辑:Vtable规则写得越宽,匹配越省事。级别值那一列写星号,意味着所有等压面层都接受,这是绝大多数情况下的合理选择。如果你非要精确到某个层次,也可以写具体数值,但一般没必要自找麻烦。
2.3 官方Vtable为什么覆盖不了JRA55
WPS自带的Variable_Tables目录里有Vtable.GFS、Vtable.ECMWF、Vtable.NCEP、Vtable.JMA等模板。很多JRA55新手会顺手拿Vtable.JMA来用,因为都是日本气象厅的产出,以为差不到哪里去。
实际试过就明白,Vtable.JMA是为JMA业务预报产品准备的,编码和JRA55再分析资料并不一致。JRA55虽然是JMA出品,但作为再分析资料,它有自己的参数定义方式,尤其是早期GRIB1版本的本地表,跟现行数值预报产品已经是两套体系。官方后来也试图在部分WPS版本里补一些JRA55支持,但面对不同分发平台反复转包、重新切片的数据,官方模板很难做到通吃。
所以,与其背靠官方模板碰运气,不如养成一个习惯:不管拿到哪份JRA55文件,先用工具把编码看清楚,再按自己的实际数据写一份Vtable。这也是本文后面所有操作的核心思想。
3. 手把手定制JRA55可用的Vtable
3.1 动手之前,先把数据底细摸清
拿到一份JRA55 GRIB文件,第一件事不是写Vtable,是看数据。你需要确认三件事:文件是GRIB1还是GRIB2,里面有哪些变量,每个变量的参数编码和级别类型是什么。
GRIB1数据就用wgrib检查。命令很简单:
wgrib JRA55_file.grib | head -30如果加上-V参数,能看到每条记录的详细编码信息,包括表号、参数号、级别类型、级别值。
GRIB2数据就用wgrib2:
wgrib2 JRA55_file.grib2 | head -30这两个工具都很小,网上很好找到,解压就能用。第一次查的时候建议把前几十条记录全部打出来,对照后面要写的Vtable逐条核对。数据底细摸清了,写Vtable其实就是机械劳动;反过来,如果省略这步直接上手编,后面极大概率要反复返工。
3.2 建立JRA55编码到WRF变量的映射表
看完成数据之后,下一步就是把JRA55的实际编码一一对应到WRF中间格式需要的变量名上。
WRF做区域模拟,从再分析资料里最需要的是三维场:气压、位势高度、温度、U风、V风、湿度。地面附近还需要表面气压,理想情况下也可以要2米温度、10米风这些地面变量,但不是必需。
我手头一份JRA55 GRIB1数据里,JMA本地表的编码规律大致是这样:
| WRF中间变量 | 变量含义 | JRA55 GRIB1参数号 | 典型级别类型 |
|---|---|---|---|
| GHT | 位势高度 | 129 | 100(等压面) |
| TT | 温度 | 130 | 100(等压面) |
| UGRD | U风分量 | 131 | 100(等压面) |
| VGRD | V风分量 | 132 | 100(等压面) |
| SPECHUMD | 比湿 | 133 | 100(等压面) |
| PRES | 地面气压 | 134 | 105或1(地面) |
| RH | 相对湿度 | 151 | 100(等压面) |
注意,这组参数号来自我实际接触过的一批JRA55文件,并不代表所有分发渠道完全一样。有的平台会把原始文件重新打包、重新标定表号,所以强烈建议你在自己的数据上用wgrib核对一遍,再把它落到Vtable里。不要嫌这一步麻烦,它才是整个定制过程里最不容易出错的地方。
3.3 写一份能直接用的Vtable文件
映射表确认之后,新建一个文件,比如叫Vtable.JRA55,然后把映射规则填进去。下面给我当时用的模板,方便你直接照改:
GRIB1 GHT Geopotential height m 2 129 100 * TT Temperature K 2 130 100 * UGRD U wind component m/s 2 131 100 * VGRD V wind component m/s 2 132 100 * SPECHUMD Specific humidity kg/kg 2 133 100 * PRES Surface pressure Pa 2 134 105 * RH Relative humidity % 2 151 100 *这里我把表号写成了2,对应JMA本地表。到底写1还是2,以wgrib输出为准。级别类型我写了100代表等压面,105代表地面,这也是最常见的两种,实际数据如果不同,照数据改就行。
把这份文件放到WPS目录下,然后通过软链接指给ungrib:
ln -sf /path/to/your/Vtable.JRA55 $WPS_DIR/Vtable如果你愿意,也可以不放进WPS自带的Variable_Tables目录,放在项目目录里统一管理。我习惯每个项目单独放一份,因为不同项目拿到的JRA55数据可能并不完全一样,独立存放方便追溯。
3.4 跑通ungrib,检查中间格式
Vtable就位之后,用link_grib.csh把GRIB文件链接到运行目录,再跑ungrib.exe。如果namelist.wps里没特别指定前缀,输出文件一般是FILE:开头,例如FILE:2019-08-01_00。
检查中间格式是定制Vtable流程里绝对不能省的一步。WPS自带一个小工具rd_intermediate.exe,在WPS的util目录下。运行后输入中间格式文件名,就能看到解出了哪些变量、每个变量有几层、单位是什么。
正常来说,中间格式里应当能看到GHT、TT、UGRD、VGRD、SPECHUMD,以及可能的PRES和RH字段,垂直层数和原始数据保持一致。如果看到变量名变成了VAR开头,或者某个字段缺失,说明映射规则还有问题,回头查参数号和级别类型。只要这一步通过了,定制工作就算完成,后面接metgrid和real就能顺畅走下去。
3.5 如果你的JRA55数据其实是GRIB2
现在很多JRA55分发渠道已经提供了GRIB2格式,尤其是近几年更新的数据。GRIB2的编码体系和GRIB1完全不同,它用discipline、category、parameter三组数字来定位一个变量。好消息是,GRIB2里气象要素的编码在全球各大中心基本统一,不像GRIB1那样各搞一套本地表。
JRA55的GRIB2版本里,温度、风、比湿、位势高度这些标准变量,用的都是WMO标准GRIB2编码。所以它的Vtable写起来反而简单,直接参考官方GRIB2模板的结构就行。文件第一行写GRIB2,字段行依次是变量缩写、描述、单位、discipline、category、parameter、级别类型、级别值。
一个参考模板:
GRIB2 PRES Pressure Pa 0 3 0 100 * TT Temperature K 0 0 0 100 * UGRD U wind component m/s 0 2 2 100 * VGRD V wind component m/s 0 2 3 100 * GHT Geopotential height m 0 3 5 100 * SPECHUMD Specific humidity kg/kg 0 1 0 100 *拿到GRIB2数据时,问题往往会跑到别的地方,比如文件时间标签和文件名对不上,或者同一个变量被切成了多个文件。Vtable本身反而不太容易出错。但无论如何,先wgrib2看一眼再动手,这个习惯不会亏。
4. 实战避坑指南与问题速查
4.1 最常见的翻车:变量全部变成VAR开头
定制完Vtable第一次跑ungrib,最容易遇到的现象是中间格式里生成了一堆VAR0、VAR1。看起来解出了变量,但名字全是VAR,后续流程根本用不了。这说明ungrib已经读到了GRIB记录,却在Vtable里找不到任何匹配规则,只能把它们当作未知类型处理。换句话说,就是参数号、表号、级别类型里至少有一个对不上。
遇到这种情况,不要一份份去试模板,直接回到数据本身。用wgrib加-V参数把前几条记录的完整编码打出来,和Vtable里面的表号、参数号、级别类型逐一比对。我见过最低级的错误是表号写错一位,JRA55实际是2,Vtable里写了1;还有把地面气压的级别类型写成100,导致它被当成等压面层去匹配,永远匹配不上。这类问题往往只差一个数字,但排查起来特别磨人,所以把数据底细摸清永远是最省时间的第一步。
4.2 中间格式有了,metgrid却报缺变量
有时候ungrib跑得挺顺利,中间格式里也有变量,结果跑到metgrid却报缺GHT、缺RH之类。这种问题通常不是字段缺失,而是Vtable第一列的变量缩写和WRF的约定不一致。
WPS中间格式里变量名有固定的习惯写法。位势高度是GHT,温度是TT,比湿是SPECHUMD,相对湿度是RH,水平风是UGRD和VGRD。如果你按数据原始名字去写,比如把位势高度写成了HGT,把比湿写成了Q,ungrib虽然能解出来,但metgrid会把它当成陌生变量忽略,后面real就拿不到驱动场。说穿了,Vtable第一列不是写给数据看的,是写给WRF后续流程看的,必须遵守命名习惯。
拿不准缩写的时候,直接翻开官方Vtable.GFS对照一下,用官方模板那一列的名字。这是我一直在用的偷懒办法,也是最稳妥的办法。
4.3 JRA55垂直层与地面场的特别提醒
JRA55的等压面文件一般覆盖1000百帕到1百帕,对绝大多数WRF模拟场景都够用。但要注意,有些分发平台会把等压面场和地面场拆成不同文件,甚至一个变量按时间切片拆成多个文件。link_grib.csh链接文件时,如果文件顺序不对,ungrib处理出来的时间标签会乱。这个问题在长期模拟里特别隐蔽,不容易被发现,等跑到一半发现边界条件错位就晚了。
另外,如果只是拿JRA55当边界条件,等压面三维场加表面气压就够了,2米温度、10米风属于可选项。但做嵌套模拟或者想对陆面初始化更精细一点,地面附近这几个变量最好还是补上。补充方法跟前面完全一样,用wgrib确认参数号和级别类型,往Vtable里追加几行,重新跑ungrib,再用rd_intermediate确认变量出现,再接metgrid。
4.4 问题速查表
把我实际踩过、以及帮人排查过的高频问题整理成了表,方便快速对照:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| ungrib解出大量VAR开头变量 | Vtable参数号或表号与数据不一致 | 用wgrib -V核对并修正Vtable |
| ungrib解不出任何变量 | 数据格式判断错误,GRIB1当GRIB2写了 | 确认文件类型,改Vtable首行 |
| metgrid报缺GHT | 变量缩写写错,比如写成HGT | 改为WPS标准缩写GHT |
| metgrid报缺RH | 只有比湿没映射,或缩写成Q | 补RH或SPECHUMD映射行 |
| 中间格式时间混乱 | link_grib.csh链接顺序不对 | 统一文件名前缀,按时间排序 |
| 垂直层数少了一半 | Level Type写错,比如把100写成1 | 用wgrib确认级别类型 |
这个表看起来很简单,但每一条背后都是真金白银的调试时间。特别是最后一条,很容易让人误以为数据下载不完整跑去重新下,其实就是一个级别类型写错的问题。
最后说一点个人习惯。我现在不管用哪家再分析资料,都会先花十分钟把数据编码完整打出来看一眼,再决定用什么模板、改什么映射。这个习惯帮我省下了很多次深夜改文件的精力。如果你手头项目要长期用JRA55跑批量模拟,验证好的Vtable最好连同数据说明一起存进项目目录,换机器、换WPS版本的时候直接拿来用,能省不少事。