swatplus-bmi 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.
- swatplus_bmi-0.1.0/.gitignore +9 -0
- swatplus_bmi-0.1.0/CHANGELOG.md +26 -0
- swatplus_bmi-0.1.0/CITATION.cff +31 -0
- swatplus_bmi-0.1.0/CODE_OF_CONDUCT.md +11 -0
- swatplus_bmi-0.1.0/COMPATIBILITY.md +39 -0
- swatplus_bmi-0.1.0/CONTRIBUTING.md +54 -0
- swatplus_bmi-0.1.0/LICENSE +10 -0
- swatplus_bmi-0.1.0/LICENSES/BSD-3-Clause.txt +28 -0
- swatplus_bmi-0.1.0/LICENSES/LGPL-2.1.txt +504 -0
- swatplus_bmi-0.1.0/PKG-INFO +415 -0
- swatplus_bmi-0.1.0/README.md +388 -0
- swatplus_bmi-0.1.0/build.sh +109 -0
- swatplus_bmi-0.1.0/docs/design.md +427 -0
- swatplus_bmi-0.1.0/docs/figures/tour-feedback.png +0 -0
- swatplus_bmi-0.1.0/docs/figures/tour-state.png +0 -0
- swatplus_bmi-0.1.0/docs/figures/tour-tradeoff.png +0 -0
- swatplus_bmi-0.1.0/docs/figures/tour-warmup.png +0 -0
- swatplus_bmi-0.1.0/docs/upstream-issue-aquifer-withdrawal.md +29 -0
- swatplus_bmi-0.1.0/docs/upstream-issue-recall-diversion.md +41 -0
- swatplus_bmi-0.1.0/docs/upstream-issue.md +37 -0
- swatplus_bmi-0.1.0/examples/tour.py +560 -0
- swatplus_bmi-0.1.0/fortran/bmi_exchange_module.f90 +931 -0
- swatplus_bmi-0.1.0/fortran/bmi_fork.c +53 -0
- swatplus_bmi-0.1.0/patches/62.0.1/0001-exchange-mode.patch +102 -0
- swatplus_bmi-0.1.0/patches/62.0.1/carried-locals.toml +12 -0
- swatplus_bmi-0.1.0/pyproject.toml +60 -0
- swatplus_bmi-0.1.0/src/swatplus_bmi/__init__.py +7 -0
- swatplus_bmi-0.1.0/src/swatplus_bmi/bmi.py +333 -0
- swatplus_bmi-0.1.0/src/swatplus_bmi/build.py +109 -0
- swatplus_bmi-0.1.0/src/swatplus_bmi/exchange.py +319 -0
- swatplus_bmi-0.1.0/tests/conftest.py +122 -0
- swatplus_bmi-0.1.0/tests/test_allocation.py +204 -0
- swatplus_bmi-0.1.0/tests/test_branch.py +101 -0
- swatplus_bmi-0.1.0/tests/test_reading.py +99 -0
- swatplus_bmi-0.1.0/tests/test_saved_locals.py +39 -0
- swatplus_bmi-0.1.0/tests/test_setting.py +163 -0
- swatplus_bmi-0.1.0/tests/test_state.py +151 -0
- swatplus_bmi-0.1.0/tests/test_stepping.py +165 -0
- swatplus_bmi-0.1.0/tools/carried_locals.py +90 -0
- swatplus_bmi-0.1.0/tools/gen_serializer.py +345 -0
- swatplus_bmi-0.1.0/tools/reset_saved_locals.py +198 -0
- swatplus_bmi-0.1.0/tools/state_inventory.py +230 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Changes that matter to someone using swatplus-bmi. Versions follow semantic versioning; the
|
|
4
|
+
SWAT+ releases each version supports are in COMPATIBILITY.md.
|
|
5
|
+
|
|
6
|
+
## 0.1.0 (2026-11-04)
|
|
7
|
+
|
|
8
|
+
First release, for SWAT+ 62.0.1.
|
|
9
|
+
|
|
10
|
+
- Exchange mode for SWAT+, off unless started with `--exchange`: SWAT+ pauses before each day
|
|
11
|
+
and takes commands on standard input. Six calls in three SWAT+ files, one Fortran module, and
|
|
12
|
+
a C helper for branching (Mac, Linux).
|
|
13
|
+
- Python BMI 2.0 wrapper (`SwatPlusBmi`): one-day steps, time in days since the start date, one
|
|
14
|
+
grid of points per object type, CSDMS-style names.
|
|
15
|
+
- Reading: channel outflow, inflow and storage; aquifer storage, depth to water, outflow and
|
|
16
|
+
recharge; point source flow; water allocation demand and withdrawal.
|
|
17
|
+
- Setting, for the next day: point source flow, water allocation demand.
|
|
18
|
+
- Snapshots:
|
|
19
|
+
- `branch()` forks the paused process (Mac, Linux);
|
|
20
|
+
- `save_state`/`load_state` and `get_state`/`set_state` work on every platform, with the
|
|
21
|
+
serializer generated from SWAT+'s module declarations;
|
|
22
|
+
- saved locals that carry state are listed per release and saved too.
|
|
23
|
+
- `swatplus-bmi build` fetches, patches and builds SWAT+ from an installed package.
|
|
24
|
+
- Tests against unpatched SWAT+: every output file byte for byte, every variable against SWAT+'s
|
|
25
|
+
daily output, water balances, branching and saving against unbroken runs.
|
|
26
|
+
- Example marimo notebook (`examples/tour.py`).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use swatplus-bmi in your work, please cite it as below."
|
|
3
|
+
title: "swatplus-bmi: stepping the SWAT+ watershed model one day at a time through the Basic Model Interface"
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: Sommerlot
|
|
7
|
+
given-names: Andrew
|
|
8
|
+
affiliation: Northline Hydrology
|
|
9
|
+
# orcid: https://orcid.org/0000-0000-0000-0000
|
|
10
|
+
version: 0.1.0
|
|
11
|
+
license:
|
|
12
|
+
- BSD-3-Clause
|
|
13
|
+
- LGPL-2.1-only
|
|
14
|
+
repository-code: "https://github.com/northlinehydrology/swatplus-bmi"
|
|
15
|
+
keywords:
|
|
16
|
+
- hydrology
|
|
17
|
+
- watershed modeling
|
|
18
|
+
- SWAT+
|
|
19
|
+
- Basic Model Interface
|
|
20
|
+
- BMI
|
|
21
|
+
- model coupling
|
|
22
|
+
references:
|
|
23
|
+
- type: article
|
|
24
|
+
title: "Introduction to SWAT+, a completely restructured version of the Soil and Water Assessment Tool"
|
|
25
|
+
authors:
|
|
26
|
+
- family-names: Bieger
|
|
27
|
+
given-names: Katrin
|
|
28
|
+
- name: "and others"
|
|
29
|
+
journal: "Journal of the American Water Resources Association"
|
|
30
|
+
year: 2017
|
|
31
|
+
doi: 10.1111/1752-1688.12482
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Code of conduct
|
|
2
|
+
|
|
3
|
+
This project follows the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
4
|
+
|
|
5
|
+
In short: be respectful and constructive, assume good faith, and keep discussion about the
|
|
6
|
+
work. Harassment and personal attacks aren't tolerated in issues, pull requests or any other
|
|
7
|
+
project space.
|
|
8
|
+
|
|
9
|
+
Report a problem to the maintainer, Andrew Sommerlot, at andrew@northlinehydrology.com. Reports
|
|
10
|
+
are kept confidential. The maintainer will respond, and may warn, suspend or remove anyone who
|
|
11
|
+
doesn't follow this code, as the Contributor Covenant's enforcement guidelines describe.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SWAT+ versions
|
|
2
|
+
|
|
3
|
+
swatplus-bmi patches a specific SWAT+ release. A version is supported only if
|
|
4
|
+
it has a folder in `patches/` and passes the full test suite. `build.sh`
|
|
5
|
+
refuses any other version.
|
|
6
|
+
|
|
7
|
+
| SWAT+ | Released | Status | Tested on |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| 62.0.1 | 2026-10-19 | **Supported** | CI on every push: Ubuntu (gfortran from apt) and macOS 14 (Homebrew gcc). Locally: macOS 14 arm64, gfortran 16.1. |
|
|
10
|
+
| main | rolling | Watched: built and tested nightly with the 62.0.1 patch, as an early warning. Not supported. | nightly build |
|
|
11
|
+
| 62.0.0 | 2026-06-18 | Not supported: the patch doesn't apply (`time_control.f90` differs) | — |
|
|
12
|
+
| 61.x and earlier | 2024–2026 | Not supported: no water allocation places of use, and the patch doesn't apply | — |
|
|
13
|
+
|
|
14
|
+
Checked Nov 4, 2026: the patch applies unchanged to SWAT+ main as of commit
|
|
15
|
+
6f51536 (Oct 16, 2026). `time_control.f90`, `command.f90` and `main.f90.in`
|
|
16
|
+
are identical to 62.0.1 there.
|
|
17
|
+
|
|
18
|
+
## How SWAT+ versions work
|
|
19
|
+
|
|
20
|
+
SWAT+ numbers its releases by model revision (the "Revision" line in
|
|
21
|
+
`simulation.out`), not semantic versioning: the 60.x series came before 61.x,
|
|
22
|
+
and 62 is the current series. Full releases are infrequent: 61.0.1 (Jul 2024),
|
|
23
|
+
61.0.2 (Aug 2024), 62.0.0 (Jun 2026), 62.0.1 (Oct 2026). Between them the
|
|
24
|
+
SWAT+ team tags prereleases (twelve 61.0.2.x tags, Nov 2024 to Jan 2026),
|
|
25
|
+
and the main branch takes merged pull requests continuously.
|
|
26
|
+
|
|
27
|
+
## Policy
|
|
28
|
+
|
|
29
|
+
- Each supported release gets its own `patches/<tag>/` folder. A new SWAT+
|
|
30
|
+
release is added when the patch is moved onto it and the full suite
|
|
31
|
+
passes, including the byte-for-byte comparisons with stock SWAT+.
|
|
32
|
+
- Only full releases are supported, not prereleases or main.
|
|
33
|
+
- The nightly build tests main with the newest supported patch. When it
|
|
34
|
+
fails, a new SWAT+ release is likely to need a new patch.
|
|
35
|
+
- An older release stays supported as long as its patch still builds and
|
|
36
|
+
passes. It isn't fixed for new features.
|
|
37
|
+
- If the exchange mode is merged into SWAT+ itself, the patch is no longer
|
|
38
|
+
needed from that release on, and this table records which SWAT+ release
|
|
39
|
+
has it built in.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
swatplus-bmi is meant to be used in studies whose results feed public decisions about water,
|
|
4
|
+
so a change has to keep the one promise the project makes: **SWAT+ stepped, branched or loaded
|
|
5
|
+
through swatplus-bmi gives exactly the output SWAT+ gives on its own.** Every rule below follows
|
|
6
|
+
from that.
|
|
7
|
+
|
|
8
|
+
## Ways to contribute
|
|
9
|
+
|
|
10
|
+
- **Report a bug.** Open an issue with the SWAT+ version, your platform and compiler, what you
|
|
11
|
+
ran, and what happened. A SWAT+ project that shows the problem is the most useful thing you
|
|
12
|
+
can attach.
|
|
13
|
+
- **Share a test project.** The tests run on the two example projects that ship with SWAT+, and
|
|
14
|
+
those exercise about half of SWAT+'s code. A project that uses reservoirs, pesticides, salts,
|
|
15
|
+
gwflow or calibration, and can be made public, would widen the tests more than anything else.
|
|
16
|
+
- **Ask for a variable.** Say what you want to read or set, which SWAT+ variable holds it, and
|
|
17
|
+
what you'd check it against.
|
|
18
|
+
- **Pull requests** are welcome for fixes, variables, tests and documentation. For a larger
|
|
19
|
+
change (a new SWAT+ release, a protocol change), open an issue first.
|
|
20
|
+
- **Questions:** open an issue with the `question` label.
|
|
21
|
+
|
|
22
|
+
## Rules for changes
|
|
23
|
+
|
|
24
|
+
1. **Identical output.** The comparison tests against unpatched SWAT+ must pass. If a change
|
|
25
|
+
can't keep SWAT+'s output identical, it doesn't go in.
|
|
26
|
+
2. **A test for every variable.** A new variable is checked against SWAT+'s own output files,
|
|
27
|
+
every day, in `tests/test_reading.py` or `tests/test_setting.py`.
|
|
28
|
+
3. **Only fluxes can be set.** Storage, land use, soils and parameters stay scenario inputs.
|
|
29
|
+
4. **The patch stays small.** Changes to SWAT+'s own files go in `patches/<tag>/`, and as few as
|
|
30
|
+
possible. Everything else goes in new files in `fortran/`.
|
|
31
|
+
5. **Generated code is generated.** Don't edit `bmi_state_module.f90` or `bmi_locals_module.f90`;
|
|
32
|
+
change the generators in `tools/`.
|
|
33
|
+
6. **A new SWAT+ release** gets its own `patches/<tag>/` folder, a `carried-locals.toml` checked
|
|
34
|
+
with `build.sh --nosave` and `pytest -m full`, and a line in COMPATIBILITY.md.
|
|
35
|
+
7. **Plain writing.** Documentation and comments say what the code does and why, plainly.
|
|
36
|
+
|
|
37
|
+
## Running the checks
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv sync
|
|
41
|
+
uv run ./build.sh --stock --nosave
|
|
42
|
+
uv run pytest # about two minutes
|
|
43
|
+
uv run pytest -m full # about fifteen minutes more
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Conduct
|
|
47
|
+
|
|
48
|
+
Everyone taking part follows the [code of conduct](CODE_OF_CONDUCT.md).
|
|
49
|
+
|
|
50
|
+
## License of contributions
|
|
51
|
+
|
|
52
|
+
Contributions to `fortran/` and `patches/` are under the GNU LGPL 2.1, like SWAT+. Everything
|
|
53
|
+
else is under the BSD 3-Clause license. By opening a pull request you agree to license your
|
|
54
|
+
contribution that way.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
swatplus-bmi is under two licenses.
|
|
2
|
+
|
|
3
|
+
- fortran/ and patches/ (the exchange mode added to SWAT+) and any SWAT+
|
|
4
|
+
built with them: GNU Lesser General Public License, version 2.1, the
|
|
5
|
+
license of SWAT+ itself. See LICENSES/LGPL-2.1.txt.
|
|
6
|
+
|
|
7
|
+
- Everything else, including the Python wrapper in src/swatplus_bmi/, the
|
|
8
|
+
tests, tools and documentation: BSD 3-Clause. See LICENSES/BSD-3-Clause.txt. The wrapper is
|
|
9
|
+
a separate program: it starts SWAT+ as its own process and talks to it
|
|
10
|
+
over standard input and output, and is not linked with it.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Andrew Sommerlot
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|