From 229f15e47a8e4346fbb038fa2a7849aed9cd5986 Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Tue, 12 Nov 2024 09:42:38 -0500 Subject: [PATCH] adapt/stub some more examples (#46) --- docs/examples/list_example.py | 64 ++++++++++++++ docs/examples/record_example.py | 84 ++++++++++++++++++- docs/examples/transient_example.py | 81 ++++++++++++++++++ ..._model_example.py => variables_example.py} | 4 +- 4 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 docs/examples/list_example.py create mode 100644 docs/examples/transient_example.py rename docs/examples/{input_data_model_example.py => variables_example.py} (96%) diff --git a/docs/examples/list_example.py b/docs/examples/list_example.py new file mode 100644 index 0000000..60f0253 --- /dev/null +++ b/docs/examples/list_example.py @@ -0,0 +1,64 @@ +# # List input variables +# +# This example demonstrates how to work with list input variables. +# +# A list variable is a generic collection type, whose elements can +# be scalars, records, or unions of such. A list with a consistent +# (non-union) element type can be provided as a NumPy recarray or a +# Pandas dataframe. + +from tempfile import TemporaryDirectory + +import flopy +import numpy as np + +# set up where simulation workspace will be stored +temp_dir = TemporaryDirectory() +workspace = temp_dir.name +name = "tutorial06_mf6_data" + +# create the Flopy simulation and tdis objects +sim = flopy.mf6.MFSimulation( + sim_name=name, exe_name="mf6", version="mf6", sim_ws=workspace +) +tdis = flopy.mf6.modflow.mftdis.ModflowTdis( + sim, + pname="tdis", + time_units="DAYS", + nper=2, + perioddata=[(1.0, 1, 1.0), (1.0, 1, 1.0)], +) +# create the Flopy groundwater flow (gwf) model object +model_nam_file = f"{name}.nam" +gwf = flopy.mf6.ModflowGwf(sim, modelname=name, model_nam_file=model_nam_file) +# create the flopy iterative model solver (ims) package object +ims = flopy.mf6.modflow.mfims.ModflowIms(sim, pname="ims", complexity="SIMPLE") +# create the discretization package +bot = np.linspace(-50.0 / 3.0, -3.0, 3) +delrow = delcol = 4.0 +dis = flopy.mf6.modflow.mfgwfdis.ModflowGwfdis( + gwf, + pname="dis", + nogrb=True, + nlay=3, + nrow=10, + ncol=10, + delr=delrow, + delc=delcol, + top=0.0, + botm=bot, +) + +# Below we pass the CHD package's `stress_period_data` as a list. + +# build chd package +stress_period_data = [((1, 8, 8), 100.0), ((1, 9, 9), 105.0)] +chd = flopy.mf6.modflow.mfgwfchd.ModflowGwfchd( + gwf, + pname="chd", + maxbound=len(stress_period_data), + stress_period_data=stress_period_data, + save_flows=True, +) + +# TODO: demo typed records diff --git a/docs/examples/record_example.py b/docs/examples/record_example.py index df1a057..48d5cb0 100644 --- a/docs/examples/record_example.py +++ b/docs/examples/record_example.py @@ -1,12 +1,90 @@ -# # Record variables +# # Record and union variables # -# This example demonstrates how to work with record input variables. +# This example demonstrates how to work with record and union input +# variables. # # A record variable is a product type. Record fields can be scalars, # other record variables, or unions of such. # +# A union (keystring) variable is a sum type. +# # MODFLOW 6 represents records as (possibly variadic) tuples. FloPy # supports both a low-level tuple interface for records, conforming # to MODFLOW 6, and a high-level, strongly-typed record interface. + +# package import +from tempfile import TemporaryDirectory + +import flopy +import numpy as np + +# set up where simulation workspace will be stored +temp_dir = TemporaryDirectory() +workspace = temp_dir.name +name = "tutorial06_mf6_data" + +# create the Flopy simulation and tdis objects +sim = flopy.mf6.MFSimulation( + sim_name=name, exe_name="mf6", version="mf6", sim_ws=workspace +) +tdis = flopy.mf6.modflow.mftdis.ModflowTdis( + sim, + pname="tdis", + time_units="DAYS", + nper=2, + perioddata=[(1.0, 1, 1.0), (1.0, 1, 1.0)], +) +# create the Flopy groundwater flow (gwf) model object +model_nam_file = f"{name}.nam" +gwf = flopy.mf6.ModflowGwf(sim, modelname=name, model_nam_file=model_nam_file) +# create the flopy iterative model solver (ims) package object +ims = flopy.mf6.modflow.mfims.ModflowIms(sim, pname="ims", complexity="SIMPLE") +# create the discretization package +bot = np.linspace(-50.0 / 3.0, -3.0, 3) +delrow = delcol = 4.0 +dis = flopy.mf6.modflow.mfgwfdis.ModflowGwfdis( + gwf, + pname="dis", + nogrb=True, + nlay=3, + nrow=10, + ncol=10, + delr=delrow, + delc=delcol, + top=0.0, + botm=bot, +) + +# ## Adding MODFLOW Package Data, Connection Data, and Option Lists +# +# MODFLOW Package data, connection data, and option lists are stored by FloPy +# as numpy recarrays. FloPy does accept numpy recarrays as input, but does +# has other supported formats discussed below. +# +# MODFLOW option lists that only contain a single row or data can be either +# specified by: +# +# 1. Specifying a string containing the entire line as it would be displayed +# in the package file (`rewet_record="REWET WETFCT 1.0 IWETIT 1 IHDWET 0"`) +# 2. Specifying the data in a tuple within a list +# (`rewet_record=[("WETFCT", 1.0, "IWETIT", 1, "IHDWET", 0)]`) # -# TODO flesh out +# In the example below the npf package is created setting the `rewet_record` +# option to a string of text as would be typed into the package file. + +npf = flopy.mf6.modflow.mfgwfnpf.ModflowGwfnpf( + gwf, + rewet_record="REWET WETFCT 1.0 IWETIT 1 IHDWET 0", + pname="npf", + icelltype=1, + k=1.0, + save_flows=True, + xt3doptions="xt3d rhs", +) + +# `rewet_record` is then set using the npf package's `rewet_record` property. +# This time 'rewet_record' is defined using a tuple within a list. + +npf.rewet_record = [("WETFCT", 1.1, "IWETIT", 0, "IHDWET", 1)] + +# TODO: typed API demo diff --git a/docs/examples/transient_example.py b/docs/examples/transient_example.py new file mode 100644 index 0000000..d478750 --- /dev/null +++ b/docs/examples/transient_example.py @@ -0,0 +1,81 @@ +# # Transient input variables + +# MODFLOW stress period data is stored by FloPy as a dictionary of numpy +# recarrays, where each dictionary key is a zero-based stress period and each +# dictionary value is a recarray containing the stress period data for that +# stress period. FloPy keeps this stress period data in a `MFTransientList` +# object and this data type is referred to as a transient list. +# +# FloPy accepts stress period data as a dictionary of numpy recarrays, but also +# supports replacing the recarrays with lists of tuples discussed above. +# Stress period data spanning multiple stress periods must be specified as a +# dictionary of lists where the dictionary key is the stress period expressed +# as a zero-based integer. +# +# The example below creates `stress_period_data` for the wel package with the +# first stress period containing a single well and the second stress period +# empty. When empty stress period data is entered FloPy writes an empty +# stress period block to the package file. + +from tempfile import TemporaryDirectory + +import flopy +import numpy as np + +# set up where simulation workspace will be stored +temp_dir = TemporaryDirectory() +workspace = temp_dir.name +name = "tutorial06_mf6_data" + +# create the Flopy simulation and tdis objects +sim = flopy.mf6.MFSimulation( + sim_name=name, exe_name="mf6", version="mf6", sim_ws=workspace +) +tdis = flopy.mf6.modflow.mftdis.ModflowTdis( + sim, + pname="tdis", + time_units="DAYS", + nper=2, + perioddata=[(1.0, 1, 1.0), (1.0, 1, 1.0)], +) +# create the Flopy groundwater flow (gwf) model object +model_nam_file = f"{name}.nam" +gwf = flopy.mf6.ModflowGwf(sim, modelname=name, model_nam_file=model_nam_file) +# create the flopy iterative model solver (ims) package object +ims = flopy.mf6.modflow.mfims.ModflowIms(sim, pname="ims", complexity="SIMPLE") +# create the discretization package +bot = np.linspace(-50.0 / 3.0, -3.0, 3) +delrow = delcol = 4.0 +dis = flopy.mf6.modflow.mfgwfdis.ModflowGwfdis( + gwf, + pname="dis", + nogrb=True, + nlay=3, + nrow=10, + ncol=10, + delr=delrow, + delc=delcol, + top=0.0, + botm=bot, +) + +# First we create wel package with stress_period_data dictionary +# keys as zero-based integers so key "0" is stress period 1 + +stress_period_data = { + 0: [((2, 3, 1), -25.0)], # stress period 1 well data + 1: [], +} # stress period 2 well data is empty + +# Then, using the dictionary created above, we build the wel package. + +wel = flopy.mf6.ModflowGwfwel( + gwf, + print_input=True, + print_flows=True, + stress_period_data=stress_period_data, + save_flows=False, + pname="WEL-1", +) + +# TODO typed API demo diff --git a/docs/examples/input_data_model_example.py b/docs/examples/variables_example.py similarity index 96% rename from docs/examples/input_data_model_example.py rename to docs/examples/variables_example.py index 5c694b7..6f4e9c7 100644 --- a/docs/examples/input_data_model_example.py +++ b/docs/examples/variables_example.py @@ -1,4 +1,4 @@ -# # Input data model +# Input variables # # TODO: flesh this out, describe prospective plan for type hints, # determine whether we want to work directly with numpy or with @@ -81,3 +81,5 @@ # - While MODFLOW 6 typically formulates file path inputs as records with # 3 fields (identifying keyword, `filein`/`fileout`, and filename), FloPy # simply accepts `PathLike`. + +# TODO: demonstrate setting/accessing scalars in an options block