77from autotest .conftest import get_example_data_path
88from flopy .mf6 .modflow .mfsimulation import MFSimulation
99from flopy .utils .binaryfile import CellBudgetFile
10+ from flopy .utils .gridutil import get_disu_kwargs , get_disv_kwargs
1011
1112# test low-level CellBudgetFile._build_index() method
1213
@@ -658,34 +659,36 @@ def test_read_mf6_budgetfile(example_data_path):
658659 assert len (rch_zone_3 ) == 120 * 3 + 1
659660
660661
661- def test_cellbudgetfile_get_ts_auxiliary_variables (example_data_path ):
662+ def test_cellbudgetfile_get_ts_aux_vars_mf2005 (example_data_path ):
662663 from flopy .discretization import StructuredGrid
663664
664665 mf2005_model_path = example_data_path / "mf2005_test"
665666 cbc_fname = mf2005_model_path / "test1tr.gitcbc"
666667
667- # modelgrid for test1tr (1 layer, 15 rows, 10 cols)
668- modelgrid = StructuredGrid (nrow = 15 , ncol = 10 , nlay = 1 )
668+ nlay = 1
669+ nrow = 15
670+ ncol = 10
671+ grid = StructuredGrid (nlay = nlay , nrow = nrow , ncol = ncol )
669672
670- with CellBudgetFile (cbc_fname , modelgrid = modelgrid ) as v :
671- node = 54 - 1
672- k = node // (15 * 10 )
673- i = (node % (15 * 10 )) // 10
674- j = node % 10
673+ cbc = CellBudgetFile (cbc_fname , modelgrid = grid )
674+ node = 53
675+ cellid = grid .get_lrc (node )[0 ]
675676
676- ts_default = v .get_ts (idx = (k , i , j ), text = "WELLS" )
677- ts_q_explicit = v .get_ts (idx = (k , i , j ), text = "WELLS" , variable = "q" )
678- assert ts_default .shape [1 ] == 2 # time + 1 data column
679- np .testing .assert_array_equal (ts_default , ts_q_explicit )
677+ ts_default = cbc .get_ts (idx = cellid , text = "WELLS" )
678+ ts_q_explicit = cbc .get_ts (idx = cellid , text = "WELLS" , variable = "q" )
679+ assert ts_default .shape == ts_q_explicit .shape
680+ assert ts_default .shape [1 ] == 2 # time + 1 data column
681+ assert np .array_equal (ts_default , ts_q_explicit , equal_nan = True )
680682
681- ts_iface = v .get_ts (idx = (k , i , j ), text = "WELLS" , variable = "IFACE" )
682- assert ts_iface .shape [1 ] == 2 # time + 1 data column
683- assert not np .array_equal (ts_default [:, 1 ], ts_iface [:, 1 ])
684- np .testing .assert_array_equal (ts_default [:, 0 ], ts_iface [:, 0 ])
683+ ts_iface = cbc .get_ts (idx = cellid , text = "WELLS" , variable = "IFACE" )
684+ assert ts_iface .shape [1 ] == 2 # time + 1 data column
685+ assert ts_default .shape == ts_iface .shape
686+ assert not np .array_equal (ts_default [:, 1 ], ts_iface [:, 1 ])
687+ assert np .array_equal (ts_default [:, 0 ], ts_iface [:, 0 ], equal_nan = True )
685688
686689
687- @pytest .mark . requires_exe ( "mf6" )
688- def test_cellbudgetfile_get_ts_spdis_auxiliary_variables (function_tmpdir ):
690+ @pytest .fixture
691+ def dis_sim (function_tmpdir ):
689692 from flopy .mf6 import (
690693 MFSimulation ,
691694 ModflowGwf ,
@@ -698,7 +701,7 @@ def test_cellbudgetfile_get_ts_spdis_auxiliary_variables(function_tmpdir):
698701 ModflowTdis ,
699702 )
700703
701- sim_name = "spdis_test "
704+ sim_name = "test_ts_aux_vars "
702705 sim = MFSimulation (sim_name = sim_name , sim_ws = function_tmpdir , exe_name = "mf6" )
703706 tdis = ModflowTdis (sim , nper = 2 , perioddata = [(1.0 , 1 , 1.0 ), (1.0 , 1 , 1.0 )])
704707 ims = ModflowIms (sim )
@@ -727,34 +730,211 @@ def test_cellbudgetfile_get_ts_spdis_auxiliary_variables(function_tmpdir):
727730 saverecord = [("HEAD" , "ALL" ), ("BUDGET" , "ALL" )],
728731 )
729732
733+ return sim
734+
735+
736+ @pytest .mark .requires_exe ("mf6" )
737+ def test_cellbudgetfile_get_ts_aux_vars_mf6_dis (dis_sim ):
738+ sim = dis_sim
730739 sim .write_simulation ()
731740 success , _ = sim .run_simulation (silent = True )
741+ assert success
742+
743+ gwf = sim .get_model ()
744+ cbc = gwf .output .budget ()
745+ spdis = cbc .get_data (text = "DATA-SPDIS" )
746+ available_fields = list (spdis [0 ].dtype .names )
747+ expected_fields = ["node" , "q" , "qx" , "qy" , "qz" ]
748+ for field in expected_fields :
749+ assert field in available_fields
750+
751+ cellid = (0 , 2 , 2 )
752+ nn = gwf .modelgrid .get_node (cellid )[0 ]
753+
754+ ts_q = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "q" )
755+ ts_qx = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "qx" )
756+ ts_qy = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "qy" )
757+ ts_qz = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "qz" )
758+
759+ assert ts_q .shape == ts_qx .shape == ts_qy .shape == ts_qz .shape
760+ assert ts_q .shape [1 ] == 2 # time + 1 data column
761+ assert ts_qx .shape [1 ] == 2
762+ assert ts_qy .shape [1 ] == 2
763+ assert ts_qz .shape [1 ] == 2
764+
765+ assert np .array_equal (ts_q [:, 0 ], ts_qx [:, 0 ])
766+ assert np .array_equal (ts_q [:, 0 ], ts_qy [:, 0 ])
767+ assert np .array_equal (ts_q [:, 0 ], ts_qz [:, 0 ])
768+
769+ # check get_ts() values match get_data() for each time step
770+ for i , rec in enumerate (spdis ):
771+ mask = rec ["node" ] == nn + 1 # 1-based
772+ assert np .allclose (
773+ ts_q [i , 1 ],
774+ rec ["q" ][mask ][0 ],
775+ ), f"get_ts() q value doesn't match get_data() at time { i } "
776+ assert np .allclose (
777+ ts_qx [i , 1 ],
778+ rec ["qx" ][mask ][0 ],
779+ ), f"get_ts() qx value doesn't match get_data() at time { i } "
780+ assert np .allclose (
781+ ts_qy [i , 1 ],
782+ rec ["qy" ][mask ][0 ],
783+ ), f"get_ts() qy value doesn't match get_data() at time { i } "
784+ assert np .allclose (
785+ ts_qz [i , 1 ],
786+ rec ["qz" ][mask ][0 ],
787+ ), f"get_ts() qz value doesn't match get_data() at time { i } "
788+
789+ assert not np .allclose (ts_qx [:, 1 ], 0.0 ), "qx should have non-zero flow"
790+ assert not np .allclose (ts_qy [:, 1 ], 0.0 ), "qy should have non-zero flow"
791+ assert np .allclose (ts_q [:, 1 ], 0.0 ), "q should be zero for internal cells"
792+ assert np .allclose (ts_qz [:, 1 ], 0.0 ), "qz should be zero for single layer"
732793
733- cbc_file = function_tmpdir / budget_file
734- with CellBudgetFile (cbc_file , modelgrid = gwf .modelgrid ) as cbc :
735- spdis_data = cbc .get_data (text = "DATA-SPDIS" )
736- if len (spdis_data ) == 0 :
737- pytest .skip ("No DATA-SPDIS records found" )
738794
739- available_fields = list (spdis_data [0 ].dtype .names )
740- expected_fields = ["node" , "q" , "qx" , "qy" , "qz" ]
795+ @pytest .mark .requires_exe ("mf6" )
796+ def test_cellbudgetfile_get_ts_aux_vars_mf6_disv (dis_sim ):
797+ from flopy .mf6 import ModflowGwfchd , ModflowGwfdisv
798+
799+ sim = dis_sim
800+ gwf = sim .get_model ()
801+ dis_grid = gwf .modelgrid
802+ disv_kwargs = get_disv_kwargs (
803+ nlay = dis_grid .nlay ,
804+ nrow = dis_grid .nrow ,
805+ ncol = dis_grid .ncol ,
806+ delr = dis_grid .delr ,
807+ delc = dis_grid .delc ,
808+ tp = dis_grid .top ,
809+ botm = dis_grid .botm ,
810+ xoff = dis_grid .xoffset ,
811+ yoff = dis_grid .yoffset ,
812+ )
813+ gwf .remove_package ("dis" )
814+ gwf .remove_package ("chd" )
815+ disv = ModflowGwfdisv (gwf , ** disv_kwargs )
816+ chd_spd = [[(0 , 0 ), 10.0 ], [(0 , 24 ), 0.0 ]]
817+ chd = ModflowGwfchd (gwf , stress_period_data = chd_spd )
741818
742- for field in ["qx" , "qy" , "qz" ]:
743- assert field in available_fields , (
744- f"Expected field '{ field } ' not found in { available_fields } "
745- )
819+ sim .write_simulation ()
820+ success , _ = sim .run_simulation (silent = False )
821+ assert success
822+
823+ cbc = gwf .output .budget ()
824+ spdis = cbc .get_data (text = "DATA-SPDIS" )
825+ available_fields = list (spdis [0 ].dtype .names )
826+ expected_fields = ["node" , "q" , "qx" , "qy" , "qz" ]
827+ for field in expected_fields :
828+ assert field in available_fields
829+
830+ cellid = (0 , 4 ) # cell in center of layer 0
831+ nn = 4
832+
833+ ts_q = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "q" )
834+ ts_qx = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "qx" )
835+ ts_qy = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "qy" )
836+ ts_qz = cbc .get_ts (idx = cellid , text = "DATA-SPDIS" , variable = "qz" )
837+
838+ assert ts_q .shape == ts_qx .shape == ts_qy .shape == ts_qz .shape
839+ assert ts_q .shape [1 ] == 2 # time + 1 data column
840+ assert ts_qx .shape [1 ] == 2
841+ assert ts_qy .shape [1 ] == 2
842+ assert ts_qz .shape [1 ] == 2
843+
844+ # check get_ts() values match get_data() for each time step
845+ for i , rec in enumerate (spdis ):
846+ mask = rec ["node" ] == nn + 1 # 1-based
847+ assert np .allclose (
848+ ts_q [i , 1 ],
849+ rec ["q" ][mask ][0 ],
850+ ), f"DISV get_ts() q doesn't match get_data() at time { i } "
851+ assert np .allclose (
852+ ts_qx [i , 1 ],
853+ rec ["qx" ][mask ][0 ],
854+ ), f"DISV get_ts() qx doesn't match get_data() at time { i } "
855+ assert np .allclose (
856+ ts_qy [i , 1 ],
857+ rec ["qy" ][mask ][0 ],
858+ ), f"DISV get_ts() qy doesn't match get_data() at time { i } "
859+ assert np .allclose (
860+ ts_qz [i , 1 ],
861+ rec ["qz" ][mask ][0 ],
862+ ), f"DISV get_ts() qz doesn't match get_data() at time { i } "
863+
864+ assert not np .allclose (ts_qx [:, 1 ], 0.0 ), "qx should have non-zero flow"
865+ assert not np .allclose (ts_qy [:, 1 ], 0.0 ), "qy should have non-zero flow"
866+ assert np .allclose (ts_q [:, 1 ], 0.0 ), "q should be zero for internal cells"
867+ assert np .allclose (ts_qz [:, 1 ], 0.0 ), "qz should be zero for single layer"
746868
747- test_cell = (0 , 2 , 2 )
748- ts_q = cbc .get_ts (idx = test_cell , text = "DATA-SPDIS" , variable = "q" )
749- ts_qx = cbc .get_ts (idx = test_cell , text = "DATA-SPDIS" , variable = "qx" )
750- ts_qy = cbc .get_ts (idx = test_cell , text = "DATA-SPDIS" , variable = "qy" )
751- ts_qz = cbc .get_ts (idx = test_cell , text = "DATA-SPDIS" , variable = "qz" )
752869
753- assert ts_q .shape [1 ] == 2 # time + 1 data column
754- assert ts_qx .shape [1 ] == 2
755- assert ts_qy .shape [1 ] == 2
756- assert ts_qz .shape [1 ] == 2
870+ @pytest .mark .requires_exe ("mf6" )
871+ def test_cellbudgetfile_get_ts_aux_vars_mf6_disu (dis_sim ):
872+ from flopy .mf6 import ModflowGwfchd , ModflowGwfdisu
873+
874+ sim = dis_sim
875+ gwf = sim .get_model ()
876+ dis_grid = gwf .modelgrid
877+ disu_kwargs = get_disu_kwargs (
878+ nlay = dis_grid .nlay ,
879+ nrow = dis_grid .nrow ,
880+ ncol = dis_grid .ncol ,
881+ delr = dis_grid .delr ,
882+ delc = dis_grid .delc ,
883+ tp = dis_grid .top ,
884+ botm = dis_grid .botm ,
885+ return_vertices = True ,
886+ )
887+ gwf .remove_package ("dis" )
888+ gwf .remove_package ("chd" )
889+ disu = ModflowGwfdisu (gwf , ** disu_kwargs )
890+ chd_spd = [[0 , 10.0 ], [24 , 0.0 ]]
891+ chd = ModflowGwfchd (gwf , stress_period_data = chd_spd )
757892
758- np .testing .assert_array_equal (ts_q [:, 0 ], ts_qx [:, 0 ])
759- np .testing .assert_array_equal (ts_q [:, 0 ], ts_qy [:, 0 ])
760- np .testing .assert_array_equal (ts_q [:, 0 ], ts_qz [:, 0 ])
893+ sim .write_simulation ()
894+ success , _ = sim .run_simulation (silent = False )
895+ assert success
896+
897+ nn = 4
898+
899+ cbc = gwf .output .budget ()
900+ spdis = cbc .get_data (text = "DATA-SPDIS" )
901+ available_fields = list (spdis [0 ].dtype .names )
902+ expected_fields = ["node" , "q" , "qx" , "qy" , "qz" ]
903+ for field in expected_fields :
904+ assert field in available_fields
905+
906+ ts_q = cbc .get_ts (idx = nn , text = "DATA-SPDIS" , variable = "q" )
907+ ts_qx = cbc .get_ts (idx = nn , text = "DATA-SPDIS" , variable = "qx" )
908+ ts_qy = cbc .get_ts (idx = nn , text = "DATA-SPDIS" , variable = "qy" )
909+ ts_qz = cbc .get_ts (idx = nn , text = "DATA-SPDIS" , variable = "qz" )
910+
911+ assert ts_q .shape == ts_qx .shape == ts_qy .shape == ts_qz .shape
912+ assert ts_q .shape [1 ] == 2 # time + 1 data column
913+ assert ts_qx .shape [1 ] == 2
914+ assert ts_qy .shape [1 ] == 2
915+ assert ts_qz .shape [1 ] == 2
916+
917+ # check values match get_data()
918+ for i , rec in enumerate (spdis ):
919+ mask = rec ["node" ] == nn + 1 # 1-based
920+ assert np .allclose (
921+ ts_q [i , 1 ],
922+ rec ["q" ][mask ][0 ],
923+ ), f"DISU get_ts() q doesn't match get_data() at time { i } "
924+ assert np .allclose (
925+ ts_qx [i , 1 ],
926+ rec ["qx" ][mask ][0 ],
927+ ), f"DISU get_ts() qx doesn't match get_data() at time { i } "
928+ assert np .allclose (
929+ ts_qy [i , 1 ],
930+ rec ["qy" ][mask ][0 ],
931+ ), f"DISU get_ts() qy doesn't match get_data() at time { i } "
932+ assert np .allclose (
933+ ts_qz [i , 1 ],
934+ rec ["qz" ][mask ][0 ],
935+ ), f"DISU get_ts() qz doesn't match get_data() at time { i } "
936+
937+ assert not np .allclose (ts_qx [:, 1 ], 0.0 ), "qx should have non-zero flow"
938+ assert not np .allclose (ts_qy [:, 1 ], 0.0 ), "qy should have non-zero flow"
939+ assert np .allclose (ts_q [:, 1 ], 0.0 ), "q should be zero for internal cells"
940+ assert np .allclose (ts_qz [:, 1 ], 0.0 ), "qz should be zero for single layer"
0 commit comments