def create_lgr_models(self): for k, v in self.cfg['setup_grid']['lgr'].items(): # load the config file for lgr inset model inset_cfg = load_cfg(v['filename'], default_file='/mf6_defaults.yml') # if lgr inset has already been created if inset_cfg['model']['modelname'] in self.simulation._models: return inset_cfg['model']['simulation'] = self.simulation if 'ims' in inset_cfg['model']['packages']: inset_cfg['model']['packages'].remove('ims') # set parent configuation dictionary here # (even though parent model is explicitly set below) # so that the LGR grid is snapped to the parent grid inset_cfg['parent'] = { 'namefile': self.namefile, 'model_ws': self.model_ws, 'version': 'mf6', 'hiKlakes_value': self.cfg['model']['hiKlakes_value'], 'default_source_data': True, 'length_units': self.length_units, 'time_units': self.time_units } inset_cfg = MF6model._parse_model_kwargs(inset_cfg) kwargs = get_input_arguments(inset_cfg['model'], mf6.ModflowGwf, exclude='packages') kwargs['parent'] = self # otherwise will try to load parent model inset_model = MF6model(cfg=inset_cfg, lgr=True, **kwargs) inset_model._load = self._load # whether model is being made or loaded from existing files inset_model.setup_grid() del inset_model.cfg['ims'] inset_model.cfg['tdis'] = self.cfg['tdis'] if self.inset is None: self.inset = {} self.lgr = {} self.inset[inset_model.name] = inset_model #self.inset[inset_model.name]._is_lgr = True # create idomain indicating area of parent grid that is LGR lgr_idomain = make_lgr_idomain( self.modelgrid, self.inset[inset_model.name].modelgrid) ncpp = int(self.modelgrid.delr[0] / self.inset[inset_model.name].modelgrid.delr[0]) ncppl = v.get('layer_refinement', 1) self.lgr[inset_model.name] = Lgr(self.nlay, self.nrow, self.ncol, self.dis.delr.array, self.dis.delc.array, self.dis.top.array, self.dis.botm.array, lgr_idomain, ncpp, ncppl) inset_model._perioddata = self.perioddata self._set_idomain()
def instantiate_base_simulation(sim_ws, gwfname, gwfnamec): # All pckgs between 3 test models the same except for parent model SFR input # static model data sim_workspaces.append(sim_ws) gwf_names.append(gwfname) sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", exe_name=mf6exe, sim_ws=sim_ws, continue_=False, ) # Instantiate time discretization package tdis_rc = [] for i in range(len(perlen)): tdis_rc.append((perlen[i], nstp[i], tsmult[i])) tdis = flopy.mf6.ModflowTdis(sim, time_units="DAYS", nper=nper, perioddata=tdis_rc) # Instantiate the gwf model (parent model) gwf = flopy.mf6.ModflowGwf( sim, modelname=gwfname, save_flows=True, newtonoptions="NEWTON", model_nam_file="{}.nam".format(gwfname), ) # Create iterative model solution and register the gwf model with it imsgwf = flopy.mf6.ModflowIms( sim, print_option="SUMMARY", outer_dvclose=hclose, outer_maximum=nouter, under_relaxation="NONE", inner_maximum=ninner, inner_dvclose=hclose, rcloserecord=rclose, linear_acceleration="BICGSTAB", scaling_method="NONE", reordering_method="NONE", relaxation_factor=relax, filename="{}.ims".format(gwfname), ) sim.register_ims_package(imsgwf, [gwf.name]) # Instantiate the discretization package dis = flopy.mf6.ModflowGwfdis( gwf, nlay=nlayp, nrow=nrowp, ncol=ncolp, delr=delrp, delc=delcp, top=topp, botm=botmp, idomain=idomainp, filename="{}.dis".format(gwfname), ) # Instantiate initial conditions package strt = [topp - 0.25, topp - 0.25, topp - 0.25] ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename="{}.ic".format(gwfname)) # Instantiate node property flow package npf = flopy.mf6.ModflowGwfnpf( gwf, save_flows=False, alternative_cell_averaging="AMT-LMK", icelltype=icelltype, k=hk, k33=k33, save_specific_discharge=False, filename="{}.npf".format(gwfname), ) # output control oc = flopy.mf6.ModflowGwfoc( gwf, headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # Instantiate constant head package rowList = np.arange(0, nrowp).tolist() layList = np.arange(0, nlayp).tolist() chdspd_left = [] chdspd_right = [] # Loop through rows, the left & right sides will appear in separate, # dedicated packages hd_left = 49.75 hd_right = 44.75 for l in layList: for r in rowList: # first, do left side of model chdspd_left.append([(l, r, 0), hd_left]) # finally, do right side of model chdspd_right.append([(l, r, ncolp - 1), hd_right]) chdspd = {0: chdspd_left} chd1 = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( gwf, maxbound=len(chdspd), stress_period_data=chdspd, save_flows=False, pname="CHD-1", filename="{}.chd1.chd".format(gwfname), ) chdspd = {0: chdspd_right} chd2 = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( gwf, maxbound=len(chdspd), stress_period_data=chdspd, save_flows=False, pname="CHD-2", filename="{}.chd2.chd".format(gwfname), ) welspd_mf6 = [] # [(layer, row, column), flow] welspd_mf6.append([(3 - 1, 8 - 1, 10 - 1), -5.0]) wel_mf6_spd = {0: welspd_mf6} maxbound = len(welspd_mf6) wel = flopy.mf6.ModflowGwfwel( gwf, print_input=False, print_flows=True, maxbound=maxbound, mover=True, auto_flow_reduce=0.1, stress_period_data=wel_mf6_spd, # wel_spd established in the MVR setup boundnames=False, save_flows=True, pname="WEL-1", filename="{}.wel".format(gwfname), ) # --------------------------- # Now work on the child grid # --------------------------- ncpp = 3 ncppl = [3, 3, 0] lgr = Lgr( nlayp, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=ncpp, ncppl=ncppl, xllp=0.0, yllp=0.0, ) # Get child grid info: delrc, delcc = lgr.get_delr_delc() idomainc = lgr.get_idomain() # child idomain topc, botmc = lgr.get_top_botm() # top/bottom of child grid # Instantiate the gwf model (child model) gwfc = flopy.mf6.ModflowGwf( sim, modelname=gwfnamec, save_flows=True, newtonoptions="NEWTON", model_nam_file="{}.nam".format(gwfnamec), ) # Instantiate the discretization package child_dis_shp = lgr.get_shape() nlayc = child_dis_shp[0] nrowc = child_dis_shp[1] ncolc = child_dis_shp[2] disc = flopy.mf6.ModflowGwfdis( gwfc, nlay=nlayc, nrow=nrowc, ncol=ncolc, delr=delrc, delc=delcc, top=topc, botm=botmc, idomain=idomainc, xorigin=xorigin, yorigin=yorigin, filename="{}.dis".format(gwfnamec), ) # Instantiate initial conditions package strtc = [ topc - 0.25, topc - 0.25, topc - 0.25, topc - 0.25, topc - 0.25, topc - 0.25, ] icc = flopy.mf6.ModflowGwfic(gwfc, strt=strtc, filename="{}.ic".format(gwfnamec)) # Instantiate node property flow package icelltypec = [1, 0, 0, 0, 0, 0] npfc = flopy.mf6.ModflowGwfnpf( gwfc, save_flows=False, alternative_cell_averaging="AMT-LMK", icelltype=icelltypec, k=hk, k33=k33, save_specific_discharge=False, filename="{}.npf".format(gwfnamec), ) # output control occ = flopy.mf6.ModflowGwfoc( gwfc, headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) welspd_mf6c = [] # [(layer, row, column), flow] welspd_mf6c.append([(6 - 1, 4 - 1, 9 - 1), -10.0]) wel_mf6_spdc = {0: welspd_mf6c} maxboundc = len(welspd_mf6c) welc = flopy.mf6.ModflowGwfwel( gwfc, print_input=False, print_flows=True, maxbound=maxboundc, mover=True, auto_flow_reduce=0.1, stress_period_data=wel_mf6_spdc, # wel_spd established in the MVR setup boundnames=False, save_flows=True, pname="WEL-2", filename="{}.wel".format(gwfnamec), ) # exchange data exchange_data = lgr.get_exchange_data() # Establish GWF-GWF exchange gwfgwf = flopy.mf6.ModflowGwfgwf( sim, exgtype="GWF6-GWF6", print_flows=True, print_input=True, exgmnamea=gwfname, exgmnameb=gwfnamec, nexg=len(exchange_data), exchangedata=exchange_data, mvr_filerecord="{}.mvr".format(name), pname="EXG-1", filename="{}.exg".format(name), ) return sim, gwf, gwfc
def get_model(idx, dir): global child_domain global hclose name = ex[idx] # tdis period data nper = 1 tdis_rc = [] for i in range(nper): tdis_rc.append((1.0, 1, 1)) # solver data nouter, ninner = 100, 300 hclose, rclose, relax = 1e-12, 1e-3, 0.97 h_start = 1.0 # dis nlay, nrow, ncol = 1, 7, 7 row_s, row_e = 3, 5 col_s, col_e = 3, 5 ref_fct = 3 nrowc = ref_fct * ((row_e - row_s) + 1) ncolc = ref_fct * ((col_e - col_s) + 1) idomain = np.ones((nlay, nrow, ncol)) idomain[:, row_s - 1:row_e, col_s - 1:col_e] = 0 delrc = delr / ref_fct delcc = delc / ref_fct tops = [0.0, -100.0] xoriginc = 2 * delr yoriginc = 2 * delc xmin = 0.0 xmax = ncol * delr ymin = 0.0 ymax = nrow * delc model_domain = [xmin, xmax, ymin, ymax] xminc = xoriginc xmaxc = xoriginc + ncolc * delrc yminc = yoriginc ymaxc = yoriginc + nrowc * delcc child_domain = [xminc, xmaxc, yminc, ymaxc] # boundary stress period data left_chd = [[(ilay, irow, 0), h_left] for ilay in range(nlay) for irow in range(nrow)] right_chd = [[(ilay, irow, ncol - 1), h_right] for ilay in range(nlay) for irow in range(nrow)] chd_data = left_chd + right_chd chd_spd = {0: chd_data} # build MODFLOW 6 files ws = dir sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws, memory_print_option="ALL", ) tdis = flopy.mf6.ModflowTdis(sim, time_units="DAYS", nper=nper, perioddata=tdis_rc) ims = flopy.mf6.ModflowIms( sim, print_option="SUMMARY", outer_dvclose=hclose, outer_maximum=nouter, under_relaxation="DBD", inner_maximum=ninner, inner_dvclose=hclose, rcloserecord=rclose, linear_acceleration="BICGSTAB", relaxation_factor=relax, ) # The parent model: gwf = flopy.mf6.ModflowGwf(sim, modelname=parent_name, save_flows=True) dis = flopy.mf6.ModflowGwfdis( gwf, nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, top=tops[0], botm=tops[1:], idomain=idomain, ) ic = flopy.mf6.ModflowGwfic(gwf, strt=h_start) npf = flopy.mf6.ModflowGwfnpf( gwf, save_specific_discharge=True, xt3doptions=True, save_flows=True, icelltype=0, k=k11, k33=k33, ) chd = flopy.mf6.ModflowGwfchd(gwf, stress_period_data=chd_spd) oc = flopy.mf6.ModflowGwfoc( gwf, head_filerecord="{}.hds".format(parent_name), budget_filerecord="{}.cbc".format(parent_name), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # The child model: gwfc = flopy.mf6.ModflowGwf(sim, modelname=child_name, save_flows=True) dis = flopy.mf6.ModflowGwfdis( gwfc, nlay=nlay, nrow=nrowc, ncol=ncolc, delr=delrc, delc=delcc, top=tops[0], botm=tops[1:], xorigin=xoriginc, yorigin=yoriginc, ) ic = flopy.mf6.ModflowGwfic(gwfc, strt=h_start) npf = flopy.mf6.ModflowGwfnpf( gwfc, save_specific_discharge=True, xt3doptions=True, save_flows=True, icelltype=0, k=k11, k33=k33, ) oc = flopy.mf6.ModflowGwfoc( gwfc, head_filerecord="{}.hds".format(child_name), budget_filerecord="{}.cbc".format(child_name), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # LGR: nrowp = gwf.dis.nrow.get_data() ncolp = gwf.dis.ncol.get_data() delrp = gwf.dis.delr.array delcp = gwf.dis.delc.array topp = gwf.dis.top.array botmp = gwf.dis.botm.array idomainp = gwf.dis.idomain.array lgr = Lgr( nlay, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=ref_fct, ncppl=1, ) exgdata = lgr.get_exchange_data(angldegx=True, cdist=True) exgdata_withbname = [] for exg in exgdata: l = exg angle = l[-2] if angle == 0: bname = "left" elif angle == 90.0: bname = "bottom" elif angle == 180.0: bname = "right" elif angle == 270.0: bname = "top" l.append(bname) exgdata_withbname.append(l) gwfgwf = flopy.mf6.ModflowGwfgwf( sim, exgtype="GWF6-GWF6", nexg=len(exgdata), exgmnamea=parent_name, exgmnameb=child_name, exchangedata=exgdata, xt3d=useXT3D, print_input=True, print_flows=True, save_flows=True, boundnames=True, auxiliary=["ANGLDEGX", "CDIST"], ) obslist = [] obstype = "FLOW-JA-FACE" for iexg, exg_connection in enumerate(exgdata): obslist.append((f"f{iexg + 1}", obstype, (iexg, ))) gwfgwfobs = {} gwfgwfobs["gwf_obs.csv"] = obslist gwfgwfobs["gwf_obs_boundnames.csv"] = [ ["OBSLEFT", "FLOW-JA-FACE", "LEFT"], ["OBSRIGHT", "FLOW-JA-FACE", "RIGHT"], ["OBSTOP", "FLOW-JA-FACE", "TOP"], ["OBSBOTTOM", "FLOW-JA-FACE", "BOTTOM"], ] fname = "gwfgwf.obs" gwfgwf.obs.initialize(filename=fname, digits=25, print_input=True, continuous=gwfgwfobs) return sim
def build_model(idx, dir): # grid properties nlay = 3 nrow = 6 ncol = 6 delr = 100.0 delc = 100.0 top = 300.0 botm = [200.0, 100.0, 0.0] # hydraulic properties hk = 1.0 vk = 1.0 # Set the idomain of the parent model in order to # define where the child model will be located idomain = np.ones((nlay, nrow, ncol), dtype=int) idomain[:, 2:4, 2:4] = 0 ncpp = 1 ncppl = [1, 1, 1] lgr = Lgr(nlay, nrow, ncol, delr, delc, top, botm, idomain, ncpp, ncppl) name = ex[idx] # build MODFLOW 6 files # create simulation sim = flopy.mf6.MFSimulation(sim_name=name, version="mf6", exe_name="mf6", sim_ws=dir) # create tdis package tdis = flopy.mf6.ModflowTdis(sim, nper=2, perioddata=[(1.0, 1, 1.0), (1.0, 1, 1.0)]) # create gwf model gwf = flopy.mf6.ModflowGwf(sim, modelname=namea, save_flows=True) # create iterative model solution and register the gwf model with it ims = flopy.mf6.ModflowIms(sim, outer_dvclose=1e-9, inner_dvclose=1.0e-9) # dis dis = flopy.mf6.ModflowGwfdis( gwf, nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, top=top, botm=botm, idomain=idomain, ) # initial conditions ic = flopy.mf6.ModflowGwfic(gwf, pname="ic", strt=top) # node property flow npf = flopy.mf6.ModflowGwfnpf(gwf, save_specific_discharge=True, icelltype=0, k=hk, k33=vk) # chd chdspd = [] for k in range(nlay): for i in range(nrow): chdspd.append([(k, i, 0), 1.0]) chdspd.append([(k, i, ncol - 1), 6.0]) chd = flopy.mf6.ModflowGwfchd(gwf, stress_period_data=chdspd) # output control oc = flopy.mf6.ModflowGwfoc( gwf, pname="oc", budget_filerecord="{}.cbc".format(namea), head_filerecord="{}.hds".format(namea), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], ) # create child gwf model cgwf = flopy.mf6.ModflowGwf(sim, modelname=nameb, save_flows=True) cnlay, cnrow, cncol = lgr.get_shape() cdelr, cdelc = lgr.get_delr_delc() ctop, cbotm = lgr.get_top_botm() xorigin, yorigin = lgr.get_lower_left() cidomain = lgr.get_idomain() cdis = flopy.mf6.ModflowGwfdis( cgwf, nlay=cnlay, nrow=cnrow, ncol=cncol, delr=cdelr, delc=cdelc, top=ctop, botm=cbotm, idomain=cidomain, xorigin=xorigin, yorigin=yorigin, ) cic = flopy.mf6.ModflowGwfic(cgwf, pname="ic", strt=top) cnpf = flopy.mf6.ModflowGwfnpf(cgwf, save_specific_discharge=True, icelltype=0, k=hk, k33=vk) oc = flopy.mf6.ModflowGwfoc( cgwf, pname="oc", budget_filerecord="{}.cbc".format(nameb), head_filerecord="{}.hds".format(nameb), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], printrecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], ) # exchange information exchangedata = lgr.get_exchange_data(angldegx=True, cdist=True) nexg = len(exchangedata) gwfe = flopy.mf6.ModflowGwfgwf( sim, exgtype="gwf6-gwf6", exgmnamea="a", exgmnameb="b", nexg=nexg, auxiliary=[("angldegx", "cdist")], exchangedata=exchangedata, ) return sim, None
def get_model(idx, dir): name = ex[idx] # parameters and spd # tdis nper = 1 tdis_rc = [] for i in range(nper): tdis_rc.append((1.0, 1, 1)) # solver data nouter, ninner = 100, 300 hclose, rclose, relax = g_hclose, 1e-3, 0.97 # refinement factor rft = 4 # model spatial discretization for parent nlay = 1 ncol = 8 nrow = 6 # cell spacing delr = g_delr delc = 10.0 area = delr * delc # top/bot of the aquifer tops = [0.0, -5.0] # hydraulic conductivity k11 = g_k11 # boundary stress period data h_left = g_hleft h_right = g_hright # initial head h_start = 135.0 sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", exe_name="mf6", sim_ws=dir, memory_print_option="all", ) tdis = flopy.mf6.ModflowTdis( sim, time_units="DAYS", nper=nper, perioddata=tdis_rc ) ims = flopy.mf6.ModflowIms( sim, print_option="SUMMARY", outer_dvclose=hclose, outer_maximum=nouter, under_relaxation="DBD", inner_maximum=ninner, inner_dvclose=hclose, rcloserecord=rclose, linear_acceleration="BICGSTAB", relaxation_factor=relax, ) # boundary data left_chd = [ [(ilay, irow, 0), h_left] for irow in range(nrow) for ilay in range(nlay) ] right_chd = [ [(ilay, irow, ncol - 1), h_right] for irow in range(nrow) for ilay in range(nlay) ] chd_data = left_chd + right_chd chd_spd = {0: chd_data} # idomain idomain = np.ones((nlay, nrow, ncol)) idomain[:, 1:5, 2:6] = 0 # -------------------------------------- # parent model # -------------------------------------- gwf = flopy.mf6.ModflowGwf(sim, modelname=name_parent, save_flows=True) dis = flopy.mf6.ModflowGwfdis( gwf, nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, top=tops[0], botm=tops[1:], idomain=idomain, ) ic = flopy.mf6.ModflowGwfic(gwf, strt=h_start) npf = flopy.mf6.ModflowGwfnpf( gwf, save_specific_discharge=True, save_flows=True, icelltype=0, k=k11, xt3doptions=False, ) chd = flopy.mf6.ModflowGwfchd(gwf, stress_period_data=chd_spd) oc = flopy.mf6.ModflowGwfoc( gwf, head_filerecord="{}.hds".format(name_parent), budget_filerecord="{}.cbc".format(name_parent), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # -------------------------------------- # child model (gwfc) # -------------------------------------- gwfc = flopy.mf6.ModflowGwf(sim, modelname=name_child, save_flows=True) dis = flopy.mf6.ModflowGwfdis( gwfc, nlay=nlay, nrow=rft * 4, ncol=rft * 4, delr=delr / rft, delc=delc / rft, top=tops[0], botm=tops[1:], xorigin=2 * delr, yorigin=delc, angrot=0.0, ) ic = flopy.mf6.ModflowGwfic(gwfc, strt=h_start) npf = flopy.mf6.ModflowGwfnpf( gwfc, save_specific_discharge=True, save_flows=True, icelltype=0, k=k11, xt3doptions=False, ) oc = flopy.mf6.ModflowGwfoc( gwfc, head_filerecord="{}.hds".format(name_child), budget_filerecord="{}.cbc".format(name_child), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # -------------------------------------- # LGR # -------------------------------------- nrowp = gwf.dis.nrow.get_data() ncolp = gwf.dis.ncol.get_data() delrp = gwf.dis.delr.array delcp = gwf.dis.delc.array topp = gwf.dis.top.array botmp = gwf.dis.botm.array idomainp = gwf.dis.idomain.array lgr = Lgr( nlay, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=rft, ncppl=1, ) exgdata = lgr.get_exchange_data(angldegx=True, cdist=True) exgdata_north = [ e for e in exgdata if (e[0])[1] < 3 ] # northern three rows exgdata_south = [ e for e in exgdata if (e[0])[1] > 2 ] # southern three rows # north, has XT3D flopy.mf6.ModflowGwfgwf( sim, dev_interfacemodel_on=True, exgtype="GWF6-GWF6", nexg=len(exgdata_north), exgmnamea=name_parent, exgmnameb=name_child, exchangedata=exgdata_north, xt3d=True, print_flows=True, auxiliary=["ANGLDEGX", "CDIST"], filename="north_xt3d.gwfgwf", ) # south, no XT3D flopy.mf6.ModflowGwfgwf( sim, dev_interfacemodel_on=True, exgtype="GWF6-GWF6", nexg=len(exgdata_south), exgmnamea=name_parent, exgmnameb=name_child, exchangedata=exgdata_south, xt3d=False, print_flows=True, auxiliary=["ANGLDEGX", "CDIST"], filename="south_noxt3d.gwfgwf", ) return sim
def test_lgrutil(): nlayp = 5 nrowp = 5 ncolp = 5 delrp = 100. delcp = 100. topp = 100. botmp = [-100, -200, -300, -400, -500] idomainp = np.ones((nlayp, nrowp, ncolp), dtype=np.int) idomainp[0:2, 1:4, 1:4] = 0 ncpp = 3 ncppl = [1, 1, 0, 0, 0] lgr = Lgr(nlayp, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=ncpp, ncppl=ncppl, xllp=100., yllp=100.) # child shape assert lgr.get_shape() == (2, 9, 9), 'child shape is not (2, 9, 9)' # child delr/delc delr, delc = lgr.get_delr_delc() assert np.allclose(delr, delrp / ncpp), 'child delr not correct' assert np.allclose(delc, delcp / ncpp), 'child delc not correct' # child idomain idomain = lgr.get_idomain() assert idomain.min() == idomain.max() == 1 assert idomain.shape == (2, 9, 9) # replicated parent array ap = np.arange(nrowp * ncolp).reshape((nrowp, ncolp)) ac = lgr.get_replicated_parent_array(ap) assert ac[0, 0] == 6 assert ac[-1, -1] == 18 # child top/bottom topc, botmc = lgr.get_top_botm() assert topc.shape == (9, 9) assert botmc.shape == (2, 9, 9) assert topc.min() == topc.max() == 100. errmsg = '{} /= {}'.format(botmc[:, 0, 0], np.array(botmp[:2])) assert np.allclose(botmc[:, 0, 0], np.array(botmp[:2])), errmsg # exchange data exchange_data = lgr.get_exchange_data(angldegx=True, cdist=True) ans1 = [(0, 1, 0), (0, 0, 0), 1, 50.0, 16.666666666666668, 33.333333333333336, 0.0, 354.33819375782156] errmsg = '{} /= {}'.format(ans1, exchange_data[0]) assert exchange_data[0] == ans1, errmsg ans2 = [(2, 3, 3), (1, 8, 8), 0, 50.0, 50, 1111.1111111111113, 180., 100.] errmsg = '{} /= {}'.format(ans2, exchange_data[-1]) assert exchange_data[-1] == ans2, errmsg errmsg = 'exchanges should be 71 horizontal plus 81 vertical' assert len(exchange_data) == 72 + 81, errmsg # list of parent cells connected to a child cell assert lgr.get_parent_connections(0, 0, 0) == [((0, 1, 0), -1), ((0, 0, 1), 2)] assert lgr.get_parent_connections(1, 8, 8) == [((1, 3, 4), 1), ((1, 4, 3), -2), ((2, 3, 3), -3)] return
def build_model(sim_name, silent=False): if config.buildModel: # Instantiate the MODFLOW 6 simulation name = "lgr" gwfname = "gwf-" + name sim_ws = os.path.join(ws, sim_name) sim = flopy.mf6.MFSimulation( sim_name=sim_name, version="mf6", sim_ws=sim_ws, exe_name=mf6exe, continue_=True, ) # Instantiating MODFLOW 6 time discretization tdis_rc = [] for i in range(len(perlen)): tdis_rc.append((perlen[i], nstp[i], tsmult[i])) flopy.mf6.ModflowTdis(sim, nper=nper, perioddata=tdis_rc, time_units=time_units) # Instantiating MODFLOW 6 groundwater flow model gwfname = gwfname + "-parent" gwf = flopy.mf6.ModflowGwf( sim, modelname=gwfname, save_flows=True, newtonoptions="newton", model_nam_file="{}.nam".format(gwfname), ) # Instantiating MODFLOW 6 solver for flow model imsgwf = flopy.mf6.ModflowIms( sim, print_option="SUMMARY", outer_dvclose=hclose, outer_maximum=nouter, under_relaxation="NONE", inner_maximum=ninner, inner_dvclose=hclose, rcloserecord=rclose, linear_acceleration="BICGSTAB", scaling_method="NONE", reordering_method="NONE", relaxation_factor=relax, filename="{}.ims".format(gwfname), ) sim.register_ims_package(imsgwf, [gwf.name]) # Instantiating MODFLOW 6 discretization package dis = flopy.mf6.ModflowGwfdis( gwf, nlay=nlayp, nrow=nrowp, ncol=ncolp, delr=delrp, delc=delcp, top=topp, botm=botmp, idomain=idomainp, filename="{}.dis".format(gwfname), ) # Instantiating MODFLOW 6 initial conditions package for flow model strt = [topp - 0.25, topp - 0.25, topp - 0.25] ic = flopy.mf6.ModflowGwfic(gwf, strt=strt, filename="{}.ic".format(gwfname)) # Instantiating MODFLOW 6 node-property flow package npf = flopy.mf6.ModflowGwfnpf( gwf, save_flows=False, alternative_cell_averaging="AMT-LMK", icelltype=icelltype, k=k11, k33=k33, save_specific_discharge=False, filename="{}.npf".format(gwfname), ) # Instantiating MODFLOW 6 output control package for flow model oc = flopy.mf6.ModflowGwfoc( gwf, budget_filerecord="{}.bud".format(gwfname), head_filerecord="{}.hds".format(gwfname), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # Instantiating MODFLOW 6 constant head package rowList = np.arange(0, nrowp).tolist() layList = np.arange(0, nlayp).tolist() chdspd_left = [] chdspd_right = [] # Loop through rows, the left & right sides will appear in separate, # dedicated packages hd_left = 49.75 hd_right = 44.75 for l in layList: for r in rowList: # first, do left side of model chdspd_left.append([(l, r, 0), hd_left]) # finally, do right side of model chdspd_right.append([(l, r, ncolp - 1), hd_right]) chdspd = {0: chdspd_left} chd1 = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( gwf, maxbound=len(chdspd), stress_period_data=chdspd, save_flows=False, pname="CHD-1", filename="{}.chd1.chd".format(gwfname), ) chdspd = {0: chdspd_right} chd2 = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( gwf, maxbound=len(chdspd), stress_period_data=chdspd, save_flows=False, pname="CHD-2", filename="{}.chd2.chd".format(gwfname), ) # Instantiating MODFLOW 6 Parent model's SFR package sfr = flopy.mf6.ModflowGwfsfr( gwf, print_stage=False, print_flows=False, budget_filerecord=gwfname + ".sfr.bud", save_flows=True, mover=True, pname="SFR-parent", unit_conversion=86400.0, boundnames=False, nreaches=len(connsp), packagedata=pkdat, connectiondata=connsp, perioddata=sfrspd, filename="{}.sfr".format(gwfname), ) # ------------------------------- # Now pivoting to the child grid # ------------------------------- # Leverage flopy's "Lgr" class; was imported at start of script ncpp = 3 ncppl = [3, 3, 0] lgr = Lgr( nlayp, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=ncpp, ncppl=ncppl, xllp=0.0, yllp=0.0, ) # Get child grid info: delrc, delcc = lgr.get_delr_delc() idomainc = lgr.get_idomain() # child idomain topc, botmc = lgr.get_top_botm() # top/bottom of child grid # Instantiate MODFLOW 6 child gwf model gwfnamec = "gwf-" + name + "-child" gwfc = flopy.mf6.ModflowGwf( sim, modelname=gwfnamec, save_flows=True, newtonoptions="newton", model_nam_file="{}.nam".format(gwfnamec), ) # Instantiating MODFLOW 6 discretization package for the child model child_dis_shp = lgr.get_shape() nlayc = child_dis_shp[0] nrowc = child_dis_shp[1] ncolc = child_dis_shp[2] disc = flopy.mf6.ModflowGwfdis( gwfc, nlay=nlayc, nrow=nrowc, ncol=ncolc, delr=delrc, delc=delcc, top=topc, botm=botmc, idomain=idomainc, filename="{}.dis".format(gwfnamec), ) # Instantiating MODFLOW 6 initial conditions package for child model strtc = [ topc - 0.25, topc - 0.25, topc - 0.25, topc - 0.25, topc - 0.25, topc - 0.25, ] icc = flopy.mf6.ModflowGwfic(gwfc, strt=strtc, filename="{}.ic".format(gwfnamec)) # Instantiating MODFLOW 6 node property flow package for child model icelltypec = [1, 1, 1, 0, 0, 0] npfc = flopy.mf6.ModflowGwfnpf( gwfc, save_flows=False, alternative_cell_averaging="AMT-LMK", icelltype=icelltypec, k=k11, k33=k33, save_specific_discharge=False, filename="{}.npf".format(gwfnamec), ) # Instantiating MODFLOW 6 output control package for the child model occ = flopy.mf6.ModflowGwfoc( gwfc, budget_filerecord="{}.bud".format(gwfnamec), head_filerecord="{}.hds".format(gwfnamec), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # Instantiating MODFLOW 6 Streamflow routing package for child model sfrc = flopy.mf6.ModflowGwfsfr( gwfc, print_stage=False, print_flows=False, budget_filerecord=gwfnamec + ".sfr.bud", save_flows=True, mover=True, pname="SFR-child", unit_conversion=86400.00, boundnames=False, nreaches=len(connsc), packagedata=pkdatc, connectiondata=connsc, perioddata=sfrspdc, filename="{}.sfr".format(gwfnamec), ) # Retrieve exchange data using Lgr class functionality exchange_data = lgr.get_exchange_data() # Establish MODFLOW 6 GWF-GWF exchange gwfgwf = flopy.mf6.ModflowGwfgwf( sim, exgtype="GWF6-GWF6", print_flows=True, print_input=True, exgmnamea=gwfname, exgmnameb=gwfnamec, nexg=len(exchange_data), exchangedata=exchange_data, mvr_filerecord="{}.mvr".format(name), pname="EXG-1", filename="{}.exg".format(name), ) # Instantiate MVR package mvrpack = [[gwfname, "SFR-parent"], [gwfnamec, "SFR-child"]] maxpackages = len(mvrpack) # Set up static SFR-to-SFR connections that remain fixed for entire simulation static_mvrperioddata = [ # don't forget to use 0-based values [ mvrpack[0][0], mvrpack[0][1], 7, mvrpack[1][0], mvrpack[1][1], 0, "FACTOR", 1.0, ], [ mvrpack[1][0], mvrpack[1][1], 88, mvrpack[0][0], mvrpack[0][1], 8, "FACTOR", 1, ], ] mvrspd = {0: static_mvrperioddata} maxmvr = 2 mvr = flopy.mf6.ModflowMvr( gwfgwf, modelnames=True, maxmvr=maxmvr, print_flows=True, maxpackages=maxpackages, packages=mvrpack, perioddata=mvrspd, filename="{}.mvr".format(name), ) return sim return None
def test_lgrutil(): nlayp = 5 nrowp = 5 ncolp = 5 delrp = 100. delcp = 100. topp = 100. botmp = [-100, -200, -300, -400, -500] idomainp = np.ones((nlayp, nrowp, ncolp), dtype=np.int) idomainp[0:2, 1:4, 1:4] = 0 ncpp = 3 ncppl = [1, 1, 0, 0, 0] lgr = Lgr(nlayp, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=ncpp, ncppl=ncppl, xllp=100., yllp=100.) # child shape assert lgr.get_shape() == (2, 9, 9), 'child shape is not (2, 9, 9)' # child delr/delc delr, delc = lgr.get_delr_delc() assert np.allclose(delr, delrp / ncpp), 'child delr not correct' assert np.allclose(delc, delcp / ncpp), 'child delc not correct' # child idomain idomain = lgr.get_idomain() assert idomain.min() == idomain.max() == 1 assert idomain.shape == (2, 9, 9) # replicated parent array ap = np.arange(nrowp * ncolp).reshape((nrowp, ncolp)) ac = lgr.get_replicated_parent_array(ap) assert ac[0, 0] == 6 assert ac[-1, -1] == 18 # top/bottom top, botm = lgr.get_top_botm() assert top.shape == (9, 9) assert botm.shape == (2, 9, 9) assert top.min() == top.max() == 100. assert botm.min() == botm.max() == 0. # exchange data exchange_data = lgr.get_exchange_data(angldegx=True, cdist=True) ans1 = [(0, 1, 0), (0, 0, 0), 1, 50.0, 16.666666666666668, 33.333333333333336, 0.0, 354.33819375782156] ans2 = [(1, 4, 3), (1, 8, 8), 1, 50.0, 16.666666666666668, 33.333333333333336, 90.0, 354.3381937578216] assert exchange_data[0] == ans1 assert exchange_data[-1] == ans2 assert len(exchange_data) == 72 # list of parent cells connected to a child cell assert lgr.get_parent_connections(0, 0, 0) == [((0, 1, 0), -1), ((0, 0, 1), 2)] assert lgr.get_parent_connections(1, 8, 8) == [((1, 3, 4), 1), ((1, 4, 3), -2)] return
def get_model(idx, dir): global child_domain global hclose name = ex[idx] # tdis period data nper = 1 tdis_rc = [] for i in range(nper): tdis_rc.append((1.0, 1, 1)) # solver data nouter, ninner = 100, 300 hclose, rclose, relax = 1e-12, 1e-3, 0.97 h_start = 1.0 # dis nlay, nrow, ncol = 3, 7, 7 nlayc = 1 row_s, row_e = 3, 5 col_s, col_e = 3, 5 ref_fct = 3 nrowc = ref_fct * ((row_e - row_s) + 1) ncolc = ref_fct * ((col_e - col_s) + 1) idomain = np.ones((nlay, nrow, ncol)) idomain[0, row_s - 1:row_e, col_s - 1:col_e] = 0 delrc = delr / ref_fct delcc = delc / ref_fct tops = [0.0, -100.0, -200.0, -300.0] xoriginc = 2 * delr yoriginc = 2 * delc # boundary stress period data left_chd = [ [(ilay, irow, 0), h_left] for ilay in range( 1) # apply chd only to top layer to drive vertical flow for irow in range(nrow) ] right_chd = [ [(ilay, irow, ncol - 1), h_right] for ilay in range( 1) # apply chd only to top layer to drive vertical flow for irow in range(nrow) ] chd_data = left_chd + right_chd chd_spd = {0: chd_data} # build MODFLOW 6 files ws = dir sim = flopy.mf6.MFSimulation( sim_name=name, version="mf6", exe_name="mf6", sim_ws=ws, memory_print_option="ALL", ) tdis = flopy.mf6.ModflowTdis(sim, time_units="DAYS", nper=nper, perioddata=tdis_rc) ims = flopy.mf6.ModflowIms( sim, print_option="SUMMARY", outer_dvclose=hclose, outer_maximum=nouter, under_relaxation="DBD", inner_maximum=ninner, inner_dvclose=hclose, rcloserecord=rclose, linear_acceleration="BICGSTAB", relaxation_factor=relax, ) # The parent model: gwf = flopy.mf6.ModflowGwf(sim, modelname=parent_name, save_flows=True) dis = flopy.mf6.ModflowGwfdis( gwf, nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, top=tops[0], botm=tops[1:], idomain=idomain, ) ic = flopy.mf6.ModflowGwfic(gwf, strt=h_start) npf = flopy.mf6.ModflowGwfnpf( gwf, save_specific_discharge=True, xt3doptions=False, save_flows=True, icelltype=0, k=k11, k33=k33, ) chd = flopy.mf6.ModflowGwfchd(gwf, stress_period_data=chd_spd) oc = flopy.mf6.ModflowGwfoc( gwf, head_filerecord="{}.hds".format(parent_name), budget_filerecord="{}.cbc".format(parent_name), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # The child model: gwfc = flopy.mf6.ModflowGwf(sim, modelname=child_name, save_flows=True) dis = flopy.mf6.ModflowGwfdis( gwfc, nlay=nlayc, nrow=nrowc, ncol=ncolc, delr=delrc, delc=delcc, top=tops[0], botm=tops[1], xorigin=xoriginc, yorigin=yoriginc, ) ic = flopy.mf6.ModflowGwfic(gwfc, strt=h_start) npf = flopy.mf6.ModflowGwfnpf( gwfc, save_specific_discharge=True, xt3doptions=False, save_flows=True, icelltype=0, k=k11, k33=k33, ) oc = flopy.mf6.ModflowGwfoc( gwfc, head_filerecord="{}.hds".format(child_name), budget_filerecord="{}.cbc".format(child_name), headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")], saverecord=[("HEAD", "LAST"), ("BUDGET", "LAST")], ) # LGR: nrowp = gwf.dis.nrow.get_data() ncolp = gwf.dis.ncol.get_data() delrp = gwf.dis.delr.array delcp = gwf.dis.delc.array topp = gwf.dis.top.array botmp = gwf.dis.botm.array idomainp = gwf.dis.idomain.array lgr = Lgr( 3, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=ref_fct, ncppl=[1, 0, 0], ) exgdata = lgr.get_exchange_data(angldegx=True, cdist=True) gwfgwf = flopy.mf6.ModflowGwfgwf( sim, exgtype="GWF6-GWF6", nexg=len(exgdata), exgmnamea=parent_name, exgmnameb=child_name, exchangedata=exgdata, print_flows=True, auxiliary=["ANGLDEGX", "CDIST"], dev_interfacemodel_on=ifmod[idx], ) return sim
def get_model(idx, dir): # grid properties nlay = 3 nrow = 6 ncol = 6 delr = 100. delc = 100. top = 300. botm = [200., 100., 0.] # hydraulic properties hk = 1. vk = 1. # Set the idomain of the parent model in order to # define where the child model will be located idomain = np.ones((nlay, nrow, ncol), dtype=int) idomain[:, 2:4, 2:4] = 0 ncpp = 1 ncppl = [1, 1, 1] lgr = Lgr(nlay, nrow, ncol, delr, delc, top, botm, idomain, ncpp, ncppl) name = ex[idx] # build MODFLOW 6 files # create simulation sim = flopy.mf6.MFSimulation(sim_name=name, version='mf6', exe_name='mf6', sim_ws=dir) # create tdis package tdis = flopy.mf6.ModflowTdis(sim) # create gwf model gwf = flopy.mf6.ModflowGwf(sim, modelname=namea, save_flows=True) # create iterative model solution and register the gwf model with it ims = flopy.mf6.ModflowIms(sim, outer_hclose=1e-9, inner_hclose=1.e-9) # dis dis = flopy.mf6.ModflowGwfdis(gwf, nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, top=top, botm=botm, idomain=idomain) # initial conditions ic = flopy.mf6.ModflowGwfic(gwf, pname='ic', strt=top) # node property flow npf = flopy.mf6.ModflowGwfnpf(gwf, save_specific_discharge=True, icelltype=0, k=hk, k33=vk) # chd chdspd = [] for k in range(nlay): for i in range(nrow): chdspd.append([(k, i, 0), 1.]) chdspd.append([(k, i, ncol - 1), 6.]) chd = flopy.mf6.ModflowGwfchd(gwf, stress_period_data=chdspd) # output control oc = flopy.mf6.ModflowGwfoc(gwf, pname='oc', budget_filerecord='{}.cbc'.format(namea), head_filerecord='{}.hds'.format(namea), headprintrecord=[('COLUMNS', 10, 'WIDTH', 15, 'DIGITS', 6, 'GENERAL')], saverecord=[('HEAD', 'ALL'), ('BUDGET', 'ALL')], printrecord=[('HEAD', 'ALL'), ('BUDGET', 'ALL')]) # create child gwf model cgwf = flopy.mf6.ModflowGwf(sim, modelname=nameb, save_flows=True) cnlay, cnrow, cncol = lgr.get_shape() cdelr, cdelc = lgr.get_delr_delc() ctop, cbotm = lgr.get_top_botm() xorigin, yorigin = lgr.get_lower_left() cidomain = lgr.get_idomain() cdis = flopy.mf6.ModflowGwfdis(cgwf, nlay=cnlay, nrow=cnrow, ncol=cncol, delr=cdelr, delc=cdelc, top=ctop, botm=cbotm, idomain=cidomain, xorigin=xorigin, yorigin=yorigin) cic = flopy.mf6.ModflowGwfic(cgwf, pname='ic', strt=top) cnpf = flopy.mf6.ModflowGwfnpf(cgwf, save_specific_discharge=True, icelltype=0, k=hk, k33=vk) oc = flopy.mf6.ModflowGwfoc(cgwf, pname='oc', budget_filerecord='{}.cbc'.format(nameb), head_filerecord='{}.hds'.format(nameb), headprintrecord=[('COLUMNS', 10, 'WIDTH', 15, 'DIGITS', 6, 'GENERAL')], saverecord=[('HEAD', 'ALL'), ('BUDGET', 'ALL')], printrecord=[('HEAD', 'ALL'), ('BUDGET', 'ALL')]) # exchange information exchangedata = lgr.get_exchange_data(angldegx=True, cdist=True) nexg = len(exchangedata) gwfe = flopy.mf6.ModflowGwfgwf(sim, exgtype='gwf6-gwf6', exgmnamea='a', exgmnameb='b', nexg=nexg, auxiliary=[('angldegx', 'cdist')], exchangedata=exchangedata) return sim
def build_model(sim_name, XT3D_in_models, XT3D_at_exchange): if config.buildModel: sim_ws = os.path.join(ws, sim_name) sim = flopy.mf6.MFSimulation(sim_name=sim_name, sim_ws=sim_ws, exe_name=config.mf6_exe) flopy.mf6.ModflowTdis(sim, nper=nper, perioddata=tdis_ds, time_units=time_units) flopy.mf6.ModflowIms( sim, linear_acceleration="bicgstab", outer_maximum=nouter, outer_dvclose=hclose, inner_maximum=ninner, inner_dvclose=hclose, rcloserecord="{} strict".format(rclose), ) # The coarse, outer model gwf_outer = flopy.mf6.ModflowGwf(sim, modelname=gwfname_outer, save_flows=True) flopy.mf6.ModflowGwfdis( gwf_outer, nlay=nlay, nrow=nrow, ncol=ncol, delr=delr, delc=delc, idomain=idomain, top=top, botm=botm, ) flopy.mf6.ModflowGwfnpf( gwf_outer, icelltype=icelltype, k=k11, save_specific_discharge=True, xt3doptions=XT3D_in_models, ) flopy.mf6.ModflowGwfic(gwf_outer, strt=strt) # constant head boundary LEFT left_chd = [[(ilay, irow, 0), h_left] for ilay in range(nlay) for irow in range(nrow)] chd_spd = {0: left_chd} flopy.mf6.ModflowGwfchd( gwf_outer, stress_period_data=chd_spd, pname="CHD-LEFT", filename="{}.left.chd".format(gwfname_outer), ) # constant head boundary RIGHT right_chd = [[(ilay, irow, ncol - 1), h_right] for ilay in range(nlay) for irow in range(nrow)] chd_spd = {0: right_chd} flopy.mf6.ModflowGwfchd( gwf_outer, stress_period_data=chd_spd, pname="CHD-RIGHT", filename="{}.right.chd".format(gwfname_outer), ) head_filerecord = "{}.hds".format(gwfname_outer) budget_filerecord = "{}.cbc".format(gwfname_outer) flopy.mf6.ModflowGwfoc( gwf_outer, head_filerecord=head_filerecord, budget_filerecord=budget_filerecord, saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], ) # the refined, inner model gwf_inner = flopy.mf6.ModflowGwf(sim, modelname=gwfname_inner, save_flows=True) flopy.mf6.ModflowGwfdis( gwf_inner, nlay=nlay, nrow=nrow_inner, ncol=ncol_inner, delr=delr_inner, delc=delc_inner, top=top, botm=botm, xorigin=xorigin, yorigin=yorigin, length_units=length_units, ) flopy.mf6.ModflowGwfic(gwf_inner, strt=strt) flopy.mf6.ModflowGwfnpf( gwf_inner, save_specific_discharge=True, xt3doptions=XT3D_in_models, save_flows=True, icelltype=icelltype, k=k11, ) head_filerecord = "{}.hds".format(gwfname_inner) budget_filerecord = "{}.cbc".format(gwfname_inner) flopy.mf6.ModflowGwfoc( gwf_inner, head_filerecord=head_filerecord, budget_filerecord=budget_filerecord, saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")], ) # Use Lgr to get the exchange data nrowp = gwf_outer.dis.nrow.get_data() ncolp = gwf_outer.dis.ncol.get_data() delrp = gwf_outer.dis.delr.array delcp = gwf_outer.dis.delc.array topp = gwf_outer.dis.top.array botmp = gwf_outer.dis.botm.array idomainp = gwf_outer.dis.idomain.array lgr = Lgr( nlay, nrowp, ncolp, delrp, delcp, topp, botmp, idomainp, ncpp=rfct, ncppl=1, ) exgdata = lgr.get_exchange_data(angldegx=True, cdist=True) for exg in exgdata: l = exg angle = l[-2] if angle == 0: bname = "left" elif angle == 90.0: bname = "bottom" elif angle == 180.0: bname = "right" elif angle == 270.0: bname = "top" l.append(bname) # group exchanges based on boundname exgdata.sort(key=lambda x: x[-3]) flopy.mf6.ModflowGwfgwf( sim, exgtype="GWF6-GWF6", nexg=len(exgdata), exgmnamea=gwfname_outer, exgmnameb=gwfname_inner, exchangedata=exgdata, xt3d=XT3D_at_exchange, print_input=True, print_flows=True, save_flows=True, boundnames=True, auxiliary=["ANGLDEGX", "CDIST"], ) return sim return None