def plot_sfr_results(gwf, silent=True): fs = USGSFigure(figure_type="graph", verbose=False) # load the observations results = gwf.sfr.output.obs().data # modify the time results["totim"] /= 365.25 * 86400.0 rnos = ( 3, 14, 26, 35, ) sfr = gwf.sfr.packagedata.array["rtp"] offsets = [] for rno in rnos: offsets.append(sfr[rno]) # create the figure fig, axes = plt.subplots( ncols=2, nrows=4, sharex=True, figsize=(6.3, 6.3), constrained_layout=True, ) ipos = 0 for i in range(4): heading = "Reach {}".format(rnos[i] + 1) for j in range(2): ax = axes[i, j] ax.set_xlim(0, 100) if j == 0: tag = "R{:02d}_STAGE".format(i + 1) offset = offsets[i] scale = 1.0 ylabel = "Reach depth, in feet" color = "blue" else: tag = "R{:02d}_FLOW".format(i + 1) offset = 0.0 scale = -1.0 ylabel = "Downstream reach flow,\nin cubic feet per second" color = "red" ax.plot( results["totim"], scale * results[tag] - offset, lw=0.5, color=color, zorder=10, ) ax.axvline(50, lw=0.5, ls="--", color="black", zorder=10) if ax.get_ylim()[0] < 0.0: ax.axhline(0, lw=0.5, color="0.5", zorder=9) fs.add_text( ax, text="Pumping", x=0.49, y=0.8, ha="right", bold=False, fontsize=7, ) fs.add_text( ax, text="Recovery", x=0.51, y=0.8, ha="left", bold=False, fontsize=7, ) ax.set_ylabel(ylabel) ax.yaxis.set_label_coords(-0.1, 0.5) fs.heading(ax, heading=heading, idx=ipos) if i == 3: ax.set_xlabel("Time since pumping began, in years") ipos += 1 # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-02{}".format(sim_name, config.figure_ext), ) fig.savefig(fpth) return
def plot_grid(sim, silent=True): verbose = not silent fs = USGSFigure(figure_type="map", verbose=verbose) name = sim.name gwf = sim.get_model(name) fig, ax = plt.subplots(figsize=(6.8, 2.0)) mc = flopy.plot.PlotCrossSection(model=gwf, line={"Row": 0}, ax=ax) ax.fill_between([0, 1], y1=0, y2=botm, color="cyan", alpha=0.5) fs.add_text( ax=ax, text="Constant head", x=0.5, y=-500.0, bold=False, italic=False, transform=False, va="center", ha="center", fontsize=9, ) ax.fill_between([2, 3], y1=0, y2=botm, color="cyan", alpha=0.5) fs.add_text( ax=ax, text="Constant head", x=2.5, y=-500.0, bold=False, italic=False, transform=False, va="center", ha="center", fontsize=9, ) ax.fill_between([1, 2], y1=-499.5, y2=-500.5, color="brown", alpha=0.5) fs.add_annotation( ax=ax, text="Delay interbed", xy=(1.5, -510.0), xytext=(1.6, -300), bold=False, italic=False, fontsize=9, ha="center", va="center", zorder=100, arrowprops=arrow_props, ) mc.plot_grid(color="0.5", lw=0.5, zorder=100) ax.set_xlim(0, 3) ax.set_ylabel("Elevation, in meters") ax.set_xlabel("x-coordinate, in meters") fs.remove_edge_ticks(ax) plt.tight_layout() # save figure if config.plotSave: fpth = os.path.join("..", "figures", "{}-grid{}".format(sim_name, config.figure_ext)) if not silent: print("saving...'{}'".format(fpth)) fig.savefig(fpth)
def plot_calibration(silent=True): verbose = not silent fs = USGSFigure(figure_type="graph", verbose=verbose) name = list(parameters.keys())[1] pth = os.path.join(ws, name, "{}.csub.obs.csv".format(name)) df_sim = get_sim_dataframe(pth) df_sim.rename({"TOTAL": "simulated"}, inplace=True, axis=1) pth = os.path.join("..", "data", sim_name, "boundary_heads.csv") df_obs_heads, col_list = process_sim_csv(pth) ccolors = ( "black", "tan", "cyan", "brown", "blue", "violet", ) xf0 = datetime.datetime(1907, 1, 1, 0, 0, 0) xf1 = datetime.datetime(2007, 1, 1, 0, 0, 0) xf0s = datetime.datetime(1990, 1, 1, 0, 0, 0) xf1s = datetime.datetime(2007, 1, 1, 0, 0, 0) xc0 = datetime.datetime(1992, 10, 1, 0, 0, 0) xc1 = datetime.datetime(2006, 9, 4, 0, 0, 0) dx = xc1 - xc0 xca = xc0 + dx / 2 # get observation data df = get_obs_dataframe(file_name="008N010W01Q005S_obs.csv") ix0 = df.index.get_loc("2006-09-04 00:00:00") offset = df_sim["simulated"].values[-1] - df.observed.values[ix0] df.observed += offset # -- subplot a ----------------------------------------------------------- # build box for subplot B o = datetime.timedelta(31) ix = (xf0s, xf0s, xf1s - o, xf1s - o, xf0s) iy = (1.15, 1.45, 1.45, 1.15, 1.15) # -- subplot a ----------------------------------------------------------- # -- subplot c ----------------------------------------------------------- # get observations df_pc = get_obs_dataframe() # get index for start of calibration period for subplot c ix0 = df_sim.index.get_loc("1992-10-01 12:00:00") # get initial simulated compaction cstart = df_sim.simulated[ix0] # cut off initial portion of simulated compaction df_sim_pc = df_sim[ix0:].copy() # reset initial compaction to 0. df_sim_pc.simulated -= cstart # reset simulated so maximum compaction is the same offset = df_pc.observed.values.max() - df_sim_pc.simulated.values[-1] df_sim.simulated += offset # interpolate subsidence observations to the simulation index for subplot c df_iobs_pc = dataframe_interp(df_pc, df_sim_pc.index) # truncate head to start of observations head_pc = dataframe_interp(df_obs_heads, df_sim_pc.index) # calculate geostatic stress gs = sgm * (0.0 - head_pc.CHD_L01.values) + sgs * ( head_pc.CHD_L01.values - botm[-1] ) # calculate hydrostatic stress for subplot c u = head_pc.CHD_L13.values - botm[-1] # calculate effective stress es_obs = gs - u # set up indices for date text for plot c locs = ["{:04d}-10-01 12:00:00".format(yr) for yr in range(1992, 2006)] locs += ["{:04d}-04-01 12:00:00".format(yr) for yr in range(1993, 2007)] locs += ["2006-09-04 12:00:00"] ixs = [head_pc.index.get_loc(loc) for loc in locs] # -- subplot c ----------------------------------------------------------- ctext = "Calibration period\n{} to {}".format( xc0.strftime("%B %d, %Y"), xc1.strftime("%B %d, %Y") ) fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(6.8, 6.8)) # -- plot a -------------------------------------------------------------- ax = axes.flat[0] ax.set_xlim(xf0, xf1) ax.plot([xf0, xf1], [0, 0], lw=0.5, color="0.5") ax.plot( [ xf0, ], [ -10, ], marker=".", ms=1, lw=0, color="red", label="Holly site (8N/10W-1Q)", ) for idx, key in enumerate(pcomp): if key == "TOTAL": key = "simulated" color = ccolors[idx] label = clabels[idx] ax.plot( df_sim.index.values, df_sim[key].values, color=color, label=label, lw=0.75, ) ax.plot(ix, iy, lw=1.0, color="red", zorder=200) fs.add_text(ax=ax, text="B", x=xf0s, y=1.14, transform=False) ax.set_ylim(1.5, -0.1) ax.xaxis.set_ticks(df_xticks) ax.xaxis.set_major_formatter(mpl.dates.DateFormatter("%m/%d/%Y")) ax.set_ylabel("Compaction, in {}".format(length_units)) ax.set_xlabel("Year") fs.graph_legend(ax=ax, frameon=False) fs.heading(ax, letter="A") fs.remove_edge_ticks(ax=ax) # -- plot b -------------------------------------------------------------- ax = axes.flat[1] ax.set_xlim(xf0s, xf1s) ax.set_ylim(1.45, 1.15) ax.plot( df.index.values, df["observed"].values, marker=".", ms=1, lw=0, color="red", ) ax.plot( df_sim.index.values, df_sim["simulated"].values, color="black", label=label, lw=0.75, ) # plot lines for calibration ax.plot([xc0, xc0], [1.45, 1.15], color="black", lw=0.5, ls=":") ax.plot([xc1, xc1], [1.45, 1.15], color="black", lw=0.5, ls=":") fs.add_annotation( ax=ax, text=ctext, italic=False, bold=False, xy=(xc0 - o, 1.2), xytext=(xca, 1.2), ha="center", va="center", arrowprops=dict(arrowstyle="-|>", fc="black", lw=0.5), color="none", bbox=dict(boxstyle="square,pad=-0.07", fc="none", ec="none"), ) fs.add_annotation( ax=ax, text=ctext, italic=False, bold=False, xy=(xc1 + o, 1.2), xytext=(xca, 1.2), ha="center", va="center", arrowprops=dict(arrowstyle="-|>", fc="black", lw=0.5), bbox=dict(boxstyle="square,pad=-0.07", fc="none", ec="none"), ) ax.yaxis.set_ticks(np.linspace(1.15, 1.45, 7)) ax.xaxis.set_ticks(df_xticks1) ax.xaxis.set_major_locator(mpl.dates.YearLocator()) ax.xaxis.set_minor_locator(mpl.dates.YearLocator(month=6, day=15)) ax.xaxis.set_major_formatter(mpl.ticker.NullFormatter()) ax.xaxis.set_minor_formatter(mpl.dates.DateFormatter("%Y")) ax.tick_params(axis="x", which="minor", length=0) ax.set_ylabel("Compaction, in {}".format(length_units)) ax.set_xlabel("Year") fs.heading(ax, letter="B") fs.remove_edge_ticks(ax=ax) # -- plot c -------------------------------------------------------------- ax = axes.flat[2] ax.set_xlim(-0.01, 0.2) ax.set_ylim(368, 376) ax.plot( df_iobs_pc.observed.values, es_obs, marker=".", ms=1, color="red", lw=0, label="Holly site (8N/10W-1Q)", ) ax.plot( df_sim_pc.simulated.values, df_sim_pc.ES14.values, color="black", lw=0.75, label="Simulated", ) for idx, ixc in enumerate(ixs): text = "{}".format(df_iobs_pc.index[ixc].strftime("%m/%d/%Y")) if df_iobs_pc.index[ixc].month == 4: dxc = -0.001 dyc = -1 elif df_iobs_pc.index[ixc].month == 9: dxc = 0.002 dyc = 0.75 else: dxc = 0.001 dyc = 1 xc = df_iobs_pc.observed[ixc] yc = es_obs[ixc] fs.add_annotation( ax=ax, text=text, italic=False, bold=False, xy=(xc, yc), xytext=(xc + dxc, yc + dyc), ha="center", va="center", fontsize=7, arrowprops=dict(arrowstyle="-", color="red", fc="red", lw=0.5), bbox=dict(boxstyle="square,pad=-0.15", fc="none", ec="none"), ) xtext = "Total compaction since {}, in {}".format( df_sim_pc.index[0].strftime("%B %d, %Y"), length_units ) ytext = ( "Effective stress at the bottom of\nthe lower aquifer, in " + "{} of water".format(length_units) ) ax.set_xlabel(xtext) ax.set_ylabel(ytext) fs.heading(ax, letter="C") fs.remove_edge_ticks(ax=ax) fs.remove_edge_ticks(ax) # finalize figure fig.tight_layout(pad=0.01) # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-03{}".format(sim_name, config.figure_ext) ) if not silent: print("saving...'{}'".format(fpth)) fig.savefig(fpth)
def plot_gwseep_results(silent=True): fs = USGSFigure(figure_type="graph", verbose=False) # load the observations name = list(parameters.keys())[0] fpth = os.path.join(ws, name, "{}.surfrate.obs.csv".format(sim_name)) drn = np.genfromtxt(fpth, delimiter=",", names=True) name = list(parameters.keys())[1] fpth = os.path.join(ws, name, "{}.surfrate.obs.csv".format(sim_name)) uzf = np.genfromtxt(fpth, delimiter=",", names=True) time = drn["time"] / 86400.0 q0 = drn["SURFRATE"] q1 = uzf["SURFRATE"] mean_error = np.mean(q0 - q1) # create the figure fig, axes = plt.subplots( ncols=2, nrows=1, sharex=True, figsize=(6.3, 3.15), constrained_layout=True, ) ax = axes[0] ax.set_xlim(0, 365) ax.set_ylim(0, 175) xp, yp = [0.0], [uzf["NETINFIL"][0]] for idx in range(time.shape[0]): if idx == 0: x0, x1 = 0.0, time[idx] else: x0, x1 = time[idx - 1], time[idx] y2 = uzf["NETINFIL"][idx] xp.append(x0) xp.append(x1) yp.append(y2) yp.append(y2) ax.fill_between( [x0, x1], 0, y2=y2, lw=0, color="blue", step="post", ec="none", zorder=100, ) ax.plot(xp, yp, lw=0.5, color="black", zorder=101) plot_stress_periods(ax) fs.heading(ax, idx=0) ax.set_xlabel("Simulation time, in days") ax.set_ylabel( "Infiltration to the unsaturated zone,\nin cubic feet per second" ) ax = axes[-1] ax.set_xlim(0, 365) ax.set_ylim(50.8, 51.8) ax.plot( time, -drn["SURFRATE"], lw=0.75, ls="-", color="blue", label="Drainage package", ) ax.plot( time, -uzf["SURFRATE"], marker="o", ms=3, mfc="none", mec="black", markeredgewidth=0.5, lw=0.0, ls="-", color="red", label="UZF groundwater seepage", ) plot_stress_periods(ax) fs.graph_legend( ax, loc="upper center", ncol=1, frameon=True, edgecolor="none" ) fs.heading(ax, idx=1) fs.add_text( ax, "Mean Error {:.2e} cubic feet per second".format(mean_error), bold=False, italic=False, x=1.0, y=1.01, va="bottom", ha="right", fontsize=7, ) ax.set_xlabel("Simulation time, in days") ax.set_ylabel( "Groundwater seepage to the land surface,\nin cubic feet per second" ) # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-01{}".format(sim_name, config.figure_ext), ) fig.savefig(fpth) return
def plot_grid(sim, silent=True): verbose = not silent fs = USGSFigure(figure_type="map", verbose=verbose) name = sim.name gwf = sim.get_model(name) extents = gwf.modelgrid.extent # read simulated heads pth = os.path.join(ws, name, "{}.hds".format(name)) hobj = flopy.utils.HeadFile(pth) h0 = hobj.get_data(kstpkper=(0, 0)) h1 = hobj.get_data(kstpkper=(59, 1)) hsxs0 = h0[0, 8, :] hsxs1 = h1[0, 8, :] # get delr array dx = gwf.dis.delr.array # create x-axis for cross-section hxloc = np.arange(1000, 2000.0 * 15, 2000.0) # set cross-section location y = 2000.0 * 11.5 xsloc = [(extents[0], extents[1]), (y, y)] # well locations w1loc = (9.5 * 2000.0, 11.75 * 2000.0) w2loc = (6.5 * 2000.0, 8.5 * 2000.0) fig = plt.figure(figsize=(6.8, 5), constrained_layout=True) gs = mpl.gridspec.GridSpec(7, 10, figure=fig, wspace=5) plt.axis("off") ax = fig.add_subplot(gs[:, 0:6]) # ax.set_aspect('equal') mm = flopy.plot.PlotMapView(model=gwf, ax=ax, extent=extents) mm.plot_grid(lw=0.5, color="0.5") mm.plot_bc(ftype="WEL", kper=1, plotAll=True) mm.plot_bc(ftype="CHD", color="blue") mm.plot_bc(ftype="RCH", color="green") mm.plot_inactive(color_noflow="0.75") mm.ax.plot(xsloc[0], xsloc[1], color="orange", lw=1.5) # contour steady state heads cl = mm.contour_array( h0, masked_values=[1.0e30], levels=np.arange(115, 200, 5), colors="black", linestyles="dotted", linewidths=0.75, ) ax.clabel(cl, fmt="%3i", inline_spacing=0.1) # well text fs.add_annotation( ax=ax, text="Well 1, layer 2", bold=False, italic=False, xy=w1loc, xytext=(w1loc[0] - 3200, w1loc[1] + 1500), ha="right", va="center", zorder=100, arrowprops=arrow_props, ) fs.add_annotation( ax=ax, text="Well 2, layer 4", bold=False, italic=False, xy=w2loc, xytext=(w2loc[0] + 3000, w2loc[1]), ha="left", va="center", zorder=100, arrowprops=arrow_props, ) ax.set_ylabel("y-coordinate, in meters") ax.set_xlabel("x-coordinate, in meters") fs.heading(ax, letter="A", heading="Map view") fs.remove_edge_ticks(ax) ax = fig.add_subplot(gs[0:5, 6:]) mm = flopy.plot.PlotCrossSection(model=gwf, ax=ax, line={"row": 8}) mm.plot_grid(lw=0.5, color="0.5") # items for legend mm.ax.plot( -1000, -1000, "s", ms=5, color="green", mec="black", mew=0.5, label="Recharge", ) mm.ax.plot( -1000, -1000, "s", ms=5, color="red", mec="black", mew=0.5, label="Well", ) mm.ax.plot( -1000, -1000, "s", ms=5, color="blue", mec="black", mew=0.5, label="Constant head", ) mm.ax.plot( -1000, -1000, "s", ms=5, color="0.75", mec="black", mew=0.5, label="Inactive", ) mm.ax.plot( [-1000, -1001], [-1000, -1000], color="orange", lw=1.5, label="Cross-section line", ) # aquifer coloring ax.fill_between([0, dx.sum()], y1=150, y2=-100, color="cyan", alpha=0.5) ax.fill_between([0, dx.sum()], y1=-100, y2=-150, color="#D2B48C", alpha=0.5) ax.fill_between([0, dx.sum()], y1=-150, y2=-350, color="#00BFFF", alpha=0.5) # well coloring ax.fill_between([dx.cumsum()[8], dx.cumsum()[9]], y1=50, y2=-100, color="red", lw=0) # labels fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=300, y=-97, text="Upper aquifer", va="bottom", ha="left", fontsize=9, ) fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=300, y=-147, text="Confining unit", va="bottom", ha="left", fontsize=9, ) fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=300, y=-347, text="Lower aquifer", va="bottom", ha="left", fontsize=9, ) fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=29850, y=53, text="Layer 1", va="bottom", ha="right", fontsize=9, ) fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=29850, y=-97, text="Layer 2", va="bottom", ha="right", fontsize=9, ) fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=29850, y=-147, text="Layer 3", va="bottom", ha="right", fontsize=9, ) fs.add_text( ax=ax, transform=False, bold=False, italic=False, x=29850, y=-347, text="Layer 4", va="bottom", ha="right", fontsize=9, ) ax.plot( hxloc, hsxs0, lw=0.75, color="black", ls="dotted", label="Steady-state\nwater level", ) ax.plot( hxloc, hsxs1, lw=0.75, color="black", ls="dashed", label="Water-level at the end\nof stress-period 2", ) ax.set_ylabel("Elevation, in meters") ax.set_xlabel("x-coordinate along model row 9, in meters") fs.graph_legend( mm.ax, ncol=2, bbox_to_anchor=(0.5, -0.6), borderaxespad=0, frameon=False, loc="lower center", ) fs.heading(ax, letter="B", heading="Cross-section view") fs.remove_edge_ticks(ax) # save figure if config.plotSave: fpth = os.path.join("..", "figures", "{}-grid{}".format(sim_name, config.figure_ext)) if not silent: print("saving...'{}'".format(fpth)) fig.savefig(fpth)
def plot_grid(gwf, silent=True): sim_ws = os.path.join(ws, sim_name) # load the observations fpth = os.path.join(ws, sim_name, "{}.lak.obs.csv".format(sim_name)) lak_results = np.genfromtxt(fpth, delimiter=",", names=True) # create MODFLOW 6 head object file_name = gwf.oc.head_filerecord.get_data()[0][0] fpth = os.path.join(sim_ws, file_name) hobj = flopy.utils.HeadFile(fpth) # create MODFLOW 6 cell-by-cell budget object file_name = gwf.oc.budget_filerecord.get_data()[0][0] fpth = os.path.join(sim_ws, file_name) cobj = flopy.utils.CellBudgetFile(fpth, precision="double") kstpkper = hobj.get_kstpkper() head = hobj.get_data(kstpkper=kstpkper[0]) spdis = cobj.get_data(text="DATA-SPDIS", kstpkper=kstpkper[0]) # add lake stage to heads head[head == 1e30] = lak_results["STAGE"][-1] # observation locations xcenters, ycenters = gwf.modelgrid.xycenters[0], gwf.modelgrid.xycenters[1] p1 = (xcenters[3], ycenters[3]) p2 = (xcenters[13], ycenters[13]) fs = USGSFigure(figure_type="map", verbose=False) fig = plt.figure( figsize=(4, 6.9), tight_layout=True, ) plt.axis("off") nrows, ncols = 10, 1 axes = [fig.add_subplot(nrows, ncols, (1, 5))] axes.append(fig.add_subplot(nrows, ncols, (6, 8), sharex=axes[0])) for idx, ax in enumerate(axes): ax.set_xlim(extents[:2]) if idx == 0: 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("CHD", color="cyan") mm.plot_inactive(color_noflow="#5DBB63") mm.plot_grid(lw=0.5, color="black") cv = mm.contour_array( head, levels=np.arange(140, 160, 2), linewidths=0.75, linestyles="-", colors="blue", masked_values=masked_values, ) plt.clabel(cv, fmt="%1.0f") mm.plot_specific_discharge(spdis, normalize=True, color="0.75") ax.plot(p1[0], p1[1], marker="o", mfc="red", mec="black", ms=4) ax.plot(p2[0], p2[1], marker="o", mfc="red", mec="black", ms=4) ax.set_xlabel("x-coordinate, in feet") ax.set_ylabel("y-coordinate, in feet") fs.heading(ax, heading="Map view", idx=0) fs.add_text( ax, "A", x=p1[0] + 150, y=p1[1] + 150, transform=False, bold=False, color="red", ha="left", va="bottom", ) fs.add_text( ax, "B", x=p2[0] + 150, y=p2[1] + 150, transform=False, bold=False, color="red", ha="left", va="bottom", ) fs.remove_edge_ticks(ax) ax = axes[1] xs = flopy.plot.PlotCrossSection(gwf, ax=ax, line={"row": 8}) xs.plot_array(np.ones(shape3d), head=head, cmap="jet") xs.plot_bc("CHD", color="cyan", head=head) xs.plot_ibound(color_noflow="#5DBB63", head=head) xs.plot_grid(lw=0.5, color="black") ax.set_xlabel("x-coordinate, in feet") ax.set_ylim(67, 160) ax.set_ylabel("Elevation, in feet") fs.heading(ax, heading="Cross-section view", idx=1) fs.remove_edge_ticks(ax) # legend ax = axes[-1] ax.plot( -10000, -10000, lw=0, marker="s", ms=10, mfc="#5DBB63", mec="black", markeredgewidth=0.5, label="Lake boundary", ) ax.plot( -10000, -10000, lw=0, marker="s", ms=10, mfc="cyan", mec="black", markeredgewidth=0.5, label="Constant-head boundary", ) ax.plot( -10000, -10000, lw=0, marker="s", ms=10, mfc="blue", mec="black", markeredgewidth=0.5, label="Water table", ) ax.plot( -10000, -10000, lw=0, marker="o", ms=4, mfc="red", mec="black", markeredgewidth=0.5, label="Observation well", ) ax.plot( -10000, -10000, lw=0.75, ls="-", color="blue", label=r"Head contour, $ft$", ) ax.plot( -10000, -10000, lw=0, marker=u"$\u2192$", ms=10, mfc="0.75", mec="0.75", label="Normalized specific discharge", ) fs.graph_legend(ax, loc="lower center", ncol=2) # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-grid{}".format(sim_name, config.figure_ext), ) fig.savefig(fpth) return
def plot_maw_results(silent=True): fs = USGSFigure(figure_type="graph", verbose=False) # load the observations name = list(parameters.keys())[1] fpth = os.path.join(ws, name, "{}.maw.obs.csv".format(sim_name)) maw = flopy.utils.Mf6Obs(fpth).data name = list(parameters.keys())[2] fpth = os.path.join(ws, name, "{}.gwf.obs.csv".format(sim_name)) gwf = flopy.utils.Mf6Obs(fpth).data # process heads hgwf = 0.0 ihds = 0.0 for name in gwf.dtype.names: if name.startswith("H0_"): hgwf += gwf[name] ihds += 1.0 hgwf /= ihds if silent: print("MAW head: {} Average head: {}".format(maw["H0"], hgwf)) zelev = sorted(list(set(list(obs_elev.values()))), reverse=True) results = { "maw": {}, "gwf": {}, } for z in zelev: results["maw"][z] = 0.0 results["gwf"][z] = 0.0 for name in maw.dtype.names: if name.startswith("Q"): z = obs_elev[name] results["maw"][z] += 2.0 * maw[name] for name in gwf.dtype.names: if name.startswith("Q"): z = obs_elev[name] results["gwf"][z] += 2.0 * gwf[name] q0 = np.array(list(results["maw"].values())) q1 = np.array(list(results["gwf"].values())) mean_error = np.mean(q0 - q1) if silent: print("total well inflow: {}".format(q0[q0 >= 0].sum())) print("total well outflow: {}".format(q0[q0 < 0].sum())) print("total cell inflow: {}".format(q1[q1 >= 0].sum())) print("total cell outflow: {}".format(q1[q1 < 0].sum())) # create the figure fig, ax = plt.subplots( ncols=1, nrows=1, sharex=True, figsize=(4, 4), constrained_layout=True, ) ax.set_xlim(-3.5, 3.5) ax.set_ylim(-67.5, -2.5) ax.axvline(0, lw=0.5, ls=":", color="0.5") for z in np.arange(-5, -70, -5): ax.axhline(z, lw=0.5, color="0.5") ax.plot( results["maw"].values(), zelev, lw=0.75, ls="-", color="blue", label="Multi-aquifer well", ) ax.plot( results["gwf"].values(), zelev, marker="o", ms=4, mfc="red", mec="black", markeredgewidth=0.5, lw=0.0, ls="-", color="red", label="High K well", ) ax.plot( -1000, -1000, lw=0.5, ls="-", color="0.5", label="Grid cell", ) fs.graph_legend(ax, loc="upper left", ncol=1, frameon=True) fs.add_text( ax, "Mean Error {:.2e} cubic feet per day".format(mean_error), bold=False, italic=False, x=1.0, y=1.01, va="bottom", ha="right", fontsize=7, ) ax.set_xlabel("Discharge rate, in cubic feet per day") ax.set_ylabel("Elevation, in feet") # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-01{}".format(sim_name, config.figure_ext), ) fig.savefig(fpth) return
def plot_grid(gwf, silent=True): sim_ws = os.path.join(ws, sim_name) # create lake array ilake = gwf.dis.idomain.array ilake[ilake == 0] = 100 ilake[ilake == 1] = 0 ilake[ilake == 100] = 1 for k in range(nlay): for i in range(16, nrow): for j in range(ncol): if ilake[k, i, j] == 1: ilake[k, i, j] = 2 # get edges and centers of cells xedges, yedges = gwf.modelgrid.xyedges[0], gwf.modelgrid.xyedges[1] xcenters, ycenters = gwf.modelgrid.xycenters[0], gwf.modelgrid.xycenters[1] # create sfr network poly0 = [ [xcenters[4], yedges[1]], [xcenters[4], ycenters[4]], [xcenters[7], ycenters[4]], [xcenters[7], yedges[6]], ] poly1 = [ [xcenters[8], yedges[11]], [xcenters[8], yedges[13]], [xcenters[9], yedges[14]], [xcenters[9], yedges[16]], ] poly2 = [ [xcenters[9], yedges[21]], [xcenters[9], ycenters[22]], [xedges[16], ycenters[22]], ] parts = [poly0, poly1, poly2] shape_pth = os.path.join(ws, sim_name, "sfr.shp") w = shp.Writer(target=shape_pth, shapeType=shp.POLYLINE) w.field("no", "C") w.line([poly0]) w.record(["1"]) w.line([poly1]) w.record(["2"]) w.line([poly2]) w.record(["3"]) w.close() sfr = shp.Reader(shape_pth) # load the observations fpth = os.path.join(ws, sim_name, "{}.lak.obs.csv".format(sim_name)) lak_results = np.genfromtxt(fpth, delimiter=",", names=True) # create MODFLOW 6 head object file_name = gwf.oc.head_filerecord.get_data()[0][0] fpth = os.path.join(sim_ws, file_name) hobj = flopy.utils.HeadFile(fpth) # create MODFLOW 6 cell-by-cell budget object file_name = gwf.oc.budget_filerecord.get_data()[0][0] fpth = os.path.join(sim_ws, file_name) cobj = flopy.utils.CellBudgetFile(fpth, precision="double") kstpkper = hobj.get_kstpkper() head = hobj.get_data(kstpkper=kstpkper[0]) spdis = cobj.get_data(text="DATA-SPDIS", kstpkper=kstpkper[0]) # add lake stage to heads head[ilake == 1] = lak_results["LAKE1"][-1] head[ilake == 2] = lak_results["LAKE2"][-1] # observation locations p1 = (xcenters[3], ycenters[3]) p2 = (xcenters[8], ycenters[13]) p3 = (xcenters[13], ycenters[23]) # lake text locations pl1 = (xcenters[8], ycenters[8]) pl2 = (xcenters[8], ycenters[18]) fs = USGSFigure(figure_type="map", verbose=False) fig = plt.figure( figsize=(4, 6.9), 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("CHD", color="cyan") for shape in sfr.shapeRecords(): x = [i[0] for i in shape.shape.points[:]] y = [i[1] for i in shape.shape.points[:]] ax.plot(x, y, color="#3BB3D0", lw=1.5, zorder=1) mm.plot_inactive(color_noflow="#5DBB63") mm.plot_grid(lw=0.5, color="black") cv = mm.contour_array( head, levels=np.arange(120, 160, 5), linewidths=0.75, linestyles="-", colors="blue", masked_values=masked_values, ) plt.clabel(cv, fmt="%1.0f") mm.plot_specific_discharge(spdis, normalize=True, color="0.75") ax.plot(p1[0], p1[1], marker="o", mfc="red", mec="black", ms=4) ax.plot(p2[0], p2[1], marker="o", mfc="red", mec="black", ms=4) ax.plot(p3[0], p3[1], marker="o", mfc="red", mec="black", ms=4) ax.set_xlabel("x-coordinate, in feet") ax.set_ylabel("y-coordinate, in feet") fs.add_text( ax, "A", x=p1[0] + 150, y=p1[1] + 150, transform=False, bold=False, color="red", ha="left", va="bottom", ) fs.add_text( ax, "B", x=p2[0] + 150, y=p2[1] + 150, transform=False, bold=False, color="red", ha="left", va="bottom", ) fs.add_text( ax, "C", x=p3[0] + 150, y=p3[1] + 150, transform=False, bold=False, color="red", ha="left", va="bottom", ) fs.add_text( ax, "Lake 1", x=pl1[0], y=pl1[1], transform=False, italic=False, color="white", ha="center", va="center", ) fs.add_text( ax, "Lake 2", x=pl2[0], y=pl2[1], transform=False, italic=False, color="white", ha="center", va="center", ) fs.remove_edge_ticks(ax) # legend ax = axes[-1] ax.plot( -10000, -10000, lw=0, marker="s", ms=10, mfc="#5DBB63", mec="black", markeredgewidth=0.5, label="Lake boundary", ) ax.plot( -10000, -10000, lw=0, marker="s", ms=10, mfc="cyan", mec="black", markeredgewidth=0.5, label="Constant-head boundary", ) ax.plot( -10000, -10000, lw=1.5, color="#3BB3D0", label="Stream network", ) ax.plot( -10000, -10000, lw=0, marker="o", ms=4, mfc="red", mec="black", markeredgewidth=0.5, label="Observation well", ) ax.plot( -10000, -10000, lw=0.75, ls="-", color="blue", label=r"Head contour, $ft$", ) ax.plot( -10000, -10000, lw=0, marker=u"$\u2192$", ms=10, mfc="0.75", mec="0.75", label="Normalized specific discharge", ) fs.graph_legend(ax, loc="lower center", ncol=2) # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-grid{}".format(sim_name, config.figure_ext), ) fig.savefig(fpth) return
def plot_results(silent=True): verbose = not silent if verbose: verbosity_level = 1 else: verbosity_level = 0 if config.plotModel: fs = USGSFigure(figure_type="map", verbose=verbose) # load the newton model name = list(parameters.keys())[0] sim_ws = os.path.join(ws, name) sim = flopy.mf6.MFSimulation.load(sim_name=sim_name, sim_ws=sim_ws, verbosity_level=verbosity_level) gwf = sim.get_model(sim_name) bot = gwf.dis.botm.array xnode = gwf.modelgrid.xcellcenters[0, :] # create MODFLOW 6 head object file_name = gwf.oc.head_filerecord.get_data()[0][0] fpth = os.path.join(sim_ws, file_name) hobj = flopy.utils.HeadFile(fpth) # get a list of times times = hobj.get_times() # load rewet model name = list(parameters.keys())[1] sim_ws = os.path.join(ws, name) # create MODFLOW 6 head object file_name = gwf.oc.head_filerecord.get_data()[0][0] fpth = os.path.join(sim_ws, file_name) hobj1 = flopy.utils.HeadFile(fpth) # Create figure for simulation fig, axes = plt.subplots( ncols=1, nrows=4, sharex=True, figsize=figure_size, constrained_layout=False, ) # plot the results for idx, ax in enumerate(axes): # extract heads and specific discharge for newton model head = hobj.get_data(totim=times[idx]) head = get_water_table(head, bot) # extract heads and specific discharge for newton model head1 = hobj1.get_data(totim=times[idx]) head1 = get_water_table(head1, bot) # calculate mean error diff = np.abs(head - head1) # print("max", diff.max(), np.argmax(diff)) me = diff.sum() / float(ncol * nrow) me_text = "Mean absolute water-table error {:.3f} feet".format(me) ax.set_xlim(extents[:2]) ax.set_ylim(extents[2:]) mm = flopy.plot.PlotCrossSection(model=gwf, ax=ax, extent=extents, line={"row": 1}) mm.plot_bc("CHD", color="cyan") mm.plot_grid(lw=0.5) ax.plot( xnode, head[0, :], lw=0.75, color="black", label="Newton-Raphson", ) ax.plot( xnode, head1[0, :], lw=0, marker="o", ms=4, mfc="none", mec="blue", label="Rewetting", ) if idx == 0: ax.plot( -1000, -1000, lw=0, marker="s", ms=4, mec="0.5", mfc="none", label="Model cell", ) ax.plot( -1000, -1000, lw=0, marker="s", ms=4, mec="0.5", mfc="cyan", label="Constant head", ) fs.graph_legend( ax, loc="upper right", ncol=2, frameon=True, facecolor="white", edgecolor="none", ) letter = chr(ord("@") + idx + 1) fs.heading(letter=letter, ax=ax) fs.add_text(ax, text=me_text, x=1, y=1.01, ha="right", bold=False) fs.remove_edge_ticks(ax) # set fake y-axis label ax.set_ylabel(" ") # set fake x-axis label ax.set_xlabel(" ") ax = fig.add_subplot(1, 1, 1, frameon=False) ax.tick_params(labelcolor="none", top="off", bottom="off", left="off", right="off") ax.set_xlim(0, 1) ax.set_xticks([0, 1]) ax.set_xlabel("x-coordinate, in feet") ax.set_ylim(0, 1) ax.set_yticks([0, 1]) ax.set_ylabel("Water-table elevation above arbitrary datum, in meters") fs.remove_edge_ticks(ax) # save figure if config.plotSave: fpth = os.path.join( "..", "figures", "{}-01{}".format(sim_name, config.figure_ext), ) fig.savefig(fpth)