r.hydro.hbv.basins - Delineates lumped sub-basins from a DEM and outlet points, and writes area/forest-field-fraction/station-elevation-difference physiography (plus, optionally, HBV parameter bounds) directly into the basins vector's attribute table for r.hydro.hbv.
Auto-delineate a basin for every stream link (segment between confluences) instead of at given outlet points -- no outlet coordinates needed at all. Real motivation (2026-08-23): literature/physical-gauge outlet coordinates for named stations are often imprecisely co-registered with a DEM's own derived stream network (see PLAN.md-style investigation in the calling project), and getting a complete basin decomposition for a full hydrological simulation shouldn't have to wait on that. Uses r.stream.basins' own automatic (no-points) mode: every unique stream-network link above threshold= becomes its own basin, each with basin_id "basin_N". outlets/id_column/snap_radius are ignored when this flag is set.
--overwrite
Allow output files to overwrite existing files
--help
Print usage summary
--verbose
Verbose module output
--quiet
Quiet module output
--ui
Force launching GUI dialog
Parameters:
elevation=name[required]
Input DEM; the current region (g.region) must already match it
outlets=name
Name of input vector map
Vector points map, one point per basin outlet/station. Not required with the -a/auto flag, which delineates a basin for every stream link automatically instead of at given points.
id_column=name
Attribute column in outlets holding the basin identifier (copied into basins_vector's basin_id column). Ignored with -a/auto (each auto-delineated basin's id is "basin_N (N its raster category)" instead).
Default: id
threshold=integer[required]
Minimum flow accumulation (cells) for r.watershed basin delineation
Default: 1000
snap_radius=integer[required]
Maximum distance (cells) to snap outlet points onto the derived stream network
Default: 3
basins=name[required]
Name for output delineated basins raster map
basins_vector=name[required]
Name for output delineated basins vector map; its attribute table is r.hydro.hbv's parameters input
landcover=name
Land-cover raster used to derive forest/field fraction per basin; omit to use uniform ffo/ffi instead
forest_cats=integer[,integer,...]
Land-cover category values considered "forest" (required if landcover is given)
ffo=float
Uniform forest fraction applied to every basin when landcover is not given
Default: 0.0
ffi=float
Uniform field fraction applied to every basin when landcover is not given
Default: 1.0
precip_station_elevation=float
Elevation of the precipitation station/grid reference point (elevation map units); omit to skip the correction term (dep=0)
temp_station_elevation=float
Elevation of the temperature station/grid reference point; omit to skip the correction term (det=0)
et_station_elevation=float
Elevation of the evapotranspiration station/grid reference point; omit to skip the correction term (dee=0)
parameters_template=name
CSV of HBV parameter sampling bounds (16 rows: fc,beta,lp,alpha,kf,ks,perc,cflux low/high), either 1 column (broadcast to every basin) or one column per delineated basin; written into basins_vector's fc_lo/fc_hi/... columns
hru_bands=integer[required]
Number of elevation-band HRUs per basin (1 = today's lumped, one-unit-per-basin behavior)
Default: 1
watershed_module=string[required]
Module used internally to derive drainage direction/accumulation/streams from elevation; r.watershed.opencl is a GPU/OpenCL alternative for basin-scale DEMs where r.watershed's single-threaded flow accumulation is impractically slow
Options: r.watershed, r.watershed.opencl
Default: r.watershed
device=string
Compute backend passed through to r.watershed.opencl (ignored when watershed_module=r.watershed)
Options: auto, gpu, cpu, omp
Default: auto
drainage_input=name
Pre-computed drainage-direction raster (e.g. saved from a prior run); if given together with accumulation_input, skips the internal watershed_module call entirely instead of recomputing it. Real motivation (2026-08-23): watershed_module's depression-filling/accumulation stages are threshold-independent but expensive at whole-basin scale (~76 minutes on real GPU hardware for a 270M-cell DEM) -- re-running the full module just to try a different threshold=/snap_radius= for outlet snapping wastes that entire computation every time.
accumulation_input=name
Pre-computed flow-accumulation raster, paired with drainage_input (see its description). The stream network used for snapping is re-derived from this at the threshold= given now, cheaply (one r.mapcalc pass), so re-running with a different threshold to fix a bad outlet snap no longer requires re-running watershed_module.
r.hydro.hbv.basins replaces the pysheds-based external Python
preprocessing used to prepare lumped-basin inputs for
r.hydro.hbv (originally written for the
Plumergat DICRIM flood-risk study) with GRASS-native raster analysis:
With the -a flag, outlets/id_column/snap_radius
are not needed at all: every unique stream link above threshold
becomes its own basin automatically (r.stream.basins' own
no-points mode), each with basin id basin_<raster category>.
Sidesteps outlet-coordinate/DEM-registration mismatches entirely --
useful to get a full hydrological simulation running independently of
whether precise official station coordinates are available yet.
Otherwise, sub-basins are delineated from a DEM and a set of outlet
points using watershed_module (drainage direction and stream
network --
r.watershed by default, or the GPU/OpenCL
r.watershed.opencl addon, selectable via device, for
basin-scale DEMs where r.watershed's single-threaded flow
accumulation is impractically slow), r.stream.snap
(snapping outlets onto the modelled stream network) and
r.stream.basins (tracing each
outlet's contributing area). All outlets are delineated in one pass; the
resulting raster's categories are the outlet points' own vector
categories. drainage_input/accumulation_input let a prior
run's drainage-direction/flow-accumulation rasters be reused instead of
recomputing them via watershed_module -- both stages are
independent of threshold (only the derived stream network used
for snapping depends on it, re-derived cheaply from
accumulation_input each time), so re-tuning threshold/
snap_radius to fix a bad outlet snap, or adding more outlets,
does not need to repeat an expensive basin-scale watershed computation
(confirmed real-world case: reduced a ~76-minute real-GPU whole-basin
recomputation to ~2 seconds). Give both or neither; if given,
watershed_module/device are ignored.
With hru_bands > 1 (default 1 = no splitting), each basin
is further split into that many equal-interval elevation bands (from
its own min/max elevation), each band becoming its own HRU with
category basin_category * 100 + band_index.
The basins (or HRU) raster is vectorized with
r.to.vect-v (vector category =
raster category, not discovery order -- important, since the zonal
stats below are keyed by raster category).
Per-basin (or per-HRU) physiography is derived by zonal statistics:
area via r.stats-a, mean
elevation via r.univarzones=,
forest/field fraction via a basins x land-cover cross-tabulation
(r.stats with two inputs), and elevation-difference correction
terms (dep/det/dee, in units of 100 m) as
(station_elevation - mean_elevation) / 100 for each of the
precipitation/temperature/evapotranspiration reference stations, when
their elevations are supplied. These, plus (optionally) HBV parameter
sampling bounds from parameters_template, are written directly
into basins_vector's attribute table via
v.db.addcolumn/db.execute -- no CSV files are
produced.
The current region (set beforehand with g.region) must already
match the elevation raster's extent and resolution -- this module
does not change the region itself.
basins_vector's attribute table gains, per row (one row per
basin, or per HRU when hru_bands > 1):
basin_id: from the outlets attribute column
id_column -- the parent basin's identifier, repeated
across an HRU group.
band_index (only when hru_bands > 1): 1-based
elevation band number within its parent basin.
area_km2, ffo, ffi, dep, det,
dee: the physiography r.hydro.hbv expects (rows 16-21
of its parameters input), computed within that basin/HRU
only.
fc_lo/fc_hi/.../cflux_lo/cflux_hi (only
when parameters_template is given): the 8 HBV parameters'
sampling bounds (rows 0-15) -- these aren't derivable from a DEM, so
parameters_template must be supplied externally, either as 1
column (broadcast to every basin, and to every HRU within a basin) or
one column per delineated basin.
basins is the delineated basins (or HRU) raster, for inspection
or as input to
r.hydro.hbv.forcing's zonal
climate reduction.
Any outlet that fails to produce a delineated basin (too close to
another outlet, off the DEM, or below the accumulation threshold)
is dropped with a warning, rather than aborting the whole run.
Re-tuning threshold/snap_radius on a basin-scale DEM
without repeating the expensive watershed computation -- first save the
drainage/accumulation rasters with persistent names:
then delineate (and re-delineate, as many times as needed, in seconds
rather than the original run's wall-clock time) by reference to those
saved rasters instead of elevation/watershed_module/device: