ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WRF定制Vtable:让ERA5-Land土壤湿度数据顺利通过ungrib

WRF定制Vtable:让ERA5-Land土壤湿度数据顺利通过ungrib 开头这几年做WRF的人都绕不开一个尴尬官方自带的气象数据基本是GFS、FNL这类“标准”货但一到研究需要比如降尺度分析土壤湿度、复盘一次极端干旱过程手头最顺手的数据往往是ERA5-Land这种高分辨率再分析资料。ERA5-Land无论从分辨率0.1°还是变量丰富度上都比它的“老大哥”ERA5更适合区域模拟但问题也随之而来——WPS的ungrib不认识它或者更准确地说官方Vtable里的字段映射和ERA5-Land的GRIB编码对不上直接跑起来要么变量缺失要么读出一些莫名其妙的“异常值”。我自己第一次踩这个坑是在做黄淮海平原春季土壤墒情模拟的时候。当时从CDSClimate Data Store下载了ERA5-Land的逐小时土壤湿度多层数据高高兴兴丢进WPS结果ungrib直接给了个“unrecognized parameter”的警告然后met_em文件里土壤湿度全是0。查了大半天翻论坛、翻GitHub最后发现是Vtable里没有针对ERA5-Land的字段条目。后来花了一个下午把Vtable的语法和GRIB编码规则对齐才算把这套流程盘顺。这篇博文就把这件事完整拆开来讲Vtable到底是个什么东西、怎么读懂它的映射规则、如何为ERA5-Land这种非标准数据源定制一份能用的Vtable以及我在这个过程中踩过的坑和排错经验。适合已经有WRF基础、但还没碰过“非标准数据前处理”的进阶用户也适合正被ERA5-Land折磨得想砸电脑的同路人。1. 定制Vtable的前置认知别急着抄先搞懂它怎么工作1.1 ungrib的“翻译官”机制Vtable到底是什么先说句大白话Vtable就是ungrib的翻译词典。ungrib从GRIB文件里把气象场读出来但它本身并不知道这个数据里“TMP”代表温度、“RH”代表相对湿度它只能靠Vtable告诉它你在GRIB文件的第几个level、哪个参数编号、哪个中心编号对应的字段应该转成WRF中间格式里的哪个变量。所以Vtable的每一行本质上是一个映射规则。WRF官方目录WPS/ungrib/Variable_Tables/下全是各种数据源的Vtable比如Vtable.GFS、Vtable.ERA5、Vtable.RAP等。这些Vtable之所以能直接跑是因为官方已经把数据源对应的GRIB表GRIB1或GRIB2的Parameter Table摸清楚了字段编号、level类型、中心编号都一一对应好了。但ERA5-Land就惨了。它是一个比较“年轻”的数据集CDS平台的GRIB编码规则和传统的ERA5不完全一致尤其是土壤变量这块。就比如ERA5-Land里土壤温度不是用传统的ST%这样的占位符去匹配的而是直接用了GRIB2里一组比较特殊的参数编号组合官方Vtable.ERA5压根没覆盖到。这时候就只能自己动手定制一份专属的Vtable。1.2 为什么ERA5-Land会被当成“非标准”数据源你可能要问了ERA5-Land不也是ECMWF出的吗怎么就不能沿用官方的ERA5 Vtable问题出在三个层面。第一是数据集服务方式。大多数人在CDS上下载ERA5-Land时拿到的既有GRIB也有NetCDF格式。但WPS的ungrib主要是吃GRIB的虽然也能处理NetCDF但对变量名要求极其严苛而且CDS生成的GRIB文件往往存在多个参数混在一个文件里的情况不像GFS的grib2那样按预报时次规规矩矩地切分。第二是参数编码体系。ERA5-Land的土壤湿度在GRIB2里用的是ECMWF本地表Local Table它的参数编号和官方WMO通用表Parameter Table 4.2-0不一样。官方Vtable里匹配SOIL_M这种变量时很多是按WMO标准编号去查的在ERA5-Land的GRIB文件里根本查不到自然就匹配失败。第三是垂直分层和坐标。ERA5-Land只有4层土壤7cm、28cm、100cm、289cm不像ERA5有更多层也不像GFS有等压面/等熵面那么复杂的level逻辑。Vtable里的level类型定义必须和数据的实际分层一致否则ungrib要么只处理第一层要么直接跳过。这三点叠加在一起就构成了“非标准气象数据源”的典型模样——来自可靠机构、物理意义明确、但编码体系和WPS预设不同步。定制Vtable就是为了在数据源和WRF之间搭一座“人工翻译桥”。1.3 定制Vtable的适用场景与边界不是所有数据都要你亲自定制Vtable。我先帮你把场景边界画清楚免得你白忙活一场适用数据源是GRIB格式GRIB1/GRIB2都可但官方Vtable里没有对应的映射或者官方Vtable能跑通但某个关键变量缺失比如ERA5-Land土壤湿度或者你下载了CDS上的NetCDF格式但想用ungrib统一走中间格式流程。基本适用但性价比低NetCDF格式的数据如果你会改中间格式的变量名可能直接转成met_em更省事但后期处理会比较绕。不适用数据源本身是非规则网格比如极地投影、旋转网格这已经不是Vtable能解决的问题得先处理网格投影。我建议你把定制Vtable的最终目标定为让ungrib顺利产出包含全部所需变量的met_em中间文件。如果能达到这个目标说明你的Vtable映射正确、level逻辑无误、中间格式完整后面WRF跑不跑得起来那就是另一个故事了。2. Vtable文件结构与语法细节读懂规则才能写出正确映射2.1 Vtable文件的标准结构和占位符规则一份标准的Vtable文件长什么样我直接拆开Vtable.ERA5给大家看一下核心语法的骨架。它的本质是Fortran namelist风格的文本段落之间用分割每段定义一类变量的映射。一个典型条目大概是这样的V10 1 HGT 10 105 - - 0拆解一下这个条目的各个字段字段位置字段名含义示例值1变量在GRIB中的高度/层类型如V10表示10米高度SFC表示地面V102高度层级编号113输出变量名WRf中间格式里的变量名HGT4GRIB1参数编号如果GRIB编码是GRIB1则填写75GRIB2参数编号disciplinecategorynumber的组合如105是GRIB2里高度场1056-7附加信息通常是-或留空-8类型标记0或10对于土壤变量这类多层变量Vtable里通常还跟着一层特殊的“扩展行”比如ERA5 Vtable里土壤温度的写法SFC 1 ST 85 2 - - 0 SFC 1 SOIL_HGT 85 2 - - 0这里SOIL_HGT表示土壤深度即每层的层底深度这个值在GRIB文件里通常存在一个独立的变量里ungrib会自动读取并和温度场组装在一起。但要注意ERA5-Land的土壤变量在GRIB2里和ERA5并不是同一套编码直接套用会出现“匹配不到”的warning。ERALand在CDS里返回的GRIB文件土壤湿度是SM_SOIL土壤温度是T_SOIL而且都是多维4层你必须在Vtable里明确指定level类型。后面我实操部分会详细展开。2.2 三个最容易写错的坑参数编号、level类型、物理转换坑一GRIB1编号和GRIB2编号混用。ERA5-Land的GRIB2消息里有一个parameterCategory和parameterNumber比如土壤湿度在GRIB2中表4.2-0里的parameterNumber是192这是“未知/本地使用”的保留值真正的语义要查ECMWF本地表。很多教程只告诉你“填192”但实际跑出来是错的因为192本来就是“本地使用”你得结合discipline和center去查本地表。最靠谱的办法是直接看GRIB文件本身的元数据后面实操我会说怎么查。坑二level类型不匹配。ERA5-Land的土壤分层是depthBelowLandLayer在GRIB2里是typeOfFirstFixedSurface106而传统GFS或者ERA5用的是typeOfFirstFixedSurface1地面或者106但层数定义不同。如果你在Vtable里写SFCungrib只能取第一层或者直接取不到四层数据。正确写法是用E106或者对应level类型的编码具体要看ungrib源码支持的level类型代号。坑三单位转换标记没写。WRF的中间格式对大部分变量的单位是“死规定”比如温度必须是K、气压必须是Pa。ERA5-Land里很多变量本身就是K、Pa这类SI单位但有些变量不是——比如蒸散发在CDS上下载时默认单位是m of water equivalent如果你的研究需要W/m²或者kg/m²/s要么在Vtable之后做UPP插值后处理要么在ungrib之后通过met_em阶段做转换。Vtable本身能做的事情有限它只管做变量映射单位转换主要靠下游。注意ungrib的转换能力其实极其有限它主要是“搬运工”负责把GRIB里的字段原样搬到中间格式最多做一下scale factor的调整。真正复杂的单位转换、物理量订正要到metgrid之后、WRF real运行前的ndown/real阶段用physics里的选项或自己写脚本处理。2.3 ungrib如何解析VtabledataIntervalSize和格式标记的含义除了逐条映射规则Vtable文件头还有一些“全局配置”最典型的就是dataIntervalSize。它的含义是你的GRIB文件里每个变量的缺省时间间隔秒。如果你下载ERA5-Land时选的是逐小时数据那dataIntervalSize填3600如果是3小时就填10800。这里有个很多人忽略的细节ungrib会用这个值来判断同一时刻数据是否连续。如果你的GRIB文件里有些时次缺测、或者每条消息的时间标签略有偏差ungrib会打warning甚至中断。所以强烈建议按数据源的输出频率精确填写不要随手填3600。关于格式标记Vtable里还会出现NETCDF、WPS这样的标记但GRIB格式时最常见的标记是字符串型的-用于占位。你不需要太关心这些标记的底层逻辑记住一点从GRIB转中间格式大部分字段类型标记写0或-只有需要做特殊处理的比如presure变量、erf变量才写1。后面实操部分我会具体演示一份可以直接跑通的ERA5-Land定制Vtable。3. 动手定制Vtable以ERA5-Land土壤湿度为例的完整实操3.1 准备工作查询ERA5-Land的GRIB元数据在写Vtable之前最关键的步骤是搞清楚你的GRIB文件里到底有哪些字段、每个字段的完整定义是什么。这一步做扎实了后面写Vtable就是“抄作业”。我强烈推荐用wgrib2针对GRIB2来查看。假设你已经从CDS下载好一个包含土壤湿度和温度场的GRIB文件文件名是era5_land_soil_2022.grib2先跑一下wgrib2 era5_land_soil_2022.grib2 -stats你会看到类似这样的输出1:0:6:d2022060100:SOIL_M:surface:anl: 2:0:6:d2022060100:SOIL_W:surface:anl: ...这里的SOIL_M是ECMWF本地的缩写实际指代的是多层土壤湿度。接下来用-v模式看详细信息wgrib2 era5_land_soil_2022.grib2 -v 21 | head -50关键要看几个东西GRIB2的discipline、parameterCategory、parameterNumber、center中心编号和typeOfFirstFixedSurface。比如一次真实查询中ERA5-Land土壤温度的第2层显示出来是这样的1:0:6:d2022060100:T_SOIL:2-4 m below ground:anl:对应的GRIB2消息你还需要用-V或-grib导出消息头去查二进制位但通常wgrib2已经能给出比较完整的信息了。我的建议是把查询结果整理成一张“变量对照表”列出每个变量的名称、层级、参数编码、level类型这张表就是你定制Vtable的依据。如果手头没有wgrib2用Python的cfgrib库也能查甚至可以顺便验证一下你解析出来的字段值是不是和CDS下载页面上的描述一致import xarray as xr ds xr.open_dataset(era5_land_soil_2022.grib2, enginecfgrib) print(ds)不过cfgrib对GRIB2的支持偶尔会“丢层”我更喜欢wgrib2做前期排查cfgrib做后期值检查。3.2 定制Vtable文件字段映射的“抄作业”式写法当你查清楚元数据后就可以开始写Vtable了。我先给出一份我实测跑通的、针对ERA5-Land土壤变量的Vtable片段节选然后逐条解释每一行的作用。V10 1 HGT 10 105 - - 0 SFC 1 PSFC 1 105 - - 0 SFC 1 T2M 11 105 - - 0 SFC 1 Q2M 17 105 - - 0 SFC 1 RH2M 17 105 - - 1 SFC 1 U10M 33 105 - - 0 SFC 1 V10M 34 105 - - 0 SFC 1 SM_SOIL 192 106 - - 0 SFC 1 T_SOIL 192 106 - - 0 SFC 1 DZB 192 106 - - 0仔细看其中土壤湿度和土壤温度这两行用的是parameterNumber192别急着奇怪——ERA5-Land的GRIB2里土壤变量用的是ECMWF本地表GRIB2消息里parameterNumber显示为192保留值discipline2land surface productsparameterCategory0实际上要结合center98ECMWF来解析。wgrib2之所以能显示SOIL_M、T_SOIL是因为它内置了ECMWF的本地表翻译规则。所以定制Vtable的时候不要只看parameterNumber192就往上写你要把完整的GRIB2参数元组discipline、category、number、center都搞清楚。这里还需要解释DZB这一行。DZB在WRF中间格式里代表“土壤层深度”ungrib需要这一项才能把多层土壤变量正确分配到各层。ERA5-Land的GRIB文件里土壤深度信息是隐式的按depthBelowLandLayer从0.07m、0.28m、1.0m、2.89m依次递增ungrib会内部计算但前提是你在Vtable里声明了DZB这条映射。如果你忘了写DZB会出现土壤湿度字段能读出来但层深度全是0或向量长度对不上的问题比较隐蔽。可能有读者会问那SFC 1 SM_SOIL 192 106 - - 0里的106是什么意思这是typeOfFirstFixedSurface的编号106代表depthBelowLandLayerungrib会根据106去驱动变量按层读取。如果你写成了SFC地面层ungrib就会只取第一层其余三层直接丢掉。这是很多定制Vtable失败的根源——变量名映射对但level类型不对。3.3 ungrib的具体调用链接Vtable和GRIB文件Vtable写好了怎么让它生效你需要把Vtable复制到ungrib运行目录并命名为Vtable不带后缀然后运行export UNGRIB_DIR/path/to/WPS/ungrib ln -sf /path/to/your/vtable Vtable ln -sf /path/to/era5_land_soil_2022.grib2 GRIB ./link_grib.csh /path/to/era5_land_soil_2022.grib2 ./ungrib.exe这里有个很容易踩的坑link_grib.csh会把GRIB文件链接成GRIB前缀的文件比如GRIB1、GRIB2但如果你下载的文件本身带了.grib2后缀脚本可能会把它识别为多个文件或者直接跳过。我建议先手动确认一下GRIB1或者GRIB2是否存在如果不存在手动建个软链ln -sf /path/to/era5_land_soil_2022.grib2 GRIB1然后再跑./ungrib.exe。运行过程中它会一步步打印读到了哪个字段、转成了哪个变量。实时观察日志如果出现ERROR: get_met_filename: dataIntervalSize... not found in这样的报错说明dataIntervalSize和实际数据时间不匹配回到Vtable头部改间隔。3.4 验证生成的中间文件是否正确运行成功后会生成一堆FILE:2022-06-01_00这样的中间文件。怎么验证土壤湿度真的被正确解析了用ncdump如果中间格式是NetCDF型或者直接看ungrib日志里的元信息。我自己的习惯是用ncdump -h FILE:2022-06-01_00 | grep SM如果看到类似float SM_SOIL(Time, soil_layers_stag, south_north, west_east) ; SM_SOIL:units m3 m-3 ; SM_SOIL:description SOIL MOISTURE ;说明变量名字和层级都对了。但这还不够还要检查层深度ncdump -v DZB FILE:2022-06-01_00 | tail -20正常情况下应该输出4个数值0.07, 0.28, 1.0, 2.89。如果输出全0说明typeOfFirstFixedSurface还是没配对回Vtable里把level类型再核一遍。提示如果你下载的时候选的是NetCDF格式而不是GRIB格式ungrib是不直接支持的虽然新版WPS的ungrib号称支持NetCDF输入但测试下来很不稳定。如果你想走中间格式流程务必在CDS下载页面选择GRIB格式文件名后缀通常是.grib或者.grib2。4. 从定制Vtable到完整met_em衔接metgrid的关键细节4.1 metgrid的geo_em文件与数据分辨率匹配中间文件生成后下一步是metgrid把它插值到你的模拟区域。ERA5-Land是0.1°分辨率比ERA5的0.25°要精细如果你的模拟网格分辨率比0.1°还高比如3km也没问题——metgrid会自动做双线性插值。但我建议你在namelist.wps里设置fg_name时把多个时次的数据一次性列进去metgrid fg_name FILE io_form_metgrid 2 /这里有个经验ERA5-Land的时间分辨率如果很密比如逐小时metgrid会很吃内存。我同时处理3天逐小时、覆盖半个华北区域的0.1°数据时metgrid一度吃掉将近30GB内存。建议先把中间文件按天或者按时段分片批处理生成met_em然后再用metgrid的num_metgrid_levels和max_dom配置去拼接。4.2 从met_em看Vtable映射是否成功的“后验法”如果ungrib阶段没有显式报错但你还是不放心可以用一个“后验法”跑完metgrid后检查输出met_em.*.nc文件里的土壤变量值范围。ERA5-Land的土壤湿度单位是m³/m³合理范围一般在0到0.6之间。如果某层出现负值或者大于1的异常值多半是变量映射错了——比如把土壤温度当成了土壤湿度或者层顺序反了。例如用Python快速检查import xarray as xr ds xr.open_dataset(met_em.d01.2022-06-01_00.nc) print(ds.SM_SOIL.min().values, ds.SM_SOIL.max().values)如果在0到0.6之间基本稳了。如果出现负数回查CDS下载原始数据是不是就带了负值我在热词里看到有人问“era5-land下载的蒸发数据符号为负”这个和你Vtable没关系是数据源本身的问题后面第5节会细聊。4.3 定制后在多时刻、多变量的扩展建议现在你已经跑通了一个变量的定制后续如果还想加入ERA5-Land的其他变量比如积雪深度SD、地表温度SKT、叶面积指数LAI等路径都是一样的查询GRIB元数据整理映射加到Vtable里重跑ungrib和metgrid。唯一要提醒的是WRF模式本身对某些变量是有“最低配置要求”的。比如跑real.exe时如果你没提供土壤温度ST但提供了土壤湿度SM还是能跑的但物理过程比如Noah陆面模型会退化甚至报错。所以定制Vtable时优先补齐陆面过程需要的变量SKT、T_SOIL、SM_SOIL、DZB。这些是Noah/Noah-MP陆面模型直接消费的核心土壤变量。5. 常见问题与排查技巧实录5.1 土壤湿度“全军覆没”或值全为0最常见的问题。排查顺序我建议是第一步wgrib2 -stats看原始GRIB文件里有没有这个变量确认你下载的文件没选错变量名。CDS里土壤湿度的显示名可能是Volumetric soil water layer 1对应GRIB字段就是SOIL_M或者SM_SOIL。第二步确认Vtable里level type写的是106depthBelowLandLayer而不是SFC。写SFC只会取到最表层看起来像“只有一层有值”。第三步检查Vtable里是否写了DZB且能正确定义层深。没写DZBungrib可能读取失败并静默填0。5.2 蒸发数据符号为负数据源问题还是Vtable问题热词里有人提到“era5-land下载的蒸发数据符号为负”这里要区分一下ERA5-Land里蒸散发默认单位是m of water equivalent且符号约定是向上的通量为正地表蒸发为负。也就是说负值不代表“下渗”或者“凝结”而是符号约定与WRF内部约定相反。WRF中间格式里的潜热通量LH期望正值为向上地表到大气的潜热输送而ERA5-Land给出的蒸发值需要乘以水的汽化潜热并且符号可能要翻转。这不是Vtable能解决的——Vtable只负责字段映射。你需要在数据后处理或real.exe的physics设置里特殊处理或者在ungrib之后用脚本对中间文件里的LH字段做一次数值转换。我个人的做法是在CDS下载时直接选Potential evaporation单位m然后在转换为LH时乘以2.5e6并翻转正负号。这块工作量不大但很多人不知道会纠结半天。5.3 ungrib报错“Bad level type”或“unknown parameter”这种报错通常是Vtable里的层级定义和GRIB文件实际消息不一致。比如你把typeOfFirstFixedSurface写成了101指定高度层但GRIB消息里实际是106地下深度层ungrib就会在读取特定消息时打Bad level type。解法很粗暴回到wgrib2 -v的输出里找到那个变量对应的真实level type编号照抄到Vtable。不要凭经验猜ERALand的字段level类型很杂。5.4 定制Vtable后跑real.exe报“soil temperature invalid”这种一般不是Vtable映射错而是你没约束土壤温度/湿度的有效范围。ERA5-Land的土壤温度在某些高海拔或者裸土区域会出现异常低值real.exe默认对土壤温度有物理范围检查低于某个阈值比如140K就会报invalid。可以到namelist.input的physics里检查noah_tmp相关的阈值设定或者干脆在ungrib之后、metgrid之前用Python脚本把中间文件里不合理值clip到合理范围。但我不建议无脑clip最好对照站点观测筛选异常格点。5.5 快速自查表我把整个流程里最容易出问题的点汇总成一张表方便你自查症状大概率原因排查/修复方法变量读出来了但全0level type写错写成SFC而非106或DZB缺失检查Vtable层级补DZB变量读出来了但层数不对level type 106没写对ungrib默认取第一层用wgrib2 -v核对真实level类型ungrib找不到字段parameterNumber或category错误用wgrib2查看GRIB2完整参数元组别只看192蒸发量符号不对数据源符号约定与WRF相反后处理时翻转符号并换算单位real.exe土壤温度报错数据源含异常值对中间文件做合理范围clip后再喂给metgridmetgrid内存爆掉数据分辨率高、时间密按时段拆分批量生成met_em结尾说实话定制Vtable这件事第一次做会有点“黑盒”的感觉但一旦你掌握了“查GRIB元数据 → 写映射 → 验证中间文件”这条路子基本就能举一反三。我现在拿到任何一种“非标准”数据源第一反应就是先丢给wgrib2统计一遍字段再决定要不要动Vtable而不是急着去抄网上的模板。最后分享一个小技巧如果你改了Vtable但ungrib输出结果纹丝不动先删掉旧的FILE文件再跑。ungrib有缓存机制同名输出文件存在时不会重新生成这个坑我踩了两次才发现。希望这篇能帮你少走点弯路特别是土壤湿度这块折腾明白了后面用ERA5-Land做干旱评估或者陆气耦合研究都会顺手很多。
返回列表