Source code for hydrobricks.models.hbv_96

from __future__ import annotations

import logging
from typing import Any

from hydrobricks.models.hbv import HBV

logger = logging.getLogger(__name__)


[docs] class HBV96(HBV): """HBV-96 model (Lindström et al., 1997). HBV-96 implements the response routine as an upper, non-linear reservoir and a lower, linear reservoir: - recharge enters the upper zone (UZ), - a constant-rate percolation (PERC) feeds the lower zone (LZ), - an optional capillary transport (CFLUX) returns water from the upper zone to the soil moisture storage, - upper zone runoff: Q0 = k_uz × UZ^(1 + alpha), - lower zone runoff: Q1 = k_lz × LZ, - Q0 + Q1 are routed through the MAXBAS triangular unit hydrograph. Parameters (literature names as aliases) ---------------------------------------- tt : float Threshold/melting temperature [°C]. rfcf : float Rainfall correction factor [-] (default 1.0; corrects rain gauge undercatch). sfcf : float Snowfall correction factor [-] (default 1.0; corrects snow gauge undercatch). cfmax : float Snow melt degree-day factor [mm/d/°C]. cfr : float Refreezing coefficient [-] (typically 0.05). cwh : float Snowpack liquid water holding capacity, fraction of SWE [-] (typically 0.1). fc : float Soil moisture storage capacity (FC) [mm]. lp : float Soil moisture fraction above which ET reaches the potential rate [-]. beta : float Shape coefficient of the recharge function [-]. cflux : float Maximum capillary flux from the upper zone to the soil moisture [mm/d]. k_uz : float Upper zone response factor [mm^(-alpha)/d]. alpha : float Non-linearity coefficient of the upper zone [-]. perc : float Constant percolation rate to the lower zone [mm/d]. k_lz : float Lower zone (linear) response factor [1/d]. maxbas : float Base of the triangular unit hydrograph [d]. """ def __init__(self, name: str = "hbv96", **kwargs: Any) -> None: super().__init__(name=name, **kwargs) def _define_response_structure(self) -> None: """Define the HBV-96 response routine (non-linear UZ, linear LZ).""" self.structure["upper_zone"] = { "attach_to": "hydro_unit", "kind": "storage", "processes": { "capillary": { "kind": "capillary:hbv", "targets": list(dict.fromkeys(self._soil_names.values())), }, "percolation": { "kind": "percolation:constant", "target": "lower_zone", }, "runoff": {"kind": "runoff:hbv", "target": "routing"}, }, } self.structure["lower_zone"] = { "attach_to": "hydro_unit", "kind": "storage", "processes": { "outflow": {"kind": "outflow:linear", "target": "routing"}, }, } def _define_parameter_aliases(self) -> None: """Define HBV-96 parameter aliases (literature names).""" super()._define_parameter_aliases() self.parameter_aliases.update( { "upper_zone:percolation_rate": ["perc"], "lower_zone:response_factor": ["k_lz", "k4"], } ) def _define_parameter_constraints(self) -> None: """Define parameter constraints for the HBV-96 model. The lower zone must react slower than a linear upper zone would (k_lz < k_uz); both are expressed in [1/d] when alpha = 0 and the constraint remains a sensible ordering for alpha > 0. """ self.parameter_constraints = [ ["k_lz", "<", "k_uz"], ]