Lifespans
Two modules, and the feature definitions they share.
Lifespan Design
riverarchitect.lifespan - the Lifespan ▸ Lifespan Design tab.
Answers two questions per cell, for a chosen restoration feature:
Lifespan - how many years is this feature expected to survive here? Each modelled discharge carries a flood return period. For every criterion the feature has a threshold for, the analysis finds the lowest return period at which that threshold is exceeded, which is when the feature fails. The lifespan is the cell-wise minimum across criteria: the first flood that breaks it.
Cells that survive every modelled flood stay NoData. Their lifespan is longer than the largest modelled event and cannot be quantified from the data - writing a number there would be inventing one.
Design - how big does the feature have to be to reach a target lifespan? For grain-based features that is the stable grain size at the design flood, for example the minimum diameter of angular boulders that will not mobilise in a 20-year event.
The criteria
Hydraulic criteria produce a failure return period each, and their minimum is the lifespan:
Criterion |
Fails when |
|---|---|
Water depth |
depth reaches |
Flow velocity |
velocity reaches |
Froude number |
Froude reaches |
Grain stability |
dimensionless bed shear stress reaches |
Spatial criteria are masks applied to that result:
Criterion |
Restricts to |
|---|---|
Depth to water table |
|
Detrended DEM |
|
Grain size |
at most |
Terrain slope |
at least |
Topographic change |
scour or fill at or above the rate - or, for an inverse-relevance feature, below it |
Morphological units |
the units in |
Dimensionless bed shear stress (taux)
River Architect keeps the historical name taux for the Shields parameter. It is not
a dimensional stress and it is not the \(x\)-component of a stress tensor. For the reference
grain fraction \(D_{84}\),
where \(u_*\) is shear velocity, \(g\) is gravitational acceleration, \(s=\rho_s/\rho_w\), and \(\tau_b\) is dimensional bed shear stress. The hydraulic-model raster supplies the depth-averaged speed \(U\), not \(u_*\), so a flow-resistance relation is needed to recover \(u_*^2\) cell by cell.
Define
The current calculation changes resistance law with relative submergence:
Relative submergence |
Resistance relation |
Interpretation |
|---|---|---|
\(\chi \le 7\) |
Rickenmann–Recking |
protruding grains and large-scale roughness strongly affect the depth-averaged flow |
\(7 < \chi < 20\) |
smooth blend |
avoids a numerical seam between resistance laws |
\(\chi \ge 20\) |
Keulegan–Einstein |
well-submerged, fully rough logarithmic resistance |
The high-submergence branch is
This is the relation represented by the original ArcPy expression
Square(u / (5.75 * Log10(12.2 * h / (2 * D84)))). It contains one base-10
logarithm. It is a depth-integrated resistance law derived from a logarithmic wall profile;
it does not require two logarithmic layers in the water column, and it does not assert that
the instantaneous velocity profile is logarithmic from the grain crests to the free surface.
For lower submergence, River Architect uses the field relation of Rickenmann and Recking (2011):
Within the transition interval, let
and blend the stress coefficient, not the velocity ratio:
Outside that interval, \(C_f=C_{RR}^{-2}\) below it and \(C_f=C_K^{-2}\) above it. The reported quantities are then
What the switch does and does not diagnose
The values 7 and 20 are River Architect’s engineering transition bounds, not universal phase boundaries. Published field comparisons show that the unmodified Keulegan relation can disagree substantially with gravel-bed observations at low relative depth; the precise range also depends on bed structure, form drag, slope and how \(k_s\) is defined. The Rickenmann–Recking branch is therefore used where a grain-only log law is least defensible, and the interval is blended so a one-cell change in depth does not create a jump in stress.
This switch assumes turbulent, hydraulically rough gravel/cobble flow. Check the roughness Reynolds number \(k_s^+=u_*k_s/\nu\): if viscosity still affects the resistance, use a smooth/transitionally rough resistance law or, preferably, bed shear exported by the hydraulic model. The switch also cannot separate grain stress from bar, step, bank, vegetation or large-wood form drag.
Relative submergence is not the shallow-water assumption
\(h/k_s\) compares water depth with bed roughness. Saint-Venant or depth-averaged modelling instead requires depth to be small relative to the horizontal length scale and vertical accelerations to remain modest. A wide river can satisfy the depth-averaged approximation while having low \(h/k_s\). Conversely, a locally deep pool can contain strong three- dimensional secondary flow. River Architect uses local depth \(h\approx R\) as a wide-channel approximation to hydraulic radius; for narrow or sidewall-dominated channels, calculate the appropriate hydraulic radius or use modelled bed shear.
The grain percentile must be consistent
Use a measured \(D_{84}\) raster when possible. The fallback \(D_{84}\approx2.2D_{50}\) was
the median relation in the Rickenmann–Recking field data and is only justified when the
input represents \(D_{50}\). A file called dmean.tif is not automatically \(D_{50}\);
record what statistic it contains. Compare \(\theta_{84}\) with a critical Shields value
defined for the same reference fraction, or apply an explicit hiding/exposure correction.
Primary sources: Keulegan (1938), Einstein (1950), and Rickenmann and Recking (2011).
Where it lives, and what it writes
riverarchitect.shear.calculate_taux() is the single implementation; both
riverarchitect.lifespan.LifespanDesign.shields_stress() and
riverarchitect.recruitment.RecruitmentPotential.shields_stress() call it, so the two
modules cannot drift apart. It is pure numpy and takes plain arrays, so it can be used
directly on any aligned depth, velocity and \(D_{84}\) rasters.
Four rasters per discharge come out of it, named after the discharge exactly as the hydraulic rasters they derive from are:
Raster |
Content |
|---|---|
|
dimensionless bed shear stress \(\theta_{84}\) - the quantity the \(\tau_{*,cr}\) thresholds are compared against |
|
squared shear velocity \(u_*^2\), in the condition’s units |
|
relative submergence \(\chi=h/k_s\) |
|
0 invalid, 1 Rickenmann–Recking, 2 blended, 3 Keulegan–Einstein |
ts and tb keep the prefixes River Architect 1.x used, and ts keeps its meaning. tb
does not: 1.x wrote \(u_*^2\) into a raster named for the dimensional stress
\(\rho_w u_*^2\), having cancelled the density again when forming ts. The quantity here is
the one 1.x actually stored, documented rather than mislabelled.
They are written in two places, and both write the same numbers:
into the condition folder, by
riverarchitect.preprocessing.bed_shear_stress()- reachable as Get Started ▸ dimensionless bed shear stress (taux), and the counterpart of 1.x’sLifespanDesign/helper.py, which wrotets/andtb/subfolders there. This is the standalone stress map for a whole condition;into the output folder, by Lifespan Design and Riparian Recruitment, for the discharges each actually used.
Nothing reads them back: both analyses recompute the stress from depth, velocity and
grain size, so a stale or hand-edited ts<Q>.tif cannot quietly change a result.
Read regime<Q>.tif before trusting a stress map. On the bundled sample reach about 95 % of
wet cells are regime 1, meaning the original program’s single logarithmic law was applied
almost everywhere outside its range of validity.
Threshold values
Defaults live in riverarchitect.lifespan.FEATURES as Python rather than a binary
workbook, so they are diffable and reviewable. They reproduce the original
threshold_values.xlsx exactly.
riverarchitect.lifespan.load_threshold_workbook() still reads a project’s own
customised workbook.
The threshold units are a round trip
The original multiplies every length threshold by ft2m when reading the workbook and
divides by it again when applying it, so the two cancel. The values in FEATURES are the
workbook’s own U.S. customary numbers, unconverted. This looks like a missing conversion
and is not one.
Relation to the original
This implements the analysis hierarchy as the wiki documents it, not as a line-by-line
transcription of the arcpy control flow. The original threaded results through a mutable
raster_dict and a chain of Con() calls whose behaviour depended on which rasters
happened to exist, and several of its criteria overwrote their own result four times in a
row. Two-argument riverarchitect.raster.con() is used throughout, so the false branch
is NoData and never zero - passing 0 instead is what creates wetted-area artefacts.
Max Lifespan
riverarchitect.maxlifespan - the Lifespan ▸ Max Lifespan tab.
Lifespan mapping answers “how long does this feature last here?”. This answers the planner’s question instead: which feature belongs here, and how long will it last?
max_lf.tifis the cell-wise maximum across the feature lifespan rasters;a feature wins a cell where its own lifespan equals that maximum;
each winner is written as a mask raster and polygonised into a GeoPackage, so the result can be drawn as action areas on a map.
Ties are kept rather than broken. A cell where two features both reach the maximum appears in both layers, which is why the reported shares add to more than 100 per cent. That is deliberate, and it is what the original did: it tells the planner the choice is theirs.
The result feeds Morphology (Terraforming) - the best_<feature>.tif masks are what Terraforming
reads to know where a feature is planned.
In this section
- Feature lifespan and design assessment
- Introduction to lifespan and design mapping
- Quick GUIde to lifespan and design maps
- Lifespan design: parameter hypotheses
- Parameter hypotheses
- River design and restoration features
- Introduction and Feature Groups
- Pre-defined features and hypotheses
- Define new and modify existing features
- Lifespan design: code extension and modification
- Code extension and modification
- Maximum Lifespan Assessment (MaxLifespan)
- Introduction to maxium (best) lifespan mapping
- Quick GUIde to maximum lifespan maps
- Working principle
- Code modification: Add feature sets for maximum lifespan maps
See also
riverarchitect.lifespan and riverarchitect.maxlifespan in the API
reference.