<jupyter_start><jupyter_text>Builder Tutorial number 6The builder tutorials demonstrate how to build an operational GSFLOW model using `pyGSFLOW` from shapefile, DEM, and other common data sources. These tutorials focus on the `gsflow.builder` classes. Building modflow input filesIn this tutorial, we demonstrate how to build modflow input files for GSFLOW and MODFLOW-NWT models. The building method relies on a number of defaults stored within pyGSFLOW, which allows the user to 1) rapidly generate a basic Modflow model, and 2) later adjust it using pyGSFLOW and FloPy functionality.<jupyter_code>import os
import shapefile
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
import flopy
import platform
from gsflow.builder import GenerateFishnet, FlowAccumulation<jupyter_output><empty_output><jupyter_text>The `ModflowBuilder` classThe `ModflowBuilder` class builds a steady state MODFLOW-NWT model from pyGSFLOW default MODFLOW parameter values and user supplied information. This class has support to build MODFLOW's DIS, BAS6, UPW, NWT, OC, UZF, and SFR packages, either individually or bundled together as a `gsflow.modflow.Modflow` object.The `ModflowBuilder` class has 3 required parameters and one optional parameter:   **REQUIRED parameters**   - `modelgrid` : modelgrid instance from GenerateFishnet (flopy.discretization.StructuredGrid object)   - `dem_data` : numpy array of resampled DEM map data   - `model_name` : name of the model to build   **OPTIONAL parameters**   - `defaults` : optional parameter, user can supply a gsflow.builder.Defaults instance to ModflowBuilder to use a custom set of default values   Let's start by importing the class<jupyter_code>from gsflow.builder import ModflowBuilder<jupyter_output><empty_output><jupyter_text>Applying the methods to the Sagehen 50m example problemIn this example the methods are applied directly to the Sagehen 50m model as they are presented.<jupyter_code># define the input and output data paths
input_ws = os.path.join("data", "sagehen", "50m_tutorials")
output_ws = os.path.join("data", "temp")

# define the modelgrid and resampled DEM data paths
mg_file = os.path.join(input_ws, "sagehen_50m_grid.bin")
dem_data = os.path.join(input_ws, "sagehen_50m_dem.txt")

# define the watershed data path
watershed_file = os.path.join(input_ws, "sagehen_50m_watershed.txt")

# define the stream information binary data path
stream_file = os.path.join(input_ws, "sagehen_50m_streams.bin")<jupyter_output><empty_output><jupyter_text>Load the previously processed data<jupyter_code># load modelgrid, dem, watershed, and stream information file
modelgrid = GenerateFishnet.load_from_file(mg_file)
dem_data = np.genfromtxt(dem_data)
watershed = np.genfromtxt(watershed_file, dtype=int)
strm_obj = FlowAccumulation.load_streams(stream_file)<jupyter_output><empty_output><jupyter_text>Now that the modelgrid, resampled dem, watershed, and streamflow information has been loaded. `ModflowBuilder` can be instantiatedIn this example only the required parameters are supplied to `ModflowBuilder` on instantiation and the built in `Defaults` will be used to create the initial iteration of the Sagehen 50m model.<jupyter_code>mfbuild = ModflowBuilder(modelgrid, dem_data, "sagehen_50m")<jupyter_output><empty_output><jupyter_text>Creating individual packages with `ModflowBuilder`Individual packages can be created with the `ModflowBuilder` object and they are added to the base model object contained within the `ModflowBuilder` class. This section will step through how to build each individual package  Building the DIS objectThe `build_dis` method allows the user to build a 1 layer steady state model DIS file with the built in defaults.The `build_dis` method has one optional parameter:   - `botm` : numpy array that defines the cell bottom elevations (defaults to 50 model units less than model top)   Here is an example<jupyter_code># set the botm elevation to be 100 m less than the top
botm = dem_data - 100
botm.shape = (1, modelgrid.nrow, modelgrid.ncol)

# build a DIS file
dis = mfbuild.build_dis(botm=botm)
print(type(dis))<jupyter_output><class 'flopy.modflow.mfdis.ModflowDis'><jupyter_text>Building the BAS objectThe `build_bas` method allows the user to create a BAS package for their model.The `build_bas` method has one optional parameter:   - `ibound` : numpy array that defines the active and inactive cells in model (defaults to all cells active)Here is an example<jupyter_code>bas6 = mfbuild.build_bas6(ibound=watershed)
print(type(bas6))<jupyter_output><class 'flopy.modflow.mfbas.ModflowBas'><jupyter_text>Building the UPW objectThe `build_upw` method allows the user to create a UPW package for their model from builder defaults. The model is built with unconfined conditions.Here is an example<jupyter_code>upw = mfbuild.build_upw()
print(type(upw))<jupyter_output><class 'flopy.modflow.mfupw.ModflowUpw'><jupyter_text>Building the NWT objectThe `build_nwt` method allows the user to create a NWT package for their model from builder defaults. The package is built with modflow NWT defaults and "Simple" complexity.Here is an example<jupyter_code>nwt = mfbuild.build_nwt()
print(type(nwt))<jupyter_output><class 'flopy.modflow.mfnwt.ModflowNwt'><jupyter_text>Building the OC objectThe `build_oc` method allows the user to create a OC package for their model from builder defaults. The package is built to write data to a binary head file and a binary cell budget file at the end of the steady state simulation.Here is an example<jupyter_code>oc = mfbuild.build_oc()
print(type(oc))<jupyter_output><class 'flopy.modflow.mfoc.ModflowOc'><jupyter_text>Building the UZF objectThe `build_uzf` method allows the user to create a UZF package for their model from builder defaults.The `build_uzf` method has one required parameter and two optional parameters:**REQUIRED parameters**   - `irunbnd` : array containing segment number that each individual cell provides runoff to.   **OPTIONAL parameters**   - `finf` : optional direct recharge array information, defaults to 1e-08   - `iuzfbnd` : optional active inactive uzf cell information, defaults to all cells activeHere is an example using all listed parameters<jupyter_code>uzf = mfbuild.build_uzf(
    strm_obj.irunbnd,
    finf=np.ones(dem_data.shape),
    iuzfbnd=watershed
)
print(type(uzf))<jupyter_output><class 'flopy.modflow.mfuzf1.ModflowUzf1'><jupyter_text>Building the SFR objectThe `build_sfr` method allows the user to create an SFR package for their model from builder defaults and previously calculated stream connectivity information.The `build_sfr` method has two required parameters that were created in the previous tutorial:   - `reach_data` : ModflowSfr2 compatible recarray of reach data (dataset 2 in the SFR documentation)   - `segment_data` : ModflowSfr2 compatible recarray of segment data (dataset 6 in the SFR documentation)   Here is an example of building the SFR package<jupyter_code>sfr = mfbuild.build_sfr(
    strm_obj.reach_data,
    strm_obj.segment_data
)
print(type(sfr))<jupyter_output><class 'flopy.modflow.mfsfr2.ModflowSfr2'><jupyter_text>Accessing the model object to write output to fileThe model object can be accessed through the `model` parameter on `ModflowBuilder`. This example shows how to access it and then write the model to file using FloPy's built in methods.<jupyter_code>ml = mfbuild.model

# change the path of the model
ml.change_model_ws(output_ws)
ml.write_input()<jupyter_output><empty_output><jupyter_text>Building an entire model at once Instead of building each individaul package, the `ModflowBuilder` class has a `build_all` method that let's the user build all of the packages at once and returns a model to the user.The `build_all` method has 3 required parameters and 4 optional parameters**REQUIRED parameters**   - `reach_data` : ModflowSfr2 compatible recarray of reach data (dataset 2 in the SFR documentation)   - `segment_data` : ModflowSfr2 compatible recarray of segment data (dataset 6 in the SFR documentation)   - `irunbnd` : array containing segment number that each individual UZF cell provides runoff to.   **OPTIONAL parameters**   - `finf` : optional UZF direct recharge array information, defaults to 1e-08   - `botm` : numpy array that defines the cell bottom elevations (defaults to 50 model units less than model top)   - `ibound` : numpy array that defines the active and inactive cells in model (defaults to all cells active)   - `iuzfbnd` : optional active inactive UZF cell information, defaults to all cells active   In the following example, Sagehen 50m MODFLOW-NWT input files are created using all listed parameters<jupyter_code># create a new modflow builder object
mfbuild = ModflowBuilder(modelgrid, dem_data, "sagehen_50m")

# build the model
ml = mfbuild.build_all(
    strm_obj.reach_data,
    strm_obj.segment_data,
    strm_obj.irunbnd,
    finf=np.ones(dem_data.shape),
    botm=botm,
    ibound=watershed,
    iuzfbnd=watershed
)

print(ml)<jupyter_output>MODFLOW 1 layer(s) 138 row(s) 149 column(s) 1 stress period(s)<jupyter_text>Editing package objectsBecause the `ModflowBuilder` class uses many defaults to build MODFLOW packages the user may want to adjust parameter values or even add additional packages like the WEL package to the model.This section shows how to make adjustments to the DIS, SFR, and UPW packages. The example also converts the model from a steady state model to a two stress period model that contains a steady state stress period and a transient stress period.For further details beyond what's presented in this notebook on how to work with FloPy's model and package objects, please see the [FloPy examples](https://github.com/modflowpy/flopy/tree/develop/examples/Notebooks).  Updating the DIS objectThis example shows how to update the DIS object to a 2 stress period model using FloPy.<jupyter_code># create data for perlen, nstp, tsmult, and the steady flag
perlen = [1, 5356]
nstp = [1, 5356]
tsmult = [1, 1]
steady = [True, False]

flopy.modflow.ModflowDis(
    ml,
    nlay=ml.dis.nlay,
    nrow=ml.dis.nrow,
    ncol=ml.dis.ncol,
    nper=2,
    delr=ml.dis.delr,
    delc=ml.dis.delc,
    laycbd=ml.dis.laycbd,
    top=ml.dis.top,
    botm=ml.dis.botm,
    perlen=perlen,
    nstp=nstp,
    tsmult=tsmult,
    steady=steady,
    itmuni=ml.dis.itmuni,
    lenuni=ml.dis.lenuni
)

print(ml)<jupyter_output>MODFLOW 1 layer(s) 138 row(s) 149 column(s) 2 stress period(s)<jupyter_text>Now we can see that the model has been updated to two stress periods  Updating the UPW objectThis example shows how to update hydrologic parameters in the UPW file and focuses on updating the HK (horizontal hydraulic conductivity) and the SS (specific storage) parameters.<jupyter_code># update hk using a multiplier, current value is 10
ml.upw.hk *= 1.75e-03

# show how to update the ss using a multiplier, current value is 1e-06 and appropriate for this model
ml.upw.ss *= 1.0<jupyter_output><empty_output><jupyter_text>Updating SFR segment and reach data fieldsThis example shows how to update some of the SFR segment and reach data fields for GSFLOW modeling. The two parameters we show in this example are `roughch` which is the manning's roughness coeficient and `strhc1` which is the stream bed conductance.<jupyter_code># update roughch in segment data
ml.sfr.segment_data[0]["roughch"] = 0.04

# update strhc1 in reach data
ml.sfr.reach_data["strhc1"] = 0.1<jupyter_output><empty_output><jupyter_text>Setting the model's coordinate informationThis example shows how to set the modelgrid's coordinate information for later use in plotting and raster resampling in later notebooks<jupyter_code># copy the coordinate information from the modelgrid we built in Tutorial 1
ml.modelgrid.set_coord_info(
    xoff=modelgrid.xoffset, 
    yoff=modelgrid.yoffset
)<jupyter_output><empty_output><jupyter_text>Writing the model to fileThis example shows how to write the model to file using FloPy's built in methods.<jupyter_code># change the path of the model and write to file
ml.change_model_ws(output_ws)
ml.write_input()<jupyter_output><empty_output><jupyter_text>Running the modelNow that the model is written, the user can test the single layer Sagehen 50m modflow model by running it using flopy's built in `run_model()` method.<jupyter_code># set the path to the mfnwt executable
exe_name = os.path.join("..", "bin", "mfnwt")
if platform.system().lower() == "windows":
    exe_name += ".exe"

ml.exe_name = exe_name
success, buff = ml.run_model(silent=True)
print(success)<jupyter_output>True<jupyter_text>Inspecting output from the modelA quick demonstration is shown on how to get head outputs from the binary ouput file and plot them for model inspection. For complete details on how to access modflow outputs using FloPy see the [FloPy examples](https://github.com/modflowpy/flopy/tree/develop/examples/Notebooks).<jupyter_code># define the headfile path
head_file = os.path.join(output_ws, "sagehen_50m.hds")

# load the headfile
hds = flopy.utils.HeadFile(head_file)

# get data
heads = hds.get_alldata()[-1]<jupyter_output><empty_output><jupyter_text>Now that the head data has been loaded, it can be plotted for inspection.<jupyter_code>fig = plt.figure(figsize=(12, 12))
ax = fig.add_subplot(1, 1, 1, aspect="equal")

pmv = flopy.plot.PlotMapView(model=ml, ax=ax)
pc = pmv.plot_array(heads)
ib = pmv.plot_inactive()
plt.colorbar(pc, shrink=0.7)
plt.title("Sagehen 50m modflow-nwt heads")
plt.show();<jupyter_output><empty_output><jupyter_text>Final considerations for GSFLOW modelOne additional SFR parameter needs to be adjusted before the groundwater model is ready to be added to GSFLOW. The SFR segment data parameter "flow" which defines inflow to a stream segment should be adjusted to zero as flow will be calculated by PRMS.After making this final adjustment, the model is written to file and will be ready to add to a GSFLOW model in a later tutorial.<jupyter_code># adjust SFR flow parameter to zero
ml.sfr.segment_data[0]["flow"] *= 0 

# write the model to file
ml.write_input()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07260118879139542, 'fraction_numerical': 0.0093405038211152, 'mean_word_length': 5.567379182156134, 'pattern_counts': {'":': 1, '<': 90, '<?xml version=': 0, '>': 90, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '73661', 'license': 'Unlicense', 'n_tokens_mistral': 4437, 'n_tokens_neox': 4234, 'n_words': 1627, 'path': 'examples/pygsflow1.1.0_Builder_tutorial_06_ModflowBuilder.ipynb', 'repo_name': 'usgs-pygsflow/pygsflow', 'size': '14132'}