我目前正在尝试运行python脚本来计算我的WRF输出数据上的三维锋生,以执行横截面分析。我已经有了一个工作的Petterson公式的二维版本来比较,但是我的三维版本只捕获了二维版本的非常小的方面。
用于计算3D锋生的公式I是:
渐变项为:
这是我的二维码(925 hPa)产生的示例图像:
这里是三维代码,然后内插到相同的二维(925 hPa)表面:
有些读数至少出现在图像上相同的地理区域这一事实向我显示,我至少在正确的轨道上,并且我可能在某处发生轻微错误。从我所看到的,我的python代码看起来是正确的,至少通过我对np.gradient函数如何工作的理解,这里是计算锋生的代码:
# 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%肯定的东西。
有谁知道为什么计算会产生不正确的结果,如上图所示?
答案 0 :(得分:0)
潜在温度梯度中的项是将垂直轴视为z,而相对于ω的垂直梯度中的项是考虑p。由于欧米茄是一个垂直的压力单位,我对潜在温度梯度的术语选择是不正确的。将导数从z转换为p可以解决问题的前半部分。
其次,在计算垂直方向的导数时,你需要考虑numpy.gradient假设你已经遍历了两个数据点,因此它将结果除以错误的两个,所以我创建了一个函数包装器处理分析的内部和外部点:
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库才能使用此功能。