Skip to content

Extend compute_damage to accept rainfall-driven inundation#17

Merged
rehsani merged 1 commit into
mainfrom
step-10-rainfall-driven-damage
May 4, 2026
Merged

Extend compute_damage to accept rainfall-driven inundation#17
rehsani merged 1 commit into
mainfrom
step-10-rainfall-driven-damage

Conversation

@rehsani
Copy link
Copy Markdown
Owner

@rehsani rehsani commented May 4, 2026

Summary

`compute_damage` now consumes either kind of inundation — the static `InundationDepth` (user scalar water level) or the new `RainfallInundationDepth` (per-cell field driven by Manning + HAND). Same numerics either way; only the scenario metadata differs.

Why

After the routing chain landed (PR #15 + #16), the rainfall-driven flood is a first-class output but the existing damage chain only knew about static-water-level inundation. This closes the last consumer gap: `apply_scs_cn → accumulate_runoff → peak_discharge → compute_water_level → compute_rainfall_inundation → compute_damage` now runs end-to-end on a single curve evaluation, and the resulting DamageMap carries provenance back to the precip source.

API change (backward compatible)

Item Before After
`compute_damage(depth, ...)` `depth: InundationDepth` `depth: InundationDepth | RainfallInundationDepth`
`DamageMap.scenario` not present new field, default `"static"` so existing constructors still work
`DamageMap.water_level` static scalar input for rainfall: per-cell max depth (one-number summary)

The `scenario` field on DamageMap holds either:

  • `"static water level 5.00 m"` (the existing path), or
  • `"rainfall-driven (uniform, T=6.0 hr, hand-driven-by-manning-water-levels)"` (the new path).

Test plan

  • `pytest -m "not integration"` — 332 passed (323 prior + 9 new rainfall-damage tests; 16 deselected integration)
  • All 35 existing damage tests still pass — backward compatibility verified by the default `scenario="static"` field
  • Pinned end-to-end: 100 mm × 6 hr storm over Robit Bata yields 7,355 m² damaged built-up (vs 69,199 m² for the hypothetical static 5 m scenario — order-of-magnitude smaller as the rainfall flood is a narrow channel ribbon)
  • Scenario string contains source/duration/method; water_level equals per-cell max for the rainfall path
  • Smoke test stage 17 produces a hillshade + log-scale damage plot + side-by-side console comparison with the existing stage 8 static damage

Notes

  • This intentionally avoids a Protocol or ABC — the two depth types are a small closed set and a literal Union is the simplest expression.
  • The rainfall path is fully independent of how the precipitation was generated; users plugging in their own `PrecipGrid` (from ERA5/IMERG/CHIRPS or anywhere else) get the same end-to-end damage chain for free.

Damage now consumes either kind of inundation depth — the static
InundationDepth (user-supplied scalar water level) or the new
RainfallInundationDepth (per-cell depth field driven by Manning's
normal-depth + HAND broadcast). Same numerics either way; the
DamageMap's metadata records which scenario produced it via a new
`scenario` string field plus the existing `water_level`, which now
holds the per-cell maximum depth as a one-number summary for the
rainfall path.

- floodpath/damage/models.py: DamageMap gains `scenario: str = "static"`,
  defaulted so the existing 35 damage tests pass unchanged.
- floodpath/damage/compute.py: `depth` argument typed as
  `InundationDepth | RainfallInundationDepth`. Inside, branch on type to
  set scenario string ("static water level X m" vs "rainfall-driven
  (source, T, method)") and water_level (input scalar vs per-cell max).

Tests: 9 new for the rainfall path:
- scenario string content (precip source, duration, method)
- water_level == max(values)
- numerical equivalence between rainfall and static paths at same depth
- upsample-preserving-total still works with rainfall depth + coarser exposure
- end-to-end pinned: 100 mm × 6 hr on Robit Bata fixtures yields
  7,355 m^2 damaged built-up — much smaller than the hypothetical static
  5 m scenario's 69,199 m^2 (consistent with rainfall flood being a
  narrow channel ribbon vs static water level flooding broad valleys)

Smoke test gains stage 17: applies JRC residential to the stage-16
rainfall flood, prints both totals side-by-side for direct comparison
with the existing stage 8 static damage.
@rehsani rehsani merged commit 9d4a7c3 into main May 4, 2026
1 check passed
@rehsani rehsani deleted the step-10-rainfall-driven-damage branch May 4, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant