From d795f2fc1bfb5646abfaab794e81d0e576fd2ce8 Mon Sep 17 00:00:00 2001 From: Joseph Hughes Date: Wed, 28 Jun 2023 13:14:56 -0500 Subject: [PATCH 1/2] fix(binary): fix header information --- autotest/test_mf6.py | 9 ++++++- flopy/mf6/data/mffileaccess.py | 43 +++++++++++++++++++++++++--------- flopy/utils/datafile.py | 12 +++++----- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/autotest/test_mf6.py b/autotest/test_mf6.py index 042df355c9..1c5bf17c91 100644 --- a/autotest/test_mf6.py +++ b/autotest/test_mf6.py @@ -511,6 +511,12 @@ def test_binary_write(function_tmpdir): shape3d = (nlay, nrow, ncol) # create binary data structured + idomain_data = { + "filename": "idomain.bin", + "binary": True, + "iprn": 0, + "data": 1, + } top_data = { "filename": "top.bin", "binary": True, @@ -566,6 +572,7 @@ def test_binary_write(function_tmpdir): delc=1.0, top=top_data, botm=botm_data, + idomain=idomain_data, ) ModflowGwfnpf( gwf, @@ -573,7 +580,7 @@ def test_binary_write(function_tmpdir): ) ModflowGwfic( gwf, - strt=10.0, + strt=strt_data, ) ModflowGwfchd( gwf, diff --git a/flopy/mf6/data/mffileaccess.py b/flopy/mf6/data/mffileaccess.py index ce34a06f06..ae421f0e24 100644 --- a/flopy/mf6/data/mffileaccess.py +++ b/flopy/mf6/data/mffileaccess.py @@ -252,7 +252,14 @@ def _write_layer( ilay=None, ): header_data = self._get_header( - modelgrid, modeltime, stress_period, precision, text, fname, ilay + modelgrid, + modeltime, + stress_period, + precision, + text, + fname, + ilay=ilay, + data=data, ) header_data.tofile(fd) data.tofile(fd) @@ -266,6 +273,7 @@ def _get_header( text, fname, ilay=None, + data=None, ): # handle dis (row, col, lay), disv (ncpl, lay), and disu (nodes) cases if modelgrid is not None and modeltime is not None: @@ -274,13 +282,18 @@ def _get_header( if ilay is None: ilay = modelgrid.nlay if modelgrid.grid_type == "structured": + m1, m2, m3 = modelgrid.ncol, modelgrid.nrow, ilay + if data is not None: + shape3d = modelgrid.nlay * modelgrid.nrow * modelgrid.ncol + if data.size == shape3d: + m1, m2, m3 = shape3d, 1, 1 return BinaryHeader.create( bintype="vardis", precision=precision, text=text, - nrow=modelgrid.nrow, - ncol=modelgrid.ncol, - ilay=ilay, + m1=m1, + m2=m2, + m3=m3, pertim=pertim, totim=totim, kstp=1, @@ -289,24 +302,31 @@ def _get_header( elif modelgrid.grid_type == "vertex": if ilay is None: ilay = modelgrid.nlay + m1, m2, m3 = modelgrid.ncpl, 1, ilay + if data is not None: + shape3d = modelgrid.nlay * modelgrid.ncpl + if data.size == shape3d: + m1, m2, m3 = shape3d, 1, 1 + print(f"{modelgrid.grid_type}: {text} (m1,m2,m3) ({m1},{m2},{m3})") return BinaryHeader.create( bintype="vardisv", precision=precision, text=text, - ncpl=modelgrid.ncpl, - m2=1, - ilay=ilay, + m1=m1, + m2=m2, + m3=m3, pertim=pertim, totim=totim, kstp=1, kper=stress_period, ) elif modelgrid.grid_type == "unstructured": + m1, m2, m3 = modelgrid.nnodes, 1, 1 return BinaryHeader.create( bintype="vardisu", precision=precision, text=text, - nodes=modelgrid.nnodes, + m1=m1, m2=1, m3=1, pertim=pertim, @@ -317,13 +337,14 @@ def _get_header( else: if ilay is None: ilay = 1 + m1, m2, m3 = 1, 1, ilay header = BinaryHeader.create( bintype="vardis", precision=precision, text=text, - nrow=1, - ncol=1, - ilay=ilay, + m1=m1, + m2=m2, + m3=m3, pertim=pertim, totim=totim, kstp=1, diff --git a/flopy/utils/datafile.py b/flopy/utils/datafile.py index fb5906ae29..87fb4d9d98 100644 --- a/flopy/utils/datafile.py +++ b/flopy/utils/datafile.py @@ -81,9 +81,9 @@ def __init__(self, filetype=None, precision="single"): ("pertim", floattype), ("totim", floattype), ("text", "a16"), - ("ncol", "i4"), - ("nrow", "i4"), - ("ilay", "i4"), + ("m1", "i4"), + ("m2", "i4"), + ("m3", "i4"), ] ) elif self.header_type == "vardisv": @@ -94,9 +94,9 @@ def __init__(self, filetype=None, precision="single"): ("pertim", floattype), ("totim", floattype), ("text", "a16"), - ("ncpl", "i4"), + ("m1", "i4"), ("m2", "i4"), - ("ilay", "i4"), + ("m3", "i4"), ] ) elif self.header_type == "vardisu": @@ -107,7 +107,7 @@ def __init__(self, filetype=None, precision="single"): ("pertim", floattype), ("totim", floattype), ("text", "a16"), - ("nodes", "i4"), + ("m1", "i4"), ("m2", "i4"), ("m3", "i4"), ] From 87ad66ec30a3fd1366b3598a429cf93e338ba8b0 Mon Sep 17 00:00:00 2001 From: Joseph Hughes Date: Wed, 28 Jun 2023 16:03:05 -0500 Subject: [PATCH 2/2] fix(binary): fix header information --- autotest/test_mf6.py | 189 ++++++++++++++++++++++++--------- flopy/mf6/data/mffileaccess.py | 3 +- flopy/utils/binaryfile.py | 1 + 3 files changed, 144 insertions(+), 49 deletions(-) diff --git a/autotest/test_mf6.py b/autotest/test_mf6.py index 1c5bf17c91..5e8e2c5eb8 100644 --- a/autotest/test_mf6.py +++ b/autotest/test_mf6.py @@ -505,44 +505,88 @@ def test_subdir(function_tmpdir): @requires_exe("mf6") -def test_binary_write(function_tmpdir): +@pytest.mark.parametrize("layered", [True, False]) +def test_binary_write(function_tmpdir, layered): nlay, nrow, ncol = 2, 1, 10 shape2d = (nrow, ncol) - shape3d = (nlay, nrow, ncol) + + # data for layers + botm = [4.0, 0.0] + strt = [5.0, 10.0] # create binary data structured - idomain_data = { - "filename": "idomain.bin", - "binary": True, - "iprn": 0, - "data": 1, - } + if layered: + idomain_data = [] + botm_data = [] + strt_data = [] + for k in range(nlay): + idomain_data.append( + { + "factor": 1.0, + "filename": f"idomain_l{k+1}.bin", + "data": 1, + "binary": True, + "iprn": 1, + } + ) + botm_data.append( + { + "filename": f"botm_l{k+1}.bin", + "binary": True, + "iprn": 1, + "data": np.full(shape2d, botm[k], dtype=float), + } + ) + strt_data.append( + { + "filename": f"strt_l{k+1}.bin", + "binary": True, + "iprn": 1, + "data": np.full(shape2d, strt[k], dtype=float), + } + ) + else: + idomain_data = { + "filename": "idomain.bin", + "binary": True, + "iprn": 1, + "data": 1, + } + botm_data = { + "filename": "botm.bin", + "binary": True, + "iprn": 1, + "data": np.array( + [ + np.full(shape2d, botm[0], dtype=float), + np.full(shape2d, botm[1], dtype=float), + ] + ), + } + strt_data = { + "filename": "strt.bin", + "binary": True, + "iprn": 1, + "data": np.array( + [ + np.full(shape2d, strt[0], dtype=float), + np.full(shape2d, strt[1], dtype=float), + ] + ), + } + + # binary data that does not vary by layers top_data = { "filename": "top.bin", "binary": True, - "iprn": 0, + "iprn": 1, "data": 10.0, } - botm_data = { - "filename": "botm.bin", - "binary": True, - "iprn": 0, - "data": np.array([ - np.full(shape2d, 4.0, dtype=float), - np.full(shape2d, 0.0, dtype=float), - ]), - } - strt_data = { - "filename": "strt.bin", - "binary": True, - "iprn": 0, - "data": np.full(shape3d, 10., dtype=float), - } rch_data = { 0: { "filename": "recharge.bin", "binary": True, - "iprn": 0, + "iprn": 1, "data": 0.000001, }, } @@ -554,7 +598,7 @@ def test_binary_write(function_tmpdir): 0: { "filename": "chd.bin", "binary": True, - "iprn": 0, + "iprn": 1, "data": chd_data, }, } @@ -595,8 +639,8 @@ def test_binary_write(function_tmpdir): @requires_exe("mf6") -def test_vor_binary_write(function_tmpdir): - +@pytest.mark.parametrize("layered", [True, False]) +def test_vor_binary_write(function_tmpdir, layered): # build voronoi grid boundary = [(0.0, 0.0), (0.0, 1.0), (10.0, 1.0), (10.0, 0.0)] triangle_ws = function_tmpdir / "triangle" @@ -613,36 +657,85 @@ def test_vor_binary_write(function_tmpdir): # problem dimensions nlay = 2 - shape3d = (nlay, vor.ncpl) + + # data for layers + botm = [4.0, 0.0] + strt = [5.0, 10.0] # build binary data + if layered: + idomain_data = [] + botm_data = [] + strt_data = [] + for k in range(nlay): + idomain_data.append( + { + "factor": 1.0, + "filename": f"idomain_l{k + 1}.bin", + "data": 1, + "binary": True, + "iprn": 1, + } + ) + botm_data.append( + { + "filename": f"botm_l{k + 1}.bin", + "binary": True, + "iprn": 1, + "data": np.full(vor.ncpl, botm[k], dtype=float), + } + ) + strt_data.append( + { + "filename": f"strt_l{k + 1}.bin", + "binary": True, + "iprn": 1, + "data": np.full(vor.ncpl, strt[k], dtype=float), + } + ) + else: + idomain_data = { + "filename": "idomain.bin", + "binary": True, + "iprn": 1, + "data": 1, + } + botm_data = { + "filename": "botm.bin", + "binary": True, + "iprn": 1, + "data": np.array( + [ + np.full(vor.ncpl, botm[0], dtype=float), + np.full(vor.ncpl, botm[1], dtype=float), + ] + ), + } + strt_data = { + "filename": "strt.bin", + "binary": True, + "iprn": 1, + "data": np.array( + [ + np.full(vor.ncpl, strt[0], dtype=float), + np.full(vor.ncpl, strt[1], dtype=float), + ] + ), + } + + # binary data that does not vary by layers top_data = { "filename": "top.bin", "binary": True, - "iprn": 0, + "iprn": 1, "data": 10.0, } - botm_data = { - "filename": "botm.bin", - "binary": True, - "iprn": 0, - "data": np.array([ - np.full(vor.ncpl, 4.0, dtype=float), - np.full(vor.ncpl, 0.0, dtype=float), - ]), - } - strt_data = { - "filename": "strt.bin", - "binary": True, - "iprn": 0, - "data": np.full(shape3d, 10., dtype=float), - } rch_data = { 0: { "filename": "recharge.bin", "binary": True, - "iprn": 0, - "data": np.full(vor.ncpl, 0.000001, dtype=float), #0.000001, + "iprn": 1, + "data": np.full(vor.ncpl, 0.000001, dtype=float), # 0.000001, }, } chd_data = [ @@ -673,6 +766,7 @@ def test_vor_binary_write(function_tmpdir): cell2d=vor.get_disv_gridprops()["cell2d"], top=top_data, botm=botm_data, + idomain=idomain_data, xorigin=0.0, yorigin=0.0, ) @@ -695,7 +789,6 @@ def test_vor_binary_write(function_tmpdir): assert success - def test_binary_read(function_tmpdir): test_ex_name = "binary_read" nlay = 3 diff --git a/flopy/mf6/data/mffileaccess.py b/flopy/mf6/data/mffileaccess.py index ae421f0e24..1cbac0f837 100644 --- a/flopy/mf6/data/mffileaccess.py +++ b/flopy/mf6/data/mffileaccess.py @@ -212,6 +212,8 @@ def write_binary_file( ): data = self._resolve_cellid_numbers_to_file(data) fd = self._open_ext_file(fname, binary=True, write=True) + if data.size == modelgrid.nnodes: + write_multi_layer = False if write_multi_layer: for layer, value in enumerate(data): self._write_layer( @@ -307,7 +309,6 @@ def _get_header( shape3d = modelgrid.nlay * modelgrid.ncpl if data.size == shape3d: m1, m2, m3 = shape3d, 1, 1 - print(f"{modelgrid.grid_type}: {text} (m1,m2,m3) ({m1},{m2},{m3})") return BinaryHeader.create( bintype="vardisv", precision=precision, diff --git a/flopy/utils/binaryfile.py b/flopy/utils/binaryfile.py index cb5b585afd..5c875d4257 100644 --- a/flopy/utils/binaryfile.py +++ b/flopy/utils/binaryfile.py @@ -194,6 +194,7 @@ def set_values(self, **kwargs): "ilay", "ncpl", "nodes", + "m1", "m2", "m3", ]