Skip to content
Back to skills

Swmm Water Quality

ASecurity

Complete SWMM engine coverage: pollutant buildup/washoff simulation support and load reporting. Validate water-quality config JSON, build INPs with WQ sections, and extract pollutant load summaries from completed runs.

  • 29 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added August 31, 2026
ai-agentspythonbash

Works with

  • cli

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned August 31, 2026

npx -y skills add Zhonghao1995/agentic-swmm-workflow --skill swmm-water-quality --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Swmm Water Quality?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Swmm Water Quality
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/zhonghao1995-swmm-water-quality/badge)](https://www.skillsdirectory.com/skills/zhonghao1995-swmm-water-quality)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: swmm-water-quality
description: >
  Complete SWMM engine coverage: pollutant buildup/washoff simulation
  support and load reporting.  Validate water-quality config JSON,
  build INPs with WQ sections, and extract pollutant load summaries
  from completed runs.
---

# SWMM Water Quality Skill

## Purpose

Complete SWMM engine coverage for pollutant buildup/washoff simulation
and load reporting.  This skill provides:

1. `validate_wq_config.py` — validate a WQ config JSON before passing
   it to the builder.
2. `extract_wq_loads.py` — extract WQ load summaries from a SWMM RPT.

The water-quality sections (`[POLLUTANTS]`, `[LANDUSES]`, `[COVERAGES]`,
`[BUILDUP]`, `[WASHOFF]`, `[LOADINGS]`) are emitted by
`skills/swmm-builder/scripts/build_swmm_inp.py` via the
`--water-quality-json` flag (see also `build_inp` tool's
`water_quality_json` argument).

## Agent tool: `read_wq_loads`

Read pollutant load summaries from a completed run's .rpt file.  Returns
`wq_present=false` for non-WQ runs.

```
read_wq_loads(rpt_path="runs/my_run/model.rpt")
```

Returns a structured JSON with:

- `wq_present` (bool)
- `pollutants` — sorted list of pollutant names
- `runoff_quality_continuity` — mass-balance rows (metric + per-pollutant kg)
- `quality_routing_continuity` — routing mass-balance rows
- `subcatchment_washoff` — per-subcatchment loads (kg per pollutant)
- `link_loads` — per-link transport loads (kg per pollutant)
- `outfall_loads` — per-outfall flow stats + pollutant loads

## WQ config JSON schema

Top-level keys (all required when the key is present; empty arrays are valid):

```json
{
  "pollutants": [...],
  "landuses": [...],
  "coverages": [...],
  "buildup": [...],
  "washoff": [...],
  "loadings": []
}
```

### `pollutants` entries

| Field | Type | Default | Notes |
|---|---|---|---|
| `name` | string | required | No spaces |
| `units` | string | required | `MG/L`, `UG/L`, or `#/L` |
| `c_rain` | float | `0` | Concentration in precipitation |
| `c_gw` | float | `0` | Concentration in groundwater |
| `c_ii` | float | `0` | Concentration in RDII |
| `k_decay_per_day` | float | `0` | First-order decay (1/days) |
| `snow_only` | bool | `false` | Buildup during snow only |
| `co_pollutant` | string | `"*"` | Co-pollutant name or `"*"` |
| `co_fraction` | float | `0` | Co-pollutant fraction (0–1) |
| `init_conc` | float | `0` | Initial dry-weather concentration |

### `landuses` entries

| Field | Type | Default | Notes |
|---|---|---|---|
| `name` | string | required | |
| `sweep_interval` | float | `0` | Days between sweeping (0 = no sweeping) |
| `availability` | float | `0` | Fraction of buildup removed by sweeping (0–1) |
| `last_sweep` | float | `0` | Days since last sweep at start |

### `coverages` entries

| Field | Type | Notes |
|---|---|---|
| `subcatchment` | string | Must reference an existing subcatchment |
| `landuse` | string | Must reference a defined land use |
| `percent` | float (0–100) | Percent coverage; per-subcatchment sum must be ≤ 100 |

### `buildup` entries

| Field | Type | Notes |
|---|---|---|
| `landuse` | string | Must reference a defined land use |
| `pollutant` | string | Must reference a defined pollutant |
| `func_type` | string | `POW`, `EXP`, or `SAT` (`EXT` not supported in v1) |
| `c1` | float | Max buildup (kg/ha or count/ha when normalizer=AREA) |
| `c2` | float | Rate constant |
| `c3` | float | Third coefficient (unused for EXP/SAT) |
| `normalizer` | string | `AREA` or `CURBLENGTH` |

### `washoff` entries

| Field | Type | Notes |
|---|---|---|
| `landuse` | string | Must reference a defined land use |
| `pollutant` | string | Must reference a defined pollutant |
| `func_type` | string | `EXP`, `RC`, or `EMC` |
| `c1` | float | Coefficient 1 |
| `c2` | float | Coefficient 2 (0 for EMC) |
| `sweep_removal` | float (0–1) | Fraction removed by sweeping |
| `bmp_removal` | float (0–1) | Fraction removed |

### `loadings` entries (optional)

| Field | Type | Notes |
|---|---|---|
| `subcatchment` | string | Must reference an existing subcatchment |
| `pollutant` | string | Must reference a defined pollutant |
| `init_buildup` | float | Initial buildup mass |

## Scripts

- `scripts/validate_wq_config.py` — standalone CLI validator
- `scripts/extract_wq_loads.py` — RPT load extractor

## Executed examples

### Validate a WQ config JSON

```bash
# Write a minimal WQ config JSON:
cat > /tmp/wq_example.json << 'EOJSON'
{
  "pollutants": [{"name": "TSS", "units": "MG/L", "c_rain": 0, "c_gw": 0,
                  "c_ii": 0, "k_decay_per_day": 0, "snow_only": false,
                  "co_pollutant": "*", "co_fraction": 0, "init_conc": 0}],
  "landuses": [{"name": "Residential", "sweep_interval": 0, "availability": 0, "last_sweep": 0}],
  "coverages": [{"subcatchment": "S1", "landuse": "Residential", "percent": 100}],
  "buildup": [{"landuse": "Residential", "pollutant": "TSS", "func_type": "EXP",
               "c1": 15, "c2": 0.5, "c3": 0, "normalizer": "AREA"}],
  "washoff": [{"landuse": "Residential", "pollutant": "TSS", "func_type": "EMC",
               "c1": 50, "c2": 0, "sweep_removal": 0, "bmp_removal": 0}],
  "loadings": []
}
EOJSON

python3 skills/swmm-water-quality/scripts/validate_wq_config.py \
    --wq-json /tmp/wq_example.json
# Output: {"ok": true, "pollutant_count": 1, "landuse_count": 1, ...}
```

### Extract WQ load summaries from a completed run RPT

```bash
python3 skills/swmm-water-quality/scripts/extract_wq_loads.py \
    --rpt tests/fixtures/wq/wq_smoke.rpt
# Output: {"ok": true, "wq_present": true, "pollutants": ["TSS"],
#          "runoff_quality_continuity": [...], ...}
```

### Build an INP with water quality sections

```bash
python3 skills/swmm-builder/scripts/build_swmm_inp.py \
    --subcatchments-csv <subcatchments.csv> \
    --params-json <params.json> \
    --network-json <network.json> \
    --water-quality-json /tmp/wq_example.json \
    --out-inp /tmp/wq_model.inp \
    --out-manifest /tmp/wq_model_manifest.json
```

## Validation constraints

Enforced by both `validate_wq_config.py` and `build_swmm_inp.py`:

- Referential: every `[BUILDUP]`/`[WASHOFF]` landuse/pollutant must exist
- Referential: every `[COVERAGES]`/`[LOADINGS]` subcatchment must exist
- Enum: `units` ∈ {`MG/L`, `UG/L`, `#/L`}
- Enum: buildup `func_type` ∈ {`POW`, `EXP`, `SAT`} (EXT rejected with message)
- Enum: washoff `func_type` ∈ {`EXP`, `RC`, `EMC`}
- Range: coverage `percent` ∈ [0, 100]; per-subcatchment sum ≤ 100
- Range: `sweep_removal`, `bmp_removal`, `co_fraction` ∈ [0, 1]

Files in this skill

  • SKILL.md6.4 KB
  • docs/rpt_wq_sections.md5 KB
  • scripts/extract_wq_loads.py12 KB
  • scripts/validate_wq_config.py12.5 KB
  • tests/test_wq_builder_sections.py25 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.