Skip to content

Commit 9035be9

Browse files
Switch hash table build to use source grid overlaps; add point-in-cell check
The query method now requires a point in cell check method to be sent in as an argument
1 parent 0bce72e commit 9035be9

File tree

2 files changed

+231
-94
lines changed

2 files changed

+231
-94
lines changed

parcels/_index_search.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,47 @@ def _search_time_index(field: Field, time: datetime):
4040
return np.atleast_1d(tau), np.atleast_1d(ti)
4141

4242

43+
def curvilinear_point_in_cell(grid, y: np.ndarray, x: np.ndarray, yi: np.ndarray, xi: np.ndarray):
44+
xsi = eta = -1.0 * np.ones(len(x), dtype=float)
45+
invA = np.array(
46+
[
47+
[1, 0, 0, 0],
48+
[-1, 1, 0, 0],
49+
[-1, 0, 0, 1],
50+
[1, -1, 1, -1],
51+
]
52+
)
53+
54+
px = np.array([grid.lon[yi, xi], grid.lon[yi, xi + 1], grid.lon[yi + 1, xi + 1], grid.lon[yi + 1, xi]])
55+
py = np.array([grid.lat[yi, xi], grid.lat[yi, xi + 1], grid.lat[yi + 1, xi + 1], grid.lat[yi + 1, xi]])
56+
57+
a, b = np.dot(invA, px), np.dot(invA, py)
58+
aa = a[3] * b[2] - a[2] * b[3]
59+
bb = a[3] * b[0] - a[0] * b[3] + a[1] * b[2] - a[2] * b[1] + x * b[3] - y * a[3]
60+
cc = a[1] * b[0] - a[0] * b[1] + x * b[1] - y * a[1]
61+
det2 = bb * bb - 4 * aa * cc
62+
63+
with np.errstate(divide="ignore", invalid="ignore"):
64+
det = np.where(det2 > 0, np.sqrt(det2), eta)
65+
eta = np.where(abs(aa) < 1e-12, -cc / bb, np.where(det2 > 0, (-bb + det) / (2 * aa), eta))
66+
67+
xsi = np.where(
68+
abs(a[1] + a[3] * eta) < 1e-12,
69+
((y - py[0]) / (py[1] - py[0]) + (y - py[3]) / (py[2] - py[3])) * 0.5,
70+
(x - a[0] - a[2] * eta) / (a[1] + a[3] * eta),
71+
)
72+
73+
is_in_cell = np.where((xsi >= 0) & (xsi <= 1) & (eta >= 0) & (eta <= 1), 1, 0)
74+
75+
return is_in_cell
76+
77+
4378
def _search_indices_curvilinear_2d(
4479
grid: XGrid, y: float, x: float, yi_guess: int | None = None, xi_guess: int | None = None
4580
): # TODO fix typing instructions to make clear that y, x etc need to be ndarrays
4681
yi, xi = yi_guess, xi_guess
4782
if yi is None or xi is None:
48-
yi, xi = grid.get_spatial_hash().query(y, x)
83+
yi, xi = grid.get_spatial_hash().query(y, x, curvilinear_point_in_cell)
4984

5085
xsi = eta = -1.0 * np.ones(len(x), dtype=float)
5186
invA = np.array(

0 commit comments

Comments
 (0)