From 4ef699e10b1fbd80055b85ca00a17b96d1c627ce Mon Sep 17 00:00:00 2001 From: Joshua Larsen Date: Tue, 31 Oct 2023 17:00:31 -0700 Subject: [PATCH] update(model_splitter.py): (#1994) * add check for no boundary condition instances in list based input packages. Do not write package in this case * update options setting routine to respect previously set options for split models * remove maxbound variable from mapped_data for list based input packages. Allows for dynamic maxbound setting by flopy built ins * update notebook example to skip None packages --- .../mf6_parallel_model_splitting_example.py | 2 +- autotest/test_model_splitter.py | 106 ++++++++++++++++++ flopy/mf6/utils/model_splitter.py | 13 ++- 3 files changed, 118 insertions(+), 3 deletions(-) diff --git a/.docs/Notebooks/mf6_parallel_model_splitting_example.py b/.docs/Notebooks/mf6_parallel_model_splitting_example.py index fee4fffd4b..35c535c4bc 100644 --- a/.docs/Notebooks/mf6_parallel_model_splitting_example.py +++ b/.docs/Notebooks/mf6_parallel_model_splitting_example.py @@ -188,7 +188,7 @@ pak = model.get_package(pkg) try: rarrays[ix + 1] = pak.stress_period_data.data[0] - except TypeError: + except (TypeError, AttributeError): pass recarray = mfsplit.reconstruct_recarray(rarrays) if pkg == "riv": diff --git a/autotest/test_model_splitter.py b/autotest/test_model_splitter.py index 34614cd14e..467b53e590 100644 --- a/autotest/test_model_splitter.py +++ b/autotest/test_model_splitter.py @@ -366,3 +366,109 @@ def test_control_records(function_tmpdir): raise AssertionError( "External binary file input not being preseved for MFList" ) + + +@requires_exe("mf6") +def test_empty_packages(function_tmpdir): + new_sim_path = function_tmpdir / "split_model" + + sim = flopy.mf6.MFSimulation(sim_ws=new_sim_path) + ims = flopy.mf6.ModflowIms(sim, print_option="all", complexity="simple") + tdis = flopy.mf6.ModflowTdis(sim) + + nrow, ncol = 1, 14 + base_name = "sfr01gwfgwf" + gwf = flopy.mf6.ModflowGwf(sim, modelname=base_name, save_flows=True) + dis = flopy.mf6.ModflowGwfdis(gwf, nrow=1, ncol=14, top=0., botm=-1.) + npf = flopy.mf6.ModflowGwfnpf( + gwf, + save_flows=True, + save_specific_discharge=True, + icelltype=0, + k=20., + k33=20. + ) + ic = flopy.mf6.ModflowGwfic(gwf, strt=0.) + chd = flopy.mf6.ModflowGwfchd( + gwf, + stress_period_data={0: [((0, 0, 13), 0.0),]} + ) + wel = flopy.mf6.ModflowGwfwel( + gwf, + stress_period_data={0: [((0, 0, 0), 1.),]} + ) + + # Build SFR records + packagedata = [ + (0, (0, 0, 0), 1., 1., 1., 0., 0.1, 0., 1., 1, 1., 0), + (1, (0, 0, 1), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (2, (0, 0, 2), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (3, (0, 0, 3), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (4, (0, 0, 4), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (5, (0, 0, 5), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (6, (0, 0, 6), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (7, (0, 0, 7), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (8, (0, 0, 8), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (9, (0, 0, 9), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (10, (0, 0, 10), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (11, (0, 0, 11), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (12, (0, 0, 12), 1., 1., 1., 0., 0.1, 0., 1., 2, 1., 0), + (13, (0, 0, 13), 1., 1., 1., 0., 0.1, 0., 1., 1, 1., 0), + ] + + connectiondata = [ + (0, -1), + (1, 0, -2), + (2, 1, -3), + (3, 2, -4), + (4, 3, -5), + (5, 4, -6), + (6, 5, -7), + (7, 6, -8), + (8, 7, -9), + (9, 8, -10), + (10, 9, -11), + (11, 10, -12), + (12, 11, -13), + (13, 12) + ] + + sfr = flopy.mf6.ModflowGwfsfr( + gwf, + print_input=True, + print_stage=True, + print_flows=True, + save_flows=True, + stage_filerecord=f"{base_name}.sfr.stg", + budget_filerecord=f"{base_name}.sfr.bud", + nreaches=14, + packagedata=packagedata, + connectiondata=connectiondata, + perioddata={0: [(0, "INFLOW", 1.),]} + ) + + array = np.zeros((nrow, ncol), dtype=int) + array[0, 7:] = 1 + mfsplit = Mf6Splitter(sim) + new_sim = mfsplit.split_model(array) + + m0 = new_sim.get_model(f"{base_name}_0") + m1 = new_sim.get_model(f"{base_name}_1") + + if "chd_0" in m0.package_dict: + raise AssertionError( + f"Empty CHD file written to {base_name}_0 model" + ) + + if "wel_0" in m1.package_dict: + raise AssertionError( + f"Empty WEL file written to {base_name}_1 model" + ) + + mvr_status0 = m0.sfr.mover.array + mvr_status1 = m0.sfr.mover.array + + if not mvr_status0 or not mvr_status1: + raise AssertionError( + "Mover status being overwritten in options splitting" + ) diff --git a/flopy/mf6/utils/model_splitter.py b/flopy/mf6/utils/model_splitter.py index 46ecc4e768..2cdd455d23 100644 --- a/flopy/mf6/utils/model_splitter.py +++ b/flopy/mf6/utils/model_splitter.py @@ -1823,9 +1823,11 @@ def _remap_sfr(self, package, mapped_data): # connect model network through movers between models mvr_recs = [] + mvr_mdl_set = set() for rec in sfr_mvr_conn: m0, n0 = sfr_remaps[rec[0]] m1, n1 = sfr_remaps[rec[1]] + mvr_mdl_set = mvr_mdl_set | {m0, m1} mvr_recs.append( ( self._model_dict[m0].name, @@ -1842,6 +1844,7 @@ def _remap_sfr(self, package, mapped_data): for idv, rec in div_mvr_conn.items(): m0, n0 = sfr_remaps[rec[0]] m1, n1 = sfr_remaps[rec[1]] + mvr_mdl_set = mvr_mdl_set | {m0, m1} mvr_recs.append( ( self._model_dict[m0].name, @@ -1856,7 +1859,7 @@ def _remap_sfr(self, package, mapped_data): ) if mvr_recs: - for mkey in self._model_dict.keys(): + for mkey in mvr_mdl_set: if not mapped_data[mkey]: continue mapped_data[mkey]["mover"] = True @@ -2954,7 +2957,9 @@ def _remap_package(self, package, ismvr=False): for mkey in mapped_data.keys(): if mapped_data[mkey]: - if isinstance(value, mfdatascalar.MFScalar): + if item in mapped_data[mkey]: + continue + elif isinstance(value, mfdatascalar.MFScalar): mapped_data[mkey][item] = value.data elif isinstance(value, mfdatalist.MFList): mapped_data[mkey][item] = value.array @@ -2964,7 +2969,11 @@ def _remap_package(self, package, ismvr=False): ) paks = {} for mdl, data in mapped_data.items(): + _ = mapped_data.pop("maxbound", None) if mapped_data[mdl]: + if "stress_period_data" in mapped_data[mdl]: + if not mapped_data[mdl]["stress_period_data"]: + continue paks[mdl] = pak_cls( self._model_dict[mdl], pname=package.name[0], **data )