3、数值天气预报(NWP)接入:GFS/ECMWF数据源、数据下载与预处理、网格插值技术
数值天气预报,简称NWP,是风功率预测系统的“粮食”。没有它,后面所有模型都是空中楼阁。我做了这么多年风电,见过太多团队把精力全花在算法调优上,结果NWP数据源没选对,预测精度直接垮掉。说白了,地基没打好,楼盖得再漂亮也没用。
这一章,我们就来聊聊NWP数据怎么接进来、怎么处理、怎么让它适配我们的风电场。
3.1 两大主流数据源:GFS与ECMWF
目前行业内用得最多的,就是GFS和ECMWF。这两家各有千秋,我分别说说。
GFS(全球预报系统)
GFS是美国国家环境预报中心(NCEP)发布的。免费、开放、全球覆盖。它的空间分辨率大概是0.25度(约28公里),时间分辨率3小时一次。说实话,这个精度对于大型风电场勉强够用,但对于地形复杂的山地风场,误差会比较大。
优点:完全免费,数据获取方便,更新频率高(每天4次)。
缺点:分辨率偏低,预报时效越长误差越大。
ECMWF(欧洲中期天气预报中心)
ECMWF被公认为全球最准的NWP模型。它的分辨率可以达到0.1度(约11公里),时间分辨率1小时。我个人的习惯是,只要预算允许,优先选ECMWF。
优点:精度高,尤其是对天气系统的捕捉能力很强。
缺点:收费,而且不便宜。数据获取流程也比GFS复杂。
| 对比项 | GFS | ECMWF |
|---|---|---|
| 空间分辨率 | 0.25° (~28km) | 0.1° (~11km) |
| 时间分辨率 | 3小时 | 1小时 |
| 更新频率 | 每天4次 | 每天2次 |
| 费用 | 免费 | 收费 |
| 适用场景 | 短期、粗粒度 | 中长期、高精度 |
3.2 数据下载与预处理
数据源选好了,接下来就是下载。GFS的数据可以从NCEP的FTP服务器或者NOAA的OpenDAP服务器获取。ECMWF则通过其MARS系统或CDS(气候数据存储)平台。
我一般用Python写脚本来自动化下载。下面是一个简单的GFS数据下载示例:
import requests
import xarray as xr
# GFS数据URL示例(0.25度分辨率)
url = "https://nomads.ncep.noaa.gov/dods/gfs_0p25/gfs20250301/gfs_0p25_00z"
# 使用xarray打开数据集
ds = xr.open_dataset(url)
# 选择特定变量和区域
# 风速、风向、温度、气压是风功率预测的核心变量
wind_u = ds['ugrd10m'].sel(lat=slice(40, 30), lon=slice(110, 120))
wind_v = ds['vgrd10m'].sel(lat=slice(40, 30), lon=slice(110, 120))
# 保存为NetCDF文件
wind_u.to_netcdf('gfs_wind_u.nc')
wind_v.to_netcdf('gfs_wind_v.nc')
下载下来的数据通常是GRIB2或NetCDF格式。我们需要做几步预处理:
- 格式转换:GRIB2转NetCDF,方便用Python处理。我常用
cfgrib库。 - 变量提取:只保留风速、风向、温度、气压、密度这几个关键变量。别一股脑全下载,数据量太大。
- 时间对齐:NWP的预报时间步长可能和我们的预测需求不一致。比如GFS是3小时间隔,但我们需要逐小时数据。这时候就要做时间插值。
- 质量控制:检查数据是否有缺失值、异常值。我曾经遇到过GFS数据在某个格点突然出现风速500m/s的离谱值,一看就是数据错误。
3.3 网格插值技术
NWP数据是网格化的,而我们的风电场是一个点(或者几个点)。怎么把网格数据“搬”到风机位置?这就是网格插值要干的事。
常用的插值方法有几种:
- 最近邻插值:直接取离风机最近的网格点数据。简单粗暴,但误差大,尤其在地形复杂区域。
- 双线性插值:用周围四个网格点做线性加权。精度比最近邻好,计算量也不大。
- 反距离加权(IDW):根据距离远近分配权重。距离越近,权重越大。我个人比较喜欢这种方法,因为它直观且效果稳定。
- 克里金插值:考虑空间相关性,精度最高,但计算量大。适合科研场景,工程上用得不多。
下面是一个双线性插值的Python实现:
import numpy as np
from scipy.interpolate import RegularGridInterpolator
# 假设我们有四个网格点的风速数据
lats = np.array([39.5, 40.0])
lons = np.array([115.5, 116.0])
wind_speed_grid = np.array([[8.5, 9.0], [8.8, 9.3]])
# 风机位置
turbine_lat = 39.8
turbine_lon = 115.7
# 创建插值函数
interp_func = RegularGridInterpolator((lats, lons), wind_speed_grid)
# 进行插值
wind_speed_at_turbine = interp_func([turbine_lat, turbine_lon])
print(f"风机位置的风速: {wind_speed_at_turbine[0]:.2f} m/s")
3.4 知识体系总览
为了让你对整个流程有个直观的认识,我画了一张图。它把数据源、下载、预处理、插值这几个环节串起来了。
你看,整个流程其实不复杂,但每一步都有坑。数据源选不对,后面全白干;预处理不到位,模型学歪了;插值方法选错了,预测精度直接打折。
我个人建议,刚开始做NWP接入时,先用GFS免费数据跑通流程,把下载、预处理、插值的代码都调试好。等流程稳定了,再切换到ECMWF提升精度。这样既省钱又稳妥。