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]+360
    lat = 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 required
    to 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 vertical
    spacing ``dx``, ``dy``, and ``dz`` needs to be provided, and each array should have one
    item 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 of
    map projection at data coordinate, respectively. They are optional when (a)
    `xarray.DataArray` with latitude/longitude coordinates and MetPy CRS are used as input
    or (b) longitude, latitude, and crs are given. If otherwise omitted, calculation
    will be carried out on a Cartesian, rather than geospatial, grid. Both are keyword-only
    arguments.

    Parameters
    ----------
    scalar : `pint.Quantity` or `xarray.DataArray`
        The quantity (an N-dimensional array) to be advected.
    u : `pint.Quantity` or `xarray.DataArray` or None
        The wind component in the x dimension. An N-dimensional array.
    v : `pint.Quantity` or `xarray.DataArray` or None
        The wind component in the y dimension. An N-dimensional array.
    w : `pint.Quantity` or `xarray.DataArray` or None
        The 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, optional
        Grid spacing in the x dimension.
    dy: `pint.Quantity` or None, optional
        Grid spacing in the y dimension.
    dz: `pint.Quantity` or None, optional
        Grid spacing in the z dimension.
    x_dim: int or None, optional
        Axis number in the x dimension. Defaults to -1 for (..., Z, Y, X) dimension ordering.
    y_dim: int or None, optional
        Axis number in the y dimension. Defaults to -2 for (..., Z, Y, X) dimension ordering.
    vertical_dim: int or None, optional
        Axis number in the z dimension. Defaults to -3 for (..., Z, Y, X) dimension ordering.
    parallel_scale : `pint.Quantity`, optional
        Parallel scale of map projection at data coordinate.
    meridional_scale : `pint.Quantity`, optional
        Meridional 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.0
       Changed signature from ``(scalar, wind, deltas)``

    """
    # Set up vectors of provided components
    wind_vector = {key: value
                   for key, value in {'u': u, 'v': v, 'w': w}.items()
                   if value is not None}
    return_only_horizontal = {key: value
                              for key, value in {'u': 'df/dx', 'v': 'df/dy'}.items()
                              if key in wind_vector}
    gradient_vector = ()

    # Calculate horizontal components of gradient, if needed
    if 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 needed
    if 'w' in wind_vector:
        gradient_vector = (*gradient_vector,
                           first_derivative(scalar, axis=vertical_dim, delta=dz))

    return -sum(
        wind * gradient
        for 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.pi
    re=6.37e6
    dx=re*np.cos(ylat*pi/180)*dlonx*pi/180
    dy=re*dlaty*pi/180
    
    pv_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 idx

    lon_idx = find_nearest(lon, lon0)
    lat_idx = find_nearest(lat, lat0)
    
    tadv_series = tadv[:, lat_idx, lon_idx] * 10**4
    padv2_series = padv2[:, lat_idx, lon_idx] * 10**4
    diff_series = (np.array(tadv[:, lat_idx, lon_idx]) - padv2[:, lat_idx, lon_idx]) * 10**4
    
    return tadv_series, padv2_series, diff_series

lon0, 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/760997.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Python绘制极坐标图

使用Python绘制极坐标图 极坐标图极坐标图的优点使用场景 效果代码 极坐标图 极坐标图&#xff08;Polar Chart&#xff09;是一种图表类型&#xff0c;用于显示在极坐标系中的数据。极坐标图使用圆形坐标系&#xff0c;角度表示一个变量的值&#xff0c;半径表示另一个变量的…

【Python】利用代理IP爬取当当网数据做数据分析

前言 在数字化浪潮的推动下&#xff0c;电商平台已经彻底改变了我们的购物方式。从简单的在线交易到复杂的用户交互&#xff0c;电商平台积累了海量的用户数据。这些数据&#xff0c;如同隐藏在深海中的宝藏&#xff0c;等待着被发掘和利用。通过分析用户的浏览、搜索、购买等行…

基于人脸68特征点识别的美颜算法(一) 大眼算法 C++

1、加载一张原图&#xff0c;并识别人脸的68个特征点 cv::Mat img cv::imread("5.jpg");// 人脸68特征点的识别函数vector<Point2f> points_vec dectectFace68(img);// 大眼效果函数Mat dst0 on_BigEye(800, img, points_vec);2、函数 vector<Point2f&g…

使用Perplexity打造产品的27种方式

ChatGPT和Perplexity等聊天机器人正迅速成为产品经理的首选助手。以下是一份全面的指南&#xff0c;介绍PM如何在日常工作中使用Perplexity&#xff0c;该指南基于300多份回复和30次电话后的总结。 理解并制定增长战略&#xff1a;例如&#xff0c;解释增长会计的基本原理&…

Docker的理解

Docker的理解 Docker为什么用Docker&#xff1f;1.提升系统资源利用率2.更快速的交付和部署3.高效的部署和扩容4.更简单的管理 Docker核心技术Docker镜像Docker容器Docker仓库 Docker实现原理Linux NamespaceCgroupUnion FS Docker的应用场景1.微服务架构2.持续集成3.快速部署和…

四.iOS核心动画 - 图层的视觉效果

引言 在前几篇博客中我们讨论了图层的frame,bounds,position以及让图层加载图片。但是图层事实上不仅可以显示图片&#xff0c;或者规则的矩形块&#xff0c;它还有一系列内建的特性来创建美丽优雅的页面元素。在这篇博客中我们就来探索一下CALayer的视觉效果。 视觉效果 图…

机器学习环境搭建

前言 个人笔记&#xff0c;记录框架和小问题&#xff0c;没有太详细记载。。 1、Anaconda安装 下载地址&#xff1a; Free Download | Anaconda &#xff08;慢&#xff09; ​ 国内镜像&#xff1a;https://link.csdn.net/?targethttp%3A%2F%2Fitcxy.xyz%2F241.html 下载…

五国如何实现关键基础设施保护方法的现代化

本叙述介绍了关键基础设施面临的不断演变的风险,并讨论了关键五国(澳大利亚、加拿大、新西兰、英国和美国)如何实现关键基础设施保护方法的现代化。它还确定了加强国内关键基础设施安全性和弹性的共同方法,同时认识到鉴于关键基础设施的相互关联性,国际社会需要采取合作和…

【H.264】五分钟入门H.264协议

<> 博客简介&#xff1a;Linux、rtos系统&#xff0c;arm、stm32等芯片&#xff0c;嵌入式高级工程师、面试官、架构师&#xff0c;日常技术干货、个人总结、职场经验分享   <> 公众号&#xff1a;嵌入式技术部落   <> 系列专栏&#xff1a;C/C、Linux、rt…

以现在的社会形势走向,选什么专业好?

随着高考结束&#xff0c;选专业的话题又开始变得越来越热门。因为很多学生都想知道自己更适合什么样的专业&#xff0c;如何结合未来的社会形势来选择更好的专业&#xff0c;这的确是一个很考验能力的问题&#xff0c;因为有太多人曾经为了选择专业而纠结过。 高考志愿填报选…

基于多源数据的密码攻防领域知识图谱构建

源自&#xff1a; 信息安全与通信保密杂志社 作者&#xff1a;曹增辉 , 郭渊博 , 黄慧敏 摘 要 提高网络空间安全的密码攻防能力&#xff0c;需要形成可表示、可共享、可分析的领域知识模式和知识库。利用自顶向下的构建方法&#xff0c;并通过本体构建方法梳理密码攻防领域…

Nginx 配置文件

Nginx的配置文件的组成部分&#xff1a; 主配置文件&#xff1a;nginx.conf子配置文件&#xff1a;include conf.d/*.conf 全局配置 nginx 有多种模块 核心模块&#xff1a;是 Nginx 服务器正常运行必不可少的模块&#xff0c;提供错误日志记录 、配置文件解析 、事件驱动机…

Android Studio 2023版本切换DNK版本

选择自己需要的版本下载 根目录下的配置路劲注意切换 build.gradle文件下的ndkVersion也要配好对应版本

现代信息检索笔记(二)——布尔检索

目录 信息检索概述 IR vs数据库: 结构化vs 非结构化数据 结构化数据 非结构化数据 半结构化数据 传统信息检索VS现代信息检索 布尔检索 倒排索引 一个例子 建立词项&#xff08;可以是字、词、短语、一句话&#xff09;-文档的关联矩阵。 关联向量 检索效果的评价 …

使用Visual Studio Code记笔记

因为学习需要&#xff0c;记笔记是很有必要的&#xff0c;平常发CSDN&#xff08;都让CSDN是很棒的哈&#xff09;&#xff0c;后来使用VS Code的时候发现了很多插件&#xff0c;觉得做笔记还是相对不错的&#xff0c;主要用到的还是Markdown 主要设计的插件包括&#xff1a; …

第3章:数据结构

树 对稀疏矩阵的压缩方法有三种&#xff1a; 1、三元组顺序表 2、行逻辑连接的顺序表 3、十字链表 同义词才会占用同个位置&#xff0c;从而需要进行多次比较。这些关键字的第一个可以不是e的同义词&#xff0c;可以是排在e之前的关键字正好占了那个位置。 Dijkstra算法主要特点…

MySQL 高级SQL高级语句(二)

一.CREATE VIEW 视图 可以被当作是虚拟表或存储查询。 视图跟表格的不同是&#xff0c;表格中有实际储存数据记录&#xff0c;而视图是建立在表格之上的一个架构&#xff0c;它本身并不实际储存数据记录。 临时表在用户退出或同数据库的连接断开后就自动消失了&#xff0c;而…

javassmmysql 宣和酒店点餐系统37378-计算机毕业设计项目选题推荐(附源码)

目 录 摘要 1 绪论 1.1研究背景 1.2目的 1.3ssm框架介绍 1.3论文结构与章节安排 2 宣和酒店点餐系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章…

Pascal 函数入门示例,及其汇编语言分析

1&#xff0c; Pascal 函数的定义格式 pascal 函数的定义语法格式: FUNCTION 函数名(形式参数表):函数类型; VAR 函数的变量说明; BEGIN 函数体; END; 2&#xff0c;Pascal 函数定义调用示例 order_self.pas 代码&#xff1a; PROGRAM example01;va…

黑龙江等保测评科普

黑龙江的等保测评&#xff0c;即信息安全等级保护测评&#xff0c;是中国网络安全法框架下的一项重要制度&#xff0c;旨在提升信息系统安全水平&#xff0c;保护关键信息基础设施免受威胁。下面是对黑龙江等保测评流程和要求的科普&#xff1a; 1. 等保测评概念 定义&#xff…