TERRANOETIS

Landslide debris flow (Voellmy–Salm depth-averaged)

Platform v3.0.0 Docs v3.0.0 MEASURED LOCALLY

Full description: Read the full narrative

Slope failure begins with a Mohr–Coulomb infinite-slope assessment over a susceptibility field (with Newmark-style seismic, effective-stress rainfall, and lahar triggers), converts susceptible steep cells into an initial debris mass, and routes it with the depth-averaged Voellmy–Salm equations using Rusanov mass fluxes and a semi-implicit momentum update. μ and ξ are free calibration parameters — the platform ships an endpoint to fit them against an observed runout.

Execution mode
Kaggle kernel (numpy, CPU instance); local in-process for calibration & Monte-Carlo server/kaggle/simRunner.ts:126-141 server/kaggle/localRunner.ts:1-15
Verification
MEASURED locally — convergence/conservation script PASS re-executed
Wire scenario type
landslide — contract at src/services/kaggleSim.ts:28-240; job API at Simulation job API
Evidence legend

MEASURED marks values produced by executing the actual code on this machine (commands in Reproduction; raw logs summarised in Methodology → Evidence runs).

Governing equations and coefficients

Source attribution as stated in the kernel header (verbatim):

Voellmy-Salm friction law: τ_b/ρ = μ_c·g·h·cos²θ + g·u·|u|/ξ where μ_c = tan φ_res is the residual (dynamic) basal friction and ξ (m/s²) is Voellmy's turbulent coefficient. Debris: φ_res ≈ 14°, ξ ≈ 300.
kaggle-kernels/landslide-sim/main.py:11-14
∂h/∂t + ∇·(h·u) = 0; ∂(hu)/∂t + ∇·(hu⊗u) = −g·h·∇(h+z) − τ_b/ρ
Depth-averaged debris-flow SWE (mass via Lax-Friedrichs, momentum semi-implicit Euler). kaggle-kernels/landslide-sim/main.py:7-10,518-537,579-629
τ_b/ρ = μ·g·h·cos²θ + g·u·|u|/ξ (μ capped by driving stress — yield behaviour)
Voellmy–Salm total basal stress; Coulomb term only reduces when driving stress exceeds it. kaggle-kernels/landslide-sim/main.py:593-624
FS = (c + σ′·tanφ) / (γ·h·sinθ), σ′ = γ_soil·h_soil·cosθ·0.5
Infinite-slope Mohr–Coulomb factor of safety assuming 50 % saturation; γ_soil = 18,000 N/m³, h_soil = 2 m. kaggle-kernels/landslide-sim/main.py:226-235,228-230
seismic: fs_seismic = fs − a/(g·sinθ) (Newmark criterion a_max > g(FS−1)sinθ); rainfall: fs·(1 − 0.7·rain_factor); volcanic: exp(−r/0.25·gs)·(slope>15°)
Trigger mechanisms on the susceptibility field. kaggle-kernels/landslide-sim/main.py:241-271
ln PGA[g] = 3.586 + 0.707·M − 1.093·ln(r+10) − 0.0053·(r+10) [site term 0.25·ln(760/760) ≡ 0]
"Simplified Campbell–Bozorgnia" PGA field feeding the trigger; r in km floored at 1; epicentre fixed at (0.7gs, 0.3gs). No site amplification — the term is identically zero. kaggle-kernels/landslide-sim/main.py:187-189,372
E = min(entrainment_rate·|u|·dt·(1 − h/(h+ent_ref)), bed)
Hungr/McDougall-type velocity-proportional entrainment, self-limiting, default OFF (rate 0). kaggle-kernels/landslide-sim/main.py:556-577,314-315

Coefficients and named constants

Named constants and defaults.
NameValueMeaningSource
G9.81 m/s²Gravitykaggle-kernels/landslide-sim/main.py:54
RHO_DEBRIS2000 kg/m³Bulk debris density (sediment + water)kaggle-kernels/landslide-sim/main.py:55
φ_res / μ_default14° / tan φ ≈ 0.249Residual friction angle (μ = 0.25 UI default)kaggle-kernels/landslide-sim/main.py:68-69
ξ_default300 m/s²Turbulent coefficient (range 100–1000 in comment: "ξ=300 gives ~6–11 m/s on realistic slopes")kaggle-kernels/landslide-sim/main.py:59-70
φ / c defaults35° / 500 PaMohr–Coulomb strength (overridable per run)kaggle-kernels/landslide-sim/main.py:73-74
PGA / rain thresholds0.15 g / 150 mmTrigger defaultskaggle-kernels/landslide-sim/main.py:77-78
V_MAX / CFL30 m/s / 0.15Velocity cap and inner substep criterionkaggle-kernels/landslide-sim/main.py:326-327,503-509
Source constructionsus > 0.4, slope > 25°, radius 0.32·gs, h = sus·(slope/30)·6 ∈ [2,15] m, capped at 5 % of gridLocalized failure mass (rationale comments for each guard)kaggle-kernels/landslide-sim/main.py:391-421

Parameter contract

Landslide parameters. Shared request envelope (validated at the client boundary before dispatch).

Landslide parameters.
UI controlWire fieldUnitValid range (UI · wire · kernel)DefaultPhysical meaningSource
Trigger Type selecttrigger_typeenumearthquake | rainfall | volcanicearthquakeWhich failure mechanism maps rainfall/PGA fields to susceptibilitysrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:211 kaggle-kernels/landslide-sim/main.py:298
Earthquake Magnitude slidermagnitudeMUI 4–9.5; wire 3–9.7UI 6.5 · kernel 6.5Feeds the PGA field only under earthquake triggersrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:212 kaggle-kernels/landslide-sim/main.py:299
PGA Threshold sliderpga_thresholdgUI 0.05–0.5 (auto-lowered with M); wire 0.01–1UI 0.15 · kernel 0.15Cell activates when local PGA exceeds itsrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:213,625 kaggle-kernels/landslide-sim/main.py:300
Total Rainfall sliderrainfall_mmmmUI 50–2000; wire 0–3000UI 200 · kernel 200Rain-trigger susceptibility via effective-stress loss (≤ 70 %)src/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:214 kaggle-kernels/landslide-sim/main.py:302,252-260
Friction Angle / Cohesion slidersfriction_angle, cohesion°; PaUI 20–50 / 0–2000; wire 10–60 / 0–500035° / 500 PaMohr–Coulomb strength in the FS criterionsrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:215-216 kaggle-kernels/landslide-sim/main.py:304-305
Voellmy μ slidermuUI 0.05–0.5; wire 0.01–1UI 0.25 · kernel tan 14° ≈ 0.249Dry (dynamic) Coulomb friction — free calibration parametersrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:230 kaggle-kernels/landslide-sim/main.py:311
Voellmy ξ sliderxim/s²UI 50–1500; wire 10–5000UI 300 · kernel 300Turbulent friction coefficient — free calibration parametersrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:232 kaggle-kernels/landslide-sim/main.py:312
Bed Entrainment Rate / Erodible Depth slidersentrainment_rate, erodible_depth_m1/s; mUI 0–0.01 / 0–20; wire 0–0.1 / 0–50UI 0 / 5 · kernel 0 / 0 (off)Velocity-proportional growth of the flow by bed erosion (default disabled)src/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:233-236 kaggle-kernels/landslide-sim/main.py:314-315,556-577
Duration sliderduration_hourshUI 0.5–48; wire ≤ 720; kernel also caps simulated time at 300 sUI 2 · kernel 2Flow routing windowsrc/components/scenarios/ScenarioEditor.tsx:114-134 src/services/kaggleSim.ts:217 kaggle-kernels/landslide-sim/main.py:303,435-442
Terrain (optional)terrain(+_gs)m≤ 65,536 cellsReal relief; otherwise a deterministic synthetic ridge (seed 42)src/services/kaggleSim.ts:218-224 kaggle-kernels/landslide-sim/main.py:81-103

Outputs

Files written per run (also served by GET /api/kaggle/simulate/:jobId/grid/:name and …/geotiff/:name)
FieldUnitMeaningSource
landslide_depth.npymFinal debris thicknesskaggle-kernels/landslide-sim/main.py:875-895
landslide_velocity.npy, velocity_x/y.npym/sSpeed and componentskaggle-kernels/landslide-sim/main.py:875-895
runout_distance.npykm fieldDistance from the depth-weighted source centroidkaggle-kernels/landslide-sim/main.py:457-463
susceptibility.npy / trigger_map.npy / slope.npy0–1 / g or mm / °Failure susceptibility and trigger field (PGA in g for earthquake runs, else rainfall mm)kaggle-kernels/landslide-sim/main.py:744,875-895
snapshots_depth/velocity/vx/vy.npy + snapshot_times.npy—; sAnimation serieskaggle-kernels/landslide-sim/main.py:875-895
metadata.jsonmodel "depth_averaged_debris_flow", friction_law "voellmy", solver "lax_friedrichs", total volume + outflow ledgerkaggle-kernels/landslide-sim/main.py:772-775,756-761

Spatial-origin semantics

Square domain; row 0 = north. Documented axis-naming quirk: internally dz_dx is the north–south (row-axis) gradient and dz_dy the east–west (column-axis) gradient; the code comment records that the old mapping was swapped and would have driven debris across slopes on real terrain. Runout is measured from the depth-weighted source centroid. kaggle-kernels/landslide-sim/main.py:147-148,465-475,457-463

Documented validity limits (verbatim from the code)

'The genuine conservation proof is the closed-box test (verify_closed_box) and the grid-convergence script, not this algebraic bookkeeping.' · axis-mapping note: 'The old mapping was swapped, which on *real* terrain would drive debris across the slope instead of down it' · susceptibility raw mask note: 'The raw mask (susceptibility > 0.3) covers ~99% of the grid, so the "pile" is a grid-wide slab that blows up and renders as a hollow rim.' · "Certified-grade" debris-flow modelling requires the free parameters to be fit to a real slide, not guessed … Sample runout resources: Hungr et al. (2001) runout databases
kaggle-kernels/landslide-sim/main.py:712-714,465-475,391-393 kaggle-kernels/landslide-sim/calibrate.py:4-14

The closed-box verifier exists in main.py but is NOT invoked by main() (unlike flood/tsunami/volcano); the authoritative gates are validate_convergence.py (conservation 1e-8, runout refinement ≤ 0.25, upsampling RMSE ≤ max(10 %, 30 m)) and the /api/kaggle/calibrate grid fit. kaggle-kernels/landslide-sim/main.py:808-857 kaggle-kernels/landslide-sim/validate_convergence.py:19-21,35-98

Measured runs and timings

Executed on an Apple-Silicon laptop (Python 3.14.5, NumPy 2.4.2). These are observations of one environment, not performance guarantees.
Run / checkMeasured result
Grid-convergence script re-executedPASS — conservation |Δ| = 0 with and without entrainment; runout 3.74→2.87→2.95 km over gs 64→128→256 (fixed 5.12 km domain, dx 80→40→20 m); area refinement Δ1 = 1.386 → Δ2 = 0.050 (gate ≤ 0.25); terrain upsample RMSE 20.6 m = 1.5 % of 1,381 m relief; exit 0
Representative quake-trigger run (128², M 6.5, μ 0.25, ξ 300, 5 min sim)max depth 157 m (coarse-grid pooling), max velocity 26.2 m/s, runout 4.0 km, affected 5.1 km², volume 24.5 M m³; in-domain mass ledger drift 1.56 % (boundary exchange ledger reported separately); wall 2.7 s
Rain + entrainment run (96², 300 mm, rate 0.005/s, bed 4 m)max depth 216 m, velocity 21.6 m/s, runout 6.2 km, affected 25.5 km²; entrained +126 M m³ accounted; mass drift 0.0000 %; wall 2.0 s
Calibration endpoint semanticsμ×ξ grid search {0.15…0.40}×{100…800} minimising |runout − observed| (calibrate.py:24-25,64) — exercised by the server localRunner (spawned python3, in-process)

Reproduction

Commands

# Convergence/conservation gates (in-process, no Kaggle):
cd <repo>/kaggle-kernels/landslide-sim && python3 validate_convergence.py
# → 'PASS — all gates OK'

# Calibrate μ×ξ to an observed runout (documented-event value required):
python3 calibrate.py --observed-runout-km 2.9 --grid-size 128

# Server-side UQ:
curl -s -X POST http://localhost:3001/api/kaggle/landslide/quantify \
  -H 'Content-Type: application/json' -d '{ "request": {…landslide params…}, "samples": 16 }'