psdm 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- psdm-0.1.0/.gitattributes +2 -0
- psdm-0.1.0/.gitignore +15 -0
- psdm-0.1.0/.readthedocs.yaml +17 -0
- psdm-0.1.0/CHANGELOG.md +47 -0
- psdm-0.1.0/CONTRIBUTING.md +31 -0
- psdm-0.1.0/LICENSE +27 -0
- psdm-0.1.0/PKG-INFO +118 -0
- psdm-0.1.0/README.md +89 -0
- psdm-0.1.0/benchmarks/report.html +197 -0
- psdm-0.1.0/benchmarks/results.json +21193 -0
- psdm-0.1.0/docs/api.md +94 -0
- psdm-0.1.0/docs/changelog.md +2 -0
- psdm-0.1.0/docs/conf.py +33 -0
- psdm-0.1.0/docs/design.md +116 -0
- psdm-0.1.0/docs/getting-started.md +83 -0
- psdm-0.1.0/docs/guide.md +90 -0
- psdm-0.1.0/docs/index.md +15 -0
- psdm-0.1.0/docs/model.md +64 -0
- psdm-0.1.0/examples/Example_Multi.xlsx +0 -0
- psdm-0.1.0/examples/Example_TCE.xlsx +0 -0
- psdm-0.1.0/pyproject.toml +82 -0
- psdm-0.1.0/scripts/benchmark.py +1035 -0
- psdm-0.1.0/src/psdm/__init__.py +31 -0
- psdm-0.1.0/src/psdm/capacity.py +279 -0
- psdm-0.1.0/src/psdm/collocation.py +144 -0
- psdm-0.1.0/src/psdm/correlations.py +70 -0
- psdm-0.1.0/src/psdm/fitting.py +240 -0
- psdm-0.1.0/src/psdm/fouling.py +123 -0
- psdm-0.1.0/src/psdm/fullscale.py +455 -0
- psdm-0.1.0/src/psdm/io.py +212 -0
- psdm-0.1.0/src/psdm/isotherms.py +128 -0
- psdm-0.1.0/src/psdm/model.py +193 -0
- psdm-0.1.0/src/psdm/plotting.py +55 -0
- psdm-0.1.0/src/psdm/properties.py +32 -0
- psdm-0.1.0/src/psdm/py.typed +0 -0
- psdm-0.1.0/src/psdm/solver.py +344 -0
- psdm-0.1.0/src/psdm/uncertainty.py +193 -0
- psdm-0.1.0/src/psdm/units.py +106 -0
- psdm-0.1.0/tests/conftest.py +28 -0
- psdm-0.1.0/tests/data/addesigns_test.xlsx +0 -0
- psdm-0.1.0/tests/data/reference/addesigns_single.csv +350 -0
- psdm-0.1.0/tests/data/reference/capacity.csv +13 -0
- psdm-0.1.0/tests/data/reference/capacity_cases.csv +127 -0
- psdm-0.1.0/tests/data/reference/dsfit.csv +2 -0
- psdm-0.1.0/tests/data/reference/dsfit_effluent.csv +89 -0
- psdm-0.1.0/tests/data/reference/generate.py +91 -0
- psdm-0.1.0/tests/data/reference/generate_capacity.py +68 -0
- psdm-0.1.0/tests/data/reference/generate_uncertainty_dsfit.py +90 -0
- psdm-0.1.0/tests/data/reference/multi_organic_free.csv +302 -0
- psdm-0.1.0/tests/data/reference/multi_rhine.csv +302 -0
- psdm-0.1.0/tests/data/reference/uncertainty.csv +176 -0
- psdm-0.1.0/tests/test_building_blocks.py +122 -0
- psdm-0.1.0/tests/test_capacity.py +99 -0
- psdm-0.1.0/tests/test_fullscale.py +145 -0
- psdm-0.1.0/tests/test_io_isotherms_fitting.py +93 -0
- psdm-0.1.0/tests/test_solver.py +122 -0
- psdm-0.1.0/tests/test_uncertainty_dsfit.py +78 -0
- psdm-0.1.0/uv.lock +2770 -0
psdm-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
build:
|
|
4
|
+
os: ubuntu-24.04
|
|
5
|
+
tools:
|
|
6
|
+
python: "3.12"
|
|
7
|
+
jobs:
|
|
8
|
+
create_environment:
|
|
9
|
+
- asdf plugin add uv
|
|
10
|
+
- asdf install uv latest
|
|
11
|
+
- asdf global uv latest
|
|
12
|
+
install:
|
|
13
|
+
- UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --frozen --group docs
|
|
14
|
+
|
|
15
|
+
sphinx:
|
|
16
|
+
configuration: docs/conf.py
|
|
17
|
+
fail_on_warning: true
|
psdm-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[semantic versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] - 2026-10-14
|
|
10
|
+
|
|
11
|
+
First release.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `psdm.simulate`: multi-component PSDM with NOM fouling, rewritten from the US EPA code.
|
|
16
|
+
- `psdm.Column` and `psdm.Compound` input objects with unit conversion.
|
|
17
|
+
- `psdm.fit_freundlich` and `psdm.fit_isotherm` for parameter estimation.
|
|
18
|
+
- `psdm.io.read_excel` for the EPA PSDM Excel template.
|
|
19
|
+
- Validation tests against AdDesignS and the original EPA implementation.
|
|
20
|
+
- `scripts/benchmark.py` and `benchmarks/report.html`: case-by-case comparison with the
|
|
21
|
+
original EPA PSDM code (11 cases).
|
|
22
|
+
- `psdm.estimate_capacity`: Freundlich `K` from breakthrough data for an assumed `1/n`
|
|
23
|
+
(upstream `__calculate_capacity`), with breakthrough detection and logistic/linear
|
|
24
|
+
extrapolation. Validated against the EPA code.
|
|
25
|
+
- `psdm.model_uncertainty`: uncertainty bands from ± perturbations of capacity, `K`, `1/n`,
|
|
26
|
+
influent concentration, mass, flow rate, `kf`, `dp` and `ds` (upstream `model_uncertainty`).
|
|
27
|
+
- `psdm.fit_surface_diffusivity`: grid search plus refinement for `ds` (upstream
|
|
28
|
+
`run_psdm_dsfit`).
|
|
29
|
+
- `psdm.fullscale`: `mesh_diameter`, `build_large_scale_column`, `rssct_design`,
|
|
30
|
+
`specific_throughput`, `replacement_interval` (2024 US EPA PFAS MCLs and hazard index) and
|
|
31
|
+
`staggered_bed_interval` (upstream `PSDM_extra.py` and `PSDM_tools.py`).
|
|
32
|
+
|
|
33
|
+
### Fixed relative to the EPA code
|
|
34
|
+
|
|
35
|
+
- The surface-diffusivity reference includes the Freundlich `K` term.
|
|
36
|
+
- The PFBS term is added to the hazard index in the replacement interval.
|
|
37
|
+
- Longer EBCTs in `specific_throughput` enlarge the bed instead of shrinking it.
|
|
38
|
+
- RSSCT particle diameters given with units are converted correctly.
|
|
39
|
+
|
|
40
|
+
### Still not ported
|
|
41
|
+
|
|
42
|
+
- Lead–lag configurations (`lead_lag_class.py`, needs the `ixpy` package).
|
|
43
|
+
- The equilibrium column model (`ecm.py`).
|
|
44
|
+
- `run_all_smart` fouling-factor estimates and `break_type='force'` breakthrough input.
|
|
45
|
+
|
|
46
|
+
[Unreleased]: https://github.com/zohoMatt/psdm/compare/v0.1.0...HEAD
|
|
47
|
+
[0.1.0]: https://github.com/zohoMatt/psdm/releases/tag/v0.1.0
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Development uses [uv](https://docs.astral.sh/uv/).
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
uv sync # create .venv with the package and dev tools
|
|
7
|
+
uv run pytest # tests
|
|
8
|
+
uv run ruff check . # lint
|
|
9
|
+
uv run ruff format . # format
|
|
10
|
+
uv run --group docs sphinx-build -W -b html docs docs/_build/html # docs
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Reference data
|
|
14
|
+
|
|
15
|
+
`tests/data/reference/*.csv` are breakthrough curves computed with the original US EPA code
|
|
16
|
+
(`Water_Treatment_Models` commit `3f514c2`). To regenerate them, check out that repository and
|
|
17
|
+
run
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run --no-project --with numpy --with scipy --with pandas --with openpyxl --with matplotlib \
|
|
21
|
+
python tests/data/reference/generate.py <Water_Treatment_Models>/PSDM tests/data/reference
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`tests/data/addesigns_test.xlsx` holds AdDesignS output for the same case and is the
|
|
25
|
+
independent check.
|
|
26
|
+
|
|
27
|
+
## Releasing
|
|
28
|
+
|
|
29
|
+
1. Update `__version__` in `src/psdm/__init__.py` and the changelog.
|
|
30
|
+
2. Commit, tag `vX.Y.Z`, push, and publish a GitHub release for the tag.
|
|
31
|
+
3. The `Release` workflow tests, builds and uploads to PyPI via trusted publishing.
|
psdm-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matt Zuo
|
|
4
|
+
|
|
5
|
+
This project is a rewrite of the Python PSDM code by Jonathan Burkhardt, Levi Haupert,
|
|
6
|
+
Boris Datsov and colleagues at the US Environmental Protection Agency
|
|
7
|
+
(https://github.com/USEPA/Water_Treatment_Models), itself released under the MIT License,
|
|
8
|
+
and is based on the AdDesignS(TM) PSDM by D.R. Hokanson, D.W. Hand, J.C. Crittenden,
|
|
9
|
+
T.N. Rogers and E.J. Oman (Michigan Technological University).
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
psdm-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: psdm
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pore and Surface Diffusion Model (PSDM) for fixed-bed granular activated carbon adsorbers
|
|
5
|
+
Project-URL: Documentation, https://psdm.readthedocs.io
|
|
6
|
+
Project-URL: Source, https://github.com/zohoMatt/psdm
|
|
7
|
+
Project-URL: Issues, https://github.com/zohoMatt/psdm/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/zohoMatt/psdm/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Matt Zuo
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: GAC,PFAS,PSDM,activated carbon,adsorption,water treatment
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: numpy>=1.23
|
|
22
|
+
Requires-Dist: pandas>=1.5
|
|
23
|
+
Requires-Dist: scipy>=1.9
|
|
24
|
+
Provides-Extra: excel
|
|
25
|
+
Requires-Dist: openpyxl>=3.0; extra == 'excel'
|
|
26
|
+
Provides-Extra: plot
|
|
27
|
+
Requires-Dist: matplotlib>=3.6; extra == 'plot'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# psdm
|
|
31
|
+
|
|
32
|
+
[](https://github.com/zohoMatt/psdm/actions/workflows/ci.yml)
|
|
33
|
+
[](https://pypi.org/project/psdm/)
|
|
34
|
+
[](https://psdm.readthedocs.io)
|
|
35
|
+
|
|
36
|
+
The **Pore and Surface Diffusion Model (PSDM)** for fixed-bed granular activated carbon (GAC)
|
|
37
|
+
adsorbers, as a small, tested and documented Python package.
|
|
38
|
+
|
|
39
|
+
- Multi-component competitive adsorption (ideal adsorbed solution theory, Freundlich isotherms)
|
|
40
|
+
- Film, pore and surface diffusion with built-in correlations or user-supplied coefficients
|
|
41
|
+
- Natural organic matter fouling for the AdDesignS water types and compound classes, including PFAS
|
|
42
|
+
- Time-varying influent, any time / concentration / flow units
|
|
43
|
+
- Fitting Freundlich `K` and `1/n` to column data; batch isotherm fitting
|
|
44
|
+
- Reader for the US EPA PSDM Excel input template
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install psdm # core
|
|
50
|
+
pip install "psdm[excel]" # + Excel input files
|
|
51
|
+
pip install "psdm[plot]" # + plotting
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import pandas as pd
|
|
58
|
+
import psdm
|
|
59
|
+
|
|
60
|
+
column = psdm.Column.from_units(
|
|
61
|
+
length=(2.765, "m"), diameter=(10, "ft"), mass=(20000, "lb"), flow_rate=(567, "gpm"),
|
|
62
|
+
particle_radius=(0.513, "mm"), particle_density=(0.803, "g/mL"), particle_porosity=0.641,
|
|
63
|
+
)
|
|
64
|
+
tce = psdm.Compound("TCE", mw=131.39, molar_volume=102.0, k=5026.04, n_inv=0.43)
|
|
65
|
+
influent = pd.DataFrame({"TCE": [50.0, 50.0]}, index=[0.0, 174.0]) # days, mg/L
|
|
66
|
+
|
|
67
|
+
result = psdm.simulate(column, tce, influent, conc_unit="mg/L", water="Rhine")
|
|
68
|
+
result.effluent # DataFrame: effluent concentration vs. time
|
|
69
|
+
result([30, 60, 90]) # interpolated at given times
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Reading the EPA Excel template:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from psdm.io import read_excel
|
|
76
|
+
|
|
77
|
+
data = read_excel("Example_Multi.xlsx")
|
|
78
|
+
result = data.simulate(nr=4, nz=8, ne=2)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
See the [documentation](https://psdm.readthedocs.io) for the model description, the full API
|
|
82
|
+
and more examples.
|
|
83
|
+
|
|
84
|
+
## Validation
|
|
85
|
+
|
|
86
|
+
psdm is a rewrite of the original
|
|
87
|
+
[US EPA Python PSDM](https://github.com/USEPA/Water_Treatment_Models/tree/3f514c2/PSDM)
|
|
88
|
+
(commit `3f514c2`). It solves the same model equations: orthogonal-collocation discretisation,
|
|
89
|
+
film, pore and surface diffusion, and the AdDesignS fouling correlations. It integrates them with
|
|
90
|
+
the same ODE method, scipy's BDF solver with the same tolerances and Jacobian sparsity pattern, and
|
|
91
|
+
reproduces the original's results.
|
|
92
|
+
|
|
93
|
+
- **Against the original EPA code.** The comparison covers 11 cases: 7 single-compound AdDesignS
|
|
94
|
+
cases (Rhine, Organic Free and Portage water at 5–50 mg/L), 2 multi-component cases from
|
|
95
|
+
`Example_Multi.xlsx` and 2 time-varying influent cases from `Example_TCE.xlsx`. The largest
|
|
96
|
+
difference anywhere on a breakthrough curve is **0.33 % of the influent concentration C0**, and
|
|
97
|
+
the RMS difference is at most 0.06 % of C0.
|
|
98
|
+
- **Against AdDesignS.** For the 7 single-compound cases with AdDesignS output, psdm stays within
|
|
99
|
+
0.57 % of C0 of AdDesignS. The original EPA code stays within 0.62 %.
|
|
100
|
+
- **Test suite.** The tests check psdm against reference curves generated with the EPA code and
|
|
101
|
+
against the AdDesignS output, with a tolerance of 0.5 % of C0.
|
|
102
|
+
|
|
103
|
+
The case-by-case comparison, with overlaid breakthrough curves, is in
|
|
104
|
+
[`benchmarks/report.html`](benchmarks/report.html) (download it and open it in a browser). It
|
|
105
|
+
is generated by [`scripts/benchmark.py`](scripts/benchmark.py).
|
|
106
|
+
|
|
107
|
+
## Credits
|
|
108
|
+
|
|
109
|
+
This package is a rewrite of the Python PSDM from the US EPA
|
|
110
|
+
[Water Treatment Models](https://github.com/USEPA/Water_Treatment_Models) repository
|
|
111
|
+
(J. Burkhardt, L. Haupert, B. Datsov et al.), which converted the Fortran PSDM in AdDesignS™
|
|
112
|
+
(D.R. Hokanson, D.W. Hand, J.C. Crittenden, T.N. Rogers, E.J. Oman, Michigan Technological
|
|
113
|
+
University) to Python. It is not affiliated with or endorsed by the US EPA or Michigan
|
|
114
|
+
Technological University.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT — see [LICENSE](LICENSE).
|
psdm-0.1.0/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# psdm
|
|
2
|
+
|
|
3
|
+
[](https://github.com/zohoMatt/psdm/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/psdm/)
|
|
5
|
+
[](https://psdm.readthedocs.io)
|
|
6
|
+
|
|
7
|
+
The **Pore and Surface Diffusion Model (PSDM)** for fixed-bed granular activated carbon (GAC)
|
|
8
|
+
adsorbers, as a small, tested and documented Python package.
|
|
9
|
+
|
|
10
|
+
- Multi-component competitive adsorption (ideal adsorbed solution theory, Freundlich isotherms)
|
|
11
|
+
- Film, pore and surface diffusion with built-in correlations or user-supplied coefficients
|
|
12
|
+
- Natural organic matter fouling for the AdDesignS water types and compound classes, including PFAS
|
|
13
|
+
- Time-varying influent, any time / concentration / flow units
|
|
14
|
+
- Fitting Freundlich `K` and `1/n` to column data; batch isotherm fitting
|
|
15
|
+
- Reader for the US EPA PSDM Excel input template
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install psdm # core
|
|
21
|
+
pip install "psdm[excel]" # + Excel input files
|
|
22
|
+
pip install "psdm[plot]" # + plotting
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import pandas as pd
|
|
29
|
+
import psdm
|
|
30
|
+
|
|
31
|
+
column = psdm.Column.from_units(
|
|
32
|
+
length=(2.765, "m"), diameter=(10, "ft"), mass=(20000, "lb"), flow_rate=(567, "gpm"),
|
|
33
|
+
particle_radius=(0.513, "mm"), particle_density=(0.803, "g/mL"), particle_porosity=0.641,
|
|
34
|
+
)
|
|
35
|
+
tce = psdm.Compound("TCE", mw=131.39, molar_volume=102.0, k=5026.04, n_inv=0.43)
|
|
36
|
+
influent = pd.DataFrame({"TCE": [50.0, 50.0]}, index=[0.0, 174.0]) # days, mg/L
|
|
37
|
+
|
|
38
|
+
result = psdm.simulate(column, tce, influent, conc_unit="mg/L", water="Rhine")
|
|
39
|
+
result.effluent # DataFrame: effluent concentration vs. time
|
|
40
|
+
result([30, 60, 90]) # interpolated at given times
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Reading the EPA Excel template:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from psdm.io import read_excel
|
|
47
|
+
|
|
48
|
+
data = read_excel("Example_Multi.xlsx")
|
|
49
|
+
result = data.simulate(nr=4, nz=8, ne=2)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
See the [documentation](https://psdm.readthedocs.io) for the model description, the full API
|
|
53
|
+
and more examples.
|
|
54
|
+
|
|
55
|
+
## Validation
|
|
56
|
+
|
|
57
|
+
psdm is a rewrite of the original
|
|
58
|
+
[US EPA Python PSDM](https://github.com/USEPA/Water_Treatment_Models/tree/3f514c2/PSDM)
|
|
59
|
+
(commit `3f514c2`). It solves the same model equations: orthogonal-collocation discretisation,
|
|
60
|
+
film, pore and surface diffusion, and the AdDesignS fouling correlations. It integrates them with
|
|
61
|
+
the same ODE method, scipy's BDF solver with the same tolerances and Jacobian sparsity pattern, and
|
|
62
|
+
reproduces the original's results.
|
|
63
|
+
|
|
64
|
+
- **Against the original EPA code.** The comparison covers 11 cases: 7 single-compound AdDesignS
|
|
65
|
+
cases (Rhine, Organic Free and Portage water at 5–50 mg/L), 2 multi-component cases from
|
|
66
|
+
`Example_Multi.xlsx` and 2 time-varying influent cases from `Example_TCE.xlsx`. The largest
|
|
67
|
+
difference anywhere on a breakthrough curve is **0.33 % of the influent concentration C0**, and
|
|
68
|
+
the RMS difference is at most 0.06 % of C0.
|
|
69
|
+
- **Against AdDesignS.** For the 7 single-compound cases with AdDesignS output, psdm stays within
|
|
70
|
+
0.57 % of C0 of AdDesignS. The original EPA code stays within 0.62 %.
|
|
71
|
+
- **Test suite.** The tests check psdm against reference curves generated with the EPA code and
|
|
72
|
+
against the AdDesignS output, with a tolerance of 0.5 % of C0.
|
|
73
|
+
|
|
74
|
+
The case-by-case comparison, with overlaid breakthrough curves, is in
|
|
75
|
+
[`benchmarks/report.html`](benchmarks/report.html) (download it and open it in a browser). It
|
|
76
|
+
is generated by [`scripts/benchmark.py`](scripts/benchmark.py).
|
|
77
|
+
|
|
78
|
+
## Credits
|
|
79
|
+
|
|
80
|
+
This package is a rewrite of the Python PSDM from the US EPA
|
|
81
|
+
[Water Treatment Models](https://github.com/USEPA/Water_Treatment_Models) repository
|
|
82
|
+
(J. Burkhardt, L. Haupert, B. Datsov et al.), which converted the Fortran PSDM in AdDesignS™
|
|
83
|
+
(D.R. Hokanson, D.W. Hand, J.C. Crittenden, T.N. Rogers, E.J. Oman, Michigan Technological
|
|
84
|
+
University) to Python. It is not affiliated with or endorsed by the US EPA or Michigan
|
|
85
|
+
Technological University.
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT — see [LICENSE](LICENSE).
|