简体   繁体   English

在Python中根据WRF输出计算3D Frontogenesis

[英]Calculating 3D Frontogenesis from WRF output in Python

I'm currently trying to run a python script to calculate three-dimensional frontogenesis on my WRF output data to perform cross section analysis with. 我目前正在尝试运行python脚本,以在WRF输出数据上计算三维前沿,以进行横截面分析。 I already have a working two dimensional version of Petterson's Formula in place to compare against, however my three dimensional version is only capturing very minor aspects of what the two dimensional version is. 我已经可以使用二维版本的佩特森公式进行比较,但是我的三维版本仅捕获了二维版本的很小一部分。

The formula I'm using to calculate 3D frontogenesis is: 我用来计算3D前沿发生的公式是: 均衡器1

Where the gradient term is: 梯度项为: 均衡器2

Here's an example image of what my two dimensional code (925 hPa) produces: 这是我的二维代码(925 hPa)产生的示例图像: 图片1

And here's the three dimensional code which is then interpolated down to the same two dimensional (925 hPa) surface: 这是三维代码,然后将其内插到同一二维(925 hPa)表面: 图片2

The fact that some of the readings do at least appear in the same geographical regions on the images show to me that I'm at least on the right track and that I'm probably making a minor error somewhere. 一些读数确实至少出现在图像上的相同地理区域这一事实向我表明,我至少在正确的轨道上,并且我可能在某个地方犯了小错误。 From what I've seen, my python code appears correct, at least by my understanding of how the np.gradient function works, here is the code that calculates the frontogenesis: 从我所看到的,至少通过我对np.gradient函数如何工作的理解,我的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

As a reference, the dx and dy terms are obtained directly from the NetCDF file itself (It has attributes DX and DY, both defined as 4000m) 作为参考,dx和dy项直接从NetCDF文件本身获得(它具有DX和DY属性,均定义为4000m)

I'm using the wrf-python library to import my data by means of getvar, which is importing the netCDF files. 我正在使用wrf-python库通过getvar导入我的数据,该方法正在导入netCDF文件。 As a reference, the netCDF files use an array structure similar to standard numpy arrays: [bottom-top, south-north, east-west] 作为参考,netCDF文件使用类似于标准numpy数组的数组结构:[底部,南北,东西向]

So ordering of the axis argument should be correct (z = 0, y = 1, x = 2). 因此,轴参数的排序应正确(z = 0,y = 1,x = 2)。

One of my faculty advisers believes the edges of the gradient may be causing some issues with the inside of the calculation, however my understanding is that each point is calculated independently of the edges, and therefore there should be no difference, but this is something I'm not 100% sure about. 我的一位教职顾问认为,梯度的边缘可能会导致计算内部出现某些问题,但是我的理解是,每个点的计算均独立于边缘,因此应该没有区别,但这是我所要做的我不是100%知道的。

Does anyone know why the calculation would produce an incorrect result as shown in the images above? 有谁知道为什么计算会产生不正确的结果,如上图所示?

After some more head bashing, I was able to solve the issue. 经过更多的打击后,我得以解决此问题。 Goes to show to make sure to consider your full unit analysis! 参加表演以确保考虑您的完整单位分析!

The term in the gradient of potential temperature was considering the vertical axis as z, while the term in the vertical gradient with respect to omega was considering p. 潜在温度梯度中的项将垂直轴视为z,而相对于ω的垂直梯度中的项考虑p。 As omega is a vertical unit of pressure, my term selection for the potential temperature gradient was incorrect. 由于Ω是压力的垂直单位,因此我对潜在温度梯度的术语选择不正确。 Swapping out the derivative from z to p fixed the first half of the problem. 将导数从z替换为p可以解决问题的前半部分。

Secondly, when it comes to calculating the derivatives in the vertical direction, you need to consider that numpy.gradient is assuming you have traveled over two data points, and thus it divides the result by two incorrectly, so I created a function wrapper to handle the inner and outer points of the analysis: 其次,在垂直方向上计算导数时,您需要考虑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

Afterwards, I swapped the instances of derivative terms that considered either dz or dp with the wrapper function instance to make sure the terms were being correctly calculated, and voila! 之后,我将考虑dz或dp的派生术语实例与包装函数实例交换,以确保正确计算这些术语,瞧! Everything works! 一切正常!

Here's the corrected form of my earlier function that can calculate the full 3D frontogenesis in python: 这是我先前的函数的更正形式,可以在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

Just as a reminder, you need the wrf-python library installed to use this function. 提醒一下,您需要安装wrf-python库才能使用此功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM