|  | 
| 7 | 7 | #       extension: .py | 
| 8 | 8 | #       format_name: light | 
| 9 | 9 | #       format_version: '1.5' | 
| 10 |  | -#       jupytext_version: 1.16.4 | 
|  | 10 | +#       jupytext_version: 1.17.2 | 
| 11 | 11 | #   kernelspec: | 
| 12 | 12 | #     display_name: Python 3 (ipykernel) | 
| 13 | 13 | #     language: python | 
| 14 | 14 | #     name: python3 | 
| 15 | 15 | # --- | 
| 16 | 16 | 
 | 
| 17 |  | -# # MODFLOW 6: Generate MODFLOW 6 NetCDF input from existing FloPy sim | 
|  | 17 | +# # MODFLOW 6: MODFLOW 6 NetCDF inputs from FloPy simulation | 
| 18 | 18 | # | 
| 19 |  | -# ## NetCDF tutorial 1: MODFLOW 6 structured input file | 
|  | 19 | +# ## Write MODFLOW 6 NetCDF simulation | 
| 20 | 20 | # | 
| 21 |  | -# This tutorial shows how to generate a MODFLOW 6 NetCDF file from | 
| 22 |  | -# an existing FloPy simulation. Two methods will be demonstrated that | 
| 23 |  | -# generate a simulation with package data stored in a model NetCDF | 
| 24 |  | -# file. The first method is non-interactive- FloPy will generate the | 
| 25 |  | -# file with a modified `write_simulation()` call.  The second method | 
| 26 |  | -# is interactive, which provides an oppurtinity to modify the dataset | 
| 27 |  | -# before it is written to NetCDF. | 
|  | 21 | +# This tutorial demonstrates how to generate a MODFLOW 6 NetCDF file | 
|  | 22 | +# from an existing FloPy simulation. Two variations will be shown. | 
|  | 23 | +# In the first, FloPy will generate the file with a modified | 
|  | 24 | +# `write_simulation()` call.  The second method is more interactive, | 
|  | 25 | +# providing an opputinity to modify the dataset before it is written | 
|  | 26 | +# to NetCDF. | 
|  | 27 | +# | 
|  | 28 | +# Support for generating a MODFLOW 6 NetCDF input without a defined | 
|  | 29 | +# FloPy mf6 model or package instances is briefly discussed at the | 
|  | 30 | +# end of the tutorial. | 
| 28 | 31 | # | 
| 29 | 32 | # For more information on supported MODFLOW 6 NetCDF formats see: | 
| 30 | 33 | # [MODFLOW NetCDF Format](https://github.com/MODFLOW-ORG/modflow6/wiki/MODFLOW-NetCDF-Format). | 
|  | 
| 93 | 96 | 
 | 
| 94 | 97 | # ## Load and run baseline simulation | 
| 95 | 98 | # | 
| 96 |  | -# For the purposes of this tutorial, the specifics of this simulation | 
|  | 99 | +# For the purposes of this tutorial, the specifics of the simulation | 
| 97 | 100 | # other than it is a candidate for NetCDF input are not a focus. It | 
| 98 | 101 | # is a NetCDF input candidate because it defines a supported model type | 
| 99 | 102 | # (`GWF6`) with a structured discretization and packages that support | 
| 100 | 103 | # NetCDF input parameters. | 
|  | 104 | +# | 
|  | 105 | +# More information about package NetCDF support in MODFLOW 6 can be | 
|  | 106 | +# found in the `MODFLOW 6 - Description of Input and Output` (`mf6io.pdf`), | 
|  | 107 | +# also available at the nightly build repository linked above. | 
| 101 | 108 | 
 | 
| 102 | 109 | # load and run the non-netcdf simulation | 
| 103 | 110 | sim = flopy.mf6.MFSimulation.load(sim_ws=data_path / sim_name) | 
|  | 
| 108 | 115 | 
 | 
| 109 | 116 | # ## Create NetCDF based simulation method 1 | 
| 110 | 117 | # | 
| 111 |  | -# This is the most straightforward way to create a NetCDF simulation | 
| 112 |  | -# from the loaded ascii input simulation. Simply define the `netcdf` | 
| 113 |  | -# argument to `write_simulation()` to be either `structured` or | 
| 114 |  | -# `layered`, depending on the desired format of the generated NetCDF | 
| 115 |  | -# file. | 
|  | 118 | +# The most straightforward way to create a NetCDF simulation | 
|  | 119 | +# from the loaded simulation is to provide a `netcdf` argument | 
|  | 120 | +# to `write_simulation()` and define it to be either `structured` | 
|  | 121 | +# or `layered`, depending on the desired format of the generated | 
|  | 122 | +# NetCDF file. | 
| 116 | 123 | # | 
| 117 | 124 | # The name of the created file can be specified by first setting the | 
| 118 | 125 | # model `name_file.nc_filerecord` attribute to the desired name. If | 
|  | 
| 129 | 136 | 
 | 
| 130 | 137 | # ## Run MODFLOW 6 simulation with NetCDF input | 
| 131 | 138 | # | 
| 132 |  | -# The simulation generated by this tutorial should be runnable by | 
| 133 |  | -# Extended MODFLOW 6, available from the nightly-build repository | 
| 134 |  | -# (linked above). | 
|  | 139 | +# The simulation generated by this tutorial should run with the | 
|  | 140 | +# Extended MODFLOW 6 executable, available from the nightly-build | 
|  | 141 | +# repository (linked above). | 
| 135 | 142 | 
 | 
| 136 | 143 | # success, buff = sim.run_simulation(silent=True, report=True) | 
| 137 | 144 | # assert success, pformat(buff) | 
|  | 
| 148 | 155 | 
 | 
| 149 | 156 | # ## Run MODFLOW 6 simulation with NetCDF input | 
| 150 | 157 | # | 
| 151 |  | -# The simulation generated by this tutorial should be runnable by | 
| 152 |  | -# Extended MODFLOW 6, available from the nightly-build repository | 
| 153 |  | -# (linked above). | 
|  | 158 | +# The simulation generated by this tutorial should run with the | 
|  | 159 | +# Extended MODFLOW 6 executable, available from the nightly-build | 
|  | 160 | +# repository (linked above). | 
| 154 | 161 | 
 | 
| 155 | 162 | # success, buff = sim.run_simulation(silent=True, report=True) | 
| 156 | 163 | # assert success, pformat(buff) | 
| 157 | 164 | 
 | 
| 158 | 165 | # ## Create NetCDF based simulation method 2 | 
| 159 | 166 | # | 
|  | 167 | +# In this method we will set the FloPy `netcdf` argument to `nofile` | 
|  | 168 | +# when `write_simulation()` is called. As such, FloPy will not generate | 
|  | 169 | +# the NetCDF file automatically. We will manage the NetCDF file | 
|  | 170 | +# generation ourselves in method 2. | 
|  | 171 | +# | 
| 160 | 172 | # Reset the simulation path and set the `GWF` name file `nc_filerecord` | 
| 161 | 173 | # attribute to the name of the intended input NetCDF file. Display | 
| 162 | 174 | # the resultant name file changes. | 
| 163 | 175 | # | 
| 164 | 176 | # When we write the updated simulation, all packages that support NetCDF | 
| 165 |  | -# input parameters will be converted. We will therefore need to create a | 
|  | 177 | +# input parameters will be written such that NetCDF parameters expect the | 
|  | 178 | +# data source to be a NetCDF file. We will therefore need to create a | 
| 166 | 179 | # NetCDF input file containing arrays for the `DIS`, `NPF`, `IC`, `STO`, | 
| 167 |  | -# and `GHBG` packages. Data will be copied from the package objects into | 
| 168 |  | -# dataset arrays. | 
| 169 |  | -# | 
| 170 |  | -# Flopy will not generate the NetCDF input file when the `netcdf` argument | 
| 171 |  | -# to `write_simulation()` is set to `nofile`. This step is needed, however, | 
| 172 |  | -# to update ascii input with the keywords required to support the model | 
| 173 |  | -# NetCDF file that we will generate. | 
|  | 180 | +# and `GHBG` packages. We will still use FloPy package objects to set the | 
|  | 181 | +# parameter data in the dataset; however an `update_data=False` argument | 
|  | 182 | +# could be passed to the `update_dataset()` call if this was not desired. | 
| 174 | 183 | 
 | 
| 175 | 184 | # create directory for netcdf sim | 
| 176 | 185 | sim.set_sim_path(workspace / "netcdf3") | 
|  | 
| 205 | 214 | 
 | 
| 206 | 215 | # ## Access model NetCDF attributes | 
| 207 | 216 | # | 
| 208 |  | -# Access model scoped NetCDF details by storing the dictionary | 
| 209 |  | -# returned from `netcdf_info()`. In particular, we need to set dataset | 
| 210 |  | -# scoped attributes that are stored in the model netcdf info dict. | 
|  | 217 | +# Internally, FloPy generates and uses NetCDF metadata dictionaries | 
|  | 218 | +# to update datasets. Both model and package objects can generate | 
|  | 219 | +# the dictionaries and they contain related but distinct NetCDF | 
|  | 220 | +# details. Model object dictionaries contain file scoped attribute | 
|  | 221 | +# information while package dictionaries are organized by NetCDF | 
|  | 222 | +# variable and contain variable scoped attribute information and | 
|  | 223 | +# details related to creating the variable, including dimensions, | 
|  | 224 | +# shape and data type. | 
| 211 | 225 | # | 
| 212 |  | -# First, retrieve and store the netcdf info dictionary and display | 
|  | 226 | +# The dictionaries are available via the `netcdf_info()` call. Their | 
|  | 227 | +# content also varies depending on the desired type of dataset (i.e. | 
|  | 228 | +# `structured` or `layered`). In this step we will access the model | 
|  | 229 | +# NetCDF metadata and use it to update dataset scoped attributes. | 
|  | 230 | +# | 
|  | 231 | +# First, retrieve and store the netcdf metadata dictionary and display | 
| 213 | 232 | # its contents. Then, in the following step, update the dataset with | 
| 214 | 233 | # the model scoped attributes defined in the dictionary. | 
| 215 | 234 | # | 
| 216 |  | -# These 2 operations can also be accomplished by calling `update_dataset()` | 
| 217 |  | -# on the model object. Analogous functions for the package are shown | 
| 218 |  | -# below. | 
|  | 235 | +# These operations can also both be accomplished by calling | 
|  | 236 | +# `update_dataset()` on the model object, albeit without the | 
|  | 237 | +# opportunity to modify the intermediate metadata dictionary. | 
|  | 238 | +# Examples of this approach (with package objects) are shown below. | 
| 219 | 239 | 
 | 
| 220 | 240 | # get model netcdf info | 
| 221 | 241 | nc_info = gwf.netcdf_info() | 
|  | 
| 227 | 247 | 
 | 
| 228 | 248 | # ## Update the dataset with supported `DIS` arrays | 
| 229 | 249 | # | 
| 230 |  | -# Add NetCDF supported data arrays in package to dataset. Internally, this call | 
| 231 |  | -# uses a `netcdf_info()` package dictionary to determine candidate variables | 
| 232 |  | -# and relevant information about them. Alternatively, this dictionary can | 
| 233 |  | -# be directly accessed, updated, and passed to the `update_dataset()` function. | 
| 234 |  | -# That workflow will be demonstrated in the `NPF` package update which follows. | 
|  | 250 | +# First, we will show how package NetCDF parameters can be added to the | 
|  | 251 | +# dataset without using the NetCDF metadata dictionary. We will use the | 
|  | 252 | +# metadata dictionary when updating the dataset with NPF parameter data. | 
|  | 253 | +# | 
|  | 254 | +# Add NetCDF supported data arrays in package to dataset. | 
| 235 | 255 | 
 | 
| 236 | 256 | # update dataset with `DIS` arrays | 
| 237 | 257 | dis = gwf.get_package("dis") | 
|  | 
| 240 | 260 | # ## Access `NPF` package NetCDF attributes | 
| 241 | 261 | # | 
| 242 | 262 | # Access package scoped NetCDF details by storing the dictionary returned | 
| 243 |  | -# from `netcdf_info()`. We need to set package variable attributes that are | 
| 244 |  | -# stored in the package netcdf info dict, but we also need other information | 
| 245 |  | -# that is relevant to creating the variables themselves. | 
|  | 263 | +# from `netcdf_info()`. | 
| 246 | 264 | # | 
| 247 | 265 | # The contents of the info dictionary are shown and then, in the following | 
| 248 | 266 | # step, the dictionary and the dataset are passed to a helper routine that | 
|  | 
| 253 | 271 | nc_info = npf.netcdf_info() | 
| 254 | 272 | pprint(nc_info) | 
| 255 | 273 | 
 | 
| 256 |  | -# ## Update package `netcdf_info` dictionary and dataset | 
|  | 274 | +# ## Update package NetCDF metadata dictionary and dataset | 
|  | 275 | +# | 
|  | 276 | +# Here we update the metadata dictionary and then pass it directly to the | 
|  | 277 | +# `update_dataset()` function which uses it when adding variables to the | 
|  | 278 | +# dataset. | 
| 257 | 279 | # | 
| 258 |  | -# Here we replace the default name for the `NPF K` input parameter and add | 
| 259 |  | -# the `standard_name` attribute to it's attribute dictionary.  The dictionary | 
| 260 |  | -# is then passed to the `update_dataset()` function. Note the updated name | 
| 261 |  | -# is used in the subsequent block when updating the array values. | 
|  | 280 | +# We replace the default name for the `NPF K` input parameter and add | 
|  | 281 | +# the `standard_name` attribute to it's attribute dictionary. The | 
|  | 282 | +# dictionary is then passed to the `update_dataset()` function. Note the | 
|  | 283 | +# updated name is used in the subsequent block when updating the array | 
|  | 284 | +# values. | 
| 262 | 285 | 
 | 
| 263 | 286 | # update dataset with `NPF` arrays | 
| 264 | 287 | nc_info["k"]["varname"] = "npf_k_updated" | 
|  | 
| 302 | 325 | 
 | 
| 303 | 326 | # ## Run MODFLOW 6 simulation with NetCDF input | 
| 304 | 327 | # | 
| 305 |  | -# The simulation generated by this tutorial should be runnable by | 
| 306 |  | -# Extended MODFLOW 6, available from the nightly-build repository | 
| 307 |  | -# (linked above). | 
|  | 328 | +# The simulation generated by this tutorial should run with the | 
|  | 329 | +# Extended MODFLOW 6 executable, available from the nightly-build | 
|  | 330 | +# repository (linked above). | 
| 308 | 331 | 
 | 
| 309 | 332 | # success, buff = sim.run_simulation(silent=True, report=True) | 
| 310 | 333 | # assert success, pformat(buff) | 
| 311 | 334 | 
 | 
| 312 |  | -# ## Method 4: DIY with xarray | 
|  | 335 | +# ## Method 3: DIY with xarray | 
| 313 | 336 | # | 
| 314 | 337 | # The above method still uses FloPy objects to update the dataset arrays | 
| 315 | 338 | # to values consistent with the state of the objects. The `netcdf_info` | 
|  | 
0 commit comments