计算温度的偏导数(温度的水平平流)。

huangapple go评论82阅读模式
英文:

calculate the partial derivatives of temperature (horizontal advection of temperature)

问题

我想知道计算温度在x和y方向(温度的水平平流)的偏导数的最正确的方法是什么。
第二段代码使用了温度、纬向风和经向风的数据矩阵。提取温度(T)、纬向风分量(u)和经向风分量(v)的数据。

import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import metpy
import metpy.calc as mpcalc
from metpy.units import units

# 打开包含数据的GRIB文件
ds = xr.open_dataset('cdas1_2022011700_.t00z.pgrbh00.grib2', engine='cfgrib', backend_kwargs={
                     'filter_by_keys': {'typeOfLevel': 'isobaricInhPa'}})
ds = ds.metpy.parse_cf()

# 过滤数据,只获取750 hPa的层级
u_775hPa = ds.u.sel(isobaricInhPa=775)
v_775hPa = ds.v.sel(isobaricInhPa=775)
t_775hPa = ds.t.sel(isobaricInhPa=775)

# 在x和y方向上计算温度的偏导数(温度的水平平流)
# 初始化dT_dx和dT_dy为零矩阵
dT_dx = np.zeros_like(t_775hPa.values)
dT_dy = np.zeros_like(t_775hPa.values)
# 使用numpy.gradient计算空间导数的有限差分
dT_dx, dT_dy = np.gradient(t_775hPa)

# 计算v和温度水平梯度在x和y方向上的乘积(Tadv=-(u750*dTdX+v750*dTdY))
horizontal_gradient = -u_775hPa * dT_dx - v_775hPa * dT_dy

# 创建图形和子图
fig = plt.figure(figsize=(16, 14))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())

# 添加地理特征
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS)
ax.add_feature(cfeature.STATES)

# 添加经纬度线
ax.gridlines(draw_labels=True, linewidth=0.5, color='gray', alpha=0.5, linestyle='--')

# 定义地图属性
central_lon, central_lat = -33, -55
extent = [-75, -45, -40, -16]
ax.set_extent(extent, crs=ccrs.PlateCarree())
ax.set_title("horizontal advection of temperature", fontsize=16, fontweight='bold')

# 绘制horizontal_gradient的地图
contourf = ax.contourf(ds['longitude'], ds['latitude'], horizontal_gradient,
                           cmap='rainbow', transform=ccrs.PlateCarree())

# 绘制colorbar
cbar_temp = plt.colorbar(
    contourf, ax=ax, orientation='horizontal', aspect=40, pad=0.02)
cbar_temp.set_label('horizontal advection of temperature', size=14)

# 显示地图
plt.show()

或者

import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import metpy
import metpy.calc as mpcalc
from metpy.units import units

# 打开包含数据的GRIB文件
ds = xr.open_dataset('cdas1_2022011700_.t00z.pgrbh00.grib2', engine='cfgrib', backend_kwargs={
                     'filter_by_keys': {'typeOfLevel': 'isobaricInhPa'}})
ds = ds.metpy.parse_cf()
# 计算温度、经向风和纬向风的水平平流
# 提取温度(T)、经向风分量(u)和纬向风分量(v)的数据
T = ds.t
u = ds.u
v = ds.v

# 计算温度在x和y方向上的偏导数
dT_dx, dT_dy = np.gradient(T, axis=(1,2))

# 计算温度的平流
advection_of_temperature = -u * dT_dx - v * dT_dy

# 现在你可以访问温度平流的值:
advection_of_temperature = advection_of_temperature.sel(isobaricInhPa=775)
# 创建图形和子图
fig = plt.figure(figsize=(16, 14))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())

# 添加地理特征
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS)
ax.add_feature(cfeature.STATES)

# 添加经纬度线
ax.gridlines(draw_labels=True, linewidth=0.5, color='gray', alpha=0.5, linestyle='--')

# 定义地图属性
central_lon, central_lat = -33, -55
extent = [-75, -45, -40, -16]
ax.set_extent(extent, crs=ccrs.PlateCarree())
ax.set_title("horizontal advection of temperature", fontsize=16, fontweight='bold')

# 绘制advection_of_temperature的地图
contourf = ax.contourf(ds['longitude'], ds['latitude'], advection_of_temperature,
                           cmap='rainbow', transform=ccrs.PlateCarree())

# 绘制colorbar
cbar_temp = plt.colorbar(
    contourf, ax=ax, orientation='horizontal', aspect=40, pad=0.02)
cbar_temp.set_label('horizontal advection of temperature', size=14)

# 显示地图
plt.show()
英文:

I would like to know which way is the most correct to calculate the partial derivatives of temperature in the x and y directions (horizontal advection of temperature)
The second code used the data matrix of temperature, zonal wind and meridional wind. Extract the data for temperature (T), zonal wind component (u) and meridional wind component (v)

import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import metpy
import metpy.calc as mpcalc
from metpy.units import units
# Abrir el archivo GRIB con los datos
ds = xr.open_dataset('cdas1_2022011700_.t00z.pgrbh00.grib2', engine='cfgrib', backend_kwargs={
'filter_by_keys': {'typeOfLevel': 'isobaricInhPa'}})
ds = ds.metpy.parse_cf()
# Filtrar los datos para obtener solo el nivel de 750 hPa
u_775hPa = ds.u.sel(isobaricInhPa=775)
v_775hPa = ds.v.sel(isobaricInhPa=775)
t_775hPa = ds.t.sel(isobaricInhPa=775)
# Calcular las derivadas parciales de la temperatura en las direcciones x e y (advección horizontal de temperatura)
# Inicialización de dTdX con ceros
dT_dx = np.zeros_like(t_775hPa.values)
dT_dy = np.zeros_like(t_775hPa.values)
# Usamos numpy.gradient para calcular las diferencias finitas para las derivadas espaciales
dT_dx, dT_dy = np.gradient(t_775hPa)
# Calcular el producto entre v y el gradiente horizontal de T en las direcciones x e y (Tadv=-(u750*dTdX+v750*dTdY))
gradiente_horizontal = -u_775hPa * dT_dx - v_775hPa * dT_dy
# Crear la figura y el subplot
fig = plt.figure(figsize=(16, 14))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
# Agregar características geográficas
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS)
ax.add_feature(cfeature.STATES)
# Agregar las líneas de latitud y longitud
ax.gridlines(draw_labels=True, linewidth=0.5, color='gray', alpha=0.5, linestyle='--')
# Definir algunas propiedades del mapa
central_lon, central_lat = -33, -55
extent = [-75, -45, -40, -16]
ax.set_extent(extent, crs=ccrs.PlateCarree())
ax.set_title(
"horizontal advection of temperature", fontsize=16, fontweight='bold')
# Dibujar el mapa de gradiente_horizontal
contourf = ax.contourf(ds['longitude'], ds['latitude'], gradiente_horizontal,
cmap= 'rainbow' , transform=ccrs.PlateCarree())
#ploteo la barra de referencias
cbar_temp = plt.colorbar(
contourf, ax=ax, orientation='horizontal',aspect=40, pad=0.02)
cbar_temp.set_label('horizontal advection of temperature ', size=14)
# Mostrar el mapa
plt.show()

o

import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import metpy
import metpy.calc as mpcalc
from metpy.units import units
# Abrir el archivo GRIB con los datos
ds = xr.open_dataset('cdas1_2022011700_.t00z.pgrbh00.grib2', engine='cfgrib', backend_kwargs={
'filter_by_keys': {'typeOfLevel': 'isobaricInhPa'}})
ds = ds.metpy.parse_cf()
# calcular advección de temperatura para la matriz de datos de temperatura, viento zonal y viento meridional
# Extraer los datos de temperatura (T), componente zonal del viento (u) y componente meridional del viento (v)
T = ds.t
u = ds.u
v = ds.v
# Calcular las derivadas parciales de temperatura en las direcciones x e y
dT_dx, dT_dy = np.gradient(T, axis=(1,2))
# Calcular la advección de temperatura
advection_of_temperature = -u * dT_dx - v * dT_dy
# Ahora puedes acceder a los valores de la advección de temperatura:
advection_of_temperature = advection_of_temperature.sel(isobaricInhPa=775)
# Crear la figura y el subplot
fig = plt.figure(figsize=(16, 14))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
# Agregar características geográficas
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS)
ax.add_feature(cfeature.STATES)
# Agregar las líneas de latitud y longitud
ax.gridlines(draw_labels=True, linewidth=0.5, color='gray', alpha=0.5, linestyle='--')
# Definir algunas propiedades del mapa
central_lon, central_lat = -33, -55
extent = [-75, -45, -40, -16]
ax.set_extent(extent, crs=ccrs.PlateCarree())
ax.set_title(
"horizontal advection of temperature", fontsize=16, fontweight='bold')
# Dibujar el mapa de gradiente_horizontal
contourf = ax.contourf(ds['longitude'], ds['latitude'], advection_of_temperature,
cmap= 'rainbow' , transform=ccrs.PlateCarree())
#ploteo la barra de referencias
cbar_temp = plt.colorbar(
contourf, ax=ax, orientation='horizontal',aspect=40, pad=0.02)
cbar_temp.set_label('horizontal advection of temperature ', size=14)
# Mostrar el mapa
plt.show()

答案1

得分: 2

使用np.gradient应该是可以的,无论你选择哪种方法,但是你的代码中还有另一个错误。你假设np.gradient的返回值是dt_dxdt_dy。然而,数据的原始顺序是压力 x 纬度 x 经度。这意味着你在计算平流时出现了错误,因为你将风分量和梯度分量弄混了。

此外,你将dT/d(lat)用作dT/dy,这在单位上是不正确的,不能与风相乘以获得正确的温度/时间的量纲。

由于你已经在使用MetPy,实现你的目标最简单的方法是使用MetPy的平流函数,它可以利用xarray的坐标和其他元数据来自动执行“正确的操作”(事先使用parse_cf()甚至不是必需的):

import metpy.calc as mpcalc
mpcalc.advection(ds.t, u=ds.u, v=ds.v)
英文:

The use np.gradient should be fine regardless of which approach you choose, but there is another bug in your code. You assume the return from np.gradient is dt_dx, dt_dy. However, the original order of the data is pressure x latitude x longitude. This means you've incorrectly calculated advection above because you're mismatching the wind components and gradient components.

Also, you're using dT/d(lat) as dT/dy, which isn't unit-wise correct to multiply with wind and to get the right dimensionality of temperature/time.

Since you're already using MetPy, the easiest way to accomplish your goal is to use MetPy's advection function, which can take advantage of xarray coordinates and other metadata to do the "right thing" more or less automatically (using parse_cf() in advance isn't even really necessary):

import metpy.calc as mpcalc
mpcalc.advection(ds.t, u=ds.u, v=ds.v)

huangapple
  • 本文由 发表于 2023年8月8日 22:06:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定