气象运算模式WRF使用教程

3.7k 词

出于一些麻烦的原因,我最近开始给老师跑WRF算法,用于做相当复杂的气象运算。说实话,编译一次需要用gcc和gfortran两个编译器并行跑四十分钟才能完成的代码真是第一次见。单是第一步的生成可执行文件就花了不少功夫,所以记录下来好了。不管怎么说,也算是有趣的经验吧,虽然快把我累死了。

首先给读者讲两个常识:

  1. 如果你从来没有了解过你将要上手的软件,最好不要随手搜一个教程跟着做,尤其不要搜中文教程,因为这些教程可能本身就有错误,或者早已经过时。最高效的方法是去找官方网站找官方文档,或者Github官方仓库去找README。
  2. 遇到模式编译或运行中的错误,千万不要在国内网站上浪费时间,把遇到的问题用英文描述出来去官方论坛搜,找不到就去Github对应的项目搜issue,再不行就Google一下,把时间花在CSDN之类的网站上只会让你更迷惑。

以下是与WRF相关非常重要的参考URL:

  1. WRF构建详细过程的官方教程:How to Compile WRF: The Complete Process

    pCh2l3n.png

  2. WRF运行官方教程:WRF–ARW Online Tutorial

    其中包含详细配置参数解释和运行命令指南。

    pCh2a4J.png

  3. WRF官方论坛:WRF & MPAS-A Support Forum

    绝大多数问题都能搜索到答案。

WRF简介

WRF(Weather Research and Forecasting)是一个先进的开源天气预报模型系统,由美国国家大气研究中心(NCAR)、美国国家海洋和大气管理局(NOAA)、其他大学和研究机构的科学家们共同开发。WRF模型系统被广泛用于天气和气候研究、天气预报、气候模拟等领域。

WRF模型是一个多尺度、多分辨率的大气模型系统,可以模拟全球范围内的天气现象,也可以以更高的空间分辨率针对特定地区进行详细的天气模拟。它融合了动力学、物理过程、辐射传输等多个方面的数值模拟技术,能够准确地描述大气中的各种物理过程,如动力学、热力学、湍流、辐射、陆面过程等。

WRF模型系统具有以下特点和优势:

  1. 多尺度模拟能力:WRF模型可以在不同的水平分辨率下运行,从全球范围到小尺度的局地区域模拟,适用于不同尺度的气象研究和预报需求。

  2. 可配置性和可扩展性:WRF模型系统具有丰富的配置选项,可以根据用户需求选择不同的物理参数方案、边界条件和模拟设置,同时也支持与其他模型和数据源进行耦合和扩展。

  3. 开源和共享:WRF模型以开源方式发布,用户可以自由访问和使用,同时科学家们通过开放的交流和共享社区不断改进和优化模型系统。

  4. 多用途应用:WRF模型可用于天气预报、气候研究、环境模拟等多个领域。它被广泛应用于国内外的气象预报业务、科学研究机构和大学中,在气候变化、极端天气事件等领域发挥了重要作用。

总之,WRF模型是一个功能强大、灵活可配置的大气模型系统,提供高分辨率的天气模拟和预报能力,被广泛应用于天气和气候研究以及气象预报业务中。

简而言之,WRF用于输入静态地理数据和初始参数,来预测之后或之间的详细预测数据,WRF是开源软件,可以很容易的获取。

WRF构建

WRF构建相当复杂,主要流程如下:

pCh2XCj.png

或者说:依赖库配置==>依赖库测试==>WRF编译构建==>WPS编译构建==>静态地理数据下载配置==>模式选择

如果你对WRF的构建一无所知,又英语苦手,可以先看下主要流程,参考下随便就能搜到的中文教程即可,但实际操作构建编译最好还是按照官方来。

依赖库安装

WRF需要下面五个主要依赖:
netcdf-c-4.7.2
netcdf-fortran-4.5.2
Jasper-1.900.1
libpng-1.2.50
zlib-1.2.11

另外需要一个并行计算的依赖:

mpich-3.0.4

装依赖库看起来容易,但一旦出问题很难解决。这几个库里最重要的是用于气象数据格式化的netcdf,再比较早的版本里netcdf(for c)和netcdff(for fortran)是合在一个库里的,但这种会导致版本较新的WRF V4.0报错:

pChRHQ1.png

而且因为编译不会中止,所以非常浪费时间,所以依赖库一定要确保不出问题。

另外mpich如果不安装,则在WPS和WRF的编译选项里都要选择串行编译

WRF编译

编译的流程是先做配置:

1
./configure

有非常多选项可选,需要安装你的依赖和配置做选择,例如编译器gcc+gfrotran的话就用GNU,有mpich就用并行编译。注意,这里的选项很重要,如果有问题必定编译出错。

然后编译:

1
./compile case_name >& log.compile

case_name是编译命令接收的参数,其实这行命令是把编译的所有日志重定向到log里。

一般使用真实数据都用./compile em_real

编译完成后,如果成功会显示Successfully Build,并且会生成可执行文件:

pCTxxzQ.png

wrf.exe (model executable)
real.exe (real data initialization)
ndown.exe (one-way nesting)
tc.exe (for tc bogusing–serial only)

使用下面这条命令即可验证:

1
ls -ls main/*.exe

编译这步耗时很长,按照官方文档说至少也要半小时,而且很容易出错。

注意:如果编译失败了,重新编译时需要先用./clean清除原本配置。

WPS编译

首先设置环境变量,如何与WRF一样配置./configure

同样有很多选项,选择对应的即可。

然后运行命令./compile >& log.compile编译即可。

WPS编译相比之下要快的多,而且不那么容易出错,成功之后应该有如下几个可执行文件:

pCTzFoV.png

至此就完成了WPS编译。

静态地理数据下载

这一步没什么好说的,看文档就可以了,注意一定要下载完整,而且留出足够的存储。

下载地址:http://www2.mmm.ucar.edu/wrf/users/download/get_sources_wps_geog.html

另外路径需要注意与WPS默认配置对应,WPS的namelist.wps默认为:

1
geog_data_path = ´path_to_directory/Build_WRF/WPS_GEOG´

输入数据下载和模式选择

输入数据在这个网站下载,如果GFS的话文件名格式应该是类似与gfs.0p25.2022061312.f000.grib2。这个文件名是说这个数据是20220613的12时的第0时次,也就是12点的数据。

注意f000是指预测多少时次,也就是往后推多少时次,例如gfs.0p25.2022061306.f003.grib2是6时的第3时次,需要后推三个时次,也就是9点的数据。

这个信息在写输入配置时非常重要。

然后选择em_real模式来跑真实数据,就可以开始正式跑WRF了。

WRF预处理:运行WPS

但实际上,现在还不能跑WRF,因为WRF输入数据是nc格式,但是GFS输入数据是grib2,所以需要对数据做预处理(貌似类似于LAPS和RAMS的关系)。

跑WPS实际上就是运行刚才编译出来的三个exe文件,关键在于写namelist.wps的输入配置。

具体WPS流程是:

  1. geogrid.exe处理静态地理数据
  2. ungrib.exe处理输入的GFS数据,用于转换格式
  3. metgrib.exe将前两个输出文件做运算处理,输出WRF的输入文件。

关键在于写namelist.wps配置,具体参数解释可详见官方文档

其实可以分为几个部分,各自是对应可执行文件的配置,其中公用的是&share部分:

1
2
3
4
5
6
7
&share
wrf_core = 'ARW',
max_dom = 1,
start_date = '2022-06-13_09:00:00',
end_date = '2022-06-13_12:00:00',
interval_seconds = 10800,
io_form_geogrid = 2,

起始时间和结束时间是输入数据的起止点,中间的数据由WRF算法算出来。

interval_seconds是间隔,最后是配置输出格式为nc。

处理静态地理数据–geogrid.exe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
&geogrid
parent_id = 1,
parent_grid_ratio = 1,
i_parent_start = 1,
j_parent_start = 1,
e_we = 100,
e_sn = 100,
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!
! The default datasets used to produce the MAXSNOALB and ALBEDO12M
! fields have changed in WPS v4.0. These fields are now interpolated
! from MODIS-based datasets.
!
! To match the output given by the default namelist.wps in WPS v3.9.1,
! the following setting for geog_data_res may be used:
!
! geog_data_res = 'maxsnowalb_ncep+albedo_ncep+default', 'maxsnowalb_ncep+albedo_ncep+default',
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
geog_data_res = 'default','default',
dx = 100,
dy = 100,
map_proj = 'lambert',
ref_lat = 25.09,
ref_lon = 102.92,
truelat1 = 30.0,
truelat2 = 60.0,
stand_lon = 120.0,
geog_data_path = '/public/home/demo_cuit/hck/Build_WRF/WPS/WPS_GEOG/'
/

这个是处理静态地理数据的配置,其中有好几个需要仔细配置的地方。

e_we和e_sn是网格东西和南北尺寸,即WRF算法的计算网格范围,官方文档建议不应小于100*100。

dx和dy是x和y方向上的网格距离或分辨率,实际上就是WRF输入数据的分辨率

ref_lat和ref_lon是输入数据的经纬度。

geog_data_path是静态地理数据的路径。

配置好就可以跑geogrid.exe了。

直接一行命令即可:

1
./geogrid.exe >& log.geogrid

处理输入数据–ungrib.exe

1
2
3
&ungrib
out_format = 'WPS',
prefix = 'FILE',

这个部分的namelist很简单,也没什么要修改的。

但跑数据前需要配置输入数据的格式(这里是配置为GFS):

1
ln -sf ungrib/Variable_Tables/Vtable.GFS Vtable

然后把你的GFS输入数据链接过来:

1
./link_grib.csh path_where_you_placed_GFS_files

之后就可以跑了:

1
./ungrib.exe

成功运行会输出如下信息

pC7kZrD.png

并且生成前缀为FILE的文件。

整合数据–metgrid.exe

1
2
3
&metgrid
fg_name = 'FILE'
io_form_metgrid = 2,

运行成功显示如下信息:

pC7kQPI.png

生成前缀为met_em*的文件。

然后就可以作为输入文件跑WRF了。

运行WRF

WRF运行需要跑两个程序,如果是真实数据,则都在WRF/test/em_real目录下。

首先将WPS输出的met_em*文件链接到当前目录下(当然直接复制也没问题):

1
ln -sf ../../../WPS/met_em* .

WRF namelist.input配置

配置当前目录下的namelist.input,具体参数解释

这里比WPS更复杂,而且需要对参数有更正确的理解才能正确输出数据,因此只做简单介绍。

本次配置的namelist:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
&time_control
run_days = 0,
run_hours = 03,
run_minutes = 30,
run_seconds = 0,
start_year = 2022, 2000, 2000,
start_month = 06, 01, 01,
start_day = 13, 24, 24,
start_hour = 09, 12, 12,
end_year = 2022, 2000, 2000,
end_month = 06, 01, 01,
end_day = 13, 25, 25,
end_hour = 12, 12, 12,
interval_seconds = 9600,
input_from_file = .true.,.true.,.true.,
history_interval = 60, 60, 60,
frames_per_outfile = 1, 1000, 1000,
restart = .false.,
restart_interval = 1000,
io_form_history = 2
io_form_restart = 2
io_form_input = 2
io_form_boundary = 2
/

&domains
time_step = 0,
time_step_fract_num = 1,
time_step_fract_den = 10,
max_dom = 1,
e_we = 100, 112, 94,
e_sn = 100, 97, 91,
e_vert = 34, 33, 33,
p_top_requested = 5000,
num_metgrid_levels = 34,
num_metgrid_soil_levels = 4,
dx = 100, 10000, 3333.33,
dy = 100, 10000, 3333.33,
grid_id = 1, 2, 3,
parent_id = 0, 1, 2,
i_parent_start = 1, 31, 30,
j_parent_start = 1, 17, 30,
parent_grid_ratio = 1, 3, 3,
parent_time_step_ratio = 1, 3, 3,
feedback = 1,
smooth_option = 0
/

&physics
physics_suite = 'CONUS'
mp_physics = -1, -1, -1,
cu_physics = -1, -1, 0,
ra_lw_physics = -1, -1, -1,
ra_sw_physics = -1, -1, -1,
bl_pbl_physics = -1, -1, -1,
sf_sfclay_physics = -1, -1, -1,
sf_surface_physics = -1, -1, -1,
radt = 30, 30, 30,
bldt = 0, 0, 0,
cudt = 5, 5, 5,
icloud = 1,
num_land_cat = 21,
sf_urban_physics = 0, 0, 0,
/

&fdda
/

&dynamics
hybrid_opt = 2,
w_damping = 1,
diff_opt = 1, 1, 1,
km_opt = 4, 4, 4,
diff_6th_opt = 0, 0, 0,
diff_6th_factor = 0.12, 0.12, 0.12,
base_temp = 290.
damp_opt = 3,
zdamp = 5000., 5000., 5000.,
dampcoef = 0.2, 0.2, 0.2
khdif = 0, 0, 0,
kvdif = 0, 0, 0,
non_hydrostatic = .true., .true., .true.,
moist_adv_opt = 1, 1, 1,
scalar_adv_opt = 1, 1, 1,
gwd_opt = 1,
/

&bdy_control
spec_bdy_width = 5,
specified = .true.
/

&grib2
/

&namelist_quilt
nio_tasks_per_group = 0,
nio_groups = 1,
/

与WPS的namelist类似,start_year,start_month,end_day之类的参数写输入的GFS数据起止时间

domain配置

&domain是最重要的配置,其中需要修改的参数有好几个,而且需要仔细修改,否则直接影响输出数据质量:

time_step是时间积分步长,也就是每次算法的输入时间参数,与分辨率直接对应,非常重要。

很长时间里我一直跑不出目标分辨率的数据,长期报错CFL:

pCbnqun.png

官方文档对这个参数配置的说明如下:

Best Practice
It is recommended to use a value of 5-6xDX (in km) for a typical case. If you are using many vertical levels and/or with map-scale-factors much larger than 1, you will need to use a smaller time_step. If you are getting CFL errors that stop your run, this means your run has become unstable and you may need to decrease this value to about 4xDX (or perhaps even 3xDX). It makes things easier if you use a time step that evenly divides into your history_interval, so that your output times will be evenly spaced.

翻译:

在典型情况下,建议使用 5-6xDX 值(以公里为单位)。如果使用多个垂直层和/或地图比例因子远大于 1,则需要使用更小的时间步长。如果出现导致运行停止的 CFL 错误,这意味着运行变得不稳定,您可能需要将该值减小到约 4xDX(甚至 3xDX)。如果您使用的时间步长与历史时间间隔相等,那么输出时间的间隔也会相等。

也就是说一般使用5Dx或6Dx,但老师要求我跑100m分辨率的数据(即Dx为100m),所以一开始用500,之后一直改到100都不行,一直报错CFL。请教了专家才知道,当分辨率远远小于一公里时,需要将time_step设置为0.1(比我想象的还小的多啊!),就可以正常运行了。

另外设置时间步长设置0.1是不能直接设置time_step的,而且应该写成这种形式:

1
2
3
time_step                           = 0,
time_step_fract_num = 1,
time_step_fract_den = 10,

time_step_fract_num是分子,time_step_fract_den 是分母。

其他与CFL相关的报错可以参考这个原因和解决合集

e_we和e_sn是网格范围,dx和dy是分辨率,这两个不但参数名与WPS相同,配置的值也需要与WPS中配置相同,否则会在./read.exe时报错:

pCbuVUK.png

判断运行情况

配置好之后跑real.exe:

1
mpirun -np 1 ./real.exe

如果没装mpirun,直接用./real.exe应该也可以。

如果输出如下则说明成功运行:

pC7kTsO.png

之后就是WRF真正的可执行程序了:

1
mpirun -np 8 ./wrf.exe

输出的wrfout*文件就是WRF输出文件了,虽然没有后缀名,但实际上就是NC格式的。

问题总结

WRF编译失败

pChRHQ1.png

这种报错是netcdf这个依赖存在,但与编译不匹配,因此是版本问题。

升级netcdf版本或者降低WRF版本,让依赖与软件对应,然后修改对应环境变量即可。

留言