Skip to content

Commit 986cd45

Browse files
committed
copy _search_indices_curvilinear and rename
1 parent 85b0d10 commit 986cd45

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

parcels/_index_search.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,96 @@ def _search_indices_rectilinear(
270270
return (zeta, eta, xsi, _ei)
271271

272272

273+
## TODO : Still need to implement the search_indices_curvilinear
274+
def _search_indices_curvilinear_2d(field: Field, time, z, y, x, ti, particle=None, search2D=False):
275+
if particle:
276+
zi, yi, xi = field.unravel_index(particle.ei)
277+
else:
278+
xi = int(field.xdim / 2) - 1
279+
yi = int(field.ydim / 2) - 1
280+
xsi = eta = -1.0
281+
grid = field.grid
282+
invA = np.array([[1, 0, 0, 0], [-1, 1, 0, 0], [-1, 0, 0, 1], [1, -1, 1, -1]])
283+
maxIterSearch = 1e6
284+
it = 0
285+
tol = 1.0e-10
286+
if not grid.zonal_periodic:
287+
if x < field.lonlat_minmax[0] or x > field.lonlat_minmax[1]:
288+
if grid.lon[0, 0] < grid.lon[0, -1]:
289+
_raise_field_out_of_bound_error(z, y, x)
290+
elif x < grid.lon[0, 0] and x > grid.lon[0, -1]: # This prevents from crashing in [160, -160]
291+
_raise_field_out_of_bound_error(z, y, x)
292+
if y < field.lonlat_minmax[2] or y > field.lonlat_minmax[3]:
293+
_raise_field_out_of_bound_error(z, y, x)
294+
295+
while xsi < -tol or xsi > 1 + tol or eta < -tol or eta > 1 + tol:
296+
px = np.array([grid.lon[yi, xi], grid.lon[yi, xi + 1], grid.lon[yi + 1, xi + 1], grid.lon[yi + 1, xi]])
297+
if grid.mesh == "spherical":
298+
px[0] = px[0] + 360 if px[0] < x - 225 else px[0]
299+
px[0] = px[0] - 360 if px[0] > x + 225 else px[0]
300+
px[1:] = np.where(px[1:] - px[0] > 180, px[1:] - 360, px[1:])
301+
px[1:] = np.where(-px[1:] + px[0] > 180, px[1:] + 360, px[1:])
302+
py = np.array([grid.lat[yi, xi], grid.lat[yi, xi + 1], grid.lat[yi + 1, xi + 1], grid.lat[yi + 1, xi]])
303+
a = np.dot(invA, px)
304+
b = np.dot(invA, py)
305+
306+
aa = a[3] * b[2] - a[2] * b[3]
307+
bb = a[3] * b[0] - a[0] * b[3] + a[1] * b[2] - a[2] * b[1] + x * b[3] - y * a[3]
308+
cc = a[1] * b[0] - a[0] * b[1] + x * b[1] - y * a[1]
309+
if abs(aa) < 1e-12: # Rectilinear cell, or quasi
310+
eta = -cc / bb
311+
else:
312+
det2 = bb * bb - 4 * aa * cc
313+
if det2 > 0: # so, if det is nan we keep the xsi, eta from previous iter
314+
det = np.sqrt(det2)
315+
eta = (-bb + det) / (2 * aa)
316+
if abs(a[1] + a[3] * eta) < 1e-12: # this happens when recti cell rotated of 90deg
317+
xsi = ((y - py[0]) / (py[1] - py[0]) + (y - py[3]) / (py[2] - py[3])) * 0.5
318+
else:
319+
xsi = (x - a[0] - a[2] * eta) / (a[1] + a[3] * eta)
320+
if xsi < 0 and eta < 0 and xi == 0 and yi == 0:
321+
_raise_field_out_of_bound_error(0, y, x)
322+
if xsi > 1 and eta > 1 and xi == grid.xdim - 1 and yi == grid.ydim - 1:
323+
_raise_field_out_of_bound_error(0, y, x)
324+
if xsi < -tol:
325+
xi -= 1
326+
elif xsi > 1 + tol:
327+
xi += 1
328+
if eta < -tol:
329+
yi -= 1
330+
elif eta > 1 + tol:
331+
yi += 1
332+
(yi, xi) = _reconnect_bnd_indices(yi, xi, grid.ydim, grid.xdim, grid.mesh)
333+
it += 1
334+
if it > maxIterSearch:
335+
print(f"Correct cell not found after {maxIterSearch} iterations")
336+
_raise_field_out_of_bound_error(0, y, x)
337+
xsi = max(0.0, xsi)
338+
eta = max(0.0, eta)
339+
xsi = min(1.0, xsi)
340+
eta = min(1.0, eta)
341+
342+
if grid.zdim > 1 and not search2D:
343+
if grid._gtype == GridType.CurvilinearZGrid:
344+
try:
345+
(zi, zeta) = search_indices_vertical_z(field.grid, field.gridindexingtype, z)
346+
except FieldOutOfBoundError:
347+
_raise_field_out_of_bound_error(z, y, x)
348+
elif grid._gtype == GridType.CurvilinearSGrid:
349+
(zi, zeta) = search_indices_vertical_s(field.grid, field.interp_method, time, z, y, x, ti, yi, xi, eta, xsi)
350+
else:
351+
zi = -1
352+
zeta = 0
353+
354+
if not ((0 <= xsi <= 1) and (0 <= eta <= 1) and (0 <= zeta <= 1)):
355+
_raise_field_sampling_error(z, y, x)
356+
357+
if particle:
358+
particle.ei[field.igrid] = field.ravel_index(zi, yi, xi)
359+
360+
return (zeta, eta, xsi, zi, yi, xi)
361+
362+
273363
## TODO : Still need to implement the search_indices_curvilinear
274364
def _search_indices_curvilinear(field: Field, time, z, y, x, ti, particle=None, search2D=False):
275365
if particle:

0 commit comments

Comments
 (0)