首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >xwrf | 批量处理多个wrf文件并插值指定高度层

xwrf | 批量处理多个wrf文件并插值指定高度层

作者头像
用户11172986
发布2026-04-24 18:40:13
发布2026-04-24 18:40:13
610
举报
文章被收录于专栏:气python风雨气python风雨

xwrf | 批量处理多个wrf文件并插值指定高度层

项目概述

之前有发出节目预告,不知各位有没看到公众号的文章。

WRF(Weather Research and Forecasting)模式是广泛应用于气象研究和业务预报的中尺度数值天气预报系统,其输出结果通常包含多维气象要素场。在实际科研和业务应用中,我们经常需要处理多个WRF输出文件(通常以NetCDF格式存储),并对这些数据进行后处理和分析。其中,将三维气象要素插值到指定高度层是一项常见且重要的需求,这有助于在不同高度层次上分析大气状态,便于垂直剖面分析或与其他观测数据进行对比。

本教程将介绍如何使用xWRF工具(基于xarray的WRF数据处理扩展)批量处理多个WRF输出文件,并将三维气象场插值到用户指定的高度层。这种方法相比传统逐文件处理方式更加高效,能够充分利用Python生态中的并行处理能力,同时保持代码的简洁性和可读性。

环境设置

安装依赖

代码语言:javascript
复制
!pip install xwrf -i https://pypi.mirrors.ustc.edu.cn/simple/
代码语言:javascript
复制
!pip install pint_xarray  -i https://pypi.mirrors.ustc.edu.cn/simple/
代码语言:javascript
复制
!pip install xgcm -i https://pypi.mirrors.ustc.edu.cn/simple/

导入必要的库

代码语言:javascript
复制
import xarray as xr
import xwrf
# for unit conversion (`pint` DataArray accessor)
import pint_xarray
# for `dask`-accelerated computation
from distributed import LocalCluster, Client
import numpy as np
import glob

数据处理

代码语言:javascript
复制
files = sorted(glob.glob('/home/mw/input/typhoon9537/*'))

wrf_ds = xr.open_mfdataset(
    files,
    parallel=True,
    concat_dim="Time",
    combine="nested",
    chunks={'Time': 1},
)
print(wrf_ds)
代码语言:javascript
复制


代码语言:javascript
复制


代码语言:javascript
复制
import time
start = time.time()
xwrf_ds = wrf_ds.xwrf.postprocess()
end = time.time()
print(f"{end - start} s elapsed")
print(xwrf_ds)
代码语言:javascript
复制
0.21268272399902344 s elapsed

代码语言:javascript
复制


基于dask对于批量读取的wrf数据进行坐标转换,速度很快

交错网格处理(风变量)

wrf数据是交错网格,这个我们在

本项目来源于和鲸社区,使用转载需要标注来源 作者: 酷炫用户名 来源: https://www.heywhale.com/mw/project/67093d064f507a297c3142f3 WRF | 为什么wrfout中经向风和纬向风的格点数不一样

中讲过,不再赘述

在wrf-python中,我们可以直接读取ua和va解决

在xwrf中则需要另外处理

代码语言:javascript
复制
print(xwrf_ds['U'])
代码语言:javascript
复制
<xarray.DataArray 'U' (Time: 13, z: 34, y: 437, x_stag: 448)> Size: 346MB
dask.array<concatenate, shape=(13, 34, 437, 448), dtype=float32, chunksize=(1, 34, 437, 448), chunktype=numpy.ndarray>
Coordinates:
    XTIME    (Time) datetime64[ns] 104B dask.array<chunksize=(1,), meta=np.ndarray>
    XLAT_U   (y, x_stag) float32 783kB dask.array<chunksize=(437, 448), meta=np.ndarray>
    XLONG_U  (y, x_stag) float32 783kB dask.array<chunksize=(437, 448), meta=np.ndarray>
  * z        (z) float32 136B 0.9965 0.988 0.9765 0.962 ... 0.033 0.0195 0.0065
  * Time     (Time) datetime64[ns] 104B 2019-08-08T18:00:00 ... 2019-08-09T06...
  * y        (y) float64 3kB -6.54e+05 -6.51e+05 -6.48e+05 ... 6.51e+05 6.54e+05
  * x_stag   (x_stag) float64 4kB -6.705e+05 -6.675e+05 ... 6.675e+05 6.705e+05
Attributes:
    FieldType:      104
    MemoryOrder:    XYZ
    description:    x-wind component
    units:          m s-1
    stagger:        X
    standard_name:  x_wind
    grid_mapping:   wrf_projection
代码语言:javascript
复制
xwrf_ds['UA'] = xwrf_ds['U'].xwrf.destagger().variable
print(xwrf_ds['UA'])
代码语言:javascript
复制
<xarray.DataArray 'UA' (Time: 13, z: 34, y: 437, x: 447)> Size: 345MB
dask.array<mul, shape=(13, 34, 437, 447), dtype=float32, chunksize=(1, 34, 437, 447), chunktype=numpy.ndarray>
Coordinates:
    XLAT     (y, x) float32 781kB dask.array<chunksize=(437, 447), meta=np.ndarray>
    XLONG    (y, x) float32 781kB dask.array<chunksize=(437, 447), meta=np.ndarray>
    XTIME    (Time) datetime64[ns] 104B dask.array<chunksize=(1,), meta=np.ndarray>
    CLAT     (y, x) float32 781kB dask.array<chunksize=(437, 447), meta=np.ndarray>
  * z        (z) float32 136B 0.9965 0.988 0.9765 0.962 ... 0.033 0.0195 0.0065
  * Time     (Time) datetime64[ns] 104B 2019-08-08T18:00:00 ... 2019-08-09T06...
  * y        (y) float64 3kB -6.54e+05 -6.51e+05 -6.48e+05 ... 6.51e+05 6.54e+05
  * x        (x) float64 4kB -6.69e+05 -6.66e+05 -6.63e+05 ... 6.66e+05 6.69e+05
Attributes:
    FieldType:      104
    MemoryOrder:    XYZ
    description:    x-wind component
    units:          m s-1
    standard_name:  x_wind
    grid_mapping:   wrf_projection

可见格点数变化了

垂直层插值

对应wrf-python的interplevel函数的垂直层插值功能

xwrf则是选择了xgcm库作为外援进行垂直层插值

处理交错网格

代码语言:javascript
复制
from metpy.calc import wind_speed
import xgcm
import numpy as np
for field in ['U', 'V']:
    xwrf_ds[field] = xwrf_ds[field].xwrf.destagger().variable
xwrf_ds = xwrf_ds.metpy.quantify()

单层插值

代码语言:javascript
复制
import xgcm
import numpy as np
import pint_xarray

target_levels = np.array([250.]) # in hPa
#air_pressure = xwrf_ds.air_pressure.pint.to('hPa').metpy.dequantify()
air_pressure = xwrf_ds.air_pressure.metpy.convert_units('hPa').metpy.dequantify()
xwrf_ds['wind_speed'] =wind_speed(xwrf_ds.U, xwrf_ds.V).metpy.dequantify()

grid = xgcm.Grid(xwrf_ds, periodic=False)

_wind_speed = grid.transform(xwrf_ds.wind_speed.metpy.dequantify(), 'Z', target_levels, target_data=air_pressure, method='log')

_wind_speed = _wind_speed.compute()
代码语言:javascript
复制
/opt/conda/lib/python3.11/site-packages/xgcm/grid.py:989: 
代码语言:javascript
复制
print(_wind_speed)
代码语言:javascript
复制
<xarray.DataArray 'wind_speed' (Time: 13, y: 437, x: 447, air_pressure: 1)> Size: 20MB
array([[[[ 2.15332438],
         [ 2.05429516],
         [ 1.96162581],
         ...,
         [ 8.61106545],
         [ 8.51674219],
         [ 8.42776731]],

        [[ 2.12816252],
         [ 2.02488963],
         [ 1.92792811],
         ...,
         [ 8.91645327],
         [ 8.82431303],
         [ 8.73533366]],

        [[ 2.11298364],
         [ 2.00608941],
         [ 1.90560238],
         ...,
...
         ...,
         [15.60896739],
         [16.0766267 ],
         [15.59409096]],

        [[ 4.00628541],
         [ 4.02528941],
         [ 3.97536056],
         ...,
         [15.96039649],
         [16.50404221],
         [15.90062312]],

        [[ 4.04618942],
         [ 3.99713923],
         [ 3.95577495],
         ...,
         [15.36883414],
         [15.29024682],
         [15.2005086 ]]]])
Coordinates:
    XTIME         (Time) datetime64[ns] 104B 2019-08-08T18:00:00 ... 2019-08-...
  * Time          (Time) datetime64[ns] 104B 2019-08-08T18:00:00 ... 2019-08-...
    XLAT          (y, x) float32 781kB 20.89 20.89 20.89 ... 32.78 32.78 32.78
    XLONG         (y, x) float32 781kB 116.5 116.6 116.6 ... 130.2 130.2 130.3
    CLAT          (y, x) float32 781kB 20.89 20.89 20.89 ... 32.78 32.78 32.78
  * y             (y) float64 3kB -6.54e+05 -6.51e+05 ... 6.51e+05 6.54e+05
  * x             (x) float64 4kB -6.69e+05 -6.66e+05 ... 6.66e+05 6.69e+05
  * air_pressure  (air_pressure) float64 8B 250.0

多层插值

代码语言:javascript
复制
from metpy.calc import wind_speed
import xgcm
import numpy as np
import xarray as xr

files = sorted(glob.glob('/home/mw/input/typhoon9537/*'))

xwrf_ds = xr.open_mfdataset(
    files,
    parallel=True,
    concat_dim="Time",
    combine="nested",
    chunks={'Time': 1},
).xwrf.postprocess()

def calculate_wind_speed(dataset, target_levels):
    """计算并插值风速到指定气压层"""
    # 解交错网格并添加单位
    for field in ['U', 'V']:
        dataset[field] = dataset[field].xwrf.destagger().variable
    
    # 计算风速并确保是去量纲化的DataArray
    dataset['wind_speed'] = wind_speed(dataset.U, dataset.V).metpy.dequantify()
    print(dataset.air_pressure.pint)
    # 处理气压数据,确保是去量纲化的DataArray
#   air_pressure = dataset.air_pressure.pint.to('hPa').metpy.dequantify()
    air_pressure = dataset.air_pressure.metpy.convert_units('hPa').metpy.dequantify()
    # 创建xgcm网格
    grid = xgcm.Grid(dataset, periodic=False)
    
    # 执行插值
    result = grid.transform(
        dataset.wind_speed,
        'Z',
        target_levels,
        target_data=air_pressure,
        method='log'
    ).compute()  # 确保计算结果
    
    return result

# 使用示例
target_levels = np.array([850,725,500,250.,200])  # hPa
wind_speed_multi = calculate_wind_speed(xwrf_ds, target_levels)
代码语言:javascript
复制
<pint_xarray.accessors.PintDataArrayAccessor object at 0x7f2a16aa3510
代码语言:javascript
复制
print(wind_speed_multi)
代码语言:javascript
复制
<xarray.DataArray 'wind_speed' (Time: 13, y: 437, x: 447, air_pressure: 5)> Size: 102MB
array([[[[ 9.25609613,  8.34912411,  9.4607662 ,  2.15332438,
           3.45706554],
         [ 9.3940668 ,  8.52057594,  9.56193775,  2.05429516,
           3.56831646],
         [ 9.54101839,  8.70075069,  9.65882567,  1.96162581,
           3.69223884],
         ...,
         [22.81890334, 17.9803955 , 23.20878212,  8.61106545,
           7.77787846],
         [22.70740632, 17.86505295, 23.15872668,  8.51674219,
           7.60701875],
         [22.59427188, 17.75521747, 23.09905585,  8.42776731,
           7.4744698 ]],

        [[ 9.22080649,  8.39445186,  9.43068502,  2.12816252,
           3.34152052],
         [ 9.36072463,  8.56623378,  9.53015887,  2.02488963,
           3.45191456],
         [ 9.51037999,  8.74737881,  9.62507364,  1.92792811,
           3.57544112],
...
         [ 4.92995826,  5.77725726,  3.21912271, 15.96039649,
          20.74913331],
         [ 4.71819977,  5.79624439,  4.17212933, 16.50404221,
          21.64187518],
         [ 4.56275508,  6.07743758,  3.95430655, 15.90062312,
          21.35588073]],

        [[ 5.04970797,  3.97664761,  3.14422791,  4.04618942,
           8.55706546],
         [ 5.0531973 ,  4.00633996,  3.21976034,  3.99713923,
           8.47484533],
         [ 5.0878566 ,  4.01714974,  3.33147043,  3.95577495,
           8.39265859],
         ...,
         [ 5.47635917,  6.58052366,  3.33776199, 15.36883414,
          20.65481604],
         [ 5.50332557,  6.69873229,  3.81604314, 15.29024682,
          20.69798193],
         [ 5.1656812 ,  6.6051779 ,  3.81690317, 15.2005086 ,
          20.73190761]]]])
Coordinates:
    XLAT          (y, x) float32 781kB 20.89 20.89 20.89 ... 32.78 32.78 32.78
    XLONG         (y, x) float32 781kB 116.5 116.6 116.6 ... 130.2 130.2 130.3
    XTIME         (Time) datetime64[ns] 104B 2019-08-08T18:00:00 ... 2019-08-...
    CLAT          (y, x) float32 781kB 20.89 20.89 20.89 ... 32.78 32.78 32.78
  * Time          (Time) datetime64[ns] 104B 2019-08-08T18:00:00 ... 2019-08-...
  * y             (y) float64 3kB -6.54e+05 -6.51e+05 ... 6.51e+05 6.54e+05
  * x             (x) float64 4kB -6.69e+05 -6.66e+05 ... 6.66e+05 6.69e+05
  * air_pressure  (air_pressure) float64 40B 850.0 725.0 500.0 250.0 200.0

总结

总的来说,用习惯了wrf-python,对于xwrf还是不适应,之前一两行搞定插值的代码需要借助metpy xgcm等等外力来完成

当然xwrf本身设计的特点就是轻量化,这个也是没办法

其能够借助dask完成大量数据的计算也是值得肯定的

实际上这期还做了个动图

但是贴不上来,自行到和鲸的帖子看吧

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 气python风雨 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • xwrf | 批量处理多个wrf文件并插值指定高度层
    • 项目概述
    • 环境设置
      • 安装依赖
      • 导入必要的库
    • 数据处理
    • 交错网格处理(风变量)
    • 垂直层插值
      • 处理交错网格
    • 单层插值
    • 多层插值
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档