This page was generated from ex-gwf-maw-p02.py. It's also available as a notebook.

Multi-Aquifer Well Problem, Flowing Well Option

This is a modified version of the Neville-Tonkin Multi-Aquifer Well problem from Neville and Tonkin, 2004 that uses the flowing well option.

Initial setup

Import dependencies, define the example name and workspace, and read settings from environment variables.

[1]:
import os
import pathlib as pl

import flopy
import git
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from flopy.plot.styles import styles
from modflow_devtools.misc import get_env, timed

# Example name and workspace paths. If this example is running
# in the git repository, use the folder structure described in
# the README. Otherwise just use the current working directory.
sim_name = "ex-gwf-maw-p02"
try:
    root = pl.Path(git.Repo(".", search_parent_directories=True).working_dir)
except:
    root = None
workspace = root / "examples" if root else pl.Path.cwd()
figs_path = root / "figures" if root else pl.Path.cwd()

# Settings from environment variables
write = get_env("WRITE", True)
run = get_env("RUN", True)
plot = get_env("PLOT", True)
plot_show = get_env("PLOT_SHOW", True)
plot_save = get_env("PLOT_SAVE", True)

Define parameters

Define model units, parameters and other settings.

[2]:
# Model units
length_units = "meters"
time_units = "days"

# Model parameters
nper = 1  # Number of periods
nlay = 2  # Number of layers
nrow = 101  # Number of rows
ncol = 101  # Number of columns
delr = 142.0  # Column width ($m$)
delc = 142.0  # Row width ($m$)
top = -50.0  # Top of the model ($m$)
botm_str = "-142.9, -514.5"  # Bottom elevations ($m$)
strt_str = "3.05, 9.14"  # Starting head ($m$)
k11 = 1.0  # Horizontal hydraulic conductivity ($m/d$)
k33 = 1.0e-16  # Vertical hydraulic conductivity ($m/d$)
ss = 1e-4  # Specific storage ($1/d$)
maw_radius = 0.15  # Well radius ($m$)
maw_rate = 0.0  # Well pumping rate ($m^{3}/d$)

# parse parameter strings into tuples
botm = [float(value) for value in botm_str.split(",")]
strt = [float(value) for value in strt_str.split(",")]

# Static temporal data used by TDIS file
tdis_ds = ((2.314815, 50, 1.2),)

# Define dimensions
extents = (0.0, delr * ncol, 0.0, delc * nrow)
shape2d = (nrow, ncol)
shape3d = (nlay, nrow, ncol)

# create idomain
idomain = np.ones(shape3d, dtype=float)
xw, yw = (ncol / 2) * delr, (nrow / 2) * delc
y = 0.0
for i in range(nrow):
    x = 0.0
    y = (float(i) + 0.5) * delc
    for j in range(ncol):
        x = (float(j) + 0.5) * delr
        r = np.sqrt((x - xw) ** 2.0 + (y - yw) ** 2.0)
        if r > 7163.0:
            idomain[:, i, j] = 0

# MAW Package boundary conditions
maw_row = int(nrow / 2)
maw_col = int(ncol / 2)
maw_packagedata = [[0, maw_radius, botm[-1], strt[-1], "SPECIFIED", 2]]
maw_conn = [
    [0, 0, 0, maw_row, maw_col, top, botm[-1], 111.3763, -999.0],
    [0, 1, 1, maw_row, maw_col, top, botm[-1], 445.9849, -999.0],
]
maw_spd = [[0, "rate", maw_rate], [0, "flowing_well", 0.0, 7500.0, 0.5]]

# Solver parameters
nouter = 500
ninner = 100
hclose = 1e-9
rclose = 1e-4

Model setup

Define functions to build models, write input files, and run the simulation.

[3]:
def build_models():
    sim_ws = os.path.join(workspace, sim_name)
    sim = flopy.mf6.MFSimulation(sim_name=sim_name, sim_ws=sim_ws, exe_name="mf6")
    flopy.mf6.ModflowTdis(sim, nper=nper, perioddata=tdis_ds, time_units=time_units)
    flopy.mf6.ModflowIms(
        sim,
        print_option="summary",
        outer_maximum=nouter,
        outer_dvclose=hclose,
        inner_maximum=ninner,
        inner_dvclose=hclose,
        rcloserecord=f"{rclose} strict",
    )
    gwf = flopy.mf6.ModflowGwf(sim, modelname=sim_name, save_flows=True)
    flopy.mf6.ModflowGwfdis(
        gwf,
        length_units=length_units,
        nlay=nlay,
        nrow=nrow,
        ncol=ncol,
        delr=delr,
        delc=delc,
        top=top,
        botm=botm,
        idomain=idomain,
    )
    flopy.mf6.ModflowGwfnpf(
        gwf,
        icelltype=0,
        k=k11,
        k33=k33,
        save_specific_discharge=True,
    )
    flopy.mf6.ModflowGwfsto(
        gwf,
        iconvert=0,
        ss=ss,
    )
    flopy.mf6.ModflowGwfic(gwf, strt=strt)

    maw = flopy.mf6.ModflowGwfmaw(
        gwf,
        flowing_wells=True,
        nmawwells=1,
        packagedata=maw_packagedata,
        connectiondata=maw_conn,
        perioddata=maw_spd,
    )
    obs_file = f"{sim_name}.maw.obs"
    csv_file = obs_file + ".csv"
    obs_dict = {
        csv_file: [
            ("head", "head", (0,)),
            ("Q1", "maw", (0,), (0,)),
            ("Q2", "maw", (0,), (1,)),
            ("FW", "fw-rate", (0,)),
        ]
    }
    maw.obs.initialize(
        filename=obs_file, digits=10, print_input=True, continuous=obs_dict
    )

    flopy.mf6.ModflowGwfoc(
        gwf,
        printrecord=[("BUDGET", "LAST")],
    )
    return sim


def write_models(sim, silent=True):
    sim.write_simulation(silent=silent)


@timed
def run_models(sim, silent=True):
    success, buff = sim.run_simulation(silent=silent)
    assert success, buff

Plotting results

Define functions to plot model results.

[4]:
# Set figure properties specific to the
figure_size = (6.3, 4.3)
masked_values = (0, 1e30, -1e30)


def plot_maw_results(silent=True):
    with styles.USGSPlot():
        # load the observations
        fpth = os.path.join(workspace, sim_name, f"{sim_name}.maw.obs.csv")
        maw = flopy.utils.Mf6Obs(fpth).data

        time = maw["totim"] * 86400.0

        tmin = time[0]
        tmax = time[-1]

        # create the figure
        fig, axes = plt.subplots(
            ncols=1,
            nrows=2,
            sharex=True,
            figsize=figure_size,
            constrained_layout=True,
        )

        ax = axes[0]
        ax.set_xlim(tmin, tmax)
        ax.set_ylim(0, 4500)
        ax.semilogx(
            time,
            maw["Q1"],
            lw=0.75,
            ls="-",
            color="blue",
            label="Upper aquifer",
        )
        ax.semilogx(
            time,
            maw["Q2"],
            lw=0.75,
            ls="-",
            color="red",
            label="Lower aquifer",
        )
        ax.axhline(0, lw=0.5, color="0.5")
        ax.set_ylabel(" ")
        styles.heading(ax, idx=0)
        # styles.graph_legend(ax, loc="upper right", ncol=2)

        ax = axes[1]
        ax.set_xlim(tmin, tmax)
        ax.set_ylim(-4500, 0)
        ax.axhline(
            10.0,
            lw=0.75,
            ls="-",
            color="blue",
            label="Upper aquifer",
        )
        ax.axhline(
            10.0,
            lw=0.75,
            ls="-",
            color="red",
            label="Lower aquifer",
        )
        ax.semilogx(
            time,
            maw["FW"],
            lw=0.75,
            ls="-",
            color="black",
            label="Flowing well discharge",
        )
        ax.set_xlabel(" ")
        ax.set_ylabel(" ")
        for axis in (ax.xaxis,):
            axis.set_major_formatter(mpl.ticker.ScalarFormatter())
        styles.heading(ax, idx=1)
        styles.graph_legend(ax, loc="upper left", ncol=1)

        # add y-axis label that spans both subplots
        ax = fig.add_subplot(1, 1, 1)
        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)

        # get rid of ticks and spines for legend area
        # ax.axis("off")
        ax.set_xticks([])
        ax.set_yticks([])
        ax.spines["top"].set_color("none")
        ax.spines["bottom"].set_color("none")
        ax.spines["left"].set_color("none")
        ax.spines["right"].set_color("none")
        ax.patch.set_alpha(0.0)

        ax.set_xlabel("Simulation time, in seconds")
        ax.set_ylabel("Discharge rate, in cubic meters per day")

        if plot_show:
            plt.show()
        if plot_save:
            fpth = figs_path / f"{sim_name}-01.png"
            fig.savefig(fpth)


def plot_grid(sim, silent=True):
    gwf = sim.get_model(sim_name)
    with styles.USGSMap():
        fig = plt.figure(
            figsize=(4, 4.3),
            tight_layout=True,
        )
        plt.axis("off")

        nrows, ncols = 10, 1
        axes = [fig.add_subplot(nrows, ncols, (1, 8))]

        for idx, ax in enumerate(axes):
            ax.set_xlim(extents[:2])
            ax.set_ylim(extents[2:])
            ax.set_aspect("equal")

        # legend axis
        axes.append(fig.add_subplot(nrows, ncols, (9, 10)))

        # set limits for legend area
        ax = axes[-1]
        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)

        # get rid of ticks and spines for legend area
        ax.axis("off")
        ax.set_xticks([])
        ax.set_yticks([])
        ax.spines["top"].set_color("none")
        ax.spines["bottom"].set_color("none")
        ax.spines["left"].set_color("none")
        ax.spines["right"].set_color("none")
        ax.patch.set_alpha(0.0)

        ax = axes[0]
        mm = flopy.plot.PlotMapView(gwf, ax=ax, extent=extents)
        mm.plot_bc("MAW", color="red")
        mm.plot_inactive(color_noflow="black")
        ax.set_xticks([0, extents[1] / 2, extents[1]])
        ax.set_yticks([0, extents[1] / 2, extents[1]])

        ax = axes[-1]
        ax.plot(
            -10000,
            -10000,
            lw=0,
            marker="s",
            ms=10,
            mfc="black",
            mec="black",
            markeredgewidth=0.5,
            label="Inactive cells",
        )
        ax.plot(
            -10000,
            -10000,
            lw=0,
            marker="s",
            ms=10,
            mfc="red",
            mec="red",
            markeredgewidth=0.5,
            label="Multi-aquifer well",
        )
        styles.graph_legend(ax, loc="lower center", ncol=2)

        if plot_show:
            plt.show()
        if plot_save:
            fpth = figs_path / f"{sim_name}-grid.png"
            fig.savefig(fpth)


def plot_results(sim, silent=True):
    plot_grid(sim, silent=silent)
    plot_maw_results(silent=silent)

Running the example

Define and invoke a function to run the example scenario, then plot results.

[5]:
def scenario(silent=True):
    sim = build_models()
    if write:
        write_models(sim, silent=silent)
    if run:
        run_models(sim, silent=silent)
    if plot:
        plot_results(sim, silent=silent)


scenario()
<flopy.mf6.data.mfstructure.MFDataItemStructure object at 0x7f5e97c11670>
run_models took 2291.26 ms
../_images/_notebooks_ex-gwf-maw-p02_10_2.png
../_images/_notebooks_ex-gwf-maw-p02_10_3.png