OpenWQ

Sources, Sinks & Loads
Five methods for defining chemical loading β€” from simple CSV files
to land-use calculations and machine learning predictions

Contents

β€’ Loading Options Overview

β€’ Sources/Sinks vs External Fluxes

Section 01: JSON Inline Format

β€’ JSON Configuration

β€’ Inline Data Examples

Section 02: CSV/ASCII Files

β€’ External File Format

β€’ Time Series Data

Section 03: HDF5 Coupling

β€’ Model Integration

Section 04: Land Use Based Loading

β€’ LULC with Static Coefficients

β€’ LULC with Dynamic Coefficients

Section 05: Machine Learning

β€’ ML Model Predictions

β€’ Temporal Patterns & Wildcards

β€’ Discrete vs Continuous Loads

β€’ Master Configuration

Loading Options Overview

OpenWQ supports five methods for defining sources/sinks and external fluxes:

πŸ“‹

JSON Inline

Data embedded directly in config files

πŸ“„

CSV/ASCII

External time series files

πŸ“¦

HDF5

Upstream model coupling

πŸ›°οΈ

LULC-Based

Copernicus land use export coefficients

πŸ€–

ML Model

XGBoost/RF predictions from monitoring data

Two Load Types: Sources/Sinks (add/remove mass) and External Water Fluxes (concentration in incoming water)

Sources/Sinks vs External Fluxes

πŸ“₯ Sources & Sinks (SS)

Direct mass addition or removal from a compartment

  • Sources β€” Add mass (fertilizer, point discharge)
  • Sinks β€” Remove mass (uptake, abstraction)
  • Units: mass or mass/time (kg, kg/day)
  • Supports discrete or continuous loads
Example: 50 kg N fertilizer applied on April 15

🌧️ External Water Fluxes (EWF)

Concentration in water entering from external sources

  • Tied to water flux from host model
  • Precipitation, irrigation, inflows
  • Units: concentration (mg/L)
  • Mass = concentration Γ— water volume
Example: 2.5 mg/L NO₃ in precipitation
01

JSON Inline Format

Method 1: JSON Inline Data

JSON Embed time series directly in the configuration file

{
    "1": {
        "CHEMICAL_NAME": "NO3_N",
        "COMPARTMENT_NAME": "SOIL",
        "TYPE": "source",
        "UNITS": "kg",
        "DATA_FORMAT": "JSON",
        "DATA": {
            // [YYYY, MM, DD, HH, MIN, SEC, ix, iy, iz, load, load_type, time_units]
            "1": [2020, 4, 15, 8, 0, 0, "all", "all", 1, 50.0, "discrete"],
            "2": [2020, "all", "all", "all", "all", "all", "all", "all", 1, 0.5, "continuous", "day"]
        }
    }
}
                

Data Row Fields

YYYY, MM, DD...Date/time (or "all")
ix, iy, izSpatial indices (or "all")
loadValue in specified units
load_type"discrete" or "continuous"

Wildcards

  • "all" for time β†’ recurring pattern
  • "all" for space β†’ entire dimension
  • Cell ID strings supported (e.g., "1200014181")
02

CSV/ASCII Files

Method 2: External CSV Files

CSV Reference external time series files for large datasets

JSON Configuration

{
    "1": {
        "CHEMICAL_NAME": "NO3_N",
        "COMPARTMENT_NAME": "RIVER",
        "TYPE": "source",
        "UNITS": "kg/day",
        "DATA_FORMAT": "ASCII",
        "DATA": {
            "FILEPATH": "loads.csv",
            "DELIMITER": ","
        }
    }
}
                        

CSV File Format

# Loading data for point source
YYYY,MM,DD,HH,MIN,SEC,ix,iy,iz,load,load_type
2020,1,1,0,0,0,1,1,1,10.5,continuous
2020,1,2,0,0,0,1,1,1,11.2,continuous
2020,1,3,0,0,0,1,1,1,9.8,continuous
...
                        
Tip: Header row auto-detected by scanning for "YYYY" column
03

HDF5 Coupling

Method 3: HDF5 Model Coupling

HDF5 Couple with upstream model output (External Water Fluxes only)

{
    "1": {
        "DATA_FORMAT": "HDF5",
        "UNITS": "mg/L",
        "CHEMICAL_NAME": "NO3_N",

        // Upstream model info
        "EXTERNAL_COMPARTMENT_NAME": "ATMOSPHERE",
        "EXTERNAL_INPUTFLUX_NAME": "PRECIP",

        // Spatial interface
        "INTERACTION_INTERFACE": ["all", "all", 1],

        // Time interpolation
        "INTERPOLATION": "LINEAR",

        "FOLDERPATH": "upstream_output/"
    }
}
                        

Use Cases

  • Atmospheric deposition from chemistry model
  • Upstream watershed to river
  • Regional to local downscaling

Interpolation Options

STEPPrevious value (zero-order)
NEARESTClosest timestamp
LINEARLinear interpolation
04

Land Use Based Loading

Method 4a: LULC with Static Coefficients

LULC Calculate loads from Copernicus land use data and export coefficients

   Copernicus LULC NetCDF          Basin Shapefile           Export Coefficients
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ β€’ Land cover class  β”‚   +    β”‚ β€’ HRU polygons  β”‚   +   β”‚ β€’ Cropland: 15 kg/haβ”‚
   β”‚ β€’ Annual maps       β”‚        β”‚ β€’ Reach IDs     β”‚       β”‚ β€’ Forest: 2 kg/ha   β”‚
   β”‚ β€’ 300m resolution   β”‚        β”‚                 β”‚       β”‚ β€’ Urban: 8 kg/ha    β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                            β”‚                           β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                                 β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  Per-HRU Annual Loads (CSV) β”‚
                    β”‚  Load = Ξ£(Area Γ— Coeff)     β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    

Required Inputs

  • Copernicus LULC NetCDF files
  • Basin shapefile with HRU polygons
  • Export coefficients by land class

Output

  • Annual CSV load files per HRU
  • OpenWQ SS JSON referencing CSVs

Method 4b: LULC with Dynamic Coefficients

LULC+Climate Extend static method with monthly precipitation and temperature scaling

Monthly Weight Formula (SWAT-inspired)
wm = PmΞ± Γ— Q10(Tm - Tref) / 10
ParameterDescriptionDefault
PmMonthly precipitationmm
Ξ±Precip scaling power1.0
Q10Temperature coefficient2.0
TrefReference temperature15Β°C

Monthly Distribution

Annual load is distributed across months based on climate weights:

  • Wetter months β†’ higher loads
  • Warmer months β†’ higher bio-activity
  • Weights normalized to sum to 1
Use case: Diffuse agricultural pollution with seasonal variability
05

Machine Learning

Method 5: ML Model Predictions

ML Train XGBoost or Random Forest on monitoring data to predict loads

  Monitoring CSV                    ML Training                     OpenWQ Input
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ date, discharge,    β”‚         β”‚ β€’ Feature engineer  β”‚         β”‚ β€’ JSON with         β”‚
β”‚ precip, temp,       │────────▢│ β€’ Train XGBoost/RF  │────────▢│   predicted loads   β”‚
β”‚ NO3-N, TP, ...      β”‚         β”‚ β€’ Validate (RΒ², RMSE)β”‚        β”‚ β€’ Model files (.txt)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    

Input Data Format

date,discharge_m3s,precip_mm,temp_c,NO3-N,TP
2018-01-01,15.2,3.5,-2.1,2.3,0.05
2018-01-02,14.8,0.0,-3.5,2.1,0.04
...
                            

Model Options

  • XGBoost β€” gradient boosting
  • Random Forest β€” ensemble trees

Output Files

  • ml_model_NO3-N.txt β€” trained model
  • ml_model_features.json β€” config
  • OpenWQ SS JSON with predictions
FastForest compatible: Models exported in text format for C++ runtime prediction

Temporal Patterns & Wildcards

Use "all" wildcards to create recurring patterns without repeating data:

Pattern Data Row Meaning
Single event [2020, 4, 15, 8, 0, 0, ...] April 15, 2020 at 8:00 AM
Every year ["all", 4, 15, 8, 0, 0, ...] April 15 at 8:00 AM every year
Every month [2020, "all", 15, 8, 0, 0, ...] 15th of each month in 2020
Every day [2020, 4, "all", 8, 0, 0, ...] Every day at 8:00 AM in April 2020
Continuous [2020, "all", "all", "all", "all", "all", ..., "continuous", "day"] Steady load throughout 2020
Tip: Combine temporal wildcards with spatial wildcards ("all" for ix, iy, iz) for watershed-wide loads

Discrete vs Continuous Loads

Discrete Load

Applies entire load value at a specific instant

// 50 kg applied on April 15 at 8 AM
[2020, 4, 15, 8, 0, 0, "all", "all", 1,
 50.0, "discrete"]
                            
  • Instantaneous addition
  • Event-based releases
  • Fertilizer application
  • Spill events

Continuous Load

Distributes load evenly over a time period

// 0.5 kg/day throughout April
[2020, 4, "all", "all", "all", "all",
 "all", "all", 1, 0.5, "continuous", "day"]
                            
  • Steady emission rate
  • Background loading
  • WWTP discharges
  • Atmospheric deposition

Master Configuration

Register loading files in the master JSON under OPENWQ_INPUT:

{
    "OPENWQ_INPUT": {
        "CONFIG_FILEPATH": "openwq_config.json",

        "SINK_SOURCE": {
            "1": { "LABEL": "Fertilizer", "FILEPATH": "fertilizer_loads.json" },
            "2": { "LABEL": "WWTP", "FILEPATH": "point_sources.json" },
            "3": { "LABEL": "Diffuse", "FILEPATH": "lulc_loads.json" }
        },

        "EXTERNAL_WATER_FLUXES": {
            "1": { "LABEL": "Precipitation", "FILEPATH": "precip_conc.json" },
            "2": { "LABEL": "Upstream", "FILEPATH": "upstream_hdf5.json" }
        }
    }
}
                

Summary

Method Format Best For Complexity
JSON Inline data Small datasets, quick setup Low
CSV External files Long time series, existing data Low
HDF5 Binary arrays Model coupling, large grids Medium
LULC Satellite + coeffs Diffuse sources, scenarios Medium
ML Trained model Data-rich sites, gap-filling High
All methods produce the same internal format β€” mix and match as needed!

Thank You

Questions?