Skip to content

Commit 66ab10a

Browse files
Regridding OBC Velocity & Tracers Test 1 (#276)
* First Try * New test * Rm tides test * This --------- Co-authored-by: Ashley Barnes <53282288+ashjbarnes@users.noreply.github.com>
1 parent 89de811 commit 66ab10a

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

tests/conftest.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import xarray as xr
44
import numpy as np
55
import regional_mom6 as rmom6
6+
from regional_mom6 import experiment
67

78
# Define the path where the curvilinear hgrid file is expected in the Docker container
89
DOCKER_FILE_PATH = "/data/small_curvilinear_hgrid.nc"
@@ -12,6 +13,56 @@
1213
LOCAL_FILE_PATH = str(os.getenv("local_curvilinear_hgrid"))
1314

1415

16+
@pytest.fixture
17+
def toy_glorys_ds():
18+
lat = np.linspace(2, 4, 2)
19+
lon = np.linspace(2, 4, 2)
20+
depth = np.linspace(0, 1, 2)
21+
time = np.arange(1, dtype=float)
22+
s4 = (len(time), len(depth), len(lat), len(lon))
23+
s3 = (len(time), len(lat), len(lon))
24+
c4 = {
25+
"time": time,
26+
"depth": depth,
27+
"lat": lat,
28+
"lon": lon,
29+
}
30+
c3 = {"time": time, "lat": lat, "lon": lon}
31+
d4 = ["time", "depth", "lat", "lon"]
32+
d3 = ["time", "lat", "lon"]
33+
# Define 2D spatial pattern
34+
temp_2d = np.array([[20.0, 22.0], [24.0, 26.0]]) # shape (lat, lon)
35+
temp_4d = np.broadcast_to(temp_2d[np.newaxis, np.newaxis, :, :], s4).copy()
36+
ds = xr.Dataset(
37+
{
38+
"temp": xr.DataArray(temp_4d, dims=d4, coords=c4),
39+
"salt": xr.DataArray(np.full(s4, 35.0), dims=d4, coords=c4),
40+
"u": xr.DataArray(np.zeros(s4), dims=d4, coords=c4),
41+
"v": xr.DataArray(np.zeros(s4), dims=d4, coords=c4),
42+
"eta": xr.DataArray(np.zeros(s3), dims=d3, coords=c3),
43+
}
44+
)
45+
ds.time.attrs = {"units": "days"}
46+
return ds
47+
48+
49+
@pytest.fixture
50+
def simple_experiment(tmp_path):
51+
return experiment(
52+
longitude_extent=[-5, 5],
53+
latitude_extent=[0, 10],
54+
date_range=["2003-01-01 00:00:00", "2003-01-01 00:00:00"],
55+
resolution=0.1,
56+
number_vertical_layers=5,
57+
layer_thickness_ratio=1,
58+
depth=1000,
59+
mom_run_dir=tmp_path / "rundir",
60+
mom_input_dir=tmp_path / "inputdir",
61+
fre_tools_dir="toolpath",
62+
hgrid_type="even_spacing",
63+
)
64+
65+
1566
@pytest.fixture
1667
def get_curvilinear_hgrid():
1768
# Check if the file exists in the Docker-specific location

tests/test_regridding.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import pytest
55
import xarray as xr
66
import numpy as np
7+
import pandas as pd
8+
from regional_mom6.regional_mom6 import segment
9+
import shutil
710

811

912
# Not testing get_arakawa_c_points, coords, & create_regridder
@@ -264,3 +267,101 @@ def test_mask_dataset(get_curvilinear_hgrid):
264267
).all() == True and (
265268
(ds["temp"][0, 0, 0][(((end_ind * 2) + 1) + 1 + 1) : -1] == fill_value)
266269
).all() == True # Ensure data is not in land area
270+
271+
272+
def test_regrid_velocity_tracers(toy_glorys_ds, tmp_path):
273+
"""
274+
Correctness test for segment.regrid_velocity_tracers.
275+
276+
Checks:
277+
- Output OBC file is written
278+
- Variables follow the {var}_{segment_name} naming convention
279+
- Temperature is in Celsius (< 100)
280+
- 3D fields have companion dz_* variables
281+
- Vertical coordinate is re-encoded as incremental integers
282+
- Perpendicular dimension has size 1
283+
"""
284+
lat = np.linspace(2, 4, 2)
285+
lon = np.linspace(2, 4, 2)
286+
hgrid = rmom6.generate_rectangular_hgrid(lat, lon)
287+
288+
seg_name = "segment_001"
289+
outfolder = tmp_path / "inputdir"
290+
outfolder.mkdir()
291+
292+
# Minimal synthetic boundary dataset covering the east edge of the hgrid (lon ≈ 10, lat 0-10)
293+
294+
infile = tmp_path / "east_raw.nc"
295+
ds = toy_glorys_ds
296+
ds.to_netcdf(infile)
297+
ds.close()
298+
299+
varnames = {
300+
"xh": "lon",
301+
"yh": "lat",
302+
"time": "time",
303+
"eta": "eta",
304+
"zl": "depth",
305+
"u": "u",
306+
"v": "v",
307+
"tracers": {"temp": "temp", "salt": "salt"},
308+
}
309+
310+
seg = segment(
311+
hgrid=hgrid,
312+
outfolder=outfolder,
313+
segment_name=seg_name,
314+
orientation="east",
315+
startdate="2003-01-01 00:00:00",
316+
)
317+
segment_out, _ = seg.regrid_velocity_tracers(infile, varnames, arakawa_grid="A")
318+
319+
# Salt is spatially constant, so all ocean points must match exactly.
320+
salt_vals = segment_out[f"salt_{seg_name}"].values
321+
np.testing.assert_allclose(salt_vals, 35.0, rtol=1e-4)
322+
323+
# Temp is spatially varying (20–26 °C), so just check values are exact (hgrid overlap with seg exactly)
324+
temp_vals = segment_out[f"temp_{seg_name}"].values
325+
assert temp_vals[0, 0, 0, 0] == 22
326+
assert temp_vals[0, 0, 1, 0] == 26
327+
328+
seg_north = segment(
329+
hgrid=hgrid,
330+
outfolder=outfolder,
331+
segment_name=seg_name,
332+
orientation="north",
333+
startdate="2003-01-01 00:00:00",
334+
)
335+
segment_out_north, _ = seg_north.regrid_velocity_tracers(
336+
infile, varnames, arakawa_grid="A"
337+
)
338+
temp_vals = segment_out_north[f"temp_{seg_name}"].values
339+
assert temp_vals[0, 0, 0, 0] == 24
340+
assert temp_vals[0, 0, 0, 1] == 26
341+
342+
# Mess with hgrid, subtract 1
343+
344+
folder = outfolder / "weights"
345+
shutil.rmtree(
346+
folder
347+
) # removes weights so they aren't saved with the old hgrid, and forces them to be recomputed with the new hgrid
348+
folder.mkdir() # recreate the empty folder
349+
hgrid["x"] = hgrid.x + 1
350+
hgrid["y"] = hgrid.y + 1
351+
seg_regrid = segment(
352+
hgrid=hgrid,
353+
outfolder=outfolder,
354+
segment_name=seg_name,
355+
orientation="west",
356+
startdate="2003-01-01 00:00:00",
357+
)
358+
seg_regridded, _ = seg_regrid.regrid_velocity_tracers(
359+
infile, varnames, arakawa_grid="A", regridding_method="bilinear"
360+
)
361+
temp_vals = seg_regridded[f"temp_{seg_name}"].values
362+
assert (
363+
np.abs(temp_vals[0, 0, 0, 0] - 23) < 0.01
364+
) # bilinear at this point is nearly the average of the toy_glory_ds values (22 and 24 and 26 and 20)
365+
assert (
366+
temp_vals[0, 0, 1, 0] == 0
367+
) # The bilinear regridding would be zero here because there isn't 4 points

0 commit comments

Comments
 (0)