Skip to content

WIP: Add vegetation-aware flood modeling: roughness, curve number, and depth from land cover#1029

Merged
brendancol merged 2 commits into
masterfrom
vegetation-flood-modeling
Mar 19, 2026
Merged

WIP: Add vegetation-aware flood modeling: roughness, curve number, and depth from land cover#1029
brendancol merged 2 commits into
masterfrom
vegetation-flood-modeling

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

@brendancol brendancol commented Mar 18, 2026

Summary

Adds three new functions that bridge vegetation/land-cover data and the existing flood pipeline:

  • vegetation_roughness() — derives Manning's n from NLCD land cover codes (categorical lookup) or continuous NDVI (piecewise linear interpolation). Feeds directly into travel_time().
  • vegetation_curve_number() — derives SCS curve number from NLCD + hydrologic soil group (1=A through 4=D). 60-entry lookup table from TR-55/HEC-HMS. Feeds directly into curve_number_runoff().
  • flood_depth_vegetation() — computes flood depth via Manning's normal depth equation: h = (q·n / sqrt(tan(S)))^(3/5), where q is unit discharge, n is roughness, S is slope. Accounts for both terrain slope and spatially varying vegetation roughness, unlike flood_depth() which uses a uniform water level.

Also includes:

  • NLCD_MANNINGS_N dict (15 NLCD codes) and NLCD_CURVE_NUMBER dict (60 code/soil pairs) as public constants
  • 4-backend implementations for each function (numpy, cupy, dask, dask+cupy)
  • 36 new tests covering known values, NaN propagation, validation, custom lookups, physical invariants, and cross-backend parity
  • Top-level imports in __init__.py and accessor methods on both DataArray and Dataset
  • Comparison notebook (33_Vegetation_Flood_Modeling.ipynb) showing standard vs. vegetation-aware workflows side by side

Validation results

38/38 checks passed across all three functions.

Ground truth (hand-computed expected values)

Check Status Max abs error
vegetation_roughness NLCD mode PASS 0.0
vegetation_roughness NDVI mode PASS 0.0
vegetation_curve_number (all 60 lookup entries) PASS 0.0
flood_depth_vegetation scalar n PASS 0.0
flood_depth_vegetation raster n PASS 0.0

Backend parity (256x256 stress dataset, 3-5% NaN)

Comparison Max abs diff NaN match Status
NumPy vs Dask (64x64 chunks) 0.0 yes PASS
NumPy vs Dask (100x100 ragged chunks) 0.0 yes PASS
NumPy vs CuPy 4.4e-16 yes PASS
NumPy vs Dask+CuPy 0.0 yes PASS

All backends produce bit-exact or near-bit-exact results. Max CuPy divergence is within float64 ULP.

Edge cases

Check Status
NaN propagation (all 3 inputs) PASS
Constant surface PASS
Single cell (1x1) PASS
float32 vs float64 input PASS
Float NLCD/CN input with NaN PASS
Unknown NLCD codes -> NaN PASS
Higher roughness -> deeper water PASS
Steeper slope -> shallower water PASS
Zero slope clamped (no inf) PASS

Efficiency

Integer-input backends skip the float64 conversion previously used for NaN checks (dtype.kind == 'f' guard), avoiding unnecessary temporary allocations.

Test plan

  • pytest xrspatial/tests/test_flood.py -v — 81/81 pass (45 existing + 36 new)
  • Ground truth validation against hand-computed values (5/5)
  • Backend parity: numpy, dask, cupy, dask+cupy (all pass)
  • Edge cases: NaN propagation, single cell, dtype, physical invariants (9/9)
  • Run the notebook end-to-end to verify plots render

…th from land cover (#1024)

Three new functions that convert vegetation data into hydraulic
parameters for the existing flood pipeline:

- vegetation_roughness(): Manning's n from NLCD land cover or NDVI
- vegetation_curve_number(): SCS curve number from NLCD + soil group
- flood_depth_vegetation(): Manning's normal depth with spatially
  varying roughness

Includes lookup tables (15 NLCD codes, 60 code/soil entries),
4-backend implementations (numpy/cupy/dask/dask+cupy), 36 new tests,
accessor methods, and a comparison notebook.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Mar 18, 2026
@brendancol brendancol changed the title Add vegetation-aware flood modeling: roughness, curve number, and depth from land cover WIP: Add vegetation-aware flood modeling: roughness, curve number, and depth from land cover Mar 18, 2026
The NLCD/soil lookup backends were converting integer arrays to float64
solely to call isnan(), which always returns False for integer data.
Guard with dtype.kind == 'f' to skip the allocation entirely.
@brendancol brendancol merged commit d6db06f into master Mar 19, 2026
11 checks passed
@brendancol brendancol deleted the vegetation-flood-modeling branch May 4, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant