Skip to content

Commit 0c61f01

Browse files
mjrenomjreno
authored andcommitted
add mesh grid and netcdf file compare to tests
1 parent 7d4fc6a commit 0c61f01

File tree

7 files changed

+495
-62
lines changed

7 files changed

+495
-62
lines changed

autotest/regression/test_mf6_netcdf.py

Lines changed: 305 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,62 @@
66

77
import numpy as np
88
import pytest
9-
from modflow_devtools.markers import requires_exe, requires_pkg
9+
import xarray as xr
1010

1111
import flopy
12-
from flopy.utils import import_optional_dependency
12+
from flopy.discretization.structuredgrid import StructuredGrid
13+
from flopy.discretization.vertexgrid import VertexGrid
1314
from flopy.utils.datautil import DatumUtil
1415
from flopy.utils.gridutil import get_disv_kwargs
16+
from flopy.utils.model_netcdf import create_dataset
17+
18+
19+
def compare_netcdf(base, gen):
20+
"""Check for functional equivalence"""
21+
xrb = xr.open_dataset(base, engine="netcdf4")
22+
xrg = xr.open_dataset(gen, engine="netcdf4")
23+
24+
# global attributes
25+
for a in xrb.attrs:
26+
# TODO
27+
if a == "title" or a == "history" or a == "source":
28+
assert a in xrg.attrs
29+
continue
30+
assert xrb.attrs[a] == xrg.attrs[a]
31+
32+
# coordinates
33+
for coordname, da in xrb.coords.items():
34+
assert coordname in xrg.coords
35+
# TODO
36+
# assert np.allclose(xrb.coords[coordname].data, xrg.coords[coordname].data)
37+
38+
# variables
39+
for varname, da in xrb.data_vars.items():
40+
# TODO
41+
if varname == "mesh_face_xbnds" or varname == "mesh_face_ybnds":
42+
continue
43+
44+
# TODO
45+
if varname == "projection":
46+
continue
47+
48+
# check variable name
49+
assert varname in xrg.data_vars
50+
51+
# check variable attributes
52+
for a in da.attrs:
53+
# TODO delr/delc
54+
if a == "grid_mapping" or a == "long_name":
55+
continue
56+
assert da.attrs[a] == xrg.data_vars[varname].attrs[a]
57+
58+
# check variable data
59+
print(f"NetCDF file check data equivalence for variable: {varname}")
60+
assert np.allclose(da.data, xrg.data_vars[varname].data)
1561

1662

17-
@requires_pkg("xarray")
18-
@requires_exe("mf6")
1963
@pytest.mark.regression
20-
def test_load_netcdf_gwfsto01(function_tmpdir, example_data_path):
21-
xr = import_optional_dependency("xarray")
64+
def test_load_gwfsto01(function_tmpdir, example_data_path):
2265
data_path_base = example_data_path / "mf6" / "netcdf"
2366
tests = {
2467
"test_gwf_sto01_mesh": {
@@ -71,14 +114,11 @@ def test_load_netcdf_gwfsto01(function_tmpdir, example_data_path):
71114
for line1, line2 in zip(file1, file2):
72115
assert line1.lower() == line2.lower()
73116
else:
74-
# TODO compare nc files
75-
assert os.path.exists(gen)
117+
compare_netcdf(base, gen)
76118

77119

78-
@requires_pkg("xarray")
79120
@pytest.mark.regression
80-
def test_create_netcdf_gwfsto01(function_tmpdir, example_data_path):
81-
xr = import_optional_dependency("xarray")
121+
def test_create_gwfsto01(function_tmpdir, example_data_path):
82122
data_path_base = example_data_path / "mf6" / "netcdf"
83123
tests = {
84124
"test_gwf_sto01_mesh": {
@@ -308,14 +348,134 @@ def test_create_netcdf_gwfsto01(function_tmpdir, example_data_path):
308348
for line1, line2 in zip(file1, file2):
309349
assert line1 == line2
310350
else:
311-
# TODO compare nc files
312-
assert os.path.exists(gen)
351+
compare_netcdf(base, gen)
313352

314353

315-
@requires_pkg("xarray")
316354
@pytest.mark.regression
317-
def test_load_netcdf_disv01b(function_tmpdir, example_data_path):
318-
xr = import_optional_dependency("xarray")
355+
def test_gwfsto01(function_tmpdir, example_data_path):
356+
data_path_base = example_data_path / "mf6" / "netcdf"
357+
tests = {
358+
"test_gwf_sto01_mesh": {
359+
"base_sim_dir": "gwf_sto01",
360+
"netcdf_output_file": "gwf_sto01.in.nc",
361+
"netcdf_type": "mesh2d",
362+
},
363+
"test_gwf_sto01_structured": {
364+
"base_sim_dir": "gwf_sto01",
365+
"netcdf_output_file": "gwf_sto01.in.nc",
366+
"netcdf_type": "structured",
367+
},
368+
}
369+
370+
# spatial discretization data
371+
nlay, nrow, ncol = 3, 10, 10
372+
delr = [1000.0]
373+
delc = [2000.0]
374+
top = np.full((nrow, ncol), 0.0)
375+
botm = []
376+
botm.append(np.full((nrow, ncol), -100.0))
377+
botm.append(np.full((nrow, ncol), -150.0))
378+
botm.append(np.full((nrow, ncol), -350.0))
379+
botm = np.array(botm)
380+
381+
# ic
382+
strt = np.full((nlay, nrow, ncol), 0.0)
383+
384+
# npf
385+
# icelltype
386+
ic1 = np.full((nrow, ncol), 1)
387+
ic2 = np.full((nrow, ncol), 0)
388+
ic3 = np.full((nrow, ncol), 0)
389+
icelltype = np.array([ic1, ic2, ic3])
390+
391+
# k
392+
hk2fact = 1.0 / 50.0
393+
hk2 = np.ones((nrow, ncol), dtype=float) * 0.5 * hk2fact
394+
hk2[0, :] = 1000.0 * hk2fact
395+
hk2[-1, :] = 1000.0 * hk2fact
396+
hk2[:, 0] = 1000.0 * hk2fact
397+
hk2[:, -1] = 1000.0 * hk2fact
398+
k1 = np.full((nrow, ncol), 20.0)
399+
k3 = np.full((nrow, ncol), 5.0)
400+
k = np.array([k1, hk2, k3])
401+
402+
# k33
403+
k33_1 = np.full((nrow, ncol), 1e6)
404+
k33_2 = np.full((nrow, ncol), 7.5e-5)
405+
k33_3 = np.full((nrow, ncol), 1e6)
406+
k33 = np.array([k33_1, k33_2, k33_3])
407+
408+
# sto
409+
iconvert = icelltype
410+
411+
# storage and compaction data
412+
ss1 = np.full((nrow, ncol), 6e-4)
413+
ss2 = np.full((nrow, ncol), 3e-4)
414+
ss3 = np.full((nrow, ncol), 6e-4)
415+
ss = np.array([ss1, ss2, ss3])
416+
417+
sy = np.full((nlay, nrow, ncol), 0)
418+
419+
ws = function_tmpdir / "ws"
420+
for base_folder, test_info in tests.items():
421+
print(f"RUNNING TEST: {base_folder}")
422+
data_path = os.path.join(data_path_base, base_folder, test_info["base_sim_dir"])
423+
# copy example data into working directory
424+
base_model_folder = os.path.join(ws, f"{base_folder}_base")
425+
test_model_folder = os.path.join(ws, f"{base_folder}_test")
426+
shutil.copytree(data_path, base_model_folder)
427+
os.mkdir(test_model_folder)
428+
429+
# create discretization
430+
dis = flopy.discretization.StructuredGrid(
431+
delc=np.array(delc * nrow),
432+
delr=np.array(delr * ncol),
433+
top=top,
434+
botm=botm,
435+
nlay=nlay,
436+
nrow=nrow,
437+
ncol=ncol,
438+
)
439+
440+
ds = create_dataset(
441+
"gwf6",
442+
"gwf_sto01",
443+
test_info["netcdf_type"],
444+
test_info["netcdf_output_file"],
445+
dis,
446+
)
447+
448+
# add dis arrays
449+
ds.create_array("dis", "delc", dis.delc, ["nrow"])
450+
ds.create_array("dis", "delr", dis.delr, ["ncol"])
451+
ds.create_array("dis", "top", dis.top, ["nrow", "ncol"])
452+
ds.create_array("dis", "botm", dis.botm, ["nlay", "nrow", "ncol"])
453+
454+
# add ic array
455+
ds.create_array("ic", "strt", strt, ["nlay", "nrow", "ncol"])
456+
457+
# add npf arrays
458+
ds.create_array("npf", "icelltype", icelltype, ["nlay", "nrow", "ncol"])
459+
ds.create_array("npf", "k", k, ["nlay", "nrow", "ncol"])
460+
ds.create_array("npf", "k33", k33, ["nlay", "nrow", "ncol"])
461+
462+
# add sto array
463+
ds.create_array("sto", "iconvert", iconvert, ["nlay", "nrow", "ncol"])
464+
ds.create_array("sto", "ss", ss, ["nlay", "nrow", "ncol"])
465+
ds.create_array("sto", "sy", sy, ["nlay", "nrow", "ncol"])
466+
467+
# write to netcdf
468+
ds.write(test_model_folder)
469+
470+
# compare
471+
compare_netcdf(
472+
os.path.join(base_model_folder, test_info["netcdf_output_file"]),
473+
os.path.join(test_model_folder, test_info["netcdf_output_file"]),
474+
)
475+
476+
477+
@pytest.mark.regression
478+
def test_load_disv01b(function_tmpdir, example_data_path):
319479
data_path_base = example_data_path / "mf6" / "netcdf"
320480
tests = {
321481
"test_gwf_disv01b": {
@@ -363,14 +523,11 @@ def test_load_netcdf_disv01b(function_tmpdir, example_data_path):
363523
for line1, line2 in zip(file1, file2):
364524
assert line1.lower() == line2.lower()
365525
else:
366-
# TODO compare nc files
367-
assert os.path.exists(gen)
526+
compare_netcdf(base, gen)
368527

369528

370-
@requires_pkg("xarray")
371529
@pytest.mark.regression
372-
def test_create_netcdf_disv01b(function_tmpdir, example_data_path):
373-
xr = import_optional_dependency("xarray")
530+
def test_create_disv01b(function_tmpdir, example_data_path):
374531
data_path_base = example_data_path / "mf6" / "netcdf"
375532
tests = {
376533
"test_gwf_disv01b": {
@@ -453,5 +610,130 @@ def test_create_netcdf_disv01b(function_tmpdir, example_data_path):
453610
for line1, line2 in zip(file1, file2):
454611
assert line1 == line2
455612
else:
456-
# TODO compare nc files
457-
assert os.path.exists(gen)
613+
compare_netcdf(base, gen)
614+
615+
616+
@pytest.mark.regression
617+
def test_disv01b(function_tmpdir, example_data_path):
618+
data_path_base = example_data_path / "mf6" / "netcdf"
619+
tests = {
620+
"test_gwf_disv01b": {
621+
"base_sim_dir": "disv01b",
622+
"netcdf_output_file": "disv01b.in.nc",
623+
"netcdf_type": "mesh2d",
624+
},
625+
}
626+
627+
nlay = 3
628+
nrow = 3
629+
ncol = 3
630+
ncpl = nrow * ncol
631+
# delr = 10.0
632+
# delc = 10.0
633+
# xoff = 100000000.0
634+
# yoff = 100000000.0
635+
636+
vertices = [
637+
(0, 1.0000000e08, 1.0000003e08),
638+
(1, 1.0000001e08, 1.0000003e08),
639+
(2, 1.0000002e08, 1.0000003e08),
640+
(3, 1.0000003e08, 1.0000003e08),
641+
(4, 1.0000000e08, 1.0000002e08),
642+
(5, 1.0000001e08, 1.0000002e08),
643+
(6, 1.0000002e08, 1.0000002e08),
644+
(7, 1.0000003e08, 1.0000002e08),
645+
(8, 1.0000000e08, 1.0000001e08),
646+
(9, 1.0000001e08, 1.0000001e08),
647+
(10, 1.0000002e08, 1.0000001e08),
648+
(11, 1.0000003e08, 1.0000001e08),
649+
(12, 1.0000000e08, 1.0000000e08),
650+
(13, 1.0000001e08, 1.0000000e08),
651+
(14, 1.0000002e08, 1.0000000e08),
652+
(15, 1.0000003e08, 1.0000000e08),
653+
]
654+
655+
cell2d = [
656+
(0, 1.00000005e08, 1.00000025e08, 4, 0, 1, 5, 4),
657+
(1, 1.00000015e08, 1.00000025e08, 4, 1, 2, 6, 5),
658+
(2, 1.00000025e08, 1.00000025e08, 4, 2, 3, 7, 6),
659+
(3, 1.00000005e08, 1.00000015e08, 4, 4, 5, 9, 8),
660+
(4, 1.00000015e08, 1.00000015e08, 4, 5, 6, 10, 9),
661+
(5, 1.00000025e08, 1.00000015e08, 4, 6, 7, 11, 10),
662+
(6, 1.00000005e08, 1.00000005e08, 4, 8, 9, 13, 12),
663+
(7, 1.00000015e08, 1.00000005e08, 4, 9, 10, 14, 13),
664+
(8, 1.00000025e08, 1.00000005e08, 4, 10, 11, 15, 14),
665+
]
666+
667+
top = np.array(np.full((ncpl), 0.0))
668+
669+
idomain = np.array(
670+
[
671+
[1, 0, 1, 1, 1, 1, 1, 1, 1],
672+
[1, 1, 1, 1, 1, 1, 1, 1, 1],
673+
[1, 1, 1, 1, 1, 1, 1, 1, 1],
674+
]
675+
)
676+
677+
botm = []
678+
botm.append(np.full((ncpl), -10.0))
679+
botm.append(np.full((ncpl), -20.0))
680+
botm.append(np.full((ncpl), -30.0))
681+
botm = np.array(botm)
682+
683+
# npf
684+
icelltype = np.full((nlay, ncpl), 0)
685+
k = np.full((nlay, ncpl), 1)
686+
687+
# ic
688+
strt = np.full((nlay, ncpl), 0.0)
689+
690+
ws = function_tmpdir / "ws"
691+
for base_folder, test_info in tests.items():
692+
print(f"RUNNING TEST: {base_folder}")
693+
data_path = os.path.join(data_path_base, base_folder, test_info["base_sim_dir"])
694+
# copy example data into working directory
695+
base_model_folder = os.path.join(ws, f"{base_folder}_base")
696+
test_model_folder = os.path.join(ws, f"{base_folder}_test")
697+
shutil.copytree(data_path, base_model_folder)
698+
os.mkdir(test_model_folder)
699+
700+
# create discretization
701+
disv = VertexGrid(
702+
vertices=vertices,
703+
cell2d=cell2d,
704+
top=top,
705+
idomain=idomain,
706+
botm=botm,
707+
nlay=nlay,
708+
ncpl=ncpl,
709+
)
710+
711+
# create dataset
712+
ds = create_dataset(
713+
"gwf6",
714+
"disv01b",
715+
test_info["netcdf_type"],
716+
test_info["netcdf_output_file"],
717+
disv,
718+
)
719+
720+
# add dis arrays
721+
ds.create_array("disv", "top", disv.top, ["ncpl"])
722+
ds.create_array("disv", "botm", disv.botm, ["nlay", "ncpl"])
723+
ds.create_array("disv", "idomain", disv.idomain, ["nlay", "ncpl"])
724+
725+
# add npf arrays
726+
ds.create_array("npf", "icelltype", icelltype, ["nlay", "ncpl"])
727+
ds.create_array("npf", "k", k, ["nlay", "ncpl"])
728+
729+
# add ic arrays
730+
ds.create_array("ic", "strt", strt, ["nlay", "ncpl"])
731+
732+
# write to netcdf
733+
ds.write(test_model_folder)
734+
735+
# compare
736+
compare_netcdf(
737+
os.path.join(base_model_folder, test_info["netcdf_output_file"]),
738+
os.path.join(test_model_folder, test_info["netcdf_output_file"]),
739+
)
-19.4 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.

flopy/mf6/data/mfdataarray.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,9 +1603,8 @@ def _set_storage_netcdf(self, nc_dataset, create=False):
16031603

16041604
if create:
16051605
# add array to netcdf dataset
1606-
nc_varname = f"{p}_{n}".lower()
16071606
data = self._get_data()
1608-
nc_dataset.create_array(nc_varname, input_tag, 0, data, self.structure.shape)
1607+
nc_dataset.create_array(p, n, data, self.structure.shape)
16091608

16101609
storage._set_storage_netcdf(
16111610
nc_dataset, input_tag, self.structure.layered, storage.layer_storage.get_total_size() - 1

0 commit comments

Comments
 (0)