Skip to content

Commit f8e2671

Browse files
authored
test(framework): remove cbc comparison function (#2567)
cf modflowpy/flopy#2636, also tidy some type hints, fix RTD docs issues, and remove an old likely unused script
1 parent ff6f4d1 commit f8e2671

File tree

7 files changed

+23
-139
lines changed

7 files changed

+23
-139
lines changed

.build_rtd_docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
fpth = "mf6_6_0_prt_migration_guide.md"
111111
src = os.path.join(fpth)
112112
dst = os.path.join(dstdir, fpth)
113-
shutil.move(src, dst)
113+
shutil.copy(src, dst)
114114

115115
# -- build the deprecations table --------------------------------------------
116116
print("Build the deprecations markdown table")

.build_rtd_docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ Contents:
1616
_mf6run/deprecations.md
1717
mf6io
1818
dev
19-
migration
19+
misc

.build_rtd_docs/misc.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Special Topics
22
--------------
33

4-
This section includes miscellaneous documents, such as version-specific migration guides for particular models or capabilities.
4+
This section contains miscellaneous content.
55

66
.. toctree::
77
:maxdepth: 1

DEVELOPER.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,6 @@ MODFLOW 6 integration tests are written in Python with [`pytest`](https://docs.p
523523

524524
Before running tests, there are a few steps to complete. Most importantly, the local development version of MODFLOW 6 must be built, e.g. with Meson as described above.
525525

526-
The `autotest/build_exes.py` script is provided as a shortcut to rebuild local binaries. It can be invoked as a standard Python script or with Pytest. By default, binaries are placed in the `bin` directory relative to the project root, as in the Meson commands described above. To change the location of the binaries, use the `--path` option.
527-
528526
#### Configuring unit tests
529527

530528
Unit tests are [driven with Meson](https://mesonbuild.com/Unit-tests.html). A small number of Meson-native tests are defined in the top-level `meson.build` file to check that MODFLOW 6 has installed successfully. These require no additional configuration.

autotest/build_exes.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

autotest/framework.py

Lines changed: 18 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
from pathlib import Path
66
from subprocess import PIPE, STDOUT, Popen
77
from traceback import format_exc
8-
from typing import Callable, Optional, Union
8+
from typing import Callable, Union
99
from warnings import warn
1010

1111
import flopy
12-
import numpy as np
1312
from compare import (
1413
Comparison,
1514
adjust_htol,
@@ -21,7 +20,7 @@
2120
)
2221
from flopy.mbase import BaseModel
2322
from flopy.mf6 import MFSimulation
24-
from flopy.utils.compare import compare_heads
23+
from flopy.utils.compare import compare_cell_budget, compare_heads
2524
from modflow_devtools.misc import get_ostag, is_in_ci
2625

2726
DNODATA = 3.0e30
@@ -232,20 +231,20 @@ class TestFramework:
232231
def __init__(
233232
self,
234233
name: str,
235-
workspace: Union[str, os.PathLike],
234+
workspace: str | os.PathLike,
236235
targets: dict[str, Path],
237-
api_func: Optional[Callable] = None,
238-
build: Optional[Callable] = None,
239-
check: Optional[Callable] = None,
240-
plot: Optional[Callable] = None,
241-
compare: Optional[str] = "auto",
242-
parallel=False,
243-
ncpus=1,
244-
htol=None,
245-
rclose=None,
246-
overwrite=True,
247-
verbose=False,
248-
xfail=False,
236+
api_func: Callable | None = None,
237+
build: Callable | None = None,
238+
check: Callable | None = None,
239+
plot: Callable | None = None,
240+
compare: str | Comparison | None = "auto",
241+
parallel: bool = False,
242+
ncpus: int = 1,
243+
htol: float | None = None,
244+
rclose: float | None = None,
245+
overwrite: bool = True,
246+
verbose: bool = False,
247+
xfail: bool | list[bool] = False,
249248
):
250249
# make sure workspace exists
251250
workspace = Path(workspace).expanduser().absolute()
@@ -422,96 +421,13 @@ def _compare_budgets(self, extensions="cbc", rclose=0.001) -> bool:
422421
f"{EXTTEXT[extension]} comparison {i + 1}",
423422
f"{self.name} ({os.path.basename(fpth0)})",
424423
)
425-
success = self._compare_budget_files(extension, fpth0, fpth1, rclose)
424+
outname = os.path.splitext(os.path.basename(fpth0))[0]
425+
outfile = os.path.join(self.workspace, f"{outname}.{extension}.cmp.out")
426+
success = compare_cell_budget(fpth0, fpth1, outfile=outfile, rclose=rclose)
426427
if not success:
427428
return False
428429
return True
429430

430-
def _compare_budget_files(self, extension, fpth0, fpth1, rclose=0.001) -> bool:
431-
success = True
432-
if os.stat(fpth0).st_size * os.stat(fpth0).st_size == 0:
433-
return success, ""
434-
outfile = os.path.splitext(os.path.basename(fpth0))[0]
435-
outfile = os.path.join(self.workspace, outfile + f".{extension}.cmp.out")
436-
fcmp = open(outfile, "w")
437-
fcmp.write("Performing CELL-BY-CELL to CELL-BY-CELL comparison\n")
438-
fcmp.write(f"{fpth0}\n")
439-
fcmp.write(f"{fpth1}\n\n")
440-
441-
# open the files
442-
cbc0 = flopy.utils.CellBudgetFile(
443-
fpth0, precision="double", verbose=self.verbose
444-
)
445-
cbc1 = flopy.utils.CellBudgetFile(
446-
fpth1, precision="double", verbose=self.verbose
447-
)
448-
449-
# build list of cbc data to retrieve
450-
avail0 = cbc0.get_unique_record_names()
451-
avail1 = cbc1.get_unique_record_names()
452-
avail0 = [t.decode().strip() for t in avail0]
453-
avail1 = [t.decode().strip() for t in avail1]
454-
455-
# initialize list for storing totals for each budget term terms
456-
cbc_keys0 = []
457-
cbc_keys1 = []
458-
for t in avail0:
459-
t1 = t
460-
if t not in avail1:
461-
# check if RCHA or EVTA is available and use that instead
462-
# should be able to remove this once v6.3.0 is released
463-
if t[:-1] in avail1:
464-
t1 = t[:-1]
465-
else:
466-
raise Exception(f"Could not find {t} in {fpth1}")
467-
cbc_keys0.append(t)
468-
cbc_keys1.append(t1)
469-
470-
# get list of times and kstpkper
471-
kk = cbc0.get_kstpkper()
472-
times = cbc0.get_times()
473-
474-
# process data
475-
for key, key1 in zip(cbc_keys0, cbc_keys1):
476-
for idx, (k, t) in enumerate(zip(kk, times)):
477-
v0 = cbc0.get_data(kstpkper=k, text=key)[0]
478-
v1 = cbc1.get_data(kstpkper=k, text=key1)[0]
479-
if v0.dtype.names is not None:
480-
v0 = v0["q"]
481-
v1 = v1["q"]
482-
# skip empty vectors
483-
if v0.size < 1:
484-
continue
485-
vmin = rclose
486-
if vmin < 1e-6:
487-
vmin = 1e-6
488-
vmin_tol = 5.0 * vmin
489-
if v0.shape != v1.shape:
490-
v0 = v0.flatten()
491-
v1 = v1.flatten()
492-
idx = (abs(v0) > vmin) & (abs(v1) > vmin)
493-
diff = np.zeros(v0.shape, dtype=v0.dtype)
494-
diff[idx] = abs(v0[idx] - v1[idx])
495-
diffmax = diff.max()
496-
indices = np.where(diff == diffmax)[0]
497-
if diffmax > vmin_tol:
498-
success = False
499-
msg = (
500-
f"{os.path.basename(fpth0)} - "
501-
+ f"{key:16s} "
502-
+ f"difference ({diffmax:10.4g}) "
503-
+ f"> {vmin_tol:10.4g} "
504-
+ f"at {indices.size} nodes "
505-
+ f" [first location ({indices[0] + 1})] "
506-
+ f"at time {t} "
507-
)
508-
fcmp.write(f"{msg}\n")
509-
if self.verbose:
510-
print(msg)
511-
512-
fcmp.close()
513-
return success
514-
515431
def _compare(self, comparison: Comparison):
516432
"""
517433
Compare the main simulation's output with that of another simulation or model.

autotest/test_gwf_mf6io_app2_examples_distypes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import numpy as np
55
import pytest
66
from conftest import try_get_target
7+
from flopy.utils.compare import compare_cell_budget
78
from flopy.utils.gridgen import Gridgen
89
from framework import TestFramework
910

@@ -536,7 +537,7 @@ def check_output(idx, test):
536537
fpth0 = ws / f"{sim_name}.{extension}"
537538
# fpth1 = ws / f"mf6/{get_dis_name(name)}.{extension}"
538539
fpth1 = ws / f"mf6/{sim_name}.{extension}"
539-
test._compare_budget_files(extension, fpth0, fpth1)
540+
assert compare_cell_budget(fpth0, fpth1, outfile=ws / f"{name}.cmp")
540541

541542

542543
@pytest.mark.parametrize("idx, name", enumerate(cases))

0 commit comments

Comments
 (0)