先把结论放在前头:这个项目标题看起来很硬核,但它本质上是把“WRF模式系统”当成一个天气实验室来搭建和做实验,从驱动场数据准备、区域设置,到跑一个典型台风暴雨过程,再到通过修改地表和地形制造对照试验,最后用Python把模式结果变成图、路径和统计结论,是一条非常典型的数值模拟全链路。我做过不少类似风格的案例,过程中踩过的坑比想象中多得多,所以这篇直接把能复用的流程和细节写出来,给同样想用WRF做中尺度模拟、或准备做敏感性试验的朋友作参考。
1. 项目全貌:这不止是“跑WRF”,而是一整套科研工作流
1.1 从标题拆出来的几条任务线
这个标题里有几个关键词:WRF、GFS、ERA5、Python,加上“台风暴雨案例”“修改土地利用与地形”“敏感性试验”。这些东西单独拿出来都不难理解,但放在一个项目里,就意味着你要具备好几块能力:
- 能在Linux环境里编译部署WRF和WPS,并且把NetCDF、MPI等依赖库安排明白;
- 能处理两种不同来源的驱动场数据,也就是GFS预报数据和ERA5再分析资料;
- 会设计嵌套区域、写namelist,并能独立完成WPS到real再到wrf.exe的完整运行;
- 能修改模式底层的静态地理数据,比如土地利用类型和地形高度;
- 有做控制变量试验的方法论,能设计出可信的敏感性试验;
- 最终还要用Python读取wrfout文件,做风场、海平面气压、降水、路径等的专业气象分析。
串起来看,这不只是单一“模拟流程”的内容,更像是一个中尺度天气数值实验的完整技术栈。它的应用场景很广:台风路径与暴雨落区分析、城市热岛和土地利用变化对降水的影响、复杂地形下的局地环流研究、物理参数化方案对比等等。能把这套链路跑通的人,基本就具备了独立开展中尺度数值模拟研究的能力。
1.2 整体链路和阶段产物
我们可以把整个项目拆成五个阶段:
- 数据准备阶段:下载GFS或ERA5数据,整理驱动场文件,并完成格式转换和预处理;
- 静态数据生成阶段:通过geogrid生成包含地形、土地利用、土壤类型等信息的geo_em文件;
- 初边条件生成阶段:ungrib将GRIB格式的气象要素转成中间格式,metgrid将驱动场插值到模拟网格上,生成met_em文件;
- 模式积分阶段:real.exe读取met_em生成初始条件和边界条件文件,wrf.exe完成时间积分,输出wrfout文件;
- 分析与试验阶段:用Python读wrfout,绘制台风路径、降水分布、敏感性试验对比图,再结合修改geo_em或物理方案做对照,评估不同因素对结果的影响。
我建议第一次接触这套流程的人,先把阶段1到4完整跑通一次,不追求物理方案多先进、嵌套多细,先用一个单域、简单方案跑出一个结果,再逐步增加复杂度。否则很容易在最复杂的配置里迷失方向,最后连是namelist写错还是数据没下对都分不清。
1.3 这套内容适合谁来做
如果你是想做毕业论文的气象学生、需要给项目提供模式支撑的科研助理、或者是想用数值模拟方法做局地天气过程分析的从业者,这个项目方向都挺合适。只要你已经具备Linux基本操作能力和一点点Python基础,就可以按这个流程逐步搭起来。纯新手也不用怕,前面耗时间的部分其实是配环境和处理数据,真正上手后你会发现WRF的模式积分反而不是最大的技术门槛。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 先把“天气实验室”环境搭好:从系统到依赖库
2.1 硬件和操作系统的建议
跑WRF没有说一定要上超算,但需要一台够用的Linux机器。以我要跑的台风案例为例,如果做三层嵌套,最内层分辨率到3km,建议物理核心不少于16核,内存不低于32GB,磁盘预留至少300GB。一个72小时的三层嵌套模拟,如果用16核并行跑,可能需要一天甚至更长时间,具体取决于你选择的物理方案和分辨率。
在系统层面上,OpenMPI、gfortran、NetCDF这些基础环境是核心。操作系统的发行版影响不大,Ubuntu、CentOS、Rocky Linux都行,但有一点很重要:WRF不支持Windows原生跑,别想着在Windows里编译运行;如果只有Windows机器,也要用WSL2或者干脆在Linux服务器上操作。路径尽量不要出现空格、中文和过长的层级,这是很多初学者容易忽视的坑。
2.2 依赖库的编译顺序和版本匹配
WRF依赖的关键库有NetCDF-C、NetCDF-Fortran、MPI,如果处理GRIB2数据还需要JasPer、libpng、zlib。很多人在WPS处理GFS数据时遇到“can't find jasper”之类的问题,往往就是这几个库没装好或者版本不匹配。
我建议的编译顺序是:
- 先装zlib和libpng;
- 再装JasPer;
- 之后是NetCDF-C;
- 然后编译NetCDF-Fortran;
- 最后确认MPI环境可用。
安装NetCDF时需要注意,C库和Fortran库必须安装到同一个前缀目录下,比如都放到/usr/local/netcdf,否则编译WRF时会出现找不到NetCDF模块的错误。
环境变量可以这样设置:
bash复制export NETCDF=/usr/local/netcdf
export PATH=$NETCDF/bin:$PATH
export LD_LIBRARY_PATH=$NETCDF/lib:$LD_LIBRARY_PATH
export JASPERLIB=/usr/local/jasper/lib
export JASPERINC=/usr/local/jasper/include
编译WRF时,我习惯在configure阶段选择“34. GNU (gfortran/gcc)”,再选择并行模式或者串行模式。第一次跑通验证时,可以先用串行模式把流程走通,再用并行模式跑正式的嵌套案例,这样可以减少并发行数设置错误带来的干扰。
2.3 Python环境:给分析单独建一个环境
实际做WRF后处理时,我强烈建议不要用系统的Python直接装包,而用conda或者venv创建一个独立的环境。因为气象后处理需要wrf-python、netCDF4、cartopy、matplotlib、numpy这些库,依赖关系很复杂,装进系统环境很容易和别的包冲突。
bash复制conda create -n wrf python=3.10
conda activate wrf
pip install netCDF4 numpy matplotlib cartopy wrf-python
这里有一点要注意,wrf-python目前对较新的Python版本支持不算完美,用3.10或3.11都比较保险。装好之后,可以在Python里执行import wrf、import netCDF4,确认没有报错再继续。很多人跳过了这一步,结果到分析阶段才发现wrf-python装失败,回头折腾环境,很浪费时间。
3. GFS与ERA5驱动场:数据选型和处理的关键细节
3.1 两种驱动场数据的“性格”差异
GFS和ERA5都是常见的WRF驱动场,但对不同项目来说,选择逻辑差别很大。我先整理成一张表,方便对照:
| 对比项 | GFS | ERA5 |
|---|---|---|
| 数据类型 | 全球预报场 | 全球再分析资料 |
| 水平分辨率 | 0.25度或0.5度 | 约0.25度 |
| 时效性 | 实时更新,适合业务预报 | 延迟发布,适合历史个例研究 |
| 时间一致性 | 不同起报时刻之间存在跳跃 | 长时间序列一致性较好 |
| 下载复杂度 | 相对简单,GRIB2文件直接可使用 | 参数多、Level多,需要仔细选择 |
| 适用场景 | 实时台风预报、试验性模拟 | 科研个例、敏感性试验、气候统计 |
如果你要模拟的是刚发生的天气过程,那GFS几乎是必需选择,因为ERA5数据还没及时更新。但如果你做的是已经确定的历史个例研究,比如某次台风过程,我一般优先选ERA5,因为ERA5的分析场质量更好,且时间连续,不会因为使用不同起报时刻的GFS资料而引入预报误差。
3.2 下载规范和文件目录整理
不管选哪种数据,文件管理都得一开始就做规范。我的习惯是每个案例单独建立一个目录,结构类似:
text复制wps_run/
GFS/ # 存放原始GRIB2文件
met_em/ # metgrid输出
namelist.wps
ungrib_run/
Vtable
GFS/ # ungrib处理后的中间文件
real_run/
met_em/
wrfbdy_d01
wrfinput_d01
wrf_run/
wrfout_d01_...
下载GFS数据时,通常用wget循环下载每个时次即可,注意按模拟时段多下载12到24小时数据作spin-up。台风模拟我一般至少提前18到24小时开始积分,这样模式有充分时间“进入状态”。
3.3 ungrib到metgrid:最容易出错但原理最清晰的一段
ungrib做的事情,是把GRIB格式的驱动场解译成WRF能识别的中间格式。处理GFS时,在ungrib目录里先链接对应Vtable:
bash复制ln -sf ungrib/Variable_Tables/Vtable.GFS Vtable
./link_grib.csh /path/to/your_gfs_data/*.grib2
./ungrib.exe
处理ERA5时,如果下载的是GRIB格式文件,则把Vtable换成Vtable.ERA5;如果你下载的是NetCDF格式,建议先回头重新下载成GRIB,或者用ECMWF的工具转成WPS中间格式,否则ungrib可能读不到变量。
在namelist.wps里有一个重要的设置:
fortran复制&ungrib
out_format = 'WPS',
prefix = 'GFS',
/
运行完ungrib后,你会看到类似GFS:2024-08-12_00的文件,这代表成功。接着运行metgrid。metgrid本质上把水平插值到geo_em网格上,这里要注意:metgrid读取的geo_em文件必须与namelist中的时间范围一致,并且文件编号要覆盖全部模拟时间,少一个都不行。
3.4 real.exe之前:先检查这几个点
很多人在real.exe阶段报错,其实问题出在met_em文件或namelist设置上。我在跑real之前,一定会执行以下检查:
- 用
ncdump -h met_em*检查文件中的维度是否与namelist.input里e_we、e_sn一致; - 确认met_em文件的时间范围覆盖了
start_year到end_year设置的全部时间段; - 检查namelist.input中
interval_seconds是否与namelist.wps里的interval_seconds一致,一般GFS和ERA5都是6小时间隔,取21600秒; - 检查
p_top_requested是否小于驱动场最顶层气压,WRF顶层建议设在5000Pa到10000Pa之间,不能设太低导致模式顶与驱动场不匹配。
real.exe运行成功后,会生成wrfinput_d01和wrfbdy_d01文件。此时再打开rsl.out.0000看看有没有warning,尤其是关于地形、气压层缺失等警告,如果出现这类信息,后面wrf.exe即使能跑,结果也可能不靠谱。
4. 台风暴雨案例实操:三层嵌套跑通全过程
4.1 台风案例的基本配置思路
台风模拟最常用的做法是三层嵌套,从外到内分辨率逐步提高,例如27km、9km、3km。这样既能抓住大尺度引导气流,又能分辨台风内核附近的强对流和暴雨。
设计网格区域前,我会先在图上画出台风路径和关注区域,然后确定每个域的范围。需要说明的是,嵌套域的位置不是随便设的,子域必须位于父域内,而且不能太贴近父域边界,否则边界误差会很快污染内部结果。
这里给出一段示例namelist.input配置:
fortran复制&time_control
run_days = 3,
run_hours = 0,
start_year = 2024,
start_month = 08,
start_day = 12,
start_hour = 00,
end_year = 2024,
end_month = 08,
end_day = 15,
end_hour = 00,
interval_seconds = 21600,
max_dom = 3,
history_interval = 60, 30, 30,
input_from_file = .true.,.true.,.true.,
/
&domains
time_step = 18,
max_dom = 3,
e_we = 151, 226, 301,
e_sn = 121, 196, 241,
dx = 27000, 9000, 3000,
dy = 27000, 9000, 3000,
parent_grid_ratio = 1, 3, 3,
i_parent_start = 1, 40, 55,
j_parent_start = 1, 30, 45,
p_top_requested = 5000,
/
&physics
mp_physics = 8, 8, 8,
ra_lw_physics = 4, 4, 4,
ra_sw_physics = 4, 4, 4,
sf_sfclay_physics = 1, 1, 1,
sf_surface_physics = 2, 2, 2,
bl_pbl_physics = 1, 1, 1,
cu_physics = 3, 3, 0,
/
需要提醒的是,上面这些e_we和嵌套位置数字只是便于理解流程的示意,实际项目要结合目标区域调整。我的做法是先用一个绘制geo_em和路径的脚本辅助确定范围,或者用WPS自带的domain wizard工具来做,设置后跑一次geogrid,再输出一张域分布图,确认嵌套位置正确后再继续。
4.2 时间步长和物理方案的选择逻辑
时间步长的选择直接影响模式稳定性。WRF有一个常用的参考规则:对于最内层网格,每个网格对应的积分步长大约为网格距的3到6倍,单位是秒。比如最内层3km,理论建议用12到18秒;如果使用18秒后出现CFL崩溃,就降到9秒。实际台风案例中,因为地形和强对流会造成大梯度,18秒不一定稳定,我经常直接从9秒或12秒起步。
物理方案上,台风模拟的常用选择是Thompson微物理方案,它在云微物理描述的细致程度和计算成本之间比较平衡。外层区域开启积云参数化方案,3km内层则关闭积云参数化,因为高分辨率下模式已经能直接分辨深对流过程。边界层方案我常选YSU,辐射方案统一用RRTMG。这套组合在台风路径、强度和降水模拟中都属于成熟组合,适合作为控制试验。
4.3 长积分过程的稳定性处理
运行一次wrf.exe之前,先确认wrfinput_d01没有异常值,再使用mpirun并行启动:
bash复制mpirun -np 16 ./wrf.exe > run.log 2>&1 &
运行过程中不能完全不管。我会定期查看输出文件生成情况和rsl.error.0000日志。如果日志出现“cfl”字样或“the model diverged”,通常是步长过大、地形过陡或垂直层设置不合理,需要先降步长重跑,而不是继续调物理方案。
如果模拟过程稳定,但wrfout文件巨大,建议把内层域的输出频率设为30分钟,外层设为60分钟。台风路径分析有30分钟一张就足够,3km域如果也每10分钟输出一次,磁盘很容易被写满。
5. 修改土地利用与地形:如何把模式“改造”得更贴近真实
5.1 哪些场景需要动geo_em文件
虽然WRF默认的地形和土地利用数据已经很标准,但很多研究场景需要我们自己改动底图,比如:
- 城市扩张对热岛和降水的影响;
- 填湖、水库修建或湿地变化对局地环流的扰动;
- 风电场的用地类型改变对边界层过程的影响;
- 为了消除真实地形中的不必要噪音而做地形平滑处理。
在这些情况下,修改对象主要是geogrid生成的geo_em.d01.nc、geo_em.d02.nc等文件。
5.2 直接改geo_em文件:相对简单且可控
如果只是把某个目标区域的土地利用类型改掉,直接在geo_em文件上动手比较高效。geo_em中与土地利用有关的关键变量包括LU_INDEX和LANDUSEF。LU_INDEX是二维类别场,它记录了每个格点的主导土地类型;LANDUSEF是三维变量,维度类似于“土地类别数 × 南北网格数 × 东西网格数”,表示每个格点上各土地类别所占比例。
操作时,先查清楚你用的土地分类体系。以常见的MODIS分类为例,城市类别编号通常是13;如果你想把一片农田改成城市,就把对应格点的LU_INDEX赋值为13,同时修改LANDUSEF,让城市类别在该格点的比例接近1,其他类别比例接近0。
修改geo_em之前,先备份原始文件:
bash复制cp geo_em.d01.nc geo_em.d01.nc.orig
然后用Python的netCDF4库或NCO工具读取并修改。处理完以后,不能直接把geo_em丢给wrf.exe。正确的流程是重跑metgrid得到新的met_em文件,再重跑real.exe生成新的初始条件。因为土地利用和地表属性会直接影响real阶段计算的地表参数和土壤初始化,跳过这一步会造成模式初始场不协调。
5.3 改地形时的注意事项
修改地形可以类比为给模式换一个“数字海拔模型”。如果只是小幅平滑,可以在namelist.wps中调整geogrid的插值方式,或者直接对geo_em里的HGT_M变量做滤波。但如果是较大范围替换地形数据,比如用更高分辨率的DEM替换默认地形,需要注意与气象驱动场的一致性。
我更建议的处理思路是,如果要做地形影响试验,就把地形变化限制在一个合理幅度内,并确保重跑metgrid和real。只改geo_em而不重新初始化,低层温压场与地形的匹配就会出问题,最终在模式低层产生虚假的重力波噪声。
地形改动较大时,在namelist.input中可以适当调节扩散项系数,例如加大diff_6th_factor,帮助模式过滤掉高波数噪声。但这不是万能药,根本前提还是初始场要和地形一致。
6. 敏感性试验设计:怎么对比才真正有说服力
6.1 单因子控制是设计试验的底线
敏感性试验听起来很简单,但我见过不少“假试验”:一次改了微物理方案,又换了边界层方案,还顺带改了分辨率,最后不知道结果差异该归因于哪一个因素。做这种对比实验,方法论上必须是一条铁律:一次只改一个因子,其他全部保持不变。
以物理方案敏感性为例,我会跑一组控制试验和几组对比试验:
| 试验名称 | 修改内容 | 保持不变的要素 |
|---|---|---|
| CTL | 默认Thompson+YSU | 区域、分辨率、时间步长、辐射方案、积分时段 |
| EXP_MP | 改用WSM6微物理方案 | 与CTL完全一致,只改mp_physics |
| EXP_PBL | 改用MYJ边界层方案 | 与CTL完全一致,只改bl_pbl_physics |
| EXP_LU | 改变土地利用类型 | 与CTL完全一致,只改geo_em中LU数据 |
6.2 批量试验的目录与脚本组织
如果每个试验都重新走一遍WPS,会浪费大量时间。实际上,只要模拟区域和时段不变,met_em文件和geo_em文件都可以复用。我把流程设计成:
- 先完成一次WPS处理,生成所有met_em文件;
- 在父目录中给每个试验建独立子目录,例如
exp_ctl、exp_mp、exp_lu; - 把run目录里启动WRF所需的文件复制过去,包括
wrf.exe、namelist.input、对应的met_em文件链接; - 在子目录里修改各自的namelist.input;
- 分别执行
real.exe和wrf.exe。
批量启动脚本大致是这样:
bash复制for exp in exp_ctl exp_mp exp_pbl exp_lu; do
cd $exp
ln -sf ../met_em_files/met_em* .
./real.exe > real.log 2>&1
mpirun -np 16 ./wrf.exe > wrf.log 2>&1
cd ..
done
这里要注意,如果试验涉及到修改土地利用数据,必须在geogrid阶段就重新生成geo_em并重跑metgrid,不能只复制原来的met_em文件。
6.3 评价指标怎么选
不同试验之间的差异,光看图不行,还得有定量指标。对台风路径,我通常在每个积分时次从wrfout中提取最低海平面气压中心位置,然后计算模拟路径与最佳路径的绝对距离误差,以及平均距离误差,用来评估路径模拟的好坏。对降水,则需要对比观测格点数据,计算TS评分、偏差、命中率等。
用一个更直白的说法:敏感性试验不是看“有没有差别”,而是看“差别大不大、有没有统计意义、变化方向是否符合物理直觉”。所以实验设计和指标提取必须在跑模式之前就想好,而不是等结果出了再决定怎么对比。
7. Python专业分析:把wrfout读成图和气象结论
7.1 后处理知识准备
WRF输出的wrfout是NetCDF格式,Python处理时最常用的库是netCDF4和wrf-python。wrf-python最方便的地方是它封装了大量气象诊断量计算,比如海平面气压、相当位温
