Skip to content

Commit

Permalink
feat(GWE, PRT): updates for GWE and PRT support
Browse files Browse the repository at this point in the history
  • Loading branch information
jlarsen-usgs authored Aug 21, 2024
2 parents 31ec761 + 166d8b6 commit 5193948
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 27 deletions.
32 changes: 28 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,16 @@ jobs:
shell: bash
steps:
- name: Checkout repo
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Checkout mf6-examples
uses: actions/checkout@v4
with:
repository: MODFLOW-USGS/modflow6-examples
path: modflow6-examples

- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
Expand All @@ -190,15 +196,33 @@ jobs:
python -m pip install --upgrade pip
pip install git+https://[email protected]/Deltares/xmipy@develop
pip install git+https://[email protected]/MODFLOW-USGS/modflow-devtools@develop
pip install git+https://[email protected]/modflowpy/flopy@develop
pip install .[test]

- name: update flopy for mf6-examples
run: |
get-modflow :flopy
python -m flopy.mf6.utils.generate_classes --ref develop --no-backup
- name: Install modflow6 for modflow6-examples
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/modflow6-examples/autotest

- name: Build mf6-examples
working-directory: modflow6-examples/autotest
run: |
pytest -v -n=auto --init test_scripts.py
- name: Install modflow6 nightly build
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
repo: modflow6-nightly-build

- name: Run autotests
working-directory: ./autotest
shell: bash -l {0}
run: pytest -v -n auto -m "mf6 and not extensions"
run: pytest -v -n=auto test_mf6_examples.py --mf6-examples-path=../modflow6-examples/examples
39 changes: 33 additions & 6 deletions autotest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,37 @@ def get_mf6_examples_path() -> Path:
__mf6_examples_lock.release()


def pytest_addoption(parser):
parser.addoption("--mf6-examples-path", action="store", default=None)


def is_nested(namfile) -> bool:
p = Path(namfile)
if not p.is_file() or not p.name.endswith(".nam"):
raise ValueError(f"Expected a namfile path, got {p}")

return p.parent.parent.name != __mf6_examples


def pytest_generate_tests(metafunc):
# examples to skip:
# - ex-gwtgwt-mt3dms-p10: https://github.com/MODFLOW-USGS/modflow6/pull/1008
exclude = ["ex-gwt-gwtgwt-mt3dms-p10"]
option_value = metafunc.config.option.mf6_examples_path
t = metafunc.fixturenames
if (
"mf6_example_namfiles" in metafunc.fixturenames
and option_value is not None
):
mf6_examples_path = Path(option_value)
global __mf6_examples
__mf6_examples = str(mf6_examples_path.name)
else:
mf6_examples_path = get_mf6_examples_path()

# grouping...
exclude = ["ex-gwt-gwtgwt-mt3dms-p10", "mp7-p02", "mp7-p04"]
namfiles = [
str(p)
for p in get_mf6_examples_path().rglob("mfsim.nam")
for p in mf6_examples_path.rglob("mfsim.nam")
if not any(e in str(p) for e in exclude)
]

Expand All @@ -72,9 +88,20 @@ def simulation_name_from_model_path(p):
for model_name, model_namfiles in groupby(
namfiles, key=simulation_name_from_model_path
):
models = sorted(
list(model_namfiles)
) # sort in alphabetical order (gwf < gwt)
models = []
model_namfiles = list(model_namfiles)
if len(model_namfiles) > 1:
# trap gwf models as first set of models
idxs = [
ix for ix, _ in enumerate(model_namfiles) if "gwf" in _
]
if len(idxs) > 0:
for ix in idxs[::-1]:
models.append(model_namfiles.pop(ix))

models += list(
sorted(model_namfiles)
) # sort remaining models in alphabetical order (gwe < gwt < prt)
simulations.append(models)
print(
f"Simulation {model_name} has {len(models)} model(s):\n"
Expand Down
6 changes: 5 additions & 1 deletion modflowapi/extensions/apiexchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@ class ApiExchange(ApiMbase):
"""

def __init__(self, mf6, name):
pkg_types = {"gwf-gwf": ListPackage, "gwt-gwt": ListPackage}
pkg_types = {
"gwf-gwf": ListPackage,
"gwt-gwt": ListPackage,
"gwe-gwe": ListPackage,
}
super().__init__(mf6, name, pkg_types)
9 changes: 8 additions & 1 deletion modflowapi/extensions/apimodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,18 @@ def __init__(self, mf6, name):
"sto": ArrayPackage,
"wel": ListPackage,
# gwt
"adv": ArrayPackage,
"dsp": ArrayPackage,
"cnc": ListPackage,
"ist": ArrayPackage,
"mst": ArrayPackage,
"src": ListPackage,
# gwe
"cnd": ArrayPackage,
"est": ArrayPackage,
"cpt": ListPackage,
"esl": ListPackage,
# prt
"mip": ArrayPackage,
}

self.allow_convergence = True
Expand Down
10 changes: 9 additions & 1 deletion modflowapi/extensions/apisimulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,21 @@ def load(mf6):

solution_names.append(t[0])

idp_names = [i for i in mf6.get_value("__INPUT__/SIM/NAM/SLNMNAMES")]
solution_types = [
i[:-1].lower()
for ix, i in enumerate(mf6.get_value("__INPUT__/SIM/NAM/SLNTYPE"))
if idp_names[ix]
]

tmpmdl = ApiMbase(mf6, "", {})
solution_names = list(set(solution_names))
solution_dict = {}
for name in solution_names:
sid_var_addr = mf6.get_var_address("ID", name)
sid = mf6.get_value(sid_var_addr)[0]
sln = ApiSlnPackage(tmpmdl, name)
slntype = solution_types[sid - 1]
sln = ApiSlnPackage(tmpmdl, name, pkg_type=slntype)
solution_dict[sid] = sln

solutions = solution_dict
Expand Down
65 changes: 51 additions & 14 deletions modflowapi/extensions/pakbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,29 @@
"auxname_cst",
"auxvar",
],
# gwe model
"cnd": ["alh", "alv", "ath1", "ath2", "atv", "kts"],
"est": ["porosity", "decay", "cps", "rhos"],
"cpt": [
"maxbound",
"nbound",
"nodelist",
("bound", ("temp",)),
"naux",
"auxname_cst",
"auxvar",
],
"esl": [
"maxbound",
"nbound",
"nodelist",
("bound", ("senerrate",)),
"naux",
"auxname_cst",
"auxvar",
],
# gwt model
"adv": ["diffc", "alh", "alv", "ath1", "ath2", "atv"],
"dsp": ["diffc", "alh", "alv", "ath1", "ath2", "atv"],
"cnc": [
"maxbound",
"nbound",
Expand Down Expand Up @@ -121,9 +142,12 @@
"auxname_cst",
"auxvar",
],
# prt model
"mip": ["porosity", "retfactor", "izone"],
# exchange model
"gwf-gwf": ["nexg", "nodem1", "nodem2", "cl1", "cl2", "ihc"],
"gwt-gwt": ["nexg", "nodem1", "nodem2", "cl1", "cl2", "ihc"],
"gwf-gwf": ["nexg", "nodem1", "nodem2", "cl1", "cl2", "ihc", "hwva"],
"gwt-gwt": ["nexg", "nodem1", "nodem2", "cl1", "cl2", "ihc", "hwva"],
"gwe-gwe": ["nexg", "nodem1", "nodem2", "cl1", "cl2", "ihc", "hwva"],
# simulation
"ats": [
"maxats",
Expand All @@ -147,7 +171,7 @@
"tsmult",
],
# solution package
"sln": [
"sln-ims": [
"mxiter",
"dvclose",
"gamma",
Expand All @@ -170,6 +194,10 @@
"iscl",
"iord",
],
"sln-ems": [
"icnvg",
"ttsoln",
],
}


Expand Down Expand Up @@ -599,6 +627,10 @@ def __setattr__(self, item, value):
elif item in self._variables._ptrs:
self._variables.set_value(item, value)

elif item in ("mxiter",):
# hack for sln-ems
super().__setattr__(item, value)

else:
raise AttributeError(f"{item}")

Expand Down Expand Up @@ -690,21 +722,26 @@ class ApiSlnPackage(ScalarPackage):
package name (in the mf6 variables)
sim_package : bool
boolean flag for simulation level packages. Ex. TDIS, IMS
sln_type : str
ackronymn for the solution package type, default is "ims"
"""

def __init__(self, sim, pkg_name):
def __init__(self, sim, pkg_name, pkg_type="ims"):
from .apimodel import ApiMbase

super().__init__(sim, "sln", pkg_name, sim_package=True)
super().__init__(sim, f"sln-{pkg_type}", pkg_name, sim_package=True)

mdl = ApiMbase(
sim.mf6, pkg_name.upper(), pkg_types={"ims": ScalarPackage}
)
imslin = ScalarPackage(mdl, "ims", "IMSLINEAR")
for key, ptr in imslin._variables._ptrs.items():
if key in self._variables._ptrs:
key = f"{imslin.pkg_type}_{key}".lower()
self._variables._ptrs[key] = ptr
if pkg_type in ("ims",):
mdl = ApiMbase(
sim.mf6, pkg_name.upper(), pkg_types={pkg_type: ScalarPackage}
)
imslin = ScalarPackage(mdl, "ims", "IMSLINEAR")
for key, ptr in imslin._variables._ptrs.items():
if key in self._variables._ptrs:
key = f"{imslin.pkg_type}_{key}".lower()
self._variables._ptrs[key] = ptr
else:
self.mxiter = 10


def package_factory(pkg_type, basepackage):
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ test = [
"pytest!=8.1.0",
"pytest-order",
"pytest-xdist",
"GitPython",
"pooch",
"scipy",
"pyshp",
"shapely",
"rasterio",
"rasterstats"
]
lint = [
"ruff",
Expand Down

0 comments on commit 5193948

Please sign in to comment.