Skip to content

Commit 02ab7f1

Browse files
authored
fix(binaryfile): tdis in head/budget reversal methods (#2475)
#2473 flushed out some bad kper/kstp/totim/pertim values in the reversed headers, and some sloppy tests. Also remove unused utility functions. The reported error still needs a fix in followup.
1 parent 3cf92c1 commit 02ab7f1

File tree

3 files changed

+97
-256
lines changed

3 files changed

+97
-256
lines changed

autotest/test_binaryfile.py

+44-71
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""
55

66
from itertools import repeat
7+
from pathlib import Path
78
from pprint import pformat
89

910
import numpy as np
@@ -14,6 +15,7 @@
1415
from modflow_devtools.markers import requires_exe, requires_pkg
1516

1617
import flopy
18+
from flopy.discretization.modeltime import ModelTime
1719
from flopy.modflow import Modflow
1820
from flopy.utils import (
1921
BinaryHeader,
@@ -25,8 +27,6 @@
2527
)
2628
from flopy.utils.binaryfile import (
2729
get_headfile_precision,
28-
write_budget,
29-
write_head,
3030
)
3131
from flopy.utils.gridutil import get_disv_kwargs, uniform_flow_field
3232

@@ -375,43 +375,6 @@ def test_get_headfile_precision(example_data_path):
375375
assert precision == "double"
376376

377377

378-
def test_write_head(function_tmpdir):
379-
file_path = function_tmpdir / "headfile"
380-
head_data = np.random.random((10, 10))
381-
382-
write_head(file_path, head_data)
383-
384-
assert file_path.is_file()
385-
content = np.fromfile(file_path)
386-
assert np.array_equal(head_data.ravel(), content)
387-
388-
# TODO: what else needs to be checked here?
389-
390-
391-
def test_write_budget(function_tmpdir):
392-
file_path = function_tmpdir / "budgetfile"
393-
394-
nlay = 3
395-
nrow = 3
396-
ncol = 3
397-
qx = 1.0
398-
qy = 0.0
399-
qz = 0.0
400-
shape = (nlay, nrow, ncol)
401-
spdis, flowja = uniform_flow_field(qx, qy, qz, shape)
402-
403-
write_budget(file_path, flowja, kstp=0)
404-
assert file_path.is_file()
405-
content1 = np.fromfile(file_path)
406-
407-
write_budget(file_path, flowja, kstp=1, kper=1, text="text")
408-
assert file_path.is_file()
409-
content2 = np.fromfile(file_path)
410-
411-
# TODO: why are these the same?
412-
assert np.array_equal(content1, content2)
413-
414-
415378
def test_binaryfile_read(function_tmpdir, freyberg_model_path):
416379
h = HeadFile(freyberg_model_path / "freyberg.githds")
417380
assert isinstance(h, HeadFile)
@@ -466,7 +429,7 @@ def test_binaryfile_read_context(freyberg_model_path):
466429
assert str(e.value) == "seek of closed file", str(e.value)
467430

468431

469-
def test_binaryfile_reverse_mf6_dis(function_tmpdir):
432+
def test_binaryfile_reverse_mf6_dis_symmetric(function_tmpdir):
470433
name = "reverse_dis"
471434
sim = flopy.mf6.MFSimulation(sim_name=name, sim_ws=function_tmpdir, exe_name="mf6")
472435
tdis_rc = [(1, 1, 1.0), (1, 1, 1.0), (1, 1, 1.0)]
@@ -501,36 +464,43 @@ def test_binaryfile_reverse_mf6_dis(function_tmpdir):
501464
success, buff = sim.run_simulation(silent=True, report=True)
502465
assert success, pformat(buff)
503466

504-
# reverse head file in place and check reversal
505467
head_file = flopy.utils.HeadFile(function_tmpdir / head_file)
506468
orig_heads = head_file.get_alldata()
469+
orig_times = head_file.get_times()
507470
orig_kstpkper = head_file.get_kstpkper()
508471
head_file.reverse()
509472
rev_heads = head_file.get_alldata()
473+
rev_times = head_file.get_times()
510474
rev_kstpkper = head_file.get_kstpkper()
511475
exp_head_shape = (nper, 2, 10, 10)
476+
assert orig_times == rev_times
512477
assert orig_heads.shape == exp_head_shape
513478
assert rev_heads.shape == (nper, 2, 10, 10)
514479
assert orig_kstpkper == rev_kstpkper
515480

516-
# reverse budget and write to separate file
517481
budget_file_rev_path = function_tmpdir / f"{budget_file}_rev"
518482
budget_file = flopy.utils.CellBudgetFile(function_tmpdir / budget_file)
519483
budget_file.reverse(budget_file_rev_path)
520484
budget_file_rev = flopy.utils.CellBudgetFile(budget_file_rev_path)
521485
assert budget_file.get_kstpkper() == orig_kstpkper
522486
assert budget_file_rev.get_kstpkper() == rev_kstpkper
523487

524-
for kper in range(nper):
488+
budtxt = "FLOW-JA-FACE"
489+
tmax = orig_times[-1]
490+
perlen = tdis.perioddata.get_data().perlen
491+
492+
for (_, kper), t in zip(orig_kstpkper, orig_times):
525493
assert np.allclose(orig_heads[kper], rev_heads[-(kper + 1)])
526-
budget = budget_file.get_data(text="FLOW-JA-FACE", totim=kper)[0]
527-
budget_rev = budget_file_rev.get_data(text="FLOW-JA-FACE", totim=kper)[0]
494+
budget = budget_file.get_data(text=budtxt, totim=t)[0]
495+
budget_rev = budget_file_rev.get_data(
496+
text=budtxt, totim=tmax - t + perlen[kper]
497+
)[0]
528498
assert budget.shape == budget_rev.shape
529499
assert np.allclose(budget, -budget_rev)
530500

531501

532502
@requires_pkg("shapely")
533-
def test_binaryfile_reverse_mf6_disv(function_tmpdir):
503+
def test_binaryfile_reverse_mf6_disv_symmetric(function_tmpdir):
534504
name = "reverse_disv"
535505
sim = flopy.mf6.MFSimulation(sim_name=name, sim_ws=function_tmpdir, exe_name="mf6")
536506
tdis_rc = [(1, 1, 1.0), (1, 1, 1.0), (1, 1, 1.0)]
@@ -559,36 +529,42 @@ def test_binaryfile_reverse_mf6_disv(function_tmpdir):
559529
success, buff = sim.run_simulation(silent=True)
560530
assert success, pformat(buff)
561531

562-
# reverse head file in place and check reversal
563532
head_file = flopy.utils.HeadFile(function_tmpdir / head_file)
564533
orig_heads = head_file.get_alldata()
534+
orig_times = head_file.get_times()
565535
orig_kstpkper = head_file.get_kstpkper()
566536
head_file.reverse()
567537
rev_heads = head_file.get_alldata()
538+
rev_times = head_file.get_times()
568539
rev_kstpkper = head_file.get_kstpkper()
569540
exp_shape = (nper, 2, 1, 100)
541+
assert orig_times == rev_times
570542
assert orig_heads.shape == exp_shape
571543
assert rev_heads.shape == exp_shape
572544
assert orig_kstpkper == rev_kstpkper
573545

574-
# reverse budget and write to separate file
575546
budget_file_rev_path = function_tmpdir / f"{budget_file}_rev"
576547
budget_file = flopy.utils.CellBudgetFile(function_tmpdir / budget_file)
577548
budget_file.reverse(budget_file_rev_path)
578549
budget_file_rev = flopy.utils.CellBudgetFile(budget_file_rev_path, tdis=tdis)
579550
assert budget_file.get_kstpkper() == orig_kstpkper
580551
assert budget_file_rev.get_kstpkper() == rev_kstpkper
581552

582-
for kper in range(nper):
553+
budtxt = "FLOW-JA-FACE"
554+
tmax = orig_times[-1]
555+
perlen = tdis.perioddata.get_data().perlen
556+
557+
for (_, kper), t in zip(orig_kstpkper, budget_file.get_times()):
583558
assert np.allclose(orig_heads[kper], rev_heads[-(kper + 1)])
584-
budget = budget_file.get_data(text="FLOW-JA-FACE", totim=kper)[0]
585-
budget_rev = budget_file_rev.get_data(text="FLOW-JA-FACE", totim=kper)[0]
559+
budget = budget_file.get_data(text=budtxt, totim=t)[0]
560+
budget_rev = budget_file_rev.get_data(
561+
text=budtxt, totim=tmax - t + perlen[kper]
562+
)[0]
586563
assert budget.shape == budget_rev.shape
587564
assert np.allclose(budget, -budget_rev)
588565

589566

590-
def test_binaryfile_reverse_mf6_disu(example_data_path, function_tmpdir):
591-
# load simulation and extract tdis
567+
def test_binaryfile_reverse_mf6_disu_symmetric(example_data_path, function_tmpdir):
592568
sim_name = "test006_gwf3"
593569
sim = flopy.mf6.MFSimulation.load(
594570
sim_name=sim_name, sim_ws=example_data_path / "mf6" / sim_name
@@ -600,48 +576,37 @@ def test_binaryfile_reverse_mf6_disu(example_data_path, function_tmpdir):
600576
sim.write_simulation()
601577
sim.run_simulation()
602578

603-
# load head file, providing tdis as kwarg
604579
file_path = function_tmpdir / "flow.hds"
605580
head_file = HeadFile(file_path, tdis=tdis)
581+
orig_heads = head_file.get_alldata()
582+
orig_times = head_file.get_times()
606583
orig_kstpkper = head_file.get_kstpkper()
607584

608-
# reverse and write to a separate file
609585
head_file_rev_path = function_tmpdir / "flow_rev.hds"
610586
head_file.reverse(filename=head_file_rev_path)
611587
head_file_rev = HeadFile(head_file_rev_path)
588+
rev_heads = head_file_rev.get_alldata()
589+
rev_times = head_file_rev.get_times()
612590
rev_kstpkper = head_file_rev.get_kstpkper()
591+
assert orig_times == rev_times
613592
assert orig_kstpkper == rev_kstpkper
614593

615-
# load budget file
616594
file_path = function_tmpdir / "flow.cbc"
617595
budget_file = CellBudgetFile(file_path, tdis=tdis)
618-
619-
# reverse and write to a separate file
620596
budget_file_rev_path = function_tmpdir / "flow_rev.cbc"
621597
budget_file.reverse(filename=budget_file_rev_path)
622598
budget_file_rev = CellBudgetFile(budget_file_rev_path)
623599
assert budget_file.get_kstpkper() == orig_kstpkper
624600
assert budget_file_rev.get_kstpkper() == rev_kstpkper
625-
626-
# check that data from both files have the same shape
627601
assert head_file.get_alldata().shape == (nper, 1, 1, 121)
628602
assert head_file_rev.get_alldata().shape == (nper, 1, 1, 121)
629-
630-
# check number of records
631603
assert len(head_file) == nper
632604
assert len(head_file_rev) == nper
633605
assert len(budget_file) == nper * 2
634606
assert len(budget_file_rev) == nper * 2
635607

636-
# check that the data are reversed
637608
nrecords = len(head_file)
638609
for idx in range(nrecords - 1, -1, -1):
639-
# check headfile headers
640-
f_header = list(head_file.recordarray[nrecords - idx - 1])
641-
rf_header = list(head_file_rev.recordarray[idx])
642-
assert f_header != rf_header
643-
644-
# check headfile data
645610
f_data = head_file.get_data(idx=idx)[0]
646611
rf_data = head_file_rev.get_data(idx=nrecords - idx - 1)[0]
647612
assert f_data.shape == rf_data.shape
@@ -653,8 +618,16 @@ def test_binaryfile_reverse_mf6_disu(example_data_path, function_tmpdir):
653618
else:
654619
assert np.array_equal(f_data[0][0], rf_data[0][0])
655620

656-
budget = budget_file.get_data(text="FLOW-JA-FACE", totim=idx)[0]
657-
budget_rev = budget_file_rev.get_data(text="FLOW-JA-FACE", totim=idx)[0]
621+
budtxt = "FLOW-JA-FACE"
622+
tmax = orig_times[-1]
623+
perlen = tdis.perioddata.get_data().perlen
624+
625+
for (_, kper), t in zip(orig_kstpkper, budget_file.get_times()):
626+
assert np.allclose(orig_heads[kper], rev_heads[-(kper + 1)])
627+
budget = budget_file.get_data(text=budtxt, totim=t)[0]
628+
budget_rev = budget_file_rev.get_data(
629+
text=budtxt, totim=tmax - t + perlen[kper]
630+
)[0]
658631
assert budget.shape == budget_rev.shape
659632
assert np.allclose(budget, -budget_rev)
660633

autotest/test_cellbudgetfile.py

+11-24
Original file line numberDiff line numberDiff line change
@@ -626,30 +626,17 @@ def test_cellbudgetfile_reverse_mf6(example_data_path, function_tmpdir):
626626
assert len(f) == 2
627627
assert len(rf) == 2
628628

629-
# check data were reversed
630-
nrecords = len(f)
631-
for idx in range(nrecords - 1, -1, -1):
632-
# check headers
633-
f_header = list(f.recordarray[nrecords - idx - 1])
634-
rf_header = list(rf.recordarray[idx])
635-
f_totim = f_header.pop(9) # todo check totim
636-
rf_totim = rf_header.pop(9)
637-
assert f_header == rf_header
638-
639-
# check data
640-
f_data = f.get_data(idx=idx)[0]
641-
rf_data = rf.get_data(idx=nrecords - idx - 1)[0]
642-
assert f_data.shape == rf_data.shape
643-
if f_data.ndim == 1:
644-
for row in range(len(f_data)):
645-
f_datum = f_data[row]
646-
rf_datum = rf_data[row]
647-
# flows should be negated
648-
rf_datum[2] = -rf_datum[2]
649-
assert f_datum == rf_datum
650-
else:
651-
# flows should be negated
652-
assert np.array_equal(f_data[0][0], -rf_data[0][0])
629+
kstpkper = f.get_kstpkper()
630+
times = f.get_times()
631+
tmax = times[-1]
632+
budtxt = "FLOW JA FACE"
633+
perlen = tdis.perioddata.get_data().perlen
634+
635+
for (_, kper), t in zip(kstpkper, times):
636+
budget = f.get_data(text=budtxt, totim=t)[0]
637+
budget_rev = rf.get_data(text=budtxt, totim=tmax - t + perlen[kper])[0]
638+
assert budget.shape == budget_rev.shape
639+
assert np.allclose(budget, -budget_rev)
653640

654641

655642
def test_read_mf6_budgetfile(example_data_path):

0 commit comments

Comments
 (0)