<< All versions

Skill v1.0.0

currentAutomated scan100/100
lzwei196/kiss-knowledge-infrastructure-for-scientific-simulation/landlab
──Details
PublishedNovember 1, 2026 at 08:09 AM
Content Hashsha256:b4fcc8da984c8252...
Git SHA83b757d15c2a
──Files
Files (1 file, 32.4 KB)
SKILL.md32.4 KBactive
SKILL.md · 587 lines · 32.4 KB

metadata: version: "1.0.0"


MANDATORY EXECUTION POLICY — READ BEFORE PROCEEDING
You MUST run the actual model binary or package described in this document.
If the model fails to import, compile, or execute, you MUST:
1. Check diagnostics/triplets.yaml for a matching error pattern
2. Try the fix suggested in the triplet's remedy section
3. If still failing, report the error to the user with full details
You MUST NOT substitute a simplified Python formula, regression equation,
or hand-coded approximation in place of the real model.
Before starting, run: python preflight_check.py (in this KI directory)
to verify that the model binary/package and required data are available.
DEBUGGING PROTOCOL — When something goes wrong, follow this order:
1. Check triplets — diagnostics/triplets.yaml may already cover this error
2. Read official docs — The model's own documentation for expected formats/units
3. Find working examples — Check outputs/ or the model's shipped test data
4. Fix the tool — With knowledge of what "correct" looks like
Do NOT write custom debug scripts. The answers are in the docs and examples.

<!-- KI-MAP:BEGIN (projected by generate_skill_map.py — edit the KI, not this table) -->

KI map — what to read, and when

when you needreadwhy
FIRST, alwayspreflight_check.pyrun it (python preflight_check.py): proves env/binary/data are usable and emits a machine-readable PREFLIGHT_REPORT= line. Do not debug a run that never had a healthy environment.
to run the pipeline stagestools/ (8 tools)the executable pipeline. Read each tool's argparse (--help) before composing a command; SKILL.md's stage table says which tool serves which stage.
before running a stagedocs/s*_*.md (5 stage docs)per-stage procedure, verification and traps — the how-to that SKILL.md's overview compresses.
on ANY error, before debuggingdiagnostics/triplets.yaml (22 entries)symptom → diagnosis → remedy for this model's known failure modes. Check here FIRST; the answer usually exists. Never renumber or rewrite entries.
to know what an output ISdag.yamlthe model's identity: every output's medium, units, validation_rank (1 = the headline variable) and observability. Scoring and obs-binding read THIS — when asked 'what does this model predict', the dag is the answer, not a guess.
when building inputs / parsing outputsdocs/format_spec.yamlexact I/O shapes + known_issues, projected from dag + triplets. Regenerate with ki_tools_common/generate_format_spec.py after changing either — never hand-edit.
to judge a run's skilldocs/validation_convention.yamlhow this model's field judges it validated: per-dag_variable metrics, directions and CITED pass-bands. A run is graded against these, not against intuition.
for claims and thresholdsdocs/gathered_papers.json (22 papers) + docs/papers_index.mdthe literature this KI is judged by; each entry's text_path is fetched full text in the central paper cache. role: benchmark marks the model's own skill paper.
for a machine-readable summaryknowledge_infrastructure.yamlthe manifest (package, pipeline, validation tier, counts) — projected by ki_tools_common/generate_ki_manifest.py; regenerate after structural changes, never hand-edit.

Projected 2026-08-17 from the KI's actual contents — 9 components present. Refresh: `python3 ki_tools_common/generate_skill_map.py --ki_dir <this KI>`. <!-- KI-MAP:END -->

<!-- KI-TOOL-INDEX:BEGIN (projected by generate_skill_map.py — the discoverability contract: every public tool, exact path; PURPOSE stays human-authored elsewhere) -->

Executable tool index (projected — complete by construction)

Every public tool in this KI, by exact path. What each is FOR lives in the human-written Tool Inventory above; --help on any of these prints its arguments.

tool (exact path)invocation
tools/convert_dem_to_grid.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_dem_to_grid.py --help
tools/convert_soil_params.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_soil_params.py --help
tools/dissect_atchafalaya_ssc_q_surrogate.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/dissect_atchafalaya_ssc_q_surrogate.py --help
tools/dissect_loess_plateau_sediment_yield.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/dissect_loess_plateau_sediment_yield.py --help
tools/dissect_loess_plateau_slope_area.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/dissect_loess_plateau_slope_area.py --help
tools/dissect_space_ssc_q_rating.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/dissect_space_ssc_q_rating.py --help
tools/parse_landlab_output.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/parse_landlab_output.py --help
tools/run_landlab.pyKISSPATH_PYTHON_ENV/bin/python {KI}/tools/run_landlab.py --help

8 public tools; `_`-prefixed helpers and packaging files excluded. <!-- KI-TOOL-INDEX:END -->

Landlab v2.10 — Earth Surface Dynamics Modeling Toolkit

Package: hydrocraft-landlab v1.0.0 Model: Landlab 2.10.1 (Python library with Cython extensions) Domain: Geomorphology, hydrology, stratigraphy, glaciology Created by: Landlab Development Team (CU Boulder, U Washington, Tulane) Last updated: 2026-04-29 Stats: current tool, stage-doc and triplet counts: the KI map at the top of this file Validation status: production_validated


Data Preparation

Forcing data

Data Sources: Use from ki_tools_common.load_forcing import load_daily_forcing for CMFD/MSWX/NASA POWER.

Data Validation Reference: See data_ki/CMFD/SKILL.md for meteorological forcing documentation. See data_ki/USGS_Sediment/SKILL.md for suspended sediment observations.

Applicability

This KI is for landscape evolution and sediment-yield benchmarks only. It does NOT produce a daily discharge hydrograph and is NOT applicable to gauge-discharge tests (e.g. Bengbu, Wangjiaba). The surface_water__discharge field from FlowAccumulator is steady-state Q = drainage_area * uniform_runoff_rate, not a time series. Validation cases supported: slope-area, concavity, sediment yield, Whipple-Tucker analytical, SPACE Qs-Q. For streamflow benchmarks use a hydrologic KI (PIHM, mHM, VIC, etc.).

Overview

Landlab is an open-source Python package for numerical modeling of Earth surface dynamics. Unlike compiled, monolithic landscape evolution models, Landlab is a component-based framework: users compose simulations by coupling reusable process components (erosion, diffusion, flow routing, weathering, etc.) on a shared model grid. The grid stores spatially distributed fields (elevation, drainage area, soil depth) at nodes, links, patches, cells, corners, and faces.

Landlab supports six grid types: RasterModelGrid (uniform rectangular), HexModelGrid (hexagonal cells), VoronoiDelaunayGrid (irregular Voronoi), FramedVoronoiGrid, RadialModelGrid, NetworkModelGrid, and IcosphereGlobalGrid. All grids implement the same field-storage API, so components are grid-agnostic.

There are 60+ process components covering: flow routing (D8, D-infinity, MFD, priority-flood), stream-power erosion, hillslope diffusion, SPACE bedrock- alluvium erosion, overland flow (kinematic wave, de Almeida), flexural isostasy, tectonic faulting, soil production (exponential weathering), fire, vegetation dynamics, species evolution, tidal flow, marine sediment transport, and more.

Installation

From PyPI (recommended)

bash
python -m venv venv && source venv/bin/activate
pip install landlab

From source (development)

bash
git clone https://github.com/landlab/landlab.git
cd landlab
pip install -e ".[dev,testing]"

Dependencies

  • Core: numpy>=1.20, scipy, matplotlib, xarray>=0.16, pandas, pyyaml, netcdf4, bmipy, rich-click
  • Build: cython, setuptools, wheel (Cython extensions for performance)
  • Optional: pyshp (shapefiles), statsmodels, gflex (flexure)

Verify installation

python
import landlab; print(landlab.__version__)
from landlab import RasterModelGrid
mg = RasterModelGrid((10, 10), xy_spacing=100.0)
print(f"Grid OK: {mg.number_of_nodes} nodes")

Pipeline (7 stages)

StageIDToolDescription
1. Grid Setups1_grid—Create model grid with DEM or synthetic topography
2. Input Preparations2_inputconvert_dem_to_grid.pyLoad DEM, set boundary conditions, add fields
3. Soil/Parameter Setups3_paramsconvert_soil_params.pyMap HWSD or other soil data to grid fields
4. Component Assemblys4_assembly—Instantiate and couple Landlab components
5. Executions5_runrun_landlab.pyTime-stepping loop with run_one_step()
6. Output Extractions6_outputparse_landlab_output.pyExtract fields to CSV/NetCDF, compute metrics
7. Diagnosticss7_diag—Validate results against analytical solutions

Parallelism

  • Stages 2 and 3 can run in parallel (independent input preparation)
  • Stage 4 depends on both 2 and 3
  • Stages 5–7 are sequential

Execution Model

Landlab is a Python API, not a CLI binary. Simulations are Python scripts:

python
from landlab import RasterModelGrid
from landlab.components import FlowAccumulator, StreamPowerEroder, LinearDiffuser
# 1. Create grid
mg = RasterModelGrid((50, 50), xy_spacing=100.0)
z = mg.add_zeros("topographic__elevation", at="node")
z += mg.node_x * 0.01 + np.random.rand(mg.number_of_nodes)
# 2. Set boundary conditions
mg.set_closed_boundaries_at_grid_edges(True, False, True, False)
# 3. Instantiate components
fa = FlowAccumulator(mg, flow_director="FlowDirectorD8")
sp = StreamPowerEroder(mg, K_sp=1e-5, m_sp=0.5, n_sp=1.0)
ld = LinearDiffuser(mg, linear_diffusivity=0.01)
# 4. Time loop
dt = 1000.0 # years
for t in range(2000):
fa.run_one_step()
sp.run_one_step(dt)
ld.run_one_step(dt)
# 5. Output
from landlab.io import write_esri_ascii
write_esri_ascii("output.asc", mg, "topographic__elevation")

BMI Interface

Components can also be driven via the Basic Modeling Interface (BMI):

python
from landlab.bmi import wrap_as_bmi
BmiSPE = wrap_as_bmi(StreamPowerEroder)
model = BmiSPE()
model.initialize("config.yaml")
model.update()
model.finalize()

6. Output Description

Source of truth: dag.yaml. The DAG wins over this body if they ever disagree.

Headline output (validation_rank: 1):

sediment_yield — Annual catchment sediment yield via detachment-limited stream power (E = K_sp A^m S^n converted by bulk density). (t/km^2/yr)
Output variable (dag var)RankUnitEmitted inDescription
sediment_yield1t/km^2/yrderived metric (detachment-limited stream-power export)Annual catchment sediment yield via detachment-limited stream power (E = K_sp A^m S^n converted by bulk density).
sediment__outflux (SPACE Qs)2m^3/s (or kg/s)Landlab grid field at_node (SPACE / ErosionDeposition)Sediment flux out of a node; the Qs in the SPACE Qs-Q rating relationship.
surface_water__discharge (steady-state)3m^3/sLandlab grid field at_node (FlowAccumulator)Steady-state discharge Q = drainage_area * runoff_rate from FlowAccumulator; NOT a hydrograph time series.
topographic__elevation4mLandlab grid field at_node; written to ESRI ASCII (.asc) / NetCDF (.nc)Final land-surface elevation of the evolved landscape (node field).
concavity (theta)5dimensionlessderived metric from slope-area regression on the gridLand-surface/channel-topography slope-area concavity index theta = -d(logS)/d(logA); at steady state expected to approach m_sp/n_sp.
steepness (ks)6dimensionless (channel steepness index)derived metric from slope-area regressionChannel steepness index from the slope-area regression.
relief7mderived metric over core nodesMax-minus-min elevation over core nodes; landscape relief at steady state.
soil__depth8mLandlab grid field at_nodeRegolith/soil thickness above bedrock (node field).

The other DAG outputs are: topographic__elevation, concavity (theta), steepness (ks), relief, sediment__outflux (SPACE Qs), soil__depth, and surface_water__discharge (steady-state).


8. Unit Table

Source of truth: dag.yaml and docs/format_spec.yaml. Landlab is unit-agnostic, so the tools and user scripts must keep the unit system consistent.

Variable / quantitySource unit handled by this KIModel or DAG unitConversion / invariantWhere checked or used
sediment_yieldderived from detachment-limited stream-power exportt/km^2/yrE = K_sp A^m S^n converted by bulk densityDAG rank-1 output; tools/dissect_loess_plateau_sediment_yield.py
topographic__elevationDEM elevation in meters; feet are a known trapmfeet to meters: multiply by 0.3048convert_dem_to_grid.py; dt_007
xy_spacing / grid geometryprojected metric spacing requiredmreproject geographic degrees to a metric CRS before loadingconvert_dem_to_grid.py; dt_004
water__unit_flux_inrainfall / runoff from forcing datam/smm/hr to m/s: divide by 3,600,000; mm/day to m/s: divide by 86,400,000; m/yr to m/s: divide by 31,557,600FlowAccumulator; dt_001
surface_water__discharge (steady-state)derived steady-state accumulated runoffm^3/sQ = drainage_area * runoff_rateFlowAccumulator; DAG rank-3 output
soil__depthHWSD-style soil depth commonly in cmmcm to m: divide by 100convert_soil_params.py; dt_006
K_spliterature or calibrated stream-power erodibilitylength^(1-2*m_sp) / timeunits depend on m_sp and n_sp; at m_sp=0.5, n_sp=1.0, K has units 1/yr when dt is in yearsStreamPowerEroder; dt_003
linear_diffusivityliterature or calibrated diffusivitym^2/yr when dt is in yearsm^2/s to m^2/yr: multiply by 3.156e7LinearDiffuser; dt_002
dtuser-chosen timestepyr for landscape evolution, s for overland flowdt must share the time unit of K, diffusivity, uplift, and other ratesrun_landlab.py; dt_005
uplift_ratescalar or field forcingm/yrapplied as z[core_nodes] += uplift_rate * dt when dt is in yearsuser execution loop
sediment__outflux (SPACE Qs)SPACE / ErosionDeposition node fluxm^3/s (or kg/s)compare Qs directly against Q; do not fit SSC = Qs/Q when testing SPACE Qs-QDAG rank-2 output; dt_020
rainfall__daily_depthSoilMoisture rainfall can arrive in m or m/smm at cellm to mm: multiply by 1000; m/s to mm/day: multiply by 86,400,000SoilMoisture; dt_008

11. Validation Status

Run results (site, period, scores) are not kept here. They live in the run records (test_runs in hydrocraft.db and each run's own result files).

Source of truth for validation bars: docs/validation_convention.yaml. Null convention bands are written as no cited threshold; no uncited threshold is substituted.

Performance Metrics -- judged against the field's bar

DAG variableHeadline metricDirectionConvention bar, cited
sediment_yieldpbiaszero_centeredvery good: `PBIAS<= 10 (moriasi2015); good: PBIAS<= 15 (moriasi2015); satisfactory: PBIAS<= 20` (moriasi2015)
topographic__elevationcsimaximizevery good: no cited threshold; good: no cited threshold; satisfactory: no cited threshold; cites: []
concavity (theta)pbiaszero_centeredvery good: no cited threshold; good: no cited threshold; satisfactory: no cited threshold; cites: []
steepness (ks)pbiaszero_centeredvery good: no cited threshold; good: no cited threshold; satisfactory: no cited threshold; cites: []

Data replacement tracking

ComponentSourceStatusNotes
ForcingCMFD/MSWX/NASA POWER via ki_tools_common.load_forcing.load_daily_forcing where meteorological forcing is neededAvailableLandscape-evolution sediment-yield runs commonly use uniform runoff_rate, not a daily hydrograph.
SoilHWSD or other soil data via convert_soil_params.pyAvailableConvert depth from cm to m before Landlab fields.
DEM / topographySRTM/ASTER/LiDAR through convert_dem_to_grid.pyAvailableDEM must be projected in meters and NoData must be closed.
Initial conditionsLandlab grid fields (topographic__elevation, soil__depth, bedrock__elevation)AvailableField locations and units must match component expectations.

Grid Field System

Fields are stored at 7 locations on the grid:

LocationDescriptionAccess Pattern
nodeGrid vertices (most common)grid.at_node["field_name"]
linkEdges connecting nodesgrid.at_link["field_name"]
patchPolygons in primal meshgrid.at_patch["field_name"]
cellPolygons in dual meshgrid.at_cell["field_name"]
cornerVertices in dual meshgrid.at_corner["field_name"]
faceEdges in dual meshgrid.at_face["field_name"]
gridScalar (whole-grid) valuesgrid.at_grid["field_name"]

Standard Variable Names and Units

VariableUnitsLocationDescription
topographic__elevationmnodeLand surface elevation
drainage_aream^2nodeContributing upstream area
surface_water__dischargem^3/snodeVolumetric water discharge
water__unit_flux_inm/snodeRainfall rate (depth/time)
topographic__steepest_slope-nodeMax downhill gradient
flow__receiver_node-nodeDownstream neighbor ID
flow__upstream_node_order-nodeTopological sort order
flow__link_to_receiver_node-nodeLink ID to receiver
soil__depthmnodeRegolith/soil thickness
soil_production__ratem/yrnodeBedrock-to-soil conversion rate
bedrock__elevationmnodeBedrock surface elevation
hillslope_sediment__unit_volume_fluxm^2/slinkDiffusive sediment flux
topographic__gradient-linkSurface slope on links
sediment__influxm^3/snodeIncoming sediment rate
sediment__outfluxm^3/snodeOutgoing sediment rate
surface_water__depthmnodeWater depth on surface
rainfall__daily_depthmmcellDaily precipitation
vegetation__cover_fraction-cellFractional veg cover

Unit Trap Table

These are the most dangerous unit mismatches in Landlab workflows:

#VariableExpectedCommon MistakeEffectTriplet
1water__unit_flux_inm/smm/hr or m/yrDischarge 1000x–31.5M× wrongdt_001
2linear_diffusivitym^2/yr (if dt in yr)m^2/sHillslopes flatten instantlydt_002
3K_sp (erodibility)depends on m,nwrong exponent comboErosion rate orders of magnitude offdt_003
4xy_spacingmkm or degreesArea, slope, flux all wrongdt_004
5dt (timestep)must match K unitsyr vs s mismatchAll rates wrongdt_005
6soil__depthmcmWeathering rate, SPACE output wrongdt_006
7topographic__elevationmft or cmSlope calc wrong → erosion wrongdt_007
8rainfall__daily_depthmmmSoil moisture 1000× offdt_008
9roughness (Manning n)s/m^(1/3)1/n (Chezy)Velocity inverteddt_009
10DEM nodata value-99990 or NaNFlow routes into nodata cellsdt_010

Key Components Reference

Flow Routing

ComponentMethodKey Params
FlowAccumulatorWraps director + accumulationflow_director, runoff_rate
FlowDirectorD8Steepest single-direction (D8)—
FlowDirectorDINFD-infinity (two receivers)—
FlowDirectorMFDMultiple flow directionspartition_method
DepressionFinderAndRouterFill/route pitsrouting
PriorityFloodFlowRouterPriority-flood (Barnes 2014)flow_metric, suppress_out

Erosion & Sediment Transport

ComponentEquationKey Params
StreamPowerEroderE = K A^m S^nK_sp, m_sp, n_sp, threshold_sp
ErosionDepositionDavy & Lague (2009) ξ-qK, v_s, m_sp, n_sp
SpaceBedrock + alluvium layersK_sed, K_br, v_s, H_star
LinearDiffuserq = -D ∇zlinear_diffusivity
DepthDependentDiffuserNonlinear depth-dep.linear_diffusivity, soil_transport_decay_depth
TaylorNonlinearHillslopeFluxTaylor expansion nonlinearcritical_slope, nterms

Weathering & Soil Production

ComponentEquationKey Params
ExponentialWeathererP = P0 exp(-H/H*)soil_production_maximum_rate, soil_production_decay_depth
DepthDependentTaylorDiffuserCoupled soil transportsoil_transport_velocity, soil_transport_decay_depth

Hydrology

ComponentMethodKey Params
KinwaveOverlandFlowModelKinematic wave + Manningprecip_rate, roughness
OverlandFlowde Almeida et al. (2012)h_init, mannings_n
SoilMoistureLaio et al. (2001) bucketsoil_porosity, soil_field_capacity
GroundwaterDupuitPercolatorDupuit approx.hydraulic_conductivity, porosity

Tectonics & Lithology

ComponentDescriptionKey Params
NormalFaultVertical displacement on faultfaulted_surface, fault_throw_rate_through_time
FlexureLithospheric flexure (Airy/elastic)eet, youngs
LithologyTrack rock layers through erosionlayer_ids, layer_thicknesses

I/O Formats

FormatReadWriteFunction
ESRI ASCII (.asc)YesYeslandlab.io.esri_ascii.load() / dump()
NetCDF (.nc)YesYesto_netcdf() / from_netcdf()
Shapefile (.shp)YesNoread_shapefile()
VTK Legacy (.vtk)NoYeswrite_legacy_vtk()
OBJ (.obj)NoYeswrite_obj()
Native LandlabYesYessave() / load()

Critical Domain Knowledge

  1. Landlab is unit-agnostic — it does NOT enforce units internally.

The user MUST ensure all inputs share a consistent unit system. If elevation is in meters, spacing must be meters, K must be in m^(1-2m)/yr, diffusivity in m^2/yr, and dt in years. Mixing m/s with m/yr is the #1 source of silent failures. → dt_001, dt_005

  1. K_sp units depend on m_sp and n_sp exponents — for the stream power

law E = K A^m S^n, when m=0.5 and n=1.0, K has units m^(1-2m)/time = m^0/yr = 1/yr. Changing exponents changes K units. Copying K values from papers with different exponents produces wrong erosion rates. → dt_003

  1. Boundary conditions must be set before component instantiation —

FlowAccumulator needs at least one open boundary node for drainage. If all boundaries are closed, flow has nowhere to go and drainage_area will be zero everywhere. → dt_011

  1. Depression routing is not automatic — D8 flow routing stops at pits.

Without DepressionFinderAndRouter or PriorityFloodFlowRouter, interior pits accumulate flow and block downstream erosion. → dt_012

  1. CFL stability for explicit diffusion — LinearDiffuser uses an explicit

scheme with internal sub-stepping (alpha=0.15 × dx²/D). If the user wraps it in their own sub-stepping, they may defeat the internal CFL guard. → dt_013

  1. Grid spacing affects slope calculation — Slope = Δz/Δx. If xy_spacing

is in degrees instead of meters, slopes will be orders of magnitude wrong, producing unrealistic erosion. → dt_004

  1. FlowAccumulator must run before erosion components — StreamPowerEroder,

ErosionDeposition, and Space all require drainage_area, flow__receiver_node, and flow__upstream_node_order to be populated. These are outputs of FlowAccumulator. Running erosion first yields zero drainage area. → dt_014


Synthetic test setups (how-to)

SPACE Qs-Q test (quasi-1D channel)

  • Grid: 3×51 quasi-1D channel, dx=500 m, slope=5×10⁻⁴, soil_depth=2 m
  • Component: SpaceLargeScaleEroder (K_sed=2.5e-5, m_sp=0.5, n_sp=1.0, v_s=5 m/yr, H*=1 m)
  • Method: warmup 800 steps × 1 yr; then 7 runoff-rate probes (single SPACE step, no uplift)
  • Fit: log(Qs) vs log(Q) — sediment mass flux vs water flux

SPACE steady-state concavity test

  • Grid: 50×50 RasterModelGrid, dx=200 m, open south boundary
  • Duration: 4000 × 500 yr = 2 Myr; uplift U=1e-3 m/yr

Whipple & Tucker (1999) steady-state test

  • Grid: 50×50 RasterModelGrid, dx=100 m
  • Components: FlowAccumulator(D8) + StreamPowerEroder(K=1e-5, m=0.5, n=1.0) + LinearDiffuser(D=0.01 m²/yr)
  • Uplift: 1e-3 m/yr uniform
  • Duration: 2 Myr, dt=500 yr (4000 steps)
  • Boundary: South edge open, other three closed

Lessons from past runs (rules)

  1. Fit Qs vs Q directly, never SSC = Qs/Q vs Q: SSC vs Q always gives a negative exponent,

whatever the model does (dt_020).

  1. If the SPACE Qs-Q exponent b is outside [0.35, 1.20], check whether SPACE runs in the

detachment-limited or transport-limited regime (H, H*, v_s) (dt_021).

  1. For slope-area on a real DEM, use the 2D spatial gradient |∇z| with log-spaced area bins,

not the D8 receiver slope (topographic__steepest_slope) (dt_018).

  1. For slope-area on a DEM clip, use open_all boundaries; a single-outlet boundary

(closed_all_but_outlet) pushes θ toward 0 (dt_019).

  1. Do not use SPACE for annual sediment yield on a real DEM; use detachment-limited stream

power, set K_sp analytically from the target SY, and use closed_all_but_outlet for watershed-scale SY (dt_022).

  1. P export from TP = SY × 10 × P_soil_ppm × ER × 1e-6 is a gross potential; the amount at the

watershed outlet is lower because of P retention inside the basin.


Tools Reference

ToolStagePathLinesPurpose
convert_dem_to_grid.pys2tools/convert_dem_to_grid.py~250Load DEM → RasterModelGrid with fields
convert_soil_params.pys3tools/convert_soil_params.py~220HWSD soil → grid fields (depth, K, porosity)
run_landlab.pys5tools/run_landlab.py~280Execute Landlab simulation from YAML config
parse_landlab_output.pys6tools/parse_landlab_output.py~250Extract grid fields → CSV/NetCDF + metrics
dissect_atchafalaya_ssc_q_surrogate.pyvalidationtools/dissect_atchafalaya_ssc_q_surrogate.py~280SPACE Qs-Q rating and steady-state concavity check
dissect_loess_plateau_slope_area.pyvalidationtools/dissect_loess_plateau_slope_area.py~430Real-DEM slope-area (spatial gradient, log-binned)
dissect_loess_plateau_sediment_yield.pyvalidationtools/dissect_loess_plateau_sediment_yield.py~280DL stream power SY + particulate-P export

Calibration Parameters (Priority Order)

ParameterComponentRangeControlsSensitivity
K_spStreamPowerEroder1e-7–1e-3Channel erosion rateVery High
linear_diffusivityLinearDiffuser0.001–1.0 m²/yrHillslope curvatureHigh
m_spStreamPowerEroder0.3–0.7Area-discharge scalingHigh
n_spStreamPowerEroder0.7–2.0Slope sensitivityHigh
uplift_rate(user loop)1e-5–1e-2 m/yrRelief, channel gradientVery High
v_sSpace/ErosionDeposition0.01–10 m/sTransport vs detachmentHigh
K_sed / K_brSpace1e-7–1e-3Alluvium vs bedrock erosionHigh
H_starSpace0.1–2.0 mAlluvial cover effectMedium
soil_production_maximum_rateExponentialWeatherer1e-5–1e-3 m/yrSoil thicknessMedium
soil_production_decay_depthExponentialWeatherer0.2–2.0 mWeathering decayMedium

Data Requirements

DataSourceFormatNotes
DEMSRTM/ASTER/LiDARGeoTIFF or ESRI ASCIIMust be projected (meters)
Soil depthHWSD/SoilGridsRaster/CSVConvert cm → m
RainfallCMFD/MSWX/ERA5NetCDFConvert mm/hr → m/s for water__unit_flux_in
Uplift rateLiterature/GPSScalar or fieldMust match dt units
Erodibility (K)Literature/calibrationScalar or fieldUnits depend on m, n
Diffusivity (D)Literature/calibrationScalarm²/yr typical

Quick Start

bash
# Install
pip install landlab
# Run input converter
python tools/convert_dem_to_grid.py --dem input.asc --output grid.nc --spacing 100
# Run soil parameter converter
python tools/convert_soil_params.py --hwsd soil.csv --grid grid.nc --output params.json
# Run simulation
python tools/run_landlab.py --config config.yaml --output results/
# Parse output
python tools/parse_landlab_output.py --input results/ --output results/summary.csv --metrics slope_area

Diagnostic Triplets Summary

IDSeverityDomainShort Description
dt_001silentunit_conversionRainfall in mm/hr instead of m/s
dt_002silentunit_conversionDiffusivity time-unit mismatch
dt_003silentunit_conversionK_sp units wrong for given m,n
dt_004silentunit_conversionGrid spacing in degrees not meters
dt_005silentunit_conversionTimestep unit mismatch with parameters
dt_006silentunit_conversionSoil depth in cm instead of m
dt_007silentunit_conversionElevation in feet instead of meters
dt_008silentunit_conversionRainfall mm vs m for soil moisture
dt_009silentparameter_formatManning n vs Chezy C confusion
dt_010degradedinput_formatDEM nodata not handled
dt_011fatalboundary_conditionAll boundaries closed
dt_012degradedmissing_componentNo depression routing
dt_013degradednumerical_stabilityCFL violation in diffusion
dt_014fatalcomponent_orderErosion before flow routing
dt_015silentfield_locationField at wrong grid element
dt_016silentssc_q_rating_curveWrong runoff_rate breaks SPACE SSC-Q correlation
dt_017silentssc_q_rating_curvem_sp/n_sp wrong → concavity outside [0.40, 0.55]
dt_018silentslope_area_analysisD8 receiver slope polluted by depression-filling → use spatial gradient
dt_019silentslope_area_analysisSingle-outlet boundary depresses θ toward 0 → use open_all for DEM clips
dt_020silentssc_q_rating_curveFitting SSC vs Q gives negative exponent — always fit Qs vs Q
dt_021silentssc_q_rating_curveSPACE b outside [0.35,1.20] — check DL vs TL regime (H, H*, v_s)
dt_022silentmodel_scope_mismatchSPACE near-zero SY on real DEMs — use DL stream power for annual SY

Reference: diagnostics/triplets.yaml


File Structure

ki/
├── SKILL.md # This file
├── tools/
│ ├── convert_dem_to_grid.py # DEM → Landlab grid
│ ├── convert_soil_params.py # Soil data → grid fields
│ ├── run_landlab.py # Execution wrapper
│ ├── parse_landlab_output.py # Output → CSV + metrics
│ ├── dissect_atchafalaya_ssc_q_surrogate.py # SPACE Qs-Q + concavity validation
│ ├── dissect_loess_plateau_slope_area.py # Real-DEM slope-area validation
│ └── dissect_loess_plateau_sediment_yield.py # DL stream power SY + P export validation
├── docs/
│ ├── s1_grid_setup.md # Grid creation skill
│ ├── s2_input_preparation.md # DEM/forcing loading
│ ├── s3_soil_parameters.md # Soil/weathering params
│ ├── s4_component_assembly.md # Coupling components
│ └── s5_execution_output.md # Running and analyzing
└── diagnostics/
└── triplets.yaml # diagnostic triplets (count: KI map)
All versions