Create MODFLOW 6 Model with FloPy¶
import flopy
import numpy as np
Model names and units¶
length_units = 'meters'
time_units = 'days'
sim_name = 'cat_ex_1d'
gwf_name = f'gwf_{sim_name}'
gwt_name = f'gwt_{sim_name}'
sim_ws = '../rtmf6/mf6'
concentration_name = 'concentration' # name for concentration
rtmf6_sol_number_name = 'rtmf6_sol_number' # solution number of PHREEQC solution
Make FloPy simulation¶
sim = flopy.mf6.MFSimulation(sim_name=sim_name, sim_ws=sim_ws)
Time discretization¶
Number of periods¶
nper = 1
Time step (\(days\))¶
tstep = 0.002 * 0.5
Simulation time (\(days\))¶
perlen = 0.24
Number of time steps¶
nstp = perlen / tstep
nstp
240.0
Create MF6 package¶
tdis = flopy.mf6.ModflowTdis(
sim,
nper=nper,
perioddata=[(perlen, nstp, 1.0)],
time_units=time_units)
Flow Model¶
gwf = flopy.mf6.ModflowGwf(
sim,
modelname=gwf_name,
save_flows=True,
model_nam_file=f"{gwf_name}.nam",
)
Solver for flow model¶
# solver parameters
nouter, ninner = 300, 600
hclose, rclose, relax = 1e-6, 1e-6, 1.0
imsgwf = flopy.mf6.ModflowIms(
sim,
complexity="complex",
print_option="SUMMARY",
outer_dvclose=hclose,
outer_maximum=nouter,
under_relaxation="NONE",
inner_maximum=ninner,
inner_dvclose=hclose,
rcloserecord=rclose,
linear_acceleration="CG",
scaling_method="NONE",
reordering_method="NONE",
relaxation_factor=relax,
filename=f"{gwf_name}.ims",
)
sim.register_ims_package(imsgwf, [gwf.name])
Model discretization¶
nlay = 1 # Number of layers
Lx = 0.08 #m Length of domain in x-direction (ncol * delr)
ncol = 40 # Number of columns
nrow = 1 # Number of rows
delr = Lx/ncol # Column spacing along a row ($m$)
dis = flopy.mf6.ModflowGwfdis(
gwf,
length_units=length_units,
nlay=nlay,
nrow=nrow,
ncol=ncol,
delr=delr,
filename=f"{gwf_name}.dis",
nogrb=True,
)
Hydraulic properties¶
k11 = 1.0 # Horizontal hydraulic conductivity ($m/d$)
k33 = k11 # Vertical hydraulic conductivity ($m/d$)
icelltype = 1 # saturated thickness varies with computed head when head is below the cell top
npf = flopy.mf6.ModflowGwfnpf(
gwf,
save_flows=True,
save_saturation=True,
icelltype=icelltype,
k=k11,
k33=k33,
save_specific_discharge=True,
filename=f"{gwf_name}.npf",
)
Initial conditions¶
flopy.mf6.ModflowGwfic(gwf, strt=1, filename=f"{gwf_name}.ic")
package_name = ic
filename = gwf_cat_ex_1d.ic
package_type = ic
model_or_simulation_package = model
model_name = gwf_cat_ex_1d
Block griddata
--------------------
strt
{constant 1}
Injection well¶
#injection
q = 1 #injection rate m3/d
concentration = 0 # will be replaced
rtmf6_sol_number = 0 # use solution from phreeqcrm/advect.pqi
wel_spd = [[(0, 0, 0), q, concentration, rtmf6_sol_number]] # well stress period data
auxiliary = [
concentration_name, # name for concentration
rtmf6_sol_number_name # solution number of PHREEQC solution
]
wel = flopy.mf6.ModflowGwfwel(
gwf,
stress_period_data=wel_spd,
save_flows=True,
auxiliary=auxiliary,
pname='wel',
filename=f"{gwf_name}.wel"
)
Constant Head BC¶
Keep head in last column constant.
Note the zero-based counting.
head = 1
chd_spd = [[(0, 0, ncol - 1), head]]
chd_spd
[[(0, 0, 39), 1]]
chd = flopy.mf6.ModflowGwfchd(
gwf,
maxbound=len(chd_spd),
stress_period_data=chd_spd,
save_flows=False,
pname="CHD",
filename=f"{gwf_name}.chd",
)
Output control of flow model¶
oc_gwf = flopy.mf6.ModflowGwfoc(
gwf,
head_filerecord=f"{gwf_name}.hds",
budget_filerecord=f"{gwf_name}.cbb",
headprintrecord=[("COLUMNS", 10, "WIDTH", 15, "DIGITS", 6, "GENERAL")],
saverecord=[("HEAD", "ALL"), ("BUDGET", "ALL")],
printrecord=[("HEAD", "LAST"), ("BUDGET", "LAST")],
)
Transport model¶
gwt = flopy.mf6.MFModel(
sim,
model_type="gwt6",
modelname=gwt_name,
model_nam_file=f"{gwt_name}.nam"
)
Iterative model solution for transport¶
imsgwt = 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=f"{gwt_name}.ims",
)
sim.register_ims_package(imsgwt, [gwt.name])
Model discretization for transport model¶
gwt_dis = flopy.mf6.ModflowGwtdis(
gwt,
length_units=length_units,
nlay=nlay,
nrow=nrow,
ncol=ncol,
delr=delr,
filename=f"{gwt_name}.dis",
nogrb=True,
)
Initial condition for transport¶
gwt_ic = flopy.mf6.ModflowGwtic(
gwt,
strt=1, # rtmf6 solution number
filename=f"{gwt_name}.ic")
Source-sink mixing¶
sourcerecarray = ['wel', 'aux', concentration_name]
ssm = flopy.mf6.ModflowGwtssm(
gwt,
sources=sourcerecarray,
save_flows=True,
print_flows=True,
filename=f"{gwt_name}.ssm"
)
Advection¶
adv = flopy.mf6.ModflowGwtadv(
gwt,
scheme="tvd",
)
Dispersion¶
Longitudinal dispersivity (\(m\))¶
dispersivity = 0.002
Transverse vertical dispersivity (\(m\))¶
transverse_vertical_dispersivity = dispersivity * 0.1
dsp = flopy.mf6.ModflowGwtdsp(
gwt,
xt3d_off=True,
alh=dispersivity,
ath1=transverse_vertical_dispersivity,
atv=transverse_vertical_dispersivity,
filename=f"{gwt_name}.dsp",
)
Transport mass storage¶
first_order_decay = None
porosity = 1
mst = flopy.mf6.ModflowGwtmst(
gwt,
porosity=porosity,
first_order_decay=first_order_decay,
filename=f"{gwt_name}.mst",
)
Add observation well for concentration¶
lay = 0
obs_dict = {
f'{gwt_name}.obs.csv':
[(
'concentration',
concentration_name,
(lay, nrow // 2, ncol - 2)
)
]
}
flopy.mf6.ModflowUtlobs(
gwt, print_input=False, continuous=obs_dict
)
package_name = obs_0
filename = gwt_cat_ex_1d.obs
package_type = obs
model_or_simulation_package = model
model_name = gwt_cat_ex_1d
Block options
--------------------
print_input
{internal}
(False)
Block continuous
--------------------
continuous
{internal}
(rec.array([('concentration', 'concentration', (0, 0, 38), None)],
dtype=[('obsname', 'O'), ('obstype', 'O'), ('id', 'O'), ('id2', 'O')]))
Output control package for transport¶
oc_gwt = flopy.mf6.ModflowGwtoc(
gwt,
budget_filerecord=f"{gwt_name}.cbb",
concentration_filerecord=f"{gwt_name}.ucn",
concentrationprintrecord=[
("COLUMNS", 10, "WIDTH", 15, "DIGITS", 10, "GENERAL")
],
saverecord=[("CONCENTRATION", "ALL"),
("BUDGET", "ALL")
],
printrecord=[("CONCENTRATION", "ALL"),
("BUDGET", "ALL")
],
)
Fow-transport exchange¶
flopy.mf6.ModflowGwfgwt(
sim,
exgtype="GWF6-GWT6",
exgmnamea=gwf_name,
exgmnameb=gwt_name,
filename=f"{sim_name}.gwfgwt",
)
package_name = cat_ex_1d.gwfgwt
filename = cat_ex_1d.gwfgwt
package_type = gwfgwt
model_or_simulation_package = simulation
simulation_name = cat_ex_1d
Write simulation¶
sim.write_simulation()
writing simulation...
writing simulation name file...
writing simulation tdis package...
writing solution package ims_-1...
writing solution package ims_0...
writing package cat_ex_1d.gwfgwt...
writing model gwf_cat_ex_1d...
writing model name file...
writing package dis...
writing package npf...
writing package ic...
writing package wel...
INFORMATION: maxbound in ('gwf6', 'wel', 'dimensions') changed to 1 based on size of stress_period_data
writing package chd...
writing package oc...
writing model gwt_cat_ex_1d...
writing model name file...
writing package dis...
writing package ic...
writing package ssm...
writing package adv...
writing package dsp...
writing package mst...
writing package obs_0...
writing package oc...