利用Python中的WRF输出计算三维锋生
我目前正试图运行一个python脚本,在我的WRF输出数据上计算三维锋生,以执行横截面分析。我已经有了Petterson公式的二维版本来进行比较,但是我的三维版本只捕捉到了二维版本非常小的方面 我用来计算三维锋生的公式是: 其中梯度项为: 以下是我的二维代码925 hPa生成的示例图像: 这是三维代码,然后插值到相同的二维925hpa表面: 事实上,一些读数至少出现在图像上相同的地理区域,这向我表明,我至少在正确的轨道上,我可能在某个地方犯了一个小错误。从我所看到的来看,我的python代码似乎是正确的,至少从我对np.gradient函数工作原理的理解来看,下面是计算锋生的代码:利用Python中的WRF输出计算三维锋生,python,numpy,3d,gradient,weather,Python,Numpy,3d,Gradient,Weather,我目前正试图运行一个python脚本,在我的WRF输出数据上计算三维锋生,以执行横截面分析。我已经有了Petterson公式的二维版本来进行比较,但是我的三维版本只捕捉到了二维版本非常小的方面 我用来计算三维锋生的公式是: 其中梯度项为: 以下是我的二维代码925 hPa生成的示例图像: 这是三维代码,然后插值到相同的二维925hpa表面: 事实上,一些读数至少出现在图像上相同的地理区域,这向我表明,我至少在正确的轨道上,我可能在某个地方犯了一个小错误。从我所看到的来看,我的python代码
# Fetch the fields we need
p = getvar(ncFile, "pressure") * 100 # Convert to Pa
z = getvar(ncFile, "z")
ua = getvar(ncFile, "ua")
va = getvar(ncFile, "va")
theta = getvar(ncFile, "theta")
omega = getvar(ncFile, "omega")
dz = np.gradient(z, axis=0)
dp = np.gradient(p, axis=0)
theta_gradient = np.sqrt((np.gradient(theta, dx, axis=2))**2 + (np.gradient(theta, dy, axis=1))**2 + (np.gradient(theta, axis=0) / dz)**2)
zonal_gradient = (-1 * np.gradient(theta, dx, axis=2)) * ((np.gradient(ua, dx, axis=2) * np.gradient(theta, dx, axis=2)) + (np.gradient(va, dx, axis=2) * np.gradient(theta, dy, axis=1)))
meridional_gradient = (-1 * np.gradient(theta, dy, axis=1)) * ((np.gradient(ua, dy, axis=1) * np.gradient(theta, dx, axis=2)) + (np.gradient(va, dy, axis=1) * np.gradient(theta, dy, axis=1)))
vertical_gradient = (-1 * (np.gradient(theta, axis=0) / dp)) * ((np.gradient(omega, dx, axis=2) * np.gradient(theta, dx, axis=2)) + (np.gradient(omega, dy, axis=1) * np.gradient(theta, dy, axis=1)))
F3D = 1.08e9 * (1 / theta_gradient) * (zonal_gradient + meridional_gradient + vertical_gradient)
return F3D
作为参考,dx和dy术语直接从NetCDF文件本身获得。它具有属性dx和dy,两者都定义为4000m
我使用wrf python库通过getvar导入数据,getvar导入netCDF文件。作为参考,netCDF文件使用与标准numpy阵列类似的阵列结构:
[上下、南北、东西]
所以轴参数的顺序应该是正确的z=0,y=1,x=2
我的一位教员顾问认为,梯度的边缘可能会导致计算内部出现一些问题,但我的理解是,每个点都是独立于边缘计算的,因此应该没有差异,但这一点我不是100%确定
有人知道为什么计算会产生如上图所示的错误结果吗?在进行了更多的抨击之后,我能够解决这个问题。去展示,以确保考虑您的全单元分析! 势温度梯度中的项考虑垂直轴为z,而垂直梯度中关于ω的项考虑p。由于ω是一个垂直的压力单位,我对潜在温度梯度的术语选择是错误的。将z到p的导数换掉,修复了问题的前半部分
第二,当计算垂直方向上的导数时,你需要考虑NoMy.Read是假设你已经走过了两个数据点,因此它把结果分成两个错误,所以我创建了一个函数包装器来处理分析的内外点:
def calc_center_difference(A, ax):
gradient = np.gradient(A, axis=ax)
gradient *= 2.0
if ax == 0:
gradient[0,:,:] /= 2.0
gradient[-1,:,:] /= 2.0
elif ax == 1:
gradient[:,0,:] /= 2.0
gradient[:,-1,:] /= 2.0
elif ax == 2:
gradient[:,:,0] /= 2.0
gradient[:,:,-1] /= 2.0
else:
return ValueError("Invalid axis passed to calc_center_difference")
return gradient
之后,我将考虑dz或dp的派生项的实例与包装函数实例交换,以确保正确计算这些项,瞧!一切正常
下面是我前面的函数的正确形式,它可以在python中计算完整的3D锋生:
# Input netcdf
# - [bottom_top, north_south, west_east]
def three_d_fronto(ncFile):
# Fetch the fields we need
p = to_np(getvar(ncFile, "pressure") * 100)
z = to_np(getvar(ncFile, "z"))
ua = to_np(getvar(ncFile, "ua"))
va = to_np(getvar(ncFile, "va"))
theta = to_np(getvar(ncFile, "theta"))
omega = to_np(getvar(ncFile, "omega"))
dz = calc_center_difference(z, 0)
dp = calc_center_difference(p, 0)
theta_gradient = np.sqrt((np.gradient(theta, dx, axis=2))**2 + (np.gradient(theta, dy, axis=1))**2 + (calc_center_difference(theta, 0) / dp)**2)
zonal_gradient = (-1 * np.gradient(theta, dx, axis=2)) * ((np.gradient(ua, dx, axis=2) * np.gradient(theta, dx, axis=2)) + (np.gradient(va, dx, axis=2) * np.gradient(theta, dy, axis=1)))
meridional_gradient = (-1 * np.gradient(theta, dy, axis=1)) * ((np.gradient(ua, dy, axis=1) * np.gradient(theta, dx, axis=2)) + (np.gradient(va, dy, axis=1) * np.gradient(theta, dy, axis=1)))
vertical_gradient = (-1 * (calc_center_difference(theta, 0) / dp)) * ((np.gradient(omega, dx, axis=2) * np.gradient(theta, dx, axis=2)) + (np.gradient(omega, dy, axis=1) * np.gradient(theta, dy, axis=1)))
F3D = 1.08e9 * (1 / theta_gradient) * (zonal_gradient + meridional_gradient + vertical_gradient)
return F3D
作为提醒,您需要安装wrf python库才能使用此函数。这里只是一点更新。今天我决定试着用手工分别计算这些项,我想我已经解决了这个问题。这里的dz项应该处理z[n+1]-z[n-1]作为梯度项的分母,实际上是在做z[n+1]-z[n]。dp项也做了同样的事情,它会去掉被dz和dp除以的偏导数项。