| Title: | Map-First Climate-Informed Flood Assessment for Data-Scarce Basins |
|---|---|
| Description: | A reproducible, map-oriented workflow for flood hazard assessment that chains rainfall extreme value analysis, rainfall-runoff simulation, terrain-based flow routing and water-depth estimation into a single pipeline. A stationary-versus-nonstationary test for changing rainfall extremes is built in, and any flood scenario can be produced for a present-day or a climate-adjusted design event. Defaults target settings with sparse gauge networks, using satellite or reanalysis rainfall, temperature-based potential evapotranspiration and regional pooling of short records. Heavy modelling engines are wrapped rather than reimplemented so that the core stays lightweight. Methods follow established hydrology, including the generalized extreme value distribution for rainfall maxima (Coles, 2001, <doi:10.1007/978-1-4471-3675-0>) and Manning's equation for open-channel flow. |
| Authors: | George Owusu [aut, cre] |
| Maintainer: | George Owusu <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-09-28 07:35:52 UTC |
| Source: | https://github.com/gowusu/floodflow |
A long-term daily weather record for Accra, on which the manual's lumped
pipeline is built. It is real observed-and-reanalysis data retrieved from the
NASA POWER service with sebkc::weather() for the Odaw basin
(latitude 5.60 N, longitude 0.20 W), then reduced to the columns floodflow
consumes. It is bundled with the package so the examples and manual keep
working even if the online service is unavailable; drop it straight onto a
flood_project as the rainfall slot. See the manual for
how to fetch an equivalent record for your own location.
accra_rainfallaccra_rainfall
A data frame with 16637 rows and 3 variables:
Date. Calendar day, YYYY-mm-dd.
numeric. Daily precipitation in millimetres
(NASA POWER PRECTOTCORR).
numeric. Daily mean air temperature in degrees Celsius
(NASA POWER T2M); used by the Oudin potential-evapotranspiration
step inside flood_runoff.
A data frame of 16637 daily records (1981-01-01 to 2026-07-20) with
three columns: date (Date), precip_mm (numeric, mm) and
temp_c (numeric, degrees C). It is the default worked-example
rainfall record used throughout the floodflow manual.
NASA POWER daily point data, https://power.larc.nasa.gov,
for latitude 5.60, longitude -0.20, retrieved with sebkc::weather().
fp <- flood_project("Odaw basin, Accra") fp$rainfall <- accra_rainfall fp <- flood_extremes(fp) fp$extremesfp <- flood_project("Odaw basin, Accra") fp$rainfall <- accra_rainfall fp <- flood_extremes(fp) fp$extremes
Reduces a daily rainfall record to annual maxima and fits the generalized extreme value (GEV) distribution, both as a stationary model and as a non-stationary model whose location parameter trends linearly with time. A likelihood-ratio test compares the two, providing a formal test of whether extreme rainfall has intensified over the record. Design return levels (for example the 100-year daily rainfall) are computed from the stationary fit.
flood_extremes( x, periods = c(2, 10, 25, 50, 100), engine = c("internal", "extRemes") )flood_extremes( x, periods = c(2, 10, 25, 50, 100), engine = c("internal", "extRemes") )
x |
A |
periods |
Numeric vector of return periods, in years, at which to report
design rainfall. Defaults to |
engine |
Which fitting engine to use: |
By default a small internal maximum-likelihood engine is used, so no extra
package is required. If extRemes is installed and engine =
"extRemes", that package is used for the stationary fit instead.
If x is a flood_project, the same object with its
extremes slot populated and the stage recorded in the log. If
x is a data.frame, the extremes result list directly. The
result is a list of class flood_extremes with elements:
annual_max (a data frame of year and maximum), stationary
(fitted parameters and negative log-likelihood), trend (the
non-stationary fit, including the per-year location trend mu1),
lr_test (a list with the likelihood-ratio statistic,
df and p_value), trend_detected (logical, TRUE
when p_value < 0.05), and return_levels (a data frame of
period and level_mm).
Coles, S. (2001) An Introduction to Statistical Modeling of Extreme Values. Springer. doi:10.1007/978-1-4471-3675-0
flood_scenario to turn these design levels into a
climate-adjusted event.
# Build a synthetic 40-year daily rainfall record with a mild upward trend set.seed(1) dates <- seq(as.Date("1985-01-01"), as.Date("2024-12-31"), by = "day") yr <- as.integer(format(dates, "%Y")) base <- rgamma(length(dates), shape = 0.7, scale = 6) trend <- 1 + 0.02 * (yr - 1985) precip <- round(base * trend * rbinom(length(dates), 1, 0.3), 1) rain <- data.frame(date = dates, precip_mm = precip) res <- flood_extremes(rain) res$return_levels res$trend_detected# Build a synthetic 40-year daily rainfall record with a mild upward trend set.seed(1) dates <- seq(as.Date("1985-01-01"), as.Date("2024-12-31"), by = "day") yr <- as.integer(format(dates, "%Y")) base <- rgamma(length(dates), shape = 0.7, scale = 6) trend <- 1 + 0.02 * (yr - 1985) precip <- round(base * trend * rbinom(length(dates), 1, 0.3), 1) rain <- data.frame(date = dates, precip_mm = precip) res <- flood_extremes(rain) res$return_levels res$trend_detected
Computes the family of time-and-motion quantities that a routed flood implies: peak flow velocity, time of concentration (by one or more methods), channel travel time, and the time-to-peak of the routed hydrograph. These are the layers a geographer maps alongside depth.
flood_hydraulics( x, length_m = 5000, overland_m = 100, retardance = 0.4, dt_hours = 24 )flood_hydraulics( x, length_m = 5000, overland_m = 100, retardance = 0.4, dt_hours = 24 )
x |
A |
length_m |
Representative flow-path (channel) length in metres, used for
time of concentration and travel time. Default |
overland_m |
Overland flow length in metres for the Kerby component.
Default |
retardance |
Kerby retardance coefficient. Default |
dt_hours |
Time step of the routed hydrograph in hours, used to convert
the time-to-peak index into hours. Default |
Velocity comes from Manning's equation at the routed peak depth. Time of concentration is available by the Kirpich channel method, the Kerby overland method, the combined Kerby-Kirpich sum, and a velocity-based travel time (flow-path length divided by peak velocity). Time-to-peak is read directly from the routed hydrograph.
If x is a flood_project, the same object with its
hydraulics slot populated. Otherwise a list of class
flood_hydraulics with elements peak_velocity_ms,
tc (a named vector of times of concentration in minutes by method:
kirpich, kerby, kerby_kirpich, velocity),
travel_time_min, and time_to_peak_hours.
disc <- data.frame( date = seq(as.Date("2020-06-01"), by = "day", length.out = 15), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1, 0, 0, 0) ) r <- flood_route(disc, method = "muskingum-cunge") h <- flood_hydraulics(r, length_m = 4000, overland_m = 120) h$tc h$peak_velocity_msdisc <- data.frame( date = seq(as.Date("2020-06-01"), by = "day", length.out = 15), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1, 0, 0, 0) ) r <- flood_route(disc, method = "muskingum-cunge") h <- flood_hydraulics(r, length_m = 4000, overland_m = 120) h$tc h$peak_velocity_ms
Renders a chosen pipeline layer for viewing. When tmap or leaflet is installed and the layer is spatial, an interactive map is produced; otherwise the function returns a tidy data frame of the layer's values (and, for non-spatial results, draws a simple base-R plot) so the pipeline remains usable without the mapping engines. This keeps mapping a first-class output while respecting the package's lightweight core.
flood_map( x, layer = c("depth", "risk", "velocity", "uncertainty"), interactive = TRUE )flood_map( x, layer = c("depth", "risk", "velocity", "uncertainty"), interactive = TRUE )
x |
A |
layer |
Which layer to map: |
interactive |
Logical; if |
A list of class flood_map with elements layer,
rendered (logical: whether an interactive/graphic map was drawn),
engine (the engine used, or "none"), and data (a tidy
summary of the mapped values). When an interactive map is produced, the map
object is attached as map.
flood_route, flood_vulnerability.
set.seed(1) rain <- data.frame( date = seq(as.Date("1990-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(11323, 0.7, scale = 6) * rbinom(11323, 1, 0.3), 1) ) fp <- flood_project("demo") fp$rainfall <- rain fp <- flood_runoff(fp, engine = "simple") fp <- flood_route(fp, area_km2 = 300) m <- flood_map(fp, layer = "depth") m$dataset.seed(1) rain <- data.frame( date = seq(as.Date("1990-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(11323, 0.7, scale = 6) * rbinom(11323, 1, 0.3), 1) ) fp <- flood_project("demo") fp$rainfall <- rain fp <- flood_runoff(fp, engine = "simple") fp <- flood_route(fp, area_km2 = 300) m <- flood_map(fp, layer = "depth") m$data
Constructs the container object that carries data and results through every
stage of the floodflow pipeline. A flood_project is a named list
with a fixed set of slots; pipeline functions read from and write to these
slots, so a single object accumulates the DEM, rainfall record, fitted
extreme-value model, routed discharge, water depth and derived maps as it
passes through the workflow.
flood_project(name = "flood_project", crs = NULL, meta = list())flood_project(name = "flood_project", crs = NULL, meta = list())
name |
Character scalar naming the project or study basin, used in
printing and map titles. Defaults to |
crs |
Optional character scalar giving the target coordinate reference
system as an EPSG string (for example |
meta |
Optional named list of user metadata to attach to the project (for example data provenance notes). Defaults to an empty list. |
The constructor deliberately performs no geospatial work and has no heavy
dependencies, so it can be created and inspected without terra or any
modelling engine installed. Slots that are not yet populated are held as
NULL.
An object of class flood_project: a named list with slots
name, crs, meta, dem, rainfall,
extremes, scenario, roughness, runoff,
route, hydraulics, uncertainty, vulnerability
and log. All data slots are NULL until populated by later
pipeline functions. The log slot is a character vector recording the
stages that have been run.
is_flood_project to test the class.
fp <- flood_project(name = "Odaw basin") fp is_flood_project(fp)fp <- flood_project(name = "Odaw basin") fp is_flood_project(fp)
Converts the discharge series from flood_runoff into a routed
hydrograph and a water depth, using one of five methods that form a
complexity ladder. All methods obtain depth from Manning's equation for a
wide channel; they differ in how the flood wave is routed, from a steady
baseline to progressively more physics.
flood_route( x, method = c("muskingum-cunge", "manning-normal", "kinematic", "diffusive", "dynamic"), width = 20, slope = 0.001, n = 0.035, celerity = 1.5, dx = 1000, dt = 86400, area_km2 = 100, hand = NULL )flood_route( x, method = c("muskingum-cunge", "manning-normal", "kinematic", "diffusive", "dynamic"), width = 20, slope = 0.001, n = 0.035, celerity = 1.5, dx = 1000, dt = 86400, area_km2 = 100, hand = NULL )
x |
A |
method |
One of |
width |
Representative channel width in metres. Default |
slope |
Representative bed slope (dimensionless). Default |
n |
Manning's roughness. If |
celerity |
Wave celerity in m/s for routing. Default |
dx |
Reach length in metres for routing. Default |
dt |
Time step in seconds. Default |
area_km2 |
Catchment area in square kilometres, used to convert runoff
depth (mm/day) to volumetric discharge (m^3/s). Default |
hand |
Optional Height Above Nearest Drainage surface as a numeric
vector or, with terra installed, a |
"manning-normal"Steady uniform flow. Depth is the Manning normal depth of the (unrouted) peak discharge. The fast baseline.
"kinematic"Kinematic wave: near-pure translation of the hydrograph with negligible attenuation. Suited to steeper channels.
"diffusive"Diffusive wave: adds hydraulic diffusion so the peak attenuates and backwater effects appear.
"muskingum-cunge"Physically-based storage routing at diffusive-wave accuracy and low cost. The pragmatic default.
"dynamic"Uses the discharge-scaled hydraulic diffusivity as the best stable approximation available in pure R. Full two-dimensional Saint-Venant hydrodynamics are out of scope; for those, couple to a dedicated hydraulic model.
All routing is carried out with the numerically stable Muskingum-Cunge family, varying its diffusion to represent each rung of the ladder.
If x is a flood_project, the same object with its
route slot populated. Otherwise a list of class flood_route
with elements method, routed (a data frame of date,
Q_cms inflow and Q_routed outflow), peak_depth_m,
peak_velocity_ms, attenuation (routed peak divided by inflow
peak), depth_raster (a spatial inundation-depth field when
hand was supplied, otherwise NULL) and the hydraulic settings
used.
Cunge, J. A. (1969). On the subject of a flood propagation computation method (Muskingum method). Journal of Hydraulic Research, 7(2), 205-230.
Manning, R. (1891). On the flow of water in open channels and pipes. Transactions of the Institution of Civil Engineers of Ireland, 20, 161-207.
flood_runoff for the discharge this routes.
set.seed(1) dates <- seq(as.Date("2020-06-01"), by = "day", length.out = 30) Q <- c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1, rep(0, 18)) disc <- data.frame(date = dates, Q_mm = Q) r_mc <- flood_route(disc, method = "muskingum-cunge") r_kin <- flood_route(disc, method = "kinematic") # Kinematic attenuates less than Muskingum-Cunge r_kin$attenuation >= r_mc$attenuation # Spatial inundation depth from a HAND surface (a numeric vector here; a # terra SpatRaster works the same way and produces a mappable raster) hand <- c(0, 0.5, 1, 2, 4, 6) r_spatial <- flood_route(disc, area_km2 = 300, hand = hand) r_spatial$depth_raster # deepest in the valley, dry on high groundset.seed(1) dates <- seq(as.Date("2020-06-01"), by = "day", length.out = 30) Q <- c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1, rep(0, 18)) disc <- data.frame(date = dates, Q_mm = Q) r_mc <- flood_route(disc, method = "muskingum-cunge") r_kin <- flood_route(disc, method = "kinematic") # Kinematic attenuates less than Muskingum-Cunge r_kin$attenuation >= r_mc$attenuation # Spatial inundation depth from a HAND surface (a numeric vector here; a # terra SpatRaster works the same way and produces a mappable raster) hand <- c(0, 0.5, 1, 2, 4, 6) r_spatial <- flood_route(disc, area_km2 = 300, hand = hand) r_spatial$depth_raster # deepest in the valley, dry on high ground
Converts a daily rainfall record into a discharge (streamflow) series, the link between rainfall in the sky and water in the channel. floodflow operates on a daily timestep: each row of the rainfall data frame is one day, and discharge is returned in mm/day; aggregate any sub-daily record to daily totals before use. Potential evapotranspiration is computed by the Oudin formula from temperature and latitude. When airGR is installed, the GR4J lumped conceptual model is used; otherwise a simple conceptual fallback runs so the pipeline still produces a discharge series.
flood_runoff( x, lat_deg = 5.6, temp_c = 28, params = NULL, engine = c("auto", "airGR", "simple") )flood_runoff( x, lat_deg = 5.6, temp_c = 28, params = NULL, engine = c("auto", "airGR", "simple") )
x |
A |
lat_deg |
Latitude in decimal degrees, for PET. Defaults to |
temp_c |
Constant air temperature (degrees C) used when the rainfall
data has no |
params |
Optional named numeric vector of GR4J parameters |
engine |
Which engine to use: |
GR4J parameters may be supplied; if not, illustrative defaults are used. In a
real study with observed discharge, calibrate the parameters (for example
with airGR::Calibration_Michel) before relying on the output.
Infiltration is represented implicitly, not as a separate step. Rainfall
is partitioned into runoff and soil storage by a production store (a
soil-moisture bucket of capacity store_max): when the soil is dry most
rain infiltrates and little runs off, and as it saturates the runoff fraction
rises toward one. This is a saturation-excess representation. There is no
explicit Green-Ampt, Horton, or SCS curve-number infiltration function in this
version (curve-number infiltration is planned for a future release).
If x is a flood_project, the same object with its
runoff slot populated. Otherwise a list of class
flood_runoff with elements discharge (a data frame of
date and Q_mm), pet (the PET series), engine
used, and peak (the maximum discharge and its date).
pet_oudin for the evapotranspiration input.
set.seed(1) dates <- seq(as.Date("2020-01-01"), as.Date("2021-12-31"), by = "day") rain <- data.frame( date = dates, precip_mm = round(rgamma(length(dates), 0.7, scale = 8) * rbinom(length(dates), 1, 0.4), 1) ) rr <- flood_runoff(rain, engine = "simple") rr$peakset.seed(1) dates <- seq(as.Date("2020-01-01"), as.Date("2021-12-31"), by = "day") rain <- data.frame( date = dates, precip_mm = round(rgamma(length(dates), 0.7, scale = 8) * rbinom(length(dates), 1, 0.4), 1) ) rr <- flood_runoff(rain, engine = "simple") rr$peak
Turns the design return levels from flood_extremes into a
scenario for a chosen future, so that a flood can be modelled under
present-day or changed-climate conditions. Three methods are offered, from
zero-dependency to full-fidelity:
flood_scenario( x, method = c("delta", "trend", "cmip6"), change_factor = 1.15, horizon_year = NULL, scenario_label = NULL )flood_scenario( x, method = c("delta", "trend", "cmip6"), change_factor = 1.15, horizon_year = NULL, scenario_label = NULL )
x |
A |
method |
One of |
change_factor |
Numeric multiplier for |
horizon_year |
Target year for |
scenario_label |
Optional character label for the scenario (for example
|
"trend"Extrapolate the fitted non-stationary location trend forward to a target year. Uses only the record already analysed.
"delta"Scale the stationary return levels by a change factor (for example 1.15 for a 15% increase). The default and recommended route for data-scarce settings; change factors can come from published CMIP6 summaries per Shared Socioeconomic Pathway.
"cmip6"Placeholder for ingesting downscaled CMIP6
projections directly; not yet implemented, and currently returns an
informative error. Use "delta" with a CMIP6-derived change
factor in the meantime.
If x is a flood_project, the same object with its
scenario slot populated. Otherwise a list of class
flood_scenario with elements method, label,
baseline (the present-day return-level data frame), adjusted
(a data frame of period and level_mm under the scenario), and
change (the ratio of adjusted to baseline at each period).
IPCC (2021). Climate Change 2021: The Physical Science Basis. Contribution of Working Group I to the Sixth Assessment Report of the Intergovernmental Panel on Climate Change. Cambridge University Press.
flood_extremes for the design levels this adjusts.
set.seed(1) rain <- data.frame( date = seq(as.Date("1985-01-01"), as.Date("2024-12-31"), by = "day"), precip_mm = round(rgamma(14610, 0.7, scale = 6) * rbinom(14610, 1, 0.3), 1) ) ext <- flood_extremes(rain) # 15% wetter design storm sc <- flood_scenario(ext, method = "delta", change_factor = 1.15, scenario_label = "SSP2-4.5 2050") sc$adjustedset.seed(1) rain <- data.frame( date = seq(as.Date("1985-01-01"), as.Date("2024-12-31"), by = "day"), precip_mm = round(rgamma(14610, 0.7, scale = 6) * rbinom(14610, 1, 0.3), 1) ) ext <- flood_extremes(rain) # 15% wetter design storm sc <- flood_scenario(ext, method = "delta", change_factor = 1.15, scenario_label = "SSP2-4.5 2050") sc$adjusted
Builds a machine-learning emulator that approximates the routing model's depth response to its parameters, so that many what-if scenarios can be explored far faster than re-running the full pipeline. Training data are generated by evaluating the Manning depth relation across sampled parameters; the surrogate then predicts depth for new parameter sets.
flood_surrogate( x, n_train = 500, n_range = c(0.02, 0.08), width_range = c(10, 40), seed = NULL )flood_surrogate( x, n_train = 500, n_range = c(0.02, 0.08), width_range = c(10, 40), seed = NULL )
x |
A |
n_train |
Number of training samples. Default |
n_range, width_range
|
Length-2 priors for Manning's |
seed |
Optional integer seed for reproducibility. |
When ranger is installed, a random forest is used; otherwise a log-linear model provides a dependency-free fallback (exact for the power-law Manning relation, and a reasonable approximation more generally). The surrogate is a convenience for rapid exploration and interpolation, not a replacement for the physical model.
If x is a flood_project, the same object with its
surrogate entry stored in meta (the project schema has no
dedicated slot) and the stage logged. Otherwise a list of class
flood_surrogate with elements engine ("ranger" or
"loglinear"), predict (a function taking a data frame with
columns Q, n, width and returning predicted depth),
performance (in-sample rmse and r2), and
settings.
flood_route for the model being emulated.
disc <- data.frame( date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1) ) r <- flood_route(disc, area_km2 = 300) s <- flood_surrogate(r, n_train = 300, seed = 1) s$performance # Predict depth for new parameter sets, fast s$predict(data.frame(Q = 150, n = 0.04, width = 25))disc <- data.frame( date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1) ) r <- flood_route(disc, area_km2 = 300) s <- flood_surrogate(r, n_train = 300, seed = 1) s$performance # Predict depth for new parameter sets, fast s$predict(data.frame(Q = 150, n = 0.04, width = 25))
Applies Generalized Likelihood Uncertainty Estimation (GLUE) to the routing stage. Uncertain parameters (Manning's roughness and channel width) are sampled from priors, the flood depth is predicted for each sample, and each sample is weighted by an informal likelihood measuring its agreement with an observed depth. This yields a predictive uncertainty band on flood depth and, as the inverse problem, weighted parameter estimates conditioned on the observation.
flood_uncertainty( x, observed_depth_m, n_sim = 5000, n_range = c(0.02, 0.08), width_range = c(10, 40), obs_error = 0.1, behavioural_fraction = 0.1, seed = NULL )flood_uncertainty( x, observed_depth_m, n_sim = 5000, n_range = c(0.02, 0.08), width_range = c(10, 40), obs_error = 0.1, behavioural_fraction = 0.1, seed = NULL )
x |
A |
observed_depth_m |
Observed peak flood depth in metres to condition on, for example from a surveyed high-water mark or satellite estimate. |
n_sim |
Number of Monte-Carlo samples. Default |
n_range |
Length-2 numeric range for the Manning's |
width_range |
Length-2 numeric range for the channel width prior (m).
Default |
obs_error |
Relative observation error (standard deviation as a fraction
of the observed depth) used in the Gaussian likelihood. Default |
behavioural_fraction |
Fraction of samples, ranked by likelihood, kept as
behavioural. Default |
seed |
Optional integer seed for reproducibility. |
GLUE is the workhorse uncertainty method in hydrology. A key feature it reveals is equifinality: many different parameter combinations can reproduce the same observation, so individual parameters may stay uncertain even when the prediction is well constrained. The function reports the parameter spread honestly rather than collapsing it to a single point.
If x is a flood_project, the same object with its
uncertainty slot populated. Otherwise a list of class
flood_uncertainty with elements observed_depth_m,
n_behavioural (count kept), depth_band (named vector: lower,
median, upper of the weighted predictive band), obs_in_band
(logical), estimates (weighted-mean and range for each parameter),
equifinality (the n-width correlation among behavioural sets), and
behavioural (a data frame of kept samples and weights).
Beven, K. and Binley, A. (1992) The future of distributed models: model calibration and uncertainty prediction. Hydrological Processes 6, 279–298. doi:10.1002/hyp.3360060305
flood_route for the model being conditioned.
disc <- data.frame( date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1) ) r <- flood_route(disc, method = "muskingum-cunge", area_km2 = 300) u <- flood_uncertainty(r, observed_depth_m = r$peak_depth_m, n_sim = 2000, seed = 1) u$depth_band u$obs_in_banddisc <- data.frame( date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1) ) r <- flood_route(disc, method = "muskingum-cunge", area_km2 = 300) u <- flood_uncertainty(r, observed_depth_m = r$peak_depth_m, n_sim = 2000, seed = 1) u$depth_band u$obs_in_band
Implements the standard disaster-risk decomposition
. Each input layer is
normalised to , the three are multiplied cell by cell, and the
product is re-normalised to give a relative risk index. Because the
combination is multiplicative, risk is zero wherever any component is zero:
there is no risk without all of hazard, something exposed, and susceptibility.
flood_vulnerability(x, exposure, vulnerability = NULL, hazard = NULL)flood_vulnerability(x, exposure, vulnerability = NULL, hazard = NULL)
x |
A |
exposure |
Numeric vector or |
vulnerability |
Optional numeric vector or |
hazard |
Optional explicit hazard layer when |
Inputs are numeric vectors (aligned cell values) or, when terra is
installed, SpatRaster layers. Vulnerability may be omitted, in which
case exposure alone weights the hazard.
If x is a flood_project, the same object with its
vulnerability slot populated. Otherwise a list of class
flood_vulnerability with elements risk (the normalised risk
index), components (the normalised hazard, exposure and
vulnerability), and summary (min, mean, max of risk).
Reimann, L. et al. (2024) An empirical social vulnerability map for flood risk assessment at global scale. Earth's Future 12. doi:10.1029/2023EF003895
flood_route for the hazard layer.
set.seed(1) hazard <- runif(100, 0, 5) # flood depth pop <- rpois(100, 50) # exposure deprivation <- runif(100) # vulnerability v <- flood_vulnerability(hazard, exposure = pop, vulnerability = deprivation) range(v$risk)set.seed(1) hazard <- runif(100, 0, 5) # flood depth pop <- rpois(100, 50) # exposure deprivation <- runif(100) # vulnerability v <- flood_vulnerability(hazard, exposure = pop, vulnerability = deprivation) range(v$risk)
A named numeric vector of representative Manning's values for common
land-cover classes, drawn from standard hydraulic references and distributed
hydrological models. Used as the default lookup by roughness
when method = "landcover". Users may supply their own table.
floodflow_lc_roughnessfloodflow_lc_roughness
A named numeric vector. Names are land-cover classes; values are
Manning's .
A named numeric vector of length 8. Each element is a
representative Manning's roughness coefficient (dimensionless)
and its name is the land-cover class it applies to ("water",
"urban", "bare", "grassland", "cropland",
"shrub", "forest", "wetland"). It is the default
land-cover-to-roughness lookup table used by roughness.
floodflow_lc_roughness["forest"]floodflow_lc_roughness["forest"]
Test whether an object is a flood project
is_flood_project(x)is_flood_project(x)
x |
An object to test. |
A single logical value: TRUE if x inherits from class
flood_project, otherwise FALSE.
is_flood_project(flood_project()) is_flood_project(list())is_flood_project(flood_project()) is_flood_project(list())
Computes daily potential evapotranspiration (PET) from air temperature and latitude alone, following Oudin et al. (2005). Because it needs no radiation, humidity or wind data, it suits data-scarce settings where only temperature is available. Extraterrestrial radiation is derived from solar geometry for the given day of year and latitude.
pet_oudin(jday, temp_c, lat_deg)pet_oudin(jday, temp_c, lat_deg)
jday |
Integer vector of Julian day of year (1–366). |
temp_c |
Numeric vector of mean daily air temperature in degrees
Celsius, the same length as |
lat_deg |
Latitude in decimal degrees (positive north, negative south). |
A numeric vector of PET in millimetres per day, never negative.
Oudin, L. et al. (2005) Which potential evapotranspiration input for a lumped rainfall-runoff model? Journal of Hydrology 303, 290–306. doi:10.1016/j.jhydrol.2004.08.026
# A year of PET for Accra (latitude ~5.6 N) jd <- 1:365 temp <- 28 + 3 * sin(2 * pi * (jd - 40) / 365) pet <- pet_oudin(jd, temp, lat_deg = 5.6) range(pet)# A year of PET for Accra (latitude ~5.6 N) jd <- 1:365 temp <- 28 + 3 * sin(2 * pi * (jd - 40) / 365) pet <- pet_oudin(jd, temp, lat_deg = 5.6) range(pet)
Print a flood extremes result
## S3 method for class 'flood_extremes' print(x, ...)## S3 method for class 'flood_extremes' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
set.seed(1) rain <- data.frame( date = seq(as.Date("1990-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(11323, 0.7, scale = 6), 1) ) print(flood_extremes(rain))set.seed(1) rain <- data.frame( date = seq(as.Date("1990-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(11323, 0.7, scale = 6), 1) ) print(flood_extremes(rain))
Print a flood hydraulics result
## S3 method for class 'flood_hydraulics' print(x, ...)## S3 method for class 'flood_hydraulics' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) print(flood_hydraulics(flood_route(disc)))disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) print(flood_hydraulics(flood_route(disc)))
Print a flood map
## S3 method for class 'flood_map' print(x, ...)## S3 method for class 'flood_map' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
set.seed(1) rain <- data.frame( date = seq(as.Date("2000-01-01"), as.Date("2010-12-31"), by = "day"), precip_mm = round(rgamma(4018, 0.7, scale = 6) * rbinom(4018, 1, 0.3), 1) ) fp <- flood_project("demo"); fp$rainfall <- rain fp <- flood_route(flood_runoff(fp, engine = "simple"), area_km2 = 300) print(flood_map(fp, layer = "depth"))set.seed(1) rain <- data.frame( date = seq(as.Date("2000-01-01"), as.Date("2010-12-31"), by = "day"), precip_mm = round(rgamma(4018, 0.7, scale = 6) * rbinom(4018, 1, 0.3), 1) ) fp <- flood_project("demo"); fp$rainfall <- rain fp <- flood_route(flood_runoff(fp, engine = "simple"), area_km2 = 300) print(flood_map(fp, layer = "depth"))
Print a flood project
## S3 method for class 'flood_project' print(x, ...)## S3 method for class 'flood_project' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The flood_project object x, returned invisibly. Called
for the side effect of printing a compact summary to the console.
print(flood_project(name = "Odaw basin"))print(flood_project(name = "Odaw basin"))
Print a roughness result
## S3 method for class 'flood_roughness' print(x, ...)## S3 method for class 'flood_roughness' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
print(roughness(method = "constant", value = 0.04))print(roughness(method = "constant", value = 0.04))
Print a flood route result
## S3 method for class 'flood_route' print(x, ...)## S3 method for class 'flood_route' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) print(flood_route(disc))disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) print(flood_route(disc))
Print a flood runoff result
## S3 method for class 'flood_runoff' print(x, ...)## S3 method for class 'flood_runoff' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
set.seed(1) rain <- data.frame( date = seq(as.Date("2020-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(366, 0.7, scale = 8) * rbinom(366, 1, 0.4), 1) ) print(flood_runoff(rain, engine = "simple"))set.seed(1) rain <- data.frame( date = seq(as.Date("2020-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(366, 0.7, scale = 8) * rbinom(366, 1, 0.4), 1) ) print(flood_runoff(rain, engine = "simple"))
Print a flood scenario
## S3 method for class 'flood_scenario' print(x, ...)## S3 method for class 'flood_scenario' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
set.seed(1) rain <- data.frame( date = seq(as.Date("1990-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(11323, 0.7, scale = 6), 1) ) print(flood_scenario(flood_extremes(rain), change_factor = 1.2))set.seed(1) rain <- data.frame( date = seq(as.Date("1990-01-01"), as.Date("2020-12-31"), by = "day"), precip_mm = round(rgamma(11323, 0.7, scale = 6), 1) ) print(flood_scenario(flood_extremes(rain), change_factor = 1.2))
Print a flood surrogate
## S3 method for class 'flood_surrogate' print(x, ...)## S3 method for class 'flood_surrogate' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) print(flood_surrogate(flood_route(disc, area_km2 = 300), n_train = 200, seed = 1))disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) print(flood_surrogate(flood_route(disc, area_km2 = 300), n_train = 200, seed = 1))
Print a flood uncertainty result
## S3 method for class 'flood_uncertainty' print(x, ...)## S3 method for class 'flood_uncertainty' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) r <- flood_route(disc, area_km2 = 300) print(flood_uncertainty(r, observed_depth_m = r$peak_depth_m, n_sim = 1000, seed = 1))disc <- data.frame(date = seq(as.Date("2020-06-01"), by = "day", length.out = 12), Q_mm = c(0, 1, 3, 8, 18, 30, 22, 14, 8, 4, 2, 1)) r <- flood_route(disc, area_km2 = 300) print(flood_uncertainty(r, observed_depth_m = r$peak_depth_m, n_sim = 1000, seed = 1))
Print a flood vulnerability result
## S3 method for class 'flood_vulnerability' print(x, ...)## S3 method for class 'flood_vulnerability' print(x, ...)
x |
A |
... |
Ignored, present for S3 method consistency. |
The object x, invisibly; prints a compact summary.
set.seed(1) print(flood_vulnerability(runif(50, 0, 5), exposure = rpois(50, 40), vulnerability = runif(50)))set.seed(1) print(flood_vulnerability(runif(50, 0, 5), exposure = rpois(50, 40), vulnerability = runif(50)))
Produces a Manning's roughness coefficient () for use by the routing
stage, by one of three methods. Roughness is the single most sensitive
hydraulic parameter, so the function makes the choice explicit and always
lets the user override it.
roughness( x = NULL, method = c("constant", "landcover", "ndvi"), value = 0.035, table = floodflow_lc_roughness, n_min = 0.02, n_max = 0.12, data = NULL )roughness( x = NULL, method = c("constant", "landcover", "ndvi"), value = 0.035, table = floodflow_lc_roughness, n_min = 0.02, n_max = 0.12, data = NULL )
x |
A |
method |
One of |
value |
Manning's |
table |
Named numeric vector mapping land-cover classes to |
n_min, n_max
|
Roughness bounds for |
data |
Optional explicit data input when |
"constant"A single applied everywhere. Simplest and
fully reproducible.
"landcover"Look up from land-cover classes using a
table (the built-in floodflow_lc_roughness by default, or a
user-supplied named vector).
"ndvi"Derive from NDVI with a monotonic empirical
function, so remotely-sensed vegetation density sets roughness.
The function operates on plain vectors and, when terra is installed, on
raster inputs (SpatRaster). Raster handling is optional: if the input
is a raster and terra is not available, the function stops with an
informative message.
If x is a flood_project, the same object with its
roughness slot populated by a list of class flood_roughness.
Otherwise the flood_roughness list directly, with elements
method, n (the resulting roughness: a scalar, numeric vector,
or SpatRaster), and summary (min, mean and max of ).
Manning, R. (1891). On the flow of water in open channels and pipes. Transactions of the Institution of Civil Engineers of Ireland, 20, 161-207.
Chow, V. T. (1959). Open-Channel Hydraulics. McGraw-Hill, New York.
floodflow_lc_roughness for the default lookup table.
# Constant roughness roughness(method = "constant", value = 0.03) # From land-cover classes cls <- c("urban", "cropland", "forest", "water") roughness(cls, method = "landcover")$n # From NDVI values roughness(c(0, 0.3, 0.6, 0.9), method = "ndvi")$n# Constant roughness roughness(method = "constant", value = 0.03) # From land-cover classes cls <- c("urban", "cropland", "forest", "water") roughness(cls, method = "landcover")$n # From NDVI values roughness(c(0, 0.3, 0.6, 0.9), method = "ndvi")$n
Summarise a flood project
## S3 method for class 'flood_project' summary(object, ...)## S3 method for class 'flood_project' summary(object, ...)
object |
A |
... |
Ignored, present for S3 method consistency. |
A data.frame with one row per pipeline slot and columns
slot and status (either "populated" or "empty"),
returned invisibly after printing.
summary(flood_project(name = "Odaw basin"))summary(flood_project(name = "Odaw basin"))
The Kerby formula for overland (sheet) flow time of concentration, suited to the upstream portion of a catchment before channel flow begins. Often combined with Kirpich channel time in the Kerby-Kirpich approach.
tc_kerby(length_m, slope, retardance = 0.4)tc_kerby(length_m, slope, retardance = 0.4)
length_m |
Overland flow length in metres. |
slope |
Overland slope (dimensionless). |
retardance |
Kerby retardance roughness coefficient (dimensionless);
higher for rougher surfaces. Default |
Overland time of concentration in minutes.
Kerby, W. S. (1959) Time of concentration for overland flow. Civil Engineering, 29(3), 174.
tc_kerby(100, 0.01, retardance = 0.4)tc_kerby(100, 0.01, retardance = 0.4)
The Kirpich (1940) empirical formula for the time of concentration of a channelised catchment, in the SI form with length in metres. Time of concentration is the time for water to travel from the hydraulically most distant point to the outlet, a key control on peak discharge timing.
tc_kirpich(length_m, slope)tc_kirpich(length_m, slope)
length_m |
Flow-path length in metres. |
slope |
Channel slope (dimensionless, m/m). |
Time of concentration in minutes.
Kirpich, Z. P. (1940) Time of concentration of small agricultural watersheds. Civil Engineering 10(6), 362.
tc_kirpich(1500, 0.05)tc_kirpich(1500, 0.05)