-
Notifications
You must be signed in to change notification settings - Fork 1
/
azim_wind_latlon.py
88 lines (75 loc) · 2.85 KB
/
azim_wind_latlon.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Function to convert wind from (time,lat,lon) to the tangential
# wind as f(time,z,x,y) based on a TC track.
#
# INPUTS:
# track_file - file path and name for netCDF file containing track as clon,clat
# (generated by the program run_tracking.py)
# u - zonal wind as (time,x,y) (note, the order of x,y is arbitrary)
# v - meridional wind " "
# lon - array of longitude points as (x,y) [deg]
# lat - " " latitude points
# t0, t1 - bounding time indices of var, assuming shorter in time than clon/clat
#
# RETURNS:
# returns a time,x,y series masked array of identical shape to var.
#
# James Ruppert
# jruppert@ou.edu
# September 2022
# from netCDF4 import Dataset
# import numpy as np
from netCDF4 import Dataset
import numpy as np
import sys
def azim_wind_latlon(track_file, u, v, lon, lat, t0, t1):
# Settings
# rmax = 3 # degrees
# Input dimensions
nt,nz,nx1,nx2 = u.shape
# Function to account for crossing of the Intl Date Line
def dateline_lon_shift(lon_in, reverse):
if reverse == 0:
lon_offset = np.zeros(lon_in.shape)
lon_offset[np.where(lon_in < 0)] += 360
else:
lon_offset = np.zeros(lon_in.shape)
lon_offset[np.where(lon_in > 180)] -= 360
# return lon_in + lon_offset
return lon_offset
# Read TC track
ncfile = Dataset(track_file)
clon = ncfile.variables['clon'][:] # deg
clat = ncfile.variables['clat'][:] # deg
ncfile.close()
# Check for crossing Date Line
if (lon.min() < 0) and (lon.max() > 0):
lon_offset = dateline_lon_shift(lon, reverse=0)
clon_offset = dateline_lon_shift(clon, reverse=0)
else:
lon_offset = 0
clon_offset = 0
# Center grid on track
lon4d = np.repeat((lon+lon_offset)[np.newaxis,np.newaxis,:,:], nt, axis=0)
lat4d = np.repeat(lat[np.newaxis,np.newaxis,:,:], nt, axis=0)
lon4d -= (clon+clon_offset)[t0:t1,np.newaxis,np.newaxis,np.newaxis]
lat4d -= clat[t0:t1,np.newaxis,np.newaxis,np.newaxis]
# Get radius and azimuth
radius4d = np.sqrt( lon4d**2 + lat4d**2 )
azim = np.arctan(lat4d/lon4d)
azim[(lon4d < 0 )] += np.pi
# Subtract storm motion
deg2x = 6371e3*np.pi/180 # m / deg
# Assume hourly time steps
dt = 3600. # s/time step
mpsec = deg2x/dt # m / deg / (s / time step)
u_track = np.gradient(clon+clon_offset) * np.cos(clat*np.pi/180) * mpsec # deg / time step --> m / s
v_track = np.gradient(clat) * mpsec # deg / time step --> m / s
# print('U = ',u_track)
# print('V = ',v_track)
# Get tangential wind
vtx = (u - u_track[t0:t1,np.newaxis,np.newaxis,np.newaxis]) * np.sin(azim)
vty = (v - v_track[t0:t1,np.newaxis,np.newaxis,np.newaxis]) * np.cos(azim)
# vtx = u * np.sin(azim)
# vty = v * np.cos(azim)
v_tan = vty - vtx
return v_tan