Checking for missing content type metadata ...

Checking for non-preferred file/folder path names (may take a long time depending on the number of files/folders) ...

A bidirectional SWMM–MODFLOW 6 coupling for groundwater, stormwater, and sanitary-sewer exchange under sea-level rise


Authors:
Owners: This resource does not have an owner who is an active HydroShare user. Contact CUAHSI (help@cuahsi.org) for information on this resource.
Type: Resource
Storage: The size of this resource is 30.7 MB
Created: Jul 31, 2026 at 1:52 p.m. (UTC)
Last updated: Jul 31, 2026 at 2:59 p.m. (UTC)
Citation: See how to cite this resource
Sharing Status: Public
Views: 105
Downloads: 14
+1 Votes: Be the first one to 
 this.
Comments: No comments (yet)

Abstract

A bidirectional coupling of EPA SWMM and MODFLOW 6 that exchanges fluxes at a daily stress period through the MODFLOW API: subcatchment infiltration becomes groundwater recharge, groundwater drainage is injected into SWMM junctions, and head-based leakage into sanitary sewers is applied through the MODFLOW WEL package.

Subject Keywords

Coverage

Spatial

Coordinate System/Geographic Projection:
WGS 84 EPSG:4326
Coordinate Units:
Decimal degrees
Place/Area Name:
Bowers Beach
North Latitude
39.0650°
East Longitude
-75.3978°
South Latitude
39.0616°
West Longitude
-75.4015°

Temporal

Start Date:
End Date:

Content

README.md

MODFLOW-SWMM Coupling

Bidirectional coupling of SWMM (stormwater/sewer) and MODFLOW 6 (groundwater) for daily-timestep coastal-flood and sea-level-rise modeling. Originally developed for Bowers Beach, Delaware.

Three exchanges happen every stress period (1 day):

  • SWMM → MODFLOW: subcatchment infiltration becomes MODFLOW recharge (spatially proportioned to grid cells, lagged one day).
  • MODFLOW → SWMM: groundwater drainage from coupled cells injected into SWMM junctions.
  • MODFLOW ↔ sanitary nodes: head-based leakage into pipes via the MODFLOW WEL package. Sanitary nodes are identified from the SWMM [DWF] section.

Installation

The coupling requires patched builds of PySWMM and the SWMM toolkit. Vanilla pyswmm from PyPI does not expose the groundwater hooks and will fail at the MODFLOW→SWMM exchange. requirements.txt is a reference list only — do not install from it.

bash bash env/setup.sh conda activate pyflo

This creates the pyflo conda env from env/environment.yml, then clones and builds three forks pinned by commit (solver, toolkit, pyswmm). It ends by running env/verify_install.py, which asserts the groundwater setter round-trips, so a silent half-install cannot slip through.

MODFLOW 6 binaries for all three platforms ship in exe/ and are auto-detected; pass --dll-path to override.

Platform Status
macOS (Intel / Apple Silicon) Verified end-to-end
Linux Expected to work, not yet tested
Windows Untested — needs WSL2, or Git Bash + MS C++ Build Tools
ARM Linux (incl. ARM WSL2) Not supported — no MODFLOW 6 linux-arm64 build
Windows notes `setup.sh` is a bash script and will not run in `cmd.exe` or PowerShell. **WSL2 (recommended).** `wsl --install`, then install [Miniforge](https://github.com/conda-forge/miniforge), clone into the Linux filesystem (`~/`, not `/mnt/c/...`), and run the two commands above. **Git Bash + MSVC (native).** Install [Git for Windows](https://git-scm.com/download/win), [MS C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) ("Desktop development with C++" — `swmm-toolkit` compiles the SWMM C engine), and Miniforge. Enable conda in Git Bash once with `"$(conda info --base)/Scripts/conda.exe" init bash`, then run the two commands above. The script detects Windows, skips the Unix-only compiler setup, and converts paths with `cygpath` for `pip`. **Untested** — please open an issue with the output if it fails.

Running a simulation

One scenario per invocation. Run from the repository root — default input paths are relative to it.

bash python main.py run-simulation --scenario baseline

For the SLR scenario (CHD 1.2 m instead of 0.0 m), edit the head value in modflow_ws/Bowers_beach.chd first, then run with --scenario slr. The scenario tag is appended to every output filename, so runs never collide.

--scenario output filename suffix (default: baseline) --model-name MODFLOW model name (default: Bowers_beach) --log-level DEBUG | INFO | WARNING | ERROR (default: INFO) --dll-path path to libmf6.{dylib,so,dll} (auto-detected) --no-validate-first skip the pre-run setup validation

Input-path flags (--modflow-workspace, --swmm-input, --subcatchments-shapefile, --nodes-shapefile, --well-csv) default to the Bowers Beach files. python main.py validate-setup checks inputs without simulating; --help lists everything.

A run always writes logs/simulation_<scenario>.log. Redirecting the console as well captures MODFLOW's own output and the node-mapping summary, which Python does not log:

bash mkdir -p logs python main.py run-simulation --scenario baseline > logs/console_baseline.log 2>&1 &

Outputs

results/ ├── sanitary_nodes.csv # node-to-cell mapping └── simulation/ ├── gw_head_differences_<scenario>.csv ├── gw_head_differences_<scenario>.png ├── subcatchment_gwt_elev_ft_<scenario>.csv ├── subcatchment_max_infil_depth_<scenario>.csv ├── subcatchment_max_infil_depth_<scenario>.png ├── subcatchment_water_table_<scenario>.png ├── mean_water_table_<scenario>.tif └── mean_groundwater_depth_map_<scenario>.png

run-simulation writes the CSVs, the .tif and mean_groundwater_depth_map. The other three PNGs come from a separate, manual step:

bash python plots/time_series_plots.py --scenario baseline

These do not refresh when you re-run a simulation. Re-run this command after any run whose figures you intend to use, or they will silently show the previous run's results.

MODFLOW also writes modflow_ws/*.lst, *.hds, *.cbc; SWMM writes swmm_inp/Bowers_beach.rpt and .out. None of results/ is tracked by git.

Adapting to a new study area

The coupling logic is generic; the inputs are not.

  1. Replace the MODFLOW model in modflow_ws/ and the SWMM .inp in swmm_inp/. Set --model-name if it isn't Bowers_beach.
  2. Replace the two shapefiles the coupling reads. Columns are indexed by name, so a missing one raises a bare KeyError:
Shapefile Geometry Required columns
delineation_shpfile.shp subcatchment polygons id (= SWMM subcatchment name), Area (acres)
swmm_junc_out.shp junction/outfall points NAME (= SWMM node name), X, Y

Shapefiles and the MODFLOW grid must share one projected CRS in the same units as delr/delc. Nodes are placed by raw coordinate arithmetic (col = (x - xmin)/delr) with no reprojection; a mismatch appears as a flood of "nodes outside MODFLOW grid bounds" warnings in the console log rather than an error. Both are PCSWMM exports of the same model as the .inp, so re-export them together. 3. Sanitary nodes are detected automatically from the [DWF] section of the .inp — no code change needed. The classifier seeds from those and propagates through the pipe network. Run python main.py validate-setup once to generate results/sanitary_nodes.csv and print a coupling report. 4. Scenarios: edit the CHD value in modflow_ws/Bowers_beach.chd and pass any tag via --scenario.

Tests

bash pytest tests/ -q

21 tests covering drainage routing (separate vs. combined sewers, mass conservation), node-inflow accumulation and reset semantics, and head-based sanitary leakage. They need no MODFLOW solve and no SWMM run, and finish in about a second.

Project layout

main.py CLI entry point env/ setup.sh, environment.yml, verify_install.py src/ coupled_simulation.py, validation.py, postprocess.py, core/ (coupling components), utils/ (loaders, geolocation, proportioning, classifier) plots/ plotting source only — figures go to results/simulation/ tests/ pytest suite modflow_ws/ MODFLOW 6 workspace swmm_inp/ SWMM .inp + outputs shp_files/ subcatchment + node shapefiles exe/ MODFLOW 6 binaries tutorial/ Bowers_beach_tutorial.ipynb results/ generated outputs, not tracked

Troubleshooting

No CMAKE_C_COMPILER could be found — you ran conda env create directly instead of bash env/setup.sh. This cannot be fixed from environment.yml.

gw_set_state missing / setGroundwaterState fails — vanilla pyswmm is shadowing the fork:

bash conda activate pyflo pip uninstall -y pyswmm swmm-toolkit bash env/setup.sh --skip-env

Build picks the wrong Python or CMake — another conda env or Homebrew is ahead on PATH. If building by hand, export PATH="$CONDA_PREFIX/bin:$PATH" after activating.

Citation

If you use this software, please cite it using the metadata from the CITATION.cff file.

Alternatively, use the "Cite this repository" button in the GitHub sidebar to export the citation in APA or BibTeX format.

License

Released under the MIT License — free to use, modify, and redistribute, including commercially, provided the copyright notice and licence text are retained.

The MODFLOW 6 binaries in exe/ are USGS software in the public domain and are redistributed unchanged. The patched SWMM forks are built from source at install time and are not covered by this licence; they carry the licences of their upstream projects (see Reference).

Reference

SWMM's underlying source is US EPA public domain; Austin's forks and our coupling build on that base.The swmm_getGWaterState / swmm_setGWaterState API that makes this coupling possible is Austin Farnum's work. Our forks descend directly from his repositories with his commits and authorship intact; our additions fix compilation and complete the Python binding. Every change is visible as a diff against his code: solver, toolkit, pyswmm.

Credits

Funding Agencies

This resource was created using funding from the following sources:
Agency Name Award Title Award Number
National Science Foundation (NSF) CUAHSI Hydroinformatics Innovation Fellowship EAR-1849458

How to Cite

Erukubami, O., Farnum, A., Voter, C. (2026). A bidirectional SWMM–MODFLOW 6 coupling for groundwater, stormwater, and sanitary-sewer exchange under sea-level rise, HydroShare, http://www.hydroshare.org/resource/967c100072ac412589ccfd26e57b7975

MIT License. Copyright (c) 2026 Omowumi Erukubami and Austin Farnum. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, to deal in the software without restriction, provided the above copyright notice and this permission notice are included in all copies. The full licence text is in the LICENSE file included with this resource.

https://opensource.org/license/mit

Comments

There are currently no comments

New Comment

required