Skip to content

HYMOD Model

HYMOD is a conceptual rainfall-runoff model combining an exponential soil-moisture accounting store with a series of linear reservoirs (Nash cascade) for routing.

  • Registered name: hymod
  • Parameters: 5
  • Routing: Nash cascade

API Reference

hymod(p_and_e, parameters, warmup_length=30, return_state=False, normalized_params='auto', **kwargs)

Run Hymod model

See https://www.proc-iahs.net/368/180/2015/piahs-368-180-2015.pdf for a scientific paper: Quan, Z.; Teng, J.; Sun, W.; Cheng, T. & Zhang, J. (2015): Evaluation of the HYMOD model for rainfall–runoff simulation using the GLUE method. Remote Sensing and GIS for Hydrology and Water Resources, 180 - 185, IAHS Publ. 368. DOI: 10.5194/piahs-368-180-2015.

Parameters

p_and_e precipitation and potential evapotranspiration, 3-dim variable: [time, basin, feature=1] parameters five parameters: cmax, bexp, alpha, ks, kq warmup_length the length of warmup period return_state if True, return x_slow, x_quick, x_loss, else only return streamflow normalized_params parameter format specification: - "auto": automatically detect if parameters are normalized (0-1) or original scale (default) - True: parameters are normalized (0-1 range), will be converted to original scale - False: parameters are already in original scale, use as-is

Returns

Union[list, np.array] streamflow, x_slow, x_quick, x_loss or streamflow

Source code in hydromodel/models/hymod.py
def hymod(
    p_and_e,
    parameters,
    warmup_length=30,
    return_state=False,
    normalized_params="auto",
    **kwargs,
):
    """
    Run Hymod model

    See https://www.proc-iahs.net/368/180/2015/piahs-368-180-2015.pdf for a scientific paper:
    Quan, Z.; Teng, J.; Sun, W.; Cheng, T. & Zhang, J. (2015): Evaluation of the HYMOD model
    for rainfall–runoff simulation using the GLUE method. Remote Sensing and GIS for Hydrology
    and Water Resources, 180 - 185, IAHS Publ. 368. DOI: 10.5194/piahs-368-180-2015.

    Parameters
    ----------
    p_and_e
        precipitation and potential evapotranspiration, 3-dim variable: [time, basin, feature=1]
    parameters
         five parameters: cmax, bexp, alpha, ks, kq
    warmup_length
        the length of warmup period
    return_state
        if True, return x_slow, x_quick, x_loss, else only return streamflow
    normalized_params
        parameter format specification:
        - "auto": automatically detect if parameters are normalized (0-1) or original scale (default)
        - True: parameters are normalized (0-1 range), will be converted to original scale
        - False: parameters are already in original scale, use as-is

    Returns
    -------
    Union[list, np.array]
        streamflow, x_slow, x_quick, x_loss or streamflow
    """
    model_param_dict = get_model_param_config("hymod", kwargs)
    # params
    param_ranges = model_param_dict["param_range"]

    # Process parameters using unified parameter handling
    processed_params = process_parameters(
        parameters, param_ranges, normalized=normalized_params
    )

    # Extract individual parameters from processed array
    cmax = processed_params[:, 0]
    bexp = processed_params[:, 1]
    alpha = processed_params[:, 2]
    ks = processed_params[:, 3]
    kq = processed_params[:, 4]
    if warmup_length > 0:
        # set no_grad for warmup periods
        p_and_e_warmup = p_and_e[0:warmup_length, :, :]
        _, _, x_slow, x_quick, x_loss = hymod(
            p_and_e_warmup,
            parameters,
            warmup_length=0,
            return_state=True,
            **kwargs,
        )
    else:
        # Initialize slow tank state
        # x_slow = 2.3503 / (ks * 22.5)
        x_slow = np.full(
            (p_and_e.shape[1], 1), 0.0
        )  # --> works ok if calibration data starts with low discharge
        # Initialize state(s) of quick tank(s)
        x_quick = np.full((p_and_e.shape[1], 3), 0.0)
        # HYMOD PROGRAM IS SIMPLE RAINFALL RUNOFF MODEL
        x_loss = np.full((p_and_e.shape[1], 1), 0.0)
    precip = p_and_e[warmup_length:, :, 0]
    pet = p_and_e[warmup_length:, :, 1]
    t = 0
    output = np.full(precip.shape, 0.0)
    # START PROGRAMMING LOOP WITH DETERMINING RAINFALL - RUNOFF AMOUNTS
    while t <= precip.shape[0] - 1:
        pval = precip[t, :]
        pet_val = pet[t, :]
        # Compute excess precipitation and evaporation
        er1, er2, x_loss = excess(x_loss, cmax, bexp, pval, pet_val)
        # Calculate total effective rainfall
        et = er1 + er2
        #  Now partition ER between quick and slow flow reservoirs
        uq = alpha * et
        us = (1 - alpha) * et
        # Route slow flow component with single linear reservoir
        x_slow, qs = linres(x_slow, us, ks)
        # Route quick flow component with linear reservoirs
        inflow = uq

        for i in range(3):
            # Linear reservoir
            x_quick[:, i], outflow = linres(x_quick[:, i], inflow, kq)
            inflow = outflow

        # Compute total flow for timestep
        output[t, :] = qs + outflow
        t += 1
    streamflow = np.expand_dims(output, axis=2)
    if return_state:
        return streamflow, et, x_slow, x_quick, x_loss
    return streamflow, et