Local DriftCast: trajectory calculations, ensembles, and updates
This document describes the equations and operational workflow implemented by the Local DriftCast trajectory viewer. It is intended to make every displayed track reproducible from its archived forcing inputs and solver settings.
The active viewer contains two kinds of cases:
- nine observation-backed validation cases for Hooper Bay, Englullrarmiut, and Freebird; and
- five hypothetical Okinawa priority forecasts, each with a five-point north-south release line and no observations yet.
The operational calculation code is in
../data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/.
The generated viewer and its currently published case files are in
spotter_validation_viewer/.
1. Coordinate and notation conventions
All horizontal vectors use east-north order:
where is eastward and is northward. Velocities are in , positions are longitude/latitude in decimal degrees, and internal times are UTC Unix seconds.
| Symbol | Meaning | Source variable(s) |
|---|---|---|
| Eulerian surface-ocean current | SMOC uo, vo at the shallowest depth | |
| surface Stokes drift | SMOC vsdx, vsdy for Okinawa; wave-product VSDX, VSDY for validation | |
| draft-averaged Stokes drift used by the validation cases | derived from VSDX, VSDY, and VTPK | |
| 10 m wind | IFS u10, v10 | |
| tidal drift | SMOC utide, vtide | |
| full SMOC surface velocity | SMOC utotal, vtotal | |
| modeled buoy velocity | calculated | |
| local east/north position | calculated | |
| longitude and latitude | calculated or observed | |
| mean Earth radius | 6,371,000 m |
The full SMOC variables are treated as the composite velocity supplied by the product. The code does not add Stokes drift or tidal drift to again.
2. Forcing products
Operational Okinawa forecasts
The Okinawa calculations use:
- Copernicus Marine SMOC dataset
cmems_mod_glo_phy_anfc_merged-uv_PT1H-i, includinguo,vo,vsdx,vsdy,utide,vtide,utotal, andvtotal; - ECMWF deterministic IFS 10 m wind,
u10andv10; and - the Copernicus global wave forecast for viewer-only wave height, period, and direction backgrounds.
All ocean-velocity components used by a single Okinawa run come from one archived SMOC snapshot. This prevents the SMOC and finite-inertia tracks from silently mixing forecast cycles.
The regional SMOC request spans 115-145 degrees E and 15-35 degrees N, from one hour before release through one hour after the 72-hour forecast. The extra hour on each side is required by the centered material-derivative calculation.
Observation-backed validation cases
The nine fixed examples use the locally archived currents, waves, and winds associated with their historical release windows. Wind switches from ERA5 to the archived IFS forecast. If a gap exists between the last ERA5 time and first IFS time, the code linearly bridges the two endpoints.
The validation cases use a draft-averaged Stokes velocity. With peak period , deep-water wave number
draft , and , the factor is
Therefore
The Okinawa forecast generator instead uses the SMOC vsdx/vsdy surface
values directly. This is an intentional implementation difference that must be
retained when reproducing the archived results.
3. Interpolation
Forcing is sampled at every ensemble member’s current time and position. The implementation performs:
- bilinear interpolation over the four surrounding longitude/latitude cells;
- renormalization of the spatial weights if one or more corners are missing;
- linear interpolation between the two surrounding forcing times.
For a spatial field value , the four bilinear weights are
and the missing-value-aware estimate is
where contains the finite corners. Linear time interpolation is
Coordinates outside an input axis are clamped to the nearest boundary by the interpolator. Operational input coverage is therefore checked before a run so time-boundary clamping is not used as a substitute for missing forecast data.
4. Trajectory models
The active Okinawa viewer compares two trajectory formulations: the SMOC additive model and the finite-inertia model. The earlier standalone simple track is no longer plotted as a separate model because it differs from the SMOC formulation primarily by omitting the tidal contribution.
4.1 SMOC formulation: simple model plus tides
The SMOC trajectory retains the direct additive structure of the simple model and adds tidal drift. In physical-component notation, the displayed model is
The active coefficients are
| Coefficient | Value | Interpretation |
|---|---|---|
| 1.0 | full current | |
| 1.0 | full Stokes term | |
| 1.0 | full tidal term | |
| 0.012 | 1.2% of 10 m wind |
For the operational calculation, SMOC supplies these water-motion components
as the composite utotal and vtotal variables. The equation evaluated by the
integrator is therefore
This is the former simple current + Stokes + windage formulation with the tidal term included. The windage coefficient remains , or 1.2% of the 10 m wind.
For the validation examples, in this expression is replaced by the draft-averaged defined above.
utotal and vtotal are used exactly once. The separately published current,
Stokes, and tidal fields remain available as diagnostic viewer backgrounds;
they are not added a second time to the SMOC trajectory.
The SMOC model uses a 60 s integration step. For a velocity held over one step , the spherical position update is
with angular increments converted from radians to degrees. Positions are saved hourly, including the release position, producing 73 points for a 72-hour run.
4.2 Finite-inertia formulation
The finite-inertia model evolves both position and buoy velocity. Define the water velocity and relative velocities as
Again, the validation cases use , while Okinawa uses the SMOC surface Stokes velocity.
The effective mass includes added mass:
For each fluid ,
and the drag coefficient is evaluated in three Reynolds-number regimes:
The water and air drag accelerations are represented by
With Coriolis parameter
the exact component equations implemented in the solver are
The water material derivative is
It is evaluated with centered differences using and :
with analogous centered differences in east and north. The derivative is refreshed every 600 s and the local water and wind velocities every 60 s.
The solver uses forward Euler:
The Okinawa finite-inertia runs use . The northern validation cases use 4 s and the Freebird validation cases use 1 s. Okinawa is initialized with the local current + Stokes + windage velocity. Its subsequent finite-inertia evolution remains unchanged and does not substitute the SMOC tidal composite for . The validation cases instead initialize velocity from a linear fit to the observed track over approximately +/-30 minutes for the northern buoys and +/-15 minutes for Freebird.
Finite-inertia constants
| Variable | Value | Units | Meaning |
|---|---|---|---|
| 7.45 | kg | buoy mass | |
| 0.0072683 | m3 | submerged volume | |
| 0.5 | dimensionless | added-mass coefficient | |
| 11.17500375 | kg | effective mass | |
| 0.03643 | m2 | submerged frontal area | |
| 0.2993 | m | water-side characteristic length | |
| 0.0406875 | m2 | exposed frontal area | |
| 0.42 | m | air-side characteristic length | |
| 1025 | kg m-3 | seawater density | |
| 1.225 | kg m-3 | air density | |
| 1.05e-6 | m2 s-1 | water kinematic viscosity | |
| 1.50e-5 | m2 s-1 | air kinematic viscosity | |
| 7.2921159e-5 | s-1 | Earth rotation rate | |
| 9.80665 | m s-2 | gravitational acceleration | |
| 0.155 | m | draft used for validation Stokes averaging | |
| 6,371,000 | m | Earth radius |
These are fixed engineering parameters, not fitted separately for each case.
5. Ensemble construction
Only the initial position is perturbed. For each member,
The conversion to geographic coordinates is
The 1 km setting is the standard deviation of each east/north component, not a hard radial limit. For an ideal two-dimensional Gaussian, its initial 80% radial quantile is approximately 1.794 km.
Sampling is antithetic: every random offset is paired with . This centers each finite ensemble exactly on the requested release. The same offsets are shared across models, and the five Okinawa sites also share the same offset set, making model/site comparisons paired rather than confounded by different random draws.
Current Okinawa settings are:
- 100 members per site per model;
- five sites per priority area;
- 500 tracks per model and 1,000 displayed tracks per priority forecast;
- two displayed models: SMOC (current + Stokes + tides + 0.012 wind) and finite inertia;
- random seed
20260825.
Across all five priorities this is 5,000 displayed trajectories per
initialization time. The four Okinawa initialization batches contain 20,000
displayed trajectories in total. The nine validation cases contain 100 members
per model, with case-specific deterministic seeds derived from 20260819.
6. The 80% trajectory cone
At each saved hour, the viewer product calculates component-wise median longitude and latitude. It then computes every member’s great-circle distance from that median and stores the 0.8 quantile as .
Great-circle distance uses the haversine expression
The cone is a single merged geometry, rather than many overlapping translucent circles. In a local tangent plane, the code:
- offsets the median centerline by +/- along its local normal;
- joins adjacent left/right offsets with quadrilaterals;
- unions those pieces with a circular buffer at every hourly center;
- uses 16 segments per quadrant for the round buffers.
This creates a clean outline with a rounded end cap whose radius is the final 80% spread. It is a visualization of hourly marginal 80% spread, not a formal simultaneous 80% confidence region for the entire trajectory.
For a five-site forecast, each release group has its own cone. A combined outline is also stored; disconnected pieces fall back to their convex hull for viewer rendering.
7. Okinawa release geometry and timing
Each priority transect is evaluated at four initialization times. Every case runs for 72 hours and saves positions hourly.
| Initialization in JST | Initialization in UTC | Forecast end in UTC |
|---|---|---|
| 2026-08-25 09:00 JST | 2026-08-25 00:00 UTC | 2026-08-28 00:00 UTC |
| 2026-08-25 21:00 JST | 2026-08-25 12:00 UTC | 2026-08-28 12:00 UTC |
| 2026-08-26 09:00 JST | 2026-08-26 00:00 UTC | 2026-08-29 00:00 UTC |
| 2026-08-26 21:00 JST | 2026-08-26 12:00 UTC | 2026-08-29 12:00 UTC |
The same release geometry, initial perturbations, random seed, coefficients, models, and numerical settings are used at every initialization. Only the release time and therefore the sampled time-evolving forcing change. The viewer groups the twenty priority cases by JST initialization time.
Each provided midpoint is site 3. Sites 1-5 are at latitude offsets arcminutes with unchanged longitude, so adjacent nominal release points are one nautical mile apart north-south.
| Priority | Center latitude | Center longitude |
|---|---|---|
| 1 | 27 deg 16 min 0.61 sec N | 127 deg 38 min 41.64 sec E |
| 2 | 26 deg 55 min 47.44 sec N | 127 deg 16 min 57.56 sec E |
| 3 | 26 deg 12 min 24.34 sec N | 126 deg 40 min 54.52 sec E |
| 4 | 25 deg 59 min 25.80 sec N | 126 deg 39 min 44.00 sec E |
| 5 | 25 deg 59 min 0.06 sec N | 127 deg 10 min 45.89 sec E |
There are no observations for these hypothetical releases, so no forecast error or skill score is assigned to them before deployment.
8. Validation metrics
For observation-backed cases, pointwise position error is the great-circle distance
The stored headline metrics are:
Hourly interval velocity is reconstructed from consecutive positions:
Velocity error is
With observed-motion unit vector and perpendicular , the diagnostic magnitudes are
For candidate-minus-reference comparisons, positive improvement is defined as
Thus positive values mean the candidate has less error. Error growth rate is approximated by
The primary coefficient-tuning objective used in the diagnostic suite is the median across forecasts of mean 0-72 h position error:
9. Coefficient experiments versus active settings
The repository contains earlier tuning products; these do not silently alter the active viewer model.
| Experiment | Values tested | Coefficients held fixed |
|---|---|---|
| windage | 0.000-0.015 in 0.001 increments | |
| current | 0.5-1.5 in 0.1 increments | |
| Stokes | 0, 0.25, 0.5, …, 2.0 | |
| hourly rolling comparison | versus 0.6 |
The tuned case and the earlier no-tide simple track remain analysis products. Neither is presented as a separate active Okinawa model. The active additive track uses unit current, Stokes, and tidal contributions plus through the SMOC composite formulation in Section 4.1.
10. Forecast selection and automatic updates
The macOS LaunchAgent runs
poll_forecasts.py every 900 s (15 minutes) while the user is logged in and the
Mac is awake. The workflow is:
- poll and archive eligible ECMWF IFS cycles;
- poll and archive Copernicus forecast updates;
- if both pollers succeed, check whether the Okinawa cases need rebuilding;
- archive the complete new run first;
- atomically replace the five cases belonging to that initialization and update the manifest without removing the other initialization batches.
IFS cycles are initialized at 00, 06, 12, and 18 UTC. The 00/12 UTC products extend to 240 h; 06/18 UTC extend to 144 h. For the Okinawa experiment the refresh controller selects the latest initialization that is no later than the release time and still covers the complete 72-hour interval:
This is the closest eligible pre-release forecast, not simply the newest file on disk.
A fresh regional SMOC snapshot is requested no more often than every six hours by default. Its coordinate arrays and all eight trajectory variables are content-hashed with SHA-256. Trajectories are rebuilt only if the eligible IFS cycle changes, the SMOC content hash changes, or a forced run is requested.
Automatic updating stops at the release time. This prevents post-release model
updates from introducing hindsight into later validation. Retrospective runs
are possible only with the explicit --allow-after-release option and remain
timestamped in the archive.
The refresh refuses to run with less than 15 GiB of free disk space, validates full SMOC time coverage and required variables, and uses a filesystem lock to prevent concurrent rebuilds.
Manual update commands
From the repository root:
cd data/SPOTTER/driftcast-local-forcing-qc-2026-08-18
# Inspect the selected IFS cycle and whether a SMOC refresh is due.
.venv/bin/python refresh_okinawa_priority_forecasts.py --check-only
# Poll all operational sources, then refresh if inputs changed.
.venv/bin/python poll_forecasts.py
# Force a new pre-release SMOC snapshot and recalculation.
.venv/bin/python refresh_okinawa_priority_forecasts.py --forceThe trajectory generator itself uses the Python interpreter named by
DRIFTCAST_TRAJECTORY_PYTHON; if unset, it prefers
/Users/wyn/miniforge3/envs/Pacific/bin/python and otherwise falls back to the
current interpreter.
11. Archive and provenance
The active viewer contains twenty Okinawa cases: five priorities at four initialization times. Recalculating one initialization replaces only its five active viewer JSON files. Historical calculations are never overwritten in the archive.
Immutable runs live at:
data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/
forecast_archive/okinawa_priority_forecasts/
index.json
runs/
YYYYMMDDTHHMMSSZ/
run.json
cases/
ensemble_okinawa_priority-1_YYYYMMDDTHHZ.json
...
ensemble_okinawa_priority-5_YYYYMMDDTHHZ.jsonEvery run records:
- UTC calculation time and unique run ID;
- release and forecast-end time;
- IFS path, initialization cycle, SHA-256, and byte count;
- SMOC snapshot path, retrieval time, content SHA-256, byte count, and variable list;
- generator path and SHA-256;
- ensemble size, position sigma, seed, and finite-inertia time step; and
- all five complete case payloads, including every member track, medians, cones, fields, and viewer metadata.
JSON publication is atomic: data are written to a temporary file and moved into place only after serialization succeeds. A failed recalculation therefore does not leave a partially written active case.
For later deployment validation, match observations to archived cases by
forecast_run_id, release.time, and release_sites[].id. Do not use only the
current viewer JSON, because it intentionally represents the latest eligible
run rather than the full forecast history.
To see the calculation date and forcing cycles for the latest archived run:
jq '.runs[-1]' \
data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/forecast_archive/okinawa_priority_forecasts/index.json12. Viewer forcing layers
The following time-evolving backgrounds are packaged with each Okinawa case:
- Eulerian ocean-current speed and vectors;
- Stokes-drift speed and vectors;
- significant wave height with mean wave direction;
- peak wave period with peak direction;
- mean wave period;
- 10 m wind speed and vectors;
- combined SMOC current + Stokes + tidal speed and vectors; and
- tidal-drift speed and vectors.
Viewer fields are snapshots every 3 h, independent of the solver sampling. The high-resolution immediate context uses a 31 x 21 display grid. A coarser 29 x 15 East China Sea field over 115-145 degrees E and 15-35 degrees N supplies basin-wide context. These display grids do not control trajectory resolution; the trajectories sample the underlying forcing grids directly.
13. Running the viewer
From the repository root:
./code/startOpen http://localhost:8000/. A local web server is required because browsers
do not allow the case files to be fetched reliably from a file:// URL. Keep
the terminal process running and press Ctrl-C to stop it.
To use another port:
SPOTTER_VIEWER_PORT=8765 ./code/startThe older observation-validation builder can still be run with:
python3 code/spotter_validation.pyThat command regenerates the legacy validation product; it is separate from the archived operational Okinawa refresh workflow described above.
14. Primary implementation files
../data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/notebooks/generate_okinawa_line_ensemble_case.py: five-site Okinawa solver and viewer payloads.../data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/notebooks/generate_ensemble_validation_cases.py: nine observation-backed ensembles, finite-inertia equations, and cone geometry.../data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/refresh_okinawa_priority_forecasts.py: forcing selection and recalculation policy.../data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/forecast_run_archive.py: immutable run storage and atomic publishing.../data/SPOTTER/driftcast-local-forcing-qc-2026-08-18/poll_forecasts.py: operational polling entry point.spotter_validation_viewer/index.html: Local DriftCast viewer.