Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to v2 pre-release #312

Merged
merged 62 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
52bfc28
allow disconnected nodes in flowgraph
jmccreight Sep 4, 2024
8bcf362
move python versions forward, pin setuptools because of issue
jmccreight Sep 5, 2024
e953e14
move python versions forward, pin setuptools because of issue, xfail …
jmccreight Sep 5, 2024
7e49bb3
update env to match pyproject
jmccreight Sep 5, 2024
0cc98bb
enhance flow graph tests, add ci_local.sh
jmccreight Sep 9, 2024
ab73962
update ci_local
jmccreight Sep 9, 2024
0de2486
add arrowhead lake pic
jmccreight Sep 19, 2024
f643e5d
extra coordinates in netcdf output
jmccreight Sep 23, 2024
223994d
fix mmr to dfw, renaming swf to chf; some other pyproject and env fixes
jmccreight Sep 26, 2024
767d498
lint
jmccreight Sep 26, 2024
9eefbb9
fix StarfitFlowNode to return scalars but track np 1d arrays internal…
jmccreight Sep 30, 2024
692608b
remove unused dependence
jmccreight Sep 30, 2024
c7da527
update python version for rtd builds; setup-micromamba/issues/225 pin…
jmccreight Sep 30, 2024
8e46ee7
setup-micromamba/issues/225 pinning attempt 2
jmccreight Sep 30, 2024
6399471
setup-micromamba/issues/225 pinning attempt 3
jmccreight Sep 30, 2024
668684b
setup-micromamba/issues/225 pinning attempt 4
jmccreight Sep 30, 2024
9baa0f3
disable mf6 related tests pending fix of install-modflow-action
jmccreight Sep 30, 2024
2b6c260
setup-micromamba/issues/225 pinning for ci_examples.yaml
jmccreight Oct 1, 2024
a5ddbf3
update notebook 06
jmccreight Oct 1, 2024
c34273e
refactor for changes in pyPRMS
jmccreight Oct 1, 2024
5db46ff
micromamba-version: 1.5.10-0
jmccreight Oct 7, 2024
bbd070f
comment check against MF6 output
jmccreight Oct 7, 2024
809b45b
details of outputing FlowGraph coordinates
jmccreight Oct 7, 2024
f1249fd
add new notebook 06 details
jmccreight Oct 7, 2024
8b3d96b
little linting
jmccreight Oct 7, 2024
3f6242b
node_maker_id missed in a few tests; bring back MF6 binary install
jmccreight Oct 7, 2024
173913d
update to pyPRMS new API for data files
jmccreight Oct 8, 2024
5056023
clean up extra_coords/string/chararray coordinate outputs for flow graph
jmccreight Oct 8, 2024
9a63115
regression means
jmccreight Oct 17, 2024
eed30d3
update notebook 06; add notebook 07
jmccreight Oct 17, 2024
8c5c55d
update rtd yaml python version
jmccreight Oct 17, 2024
f98f7ae
suppress warnings temporarily in CI
jmccreight Oct 17, 2024
9b1183c
suppress warnings temporarily in CI part 2
jmccreight Oct 17, 2024
8442785
suppress warnings temporarily in CI part 3, ci yaml work
jmccreight Oct 17, 2024
1e0e354
suppress warnings temporarily in CI part 4, pathlib detail
jmccreight Oct 17, 2024
2b3452a
suppress warnings temporarily in CI part 5, ci errors with env vars
jmccreight Oct 17, 2024
1763176
suppress warnings temporarily in CI part 6, ipython dosent take -W
jmccreight Oct 17, 2024
c02941b
Merge pull request #307 from jmccreight/feat_swf
jmccreight Oct 18, 2024
f18fe4f
pws 2 review fixes
jmccreight Oct 18, 2024
b29a899
merge upstream/develop
jmccreight Oct 18, 2024
7612552
FlowGraph capability to cull additional, heterogeneous variables from…
jmccreight Oct 19, 2024
e3d4001
prms_channel_flow_graph _postprocess and _model_dict both handle new …
jmccreight Oct 22, 2024
b878c37
rename ObsInNode -> ObsInFlowNode and PassThroughNode -> PassThroughF…
jmccreight Oct 22, 2024
582b030
fix renaming to ObsInFlowNode in notebook 06
jmccreight Oct 23, 2024
d8e7881
fix renaming to ObsInFlowNode in notebook 06, part 2
jmccreight Oct 24, 2024
e566244
Merge pull request #306 from jmccreight/feat_flow_dag
jmccreight Oct 24, 2024
95cfaa3
inital numpy2 migration
jmccreight Oct 24, 2024
1220ee4
merge upstream/develop
jmccreight Oct 24, 2024
b00d11b
numpy2 fix for converting column 0 of PRMS csv files
jmccreight Oct 25, 2024
cc63680
update environment.yml
jmccreight Oct 25, 2024
f3c292a
numpy 2: fix errors, warnings, and additional warnings
jmccreight Oct 25, 2024
abd4b79
fix error and warnings in notebook 07
jmccreight Oct 26, 2024
2920c8f
Merge pull request #310 from jmccreight/feat_numpy_2.0
jmccreight Oct 26, 2024
1151d8c
stop testing Fortran code; xml output for domainless tests
jmccreight Oct 28, 2024
1711c82
touch up some FlowGraph docs and notebook 06
jmccreight Oct 29, 2024
f5a0b23
lint up some E501s
jmccreight Oct 29, 2024
593f7b6
final update of notebooks
jmccreight Nov 11, 2024
ff674c3
Merge pull request #311 from jmccreight/feat_flow_dag
jmccreight Nov 12, 2024
50a45eb
merge upstream/develop into feat_3099
jmccreight Nov 12, 2024
b6df066
fix bad merge
jmccreight Nov 12, 2024
87129c2
fix bad merge some more
jmccreight Nov 12, 2024
f632b16
remove incomplete cascading flow notebook.
jmccreight Nov 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install wheel build 'twine<5.0.0' 'importlib_metadata<=7.0.1' 'setuptools<=72.2.0' 'numpy<2.0'

- name: Base installation
run: |
pip --verbose install .
Expand Down Expand Up @@ -124,8 +123,7 @@ jobs:
- name: Set environment variables
run: |
echo "PYTHON_VERSION=${{ matrix.python-version }}" >> $GITHUB_ENV
echo "PYWS_FORTRAN=true" >> $GITHUB_ENV
echo 'SETUPTOOLS_ENABLE_FEATURES="legacy-editable"' >> $GITHUB_ENV
echo "PYWS_FORTRAN=false" >> $GITHUB_ENV
cat .mf6_ci_ref_remote >> $GITHUB_ENV

- name: Enforce MF6 ref and remote merge to main
Expand All @@ -150,8 +148,9 @@ jobs:
run: .github/scripts/symlink_gfortran_mac.sh

- name: Install Dependencies via Micromamba
uses: mamba-org/setup-micromamba@v1
uses: mamba-org/setup-micromamba@v1.9.0
with:
micromamba-version: '1.5.10-0'
log-level: debug
environment-file: environment.yml
cache-environment: true
Expand Down Expand Up @@ -191,7 +190,14 @@ jobs:

- name: domainless - run tests not requiring domain data
working-directory: autotest
run: pytest -m domainless -n=auto -vv
run: pytest
-m domainless
-n=auto
-vv
--durations=0
--cov=pywatershed
--cov-report=xml
--junitxml=pytest_domainless.xml

- name: sagehen_5yr_no_cascades - generate and manage test data domain, run PRMS and convert csv output to NetCDF
working-directory: autotest
Expand Down
20 changes: 19 additions & 1 deletion .github/workflows/ci_examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,30 @@ jobs:
echo "SETUPTOOLS_ENABLE_FEATURES=legacy-editable" >> $GITHUB_ENV

- name: Setup micromamba
uses: mamba-org/setup-micromamba@v1
uses: mamba-org/setup-micromamba@v1.9.0
with:
micromamba-version: '1.5.10-0'
environment-file: environment.yml
cache-environment: true
cache-downloads: true

- name: Checkout MODFLOW 6
uses: actions/checkout@v4
with:
repository: MODFLOW-USGS/modflow6
ref: develop
path: modflow6

- name: Update flopy MODFLOW 6 classes
working-directory: modflow6/autotest
run: |
python update_flopy.py

- name: Install mf6 nightly build binaries
uses: modflowpy/install-modflow-action@v1
with:
repo: modflow6-nightly-build

- name: Install error reporter
run: |
pip install pytest-github-actions-annotate-failures
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pywatershed/badges/version.svg)](https://anaconda.org/conda-forge/pywatershed)
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pywatershed/badges/platforms.svg)](https://anaconda.org/conda-forge/pywatershed)

[![DOI:10.5066/P9AVWA7Z](https://img.shields.io/badge/DOI-10.5066/P9AVWA7Z-b4a9fe.svg)](https://doi.org/10.5066/P9AVWA7Z)

[![WholeTale](https://raw.githubusercontent.com/whole-tale/wt-design-docs/master/badges/wholetale-explore.svg)](https://dashboard.wholetale.org/run/64ae29e8a887f48b9f173678?tab=metadata)


Expand All @@ -24,6 +26,7 @@
- [Installation](#installation)
- [Getting started / Example notebooks](#getting-started--example-notebooks)
- [Community engagement](#community-engagement)
- [How to Cite](#how-to-cite)
- [Disclaimer](#disclaimer)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
Expand Down Expand Up @@ -149,6 +152,8 @@ guidelines.

Thank you for your interest.

## How to Cite
McCreight, J., Langevin, C. D., & Hughes, J. D. (2023). pywatershed (Version 1.0.0) [Computer software]. [https://doi.org/10.5066/P9AVWA7Z](https://doi.org/10.5066/P9AVWA7Z)

## Disclaimer

Expand Down
61 changes: 36 additions & 25 deletions autotest/test_mmr_to_mf6_dfw.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
# Getting the gis files causes problems in parallel in CI. See regression test.

# See below to check if these answers are still up-to-date with
# mf6/autotest/test_swf_dfw.py
# mf6/autotest/test_chf_dfw.py
# Note the answers are from the binary FLW files in
# mf6/autotest/test_swf_dfw.py, if you switch to text files, the line should be
# mf6/autotest/test_chf_dfw.py, if you switch to text files, the line should be
# flw_list = [
# (int(binary), 100),
# ] # one-based cell numbers here if binary, zero-based if text

answers_swf_dfw = {
answers_chf_dfw = {
"ia": np.array([0, 2, 5, 7]),
"ja": np.array([0, 1, 1, 0, 2, 2, 1], dtype=np.int32),
"stage": np.array([[[[1.00196123, 1.00003366, 1.0]]]]),
Expand Down Expand Up @@ -52,9 +52,9 @@
@pytest.mark.skipif(mf6_bin_unavailable, reason="mf6 binary not available")
@pytest.mark.domainless
@pytest.mark.parametrize("binary_flw", [True, False])
def test_mmr_to_mf6_swf_dfw(tmp_path, binary_flw):
def test_mmr_to_mf6_chf_dfw(tmp_path, binary_flw):
# The point of this test is to reproduce the
# modflow6/autotest/test_swf_dfw.py
# modflow6/autotest/test_chf_dfw.py

# Here we supply "seg_mid_elevation" in the parameter data and
# "stress_period_data" in chd options. This bypasses the calculation of
Expand All @@ -68,8 +68,8 @@ def test_mmr_to_mf6_swf_dfw(tmp_path, binary_flw):
# stream segments, the other is about the units of volume/flow being in
# cubicfeet.

name = "swf-dfw01"
output_dir = tmp_path / "test_swf_dfw01"
name = "chf-dfw01"
output_dir = tmp_path / "test_chf_dfw01"
save_flows = True
print_flows = True

Expand Down Expand Up @@ -123,16 +123,16 @@ def test_mmr_to_mf6_swf_dfw(tmp_path, binary_flw):
# vertices could also be supplied by shapefiles
vertices = []
vertices = [[j, j * dx, 0.0] for j in range(nreach + 1)]
cell2d = []
cell1d = []
for j in range(nreach):
cell2d.append([j, 0.5, 2, j, j + 1])
nodes = len(cell2d)
cell1d.append([j, 0.5, 2, j, j + 1])
nodes = len(cell1d)
nvert = len(vertices)
disv1d_options = {
"nodes": nodes,
"nvert": nvert,
"vertices": vertices,
"cell2d": cell2d,
"cell1d": cell1d,
}

# dfw
Expand Down Expand Up @@ -191,9 +191,14 @@ def test_mmr_to_mf6_swf_dfw(tmp_path, binary_flw):
else:
flw_vol = 0.0

# <
time_coord_data = np.array([control.start_time]).astype(
"datetime64[ns]"
)

_ = xr.Dataset(
coords=dict(
time=np.array([control.start_time]),
time=time_coord_data,
nsegment=params.parameters["seg_id"],
),
data_vars={
Expand Down Expand Up @@ -246,26 +251,30 @@ def test_mmr_to_mf6_swf_dfw(tmp_path, binary_flw):
# Checks
assert success

# one can verify the answers match the current mf6 results for test_swf_dfw
# by placing the path to its output here
# one can verify the answers match the current mf6 results for test_chf_dfw
# by placing the path to its output here. Run the following lines to
# generate the mf6 results:
# cd modflow6_for_pws_ci/autotest # or your mf6 repo location
# pytest -s -vv test_chf_dfw.py --keep=keepers
# output_dir = pl.Path(
# "../../modflow6/autotest/keepers/test_mf6model[0-swf-dfw01]0"
# "../../modflow6_for_pws_ci/autotest/keepers/"
# "test_mf6model[0-chf-dfw01]0"
# )

# check binary grid file
grb = flopy.mf6.utils.MfGrdFile(output_dir / f"{name}.disv1d.grb")
ia = grb.ia
ja = grb.ja
assert (answers_swf_dfw["ia"] == ia).all()
assert (answers_swf_dfw["ja"] == ja).all()
assert (answers_chf_dfw["ia"] == ia).all()
assert (answers_chf_dfw["ja"] == ja).all()
assert ia.shape[0] == grb.nodes + 1, "ia in grb file is not correct size"

# check stage file
qobj = flopy.utils.HeadFile(
output_dir / f"{name}.stage", precision="double", text="STAGE"
)
stage = qobj.get_alldata()
assert ((answers_swf_dfw["stage"] - stage) < 1.0e-7).all()
assert ((answers_chf_dfw["stage"] - stage) < 1.0e-7).all()

# read the budget file
budobj = flopy.utils.binaryfile.CellBudgetFile(output_dir / f"{name}.bud")
Expand All @@ -275,17 +284,17 @@ def test_mmr_to_mf6_swf_dfw(tmp_path, binary_flw):
qchd = np.array(budobj.get_data(text="CHD")[0].tolist()[0])
qresidual = np.zeros(grb.nodes)[0]

assert (answers_swf_dfw["flowja"] - flowja < 1.0e-7).all()
assert (answers_swf_dfw["qstorage"] - qstorage < 1.0e-7).all()
assert (answers_swf_dfw["qflw"] - qflw < 1.0e-7).all()
assert (answers_swf_dfw["qchd"] - qchd < 1.0e-7).all()
assert (answers_swf_dfw["qresidual"] - qresidual < 1.0e-7).all()
assert (answers_chf_dfw["flowja"] - flowja < 1.0e-7).all()
assert (answers_chf_dfw["qstorage"] - qstorage < 1.0e-7).all()
assert (answers_chf_dfw["qflw"] - qflw < 1.0e-7).all()
assert (answers_chf_dfw["qchd"] - qchd < 1.0e-7).all()
assert (answers_chf_dfw["qresidual"] - qresidual < 1.0e-7).all()


# <
answers_regression_means = {
"stage_all": 1.03667372881148,
"flow_all": 44.685014111989425,
"stage_all": 1.0372047024253908,
"flow_all": 44.70210250910929,
}


Expand Down Expand Up @@ -406,6 +415,7 @@ def test_mmr_to_mf6_dfw_regression(simulation, tmp_path):
inflow_dir=inflow_dir,
)

dfw.write()
success, buff = dfw.run(silent=False, report=True)
assert success

Expand Down Expand Up @@ -468,4 +478,5 @@ def get_outflow(itime):

for kk, vv in answers_regression_means.items():
abs_diff = abs(locals()[kk].mean() - vv)

assert abs_diff < 1e-5, f"results for {kk} are not close"
17 changes: 13 additions & 4 deletions autotest/test_obsin_flow_node.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import numpy as np
import pytest
from pyPRMS import Streamflow as PRMSStreamflowData
from pyPRMS import DataFile as PRMSStreamflowData

from pywatershed import PRMSChannel
from pywatershed.base.adapter import Adapter, AdapterNetcdf, adapter_factory
from pywatershed.base.control import Control
from pywatershed.base.flow_graph import FlowGraph
from pywatershed.base.parameters import Parameters
from pywatershed.constants import nan, zero
from pywatershed.hydrology.obsin_node import ObsInNodeMaker
from pywatershed.hydrology.obsin_flow_node import ObsInFlowNodeMaker
from pywatershed.hydrology.prms_channel_flow_graph import (
HruSegmentFlowAdapter,
PRMSChannelFlowNodeMaker,
Expand Down Expand Up @@ -68,7 +68,13 @@ def test_prms_channel_obsin_compare_prms(
)
control_parameters = PrmsParameters.load(control_param_file)
obsout_seg = control_parameters.parameters["obsout_segment"] - 1
sf_data = PRMSStreamflowData(simulation["dir"] / "sf_data").data
sf_data = PRMSStreamflowData(
simulation["dir"] / "sf_data"
).data_by_variable("runoff")
old_names = sf_data.columns.tolist()
new_names = [cc.split("_")[1] for cc in sf_data.columns.tolist()]
sf_data.rename(columns=dict(zip(old_names, new_names)), inplace=True)

poi_inds = obsout_seg[np.where(obsout_seg >= 0)].tolist()
npoi = len(poi_inds)
poi_ids = discretization_prms.parameters["poi_gage_id"][(poi_inds),]
Expand Down Expand Up @@ -119,13 +125,14 @@ def advance(self) -> None:
"prms_channel": PRMSChannelFlowNodeMaker(
discretization_prms, parameters_prms
),
"obsin": ObsInNodeMaker(obsin_params, obsin_data),
"obsin": ObsInFlowNodeMaker(obsin_params, obsin_data),
}
nnodes = parameters_prms.dims["nsegment"] + npoi
node_maker_name = ["prms_channel"] * nnodes
node_maker_name[-npoi:] = ["obsin"] * npoi
node_maker_index = np.arange(nnodes)
node_maker_index[-npoi:] = np.arange(npoi)
node_maker_id = np.arange(nnodes)
to_graph_index = np.zeros(nnodes, dtype=np.int64)
dis_params = discretization_prms.parameters
to_graph_index[0:-npoi] = dis_params["tosegment"] - 1
Expand Down Expand Up @@ -171,12 +178,14 @@ def advance(self) -> None:
data_vars={
"node_maker_name": node_maker_name,
"node_maker_index": node_maker_index,
"node_maker_id": node_maker_id,
"to_graph_index": to_graph_index,
},
metadata={
"nnodes": {"dims": ["nnodes"]},
"node_maker_name": {"dims": ["nnodes"]},
"node_maker_index": {"dims": ["nnodes"]},
"node_maker_id": {"dims": ["nnodes"]},
"to_graph_index": {"dims": ["nnodes"]},
},
validate=True,
Expand Down
14 changes: 10 additions & 4 deletions autotest/test_pass_through_flow_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
from pywatershed.base.model import Model
from pywatershed.base.parameters import Parameters
from pywatershed.constants import nan, zero
from pywatershed.hydrology.pass_through_node import PassThroughNodeMaker
from pywatershed.hydrology.pass_through_flow_node import (
PassThroughFlowNodeMaker,
)
from pywatershed.hydrology.prms_channel_flow_graph import (
HruSegmentFlowAdapter,
PRMSChannelFlowNodeMaker,
Expand Down Expand Up @@ -63,8 +65,10 @@ def parameters_flow_graph(parameters_prms, discretization_prms):
nnodes = parameters_prms.dims["nsegment"] + 1
node_maker_name = ["prms_channel"] * nnodes
node_maker_name[-1] = "pass_throughs"
node_maker_name = np.array(node_maker_name, dtype="U")
node_maker_index = np.arange(nnodes)
node_maker_index[-1] = 0
node_maker_id = np.arange(nnodes)
to_graph_index = np.zeros(nnodes, dtype=np.int64)
dis_params = discretization_prms.parameters
to_graph_index[0:-1] = dis_params["tosegment"] - 1
Expand All @@ -77,11 +81,11 @@ def parameters_flow_graph(parameters_prms, discretization_prms):
)
# have to map to the graph from an index found in prms_channel
wh_intervene_above_graph = np.where(
(np.array(node_maker_name) == "prms_channel")
(node_maker_name == "prms_channel")
& (node_maker_index == wh_intervene_above_nhm[0][0])
)
wh_intervene_below_graph = np.where(
(np.array(node_maker_name) == "prms_channel")
(node_maker_name == "prms_channel")
& np.isin(node_maker_index, wh_intervene_below_nhm)
)

Expand All @@ -98,12 +102,14 @@ def parameters_flow_graph(parameters_prms, discretization_prms):
data_vars={
"node_maker_name": node_maker_name,
"node_maker_index": node_maker_index,
"node_maker_id": node_maker_id,
"to_graph_index": to_graph_index,
},
metadata={
"node_coord": {"dims": ["nnodes"]},
"node_maker_name": {"dims": ["nnodes"]},
"node_maker_index": {"dims": ["nnodes"]},
"node_maker_id": {"dims": ["nnodes"]},
"to_graph_index": {"dims": ["nnodes"]},
},
validate=True,
Expand All @@ -117,7 +123,7 @@ def node_maker_dict(parameters_prms, discretization_prms):
"prms_channel": PRMSChannelFlowNodeMaker(
discretization_prms, parameters_prms
),
"pass_throughs": PassThroughNodeMaker(),
"pass_throughs": PassThroughFlowNodeMaker(),
}


Expand Down
Loading
Loading