python读取fnl数据计算200-800km范围内的区域平均、散度、涡度实现grads函数

之前的气象数据如从NCEP中下载的FNL数据一般都是采用Grads处理,但Grads的代码语言比较繁杂,而且一般只用来处理气象数据,所以逐渐都不维护了。作为新生代的python,可以用来解决很多,因此就用python来处理这些问题。

1.python读取FNL数据

由于网上下载的NCEP的fnl数据,07年以后只有grib2文件格式,python读取grib文件需要依赖pygrib库,这个依赖库只有Linux、Mac OS系统下可以使用,Windows系统没有这个依赖库,因此这里通过wgrib2将grib2文件转化为nc文件,方便处理。详细请参考Windows上python读取FNL数据。
然而这样做的一个弊端就是,文件转化耗费时间特别长。因此,需要找到一种python直接处理grib2文件的方法。现在的一些方法是eccodes或者cfgrib+xarray,具体的等我了解清楚,再整理出来。

(2020/9/17注:已经整理出来,请参考:WIndows下xarray+cfgrib读取grib文件)

python读取nc文件:

from netCDF4 import Dataset
import numpy as np

nc_obj = Dataset('C:\\wgrib2\\test.nc')
#查看nc文件
print(nc_obj)
print('---------------------------------------')

#具体变量数据信息
tmp = nc_obj['TMP_550mb'][:]
print(tmp)

2.根据经纬度求200km-800km范围内的均值

首先得知道需要求得经纬度;
我的经纬度是从最佳路径数据集中获取的,如下:

#读取best_track文件
data = pd.read_csv('C:/TC/Best_Track/CH2016BST.csv', encoding="ISO-8859-1")
lat = data.iloc[:, 3] #第3列
lon = data.iloc[:, 4] #第4列

然后根据经纬度,找以它为圆心得圆环。
注:这里将100km近似1°。故对应经纬度2-8。
python读取fnl数据计算200-800km范围内的区域平均、散度、涡度实现grads函数_第1张图片就是将圆环中所有点的经纬度对应的变量计算,求和,取均值。
可以直接循环获取,代码如下:

lonlist=[]
latlist=[]
for i in range(lon-8, lon+8, 1):
    for j in range(lat-8, lat+8, 1):
        if(math.sqrt(math.pow(i-lon, 2)+math.pow(j-lat, 2))>=2 and math.sqrt(math.pow(i-lon, 2)+math.pow(j-lat, 2))<=8):
            lonlist.append(i)
            latlist.append(j)

注:这里直接使用的直线距离,在经纬度上可以用弧度距离来计算。

3.计算200-800km的UGRD_200mb

准备工作做完了,下面就开始实现grads代码了。
grads计算:

'set z 19'
   'd 0.4*(aave(UGRDprs,lon='nowlon+2',lon='nowlon+8',lat='nowlat-8',lat='nowlat+8')+aave(UGRDprs,lon='nowlon-8',lon='nowlon-2',lat='nowlat-8',lat='nowlat+8'))+0.1*(aave(UGRDprs,lon='nowlon-2',lon='nowlon+2',lat='nowlat+2',lat='nowlat+8')+aave(UGRDprs,lon='nowlon-2',lon='nowlon+2',lat='nowlat-8',lat='nowlat-2'))'

aave为grads里面的区域平均函数,python里面没有,所以我们需要分开计算
计算整个圆环内所有点的UGRD,然后求和取均值。

def average200_800(name):
    av1 = 0.0
    for i in range(len(lonlist)):
        av1 += nc_obj.variables[name][0][latlist[i]][lonlist[i]]
    av1 = av1 / len(lonlist)
    return av1

这样,根据需要求得变量,就可以求圆环内的区域平均了。

4.python计算200-800km的散度

散度是根据纬向风U和经向风V计算出来的。
Grads代码:

'd 0.4*(aave(hdivg(UGRDprs,VGRDprs),lon='nowlon+2',lon='nowlon+8',lat='nowlat-8',lat='nowlat+8')+aave(hdivg(UGRDprs,VGRDprs),lon='nowlon-8',lon='nowlon-2',lat='nowlat-8',lat='nowlat+8'))+0.1*(aave(hdivg(UGRDprs,VGRDprs),lon='nowlon-2',lon='nowlon+2',lat='nowlat+2',lat='nowlat+8')+aave(hdivg(UGRDprs,VGRDprs),lon='nowlon-2',lon='nowlon+2',lat='nowlat-8',lat='nowlat-2'))'

可以看到,grads里有直接计算散度的函数hdivg,它可以先计算散度,在计算区域平均。
下面通过公式用python实现计算:
散度的计算公式:
hdivg = du/dx + dv/dy
其实应该是偏导。
散度其实就是一个点的风的膨胀与收缩。
我们可以根据python里的梯度函数gradient计算每个经纬度对应的dv和du,这里dx和dy都是对应的全1矩阵,可以不用计算。
gradient函数的计算方法就是,根据这个经纬度前后对应的数据计算而来。du=(u2-u1)/2。u2,u1分别为左右经纬度处的变量。对x进行积分,就是左右变量,对y进行积分就是上下变量。
我这里直接使用公式计算:

U = 'UGRD_200mb'
V = 'VGRD_200mb'
hdivg = 0.0
for i in range(len(lonlist)):
    hdivgv = (nc_obj.variables[V][0][latlist[i] + 1][lonlist[i]] - nc_obj.variables[V][0][latlist[i] - 1][lonlist[i]])/2
    hdivgu = (nc_obj.variables[U][0][latlist[i]][lonlist[i] + 1] - nc_obj.variables[U][0][latlist[i]][lonlist[i] - 1])/2
    hdivg += hdivgv + hdivgu
hdivg = hdivg / len(lonlist) / 100000

注:这里除100000,是100km。即一个格代表100km,下同。
也可以直接使用gradient函数,分别将三个变量加入数组,直接对数组进行gradient,得到的数组中间的梯度即为所求梯度。本人实验后,两者结果一致。
这样,就通过python计算出区域内的散度了。

5…python计算200-800km的涡度

涡度与散度一样。
Grads代码:

'd 0.4*(aave(hcurl(UGRDprs,VGRDprs,lon='nowlon+2',lon='nowlon+8',lat='nowlat-8',lat='nowlat+8')+aave(hcurl(UGRDprs,VGRDprs,lon='nowlon-8',lon='nowlon-2',lat='nowlat-8',lat='nowlat+8'))+0.1*(aave(hcurl(UGRDprs,VGRDprs,lon='nowlon-2',lon='nowlon+2',lat='nowlat+2',lat='nowlat+8')+aave(hcurl(UGRDprs,VGRDprs,lon='nowlon-2',lon='nowlon+2',lat='nowlat-8',lat='nowlat-2'))'

可见,涡度也有对应的函数hcurl。
涡度的计算公式:
hcurl = dv/dx - du/dy
涡度就相当于一个点的旋转。
方法同散度。
代码如下:

U = 'UGRD_500mb'
V = 'VGRD_500mb'
hcurl500 =0.0
for i in range(len(lonlist)):
    hcurlv = (nc_obj.variables[V][0][latlist[i]][lonlist[i] + 1] - nc_obj.variables[V][0][latlist[i]][lonlist[i] - 1]) / 2
    hcurlu = (nc_obj.variables[U][0][latlist[i] + 1][lonlist[i]] - nc_obj.variables[U][0][latlist[i] - 1][lonlist[i]]) / 2
    hcurl500 += hcurlv - hcurlu
hcurl500 = hcurl500 / len(lonlist) / 100000

这样就实现了python计算涡度。

希望本博客对想要实现python计算气象数据散度涡度的同学一些帮助。

你可能感兴趣的:(Python,python)