Skip to content

Commit d5ce99d

Browse files
committed
test if p.lon/p.lat are between min/max of grid
1 parent f512df4 commit d5ce99d

3 files changed

Lines changed: 31 additions & 25 deletions

File tree

parcels/field.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,13 @@ def search_indices_rectilinear(self, x, y, z, ti=-1, time=-1, search2D=False):
403403
grid = self.grid
404404
xi = yi = -1
405405

406-
if grid.mesh is not 'spherical':
407-
if x < grid.lon[0] or x > grid.lon[-1]:
406+
if not grid.zonal_periodic:
407+
if x < grid.lonlat_minmax[0] or x > grid.lonlat_minmax[1]:
408408
raise FieldSamplingError(x, y, z, field=self)
409+
if y < grid.lonlat_minmax[2] or y > grid.lonlat_minmax[3]:
410+
raise FieldSamplingError(x, y, z, field=self)
411+
412+
if grid.mesh is not 'spherical':
409413
lon_index = grid.lon < x
410414
if lon_index.all():
411415
xi = len(grid.lon) - 2
@@ -425,11 +429,6 @@ def search_indices_rectilinear(self, x, y, z, ti=-1, time=-1, search2D=False):
425429
lon_fixed[indices.argmin():] += 360
426430
if x < lon_fixed[0]:
427431
lon_fixed -= 360
428-
if not grid.zonal_periodic:
429-
if (grid.lon[0] < grid.lon[-1]) and (x < grid.lon[0] or x > grid.lon[-1]):
430-
raise FieldSamplingError(x, y, z, field=self)
431-
elif (grid.lon[0] >= grid.lon[-1]) and (x < grid.lon[0] and x > grid.lon[-1]):
432-
raise FieldSamplingError(x, y, z, field=self)
433432

434433
lon_index = lon_fixed < x
435434
if lon_index.all():
@@ -444,8 +443,6 @@ def search_indices_rectilinear(self, x, y, z, ti=-1, time=-1, search2D=False):
444443
xi += 1
445444
xsi = (x-lon_fixed[xi]) / (lon_fixed[xi+1]-lon_fixed[xi])
446445

447-
if y < grid.lat[0] or y > grid.lat[-1]:
448-
raise FieldSamplingError(x, y, z, field=self)
449446
lat_index = grid.lat < y
450447
if lat_index.all():
451448
yi = len(grid.lat) - 2
@@ -485,12 +482,13 @@ def search_indices_curvilinear(self, x, y, z, xi, yi, ti=-1, time=-1, search2D=F
485482
[1, -1, 1, -1]])
486483
maxIterSearch = 1e6
487484
it = 0
488-
if (not grid.zonal_periodic) or grid.mesh == 'flat':
489-
if (grid.lon[0, 0] < grid.lon[0, -1]) and (x < grid.lon[0, 0] or x > grid.lon[0, -1]):
490-
raise FieldSamplingError(x, y, z, field=self)
491-
elif (grid.lon[0, 0] >= grid.lon[0, -1]) and (x < grid.lon[0, 0] and x > grid.lon[0, -1]):
492-
raise FieldSamplingError(x, y, z, field=self)
493-
if y < np.min(grid.lat) or y > np.max(grid.lat):
485+
if not grid.zonal_periodic:
486+
if x < grid.lonlat_minmax[0] or x > grid.lonlat_minmax[1]:
487+
if grid.lon[0, 0] < grid.lon[0, -1]:
488+
raise FieldSamplingError(x, y, z, field=self)
489+
elif x < grid.lon[0, 0] and x > grid.lon[0, -1]: # This prevents from crashing in [160, -160]
490+
raise FieldSamplingError(x, y, z, field=self)
491+
if y < grid.lonlat_minmax[2] or y > grid.lonlat_minmax[3]:
494492
raise FieldSamplingError(x, y, z, field=self)
495493

496494
while xsi < 0 or xsi > 1 or eta < 0 or eta > 1:

parcels/grid.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def __init__(self, lon, lat, time, time_origin, mesh):
5252
self.meridional_halo = 0
5353
self.lat_flipped = False
5454
self.defer_load = False
55-
self.lonlat_minmax = np.array([np.min(lon), np.max(lon), np.min(lat), np.max(lat)])
55+
self.lonlat_minmax = np.array([np.min(lon), np.max(lon), np.min(lat), np.max(lat)], dtype=np.float32)
5656

5757
@property
5858
def ctypes_struct(self):
@@ -203,6 +203,7 @@ def add_periodic_halo(self, zonal, meridional, halosize=5):
203203
self.lat, self.lat[0:halosize] + latshift))
204204
self.ydim = self.lat.size
205205
self.meridional_halo = halosize
206+
self.lonlat_minmax = np.array([np.min(self.lon), np.max(self.lon), np.min(self.lat), np.max(self.lat)], dtype=np.float32)
206207

207208

208209
class RectilinearZGrid(RectilinearGrid):

parcels/include/index_search.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,21 +129,24 @@ static inline ErrorCode search_indices_rectilinear(float x, float y, float z, CS
129129
float *xvals = grid->lon;
130130
float *yvals = grid->lat;
131131
float *zvals = grid->depth;
132+
float *xy_minmax = grid->lonlat_minmax;
132133
int sphere_mesh = grid->sphere_mesh;
133134
int zonal_periodic = grid->zonal_periodic;
134135
int z4d = grid->z4d;
135136

137+
if (zonal_periodic == 0){
138+
if ((x < xy_minmax[0]) || (x > xy_minmax[1]))
139+
return ERROR_OUT_OF_BOUNDS;
140+
}
141+
if ((y < xy_minmax[2]) || (y > xy_minmax[3]))
142+
return ERROR_OUT_OF_BOUNDS;
143+
136144
if (sphere_mesh == 0){
137-
if (x < xvals[0] || x > xvals[xdim-1]) {return ERROR_OUT_OF_BOUNDS;}
138145
while (*xi < xdim-1 && x > xvals[*xi+1]) ++(*xi);
139146
while (*xi > 0 && x < xvals[*xi]) --(*xi);
140147
*xsi = (x - xvals[*xi]) / (xvals[*xi+1] - xvals[*xi]);
141148
}
142149
else{
143-
if (zonal_periodic == 0){
144-
if ((xvals[0] < xvals[xdim-1]) && (x < xvals[0] || x > xvals[xdim-1])) {return ERROR_OUT_OF_BOUNDS;}
145-
else if ((xvals[0] >= xvals[xdim-1]) && (x < xvals[0] && x > xvals[xdim-1])) {return ERROR_OUT_OF_BOUNDS;}
146-
}
147150

148151
float xvalsi = xvals[*xi];
149152
// TODO: this will fail if longitude is e.g. only [-180, 180] (so length 2)
@@ -176,7 +179,6 @@ static inline ErrorCode search_indices_rectilinear(float x, float y, float z, CS
176179
*xsi = (x - xvalsi) / (xvalsi1 - xvalsi);
177180
}
178181

179-
if (y < yvals[0] || y > yvals[ydim-1]) {return ERROR_OUT_OF_BOUNDS;}
180182
while (*yi < ydim-1 && y > yvals[*yi+1]) ++(*yi);
181183
while (*yi > 0 && y < yvals[*yi]) --(*yi);
182184

@@ -220,6 +222,7 @@ static inline ErrorCode search_indices_curvilinear(float x, float y, float z, CS
220222
float *xvals = grid->lon;
221223
float *yvals = grid->lat;
222224
float *zvals = grid->depth;
225+
float *xy_minmax = grid->lonlat_minmax;
223226
int sphere_mesh = grid->sphere_mesh;
224227
int zonal_periodic = grid->zonal_periodic;
225228
int z4d = grid->z4d;
@@ -228,10 +231,14 @@ static inline ErrorCode search_indices_curvilinear(float x, float y, float z, CS
228231
float (* xgrid)[xdim] = (float (*)[xdim]) xvals;
229232
float (* ygrid)[xdim] = (float (*)[xdim]) yvals;
230233

231-
if (zonal_periodic == 0 || sphere_mesh == 0) {
232-
if ((xgrid[0][0] < xgrid[0][xdim-1]) && (x < xgrid[0][0] || x > xgrid[0][xdim-1])) {return ERROR_OUT_OF_BOUNDS;}
233-
else if ((xgrid[0][0] >= xgrid[0][xdim-1]) && (x < xgrid[0][0] && x > xgrid[0][xdim-1])) {return ERROR_OUT_OF_BOUNDS;}
234+
if (zonal_periodic == 0){
235+
if ((x < xy_minmax[0]) || (x > xy_minmax[1])){
236+
if (xgrid[0][0] < xgrid[0][xdim-1]) {return ERROR_OUT_OF_BOUNDS;}
237+
else if (x < xgrid[0][0] && x > xgrid[0][xdim-1]) {return ERROR_OUT_OF_BOUNDS;}
238+
}
234239
}
240+
if ((y < xy_minmax[2]) || (y > xy_minmax[3]))
241+
return ERROR_OUT_OF_BOUNDS;
235242

236243
double a[4], b[4];
237244

0 commit comments

Comments
 (0)