ARTICLE DETAIL

资讯详情

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

定制Vtable:让ERA5-Land土壤湿度正确接入WRF

定制Vtable:让ERA5-Land土壤湿度正确接入WRF 我第一次把WRF的驱动数据从ERA5气压层换成ERA5-Land的时候吃过一个很隐蔽的亏WPS整套流程跑下来ungrib不报错、metgrid不报错、real.exe也不报错气象场看起来一切正常唯独等我把土壤湿度初始场画出来一看整个区域清一色是模型默认值。后来拆开中间文件才发现ERA5-Land的土壤湿度GRIB记录在ungrib阶段就被静默跳过了——原因不复杂就是Vtable没有认下这个数据源的变量编码。这篇文章就围绕定制Vtable这件事展开以ERA5-Land四层土壤湿度接进WRF为例把从GRIB体检、Vtable编写到中间文件验证的完整链路走一遍顺带把ERA5-Land蒸发数据符号为负这个高频坑也一起讲清楚。适合对WPS流程已有基本操作经验、正在把ERA5-Land这类非标准数据源接入WRF的人参考。1. 为什么ERA5-Land不能直接套用Vtable.ERA51.1 ERA5-Land和ERA5血缘很近脾气完全不同ERA5-Land在官方文档里被定位为ERA5的陆地表面重分析回放驱动场来自ERA5但陆地过程是独立跑出来的。这意味着它和ERA5共享一大批变量名比如都叫Volumetric soil water content但底层GRIB编码、层级定义、网格分辨率和符号约定都可能不一样不能想当然地拿现成的Vtable.ERA5去套。最典型的差异有三个网格ERA5-Land是0.1°约9公里均匀网格ERA5是0.25°区域模拟时前者能给你明显更好的下边界空间细节这也是很多人从ERA5转向ERA5-Land的直接原因。土壤分层ERA5-Land的土壤水分有4层深度分别是0-7cm、7-28cm、28-100cm、100-289cm。这个分层和WRF里Noah陆面模型默认的0-10cm、10-40cm、40-100cm、100-200cm并不对齐后面你会发现这不仅仅是少一层多一层的问题。GRIB层级类型ERA5-Land土壤变量在GRIB2里用的层级类型是depth below land surface这类地底深度层级而默认Vtable里对应条目写的往往是surface类层级条件。ungrib是按参数号层级类型双重匹配的层级类型对不上记录就直接跳过。1.2 静默丢数据才是最危险的情况我之所以强调静默是因为这套流程里没有任何一步会给你一个红色的FATAL错误。ungrib找不到匹配的Vtable条目时只会往日志里写一条不起眼的warning然后继续处理下一条记录。metgrid在水平插值的时候发现某个二维场缺失会用默认值填上real.exe更是干脆土壤湿度初始场直接落到LSM的默认初始值。结果就是整个流程看起来成功跑完你的模拟从第一时刻起就带着错误的陆面初始状态。土壤湿度对近地面2m温度、边界层发展和后续降水都有直接影响尤其是预报的前12到48小时这种错误会顺着地表能量通量一路传染给大气。如果你做的是长时间积分或者区域气候降尺度那土壤状态错一个量级后面几个月都缓不过来。所以接ERA5-Land这种非标准数据源第一课就是不要相信流程正常只相信中间文件里真的有数。Vtable定制不是为了解决某个报错而是为了不让数据在无人知晓的情况下被丢掉。2. Vtable的六列格式先搞清楚ungrib到底在匹配什么2.1 六列字段逐列拆解Vtable本质上是一张翻译对照表告诉ungribGRIB文件里的某一条记录该转成WPS中间格式里的哪个物理量。以我手头WPS 4.5的Vtable.ERA5为例去掉注释行后每一行有六列信息字段含义示例GRIB1参数号GRIB1编码下的参数编号130GRIB2参数号ECMWF体系里grib_ls打出来的paramId130层级类型ungrib按什么层级条件去匹配GRIB记录P、S、D或GRIB2层级代码中间变量名写进WPS中间格式的字段名TT、RH、SM000010单位仅作记录通常不影响数值转换K、m3 m-3描述给人看的注释Temperature关键是第三列和第四列。ungrib在GRIB文件里逐条扫描每条记录都会拿参数号层级类型去和Vtable各行比对。比对上了就按该行指定的中间变量名写出去比对不上就打印一条warning然后跳过。你在这个阶段要做的就是保证ERA5-Land的土壤湿度记录能被某一行精确命中。2.2 层级类型标识与SM字段命名规则不同版本的WPS对层级类型标识的支持不完全一样。老版本Vtable里常见的是字符标识P代表气压层、S代表地面层、H代表离地高度层、D代表地底深度层。新一点的WPS在解析GRIB2时也接受直接用GRIB2层级类型数字比如100是等压面、1是地面、106是地底深度。你需要先打开自己WPS目录下ungrib/Variable_Tables/里的现有Vtable看一眼确认你这份WPS吃哪套写法再决定第三列填什么。以我用的WPS 4.5为例直接填106是可以被认出来的但如果你用的是老版本可能需要把第三列改成D或者在ungrib源码的层级判断分支里把106加进S的范畴。第四列SM字段的命名规则也要说清楚SM000010表示0-10cm土壤湿度SM010040表示10-40cm后面的数字单位是厘米前两位是层顶深度、后两位是层底深度。WRF/Noah体系用的就是这一套深度区间标识metgrid和real.exe后续都会按字段名里的深度信息来理解数据。所以你在定制Vtable时中间变量名这一列不能乱起必须用这套SM深度区间的命名否则后面real.exe根本认不出这是土壤湿度。3. 手写Vtable从grib_ls到ungrib跑通3.1 拿到数据先体检grib_ls和pygrib怎么用写Vtable之前一定要先看你实际下载的GRIB文件内部长什么样。ECMWF官方推荐的grib_ls是快速体检工具一行命令就能把关键编码列出来grib_ls -p paramId,shortName,typeOfLevel,level,units,stepRange era5land_20240101.grib如果环境里没有eccodes工具包用pygrib也完全可以import pygrib grbs pygrib.open(era5land_20240101.grib) for g in grbs: if g[paramId] 151 or soil in g[shortName]: print(g)我那次跑出来的土壤湿度记录大概是这样的1:Volumetric soil water layer 1:paramId151,shortNameswvl1, typeOfLeveldepthBelowLandLayer,level0.07,unitsm,stepRange0注意几个信息参数号是151shortName是swvl1到swvl4层级类型是depthBelowLandLayerlevel值分别是0.07、0.28、1.0、2.89单位是m。这里的0.07指的是该层深度范围的上边界实际含义是第一层覆盖0到0.07m。这些信息就是你写Vtable的全部依据。3.2 编写自定义Vtable我的做法是先复制一份现有Vtable作为底稿再往里加ERA5-Land特有的条目。复制的时候别直接用Vtable.ERA5建议以Vtable.ERA5或者Vtable.ECMWF为基底因为它们对气压层通用变量的映射已经齐全你只需要增补地表和土壤部分。cp ungrib/Variable_Tables/Vtable.ERA5 Vtable.ERA5LAND然后在文件末尾追加或者替换土壤相关条目。我这里给出实际用过的片段注意第三列我用的就是GRIB2层级类型106! ERA5-Land 定制条目土壤湿度与土壤温度 ! 格式GRIB1参数号 GRIB2参数号 层级类型 中间变量名 单位 描述 151 151 106 SM000010 m3 m-3 Volumetric soil water (ERA5-Land L1, 0-7cm) 151 151 106 SM010040 m3 m-3 Volumetric soil water (ERA5-Land L2, 7-28cm) 151 151 106 SM040100 m3 m-3 Volumetric soil water (ERA5-Land L3, 28-100cm) 151 151 106 SM100200 m3 m-3 Volumetric soil water (ERA5-Land L4, 100-289cm) 139 139 106 ST000010 K Soil temperature (ERA5-Land L1, 0-7cm) 139 139 106 ST010040 K Soil temperature (ERA5-Land L2, 7-28cm) 139 139 106 ST040100 K Soil temperature (ERA5-Land L3, 28-100cm) 139 139 106 ST100200 K Soil temperature (ERA5-Land L4, 100-289cm)这里有个实际操作中的细节ERA5-Land四层土壤湿度在GRIB文件里是同参数号、同层级类型、不同level值的四条独立记录。ungrib在按Vtable匹配时如果同一个参数号对应多个中间变量名通常是按GRIB记录在文件里的先后顺序来分配的。所以你的GRIB文件里四条swvl记录必须按深度从浅到深排列否则第四层的数据会被写进第一个SM字段里错位得一塌糊涂。建议下载完先跑一遍grib_ls -p shortName,level确认顺序。3.3 跑通ungrib和日志判断Vtable准备好之后把它复制到ungrib的运行目录并命名为Vtable如果你的WPS版本支持在namelist里指定vtable路径也可以直接指过去。接下来常规流程./link_grib.csh /path/to/era5land_20240101.grib编辑namelist.wps至少保证下面这部分正确ungrib out_formatWPS, prefixERA5LAND, /然后运行./ungrib.exe ungrib.log跑完之后别急着进metgrid先看日志。这一步能帮你省掉后面大量排查时间grep -i soil\|SM000010\|SM010040\|did not match\|warning ungrib.log我当时的教训就是第一版Vtable第三列写的是Sungrib日志里没有任何土壤条目被处理的痕迹但也没有任何显眼的FATAL报错所有土壤记录都被跳过了。改成106之后日志里才出现对应SM字段的successfully processed信息。4. 蒸发符号为负的坑ERA5-Land的符号惯例4.1 负蒸发是正常的别当bug很多人在CDS下载ERA5-Land的蒸发数据后会发现总蒸发量和潜在蒸发量全是一堆负值第一反应是数据坏了或者下载出错了。其实这是ERA5-Land的符号约定和ERA5正好相反。在ERA5里蒸发量被定义为从地表指向大气的向上通量为正所以蒸发发生时数据是正的。而ERA5-Land里的约定是反过来的数据为负的时候才代表蒸发水汽从地表进入大气数据为正反而代表凝结/沉降水汽从大气回到地表。所以你在ERA5-Land里看到负的蒸发恰恰说明模型在正常地蒸发。这个符号问题不直接影响Vtable的编写——Vtable只负责字段映射不负责符号变换——但如果你打算拿ERA5-Land蒸发通量来做下面两件事就必须处理它用ERA5-Land蒸发数据作为观测真值来评估WRF的陆面模拟效果用ERA5-Land蒸发通量去驱动离线的陆面模型比如Noah-MP standalone模式。两种情况下一旦符号搞错你会得出模型蒸发比观测高出几个量级或者完全相反的离谱结论。4.2 符号翻转的操作翻转符号用CDO一行就能解决cdo mulc,-1 earm5land_evaporation_orig.nc earm5land_evaporation_flipped.nc想用Python处理也可以import xarray as xr ds xr.open_dataset(era5land_evaporation.nc) ds[e] ds[e] * -1.0 ds.attrs[note] sign flipped to ERA5 convention (positive upward evaporation) ds.to_netcdf(era5land_evaporation_era5convention.nc)做完翻转之后顺手算一下区域平均值如果是正的且量级在每小时零点几毫米水当量这个范围基本就对了。还要注意ERA5-Land的蒸发是累计量而不是瞬时量单位是水当量米m of water equivalent不是mm/s。你要和WRF的瞬时输出比较时得先做时间差分换算成通量单位这一步常常比符号问题更容易被人忽略。4.3 附带提醒这跟Vtable定制是两件事我在不少交流群里见过有人把蒸发符号问题和Vtable定制混在一起问以为改Vtable能顺便把符号纠正过来。实际上这是两条独立的工作流Vtable管的是GRIB记录→中间字段的映射符号修正是数据预处理阶段的事应该在进入WPS之前就做完。换句话说如果你要用ERA5-Land蒸发量做研究下载下来第一件事就是先检查符号和累计量单位把它处理成你后续分析想要的约定这件事发生在你碰Vtable之前而不是之后。5. 验证与排错怎么确认土壤湿度真的进去了5.1 rd_intermediate.py检查中间文件ungrib跑完最可靠的验证方法不是看日志而是直接用WPS自带的util/rd_intermediate.py去读中间文件python rd_intermediate.py ERA5LAND:2024-01-01_00这个脚本会把中间文件里的所有字段、层级、和每个层的最小值/最大值/平均值打印出来。重点检查以下几点是否出现了SM000010、SM010040、SM040100、SM100200这几个字段这些字段的最小值是否落在合理范围比如0.05到0.5 m3/m3之间有没有出现-9999这种填充值每个字段的层级数量是否是1土壤湿度在中间格式里就是单层二维场。我自己的习惯是顺便画一张图直接把SM000010的二维分布用matplotlib扫一眼看空间分布是不是和地形/植被分布有合理的对应关系。数值范围对得上、空间分布也不离谱这时候我才敢说ungrib这关过了。5.2 常见错误自查表根据我接触过的案例整理了一份自查表排查顺序也是按这个来现场症状可能原因处理办法ungrib日志找不到SM相关处理记录Vtable第三列层级类型不匹配用grib_ls确认typeOfLevel把第三列改成对应写法土壤记录被匹配但全写进同一个字段GRIB文件里土壤各层顺序混乱重新排序或用grib_copy按level排序后再进ungrib中间文件SM字段全是-9999Vtable没匹配上字段未写入回到第一行原因排查SM值偏小比如0.001量级单位理解错误把m3/m3当成了其他单位核对下载变量说明必要时做单位换算metgrid跑完还是默认土壤值ungrib阶段就没写对或字段名不符合SM命名规范用rd_intermediate.py先确认中间文件本身是否正确两条土壤记录参数号相同但层级类型不同ERA5-Land某些图层用的层级类型可能不统一逐条grib_ls确认分层编写Vtable条目这表里最容易被忽略的是GRIB文件里土壤各层顺序混乱这一条。CDS批量下载有时会把多个时间步、多个变量的记录以不确定的顺序拼在一个文件里你不提前看一眼的话ungrib很可能把第4层土壤水分当成第1层写了进去。5.3 土壤分层映射的现实问题就算中间文件正确生成了ERA5-Land的四层0-7、7-28、28-100、100-289cm和WRF Noah的四层0-10、10-40、40-100、100-200cm仍然需要对账。这里我不建议做特别复杂的深度插值绝大多数实际项目用的就是就近归并策略ERA5-Land第一层0-7cm → SM000010虽然名义上是0-10cm但表层土壤湿度垂直变化本身就很大0-7和0-10的差异对它影响相对可控第二层7-28cm → SM010040同样的道理算是比较合理的近似第三层28-100cm → SM040100两者深度范围几乎一致第四层100-289cm → SM100200这是偏差最大的一组ERA5-Land的第四层明显比Noah的第四层深你等于用了一个2米以内平均的湿度值去替代2米处的值。如果你的研究对深层土壤湿度很敏感比如做长期干旱过程或者地下水补给相关的研究那就别偷懒老老实实用Python或CDO把ERA5-Land的四层数据按深度权重插值到Noah的四层深度区间再让ungrib去读插值后的GRIB文件。对于大多数天气尺度的短期模拟来说就近归并足够用了。6. 关于Vtable维护的几点个人习惯最后分享几个我自己的实操习惯不算什么标准流程但能帮你少走弯路。第一每次给一个新的数据源写Vtable我都会把grib_ls的输出存成一个文本文件跟Vtable放在同一个目录里。三个月后你再回头维护这个配置时不会记得当时到底看的哪条记录、参数号是多少有这份体检记录就全对上了。第二Vtable一定要纳入版本管理。WPS升级之后ungrib对层级类型的解析逻辑可能变化Vtable.ERA5LAND在4.3和4.5下表现可能不一样。纳入Git之后你可以精确知道是哪个版本开始失效的。第三尽量把Vtable的生成过程脚本化。比如用Shell脚本根据grib_ls的结果自动生成土壤分层条目而不是每次手敲。ERA5-Land这类数据源的参数编码相对稳定但难保将来某个版本调整编码脚本化之后你只需要重新跑一遍grib_ls对照差异即可。最后再补一句定制Vtable这件事表面上看起来是在改配置文件实际上是在检验你对数据源和ungrib工作机制的理解。把参数号层级类型中间变量名这三个概念理清楚以后不管来的是ERA5-Land还是别的什么非标准数据源你都能在一小时之内把它接进WRF。
返回列表