Python | 计算位涡平流项

写在前面

最近忙着复习、考试…都没怎么空敲代码,还得再准备一周考试。。。等考完试再慢慢更新了,今天先来浅更一个简单但是使用的python code


  • 在做动力机制分析时,我们常常需要借助收支方程来诊断不同过程的贡献,其中最常见的一项就包括水平平流项,如下所示,其中var表示某一个变量,V表示水平风场。

− V ⋅ ∇ v a r -V\cdot\mathbf{\nabla}var Vvar

以位涡的水平平流项为例,展开为

− ( u ∂ p v ∂ x + v ∂ p v ∂ y ) -(u\frac{\partial pv}{\partial x}+v\frac{\partial pv}{\partial y}) (uxpv+vypv)

其物理解释为:

  • 位涡受背景气流的调控作用。在存在背景气流的情况下,这个位涡信号受到多少平流的贡献

对于这种诊断量的计算,平流项,散度项,都可以通过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.mzph.cn/web/37346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51单片机-点亮LED灯

目录 新建项目选择型号添加新文件到该项目设置字体和utf-8编码二极管如何区分正负极原理&#xff1a;CPU通过寄存器来控制硬件电路 用P2寄存器的值控制第一个灯亮进制转换编译查看P2寄存器的地址生成HEX文件把代码下载到单片机中 新建项目 选择型号 stc是中国生产的、这个里面…

利用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…

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沿…

List接口, ArrayList Vector LinkedList

Collection接口的子接口 子类Vector&#xff0c;ArrayList&#xff0c;LinkedList 1.元素的添加顺序和取出顺序一致&#xff0c;且可重复 2.每个元素都有其对应的顺序索引 方法 在index 1 的位置插入一个对象&#xff0c;list.add(1,list2)获取指定index位置的元素&#…

sheng的学习笔记-AI-聚类(Clustering)

ai目录 sheng的学习笔记-AI目录-CSDN博客 基础知识 什么是聚类 在“无监督学习”(unsupervised learning)中&#xff0c;训练样本的标记信息是未知的&#xff0c;目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律&#xff0c;为进一步的数据分析提供基础。此类学…

Android跨进程通信,binder传输数据过大导致客户端APP,Crash,异常捕获,监听异常的数值临界值,提前Hook拦截。

文章目录 Android跨进程通信&#xff0c;binder传输数据过大导致Crash&#xff0c;异常捕获&#xff0c;监听异常的数值临界值&#xff0c;提前Hook拦截。1.binder在做跨进程传输时&#xff0c;最大可以携带多少数据1.1有时候这个1m的崩溃系统捕获不到异常&#xff0c; 2.监测异…

志愿填报指南:为什么我强烈建议你报考计算机专业

首先恭喜2024届高考的同学们&#xff0c;你们已经通过了高考的考验&#xff0c;即将进入人生的新阶段——大学。 现在正是高考完填报志愿的时刻&#xff0c;Left听到身边朋友提到报考志愿的诸多问题&#xff1a; 志愿填报怎么填&#xff1f;我要报考什么专业&#xff1f;这个…

[Cloud Networking] OSPF

OSPF 开放式最短路径优先&#xff08;Open Shortest Path First&#xff09;是一种动态路由协议&#xff0c;它属于链路状态路由协议&#xff0c;具有路由变化收敛速度快、无路由环路、支持变长子网掩码和汇总、层次区域划分等优点。 1 OSPF Area 为了适应大型网络&#xff0…

可编程定时计数器8253/8254 - 8253入门

时钟-给设备打拍子 概述 在计算机系统中&#xff0c;为了使所有设备之间的通信井然有序&#xff0c;各通信设备间必须有统一的节奏&#xff0c;不能各干各的&#xff0c;这个节奏就被称为定时或时钟 时钟并不是计算机处理速度的衡量&#xff0c;而是一种使设备间相互配合而避…