River Discharge =============== ``POST /api/v1/rivers`` delivers hourly freshwater discharge at the mouth of every listed river in a box (or at mouths passed with the request), for point or surface sources in an ocean model. A nested regional model otherwise receives river water only through its open boundaries and initial state, so a river that enters inside the domain is missing as a source and its freshwater decays over the run. Method ------ The method is common practice for gauge-driven river forcing. The NOAA Operational Forecast Systems map US Geological Survey real-time gauges onto model cells with a per-river scale factor and fall back to climatology. Regional estuary models scale gauged flow to ungauged area by the ratio of drainage areas. 1. **Gauges, derived for every request.** Only a river's mouth is listed. From its NHDPlus outlet flowline, forcingkit asks the USGS `NLDI `__ for every USGS site upstream, then keeps a site if: - USGS classes it as a stream site (``ST``). Tidal streams (``ST-TS``) and estuaries (``ES``) are left out, because their flow reverses with the tide; on the Connecticut River that rules out Hartford and Middle Haddam; - it has a drainage area, and a discharge record (15-minute or daily) covering the window; - it drains at least ``min_share`` of the mouth's area (default 0.01), so headwater brooks drop out; - no other kept site lies downstream of it, which leaves the lowest gauge on each branch. The kept gauges then measure disjoint parts of the basin. The selection follows the window: a gauge that opened in 2010 is used from 2010 on, and one that closed is dropped from then on. 2. **Discharge at the mouth.** The sum of the river's gauges, scaled by the drainage area at the mouth over the gauged area: .. math:: Q_\text{mouth} = \frac{A_\text{mouth}}{\sum_k A_k} \sum_k Q_k Gauge areas come from the USGS monitoring-location records; the mouth's area is that of the outlet's NLDI basin. 3. **Time base.** The 15-minute record from the USGS Water Data APIs (``continuous``), averaged to hourly values centred on the hour. The store holds ``hours + 1`` records, from ``start_time`` to ``start_time + hours``. 4. **Gaps.** A gap of up to ``max_gap_hours`` (default 6) with values on both sides is interpolated. A longer gap takes that day's mean from the ``daily`` record. A day with neither is an error, unless ``allow_climatology`` is set; then it takes the USGS day-of-year median of daily flow. Every filled hour is flagged in ``fill`` (0 measured, 1 interpolated, 2 daily mean, 3 climatology median), and the store's ``provenance`` attribute counts them per river. 5. **Water properties.** Salinity is zero. Water temperature (``temperature``) comes from the first gauge on the river that measures it (USGS parameter 00010), and is NaN where none does. 6. **Provisional data.** USGS values are provisional until approved, typically months later, and provisional values are revised. A store containing any provisional value is marked ``provisional = True`` and is served from the cache for one day only; after that a request rebuilds it. 7. **Travel time.** None by default. A mouth entry may set ``lag_hours``; gauge values are then taken that many hours earlier. Mouths ------ Mouths are listed in ``forcingkit/data/rivers/*.json`` and in any ``*.json`` file in the directory named by ``FORCINGKIT_RIVER_MOUTHS_DIR``; a later entry with the same name replaces an earlier one. A request may instead pass its own ``mouths``. Adding a river needs a mouth entry and no code or release: .. code-block:: json {"mouths": [ {"name": "Connecticut", "lon": -72.3305, "lat": 41.2726, "comid": 7703046}, {"name": "Saugatuck", "lon": -73.36, "lat": 41.10, "trace_from": "USGS-01208990"} ]} - ``name``, ``lon``, ``lat`` (required): the point places the mouth for the bbox test. - ``comid``: the NHDPlus outlet flowline. Otherwise ``trace_from`` names any NLDI feature on the river (a USGS site such as ``USGS-01184000``) and the outlet is the end of its downstream trace. Failing both, the point is snapped to the nearest flowline, with a warning: at an estuary the nearest flowline can be a short coastal one rather than the river. - ``include`` and ``exclude``: USGS site numbers to pin or rule out where judgement beats the rule (for example a gauge below a dam whose releases should not drive the forcing). A pinned set that drains more than the mouth's area is refused as double counting. - ``lag_hours``: travel time from the gauges to the mouth, applied to the gauge window. The id of a store includes the mouth entries and ``min_share``, but not the derived gauges, which are recorded in the store instead. NLDI facts about a mouth (its outlet, basin area, upstream sites and which sites lie downstream of which) are cached for 30 days under ``usgs/derivations`` in the cache directory, so only the first request for a mouth takes long (about a minute for the Connecticut, whose basin holds 1,375 USGS sites). The packaged mouths are the rivers into Long Island Sound. For a request over the Sound in April 2026 the derivation chose: .. list-table:: :header-rows: 1 :widths: 16 46 13 13 12 * - River - USGS gauges kept - Gauged (mi²) - Mouth (mi²) - Scale * - Housatonic - 01205500 at Stevenson; 01208500 Naugatuck at Beacon Falls - 1,804 - 1,944 - 1.08 * - Quinnipiac - 01196500 at Wallingford; 01196620 Mill River near Hamden; 01196561 Muddy River near East Wallingford - 148 - 204 - 1.37 * - Connecticut - 01184000 at Thompsonville; 01189995 Farmington at Tariffville - 10,237 - 11,242 - 1.10 * - Thames - 01127000 Quinebaug at Jewett City; 011230695 Shetucket at Taftville; 01127500 Yantic at Yantic - 1,314 - 1,470 - 1.12 The Quinnipiac's outlet basin is New Haven Harbor's, so its scaled flow also stands for the harbour's other streams. The Housatonic at Stevenson is below a hydroelectric dam, so its hourly flow follows the dam's releases. The Bronx River gauge (01302020) has no record before the 2000s, so a request for an earlier window fails unless ``skip_ungauged`` is set, which leaves such a river out and lists it in the store's ``skipped_rivers``. Request and store ----------------- .. code-block:: bash curl -s -X POST localhost:9598/api/v1/rivers -H 'Content-Type: application/json' -d '{ "bbox": {"min_lon": -73.855, "min_lat": 40.75, "max_lon": -71.9, "max_lat": 41.45}, "start_time": "2026-04-02T00:00:00Z", "hours": 48}' Optional fields: ``mouths``, ``min_share`` (default 0.01), ``max_gap_hours`` (default 6), ``allow_climatology`` and ``skip_ungauged`` (both default false), and ``cache_bust``. For that request (four rivers, 49 records), the mean discharges over the 48 hours were 1,553 m³/s for the Connecticut, 147 for the Housatonic, 148 for the Thames and 13 for the Quinnipiac. The store (schema ``river-v1``) has a ``river`` dimension: - ``discharge`` (time, river): m³ s⁻¹, ``water_volume_transport_in_river_channel``. - ``temperature`` (time, river): °C. - ``fill`` (time, river): the flags above. - ``mouth_lon``, ``mouth_lat``, ``scale_factor``, ``salinity`` (river). - Attributes: ``river_names``; ``provenance`` (JSON: per river, the gauges kept, the areas, the scale factor, the outlet, and the dropped candidates counted by reason); ``derivation_dropped`` (JSON: every dropped candidate with its reason); ``skipped_rivers``; ``provisional``; and ``built_utc``. A JSON sidecar next to the store repeats the request, the mouths and the derivation. ``GET /api/v1/rivers/download/{zarr_id}`` returns the store as a zip. Credentials ----------- None are required. A free USGS Water Data API key (``USGS_API_KEY``, from `api.waterdata.usgs.gov/signup `__) raises the hourly rate limit; it is sent in the ``X-Api-Key`` header. forcingkit uses the modernized APIs, not the legacy ``waterservices.usgs.gov``, which USGS plans to retire in 2027. Limits ------ - Mouths are not found automatically within a box: each river needs a mouth entry. Finding coastal outlets from NHDPlus would remove that step. - The selection rule cannot tell a regulated gauge from a natural one; use ``exclude`` where dam operations should not reach the forcing. - Gauges measure surface runoff. Groundwater discharge (most of Long Island's freshwater input) is not represented. - A model that applies discharge as a surface freshwater flux on fixed levels dilutes salinity but adds no volume. Whether the volume is added depends on the model's vertical coordinate, not on this store.