Advanced features
This page covers different features for more advanced simulations:
Land cover evolution — supply time-varying land cover (e.g., glacier) evolution from external data (CSV or shapefiles).
Internal glacier evolution — derive changing glacier area internally from modelled ice loss (delta-h or area scaling methods).
Snow to ice transformation — convert accumulated snow on glaciers to ice at the end of each accumulation season.
Snow redistribution — prevent unrealistic snow accumulation at high elevations using gravitational transport.
Land cover evolution
Land cover fractions can evolve over time within each hydro unit. This allows you to simulate processes like glacier retreat, afforestation, or urbanization. This section covers externally driven evolution, where the area time series is supplied directly from remote sensing or an external model. Two input formats are supported: CSV files and shapefiles.
The initial hydro unit areas serve as the starting point; evolution data takes effect at the dates provided. Changes dated before the simulation start are applied immediately.
Using CSV files
The most direct approach: supply a CSV file recording land cover areas at a series of
dates. Call load_from_csv() once per land cover type; multiple calls accumulate
changes for different land covers into the same action object.
changes = actions.ActionLandCoverChange()
changes.load_from_csv(
'/path/to/surface_changes_glacier_debris.csv',
hydro_units,
land_cover='glacier_debris',
area_unit='km2',
match_with='elevation'
)
model.add_action(changes)
Parameters (see also API):
path— path to the CSV file.hydro_units— theHydroUnitsinstance used for matching.land_cover— name of the land cover to update (e.g.,'glacier','glacier_debris').area_unit— unit of the area values:'m2'or'km2'.match_with— how to identify hydro units in the first column:'elevation'(default) or'id'.
The CSV format:
Header row: from the second column onward, the dates of the snapshots when land cover changes occur; format
YYYY-MM-DD.Remaining rows: one row per hydro unit that changes, with the identifier value followed by the area at each snapshot date.
Hydro units not listed in the file are assumed unchanged. The ground fraction is
adjusted automatically to preserve the total unit area.
elevation,2020-08-01,2025-08-01,2030-08-01,...
4274,0.013,0.003,0,...
4310,0.019,0.009,0,...
4346,0.052,0.042,0.032,...
4382,0.072,0.062,0.052,...
4418,0.129,0.119,0.109,...
Using shapefiles
Hydrobricks can derive the land cover time series automatically from a sequence of extents provided as shapefiles, specifically for glaciers (see also API):
times = ['2008-01-01', '2010-01-01', '2016-01-01']
full_glaciers = [
'/path/to/glacier_ice_2008.shp',
'/path/to/glacier_ice_2010.shp',
'/path/to/glacier_ice_2016.shp'
]
debris_glaciers = [
'/path/to/glacier_debris_2008.shp',
'/path/to/glacier_debris_2010.shp',
'/path/to/glacier_debris_2016.shp'
]
changes, changes_df = actions.ActionLandCoverChange.create_action_for_glaciers(
catchment,
times,
full_glaciers,
debris_glaciers,
with_debris=True,
method='raster',
interpolate_yearly=True)
model.add_action(changes)
Parameters:
catchment— theCatchmentobject (must be discretized into hydro units).times— list of dates ('YYYY-MM-DD') corresponding to each shapefile.full_glaciers— list of paths to shapefiles covering all glacier ice (clean ice and debris together), one per date.debris_glaciers— list of paths to debris-only shapefiles, one per date; required whenwith_debris=True.with_debris— ifTrue, splits glacier area into bare-ice and debris-covered components; defaultFalse.method— area extraction method:'vector'(default, more precise) or'raster'(faster).interpolate_yearly— ifTrue(default), linearly interpolates areas to yearly time steps between the provided dates.
The function also returns a dataframe that can be exported as CSV and reloaded later using the CSV option, avoiding repeated raster processing on subsequent runs:
changes_df[0].to_csv('/path/to/surface_changes_glacier_ice.csv', index=False)
changes_df[1].to_csv('/path/to/surface_changes_glacier_debris.csv', index=False)
changes_df[2].to_csv('/path/to/surface_changes_ground.csv', index=False)
The hydro units can also be initialized directly from the derived time series:
hyd_units.initialize_from_land_cover_change('glacier_ice', changes_df[0])
hyd_units.initialize_from_land_cover_change('glacier_debris', changes_df[1])
Internal glacier evolution
The two methods below drive glacier area changes from modelled ice loss rather than external observations. Both require an initial ice thickness raster and produce a lookup table that maps cumulative mass loss to glacier area. This makes them suitable for future projections where no observed extent time series exist.
Note
Both methods apply only to bare-ice glacier land covers and do not handle debris-covered glacier areas.
Delta-h method
The delta-h method (Huss et al. [2010], as implemented by Seibert et al. [2018]) redistributes ice loss according to a characteristic elevation-dependent melt profile, capturing the tendency of glaciers to thin faster at lower elevations. It is the preferred approach for medium and large glaciers.
The lookup table must be precomputed before running the simulation — see Delta-h lookup table on the preprocessing page. Once computed (and optionally saved to CSV), link it to the model. The glacier area is updated at the beginning of the provided month, for example each October 1st (the start of the hydrological year in Switzerland):
changes = actions.ActionGlacierEvolutionDeltaH()
changes.load_from(
glacier_evolution,
land_cover='glacier',
update_month='October'
)
model.add_action(changes)
Parameters for load_from()
(see also API):
obj— aGlacierEvolutionDeltaHpreprocessing instance carrying the lookup tables.land_cover— land cover name to update; default'glacier'.update_month— month when glacier areas are updated; full English name or integer 1–12; default'October'.
If the lookup table was saved by the preprocessing step, it can also be loaded
directly from CSV, bypassing the GlacierEvolutionDeltaH object:
changes = actions.ActionGlacierEvolutionDeltaH()
changes.load_from_csv('/path/to/results/folder/')
model.add_action(changes)
Parameters for load_from_csv():
dir_path— path to the directory containing the lookup table files.land_cover— land cover name to update; default'glacier'.filename_area— name of the area lookup table file; default'glacier_evolution_lookup_table_area.csv'.filename_volume— name of the volume lookup table file; default'glacier_evolution_lookup_table_volume.csv'.update_month— month when glacier areas are updated; default'October'.
Simple area-scaling method
The area-scaling method establishes a relationship between cumulative ice loss and glacier area per hydro unit. It is computationally simpler than the delta-h method but less accurate, as it does not account for the glacier dynamics. It is suitable for applications where the glacier is small and is not expected to advance during the simulation period.
The lookup table must be precomputed before running the simulation — see Area-scaling lookup table on the preprocessing page. Once computed (and optionally saved to CSV), link it to the model:
changes = hb.actions.ActionGlacierEvolutionAreaScaling()
changes.load_from(
glacier_evolution,
land_cover='glacier',
update_month='October'
)
model.add_action(changes)
Parameters for load_from()
(see also API):
obj— aGlacierEvolutionAreaScalingpreprocessing instance carrying the lookup tables.land_cover— land cover name to update; default'glacier'.update_month— month when glacier areas are updated; full English name or integer 1–12; default'October'.
If the lookup table has been saved previously, skip recomputation and load it directly:
changes = hb.actions.ActionGlacierEvolutionAreaScaling()
changes.load_from_csv('/path/to/results/')
model.add_action(changes)
Parameters for load_from_csv():
dir_path— path to the directory containing the lookup table files.land_cover— land cover name to update; default'glacier'.filename_area— name of the area lookup table file; default'glacier_evolution_lookup_table_area.csv'.filename_volume— name of the volume lookup table file; default'glacier_evolution_lookup_table_volume.csv'.update_month— month when glacier areas are updated; default'October'.
Snow to ice transformation
At the end of each accumulation season, snow that has accumulated on glacier land covers is converted to glacier ice. This process is important when using melt-driven glacier evolution methods (delta-h or area scaling) because these track ice volume to derive glacier area — snow that remains at season end should be reclassified as ice to avoid underestimating ice thickness.
Note
This action is used together with the delta-h or area-scaling evolution methods, which track ice volume and thickness. It is not needed for externally driven land cover changes via CSV or shapefile.
snow_to_ice = actions.ActionGlacierSnowToIceTransformation(
update_month='September',
update_day=30,
land_cover='glacier'
)
model.add_action(snow_to_ice)
Parameters (see also API):
update_month— month when the conversion is applied, at the end of the accumulation season; full English name or integer 1–12; default'September'.update_day— day of the month when the conversion is applied; default30.land_cover— name of the glacier land cover to update; default'glacier'.
Snow redistribution
|
|
Without redistribution, elevation-band models can accumulate unrealistic amounts of snow at high elevations — so-called “snow towers”. Hydrobricks addresses this with the SnowSlide algorithm (Bernhardt and Schulz [2010]), which simulates gravitational transport of snow downslope across elevation bands.
Enable snow redistribution at model creation:
socont = models.Socont(
soil_storage_nb=2,
snow_redistribution='transport:snow_slide'
)
A connectivity CSV file describing the downslope pathways between hydro units is also required (see Catchment connectivity for how to compute it):
hydro_units.set_connectivity('/path/to/connectivity.csv')
Resources: