nos-utils

Python forcing generators for NOAA NOS-OFS ocean forecast systems.

nos-utils is a standalone Python package that replaces the legacy Fortran and shell preprocessing toolchain (COMF/STOFS) with a modular, testable pipeline for generating atmospheric, ocean-boundary, river, and tidal forcing files for SCHISM-based Operational Forecast Systems (OFS).

Supported systems

  • SECOFS – SE Coastal Ocean Forecast System. Production-ready on WCOSS2: validated against the operational COMF Fortran pipeline (SSH RMSE = 0.5 mm, R = 0.999998; prep time ~23 min vs 40 min sequential).

  • STOFS-3D-ATL – Storm Surge 3-D Atlantic. Work in progress: atmospheric, NWM medium-range river, ADT satellite SSH blending, and interior T/S nudging are wired up; operational validation ongoing.

  • UFS-Coastal variants – DATM-coupled (nws=4) configurations of both SECOFS and STOFS-3D-ATL (ESMF mesh + HRRR/GFS Delaunay blender).

  • Ensemble – GEFS-driven perturbation members via ForcingConfig.for_ensemble().

Key features

  • Byte-identical COMF output structure – obc.tar (6 files), sflux_*.nc, bctides.in, param.nml, vsource.th, and source_sink.in match the layout expected by the operational model.

  • Precomputed INTERP_REMESH weights – The Fortran triangulation is exported once and replayed every cycle as pure NumPy gather operations, giving Fortran-equivalent accuracy (SSH RMSE 0.5 mm) at a fraction of the runtime.

  • ROI subsetting for RTOFS – 3D temperature and salinity reads are restricted to the SECOFS subdomain, yielding ~92% I/O reduction.

  • Parallel Phase 1 prep – GFS, HRRR, NWM, and tidal processors run concurrently via ThreadPoolExecutor; heavy NetCDF+Delaunay work for RTOFS and nudging runs sequentially in Phase 2.

  • Full-cycle speedup – Total SECOFS prep: ~23 min with nos-utils vs ~40 min for the sequential COMF Fortran pipeline (1.7x faster).

  • Interior T/S nudging – Python generates TEM_nu.nc and SAL_nu.nc for all 32,613 SECOFS interior nodes using precomputed nudge weights.

  • Unified API across OFS – the same PrepOrchestrator runs SECOFS or STOFS just by swapping the ForcingConfig factory.

  • NCO environment bridge – nco_bridge.run_prep() reads standard PDY/cyc/COMINgfs/FIXofs variables and drives the orchestrator from inside a J-job.

  • 206 unit tests passing – all inputs are synthetic fixtures; no data downloads required.

Quick start

pip install -e ".[full]"
from nos_utils.config import ForcingConfig
from nos_utils.orchestrator import PrepOrchestrator

config = ForcingConfig.for_secofs(pdy="20260406", cyc=0)
paths = {
    "gfs":    "/lfs/h1/ops/prod/com/gfs/v16.3",
    "hrrr":   "/lfs/h1/ops/prod/com/hrrr/v4.1",
    "rtofs":  "/lfs/h1/ops/prod/com/rtofs/v2.5",
    "nwm":    "/lfs/h1/ops/prod/com/nwm/v3.0",
    "fix":    "/path/to/fix/secofs",
    "output": "/tmp/secofs_prep",
}
result = PrepOrchestrator(config, paths).run(phase="nowcast")
print(result.summary())

CLI:

nos-utils prep --ofs secofs --pdy 20260406 --cyc 0 \
    --gfs /data/gfs --hrrr /data/hrrr --rtofs /data/rtofs \
    --nwm /data/nwm --fix /data/fix/secofs --output /work/prep/

nos-utils list   # show available OFS factories and processors

Documentation contents