Hydrological response units

Most geographical models, including hydrological models, work using cells. This is essentially an area on the map that responds as a unit. The resolution of the grid varies, depending on the required detail of the simulation, computational run-time, availablity of input data among others. (Near-) square cells are very useful in this respect, because input data (such as satellite observations) are often available in a grid. CWatM, like most hydrological models, operates at these grids. For each cell, various land use types are modelled, and then aggregated to the cell level while considering the relative sizes of the land use types in that particular cell. Farmers occupy non-irrigated land, paddy-irrigated land, and non-paddy irrigated land. However, when a single land use type is shared among multiple farmers, their hydrological environment is shared, and thus must respond identically.

This creates an issue for agent-based models, where implementation of heterogeneous decision-making is required. For example, when one farmer decides to irrigate and other does not, the soil moisture in their fields should also be represented separately. Therefore, we use the concept of HRUs. To create the HRUs, each individual field owned by a farmer becomes a HRU first. Then, in addition, each other land use type becomes a separate HRU. HRUs never cross cell boundaries. This means that farmers whose fields are dispersed across multiple cells are simulated by multiple HRUs. Here, we assume that each HRU, is relatively homogeneous as it each HRU is operated by 1) a single farmer, or by a single other (i.e., non-farm) land-use type and 2) never crosses the boundary a hydrological model cell. This concept is similar to hydrological response units (HRUs), but operates at the sub-grid level rather than the basin level and delineation of the units is performed differently.

_images/HRUs.png

The figure above displays how this works in practice. Grid cells in the hydrological model are separated by the regular horizontal and vertical black lines. The left panel displays the various land use types, the moddle panel the farmers that own the cropland, and the rightmost panel shows the resulting hydrological units. Note that each contiguous area in the middle and right panel of a single color is one field or hydrological unit respectively, while separated areas are different fields or hydrological units. One exception is the hydrological units of the same land use type that are not owned by agents. These are represented by a single hydrological unit if they are encompassed within a single cell.

While soil processes are simulated in the HRUs (e.g., percolation, capillary rise, and evapotranspiration), other hydrological processes such as discharge are calculated at the grid cell level. To this extent, the class HRUs.Data also contains functions to convert from HRUs to grid cells (HRUs.Data.to_HRU()) and vice versa (HRUs.Data.to_grid()). The figure below shows how runoff from the HRUs is aggregated by considering relative sizes of the HRUs, and added to discharge. CWatM then solves the kinematic wave equation at the grid cell level.

_images/aggregate_HRUs.svg
class BaseVariables[source]

This class has some basic functions that can be used for variables regardless of scale.

M3toM(array)[source]

Convert array from cubic meters to meters.

Parameters:

array (ndarray) – Data in cubic meters.

Returns:

array – Data in meters.

Return type:

ndarray

MtoM3(array)[source]

Convert array from meters to cubic meters.

Parameters:

array (ndarray) – Data in meters.

Returns:

array – Data in cubic meters.

Return type:

ndarray

plot(data, ax=None)[source]

Create a simple plot for data.

Parameters:
  • data (ndarray) – Array to plot.

  • ax – Optional matplotlib axis object. If given, data will be plotted on given axes.

Return type:

None

class Data(model)[source]

The base data class for the GEB model. This class contains the data for the normal grid, the HRUs, and has methods to convert between the grid and HRUs.

Parameters:

model – The GEB model.

to_HRU(*, data=None, fn=None)[source]

Function to convert from grid to HRU (Hydrologic Response Units).

This method is designed to transform spatial grid data into a format suitable for HRUs, which are used in to represent distinct areas with homogeneous land use, soil type, and management conditions.

Parameters:
  • data (array-like or None) – The grid data to be converted. If this parameter is set, varname must not be provided. Data should be an array where each element corresponds to grid cell values.

  • fn (str or None) – The name of the function to apply to the data before assigning it to HRUs. If None, the data is used as is. This is usually the case for variables that are independent of area, like temperature or precipitation fluxes. If ‘weightedsplit’, the data will be adjusted according to the ratios of land use within each HRU. This is important when dealing with variables that are area-dependent like precipitation or runoff volumes.

Returns:

output_data (array-like) – Data converted to HRUs format. The structure and the type of the output depend on the input and the transformation function.

Example

Suppose we have an instance of a class with a grid property containing temperature data under the attribute name ‘temperature’. To convert this grid-based temperature data into HRU format, we would use:

`python temperature_HRU = instance.to_HRU(data=temperature, fn=None) `

This will fetch the temperature data from instance.grid.temperature, assigning the temperature to HRU within a grid cell. In other words, each HRU within a grid cell has the same temperature.

Another example, where want to plant forest in all HRUs with grassland within an area specified by a boolean mask.

`python mask_HRU = instance.to_HRU(data=mask_grid, fn=None) mask_HRU[land_use_type == grass_land_use_type] = False  # set all non-grassland HRUs to False `

to_grid(*, HRU_data=None, fn=None)[source]

Function to convert from HRUs to grid.

Parameters:
  • HRU_data – The HRU data to be converted (if set, varname cannot be set).

  • fn – Name of function to apply to data. In most cases, several HRUs are combined into one grid unit, so a function must be applied. Choose from mean, sum, nansum, max and min.

Returns:

ouput_data – Data converted to grid units.

class Grid(data, model)[source]

This class is to store data in the ‘normal’ grid cells. This class works with compressed and uncompressed arrays. On initialization of the class, the mask of the study area is read from disk. This is the shape of any uncompressed array. Many values in this array, however, fall outside the stuy area as they are masked. Therefore, the array can be compressed by saving only the non-masked values.

On initialization, as well as geotransformation and cell size are set, and the cell area is read from disk.

Then, the mask is compressed by removing all masked cells, resulting in a compressed array.

compress(array)[source]

Compress array.

Parameters:

array (ndarray) – Uncompressed array.

Returns:

array – Compressed array.

Return type:

ndarray

decompress(array, fillvalue=None)[source]

Decompress array.

Parameters:
  • array (ndarray) – Compressed array.

  • fillvalue (Union[ufunc, int, float]) – Value to use for masked values.

Returns:

array – Decompressed array.

Return type:

ndarray

full(*args, **kwargs)[source]

Return a full array with size of mask. Takes any other argument normally used in np.full.

Parameters:
  • *args – Variable length argument list.

  • **kwargs – Arbitrary keyword arguments.

Return type:

ndarray

full_compressed(*args, **kwargs)[source]

Return a full array with size of compressed array. Takes any other argument normally used in np.full.

Parameters:
  • *args – Variable length argument list.

  • **kwargs – Arbitrary keyword arguments.

Return type:

ndarray

load(filepath, compress=True, layer=1)[source]

Load array from disk.

Parameters:
  • filepath – Filepath of map.

  • compress – Whether to compress array.

Returns:

array – Loaded array.

plot(array)[source]

Plot array.

Parameters:

array (ndarray) – Array to plot.

Return type:

None

plot_compressed(array, fillvalue=None)[source]

Plot compressed array.

Parameters:
  • array (ndarray) – Compressed array to plot.

  • fillvalue (Union[ufunc, int, float]) – Value to use for masked values.

class HRUs(data, model)[source]

This class forms the basis for the HRUs. To create the HRUs, each individual field owned by a farmer becomes a HRU first. Then, in addition, each other land use type becomes a separate HRU. HRUs never cross cell boundaries. This means that farmers whose fields are dispersed across multiple cells are simulated by multiple HRUs. Here, we assume that each HRU, is relatively homogeneous as it each HRU is operated by 1) a single farmer, or by a single other (i.e., non-farm) land-use type and 2) never crosses the boundary a hydrological model cell.

On initalization, the mask of the study area for the cells are loaded first, and a mask on the maximum resolution of the HRUs is created. In this case, the maximum resolution of the HRUs is 20 times higher than the mask. Then the HRUs are actually created.

Parameters:
  • data – Data class for model.

  • model – The GEB model.

property compressed_size: int

Gets the compressed size of a full HRU array.

Returns:

compressed_size – Compressed size of HRU array.

create_HRUs()[source]

Function to create HRUs.

Returns:
  • land_use_array – Land use of each HRU.

  • land_use_ratio – Relative size of HRU to grid.

  • land_use_owner – Owner of HRU.

  • HRU_to_grid – Maps HRUs to index of compressed cell index.

  • grid_to_HRU – Array of size of the compressed grid cells. Each value maps to the index of the first unit of the next cell.

  • unmerged_HRU_indices – The index of the HRU to the subcell.

Return type:

tuple[ndarray, ndarray, ndarray, ndarray, ndarray, ndarray, ndarray]

static create_HRUs_numba(farms, land_use_classes, mask, scaling)[source]

Numba helper function to create HRUs.

Parameters:
  • farms – Map of farms. Each unique integer is a unique farm. -1 is no farm.

  • land_use_classes – CWatM land use class map [0-5].

  • mask – Mask of the normal grid cells.

  • scaling – Scaling between mask and maximum resolution of HRUs.

Returns:
  • land_use_array – Land use of each HRU.

  • land_use_ratio – Relative size of HRU to grid.

  • land_use_owner – Owner of HRU.

  • HRU_to_grid – Maps HRUs to index of compressed cell index.

  • var_to_HRU – Array of size of the compressed grid cells. Each value maps to the index of the first unit of the next cell.

  • # var_to_HRU_uncompressed – Array of size of the grid cells. Each value maps to the index of the first unit of the next cell.

  • unmerged_HRU_indices – The index of the HRU to the subcell.

Return type:

tuple[ndarray, ndarray, ndarray, ndarray, ndarray, ndarray, ndarray]

decompress(HRU_array)[source]

Decompress HRU array.

Parameters:

HRU_array (ndarray) – HRU_array.

Returns:

outarray – Decompressed HRU_array.

Return type:

ndarray

full_compressed(fill_value, dtype, gpu=None, *args, **kwargs)[source]

Return a full array with size of number of HRUs. Takes any other argument normally used in np.full.

Parameters:
  • *args – Variable length argument list.

  • **kwargs – Arbitrary keyword arguments.

Returns:

array – Array with size of number of HRUs.

Return type:

ndarray

plot(HRU_array, ax=None, show=True)[source]

Function to plot HRU data.

Parameters:
  • HRU_array (ndarray) – Data to plot. Size must be equal to number of HRUs.

  • ax – Optional matplotlib axis object. If given, data will be plotted on given axes.

  • show (bool) – Boolean whether to show the plot or not.

zeros(size, dtype, *args, **kwargs)[source]

Return an array (CuPy or Numpy) of zeros with given size. Takes any other argument normally used in np.zeros.

Parameters:
  • *args – Variable length argument list.

  • **kwargs – Arbitrary keyword arguments.

Returns:

array – Array with size of number of HRUs.

Return type:

ndarray

class Modflow(data, model)[source]
to_HRU(data, grid_to_HRU, land_use_ratio, output_data, fn=None)[source]

Numba helper function to convert from grid to HRU.

Parameters:
  • data – The grid data to be converted.

  • grid_to_HRU – Array of size of the compressed grid cells. Each value maps to the index of the first unit of the next cell.

  • land_use_ratio – Relative size of HRU to grid.

  • fn – Name of function to apply to data. None if data should be directly inserted into HRUs - generally used when units are irrespective of area. ‘mean’ if data should first be corrected relative to the land use ratios - generally used when units are relative to area.

Returns:

ouput_data – Data converted to HRUs.

to_grid(data, grid_to_HRU, land_use_ratio, fn='weightedmean')[source]

Numba helper function to convert from HRU to grid.

Parameters:
  • data – The grid data to be converted.

  • grid_to_HRU – Array of size of the compressed grid cells. Each value maps to the index of the first unit of the next cell.

  • land_use_ratio – Relative size of HRU to grid.

  • fn – Name of function to apply to data. In most cases, several HRUs are combined into one grid unit, so a function must be applied. Choose from mean, sum, nansum, max and min.

Returns:

ouput_data – Data converted to HRUs.