KINEROS2 · diff

git:20260826.6c18863 to git:20261006.e6099ae

295 added, 354 removed. Audit C to C.

> **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.
- >
+ > or hand-coded approximation in place of the real model. Doing so produces
+ > scientifically invalid results and defeats the purpose of the KI.
>
> 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:
+ > **DEBUGGING PROTOCOL** — When something goes wrong (model crashes, wrong output,
+ > unexpected values), follow this order. Do NOT skip steps or write debug scripts:
> 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
+ > 2. **Read official docs** — Check the model's own documentation (PDF manual, README,
+ > official examples) for expected input formats, variable names, and units
+ > 3. **Find working examples** — Look in `outputs/` for previous successful runs of
+ > this model, or check if the model ships with test/example data
+ > 4. **Fix the tool** — Now that you know what "correct" looks like, make targeted fixes
>
- > Do NOT write custom debug scripts. The answers are in the docs and examples.
+ > Resist the urge to write diagnostic/debug Python scripts. The answers are almost
+ > always in the official docs and working examples, not in reverse-engineering the binary.
<!-- KI-MAP:BEGIN (projected by generate_skill_map.py — edit the KI, not this table) -->
## KI map — what to read, and when
| when you need | read | why |
|---|---|---|
| FIRST, always | `preflight_check.py` | run 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 stages | `tools/` (4 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 stage | `docs/s*_*.md` (7 stage docs) | per-stage procedure, verification and traps — the how-to that SKILL.md's overview compresses. |
- | on ANY error, before debugging | `diagnostics/triplets.yaml` (26 entries) | symptom → diagnosis → remedy for this model's known failure modes. Check here FIRST; the answer usually exists. Never renumber or rewrite entries. |
+ | to run the pipeline stages | `tools/` (15 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 stage | `docs/s*_*.md` (9 stage docs) | per-stage procedure, verification and traps — the how-to that SKILL.md's overview compresses. |
+ | on ANY error, before debugging | `diagnostics/triplets.yaml` (53 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 IS | `dag.yaml` | the 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 outputs | `docs/format_spec.yaml` | exact 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 skill | `docs/validation_convention.yaml` | how 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 thresholds | `docs/gathered_papers.json` (14 papers) + `docs/papers_index.md` | the 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 claims and thresholds | `docs/gathered_papers.json` (16 papers) + `docs/papers_index.md` | the 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 summary | `knowledge_infrastructure.yaml` | the 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>`.*
+ *Projected 2026-10-06 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_forcing_to_kineros2.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_forcing_to_kineros2.py --help` |
- | `tools/convert_soil_to_kineros2.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_soil_to_kineros2.py --help` |
- | `tools/parse_output_kineros2.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/parse_output_kineros2.py --help` |
- | `tools/run_kineros2.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/run_kineros2.py --help` |
+ | `tools/add_kineros2_element.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/add_kineros2_element.py --help` |
+ | `tools/build_kineros2_rainfall.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/build_kineros2_rainfall.py --help` |
+ | `tools/calibrate_kineros2_multipliers.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/calibrate_kineros2_multipliers.py --help` |
+ | `tools/configure_kineros2_sediment.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/configure_kineros2_sediment.py --help` |
+ | `tools/convert_forcing_to_kineros2.py` (**SURROGATE, not KINEROS2**) | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_forcing_to_kineros2.py --help` |
+ | `tools/convert_soil_to_kineros2.py` (**SURROGATE, not KINEROS2**) | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_soil_to_kineros2.py --help` |
+ | `tools/edit_kineros2_par.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/edit_kineros2_par.py --help` |
+ | `tools/fetch_wgew_dap.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/fetch_wgew_dap.py --help` |
+ | `tools/kineros2_soil_params.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/kineros2_soil_params.py --help` |
+ | `tools/parse_kineros2_output.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/parse_kineros2_output.py --help` |
+ | `tools/parse_output_kineros2.py` (**SURROGATE, not KINEROS2**) | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/parse_output_kineros2.py --help` |
+ | `tools/run_kineros2.py` (**SURROGATE, not KINEROS2**) | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/run_kineros2.py --help` |
+ | `tools/run_kineros2_engine.py` (**default run route: the REAL engine**) | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/run_kineros2_engine.py --help` |
+ | `tools/score_kineros2_event.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/score_kineros2_event.py --help` |
- *4 public tools; `_`-prefixed helpers and packaging files excluded.*
+ *14 public tools; `_`-prefixed helpers and packaging files excluded.*
<!-- KI-TOOL-INDEX:END -->
- # KINEROS2 Knowledge Infrastructure
-
- **Package**: hydrocraft-kineros2 v1.0.0
- **Model**: KINEROS2 (KINematic EROsion Simulation, version 2)
- **Domain**: Event-based watershed hydrology and erosion
- **Language**: Fortran (with Python analytic reimplementation)
- **License**: Public domain (USDA-ARS)
- **Created**: 2026-03-30
- **Validation**: Bengbu station (51080), Huai River Basin, China (1980--1990)
-
- | Metric | Value |
- |--------|-------|
- | Tools | 4 |
- | Pipeline stages | 7 |
- | Diagnostic triplets | 12 |
- | Validation basin | Huai River at Bengbu |
-
---
- ## Data Preparation
+ # KINEROS2 -- Knowledge Infrastructure Skill Document
- ### Forcing data
+ > **Version**: KINEROS2 K2shell 25-Oct-2019 (ARS-SWRC/KINEROS2 commit f0bbae2), gfortran build
+ > **Domain**: hydrology -- event rainfall-runoff and erosion on small watersheds
+ > **Last updated**: 2026-10-06 (rebuilt around the real engine)
+ > **Validation status**: production_validated on the official ARS samples (reproduced exactly);
+ > one real-observation comparison (Walnut Gulch flume 11, 4 Aug 1980, in-sample)
- **Data Sources**: Use `from ki_tools_common.load_forcing import load_daily_forcing` for CMFD/MSWX/NASA POWER.
+ > **SURROGATE WARNING.** `tools/run_kineros2.py` (+ `convert_forcing_to_kineros2.py`,
+ > `convert_soil_to_kineros2.py`, `parse_output_kineros2.py`, docs in `docs/surrogate/`) is a
+ > **Python SURROGATE** -- a lumped, daily, Green-Ampt + two-reservoir stand-in written before the real
+ > engine existed on this server. It is **not KINEROS2**. Never report its output (e.g. the Huaihe at
+ > Bengbu, 121,330 km2, NSE 0.851 still recorded in the models DB) as KINEROS2 results. The real model
+ > is run by `tools/run_kineros2_engine.py`.
- **Data Validation Reference**: See `data_ki/CMFD/SKILL.md` for CMFD unit documentation and known traps.
- See `data_ki/HWSD/SKILL.md` for soil property documentation.
- See `data_ki/ObservedQ/SKILL.md` for observed discharge data.
+ ---
+ ## 1. Model Identity
- ## 1. Overview
+ | Property | Value |
+ |----------|-------|
+ | Full name | KINEROS2 -- KINematic runoff and EROSion model, version 2 |
+ | Version | K2shell 25-Oct-2019 (ARS-SWRC/KINEROS2 HEAD f0bbae2a19238fe98d5b42fbc9e55a993bfbba41) |
+ | Language | Fortran 77/90 (K2shell.f90 driver + .for modules) |
+ | License | MIT (repository LICENSE), USDA-ARS public software |
+ | Repository | https://github.com/ARS-SWRC/KINEROS2 ; samples https://www.tucson.ars.ag.gov/kineros/ |
+ | Citation | Goodrich et al. 2012, K2/AGWA: model use, calibration, and validation, Trans. ASABE 55(4):1561-1574 |
+ | Primary domain | event runoff, infiltration, erosion/sediment, small agricultural/rangeland/urban watersheds |
+ | Spatial mode | Distributed cascade of 1-D elements (planes, channels, ponds, pipes, urban, injections) |
+ | Binary | `KISSPATH_HOME/engine_builds_20261006/KINEROS2/build_github/k2` (sha256 d3efaef0...a3348d) |
- KINEROS2 is a physically-based, distributed, event-oriented watershed model
- developed by USDA-ARS. It simulates rainfall interception, infiltration,
- surface runoff generation, and erosion/sediment transport over small
- agricultural and urban watersheds using cascading planes and channel elements.
+ ---
- Core physics:
+ ## 2. What This Model Does
- - **Green-Ampt infiltration**: Partitions rainfall into surface excess and
- soil absorption using a wetting-front approximation. Key equation:
- `f(t) = Ks * (1 + psi_f * delta_theta / F)` where `Ks` is saturated
- hydraulic conductivity (mm/h), `psi_f` is wetting front suction (mm),
- `delta_theta` is moisture deficit (unitless), and `F` is cumulative
- infiltration (mm).
+ KINEROS2 simulates ONE storm at minute steps on a small watershed (hectares to a few km2) described as
+ a cascade of overland-flow planes and trapezoidal channels (plus optional ponds, pipes, urban elements
+ and injected inflows). Rain from one or more recording gages is interpolated to each element,
+ intercepted, infiltrated with the Smith-Parlange/Green-Ampt family (one or two soil layers,
+ redistribution between bursts), and the excess is routed by the 1-D kinematic wave; channels lose
+ water into their beds. Optionally it erodes, deposits and transports up to five particle classes.
+ Outputs are the outlet hydrograph, event volumes, peaks and sediment yield. There is no
+ evapotranspiration, no continuous soil-moisture accounting and no spin-up: antecedent wetness is an
+ input (SAT).
- - **Kinematic wave routing**: Routes surface runoff using the kinematic wave
- approximation of the Saint-Venant equations. The momentum equation reduces
- to `S_f = S_0` (friction slope = bed slope), yielding the nonlinear
- storage-discharge relationship `Q = alpha * A^m` where `alpha` depends on
- Manning's roughness and slope, and `m` is the kinematic wave exponent
- (typically 5/3 for Manning's equation).
+ ---
- - **Soil moisture accounting**: Tracks soil storage with field capacity, wilting
- point, and gravity drainage. Actual ET extracted proportional to available
- water above wilting point.
+ ## 3. Input Requirements
- - **Dual reservoir routing**: Approximates kinematic wave behavior via fast
- (surface) and slow (baseflow) linear/nonlinear reservoirs for lumped daily
- applications.
+ **Exact shapes live in `docs/format_spec.yaml`** (projected from dag + triplets -- regenerate it,
+ never hand-edit). The full preparation plan, per tag, is `docs/input_preparation.md`.
- Key characteristics:
- - Originally designed for event-based simulation on small watersheds (<100 km2)
- - Extended here as a lumped daily model for continuous simulation
- - 8 calibration parameters (Ks, psi_f, Smax, fc, k_fast, k_slow, f_slow, alpha)
- - Driven by daily precipitation (mm/d) and temperature (deg C)
- - PET computed internally via Hamon method
- - Output: daily discharge (m3/s)
+ ### 3.1 Meteorological Forcing
- **Important caveat**: KINEROS2 is designed for event-based, small-watershed
- simulation. Application to large basins (>1000 km2) for continuous daily
- simulation is a significant extrapolation of its intended domain.
+ | Variable | Unit model expects | Source dataset | Source unit | Conversion |
+ |----------|-------------------|----------------|------------|------------|
+ | Rainfall (cumulative depth vs minutes, per gage) | mm if UNITS=METRIC, in if UNITS=ENGLISH | USDA-ARS WGEW DAP recording gages (`tools/fetch_wgew_dap.py precip`) | in or mm (chosen at download) | none -- download in the parameter file's unit; times = local start - clock origin + elapsed min |
+ | Rainfall (last resort, ungauged) | as above | `load_hourly_forcing('nasa_power'|'cmfd'|'mswx')` | mm per step | cumulative sum; x 1/25.4 for ENGLISH; peaks smeared (dt_kineros2_036) |
- ---
+ No temperature, radiation, wind or humidity input exists (GLOBAL TEMP is only the water temperature
+ for sediment settling).
- ## 2. Installation
+ ### 3.2 Static Inputs
- ### Analytic reimplementation (Python)
+ | Input | Source | Tool that prepares it |
+ |-------|--------|----------------------|
+ | Element cascade (LENGTH, WIDTH, SLOPE, topology) | existing .par (ARS sample, AGWA export) -- copy-first | `tools/edit_kineros2_par.py` |
+ | Infiltration (KS, G, DIST, POR, ROCK) | HWSD + KINEROS2 manual Table 1 (Rawls 1982) | `tools/kineros2_soil_params.py` |
+ | Roughness, interception, CV, SAT | land cover tables / field data / antecedent rain | `tools/edit_kineros2_par.py set` |
+ | Sediment classes and erodibility | particle analysis / literature | `tools/configure_kineros2_sediment.py` |
+ | Ponds (rating table), injected inflows | design data / measured flows | `tools/add_kineros2_element.py` |
- The KINEROS2 source repository (GitHub) is currently unavailable (HTTP 404).
- This KI provides a Python analytic reimplementation of the core physics.
+ ### 3.3 Configuration Files
- ```bash
- # No compilation needed -- pure Python
- pip install numpy pandas xarray geopandas scipy matplotlib shapely
- ```
+ | File | Format | Notes |
+ |------|--------|-------|
+ | parameter file `.par` | tagged blocks (`BEGIN PLANE ... END`), `TAG = v1, v2` lists or column headers | upper-cased, columns 1-200 only, `+` is a separator, tags matched by prefix |
+ | rainfall file `.pre` | one tagged block per gage | depth in the parameter file's UNITS |
+ | multiplier file | 7 lines (Ks, n, CV, G, interception, cohesion, splash) [+6 channel/saturation lines] | values > 0 |
+ | `kin.fil` | one line per run: `par,pre,out,"title",tfin,dt,Y|N,Y|N,mult|N,Y` | written by the run tool; no spaces after commas |
- ### Original Fortran source (when available)
+ ---
+ ## 4. Build Instructions
+
```bash
- git clone https://github.com/USDA-ARS-SWRC/KINEROS2
- cd KINEROS2/src
- make
- # Produces kineros2 binary
+ # already built (2026-10-06); to rebuild from the official source:
+ git clone https://github.com/ARS-SWRC/KINEROS2 src # source, docs (src/doc/*.pdf), x64/k2_x64.exe
+ # patched copy: CRLF stripped; kinsed_wepp.for:155 reshape (/5,1/) -> (/5/) (gfortran rank check)
+ KISSPATH_HOME/engine_builds_20261006/KINEROS2/build.sh KISSPATH_HOME/engine_builds_20261006/KINEROS2/src_patched OUTDIR
+ # compiles k2mods.for, kinsed.f90 first, then the rest, K2shell.f90 last; links OUTDIR/k2
```
- ### Dependencies
-
- | Component | Required | Purpose |
- |----------------|----------|-------------------------------------------|
- | numpy | Yes | Numerical computation |
- | pandas | Yes | Time series handling |
- | xarray | Yes | NetCDF forcing data |
- | geopandas | Yes | Shapefile basin masking |
- | scipy | Yes | Calibration (differential_evolution) |
- | matplotlib | Optional | Validation plots |
- | shapely | Yes | Geometry operations for basin masking |
+ **Known build issues:**
+ - No makefile in the repository; module order matters (k2mods, kinsed first).
+ - Leave out fmt10_new.for, pond_dcg.for, sedbf.for, inject.for.bak (duplicates / fragments).
+ - gfortran flags: `-O2 -fno-automatic -ffixed-line-length-none -ffree-line-length-none -std=legacy -fallow-argument-mismatch`.
+ - Cross-check: the official ARS Windows `k2_x64.exe` under WINE (needs a pty: `script -qec "wine k2_x64.exe -b kin.fil"`) agrees to the 6th-7th digit (dt_kineros2_020).
---
- ## 3. Pipeline
-
- | # | Stage | Tool | Description |
- |---|------------------------|-----------------------------------|----------------------------------------------------------|
- | 1 | Forcing preparation | `convert_forcing_to_kineros2.py` | CMFD NetCDF to daily precip (mm/d) + temp (deg C) |
- | 2 | Soil parameter setup | `convert_soil_to_kineros2.py` | HWSD soil data to Green-Ampt parameters |
- | 3 | Model configuration | (manual) | Set basin area, routing params, calibration bounds |
- | 4 | PET computation | (internal to run_kineros2.py) | Hamon method from temperature + latitude |
- | 5 | Execution | `run_kineros2.py` | Run lumped Green-Ampt + kinematic wave model |
- | 6 | Output parsing | `parse_output_kineros2.py` | Extract discharge timeseries, compute validation metrics |
- | 7 | Calibration | `run_kineros2.py --mode calibrate`| Differential evolution against observed Q |
+ ## 5. Execution
- **Parallelism**: Stages 1--2 can run in parallel. Stage 5 depends on 1--2.
- Stage 6 depends on 5. Stage 7 is iterative on 5--6.
+ ```bash
+ python3 preflight_check.py # binary + EX1 smoke run
+ python3 tools/run_kineros2_engine.py --example wg11 --check --out-dir OUT/wg11
+ python3 tools/run_kineros2_engine.py --par case.par --rain storm.pre --tfin 360 --dt 3 --courant \
+ --mult ks=0.5,g=1.5 [--sediment] --out-dir OUT/case
+ ```
- ### Stage Skill Documents
+ The tool copies inputs into a fresh workspace, writes `kin.fil`, runs `k2 -b kin.fil`, judges success
+ from the output text (the engine's exit status is ALWAYS 0, dt_kineros2_027) and writes
+ `run_result.json`. Exit codes: 0 ok, 2 input invalid, 3 engine failure, 4 binary missing, 5 example
+ mismatch. Binary lookup: `--binary` > `$KINEROS2_BIN` > models DB `binary_path` > builder default.
- - [s1_forcing_preparation.md](docs/s1_forcing_preparation.md) -- convert CMFD/ERA5-style forcing to daily KINEROS2 JSON.
- - [s2_soil_parameter_setup.md](docs/s2_soil_parameter_setup.md) -- generate Green-Ampt and routing parameters.
- - [s3_model_configuration.md](docs/s3_model_configuration.md) -- assemble basin area, latitude, mode, and calibration windows.
- - [s4_pet_computation.md](docs/s4_pet_computation.md) -- internal Hamon PET stage in `tools/run_kineros2.py`.
- - [s5_execution.md](docs/s5_execution.md) -- run the lumped Green-Ampt plus routing model.
- - [s6_output_parsing.md](docs/s6_output_parsing.md) -- export discharge, compute metrics, and optionally plot validation.
- - [s7_calibration.md](docs/s7_calibration.md) -- differential-evolution calibration against observed discharge.
+ **Expected runtime**: < 0.1 s per storm for 2-17 elements (both ARS samples); 40 calibration trials on
+ WG11 take about 2 s.
---
- ## 4. Unit Conversion Table
-
- These unit conversions cause **silent failures** if wrong. KINEROS2 performs
- no internal unit conversion; all inputs must be in the expected units.
- Exact I/O shapes live in `docs/format_spec.yaml`; this table is the human
- checklist for the conversions that must be verified before a run is trusted.
-
- | Variable | Model expects | Common source unit | Conversion | Trap ID |
- |-----------------------|----------------|--------------------|--------------------------------------|---------|
- | Precipitation | **mm/d** | kg/m2/s (CMFD) | x 86400 | dt_001 |
- | Precipitation | **mm/d** | mm/3h (CMFD) | sum 8 values per day | dt_002 |
- | Precipitation | **mm/d** | m/d (some GCMs) | x 1000 | dt_003 |
- | Temperature | **deg C** | K (CMFD/ERA5) | - 273.15 | dt_004 |
- | Temperature | **deg C** | deg F | (F - 32) x 5/9 | dt_005 |
- | Ks (hyd. conductivity)| **mm/d** | mm/h (HWSD) | x 24 | dt_006 |
- | Ks (hyd. conductivity)| **mm/d** | cm/h (some tables) | x 240 | dt_007 |
- | psi_f (suction head) | **mm** | cm | x 10 | dt_008 |
- | Smax (soil storage) | **mm** | m | x 1000 | dt_009 |
- | Basin area | **km2** | ha | / 100 | dt_010 |
- | Observed Q | **m3/s** | mm/d | x area_km2 x 1e6 / 86400 / 1000 | dt_011 |
- | mm/d to m3/s | conversion | mm/d over basin | x area_km2 x 1e6 / 86400 x 1e-3 | dt_012 |
+ ## 6. Output Description
- **Rule**: If simulated discharge is 86400x too high or too low, precipitation
- units are almost certainly wrong (kg/m2/s vs mm/d). If 1000x off, check m vs mm.
+ Sourced from `dag.yaml` (the dag wins if the two ever disagree).
- ---
+ **Headline output** (the dag's `validation_rank: 1` variable):
- ## 5. Tools Reference
+ > `discharge` — Surface water discharge (stream / channel flow) at the watershed outlet element, as an event hydrograph at the user time step in minutes. (m3/s)
- | Tool | Stage | Script | Purpose |
- |-------------------------------|-------------|-------------------------------------|----------------------------------------------------|
- | `convert_forcing_to_kineros2` | s1_forcing | `tools/convert_forcing_to_kineros2.py` | CMFD/ERA5 NetCDF to daily P (mm/d) + T (deg C) |
- | `convert_soil_to_kineros2` | s2_params | `tools/convert_soil_to_kineros2.py` | HWSD/SoilGrids to Green-Ampt parameters |
- | `run_kineros2` | s5_execute | `tools/run_kineros2.py` | Execute lumped KINEROS2 analytic model |
- | `parse_output_kineros2` | s6_output | `tools/parse_output_kineros2.py` | Parse discharge CSV, compute NSE/KGE/PBIAS |
+ | Output variable (dag `var`) | rank | File | Unit | Medium |
+ |----------------|------|------|------|--------|
+ | discharge | 1 | `.out` hydrograph table (PRINT=2) / PRINT=3 CSV; `hydrograph_<type>_<id>.csv` | m3/s (printed cu m/s or cu ft/s) | surface water (channel) |
+ | runoff_volume | 2 | `.out` Event Volume Summary, Outflow | m3 (printed cu m or cu ft) | surface water |
+ | peak_discharge | 3 | `.out` "Peak flow = ... at ... min" of the outlet | m3/s | surface water (channel) |
+ | sediment_yield | 4 | `.out` "Sediment yield =" (+ by class) | t/ha (printed tons/ha or short tons/ac) | sediment |
+ | infiltration | - | Event Volume Summary (plane / channel infiltration) | mm | soil |
+ | sediment_discharge | - | hydrograph column / PRINT=3 per-class columns | kg/s (lb/s ENGLISH) | sediment in water |
- All tools follow the **validate -> process -> validate** pattern:
- 1. Parse CLI arguments with `argparse`
- 2. Validate all inputs (file existence, unit plausibility, range checks)
- 3. Process (convert, run, parse)
- 4. Validate outputs (physical plausibility, diagnostic warnings)
- 5. Return JSON: `{"status": "success/error", "output": {...}, "log": [...]}`
+ `run_kineros2_engine.py` puts all of these, converted to SI, into `run_result.json`
+ (`event_summary_si`, `outlet.peak_discharge_m3s`); `parse_kineros2_output.py` does the same for an
+ existing `.out`.
---
- ## 6. Output Description
-
- **Source: `dag.yaml`.** The dag is the model identity for observable outputs.
- If this section and `dag.yaml` disagree, `dag.yaml` wins.
-
- **Headline output**: the dag's rank-1 output is:
+ ## 7. Tool Inventory
- > `discharge` -- Daily simulated streamflow at the basin outlet. (`m3/s`)
+ | Tool | Purpose | Inputs | Outputs |
+ |------|---------|--------|---------|
+ | `tools/run_kineros2_engine.py` | run the REAL engine headless, honest status, parse | .par, .pre, tfin, dt, flags, multipliers | .out, run_result.json, hydrograph CSVs |
+ | `tools/parse_kineros2_output.py` | parse an existing .out (+ PRINT=3 CSV) | .out | JSON + CSV, SI values |
+ | `tools/edit_kineros2_par.py` | list / validate / get / set tags with the engine's lookup rules (copy-first) | .par [.pre] | new .par, validation report |
+ | `tools/kineros2_soil_params.py` | KS, G, DIST, POR, ROCK from HWSD or texture | lat/lon or texture | JSON, filled .par copy |
+ | `tools/build_kineros2_rainfall.py` | write a .pre from WGEW DAP gages, CSV or gridded hourly rain | breakpoints / forcing | .pre |
+ | `tools/fetch_wgew_dap.py` | download WGEW flume runoff and rain-gage data (USDA-ARS DAP) | ids, dates, units | DAP text with provenance |
+ | `tools/configure_kineros2_sediment.py` | check / set sediment classes and erosion tags | .par | sediment-ready .par |
+ | `tools/add_kineros2_element.py` | insert a POND or an INJECT element and re-wire | .par, rating / hydrograph CSV | new .par (+ inject data file) |
+ | `tools/score_kineros2_event.py` | event metrics vs an observed hydrograph, figure | run_result.json, obs file, clock offset | score.json, PNG |
+ | `tools/calibrate_kineros2_multipliers.py` | grid / Nelder-Mead on multipliers, real engine per trial | case + obs | trials.csv, best.json, best/ |
+ | `tools/_k2lib.py` | shared private helpers (binary lookup, tag reader mirror, kin.fil, parser) | - | - |
+ | `tools/run_kineros2.py` | **SURROGATE** (Python lumped daily stand-in) -- not KINEROS2 | forcing JSON | surrogate JSON (stamped model_identity) |
+ | `tools/convert_forcing_to_kineros2.py` | **SURROGATE** helper (daily basin forcing) | NetCDF | JSON |
+ | `tools/convert_soil_to_kineros2.py` | **SURROGATE** helper (lumped parameters) | texture | JSON |
+ | `tools/parse_output_kineros2.py` | **SURROGATE** helper (daily series metrics) | surrogate JSON | CSV/metrics |
- | Output variable (dag `var`) | validation rank | Unit | Description |
- |-----------------------------|-----------------|------|-------------|
- | discharge | 1 | m3/s | Daily simulated streamflow at the basin outlet. |
- | infiltration | not rank-1 in supplied dag facts | no unit stated in supplied dag facts | Listed as an additional dag output. |
- | surface_excess | not rank-1 in supplied dag facts | no unit stated in supplied dag facts | Listed as an additional dag output. |
+ ### Shared Utilities (ki_tools_common)
- Downstream validation and observation binding should use `discharge` as the
- headline variable unless `dag.yaml` is changed and the projected KI artifacts
- are regenerated.
+ ```python
+ from ki_tools_common.soil_utils import lookup_hwsd # kineros2_soil_params.py (Ks, texture, gravel)
+ from ki_tools_common.load_forcing import load_hourly_forcing # build_kineros2_rainfall.py --from-gridded
+ from ki_tools_common.metrics import all_metrics # score_kineros2_event.py (NSE, KGE, PBIAS, RMSE, r)
+ from ki_tools_common.validation import validate_water_balance # run_kineros2_engine.py event balance (residual only)
+ ```
---
- ## 6b. Critical Domain Knowledge
-
- These non-obvious facts cause silent failures. Each links to a diagnostic triplet.
-
- 1. **dt_001 / dt_002**: CMFD precipitation is in kg/m2/s, which equals mm/s.
- Multiply by 86400 to get mm/d. Forgetting this makes precipitation ~0.03
- mm/d instead of ~2.7 mm/d, producing near-zero runoff.
-
- 2. **dt_004**: CMFD temperature is in Kelvin. Subtracting 273.15 is mandatory.
- Without this, Hamon PET receives ~280 deg C and produces absurdly high
- evapotranspiration estimates.
-
- 3. **dt_006 / dt_007**: Saturated hydraulic conductivity (Ks) in HWSD and
- many soil databases is given in mm/h or cm/h for hourly models. For daily
- KINEROS2, convert to mm/d (x24 or x240). Using hourly Ks in a daily model
- makes infiltration capacity ~24x too low.
+ ## 8. Unit Conversion Table
- 4. **dt_008**: Wetting front suction (psi_f) in some references (e.g., Rawls
- et al. 1983) is given in cm. The model expects mm. Using cm values makes
- infiltration capacity too low by 10x.
+ > KINEROS2 converts nothing between unit systems: GLOBAL `UNITS` fixes every number in the parameter
+ > AND rainfall files. Rows below were verified on the engine output and source (`conv`, `wconv`).
- 5. **Green-Ampt near-saturation behavior**: When soil moisture approaches
- saturation (theta_def < 0.01), infiltration capacity collapses to Ks.
- This is physically correct but numerically sensitive -- a small Ks with
- large psi_f causes abrupt runoff transitions.
+ | Variable | Source unit (verified) | Model unit | Factor | Type |
+ |----------|----------------------|------------|--------|------|
+ | Rain depth (WGEW DAP) | in or mm (export header) | in (ENGLISH) / mm (METRIC) | 1 (download in the right unit) | none |
+ | Gridded hourly rain (loader) | mm per step | mm or in cumulative | cumsum; /25.4 for ENGLISH | multiplicative |
+ | KS (Rawls / HWSD ksat_cm_hr) | cm/hr | mm/hr / in/hr | x10 / x10/25.4, then x(1-ROCK) | multiplicative |
+ | G (manual Table 1) | cm | mm / in | x10 / x10/25.4 | multiplicative |
+ | ROCK (HWSD gravel) | volume % | fraction | /100 | multiplicative |
+ | Discharge printed | cu ft/s (ENGLISH) | m3/s | x0.028316847 | multiplicative |
+ | Volume printed | cu ft | m3 | x0.028316847 | multiplicative |
+ | Depth printed | in | mm | x25.4 | multiplicative |
+ | Area printed | ac | ha | x0.404686 | multiplicative |
+ | Sediment yield printed | short tons/ac | t/ha | x2.2417 | multiplicative |
+ | Sediment discharge printed | lb/s | kg/s | x0.453592 | multiplicative |
+ | WGEW flume runoff (mm, in) | per NOMINAL flume area | -- | do not compare depths; use cfs/ft3 | trap (dt_kineros2_033) |
- 6. **Event-based vs continuous**: KINEROS2 was designed for event-based
- simulation. For continuous daily use, soil moisture must be tracked
- between events. The lumped reimplementation adds soil moisture accounting
- (ET extraction, gravity drainage) not in the original event model.
+ ## 8c. Sign Conventions and Output Units
- 7. **Basin scale limitation**: KINEROS2 is designed for small watersheds
- (<100 km2). Application to large basins (e.g., Huai River at 121,330 km2)
- requires lumped conceptualization that loses the distributed physics.
+ | Variable | Convention in this model | Common alternative | Impact if wrong |
+ |----------|------------------------|-------------------|-----------------|
+ | Evapotranspiration | not simulated | - | none |
+ | Infiltration | positive = loss from the surface (volume, depth over total watershed area) | per element area | depth mis-scaled |
+ | Runoff / discharge | absolute flow at an element outlet (m3/s or cu ft/s); rates mm/hr over the CONTRIBUTING area | depth over the gauge's nominal area | volume bias when areas differ |
+ | Time | minutes after the rain-file clock origin | local clock time | shifted hydrograph (dt_kineros2_049) |
- 8. **Manning's alpha exponent**: The kinematic wave exponent in Manning's
- equation is 5/3 = 1.667. In the lumped approximation, this is calibrated
- as the `alpha` parameter (range 1.0--2.0). Values outside this range
- indicate overfitting.
+ **Output unit verification checklist:** `run_result.json` `units` (metric|english) comes from the
+ printed labels ('cu m' vs 'cu ft'); the SI block is computed from it; peak lines include both the
+ discharge and the rate per contributing area.
---
- ## 7. KINEROS2 Parameters (lumped daily model)
-
- | Parameter | Symbol | Unit | Range | Sensitivity | Description |
- |-----------|---------|--------|---------------|-------------|------------------------------------------|
- | Sat. hyd. cond. | Ks | mm/d | [1, 80] | Very High | Green-Ampt saturated hydraulic conductivity |
- | Wetting suction | psi_f | mm | [10, 500] | High | Green-Ampt wetting front suction head |
- | Max soil storage| Smax | mm | [100, 800] | High | Maximum soil moisture capacity |
- | Field capacity | fc | -- | [0.2, 0.8] | Medium | Field capacity as fraction of Smax |
- | Fast recession | k_fast| 1/d | [0.01, 0.5] | High | Surface runoff reservoir recession rate |
- | Slow recession | k_slow| 1/d | [0.001, 0.05] | Medium | Baseflow reservoir recession rate |
- | Slow fraction | f_slow| -- | [0.1, 0.7] | Medium | Fraction of runoff to slow reservoir |
- | Routing exponent| alpha | -- | [1.0, 2.0] | Low | Nonlinear fast reservoir exponent |
+ ## 9. Diagnostic Triplets (Top 5)
- ---
+ | # | Error | Diagnosis | Remedy |
+ |---|-------|-----------|--------|
+ | 1 | `dt_kineros2_027` run "succeeds" (exit 0) with no event summary | every engine error path ends in `stop`, status 0 | judge from text; use run_kineros2_engine.py (exit 3) |
+ | 2 | `dt_kineros2_029` no hydrograph although `PR = 2` | engine asks for `PRI`; `PR`/`Plot` are not read | `--set <outlet>:PRINT=2` |
+ | 3 | `dt_kineros2_030` element SA edits change nothing | gage SAT overrides element SA | keep SAT in one place |
+ | 4 | `dt_kineros2_032` runoff ~0 or huge | rain file read in the parameter file's UNITS | build the .pre with matching `--units` |
+ | 5 | `dt_kineros2_033` volume/depth error vs a flume | gauge depth uses nominal area (WG11 1551 vs 2035 ac) | compare m3/s and m3 |
- ## 8. Green-Ampt Infiltration Physics
+ Also frequent: `dt_kineros2_031` ('+' splits 1.6e+06), `dt_kineros2_044` (element order),
+ `dt_kineros2_046` (surrogate output mistaken for KINEROS2). Original ids 013/018/020/021/024/026 were
+ corrected on 2026-10-06; ids tagged `applies_to: python_surrogate` concern the stand-in only.
- The Green-Ampt equation for infiltration rate:
+ ---
- ```
- f(t) = Ks * (1 + psi_f * delta_theta / F(t))
- ```
+ ## 10. Coupling Interfaces
- Where:
- - `f(t)` = infiltration rate at time t (mm/d)
- - `Ks` = saturated hydraulic conductivity (mm/d)
- - `psi_f` = wetting front suction head (mm)
- - `delta_theta` = soil moisture deficit = porosity - theta_initial (unitless)
- - `F(t)` = cumulative infiltration at time t (mm)
+ | Upstream model | Variable exchanged | Unit | Temporal resolution |
+ |---------------|-------------------|------|-------------------|
+ | Recording rain gages / radar / nowcast | cumulative rain depth per gage | mm or in | breakpoints (minutes) |
+ | Any hydrologic/hydraulic model or gauge | injected inflow (+ sediment concentration) via INJECT | m3/s or ft3/s | minutes |
- For daily time steps, this is simplified to:
- ```
- if theta_deficit > 0.01:
- f_cap = Ks * (1 + psi_f * theta_deficit / max(S, 1))
- else:
- f_cap = Ks # near saturation
- infiltration = min(precipitation, f_cap)
- surface_excess = max(0, precipitation - f_cap)
- ```
+ | Downstream model | Variable exchanged | Unit | Temporal resolution |
+ |-----------------|-------------------|------|-------------------|
+ | Hydraulic models (e.g. HEC-RAS, as in Nguyen et al. 2015) | outlet discharge hydrograph | m3/s | user dt (minutes) |
+ | Reservoir / pond / sediment budgets | event runoff volume, sediment yield by class | m3, t/ha | per event |
- Typical Green-Ampt parameter values by USDA soil texture class:
+ ---
- | Texture | Ks (mm/h) | Ks (mm/d) | psi_f (mm) | Porosity |
- |-------------|-----------|-----------|------------|----------|
- | Sand | 117.8 | 2827 | 49.5 | 0.437 |
- | Loamy sand | 29.9 | 718 | 61.3 | 0.437 |
- | Sandy loam | 10.9 | 262 | 110.1 | 0.453 |
- | Loam | 3.4 | 82 | 88.9 | 0.463 |
- | Silt loam | 6.5 | 156 | 166.8 | 0.501 |
- | Clay loam | 1.0 | 24 | 208.8 | 0.464 |
- | Clay | 0.3 | 7.2 | 316.3 | 0.475 |
+ ## 11. Validated Results
- Source: Rawls et al. (1983), Green-Ampt infiltration parameters from soils data.
+ ### Test Basin: Walnut Gulch subwatershed 11 (USDA-ARS WGEW, Arizona), storm of 4 Aug 1980
- ---
+ | Property | Value |
+ |----------|-------|
+ | Location | flume 11, UTM 12N 595224 E 3512227 N (about 31.72 N, 110.06 W) |
+ | Area | 627.7 ha modelled contributing area (1551.03 ac); flume nominal 2035 ac |
+ | Period | one storm, 360 min from 12:35 local, 3-min output |
+ | Resolution | 17 elements (12 planes, 5 channels), 10 recording rain gages |
- ## 9. Validated Results
+ **Official samples reproduced (2026-10-06, `run_kineros2_engine.py --example ... --check`)**: EX1
+ rain 77.0 mm, plane infiltration 41.51009 mm, outflow 35.29868 mm (705.974 m3), sediment 5.172343
+ t/ha; WG11 rain 1.3642 in, outflow 0.292209 in (1,645,201 ft3), outlet peak 668.4023 cfs at 64.7 min
+ -- every value identical to the build log (tolerance rel 1e-4). The WG11 rain file rebuilt from the
+ raw ARS gage export is identical to the shipped one (10/10 gages).
- **Basin**: Huai River at Bengbu (Station 51080), China
- **Area**: 121,330 km2
- **Forcing**: CMFD V0200 0.25-deg daily
- **Tier**: analytic (Python reimplementation of KINEROS2 physics)
+ ### Performance Metrics — judged against the field's bar, not intuition
- ### Performance Metrics -- Convention Bars
+ > Bar for `discharge` (NSE, per `leta2023` and `cirilo2020`, Moriasi-style classes transferred from
+ > daily/monthly flow): satisfactory ≥ 0.50, good ≥ 0.65, very good ≥ 0.75; PBIAS within ±25 %
+ > satisfactory. Achieved on WG11 4 Aug 1980 with the ARS readme multipliers: NSE 0.812 → **very good
+ > by that band**, but PBIAS (on the 3-min grid) +26.6 % → **just outside satisfactory**; one event, in-sample.
- **Source: `docs/validation_convention.yaml`.** A metric value must be judged
- against the convention bars below, not against intuition or remembered
- thresholds. Null convention bands are written as "no cited threshold".
+ | Metric | Calibration | Validation | Full Period | Bar (convention, cited) |
+ |--------|-------------|------------|-------------|-------------------------|
+ | NSE | 0.855 (multipliers re-fit, in-sample) | - | 0.812 (ARS readme multipliers) | satisfactory/good/very good 0.50/0.65/0.75, `leta2023` |
+ | KGE | - | - | 0.720 | no cited threshold |
+ | PBIAS (%) | - | - | +26.6 (3-min grid) | ±25 satisfactory, `leta2023` |
+ | r | - | - | 0.910 | no cited threshold |
+ | Peak error | -31.0 % | - | -25.6 % (18.84 vs 25.32 m3/s) | no cited threshold (null band) |
+ | Time to peak | - | - | 66 vs 72 min | no cited threshold |
+ | Event volume | +4.7 % | - | +27.6 % (46,544 vs 36,490 m3) | ±25 satisfactory (`leta2023`, transferred) |
- | Dag variable | Metric | Direction | Very good | Good | Satisfactory |
- |--------------|--------|-----------|-----------|------|--------------|
- | discharge | NSE | maximize | >= 0.75 (leta2023, cirilo2020) | >= 0.65 (leta2023, cirilo2020) | >= 0.5 (leta2023, cirilo2020) |
- | discharge | PBIAS | zero_centered | abs(PBIAS) <= 10.0 (leta2023, cirilo2020) | abs(PBIAS) <= 15.0 (leta2023, cirilo2020) | abs(PBIAS) <= 25.0 (leta2023, cirilo2020) |
- | infiltration | NSE | maximize | no cited threshold | no cited threshold | no cited threshold |
- | surface_excess | NSE | maximize | no cited threshold | no cited threshold | no cited threshold |
+ Validation tier: **real** observation (independent flume data), but **in-sample**: the readme
+ multipliers were chosen by ARS for this storm. No blind multi-event test has been run yet.
- Achieved calibration and validation metric values are run artifacts, not
- restated by the supplied convention facts for this upgrade. When available,
- compare `discharge` NSE and PBIAS to the cited bars above and report the
- verdict explicitly.
+ ### Data Replacement Tracking
- Calibration method: Differential evolution (scipy), 150 iterations, population 20.
- Objective: -(0.5*KGE + 0.5*NSE) on 1981--1985 calibration period.
- Spinup year: 1980.
+ | Component | Source | Status | Notes |
+ |-----------|--------|--------|-------|
+ | Forcing | WGEW DAP recording gages via fetch + build tools | Validated | rebuilt 4Aug80.pre identical to ARS file |
+ | Soil | HWSD + Table 1 tool | Pending | class KS 0.135 in/hr vs ARS 0.40-0.52 in/hr (dt_kineros2_053) |
+ | Land cover | ARS sample values | Pending | no roughness tool; edit by hand |
+ | DEM / elements | ARS sample cascade | Pending | no discretiser in this KI (AGWA) |
+ | Initial conditions | ARS gage SAT 0.09-0.13 | Validated (sample) | event specific |
---
- ## 10. Coupling Points
+ ## 12. Parameter Selection by Region
- | Source | Target | Variable | Unit | Notes |
- |---------------------|---------------------|--------------|---------|------------------------------------|
- | CMFD/ERA5 NetCDF | Forcing converter | Precip | mm/d | Basin-average via shapefile mask |
- | CMFD/ERA5 NetCDF | Forcing converter | Temperature | deg C | Basin-average |
- | Hamon method | Model internal | PET | mm/d | From temperature + latitude |
- | HWSD / SoilGrids | Soil converter | Ks, psi_f | mm/d, mm| Pedotransfer functions |
- | KINEROS2 output | Parse output | Discharge | m3/s | Daily at basin outlet |
- | Observed gauge | Validation | Discharge | m3/s | Bengbu station |
+ | Climate / Region | Key parameters | Rationale |
+ |---|---|---|
+ | Semi-arid rangeland, SE Arizona (WGEW) | planes KS 0.40-0.52 in/hr, G 6.7-7.3 in, POR 0.453, ROCK 0.38-0.41, DIST 0.6, CV 0.8, n 0.05-0.10, INTER 0.014 in; channels KS 7.8-11 in/hr, WOOL=YES; multipliers Ks 0.5, G 1.5 | ARS wg11.par + readme; gravelly soils, sandy ephemeral channels with large transmission losses |
+ | Small plot / hypothetical (metric) | KS 10/50 mm/hr two layers, G 500/250 mm, CV 0.12, SAT 0.2, n 0.04 | ARS EX1.PAR (format example) |
+ | Ungauged start point (any) | KS, G, DIST, POR from texture (manual Table 1), ROCK from HWSD gravel; calibrate Ks then n | Goodrich et al. 2012 calibration order |
+ | Humid / saturation-excess catchments | out of scope | KINEROS2 generates Hortonian runoff only |
---
- ## 11. Data Requirements
+ ## 13. Known Limitations
- | Data Type | Source | Unit | Required | Path / Notes |
- |----------------------|-------------------|---------------|----------|------------------------------------------|
- | Precipitation | CMFD V0200 | kg/m2/s | Yes | Convert to mm/d (x 86400) |
- | Temperature | CMFD V0200 | K | Yes | Convert to deg C (- 273.15) |
- | Basin shapefile | GIS | -- | Yes | For spatial masking of gridded data |
- | Observed discharge | Gauge station | m3/s | Optional | For calibration and validation |
- | Soil properties | HWSD / SoilGrids | varies | Optional | For Green-Ampt parameter estimation |
+ - Event model: no ET, no continuous moisture, no baseflow dynamics; one storm per run line.
+ - Hortonian runoff only; saturation-excess catchments are outside its physics.
+ - Needs an element cascade; this KI copies and edits existing ones but has no DEM discretiser.
+ - Gridded hourly rain cannot represent convective intensities (dt_kineros2_036).
+ - The WG11 comparison is a single, in-sample event; volume +27.6 % and a slow simulated recession.
+ - `PIPE`, `URBAN`, `ADDER`, `DIVERTER` and compound channels are edited by hand (no tool).
+ - The models DB still stores the surrogate's daily metrics (NSE 0.851 / KGE 0.882 / r 0.923, Huaihe at Bengbu) and tier
+ for KINEROS2. `knowledge_infrastructure.yaml` lists them only under `validation.surrogate_metrics_not_kineros2`;
+ its `validation.metrics` hold the real-engine WG11 score (NSE 0.8115, 121 points, in-sample). Regenerating the
+ manifest with generate_ki_manifest.py would project the DB's surrogate metrics again -- re-check it after any regeneration.
---
- ## 12. Quick Start
-
- ```bash
- # 1. Convert CMFD forcing to KINEROS2 format
- python ki/tools/convert_forcing_to_kineros2.py \
- --forcing-dir /path/to/CMFD/Data_forcing_01dy_025deg \
- --shapefile /path/to/basin.shp \
- --years 1980-1990 \
- --output forcing.json
+ ## 14. Spinup Requirements
- # 2. Estimate soil parameters from HWSD
- python ki/tools/convert_soil_to_kineros2.py \
- --texture "silt loam" \
- --depth-cm 150 \
- --output params.json
+ | Parameter | Value |
+ |-----------|-------|
+ | Spinup length | none (event model) |
+ | Why | antecedent soil moisture is the SAT input per element / gage / global |
+ | Discard from metrics | No -- but align clocks and trim to the event window |
- # 3. Run model (simulation mode)
- python ki/tools/run_kineros2.py \
- --mode simulate \
- --forcing forcing.json \
- --params params.json \
- --basin-area-km2 121330 \
- --output simulation.json
+ ---
- # 4. Parse output and validate
- python ki/tools/parse_output_kineros2.py \
- --input simulation.json \
- --observed /path/to/observed_Q.csv \
- --output results.csv \
- --metrics-json metrics.json \
- --figure validation.png
+ ## 15. References
- # 5. Or run calibration end-to-end
- python ki/tools/run_kineros2.py \
- --mode calibrate \
- --forcing forcing.json \
- --observed /path/to/observed_Q.csv \
- --basin-area-km2 121330 \
- --cal-start 1981-01-01 --cal-end 1985-12-31 \
- --output calibrated.json
- ```
+ 1. Goodrich, D.C., et al. 2012. KINEROS2/AGWA: model use, calibration, and validation. Trans. ASABE 55(4):1561-1574. doi:10.13031/2013.42264
+ 2. Woolhiser, D.A., R.E. Smith, D.C. Goodrich. 1990. KINEROS, a kinematic runoff and erosion model: documentation and user manual. USDA-ARS ARS-77.
+ 3. Smith, R.E., D.C. Goodrich, D.A. Woolhiser, C.L. Unkrich. 1995. KINEROS -- a kinematic runoff and erosion model. In Computer Models of Watershed Hydrology, V.P. Singh (ed.), 697-732.
+ 4. KINEROS2 manual chapters shipped with the source: Input, Infiltration, Overland, Channel, Erosion, Rain, Source (src/doc/*.pdf).
+ 5. Stone, J.J., M.H. Nichols, D.C. Goodrich, J. Buono. 2008. Long-term runoff database, Walnut Gulch Experimental Watershed. WRR 44, W05S05. doi:10.1029/2006WR005733
+ 6. Goodrich, D.C., et al. 2008. Long-term precipitation database, Walnut Gulch Experimental Watershed. WRR 44, W05S04. doi:10.1029/2006WR005782
+ 7. Rawls, W.J., D.L. Brakensiek, K.E. Saxton. 1982. Estimation of soil water properties. Trans. ASAE 25:1316-1320.
+ 8. Sensitivity: Hantush & Kalin 2005 (doi:10.1623/hysj.2005.50.6.1151); Al-Qurashi et al. 2008 (doi:10.1016/j.jhydrol.2008.03.006); Korgaonkar et al. 2020 (doi:10.1016/j.envsoft.2020.104814).
+ 9. Full literature list: `docs/papers_index.md` (16 papers).
---
- ## 13. Diagnostic Triplets Summary
-
- | ID | Stage | Failure Domain | Severity | Symptom |
- |--------|------------|-------------------|----------|---------------------------------------------|
- | dt_001 | s1_forcing | unit_conversion | silent | Precip 86400x too low (kg/m2/s not mm/d) |
- | dt_002 | s1_forcing | unit_conversion | silent | Precip 8x too high (mm/3h not mm/d) |
- | dt_003 | s1_forcing | unit_conversion | silent | Precip 1000x too high (m/d not mm/d) |
- | dt_004 | s1_forcing | unit_conversion | silent | Temp in K causes absurd PET |
- | dt_005 | s1_forcing | unit_conversion | silent | Temp in F gives wrong PET seasonality |
- | dt_006 | s2_params | unit_conversion | silent | Ks in mm/h not mm/d -- infiltration 24x low |
- | dt_007 | s2_params | unit_conversion | silent | Ks in cm/h not mm/d -- infiltration 240x low |
- | dt_008 | s2_params | unit_conversion | silent | psi_f in cm not mm -- suction 10x low |
- | dt_009 | s2_params | unit_conversion | silent | Smax in m not mm -- storage 1000x wrong |
- | dt_010 | s2_params | unit_conversion | silent | Area in ha not km2 -- Q conversion wrong |
- | dt_011 | s6_output | unit_conversion | silent | Observed Q in mm/d not m3/s |
- | dt_012 | s5_execute | conversion_factor | silent | mm/d to m3/s factor wrong from area error |
+ ## Pipeline walk (stage docs)
- ---
+ | Stage | Doc | Tools |
+ |---|---|---|
+ | plan | `docs/input_preparation.md` | - |
+ | s1 rainfall | `docs/s1_rainfall_input.md` | fetch_wgew_dap.py, build_kineros2_rainfall.py |
+ | s2 infiltration | `docs/s2_infiltration_soil_parameters.md` | kineros2_soil_params.py |
+ | s3 watershed | `docs/s3_watershed_parameter_file.md` | edit_kineros2_par.py |
+ | s4 sediment | `docs/s4_sediment_erosion.md` | configure_kineros2_sediment.py |
+ | s5 ponds / inflow | `docs/s5_ponds_injection_elements.md` | add_kineros2_element.py |
+ | s6 execution | `docs/s6_execution_real_engine.md` | run_kineros2_engine.py |
+ | s7 output | `docs/s7_output_parsing.md` | parse_kineros2_output.py |
+ | s8 calibration | `docs/s8_calibration_multipliers.md` | calibrate_kineros2_multipliers.py |
+ | s9 validation | `docs/s9_validation_wg11.md` | score_kineros2_event.py |
- ## 14. File Structure
+ Surrogate history: `docs/surrogate/README.md`.
- ```
- ki/
- SKILL.md # This file -- agent entry point
- tools/
- convert_forcing_to_kineros2.py # Stage 1: CMFD/ERA5 -> daily P, T
- convert_soil_to_kineros2.py # Stage 2: Soil data -> Green-Ampt params
- run_kineros2.py # Stage 5: Execute lumped analytic model
- parse_output_kineros2.py # Stage 6: Parse output + metrics
- ```
+ *Generated by the Knowledge Dissection Toolkit; rebuilt for the real engine 2026-10-06.*