@@ -20,6 +20,40 @@ def test_invalid_positions():
2020 assert np .all (i == - 3 )
2121
2222
23+ def test_spherical_regional_bounds ():
24+ """Hash-grid bounds for spherical meshes are the Cartesian bounding box of the
25+ (regional) grid, not the whole unit cube, so quantization resolution is not
26+ wasted on parts of the sphere the grid does not cover.
27+ """
28+ ds = datasets ["2d_left_rotated" ]
29+ grid = FieldSet .from_sgrid_conventions (ds , mesh = "spherical" ).data_g .grid
30+ spatialhash = grid .get_spatial_hash ()
31+
32+ extents = np .array (
33+ [
34+ spatialhash ._xmax - spatialhash ._xmin ,
35+ spatialhash ._ymax - spatialhash ._ymin ,
36+ spatialhash ._zmax - spatialhash ._zmin ,
37+ ]
38+ )
39+ assert np .all (extents > 0.0 )
40+ assert np .all (extents < 2.0 ) # strictly tighter than the unit cube
41+
42+ # Queries at cell centers must still resolve to the correct cell
43+ lon , lat = grid .lon , grid .lat
44+ clon = 0.25 * (lon [:- 1 , :- 1 ] + lon [:- 1 , 1 :] + lon [1 :, :- 1 ] + lon [1 :, 1 :])
45+ clat = 0.25 * (lat [:- 1 , :- 1 ] + lat [:- 1 , 1 :] + lat [1 :, :- 1 ] + lat [1 :, 1 :])
46+ jj , ii = np .meshgrid (np .arange (clat .shape [0 ]), np .arange (clat .shape [1 ]), indexing = "ij" )
47+ j , i , _ = spatialhash .query (clat .ravel (), clon .ravel ())
48+ assert np .array_equal (j , jj .ravel ())
49+ assert np .array_equal (i , ii .ravel ())
50+
51+ # Points far outside the regional domain must not match any cell
52+ j , i , _ = spatialhash .query ([- 60.0 , 80.0 ], [120.0 , - 150.0 ])
53+ assert np .all (j == - 3 )
54+ assert np .all (i == - 3 )
55+
56+
2357def test_mixed_positions ():
2458 ds = datasets ["2d_left_rotated" ]
2559 grid = FieldSet .from_sgrid_conventions (ds , mesh = "flat" ).data_g .grid
0 commit comments