Running xhycom at scale

Running xhycom at scale#

Regridding or averaging full HYCOM archives is compute-intensive: a single year of daily fields on the TP2 grid to GLORYS is ~1.6 TB, and streaming through all daily files to build monthly means takes the same wall time regardless of how many output steps you want. For multi-year or multi-variable runs, a Slurm batch job is more practical than an interactive notebook kernel.

This page covers the most common pre-compute pattern — monthly means on a fixed grid — and points to real-world Slurm script examples.

Setup#

The cells below pick up where Regridding left off — the same HYCOM dataset, GLORYS mask, and cached regrid weights.

import numpy as np
import xarray as xr
import xhycom
import dask
from dask.diagnostics import ProgressBar
import os
os.environ["XHYCOM_CACHE_DIR"] = f"/cluster/projects/nn2993k/{os.environ['USER']}/.xhycom-cache-dir"

grid = "/cluster/home/nlo043/NERSC-HYCOM-CICE/TP2a0.10/topo/regional.grid"
DATA_PATH = "/nird/datalake/NS9481K/shuang/TP2_output/expt_02.8/"

ds = xhycom.open_mfdataset(DATA_PATH + "archm.2020*", grid=grid, chunks={"time": 1}, postprocess=True)

GRIDS = "/nird/datapeak/NS9481K/MERCATOR_DATA/REGULAR_GRID_COORD"
glorys = xr.open_dataset(f"{GRIDS}/GLO-MFC_001_030_mask_bathy.nc")

Computing monthly means#

The full daily regrid is large (~1.6 TB for four variables) and rarely what you want — the usual target is monthly means on the GLORYS grid. For two variables (temp and salin) that is ~26 GB for one year and takes around 10 minutes to write on Olivia.

How you build the monthly mean is a methodology question in its own right — average on the native layers (thickness-weighted, the way HYCOM averages online) or at fixed depth — and the choice matters near fronts and the seasonal pycnocline. That’s covered in Time-averaging on a moving vertical grid; here we use the recommended thickness-weighted route and write it to disk.

Even the monthly-mean route streams through all the daily fields to build the average, so runtime scales with the full time range, not just the 12 output steps. A single year interactively in a notebook is fine; a multi-decade run belongs in a Slurm script — see below.

# Recommended monthly mean: thickness-weighted on the native layers (the HYCOM
# monthly mean — see time-averaging.ipynb), then a single regrid. Cheap: ~12 remaps.
h = ds["thknss"]
hbar = h.resample(time="1MS").mean()
monthly = (ds[["temp", "salin"]] * h).resample(time="1MS").mean() / hbar.where(hbar > 0)
monthly["thknss"] = hbar
g_month = xhycom.regrid(monthly, target=glorys, grid=grid, weights=True)
g_month   # 12 monthly means on the GLORYS grid
<xarray.Dataset> Size: 26GB
Dimensions:  (time: 12, lat: 624, lon: 4320, depth: 50)
Coordinates:
  * time     (time) object 96B 2020-01-01 00:00:00 ... 2020-12-01 00:00:00
  * lat      (lat) float32 2kB 38.08 38.17 38.25 38.33 ... 89.83 89.92 90.0
  * lon      (lon) float32 17kB -180.0 -179.9 -179.8 ... 179.8 179.8 179.9
  * depth    (depth) float64 400B 0.494 1.541 2.646 ... 5.275e+03 5.728e+03
Data variables:
    temp     (time, lat, lon, depth) float64 13GB dask.array<chunksize=(1, 624, 4320, 50), meta=np.ndarray>
    salin    (time, lat, lon, depth) float64 13GB dask.array<chunksize=(1, 624, 4320, 50), meta=np.ndarray>
Attributes:
    iversn:         23
    iexpt:          28
    yrflag:         3
    archive_type:   mean
    long_name:      layer thickness
    units:          m
    comment:        converted from Pa (factor 0.000101978)
    regrid_method:  conservative
# Cap workers to keep memory bounded — the ~GB regridded chunks can outrun the
# single-locked netCDF writer at high parallelism.
with dask.config.set(num_workers=4), ProgressBar():
    g_month.to_netcdf("/cluster/work/projects/nn2993k/nlo043/hycom_on_glorys_2020_monthly.nc")
[########################################] | 100% Completed | 599.47 s

Slurm script examples#

The OHC-GLORYS-HYCOM repository contains worked examples of running xhycom regridding in Slurm batch jobs on Sigma2 Olivia. Start there when setting up a multi-year regrid pipeline.