ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ERA5驱动WRF单层嵌套全流程:从数据下载到报错排查

2026/10/3 3:53:48 拓冰建站 浏览量
ERA5驱动WRF单层嵌套全流程:从数据下载到报错排查 说实话现在拿ERA5驱动WRF的人越来越多了但大多数新手一上来就按着多嵌套教程去配d01、d02、d03结果光报错就能折腾一周。我自己从FNL切到ERA5、从两三层嵌套退回单层重跑的时候反而把整条链路理得更清楚了。这里说的“单层嵌套”并不是指垂直层只有一层而是namelist里只配置一个domain也就是只有d01不套子网格。这篇文章就把我用ERA5驱动WRFV4.4跑通单层嵌套的完整过程讲透重点放在数据准备、namelist配置和那些高频关键报错的排查思路上适合刚接触ERA5WRF、或者被各种init错误折磨到怀疑人生的朋友。1. 为什么我坚持用ERA5做驱动场从数据下载到GRIB预处理的细节1.1 ERA5对比FNL/GFS到底赢在哪里很多老教程还在用NCEP FNL或GFS的GRIB2数据分辨率一般是0.25度、时间间隔6小时。这当然能跑通WRF但在区域性天气过程模拟里你会发现初始场对6小时间隔很敏感尤其是夏季午后对流6小时前的温度湿度场和1小时前差别非常大。ERA5最大的优势是水平分辨率约0.25度约31公里时间分辨率做到逐小时垂直方向有137层。对WRF单层domain来说逐小时驱动场的优势非常直接侧边界更新更平滑地转适应过程不容易在边界产生虚假扰动。再加上ERA5是ECMWF用四维变分同化做出来的再分析产品同化了大量卫星和常规观测资料整个场的动力一致性比纯预报场的GFS要好。当然这不代表ERA5万能。ERA5的0.25度分辨率对你9km或12km的WRF domain来说依然偏粗它只是提供一个更好的大尺度背景场中尺度信息要靠WRF自己spin-up。另外ERA5陆面场和实际下垫面也有偏差如果你做长时间陆面过程模拟最好用ERA5-Land做土壤初始化。但作为单层domain的驱动数据ERA5气压层加单层场已经完全够用。1.2 CDS下载时最容易漏掉的变量和层次ERA5的下载入口是Copernicus Climate Data Store用Python的cdsapi脚本拉取比较方便。我强烈建议直接下载GRIB格式不要下载NetCDF格式。WPS里的ungrib本来就是为GRIB设计的你把数据转成NetCDF反而要额外处理。在CDS里需要拉两个数据集reanalysis-era5-pressure-levels气压层上的温度T、风U/V、位势Z、比湿Qreanalysis-era5-single-levels地表气压SP、平均海平面气压MSL、2m温度T2M、2m露点温度D2M、10m风U10/V10、海表温度SST、土壤温度/湿度等下载脚本大致长这样import cdsapi c cdsapi.Client() c.retrieve( reanalysis-era5-pressure-levels, { product_type: reanalysis, format: grib, variable: [ geopotential, specific_humidity, temperature, u_component_of_wind, v_component_of_wind ], pressure_level: [ 1, 2, 3, 5, 7, 10, 20, 30, 50, 70, 100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000 ], year: 2020, month: 07, day: [01, 02], time: [00:00, 01:00, 02:00], area: [45, 95, 15, 125], }, era5_pl.grib ) c.retrieve( reanalysis-era5-single-levels, { product_type: reanalysis, format: grib, variable: [ 10m_u_component_of_wind, 10m_v_component_of_wind, 2m_dewpoint_temperature, 2m_temperature, mean_sea_level_pressure, sea_surface_temperature, skin_temperature, soil_temperature_level_1, soil_temperature_level_2, soil_temperature_level_3, soil_temperature_level_4, soil_type, surface_pressure, volumetric_soil_water_layer_1, volumetric_soil_water_layer_2, volumetric_soil_water_layer_3, volumetric_soil_water_layer_4 ], year: 2020, month: 07, day: [01, 02], time: [00:00, 01:00, 02:00], area: [45, 95, 15, 125], }, era5_sl.grib )这里有两个经验第一area参数的顺序是北、西、南、东很多人习惯写成南、西、北、东结果下回来的区域完全反了。下载回来先随便画个经纬度范围检查一下别等metgrid阶段才抓瞎。第二单层变量必须包含土壤温度和土壤水。ERA5的土壤温度分4层分别对应0-7cm、7-28cm、28-100cm、100-289cm左右WRF的Noah陆面模式正好需要这四层土壤温度和湿度。很多人只下载了大气变量结果real.exe阶段报土壤变量缺失这属于非常经典的低级错误。1.3 把气压层和单层文件合在一起再交给ungrib气压层数据和单层数据下载回来是两个独立的GRIB文件。ungrib在读取时会按照Vtable去解析每个GRIB消息的变量、层次和时间。如果直接通过link_grib.csh把两个文件都链接过去以前我在某些WPS版本上遇到过时间循环错位的问题表现为某些时次的单层变量没被读进去metgrid阶段报“找不到某时刻的SST”。我现在的做法是先把两个文件合并成一个GRIB文件再处理cat era5_pl.grib era5_sl.grib ERA5_20200701_20200702.gribGRIB本质上是消息序列cat合并是合法且非常通用的做法。合并后检查一下文件大小和变量数量确认没有下载到半截文件grib_ls -p paramId,shortName,typeOfLevel,level,stepRange ERA5_20200701_20200702.grib | head -60重点确认shortName里有t、u、v、z、q单层里有sp、msl、2t、2d、10u、10v、sst。在WPS3.9之后的版本里Vtable.ERA5基本能识别这些变量。如果检查时发现shortName变成unknown大概率是下载格式出了问题回到CDS重新确认format确实是grib而不是netcdf。2. WRFV4.4编译和目录准备先别急着跑把这些前置条件确认清楚2.1 依赖库与configure选型里那些“不说但很致命”的细节WRFV4.4编译本身不算难真正坑人的是依赖库版本。需要提前装好netCDF-C、netCDF-Fortran、MPIOpenMPI或者MPICH都行如果要处理GRIB2还要装jasper、libpng、zlib。我踩过最无语的一个坑是系统里同时存在Anaconda自带的netCDF和系统编译的netCDF导致nc-config和nf-config指向不一致WRF configure检测到一半就崩。后来我学乖了编译前先检查环境which gfortran which mpirun nc-config --all | grep -E prefix|version nf-config --all | grep -E prefix|version确保netCDF-C和netCDF-Fortran的prefix在同一个目录比如都是/usr/local/netcdf。然后通过环境变量强制指定export NETCDF/usr/local/netcdf export PATH$NETCDF/bin:$PATH export LD_LIBRARY_PATH$NETCDF/lib:$LD_LIBRARY_PATHconfigure的时候建议选dmpar模式的GNU编译选项。串行版本不是不能跑但单层domain即使只有100x100格点跑24小时也需要好几个小时并行版本才能把效率提上来。选完configure之后在./compile em_real编译完检查ls -l main/*.exe必须看到wrf.exe、real.exe、ndown.exe、tc.exe四个可执行文件。2.2 WPS里的静态地理数据和Vtable软链接WPS编译完成后geogrid.exe需要静态地理数据。默认的geog_data_path一般指向WPS_GEOG目录这个数据包有十几个G第一次用的时候一定要确认目录是否完整。检查标准很简单看WPS_GEOG下面有没有albedo_ncep、erosion、greenfrac、landuse_30s这些子目录如果某个子目录是空的geogrid会在运行时安静地给你填默认值导致下垫面数据和真实情况差得很远。在WPS主目录下还需要准备Vtable软链接。WPS源码包里自带的Vtable.ERA5路径是ungrib/Variable_Tables/Vtable.ERA5执行cd WPS ln -sf ungrib/Variable_Tables/Vtable.ERA5 Vtable很多教程讲到这里一笔带过但如果你忘了这个软链接ungrib会默认用Vtable.GFS去解析ERA5的GRIB消息然后报一堆“unknown parameter”的错。这个错极其迷惑因为日志里只会告诉你哪个变量解析不了而不会告诉你Vtable选错了。2.3 编译目录和运行目录最好分开我个人的习惯是WPS和WRF编译完成后不要在编译目录里直接跑业务模拟而是把需要的可执行文件、namelist模板和中间目录复制到一个“case目录”。比如mkdir -p /data/wrf_case/20200701 cd /data/wrf_case/20200701 ln -sf /data/WPS/geogrid.exe . ln -sf /data/WRF/main/real.exe . ln -sf /data/WRF/main/wrf.exe .这样做的好处是每次模拟的namelist、日志、中间文件都在同一个目录里排查问题的时候路径非常清晰。很多新手把所有case混在同一个目录过两天再看连哪个namelist对应哪个输出都分不清。3. 单层嵌套的namelist配置区域、数据流和物理方案要对得上3.1 单层domain的投影参数怎么定所谓“单层嵌套”在namelist里其实就是max_dom 1不需要设置parent_grid_ratio、i_parent_start这些针对子domain的项。但这不代表你可以随便填参数。对于中国中纬度区域我个人常用Lambert投影因为它在中纬度地区的变形最小。低纬度热带地区更适合用Mercator极区则用极射赤面投影。如果区域跨中纬度又跨了热带那你就该考虑是不是domain太大了一般单层domain搞3万平方公里以上本来就不太合适。一个比较稳妥的单层配置是这样的share wrf_core ARW max_dom 1 interval_seconds 3600 io_form_geogrid 2 / geogrid parent_grid_ratio 1 i_parent_start 1 j_parent_start 1 e_we 120 e_sn 120 geog_data_res default dx 9000 dy 9000 map_proj lambert ref_lat 30.0 ref_lon 105.0 truelat1 20.0 truelat2 40.0 stand_lon 105.0 geog_data_path /data/WPS_GEOG / ungrib out_format WPS prefix ERA5 / metgrid fg_name ERA5 io_form_metgrid 2 /这里的dx9000表示水平格距9公里也就是e_we120、e_sn120的domain大约是120x120个格点东西方向覆盖约1080公里。这个尺度对单层domain来说比较理想既能容纳中尺度系统的发展又不至于让边界条件对模拟结果影响过大。有个常见误区是把ref_lat和ref_lon设成domain中心把truelat1、truelat2设成和中心纬度一样。这样不是不行但对Lambert投影来说两条标准纬线最好分开stand_lon要和ref_lon一致这样投影出来的网格才是“正”的。如果不一致geo_em.nc里的网格会整体旋转一个角度后面画图会非常难受。3.2 ungrib和metgrid的prefix必须对得上在ungrib里设置了prefix ERA5ungrib输出的中间文件就是ERA5:2020-07-01_00这种带冒号的文件名。然后在metgrid里设置fg_name ERA5metgrid才会自动去寻找以ERA5开头的中间文件。注意这里的大小写、前缀必须完全一致。我见过有人prefix era5但fg_name ERA5结果metgrid阶段报找不到fg数据查了半天才发现是大小写不一致。interval_seconds 3600这个参数在ungrib和WRF运行阶段必须一致。如果你下载的ERA5是逐小时的就填3600如果为了省空间下载成3小时间隔就填10800。这个参数不匹配的典型报错是real.exe读取met_em文件时发现时间步长和namelist.input里的interval_seconds对不上。3.3 namelist.input物理方案不是越高级越好real.exe和wrf.exe共用同一个namelist.input文件它的结构和namelist.wps一一对应。单层单域在domains里只要写一个值不要因为看了多嵌套教程就写三个值否则WRF会去找第二、第三个domain的初始场然后报错。time_control start_year 2020 start_month 07 start_day 01 start_hour 00 start_minute 00 start_second 00 end_year 2020 end_month 07 end_day 02 end_hour 00 end_minute 00 end_second 00 interval_seconds 3600 input_from_file .true. history_interval 60 frames_per_outfile 1 restart .false. / domains time_step 54 max_dom 1 e_we 120 e_sn 120 e_vert 50 dx 9000 dy 9000 p_top_requested 5000 / physics mp_physics 8 ra_lw_physics 4 ra_sw_physics 4 radt 30 sf_sfclay_physics 1 sf_surface_physics 2 bl_pbl_physics 1 bldt 0 cu_physics 1 cudt 0 / fdda grid_fdda 0 / dynamics diff_opt 1 km_opt 4 / bdy_control spec_bdy_width 5 spec_zone 1 relax_zone 4 /这里解释两个关键选择。time_step 54是按“6倍格距公里数”的经验公式来的9km格距对应54秒这个值在大多数中纬度天气过程里是稳定的。如果你用的是3km格距时间步长就应该压到18秒或更小不能再靠这个公式硬套。物理方案我选的是Thompson微物理RRTMG长短波辐射YSU边界层Noah陆面Kain-Fritsch积云参数化。这不是“最先进”的组合但它是一个非常成熟的组合WRFV4.4各版本对其支持稳定报错率低。单层9km格距下积云参数化仍然需要开着因为9km还不能完全解析深对流。等你以后跑到4km以下再考虑关掉cu_physics。4. 从geogrid到wrf的五步链路每一步都要检查中间产物4.1 执行顺序和每步该看的文件整条链路是固定的geogrid - link_grib - ungrib - metgrid - real - wrf。我建议不要写一个shell脚本一路执行到底而是手动一步一步跑每步看一眼输出确认无误再进下一步。刚开始跑的时候自动化程度越高出错时越难定位。# 第一步生成地理静态场 ./geogrid.exe # 第二步链接GRIB数据并设置Vtable ./link_grib.csh /data/ERA5/ERA5_20200701_20200702.grib ln -sf ungrib/Variable_Tables/Vtable.ERA5 Vtable # 第三步解压GRIB为WPS中间格式 ./ungrib.exe # 第四步生成met_em文件 ./metgrid.exe # 第五步生成wrfinput和wrfbdy ln -sf /data/WRF/test/em_real/real.exe . ln -sf /data/WRF/test/em_real/wrf.exe . ./real.exe # 第六步运行WRF mpirun -np 8 ./wrf.exe每一步应该检查的文件如下表阶段关键输出文件验证重点geogridgeo_em.d01.nc区域经纬度范围、投影参数是否和namelist一致ungribERA5:2020-07-01_00每个时次文件大小是否在100MB以上过小说明变量缺失metgridmet_em.d01.2020-07-01_00.nc文件时间覆盖范围、是否存在所有时次realwrfinput_d01、wrfbdy_d01日志最后出现SUCCESS COMPLETE REAL_EM INITwrfwrfout_d01_*rsl.out.0000里的积分时间步是否正常推进每次换新数据集或换机器我都建议用ncdump -h geo_em.d01.nc检查一下全局属性里的DX、DY、CEN_LAT、CEN_LON、TRUELAT1、TRUELAT2。这一步看似多余但对排查第5章的报错非常有帮助。4.2 中间文件“有”不等于“对”很多人一看到ls里有文件就觉得这一步行了其实中间产物很容易出现“有文件但内容不对”的情况。ungrib生成的ERA5:2020-07-01_00这类文件是自定义二进制格式无法用ncdump直接看。判断方法可以看文件大小37层气压层加上十几层单层变量单个时次的WPS中间文件大概有100到200MB。如果文件只有几MB说明变量大量缺失多半是下载数据时变量清单漏了。met_em文件则是NetCDF格式直接看ncdump -h met_em.d01.2020-07-01_00.nc | grep -E Times|num_metgrid_levels|MAP_PROJ注意num_metgrid_levels这个值它应该等于你的ERA5气压层数量。如果这里明显偏少说明ungrib在解析时丢了很多层后面real初始化的垂直结构就会很奇怪。4.3 real.exe成功之后别急着跑先验证两个文件real.exe正常结束的标志是日志末尾出现SUCCESS COMPLETE REAL_EM INIT。但即使这样我还会再看一眼wrfinput和wrfbdy的一致性。ncdump -v Times wrfinput_d01 | tail -5 ncdump -v Times wrfbdy_d01 | tail -5确保wrfinput里的Times和wrf运行起止时间一致wrfbdy里的时间能覆盖到模拟结束时间。另一个容易出问题的是input_from_file .true.它在time_control里告诉reald01的初始场要由met_em生成。对单层domain来说这个值必须保持.true.否则real会尝试从外部文件读初始场然后告诉你文件不存在。5. 高频报错排查实录我从单层跑通过程中总结的排查链路5.1 报错日志的检索顺序很重要WRF最让人抓狂的是日志文件很多。dmpar模式下每个并行进程都会有rsl.out.xxxx和rsl.error.xxxx。新手喜欢从头到尾看这完全是浪费时间。我的检索顺序是# 先看0号进程的最后100行 tail -100 rsl.error.0000 # 如果只有warning没有fatal再看out文件最后的积分状态 tail -50 rsl.out.0000大多数fatal错误会在rsl.error.0000的最后几行。如果里面出现FATAL CALLED FROM就可以直接定位到具体模块了。在单层单域模式下根本不用理会其他进程的日志只看0000号进程就够了。5.2 三类典型报错案例复盘第一类是metgrid阶段报“找不到对应时次的数据”。这类报错最常见的原因是ungrib生成的中间文件前缀和fg_name不一致或者时间覆盖范围不对。排查链路是先ls ERA5:*确认所有需要时次都在再检查namelist.wps里interval_seconds和文件时间间隔是否一致最后看metgrid.log里到底在找什么前缀的文件。第二类是real阶段报ERROR: Could not find matching geo_em。这个报错在单层配置里反而特别容易被人忽略。因为单层不需要第二、第三个geo_em文件但如果你namelist.input的max_dom1而实际目录里没有geo_em.d01.ncreal就会报错。检查方法很简单ls geo_em.d01.nc如果没有就回到WPS目录重新geogrid。还有种情况是geo_em.d01.nc的投影参数和namelist.input不一致比如namelist.wps里dx9000但geo_em文件里却记录的是12000这种多半是改过namelist后忘了重新跑geogrid。第三类是WRF运行过程中报CFL条件不满足。比如日志里出现cfl exceeded at ... FATAL CALLED FROM: module_big_step_em排查思路不是直接去调time_step而是先看是哪一层的哪个变量爆了。很多时候是地形区域垂直速度过大或者初始场在高层有异常大值。如果是era5驱动场在高纬度或异常天气下带来的高层风过大可以把p_top_requested从5000提高到3000也就是把模式顶往上抬给高层波动更多缓冲空间。如果只是单纯时间步长太大再把time_step从54降到45观察是否还报。5.3 一个隐蔽的地形与土壤初始化问题还有一个很隐蔽的坑可能只在单层domain且分辨率较高时出现real.exe阶段报土壤变量读取错误或者wrfout里陆面温度初始场出现明显的“斑块”。这通常不是WRF代码问题而是WPS_GEOG静态数据和ERA5土壤数据之间的下垫面分类不一致。比如ERA5认为某个格点是水体但geogrid静态数据认为它是农田于是real在初始化土壤温度和湿度时只能用默认值填补形成异常格点。解决办法是回到namelist.wps里给geogrid设置更精细的地理数据分辨率比如geog_data_res modis_lakes或者30s。对于大多数单层模拟default够用一旦发现土壤初始场异常优先检查这一项。这个排查点很多老手都不一定第一时间想到我也是对比了多个case之后才确定的。5.4 排查完成后的运行效率检查单层domain跑通之后还要确认它跑得“正常”。我每次都会看一眼rsl.out.0000里的积分时间统计如果每个时次的积分时间明显忽快忽慢先检查是不是机器负载问题如果一开始很快后面越来越慢多半是输出间隔太短写wrfout文件占了太多I/O。history_interval 60意味着每小时写一次输出24小时模拟会产生24个文件。如果你不需要逐小时中间场改成history_interval 180能明显减轻磁盘压力。最后一个个人习惯每次模拟结束后把namelist.wps、namelist.input和对应的rsl文件一起归档到以日期命名的目录。因为单层跑通之后你迟早会上嵌套到时候回头看单层的配置这些日志就是你排错最重要的参考。我就是在一次一次归档对比中才真正理解了WRF里“一致性”这三个字的分量。