**Package**: `hydrocraft-gr4j-airgr` v1.0.0 **Model**: GR4J daily lumped rainfall-runoff model via airGR R package v1.7.8 **Created by**: Jianyun Zhang Research Group, Hohai University **Last updated**: 2026-03-25 **Stats**: 4 tools | 5 skill documents | 15+ diagnostic triplets | ~1,500 lines of validated Python **Validation status**: `production_validated` (airGR L0123001 built-in dataset) ---
Scanned 9/11/2026
Install to Claude Code
npx -y skills add lzwei196/KISS---Knowledge-Infrastructure-for-Scientific-Simulation --skill GR4J___airGR --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of GR4J AirGR?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lzwei196-gr4j-airgr)More formats (shields.io, HTML) on the badges page.
> **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 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` (5 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` (18 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` (17 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>`.*
<!-- 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_catchment_params.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_catchment_params.py --help` |
| `tools/convert_forcing_to_gr4j.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_forcing_to_gr4j.py --help` |
| `tools/parse_gr4j_output.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/parse_gr4j_output.py --help` |
| `tools/run_gr4j.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/run_gr4j.py --help` |
*4 public tools; `_`-prefixed helpers and packaging files excluded.*
<!-- KI-TOOL-INDEX:END -->
# GR4J (airGR) — Knowledge Infrastructure
**Package**: `hydrocraft-gr4j-airgr` v1.0.0
**Model**: GR4J daily lumped rainfall-runoff model via airGR R package v1.7.8
**Created by**: Jianyun Zhang Research Group, Hohai University
**Last updated**: 2026-03-25
**Stats**: 4 tools | 5 skill documents | 15+ diagnostic triplets | ~1,500 lines of validated Python
**Validation status**: `production_validated` (airGR L0123001 built-in dataset)
---
## 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 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.
## Overview
This knowledge infrastructure enables fully autonomous simulation of catchment rainfall-runoff processes using the GR4J model (Perrin et al., 2003) implemented in the airGR R package. The 4 validated Python tools replace manual R workflow steps with a Python pipeline that integrates directly with HydroCraft's forcing, routing, and calibration infrastructure.
**What GR4J does**: Four-parameter daily lumped conceptual hydrological model. Simulates:
- Production store: soil moisture accounting (interception, evaporation, percolation)
- Two unit hydrographs (UH1: 90% routed, UH2: 10% direct)
- Routing store: nonlinear outflow from routed branch
- Inter-catchment groundwater exchange
- Total runoff = routed flow (QR) + direct flow (QD)
**Key difference from other HydroCraft models**: GR4J operates on a lumped catchment (single spatial unit), not gridded. All inputs are catchment-average values in mm/day. It can optionally couple with CemaNeige for snow processes. The Fortran core is wrapped by R functions in airGR.
**Model Reference**: Perrin, C., Michel, C. and Andreassian, V. (2003). Improvement of a parsimonious model for streamflow simulation. Journal of Hydrology, 279(1-4), 275-289.
---
## Installation
### R Package
```
airGR v1.7.8: CRAN package (R >= 3.5.0)
Install: install.packages("airGR")
Source: https://github.com/cran/airGR
Fortran core: src/frun_GR4J.f90 (compiled via R CMD INSTALL)
```
### Dependencies (R)
```
Depends: R (>= 3.5.0)
Imports: graphics, grDevices, stats, utils
Suggests: knitr, rmarkdown, caRamel, DEoptim, testthat
```
### Python dependencies (HydroCraft tools)
```
rpy2, numpy, pandas, matplotlib
```
### Test example
```
data(L0123001) # Built-in fictional catchment
BasinObs: DatesR, P [mm/d], T [degC], E [mm/d], Qls [l/s], Qmm [mm/d]
BasinInfo: code, name, area [km2], HypsoData [m]
Period: 1984-01-01 to 2005-12-31 (daily)
```
**Validated**: GR4J runs successfully on L0123001 data. Judge performance against
`docs/validation_convention.yaml`, not remembered thresholds.
---
## Model Parameters
GR4J has exactly **4 free parameters**:
| Parameter | Symbol | Unit | Description | Typical Range |
|-----------|--------|------|-------------|---------------|
| X1 | Prod store capacity | mm | Maximum capacity of production (soil moisture) store | 100 - 1200 |
| X2 | Exchange coefficient | mm/d | Inter-catchment groundwater exchange coefficient | -5 - 3 |
| X3 | Routing store capacity | mm | Maximum capacity of routing store | 20 - 300 |
| X4 | UH time constant | d | Time base of unit hydrographs | 1.1 - 2.9 |
### Parameter Constraints
- X1 >= 0.01 mm (enforced by RunModel_GR4J)
- X3 >= 0.01 mm (enforced by RunModel_GR4J)
- X4 >= 0.5 d (enforced by RunModel_GR4J)
- X2 can be negative (catchment loses water to groundwater)
### Parameter Transformation (for calibration)
The calibration uses transformed parameters to ensure unconstrained optimization:
- X1: log transform (real = exp(transformed))
- X2: sinh transform (real = sinh(transformed))
- X3: log transform (real = exp(transformed))
- X4: linear rescaling to [0.5, 39.5] range
---
## Pipeline (7 stages)
| # | Stage | Tool(s) | Description |
|---|-------|---------|-------------|
| 0 | Configuration | (manual) | Catchment selection, period, forcing source |
| 1 | Forcing preparation | `convert_forcing_to_gr4j` | Global forcing (CMFD/ERA5) to airGR input format (P, PE in mm/d) |
| 2 | Catchment parameters | `convert_catchment_params` | HWSD soil data + DEM to catchment properties |
| 3 | Model execution | `run_gr4j` | Run GR4J via rpy2 with warmup, calibration, simulation |
| 4 | Calibration | `run_gr4j` (calibration mode) | Calibration_Michel with NSE/KGE objective |
| 5 | Output parsing | `parse_gr4j_output` | Extract Qsim, store levels, fluxes to CSV |
| 6 | Validation | `parse_gr4j_output` (validation mode) | Compute NSE, KGE, PBIAS, plot observed vs simulated |
### Parallelism
Stages 1 and 2 can run in parallel after stage 0.
Stage 3 depends on 1 and 2.
Stage 4 depends on 3 (uses same tool with calibrate=True).
Stage 5 depends on 3 or 4.
Stage 6 depends on 5.
---
## 3. Input Requirements and I/O Specification
**Exact shapes live in `docs/format_spec.yaml`** (projected from dag + triplets;
regenerate it, never hand-edit). This section explains intent, units, and traps;
the spec file is the contract.
### Inputs (all catchment-average, daily)
| Variable | Unit | Source | Notes |
|----------|------|--------|-------|
| DatesR | POSIXt | Time series dates | Must be continuous, no gaps |
| Precip (P) | mm/day | CMFD, ERA5, gauge | Must be >= 0, no NA allowed |
| PotEvap (E) | mm/day | Oudin formula or pre-computed | Must be >= 0, no NA allowed |
| Qobs | mm/day | Gauged streamflow (for calibration) | NA values allowed |
| TempMean (T) | degC | Required only if computing PE via PE_Oudin | Mean daily air temperature |
### PE_Oudin Formula (if PotEvap not pre-computed)
```
PE_Oudin(JD, Temp, Lat, LatUnit="deg")
JD: Julian day of year (1-366)
Temp: daily mean air temperature [degC]
Lat: catchment latitude [degrees or radians]
Returns: PE [mm/day]
```
### Unit Conversion from CMFD to airGR
| CMFD Variable | CMFD Unit | airGR Variable | airGR Unit | Conversion |
|---------------|-----------|----------------|------------|------------|
| prec | mm/3hr | Precip | mm/day | sum 8 timesteps per day |
| temp | K | TempMean | degC | subtract 273.15 |
| shum + pres | kg/kg, Pa | PotEvap | mm/day | Use PE_Oudin(JD, T_degC, lat) |
| srad | W/m2 | (not used) | - | GR4J uses PE, not radiation directly |
| wind | m/s | (not used) | - | GR4J uses PE, not wind directly |
### Unit Conversion from Discharge
| Source | Source Unit | Target | Target Unit | Conversion |
|--------|-----------|--------|-------------|------------|
| Gauge | m3/s | Qmm | mm/day | Q_m3s * 86400 / (area_km2 * 1e6) * 1000 |
| Gauge | l/s | Qmm | mm/day | Q_ls / 1000 * 86400 / (area_km2 * 1e6) * 1000 |
| VIC routing | mm/day | Qmm | mm/day | Direct (same unit) |
---
## 6. Output Description
**Source: `dag.yaml`.** The dag is the model's identity for observable outputs:
if this section and `dag.yaml` disagree, the dag wins.
**Headline output** (the dag's `validation_rank: 1` variable):
> `Qsim` — Simulated total catchment discharge at the outlet, QR (routing branch) + QD (direct branch). (`mm/day`)
| Output variable (dag `var`) | Rank / role | Unit | Dag description |
|-----------------------------|-------------|------|-----------------|
| Qsim | 1 / headline validation output | mm/day | Simulated total catchment discharge at the outlet, QR (routing branch) + QD (direct branch). |
Other dag outputs: `AE`, `Prod`, `AExch`.
The airGR per-timestep output table below provides the operational parser names
used by the tools; `dag.yaml` remains the source of truth for validation identity,
units, observability, and rank.
---
## 8. Unit Conversion Table
The model uses catchment-average daily water depths. Every forcing and observed
discharge conversion must preserve that convention before execution or validation.
### Unit Trap Table (CRITICAL)
These unit mismatches cause **silent failures** — the model runs but produces garbage.
| Trap ID | Source | Expected by GR4J | Wrong Value | Correct Value | Symptom |
|---------|--------|-------------------|-------------|---------------|---------|
| UT-001 | CMFD temp in K | degC | 293.15 | 20.0 | PE ~300 mm/d, all water evaporates |
| UT-002 | Precip in m/day | mm/day | 0.005 | 5.0 | Near-zero runoff, extreme drought |
| UT-003 | Precip in mm/3hr not aggregated | mm/day | 2.5 (3hr value) | 20.0 (daily sum) | Runoff 1/8 of expected |
| UT-004 | Q_obs in m3/s | mm/day | 100 | 0.86 | NSE = -infinity during calibration |
| UT-005 | Q_obs in l/s not converted | mm/day | 100000 | 0.86 | Calibration fails completely |
| UT-006 | Area in m2 used for conversion | km2 expected | 1e8 | 100 | Q_mm off by factor 1e6 |
| UT-007 | PE from Penman in mm/month | mm/day | 150 | 5.0 | Store depletes instantly |
| UT-008 | Negative PE values | >= 0 | -2.0 | 0.0 | Warning, then truncation artifacts |
---
## 7. Tool Inventory
| Tool | Stage | Script Path | Lines | Purpose |
|------|-------|-------------|------:|---------|
| `convert_forcing_to_gr4j` | s1 | `tools/convert_forcing_to_gr4j.py` | ~250 | CMFD/ERA5/gauge to airGR format (P, PE in mm/d) |
| `convert_catchment_params` | s2 | `tools/convert_catchment_params.py` | ~200 | HWSD soil + DEM to catchment area, hypsometry |
| `run_gr4j` | s3-s4 | `tools/run_gr4j.py` | ~350 | Execute GR4J via rpy2 (simulation + calibration) |
| `parse_gr4j_output` | s5-s6 | `tools/parse_gr4j_output.py` | ~300 | Extract results to CSV, compute metrics, plot |
**Total**: 4 tools, ~1,100 lines of validated Python code.
---
## Skill Knowledge
| Stage | Topic | Skill Document |
|-------|-------|----------------|
| s1 | Forcing preparation, unit conversions | `docs/s1_forcing_preparation.md` |
| s2 | Catchment parameter extraction | `docs/s2_catchment_parameters.md` |
| s3 | Model execution and warmup | `docs/s3_model_execution.md` |
| s4 | Calibration procedure | `docs/s4_calibration.md` |
| s5 | Output analysis and validation | `docs/s5_output_analysis.md` |
---
## 9. Diagnostic Triplets and Critical Domain Knowledge
These non-obvious facts cause **silent failures** if violated. Each has a corresponding diagnostic triplet.
### 1. All fluxes in mm/day, NOT m3/s (dt_001)
GR4J operates entirely in mm/day (water depth equivalent over catchment area). Precipitation, potential evapotranspiration, and simulated discharge are all in mm/day. Observed discharge for calibration MUST be converted from m3/s or l/s to mm/day using: `Qmm = Q_m3s * 86400 / (area_km2 * 1e6) * 1000`. Using m3/s directly causes NSE = -infinity.
### 2. Temperature must be in Celsius for PE_Oudin (dt_002)
The PE_Oudin function expects temperature in degrees Celsius. CMFD provides temperature in Kelvin. Forgetting to subtract 273.15 causes PE values of ~300 mm/day (instead of ~5 mm/day), draining all soil moisture instantly.
### 3. Warm-up period is essential (dt_006)
GR4J has two stores (production and routing) plus unit hydrograph states. Default initialization sets production store to 30% and routing store to 50% capacity. Without a warm-up period of at least 1 year, the first months/years of simulation are unreliable. airGR auto-selects 1 year of warm-up by default.
### 4. No missing values in precipitation or PE (dt_007)
airGR does NOT allow NA values in Precip or PotEvap. Any NA causes an error. Gap-fill forcing data BEFORE creating InputsModel. Observed discharge (Qobs) CAN contain NA values.
### 5. Calibration uses transformed parameter space (dt_008)
Calibration_Michel operates in transformed parameter space (log/sinh transforms). Direct parameter values cannot be used as starting points — they must be transformed first via TransfoParam_GR4J(). The search grid covers a wide range by default.
### 6. IndPeriod must be integer type (dt_009)
R's seq() creates numeric vectors by default. IndPeriod_Run and IndPeriod_WarmUp must be integer vectors. Use `as.integer(seq(...))` or `seq.int(...)`. Non-integer indices cause a hard error.
### 7. Daily precipitation must be positive sums, not rates (dt_010)
GR4J expects daily total precipitation in mm, not instantaneous rates. When aggregating sub-daily data, SUM the values (not average). Averaging 3-hourly precipitation gives 1/8 of the correct daily total.
### 8. X4 minimum is 0.5, not 0 (dt_011)
The unit hydrograph time constant X4 has a hard floor at 0.5 days. Values below 0.5 are silently clipped with a warning. During calibration, the parameter transform ensures X4 stays in [0.5, 39.5].
---
## Model Architecture (Fortran Core)
The GR4J Fortran subroutine (`frun_GR4J.f90`) implements the following water balance:
```
For each daily time step:
1. Net rainfall/evaporation
If P >= E: PN = P - E, EN = 0
If P < E: PN = 0, EN = E - P
2. Production store (soil moisture accounting)
PS = fraction of PN entering store (tanh function of store level / X1)
ES = actual evaporation from store (tanh function of EN / X1)
Update store: S = S + PS - ES
3. Percolation from production store
PERC = S * (1 - (1 + (S/(9/4*X1))^4)^(-0.25))
S = S - PERC
4. Total effective rainfall
PR = PN - PS + PERC
5. Split into two branches
PRUH1 = 0.9 * PR (slow routed branch)
PRUH2 = 0.1 * PR (fast direct branch)
6. Unit hydrograph convolution
UH1: S-curve with time base X4 (20 ordinates max)
UH2: S-curve with time base 2*X4 (40 ordinates max)
7. Groundwater exchange
EXCH = X2 * (R/X3)^3.5
R = routing store level
8. Routing store
R = R + Q9 + EXCH (Q9 = UH1 output)
QR = R * (1 - (1 + (R/X3)^4)^(-0.25))
R = R - QR
9. Direct branch
QD = max(0, Q1 + EXCH) (Q1 = UH2 output)
10. Total discharge
Q = QR + QD [mm/day]
```
### State Variables (67 total)
- St(1): Production store level [mm]
- St(2): Routing store level [mm]
- StUH1(1:20): UH1 states [mm]
- StUH2(1:40): UH2 states [mm]
- 5 additional internal states
### Output Variables (18 per timestep)
| Index | Name | Description | Unit |
|-------|------|-------------|------|
| 1 | PotEvap | Input PE | mm/d |
| 2 | Precip | Input P | mm/d |
| 3 | Prod | Production store level | mm |
| 4 | Pn | Net rainfall | mm/d |
| 5 | Ps | Part filling production store | mm/d |
| 6 | AE | Actual evapotranspiration | mm/d |
| 7 | Perc | Percolation | mm/d |
| 8 | PR | Effective rainfall | mm/d |
| 9 | Q9 | UH1 outflow | mm/d |
| 10 | Q1 | UH2 outflow | mm/d |
| 11 | Rout | Routing store level | mm |
| 12 | Exch | Potential exchange | mm/d |
| 13 | AExch1 | Actual exchange branch 1 | mm/d |
| 14 | AExch2 | Actual exchange branch 2 | mm/d |
| 15 | AExch | Total actual exchange | mm/d |
| 16 | QR | Routing store outflow | mm/d |
| 17 | QD | Direct flow after exchange | mm/d |
| 18 | Qsim | Simulated discharge | mm/d |
---
## Calibration
### Calibration_Michel Algorithm
1. **Grid screening**: Test predefined parameter combinations on a coarse grid
2. **Steepest descent**: Local search from best grid point, with adaptive step size
3. **Convergence**: Step size shrinks until < 0.01 in transformed space
### Available Criteria
| Criterion | Function | Best Value | Use Case |
|-----------|----------|------------|----------|
| NSE | ErrorCrit_NSE | 1.0 | General flow simulation |
| KGE | ErrorCrit_KGE | 1.0 | Balanced bias/correlation/variability |
| KGE2 | ErrorCrit_KGE2 | 1.0 | Modified KGE (CV ratio) |
| RMSE | ErrorCrit_RMSE | 0.0 | Absolute error |
### Typical Calibrated Values (literature)
| Catchment Type | X1 [mm] | X2 [mm/d] | X3 [mm] | X4 [d] |
|---------------|---------|-----------|---------|--------|
| Humid temperate | 200-500 | 0.5-2.0 | 50-150 | 1.5-2.5 |
| Semi-arid | 500-1200 | -2.0-1.0 | 100-300 | 1.5-3.0 |
| Tropical wet | 100-400 | 1.0-3.0 | 20-100 | 1.0-2.0 |
---
## 11. Validated Results
### Test Basin
| Property | Value |
|----------|-------|
| Dataset | airGR `L0123001` built-in dataset |
| Period | 1984-01-01 to 2005-12-31 (daily) |
| Status | GR4J executes successfully on the built-in dataset |
### Performance Metrics — judged against the field's bar, not intuition
**Source: `docs/validation_convention.yaml`.** The bars below restate the
convention file. Do not substitute uncited thresholds.
| Dag variable | Metric | Direction | Convention bar, cited |
|--------------|--------|-----------|-----------------------|
| Qsim | nse | maximize | very_good >= 0.75 (`moriasi2007`, `moriasi2015`); good >= 0.65 (`moriasi2007`, `moriasi2015`); satisfactory >= 0.5 (`moriasi2007`, `moriasi2015`) |
| Qsim | pbias | zero_centered | very_good <= +/-10 (`moriasi2007`, `moriasi2015`); good <= +/-15 (`moriasi2007`, `moriasi2015`); satisfactory <= +/-25 (`moriasi2007`, `moriasi2015`) |
| AE | nse | maximize | satisfactory: no cited threshold |
| Prod | r | maximize | satisfactory: no cited threshold |
`Qsim` is the rank-1 validation output from `dag.yaml`; `AE`, `Prod`, and
`AExch` are additional dag outputs. A reported run should include achieved metric
values separately and compare them to the cited bars above.
---
## CemaNeige Snow Module (Optional)
For snow-affected catchments, GR4J can be coupled with CemaNeige:
- Function: `RunModel_CemaNeigeGR4J`
- Additional parameters: 2 (CTG: degree-day factor, Kf: snowpack inertia)
- Additional inputs: TempMean [degC], HypsoData [m], ZInputs [m]
- Total parameters when coupled: 6 (4 GR4J + 2 CemaNeige)
**WIRED INTO `run_gr4j.py` (use `--snow`).** For any cold-region / snowmelt-driven
catchment (winter precip falls as snow, hydrograph driven by a spring/summer
freshet), run with `--snow` (alias for `--model cemaneige_gr4j`). The CemaNeige
variant needs the `TempMean_degC` column (written by `convert_forcing_to_gr4j` by
default) and runs as a single elevation layer if no HypsoData is supplied.
**WHY IT MATTERS (HYDAT 08NH120 Moyie R., BC, 2026-06-23):** plain GR4J on this
alpine snowmelt basin calibrated to NSE 0.14 only, with X2 forced to +7.3 mm/d
(far outside the typical −5..3 range) to import phantom groundwater faking the
spring freshet. Adding `--snow` lifted calibration NSE to 0.80 / validation 0.77
and returned X2 to a physical +0.34. Diagnostic tell: if your best-fit X2 is large
and you're on a cold catchment, you are missing snow — switch to `--snow`.
Calibration example (6-param, CemaNeige adds X5=CTG, X6=Kf):
```
run_gr4j.py --forcing forcing_gr4j.csv --output sim.csv --mode calibration --snow \
--start 2006-01-01 --end 2010-12-31 --criterion NSE --meta-json p.json
# then simulate with the calibrated 6 params: --mode simulation --snow --x1..--x6
```
**ELEVATION LAYERS (`--hypso-json`, added 2026-07-13, Lancang 允景洪):** by default
CemaNeige runs as a SINGLE elevation layer at the forcing elevation, which smears
snow across the full relief. For high-relief basins (>1500 m relief — e.g. the
Lancang at Jinghong spans ~550-5,500 m), pass the catchment-params JSON written by
`convert_catchment_params` (must contain the 101-point `hypsometry` array from the
basin-masked DEM): `--snow --hypso-json catchment_params.json [--nlayers 5]`.
airGR then extrapolates T and P over the elevation bands
(DataAltiExtrapolation_Valery) with ZInputs = median(HypsoData), so only the cold
fraction of the basin accumulates snow. Ascending, exactly-101-value hypsometry is
enforced by the tool.
---
## References
- Perrin, C., Michel, C. and Andreassian, V. (2003). Improvement of a parsimonious model for streamflow simulation. Journal of Hydrology, 279(1-4), 275-289.
- Oudin, L., Hervieu, F., Michel, C., Perrin, C., Andreassian, V., Anctil, F. and Loumagne, C. (2005). Which potential evapotranspiration input for a lumped rainfall-runoff model? Part 2. Journal of Hydrology, 303(1-4), 290-306.
- Valery, A., Andreassian, V. and Perrin, C. (2014). As simple as possible but not simpler: What is useful in a temperature-based snow-accounting routine? Journal of Hydrology, 517, 1176-1187.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!