@@ -202,6 +202,7 @@ class GridDataset(object):
202202
203203 GRAVITY = 9.807
204204 EARTH_RADIUS = 6370997.
205+ # EARTH_RADIUS = 6378136.3
205206 N = 1
206207
207208 def __init__ (self , filename , x_name , y_name , centered = None ):
@@ -374,7 +375,6 @@ def copy(self, grid_in, grid_out):
374375 )
375376 self .vars [grid_out ] = self .grid (grid_in ).copy ()
376377
377-
378378 def grid (self , varname ):
379379 """give grid required
380380 """
@@ -1068,6 +1068,7 @@ def spectrum_lonlat(self, grid_name, area=None, ref=None, **kwargs):
10681068 def add_uv (self , grid_height ):
10691069 """Compute a u and v grid
10701070 """
1071+ data = self .grid (grid_height )
10711072 h_dict = self .variables_description [grid_height ]
10721073 for variable in ('u' , 'v' ):
10731074 self .variables_description [variable ] = dict (
@@ -1076,44 +1077,67 @@ def add_uv(self, grid_height):
10761077 args = tuple ((variable , * h_dict ['args' ][1 :])),
10771078 kwargs = h_dict ['kwargs' ].copy (),
10781079 )
1080+
10791081 self .variables_description [variable ]['attrs' ]['units' ] += '/s'
1080- data = self .grid (grid_height )
1081- gof = sin (deg2rad (self .y_c )) * ones ((self .x_c .shape [0 ], 1 )) * 4. * pi / 86400.
1082- # gof = sin(deg2rad(self.y_c))* ones((self.x_c.shape[0], 1)) * 4. * pi / (23 * 3600 + 56 *60 +4.1 )
1082+ # Divide by sideral day
1083+ gof = sin (deg2rad (self .y_c )) * ones ((self .x_c .shape [0 ], 1 )) * 4. * pi / (23 * 3600 + 56 * 60 + 4.1 )
10831084 with errstate (divide = 'ignore' ):
10841085 gof = self .GRAVITY / (gof * ones ((self .x_c .shape [0 ], 1 )))
10851086
1086- m_y = array ((1 , 0 , - 1 ))
1087- m_x = array ((1 , 0 , - 1 ))
1088- d_hy = convolve (
1089- data ,
1090- weights = m_y .reshape ((- 1 , 1 )).T
1091- )
1092- mask = convolve (
1093- int8 (data .mask ),
1094- weights = ones (m_y .shape ).reshape ((1 , - 1 ))
1095- )
1096- d_hy = ma .array (d_hy , mask = mask != 0 )
1087+ w = [
1088+ array ((3 , - 32 , 168 , - 672 , 0 , 672 , - 168 , 32 , - 3 )) / 840. ,
1089+ array ((- 1 , 9 , - 45 , 0 , 45 , - 9 , 1 )) / 60. ,
1090+ array ((1 , - 8 , 0 , 8 , - 1 )) / 12. ,
1091+ array ((- 1 , 0 , 1 )) / 2. ,
1092+ array ((- 1 , 1 )), # array((0, -1, 1))
1093+ (1 , array ((- 1 , 1 ))), # array((-1, 1, 0))
1094+ ]
1095+
1096+ # Compute v
1097+ self .vars ['v' ] = None
1098+ mode = 'wrap' if self .is_circular () else 'reflect'
1099+ for m_x in w :
1100+ if isinstance (m_x , tuple ):
1101+ shift , m_x = m_x
1102+ data_ = data .copy ()
1103+ data_ [shift :] = data [:- shift ]
1104+ data_ [:shift ] = data [- shift :]
1105+ else :
1106+ data_ = data
1107+ d_hx = convolve (data_ , weights = m_x .reshape ((- 1 , 1 )), mode = mode )
1108+ mask = convolve (int8 (data_ .mask ), weights = ones (m_x .shape ).reshape ((- 1 , 1 )), mode = mode )
1109+ d_hx = ma .array (d_hx , mask = mask != 0 )
1110+
1111+ d_x_degrees = convolve (self .x_c , m_x , mode = mode ).reshape ((- 1 , 1 ))
1112+ d_x_degrees = (d_x_degrees + 180 ) % 360 - 180
1113+ d_x = self .EARTH_RADIUS * 2 * pi / 360 * d_x_degrees * cos (deg2rad (self .y_c ))
1114+ v = d_hx / d_x * gof
1115+ if self .vars ['v' ] is None :
1116+ self .vars ['v' ] = v
1117+ else :
1118+ self .vars ['v' ][self .vars ['v' ].mask ] = v [self .vars ['v' ].mask ]
1119+
1120+ # Compute u
1121+ self .vars ['u' ] = None
1122+ for m_y in w :
1123+ if isinstance (m_y , tuple ):
1124+ shift , m_y = m_y
1125+ data_ = data .copy ()
1126+ data_ [:, shift :] = data [:, :- 1 ]
1127+ else :
1128+ data_ = data
10971129
1098- d_y = self .EARTH_RADIUS * 2 * pi / 360 * convolve (self .y_c , m_y )
1130+ d_hy = convolve (data_ , weights = m_y .reshape ((- 1 , 1 )).T )
1131+ mask = convolve (int8 (data_ .mask ), weights = ones (m_y .shape ).reshape ((1 , - 1 )))
1132+ d_hy = ma .array (d_hy , mask = mask != 0 )
10991133
1100- self .vars ['u' ] = - d_hy / d_y * gof
1101- mode = 'wrap' if self .is_circular () else 'reflect'
1102- d_hx = convolve (
1103- data ,
1104- weights = m_x .reshape ((- 1 , 1 )),
1105- mode = mode ,
1106- )
1107- mask = convolve (
1108- int8 (data .mask ),
1109- weights = ones (m_x .shape ).reshape ((- 1 , 1 )),
1110- mode = mode ,
1111- )
1112- d_hx = ma .array (d_hx , mask = mask != 0 )
1113- d_x_degrees = convolve (self .x_c , m_x , mode = mode ).reshape ((- 1 , 1 ))
1114- d_x_degrees = (d_x_degrees + 180 ) % 360 - 180
1115- d_x = self .EARTH_RADIUS * 2 * pi / 360 * d_x_degrees * cos (deg2rad (self .y_c ))
1116- self .vars ['v' ] = d_hx / d_x * gof
1134+ d_y = self .EARTH_RADIUS * 2 * pi / 360 * convolve (self .y_c , m_y )
1135+
1136+ u = - d_hy / d_y * gof
1137+ if self .vars ['u' ] is None :
1138+ self .vars ['u' ] = u
1139+ else :
1140+ self .vars ['u' ][self .vars ['u' ].mask ] = u [self .vars ['u' ].mask ]
11171141
11181142 def speed_coef_mean (self , contour ):
11191143 """some nan can be compute over contour if we are near border,
@@ -1226,8 +1250,9 @@ def bbox_indice_regular(vertices, x0, y0, xstep, ystep, N, circular, x_size):
12261250 lat_min , lat_max = lat .min (), lat .max ()
12271251 i_x0 , i_y0 = int32 (((lon_min - x0 ) % 360 ) // xstep ), int32 ((lat_min - y0 ) // ystep )
12281252 i_x1 , i_y1 = int32 (((lon_max - x0 ) % 360 ) // xstep ), int32 ((lat_max - y0 ) // ystep )
1229-
12301253 if circular :
12311254 slice_x = (i_x0 - N ) % x_size , (i_x1 + N + 1 ) % x_size
1255+ else :
1256+ slice_x = min (i_x0 - N , 0 ), i_x1 + N + 1
12321257 slice_y = i_y0 - N , i_y1 + N + 1
12331258 return slice_x , slice_y
0 commit comments