Skip to content

Commit b185396

Browse files
Merge pull request #2153 from OceanParcels/testing_nemo_spatialhash
Testing and fixing NEMO spatialhash index_search
2 parents b16fcc8 + 9e91ee0 commit b185396

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

parcels/_index_search.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import numpy as np
77

8+
from parcels._typing import Mesh
89
from parcels.tools.statuscodes import (
910
_raise_field_out_of_bound_error,
1011
_raise_field_sampling_error,
@@ -108,21 +109,13 @@ def _search_indices_curvilinear_2d(
108109
return (yi, eta, xi, xsi)
109110

110111

111-
def _reconnect_bnd_indices(yi: int, xi: int, ydim: int, xdim: int, sphere_mesh: bool):
112-
if xi < 0:
113-
if sphere_mesh:
114-
xi = xdim - 2
115-
else:
116-
xi = 0
117-
if xi > xdim - 2:
118-
if sphere_mesh:
119-
xi = 0
120-
else:
121-
xi = xdim - 2
122-
if yi < 0:
123-
yi = 0
124-
if yi > ydim - 2:
125-
yi = ydim - 2
126-
if sphere_mesh:
127-
xi = xdim - xi
112+
def _reconnect_bnd_indices(yi: int, xi: int, ydim: int, xdim: int, mesh: Mesh):
113+
xi = np.where(xi < 0, (xdim - 2) if mesh == "spherical" else 0, xi)
114+
xi = np.where(xi > xdim - 2, 0 if mesh == "spherical" else (xdim - 2), xi)
115+
116+
xi = np.where(yi > ydim - 2, xdim - xi if mesh == "spherical" else xi, xi)
117+
118+
yi = np.where(yi < 0, 0, yi)
119+
yi = np.where(yi > ydim - 2, ydim - 2, yi)
120+
128121
return yi, xi

tests/v4/test_index_search.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import numpy as np
22
import pytest
3+
import xarray as xr
34

45
from parcels._datasets.structured.generic import datasets
56
from parcels._index_search import _search_indices_curvilinear_2d
67
from parcels.field import Field
7-
from parcels.xgrid import (
8-
XGrid,
9-
)
8+
from parcels.tools.exampledata_utils import download_example_dataset
9+
from parcels.xgcm import Grid
10+
from parcels.xgrid import XGrid
1011

1112

1213
@pytest.fixture
@@ -51,3 +52,32 @@ def test_grid_indexing_fpoints(field_cone):
5152
]
5253
assert x > np.min(cell_lon) and x < np.max(cell_lon)
5354
assert y > np.min(cell_lat) and y < np.max(cell_lat)
55+
56+
57+
def test_indexing_nemo_curvilinear():
58+
data_folder = download_example_dataset("NemoCurvilinear_data")
59+
ds = xr.open_mfdataset(
60+
data_folder.glob("*.nc4"), combine="nested", data_vars="minimal", coords="minimal", compat="override"
61+
)
62+
ds = ds.isel({"time_counter": 0, "time": 0, "z_a": 0}, drop=True).rename(
63+
{"glamf": "lon", "gphif": "lat", "z": "depth"}
64+
)
65+
xgcm_grid = Grid(ds, coords={"X": {"left": "x"}, "Y": {"left": "y"}}, periodic=False)
66+
grid = XGrid(xgcm_grid)
67+
68+
# Test points on the NEMO 1/4 degree curvilinear grid
69+
lats = np.array([-30, 0, 88])
70+
lons = np.array([30, 60, -150])
71+
72+
yi, eta, xi, xsi = _search_indices_curvilinear_2d(grid, lats, lons)
73+
74+
# Construct cornerpoints px
75+
px = np.array([grid.lon[yi, xi], grid.lon[yi, xi + 1], grid.lon[yi + 1, xi + 1], grid.lon[yi + 1, xi]])
76+
77+
# Maximum 5 degree difference between px values
78+
for i in range(lons.shape[0]):
79+
np.testing.assert_allclose(px[1, i], px[:, i], atol=5)
80+
81+
# Reconstruct lons values from cornerpoints
82+
xx = (1 - xsi) * (1 - eta) * px[0] + xsi * (1 - eta) * px[1] + xsi * eta * px[2] + (1 - xsi) * eta * px[3]
83+
np.testing.assert_allclose(xx, lons, atol=1e-6)

0 commit comments

Comments
 (0)