Skip to content

Commit

Permalink
test(utils): add tests for relocated utilities
Browse files Browse the repository at this point in the history
* add tests for grid and namefile utilities
* stub tests for comparison and binary file utilities
* mark get-modflow tests using GitHub API as slow
* only skip test for generating classes from DFN if running in parallel
  • Loading branch information
wpbonelli committed Nov 15, 2022
1 parent 0f3736b commit c6aa66a
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 52 deletions.
26 changes: 26 additions & 0 deletions autotest/generate_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os

import pytest
from autotest.conftest import excludes_branch, get_project_root_path

from flopy.mf6.utils import generate_classes


_project_root_path = get_project_root_path()
_using_xdist = bool(os.environ.get("PYTEST_XDIST_WORKER", None))


@excludes_branch("master")
@pytest.mark.mf6
@pytest.mark.skipif(_using_xdist, reason="modifies and reverts repository files, can't be run in parallel")
def test_generate_classes_from_dfn():
try:
generate_classes(branch="develop", backup=False)
finally:
paths = [
_project_root_path / "flopy" / "mf6" / "data" / "dfn",
_project_root_path / "flopy" / "mf6" / "modflow"
]
# restoring might lose work if these files have been modified
for path in paths:
os.system(f"git restore {path}")
10 changes: 10 additions & 0 deletions autotest/test_binaryfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,13 @@ def test_budgetfile_detect_precision_single(path):
def test_budgetfile_detect_precision_double(path):
file = CellBudgetFile(path, precision="auto")
assert file.realtype == np.float64


@pytest.mark.skip(reason="todo")
def test_write_head():
pass


@pytest.mark.skip(reason="todo")
def test_write_budget():
pass
39 changes: 39 additions & 0 deletions autotest/test_compare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest

pytestmark = pytest.mark.skip(reason="todo")


def test_calculate_diffmax():
pass


def test_calculate_difftol():
pass


def test_eval_bud_diff():
pass


def test_compare_budget():
pass


def test_compare_swrbudget():
pass


def test_compare_heads():
pass


def test_compare_concs():
pass


def test_compare_stages():
pass


def test_compare():
pass
16 changes: 0 additions & 16 deletions autotest/test_generate_classes.py

This file was deleted.

2 changes: 2 additions & 0 deletions autotest/test_get_modflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def test_script_options(tmpdir, downloads_dir):

@flaky
@requires_github
@pytest.mark.slow
@pytest.mark.parametrize("repo", repo_options.keys())
def test_script(tmpdir, repo, downloads_dir):
bindir = str(tmpdir)
Expand All @@ -260,6 +261,7 @@ def test_script(tmpdir, repo, downloads_dir):

@flaky
@requires_github
@pytest.mark.slow
@pytest.mark.parametrize("repo", repo_options.keys())
def test_python_api(tmpdir, repo, downloads_dir):
bindir = str(tmpdir)
Expand Down
55 changes: 54 additions & 1 deletion autotest/test_gridutil.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from itertools import product

import numpy as np
import pytest

from flopy.utils.gridutil import get_lni
from flopy.utils.gridutil import get_lni, get_disu_kwargs, uniform_flow_field


@pytest.mark.parametrize(
Expand Down Expand Up @@ -51,3 +54,53 @@ def test_get_lni_infers_layer_count_when_int_ncpl(ncpl, nodes, expected):
assert isinstance(lni, list)
for i, ln in enumerate(lni):
assert ln == expected[i]


@pytest.mark.parametrize("nlay, nrow, ncol, delr, delc, tp, botm",
[
(1, 61, 61, np.array(61 * [50]), np.array(61 * [50]), np.array([-10]), np.array([-30.0, -50.0])),
(2, 61, 61, np.array(61 * [50]), np.array(61 * [50]), np.array([-10]), np.array([-30.0, -50.0])),
])
def test_get_disu_kwargs(nlay, nrow, ncol, delr, delc, tp, botm):
kwargs = get_disu_kwargs(nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, tp=tp, botm=botm)

from pprint import pprint
pprint(kwargs["area"])

assert kwargs["nodes"] == nlay * nrow * ncol
assert kwargs["nvert"] == None

area = np.array([dr * dc for (dr, dc) in product(delr, delc)], dtype=float)
area = np.array(nlay * [area]).flatten()
assert np.array_equal(kwargs["area"], area)

# TODO: test other properties
# print(kwargs["iac"])
# print(kwargs["ihc"])
# print(kwargs["ja"])
# print(kwargs["nja"])


@pytest.mark.parametrize("qx, qy, qz, nlay, nrow, ncol", [
(1, 0, 0, 1, 1, 10),
(0, 1, 0, 1, 1, 10),
(0, 0, 1, 1, 1, 10),
(1, 0, 0, 1, 10, 10),
(1, 0, 0, 2, 10, 10),
(1, 1, 0, 2, 10, 10),
(1, 1, 1, 2, 10, 10),
(2, 1, 1, 2, 10, 10)
])
def test_uniform_flow_field(qx, qy, qz, nlay, nrow, ncol):
shape = nlay, nrow, ncol
spdis, flowja = uniform_flow_field(qx, qy, qz, shape)

assert spdis.shape == (nlay * nrow * ncol,)
for i, t in enumerate(spdis.flatten()):
assert t[0] == t[1] == i
assert t[3] == qx
assert t[4] == qy
assert t[5] == qz

# TODO: check flowja
# print(flowja.shape)
34 changes: 34 additions & 0 deletions autotest/test_mfreadnam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pytest
from autotest.conftest import get_example_data_path
from flopy.utils.mfreadnam import get_entries_from_namefile

_example_data_path = get_example_data_path()


@pytest.mark.parametrize("path", [
_example_data_path / "mf6" / "test001a_Tharmonic" / "mfsim.nam",
_example_data_path / "mf6" / "test001e_UZF_3lay" / "mfsim.nam",
_example_data_path / "mf6-freyberg" / "mfsim.nam",
])
def test_get_entries_from_namefile_mf6(path):
package = "IMS6"
entries = get_entries_from_namefile(path, ftype=package)
assert len(entries) == 1

entry = entries[0]
assert path.parent.name in entry[0]
assert entry[1] == package


@pytest.mark.skip(reason="only supports mf6 namefiles")
@pytest.mark.parametrize("path", [
_example_data_path / "mf6-freyberg" / "freyberg.nam",
])
def test_get_entries_from_namefile_mf2005(path):
package = "IC6"
entries = get_entries_from_namefile(path, ftype=package)
assert len(entries) == 1

entry = entries[0]
assert path.parent.name in entry[0]
assert entry[1] == package
71 changes: 36 additions & 35 deletions flopy/utils/mfreadnam.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"""
import os
from os import PathLike
from pathlib import Path, PurePosixPath, PureWindowsPath
from typing import Tuple, List


class NamData:
Expand Down Expand Up @@ -269,13 +271,13 @@ def attribs_from_namfile_header(namefile):
return defaults


def get_entries_from_namefile(namefile, ftype=None, unit=None, extension=None):
"""Get entries from a namefile. Can select using FTYPE, UNIT, or file
extension.
def get_entries_from_namefile(path: PathLike, ftype: str = None, unit: int = None, extension: str = None) -> List[Tuple]:
"""Get entries from an MF6 namefile. Can select using FTYPE, UNIT, or file extension.
This function only supports MF6 namefiles.
Parameters
----------
namefile : str
path : str
path to a MODFLOW-based model name file
ftype : str
package type
Expand All @@ -288,39 +290,38 @@ def get_entries_from_namefile(namefile, ftype=None, unit=None, extension=None):
-------
entries : list of tuples
list of tuples containing FTYPE, UNIT, FNAME, STATUS for each
namefile entry that meets a user-specified value.
namefile entry that meets a user-specified value. if no entries
are found, a single-element list containing a None-valued tuple is returned.
"""
entries = []
f = open(namefile, "r")
for line in f:
if line.strip() == "":
continue
if line[0] == "#":
continue
ll = line.strip().split()
if len(ll) < 3:
continue
status = "UNKNOWN"
if len(ll) > 3:
status = ll[3].upper()
if ftype is not None:
if ftype.upper() == ll[0].upper():
filename = os.path.join(os.path.split(namefile)[0], ll[2])
entries.append((filename, ll[0], ll[1], status))
elif unit is not None:
if int(unit) == int(ll[1]):
filename = os.path.join(os.path.split(namefile)[0], ll[2])
entries.append((filename, ll[0], ll[1], status))
elif extension is not None:
filename = os.path.join(os.path.split(namefile)[0], ll[2])
ext = os.path.splitext(filename)[1]
if len(ext) > 0:
if ext[0] == ".":
ext = ext[1:]
if extension.lower() == ext.lower():
with open(path, "r") as f:
for line in f:
if line.strip() == "":
continue
if line[0] == "#":
continue
ll = line.strip().split()
if len(ll) < 3:
continue
status = "UNKNOWN"
if len(ll) > 3:
status = ll[3].upper()
if ftype is not None:
if ftype.upper() in ll[0].upper():
filename = os.path.join(os.path.split(path)[0], ll[2])
entries.append((filename, ll[0], ll[1], status))
elif unit is not None:
if int(unit) == int(ll[1]):
filename = os.path.join(os.path.split(path)[0], ll[2])
entries.append((filename, ll[0], ll[1], status))
f.close()
if len(entries) < 1:
entries.append((None, None, None, None))
elif extension is not None:
filename = os.path.join(os.path.split(path)[0], ll[2])
ext = os.path.splitext(filename)[1]
if len(ext) > 0:
if ext[0] == ".":
ext = ext[1:]
if extension.lower() == ext.lower():
entries.append((filename, ll[0], ll[1], status))

return entries

0 comments on commit c6aa66a

Please sign in to comment.