|
4 | 4 | import pytest |
5 | 5 | import xarray as xr |
6 | 6 | import numpy as np |
| 7 | +import pandas as pd |
| 8 | +from regional_mom6.regional_mom6 import segment |
| 9 | +import shutil |
7 | 10 |
|
8 | 11 |
|
9 | 12 | # Not testing get_arakawa_c_points, coords, & create_regridder |
@@ -264,3 +267,101 @@ def test_mask_dataset(get_curvilinear_hgrid): |
264 | 267 | ).all() == True and ( |
265 | 268 | (ds["temp"][0, 0, 0][(((end_ind * 2) + 1) + 1 + 1) : -1] == fill_value) |
266 | 269 | ).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