Python | 計算位渦平流項

寫在前面

最近忙著復習、考試…都沒怎么空敲代碼,還得再準備一周考試。。。等考完試再慢慢更新了,今天先來淺更一個簡單但是使用的python code


  • 在做動力機制分析時,我們常常需要借助收支方程來診斷不同過程的貢獻,其中最常見的一項就包括水平平流項,如下所示,其中var表示某一個變量,V表示水平風場。

? V ? ? v a r -V\cdot\mathbf{\nabla}var ?V??var

以位渦的水平平流項為例,展開為

? ( u ? p v ? x + v ? p v ? y ) -(u\frac{\partial pv}{\partial x}+v\frac{\partial pv}{\partial y}) ?(u?x?pv?+v?y?pv?)

其物理解釋為:

  • 位渦受背景氣流的調控作用。在存在背景氣流的情況下,這個位渦信號受到多少平流的貢獻

對于這種診斷量的計算,平流項,散度項,都可以通過metpy來計算。之前介紹過一次,因為metpy為大大簡便了計算

advection

但是,如果這樣還是不放心應該怎么辦呢,這里可以基于numpy的方式自己來手動計算平流項,然后比較兩種方法的差異。下面我就從兩種計算方式以及檢驗方式來計算pv的水平平流項

首先來導入基本的庫和數據,我這里用的wrf輸出的風場以及位渦pv,同時,為了減少計算量,對于數據進行區域和高度層的截取

  • 經緯度可以直接從nc數據中獲取,我下面是之前的代碼直接拿過來用了,還是以wrf*out數據來提取的lon&lat
import numpy as np
import pandas as pd
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import glob
from matplotlib.colors import ListedColormap 
from wrf import getvar,pvo,interplevel,destagger,latlon_coords
from cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatter
from netCDF4 import Dataset
import matplotlib as mpl   
from metpy.units import units
import metpy.constants as constants
import metpy.calc as mpcalc
import cmaps
# units.define('PVU = 1e-6 m^2 s^-1 K kg^-1 = pvu')
import cartopy.feature as cfeature
f_w   = r'L:\JAS\wind.nc'
f_pv  = r'L:\JAS\pv.nc'
def  cal_dxdy(file):ncfile = Dataset(file)P = getvar(ncfile, "pressure")lats, lons = latlon_coords(P)lon = lons[0]lon[lon<=0]=lon[lon<=0]+360lat = lats[:,0]dx, dy = mpcalc.lat_lon_grid_deltas(lon.data, lat.data)return lon,lat,dx,dy
path  = r'L:\\wrf*'
filelist = glob.glob(path)
filelist.sort()
lon,lat,_,_ = cal_dxdy(filelist[-1]) 
dw = xr.open_dataset(f_w).sel(level=850,lat=slice(0,20),lon=slice(100,150))
dp = xr.open_dataset(f_pv).sel(level=850,lat=slice(0,20),lon=slice(100,150))
u = dw.u.sel(lat=slice(0,20),lon=slice(100,150))
v = dw.v.sel(lat=slice(0,20),lon=slice(100,150))
pv = dp.pv.sel(lat=slice(0,20),lon=slice(100,150))
lon = u.lon
lat = u.lat

metpy

###############################################################################
#####                  
#####                      using metpy to calculate advection
#####
###############################################################################
tadv = mpcalc.advection(pv*units('pvu'), u*units('m/s'), v*units('m/s'))
print(tadv)
###############################################################################
#####                  
#####                       plot advection
#####
###############################################################################
# start figure and set axis
fig, (ax) = plt.subplots(1, 1, figsize=(8, 6),dpi=200, subplot_kw={'projection': ccrs.PlateCarree()})
proj = ccrs.PlateCarree()
# plot isotherms
cs = ax.contour(lon, lat, pv[-1]*10**4, 8, colors='k',linewidths=0.2)
ax.coastlines('10m',linewidths=0.5,facecolor='w',edgecolor='k')
box = [100,121,0,20]
ax.set_extent(box,crs=ccrs.PlateCarree())
ax.set_xticks(np.arange(box[0],box[1], 10), crs=proj)
ax.set_yticks(np.arange(box[2], box[3], 5), crs=proj)
ax.xaxis.set_major_formatter(LongitudeFormatter())
ax.yaxis.set_major_formatter(LatitudeFormatter())
# plot tmperature advection and convert units to Kelvin per 3 hours
cf = ax.contourf(lon, lat,   tadv[10]*10**4, np.linspace(-4, 4, 21), extend='both',cmap='RdYlGn', alpha=0.75)
plt.colorbar(cf, pad=0.05, aspect=20,shrink=0.75)
ax.set_title('PV Advection Calculation')
plt.show()

pv advection with metpy

metpy官網也提供了計算示例:

  • https://unidata.github.io/MetPy/latest/examples/calculations/Advection.html

當然,這里需要提醒的是,在使用metpy計算時,最好是將變量帶上單位,這樣可以保證計算結果的量級沒有問題;或者最后將其轉換為國際基本單位:m , s ,g ...

關于metpt中單位unit的使用,可以在官網進行查閱:

  • https://unidata.github.io/MetPy/latest/tutorials/unit_tutorial.html
Lf = 1000 * units('J/kg')
print(Lf, Lf.to_base_units(), sep='\n')1000.0 joule / kilogram
1000.0 meter ** 2 / second ** 2

units convert

當然,還可以點擊 source code 去了解這個函數背后的計算過程:

  • https://github.com/Unidata/MetPy/blob/v1.6.2/src/metpy/calc/kinematics.py#L359-L468
def advection(scalar,u=None,v=None,w=None,*,dx=None,dy=None,dz=None,x_dim=-1,y_dim=-2,vertical_dim=-3,parallel_scale=None,meridional_scale=None
):r"""Calculate the advection of a scalar field by 1D, 2D, or 3D winds.If ``scalar`` is a `xarray.DataArray`, only ``u``, ``v``, and/or ``w`` are requiredto compute advection. The horizontal and vertical spacing (``dx``, ``dy``, and ``dz``)and axis numbers (``x_dim``, ``y_dim``, and ``z_dim``) are automatically inferred from``scalar``. But if ``scalar`` is a `pint.Quantity`, the horizontal and verticalspacing ``dx``, ``dy``, and ``dz`` needs to be provided, and each array should have oneitem less than the size of ``scalar`` along the applicable axis. Additionally, ``x_dim``,``y_dim``, and ``z_dim`` are required if ``scalar`` does not have the default[..., Z, Y, X] ordering. ``dx``, ``dy``, ``dz``, ``x_dim``, ``y_dim``, and ``z_dim``are keyword-only arguments.``parallel_scale`` and ``meridional_scale`` specify the parallel and meridional scale ofmap projection at data coordinate, respectively. They are optional when (a)`xarray.DataArray` with latitude/longitude coordinates and MetPy CRS are used as inputor (b) longitude, latitude, and crs are given. If otherwise omitted, calculationwill be carried out on a Cartesian, rather than geospatial, grid. Both are keyword-onlyarguments.Parameters----------scalar : `pint.Quantity` or `xarray.DataArray`The quantity (an N-dimensional array) to be advected.u : `pint.Quantity` or `xarray.DataArray` or NoneThe wind component in the x dimension. An N-dimensional array.v : `pint.Quantity` or `xarray.DataArray` or NoneThe wind component in the y dimension. An N-dimensional array.w : `pint.Quantity` or `xarray.DataArray` or NoneThe wind component in the z dimension. An N-dimensional array.Returns-------`pint.Quantity` or `xarray.DataArray`An N-dimensional array containing the advection at all grid points.Other Parameters----------------dx: `pint.Quantity` or None, optionalGrid spacing in the x dimension.dy: `pint.Quantity` or None, optionalGrid spacing in the y dimension.dz: `pint.Quantity` or None, optionalGrid spacing in the z dimension.x_dim: int or None, optionalAxis number in the x dimension. Defaults to -1 for (..., Z, Y, X) dimension ordering.y_dim: int or None, optionalAxis number in the y dimension. Defaults to -2 for (..., Z, Y, X) dimension ordering.vertical_dim: int or None, optionalAxis number in the z dimension. Defaults to -3 for (..., Z, Y, X) dimension ordering.parallel_scale : `pint.Quantity`, optionalParallel scale of map projection at data coordinate.meridional_scale : `pint.Quantity`, optionalMeridional scale of map projection at data coordinate.Notes-----This implements the advection of a scalar quantity by wind:.. math:: -\mathbf{u} \cdot \nabla = -(u \frac{\partial}{\partial x}+ v \frac{\partial}{\partial y} + w \frac{\partial}{\partial z}).. versionchanged:: 1.0Changed signature from ``(scalar, wind, deltas)``"""# Set up vectors of provided componentswind_vector = {key: valuefor key, value in {'u': u, 'v': v, 'w': w}.items()if value is not None}return_only_horizontal = {key: valuefor key, value in {'u': 'df/dx', 'v': 'df/dy'}.items()if key in wind_vector}gradient_vector = ()# Calculate horizontal components of gradient, if neededif return_only_horizontal:gradient_vector = geospatial_gradient(scalar, dx=dx, dy=dy, x_dim=x_dim, y_dim=y_dim,parallel_scale=parallel_scale,meridional_scale=meridional_scale,return_only=return_only_horizontal.values())# Calculate vertical component of gradient, if neededif 'w' in wind_vector:gradient_vector = (*gradient_vector,first_derivative(scalar, axis=vertical_dim, delta=dz))return -sum(wind * gradientfor wind, gradient in zip(wind_vector.values(), gradient_vector))

Numpy

下面,是基于numpy或者說從他的平流表達式來進行計算,下面圖方便直接將其封裝為函數了:

###############################################################################
#####                  
#####                      using numpy to calculate advection
#####
###############################################################################
def advection_with_numpy(lon,lat,pv):xlon,ylat=np.meshgrid(lon,lat)dlony,dlonx=np.gradient(xlon)dlaty,dlatx=np.gradient(ylat)pi=np.pire=6.37e6dx=re*np.cos(ylat*pi/180)*dlonx*pi/180dy=re*dlaty*pi/180pv_dx = np.gradient(pv,axis=-1)pv_dy = np.gradient(pv,axis=-2)padv_numpy = np.full((pv.shape),np.nan)for i in range(40):padv_numpy[i] = -(u[i]*pv_dx[i]/dx+v[i]*pv_dy[i]/dy)return    padv_numpy
padv = advection_with_numpy(lon, lat, pv)
###############################################################################
#####                  
#####                      check calculate advection
#####
###############################################################################
plt.figure(figsize=(10, 6),dpi=200)
plt.plot( tadv[0,0], label='adv_mean', color='blue')
plt.plot( padv[0,0], label='pvadv_mean', color='red')plt.show()

check resuly

  • 可以發現兩種方法的曲線基本一致

方法檢驗

對于兩種計算方法的計算結果進行檢驗,前面也簡單畫了一下圖,下面主要從空間分布圖以及任意選擇一個空間點的時間序列來檢驗其計算結果是否存在差異。

空間分布圖

def plot_contour(ax, data, label, lon, lat, levels, cmap='RdYlGn', transform=ccrs.PlateCarree(), extend='both'):cs = ax.contourf(lon, lat, data, levels=levels, cmap=cmap, transform=transform, extend=extend)ax.coastlines()ax.add_feature(cfeature.BORDERS)ax.set_title(label)box = [100,120,10,20]ax.set_extent(box,crs=ccrs.PlateCarree())ax.set_xticks(np.arange(box[0],box[1], 10), crs=transform)ax.set_yticks(np.arange(box[2], box[3], 5), crs=transform)ax.xaxis.set_major_formatter(LongitudeFormatter())ax.yaxis.set_major_formatter(LatitudeFormatter())plt.colorbar(cs, ax=ax, orientation='horizontal')ax.set_aspect(1)
# 創建畫布和子圖
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(16, 6),dpi=200, subplot_kw={'projection': ccrs.PlateCarree()})# 繪制三個不同的圖
plot_contour(ax1, tadv[0] * 10**4, 'Metpy', lon, lat, levels=np.linspace(-1, 1, 21))
plot_contour(ax2, padv[0] * 10**4, 'Numpy', lon, lat, levels=np.linspace(-1, 1, 21))
plot_contour(ax3, (np.array(tadv[0]) - padv[0]) * 10**4, 'difference',lon, lat, levels=11)# 顯示圖形
plt.tight_layout()
plt.show()

空間分布

  • 子圖1為metpy計算結果,子圖2為numpy計算結果,子圖3為兩種計算結果的差異
  • 為了保證結果可靠性,前兩個子圖選擇相同的量級,繪制間隔(levels),colormap

可以發現,整體上對于第一個時刻的pv平流項空間分布圖,兩種方法的計算結果整體上是一致的,說明兩種計算方法都是可行的;兩種計算方法的差異小于0.01,在一定程度上可以忽略,不影響整體結論以及后續的分析。

任意空間點的時間序列


def extract_time_series(lon, lat, lon0, lat0, tadv, padv2):def find_nearest(array, value):array = np.asarray(array)idx = (np.abs(array - value)).argmin()return idxlon_idx = find_nearest(lon, lon0)lat_idx = find_nearest(lat, lat0)tadv_series = tadv[:, lat_idx, lon_idx] * 10**4padv2_series = padv2[:, lat_idx, lon_idx] * 10**4diff_series = (np.array(tadv[:, lat_idx, lon_idx]) - padv2[:, lat_idx, lon_idx]) * 10**4return tadv_series, padv2_series, diff_serieslon0, lat0 = 100, 15  # 根據實際需要修改# 提取該點的時間序列數據
tadv_series, padv_series, diff_series = extract_time_series(lon, lat, lon0, lat0, tadv, padv)# 創建新的畫布繪制時間序列曲線
plt.figure(figsize=(10, 6),dpi=200)
plt.plot(tadv_series, label='Metpy')
plt.plot(padv_series, label='Numpy')
plt.plot(diff_series, label='Diff')
plt.xlabel('Time')
plt.ylabel('Value')
plt.legend()
plt.title(f'Time Series at Point ({lon0}, {lat0})')
plt.grid(True)
plt.show()

時間序列檢驗

  • 從任意空間點的時間序列檢驗上,可以發現兩種計算方法差異基本一致,總體上Metpy的結果稍微高于numpy的計算方法,可以和地球半徑以及pi的選擇有關
  • 從差異上來看,總體上在-0.1~0.1之間,誤差可以忽略,不會影響主要的結論

總結

  • 這里,通過基于Metpy和Numpy的方法分別計算了位渦的平流項,并繪制了空間分布圖以及任意空間點時間序列曲線來證明兩種方法的有效性,在計算過程我們需要重點關注的是單位是否為國際基本度量單位,這里避免我們的計算的結果的量級的不確定性;
  • 當然,這里僅僅是收支方程中的一項,我們可以在完整的計算整個收支方程的各項結果后,比較等號兩端的單位是否一致,來證明收支方程結果的有效性。

單位查閱:https://unidata.github.io/MetPy/latest/tutorials/unit_tutorial.html
advection:https://unidata.github.io/MetPy/latest/api/generated/metpy.calc.advection.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37346.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37346.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37346.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

51單片機-點亮LED燈

目錄 新建項目選擇型號添加新文件到該項目設置字體和utf-8編碼二極管如何區分正負極原理&#xff1a;CPU通過寄存器來控制硬件電路 用P2寄存器的值控制第一個燈亮進制轉換編譯查看P2寄存器的地址生成HEX文件把代碼下載到單片機中 新建項目 選擇型號 stc是中國生產的、這個里面…

token登錄比密碼登錄有什么優勢嗎

token登錄比密碼登錄有什么優勢嗎 使用令牌&#xff08;Token&#xff09;登錄相比于密碼登錄具有一些優勢&#xff0c;包括&#xff1a; 安全性&#xff1a;令牌通常采用加密技術&#xff0c;使得它們更難以被盜取或猜測。相比之下&#xff0c;密碼存在被猜測、破解或被暴力攻…

解決瀏覽器兼容性問題的方法

解決瀏覽器兼容性問題的方法 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們來探討如何解決網頁開發中常見的瀏覽器兼容性問題。隨著互聯網技術的發展&…

java中輸入輸出流的繼承關系

在 Java 中,輸入輸出流的繼承關系主要圍繞兩個抽象基類展開:字節流基類 InputStream 和 OutputStream,以及字符流基類 Reader 和 Writer。這些類形成了 Java I/O 系統的基礎,提供了豐富的子類以適應不同的輸入輸出需求。 字節流 字節流用于處理原始的二進制數據。 Input…

利用Linked SQL Server提權

點擊星標&#xff0c;即時接收最新推文 本文選自《內網安全攻防&#xff1a;紅隊之路》 掃描二維碼五折購書 利用Linked SQL Server提權 Linked SQL server是一個SQL Server數據庫中的對象&#xff0c;它可以連接到另一個SQL Server或非SQL Server數據源&#xff08;如Oracle&a…

初學者輕松搞定19個經典的Python程序以及代碼演示

Python的經典程序展示了Python語言基本特性和功能的簡單示例,這些程序在學習和理解Python編程語言的過程中起著至關重要的作用. 一些常見的經典Python程序及其在學習Python時的功能&#xff1a; 1.Hello, World! print("Hello, World!")解釋:這是Python的基本輸出…

primeflex overflow樣式類相關的用法和案例

文檔地址&#xff1a;https://primeflex.org/overflow 案例1 <script setup> import axios from "axios"; import {ref} from "vue";const message ref("frontend variable") axios.get(http://127.0.0.1:8001/).then(function (respon…

【Flink】Flink SQL

一、Flink 架構 Flink 架構 | Apache Flink 二、設置TaskManager、Slot和Parallelism 在Apache Flink中&#xff0c;設置TaskManager、Slot和Parallelism是配置Flink集群性能和資源利用的關鍵步驟。以下是關于如何設置這些參數的詳細指南&#xff1a; 1. TaskManager 設置 …

【漏洞復現】致遠互聯FE協作辦公平臺——SQL注入

聲明&#xff1a;本文檔或演示材料僅供教育和教學目的使用&#xff0c;任何個人或組織使用本文檔中的信息進行非法活動&#xff0c;均與本文檔的作者或發布者無關。 文章目錄 漏洞描述漏洞復現測試工具 漏洞描述 致遠互聯FE協作辦公平臺是一個專注于協同管理軟件領域的數智化運…

關于內存和外存文件不同字符集下占用空間大小問題

關于內存和外存不同字符集下文件占用空間大小問題 存儲&#xff08;外存&#xff09;的文件中的字符&#xff1a; ASCII&#xff1a;每個字符占用1個字節&#xff0c;用來存儲英文字符和常用標點符號。ISO-8859-1&#xff1a;每個字符占用1個字節&#xff0c;向下兼容ASCII。G…

DS18B20單總線數字溫度傳感器國產替代MY18E20 MY1820 MY18B20Z MY18B20L(一)

前言 DS18B20是全球第一個單總線數字溫度傳感器&#xff0c;推出時間已經超過30年&#xff0c;最早由美國達拉斯半導體公司推出&#xff0c;2001年1月&#xff0c;美信以25億美元收購達拉斯半導體&#xff08;Dallas Semiconductor&#xff09;&#xff0c;而美信在2021年8月被…

DM達夢數據庫存儲過程

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;歡迎各位來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里不僅可以有所收獲&#xff0c;同時也能感受到一份輕松歡樂的氛圍&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

RDMA通信2:RDMA基本元素和組成 通信過程元素關系解析 視頻教程

哈哈哈&#xff0c;今天我們把下面這張圖理解了&#xff0c;我們的任務就完成了&#xff01; 視頻教程在這&#xff1a;1.2 RDMA基本元素和組成 通信過程元素關系解析_嗶哩嗶哩_bilibili 一、WQ和WQE 工作隊列元素(work queue element,WQE)&#xff1a;是軟件下發給硬件的任務…

Apache Ranger 2.4.0 集成Hive 3.x(Kerbos)

一、解壓tar包 tar zxvf ranger-2.4.0-hive-plugin.tar.gz 二、修改install.propertis POLICY_MGR_URLhttp://localhost:6080REPOSITORY_NAMEhive_repoCOMPONENT_INSTALL_DIR_NAME/BigData/run/hiveCUSTOM_USERhadoop 三、進行enable [roottv3-hadoop-01 ranger-2.4.0-hive…

什么是TOGAF架構框架的ADM方法?

ADM是架構開發方法&#xff08; Architecture Development Method&#xff09;&#xff0c;為開發企業架構所要執行的各個步驟以及它們質檢的關系進行詳細的定義&#xff0c;它是TOGAF規范中最為核心的內容。 ADM的具體步驟&#xff1a; 預備階段&#xff08;Preliminary Phas…

求職刷題力扣 DAY38動態規劃 part04

1. 1049. 最后一塊石頭的重量 II 有一堆石頭&#xff0c;用整數數組 stones 表示。其中 stones[i] 表示第 i 塊石頭的重量。 每一回合&#xff0c;從中選出任意兩塊石頭&#xff0c;然后將它們一起粉碎。假設石頭的重量分別為 x 和 y&#xff0c;且 x < y。那么粉碎的可能…

STM32第十三課:DMA多通道采集光照煙霧

文章目錄 需求一、DMA&#xff08;直接存儲器存取&#xff09;二、實現流程1.時鐘使能2.設置外設寄存器地址3.設置存儲器地址4.設置要傳輸的數據量5.設置通道優先級6.設置傳輸方向7.使通道和ADC轉換 三、數據處理四、需求實現總結 需求 通過DMA實現光照強度和煙霧濃度的多通道…

【SkiaSharp繪圖13】SKCanvas方法詳解(二)填充顏色、封裝對象、高性能繪制、點(集)(多段)線、圓角矩形、Surface、沿路徑繪制文字

文章目錄 SKCanvas方法DrawColor 填充顏色DrawDrawable 繪制封裝對象DrawImage 高性能繪制圖像SKBitmap與SKImage對比DrawPicture 繪制圖像SKPicture DrawPoint / DrawPoints 繪制點DrawRoundRect/DrawRoundRectDifference繪制圓角矩形DrawSurface 繪制SurfaceDrawTextOnPath沿…

力扣2055.蠟燭之間的盤子

力扣2055.蠟燭之間的盤子 預處理每個元素左右最近的蠟燭下標 同時求前綴和遍歷每個詢問找到左右端點對應的內部的最近蠟燭(最大區間) class Solution {public:vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {vector<…

List接口, ArrayList Vector LinkedList

Collection接口的子接口 子類Vector&#xff0c;ArrayList&#xff0c;LinkedList 1.元素的添加順序和取出順序一致&#xff0c;且可重復 2.每個元素都有其對應的順序索引 方法 在index 1 的位置插入一個對象&#xff0c;list.add(1,list2)獲取指定index位置的元素&#…