Water Quality Reference¶
pywmp.wq adds advection-dispersion transport of dissolved and particulate water quality constituents (TSS, TP, TN, and custom scalars) to any PyWMP 2D simulation.
Physics¶
| Process | Method |
|---|---|
| Advection | First-order explicit upwind (delegates to pywmp.sediment.advection) |
| Dispersion | Fickian — explicit central difference (Elder 1959) |
| Precipitation loading | Event Mean Concentration (EMC) — EPA NSQD 2004 |
| Decay | First-order (settling, sorption, biological uptake) |
Quick start¶
import numpy as np
from pywmp.wq import TSSModel, TPModel, WQResults
shape = (100, 80)
dx = 10.0 # cell size (m)
dt = 60.0 # timestep (s)
# TSS model (Total Suspended Solids)
tss = TSSModel(
shape = shape,
dx = dx,
D = 0.5, # dispersion coefficient (m²/s)
init_conc_mg_L = 5.0, # initial ambient concentration
)
# TP model (Total Phosphorus)
tp = TPModel(
shape = shape,
dx = dx,
emc_tp_mg_L = 0.40, # event mean concentration for TP loading
)
# In the hydraulic time-stepping loop:
tss_results = WQResults("TSS", "mg/L", dx=dx)
tp_results = WQResults("TP", "mg/L", dx=dx)
for step in range(n_steps):
h = get_depth(step)
qx = get_qx(step)
qy = get_qy(step)
Dr = get_erosion_rate(step) # deposition rate from sediment module
Df = get_deposition_rate(step)
precip = get_precip_rate(step) # m/s
C_tss = tss.advance(dt, h, qx, qy, Dr, Df)
C_tp = tp.advance(dt, h, qx, qy, precip_rate=precip, tss_mg_L=C_tss)
if step % 60 == 0: # record every hour
tss_results.record(C_tss, t_sec=step * dt)
tp_results.record(C_tp, t_sec=step * dt)
print(tss_results.summary())
print(tp_results.summary())
TSSModel¶
TSSModel(shape, dx, D=0.5, init_conc_mg_L=0.0, k_decay=0.0)
| Parameter | Description |
|---|---|
shape |
Grid dimensions (ny, nx) |
dx |
Cell size (m) |
D |
Fickian dispersion coefficient (m²/s). Typical: 0.1–2.0 for shallow urban flow |
init_conc_mg_L |
Initial TSS concentration (mg/L; background) |
k_decay |
First-order decay rate (1/s; 0 = conservative tracer) |
Method:
C_new = tss.advance(dt, h, qx, qy, erosion_rate, deposition_rate)
Returns updated concentration array (mg/L).
TPModel¶
TPModel(shape, dx, emc_tp_mg_L=0.30, D=0.3, k_decay=1e-5)
| Parameter | Description |
|---|---|
emc_tp_mg_L |
Event Mean Concentration for TP in stormwater runoff (mg/L) |
k_decay |
First-order decay/uptake rate (1/s) |
Typical EMC values (EPA NSQD 2004):
| Land use | TP EMC (mg/L) | TSS EMC (mg/L) |
|---|---|---|
| Residential | 0.30–0.50 | 80–150 |
| Commercial | 0.40–0.70 | 100–200 |
| Industrial | 0.30–0.60 | 100–300 |
| Freeway/highway | 0.20–0.40 | 100–250 |
| Open/park | 0.05–0.20 | 20–80 |
Method:
C_new = tp.advance(dt, h, qx, qy, precip_rate, tss_mg_L=C_tss)
TP transport includes a particulate-sorbed fraction (coupled to TSS) and a dissolved fraction.
WQResults¶
WQResults(constituent_name, units, dx)
Records spatial snapshots and computes summary statistics.
| Method | Description |
|---|---|
.record(C, t_sec) |
Store a concentration snapshot at time t_sec |
.summary() |
Print peak concentration, spatial mean, and mass balance |
.plot_snapshot(t_sec, path) |
Map of concentration at a given time |
.plot_time_series(row, col, path) |
Concentration vs. time at a grid cell |
.to_csv(path) |
Export snapshot table to CSV |
Summary output:
WQ Summary — TSS (mg/L)
-----------------------------------
Peak concentration : 145.3 mg/L
Domain mean : 18.6 mg/L
Mass at t=6hr : 4.2 kg
Mass at t=12hr : 1.8 kg (decay)
EMC_TP_BY_NLCD¶
Pre-built EMC lookup table for TP by NLCD land cover code:
from pywmp.wq import EMC_TP_BY_NLCD
tp_emc = EMC_TP_BY_NLCD[23] # NLCD code 23 = Developed, medium intensity
print(f"TP EMC for medium-density development: {tp_emc:.2f} mg/L")
References¶
- Elder (1959) J. Fluid Mech. 5:544 — dispersion coefficient
- Fischer et al. (1979) Mixing in Inland and Coastal Waters — longitudinal dispersion
- Chapra (1997) Surface Water Quality Modeling — first-order decay
- EPA NSQD (2004) — event mean concentration database