Skip to content

Commit b7c5e25

Browse files
mjrenomjreno
authored andcommitted
add update_dataset functions
1 parent fc873c1 commit b7c5e25

File tree

5 files changed

+136
-104
lines changed

5 files changed

+136
-104
lines changed

.docs/Notebooks/netcdf01_tutorial.py

Lines changed: 67 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -242,44 +242,12 @@ def create_sim(ws):
242242
return sim
243243

244244

245-
# ## Create helper function to update dataset
246-
#
247-
# This function updates an xarray dataset to add variables described
248-
# in a FloPy provided dictionary.
249-
#
250-
# The dimmap variable relates NetCDF dimension names to a value.
251-
252-
253-
# A subroutine that can update an xarray dataset with package
254-
# netcdf information stored in a dict
255-
def add_netcdf_vars(dataset, nc_info, dimmap):
256-
def _data_shape(shape):
257-
dims_l = []
258-
for d in shape:
259-
dims_l.append(dimmap[d])
260-
261-
return dims_l
262-
263-
for v in nc_info:
264-
varname = nc_info[v]["varname"]
265-
data = np.full(
266-
_data_shape(nc_info[v]["netcdf_shape"]),
267-
nc_info[v]["attrs"]["_FillValue"],
268-
dtype=nc_info[v]["xarray_type"],
269-
)
270-
var_d = {varname: (nc_info[v]["netcdf_shape"], data)}
271-
dataset = dataset.assign(var_d)
272-
for a in nc_info[v]["attrs"]:
273-
dataset[varname].attrs[a] = nc_info[v]["attrs"][a]
274-
275-
return dataset
276-
277-
278245
# ## Create simulation workspace
279246

280247
# create temporary directories
281-
temp_dir = TemporaryDirectory()
282-
workspace = Path(temp_dir.name)
248+
# temp_dir = TemporaryDirectory()
249+
# workspace = Path(temp_dir.name)
250+
workspace = Path("./working")
283251

284252
# ## Write and run baseline simulation
285253

@@ -323,49 +291,39 @@ def _data_shape(shape):
323291
# First, retrieve and store the netcdf info dictionary and display
324292
# its contents. Then, in the following step, update the dataset with
325293
# the model scoped attributes defined in the dictionary.
294+
#
295+
# These 2 operations can also be accomplised by calling `update_dataset()`
296+
# on the model object. Analogous functions for the package are shown
297+
# below.
326298

327299
# get model netcdf info
328300
nc_info = gwf.netcdf_info()
329301
pprint(nc_info)
330302

331-
# update dataset with required attributes
303+
# update dataset directly with required attributes
332304
for a in nc_info["attrs"]:
333305
ds.attrs[a] = nc_info["attrs"][a]
334306

335-
# ## Map dataset dimension names to values
336-
337-
# define dimensional info
338-
dimmap = {
339-
"time": sum(gwf.modeltime.nstp),
340-
"z": gwf.modelgrid.nlay,
341-
"y": gwf.modelgrid.nrow,
342-
"x": gwf.modelgrid.ncol,
343-
}
344-
345-
# ## Access package NetCDF attributes
346-
#
347-
# Access package scoped NetCDF details by storing the dictionary returned
348-
# from `netcdf_info()`. We need to set package variable attributes that are
349-
# stored in the package netcdf info dict, but we also need other information
350-
# that is relevant to creating the variables themselves.
307+
# ## Update the dataset with supported `DIS` arrays
351308
#
352-
# The contents of the info dictionary are shown and then, in the following
353-
# step, the dictionary and the dataset are passed to a helper routine that
354-
# create the intended array variables.
309+
# Add NetCDF supported data arrays in package to dataset. Internally, this call
310+
# uses a `netcdf_info()` package dictionary to determine candidate variables
311+
# and relevant information about them. Alternatively, this dictionary can
312+
# be directly accessed, updated, and passed to the `update_dataset()` function.
313+
# That workflow will be demonstrated in the `NPF` package update which follows.
355314

356-
# get dis package netcdf info
315+
# update dataset with `DIS` arrays
357316
dis = gwf.get_package("dis")
358-
nc_info = dis.netcdf_info()
359-
pprint(nc_info)
360-
361-
# create dis dataset variables
362-
ds = add_netcdf_vars(ds, nc_info, dimmap)
317+
ds = dis.update_dataset(ds)
363318

364319
# ## Update array data
365320
#
366321
# We have created dataset array variables for the package but they do not yet
367322
# define the expected input data for MODFLOW 6. We will take advantage of the
368323
# existing simulation objects and update the dataset.
324+
#
325+
# Default dataset variable names are defined in the package `netcdf_info()`
326+
# dictionary.
369327

370328
# update dataset from dis arrays
371329
ds["dis_delr"].values = dis.delr.get_data()
@@ -378,7 +336,7 @@ def _data_shape(shape):
378336
#
379337
# MODFLOW 6 input data for the package is now in the dataset. Once the NetCDF
380338
# file is generated, we need to configure MODFLOW 6 so that it looks to that
381-
# file for the package array input. The ASCII file will no longer defined the
339+
# file for the package array input. The ASCII file will no longer define the
382340
# arrays- instead the array names will be followed by the NETCDF keyword.
383341
#
384342
# We will simply overwrite the entire MODFLOW 6 `DIS` package input file with the
@@ -404,21 +362,46 @@ def _data_shape(shape):
404362
with open(workspace / "netcdf" / "uzf01.dis", "r") as fh:
405363
print(fh.read())
406364

407-
# ## Update MODFLOW 6 package input file
365+
# ## Access `NPF` package NetCDF attributes
408366
#
409-
# Follow the same process as above for the `NPF` package.
367+
# Access package scoped NetCDF details by storing the dictionary returned
368+
# from `netcdf_info()`. We need to set package variable attributes that are
369+
# stored in the package netcdf info dict, but we also need other information
370+
# that is relevant to creating the variables themselves.
371+
#
372+
# The contents of the info dictionary are shown and then, in the following
373+
# step, the dictionary and the dataset are passed to a helper routine that
374+
# create the intended array variables.
410375

411376
# get npf package netcdf info
412377
npf = gwf.get_package("npf")
413378
nc_info = npf.netcdf_info()
414379
pprint(nc_info)
415380

416-
# create npf dataset variables
417-
ds = add_netcdf_vars(ds, nc_info, dimmap)
381+
# ## Update package `netcdf_info` dictionary and dataset
382+
#
383+
# Here we replace the default name for the `NPF K` input parameter and add
384+
# the `standard_name` attribute to it's attribute dictionary. The dictionary
385+
# is then passed to the `update_dataset()` function. Note the udpated name
386+
# is used in the subsequent block when updating the array values.
387+
388+
# update dataset with `NPF` arrays
389+
nc_info["k"]["varname"] = "npf_k_updated"
390+
nc_info["k"]["attrs"]["standard_name"] = "soil_hydraulic_conductivity_at_saturation"
391+
ds = npf.update_dataset(ds, netcdf_info=nc_info)
392+
393+
# ## Update array data
418394

419395
# update dataset from npf arrays
420396
ds["npf_icelltype"].values = npf.icelltype.get_data()
421-
ds["npf_k"].values = npf.k.get_data()
397+
ds["npf_k_updated"].values = npf.k.get_data()
398+
399+
# ## Show dataset `NPF K` parameter with udpates
400+
401+
# print dataset npf k variable
402+
print(ds["npf_k_updated"])
403+
404+
# ## Update MODFLOW 6 package input file
422405

423406
# rewrite mf6 npf input to read from netcdf
424407
with open(workspace / "netcdf" / "uzf01.npf", "w") as f:
@@ -431,21 +414,13 @@ def _data_shape(shape):
431414
with open(workspace / "netcdf" / "uzf01.npf", "r") as fh:
432415
print(fh.read())
433416

434-
# ## Update MODFLOW 6 package input file
435-
#
436-
# Follow the same process as above for the `GHBG` package. The difference is
437-
# that this is PERIOD input and therefore stored as timeseries data in the
438-
# NetCDF file. As NETCDF timeseries are defined in terms of total number of
439-
# simulation steps, care must be taken in the translation of FloPy period
440-
# data to the timeseries.
417+
# ## Update the dataset with supported `GHBG` arrays
441418

442-
# get ghbg package netcdf info
419+
# update dataset with 'GHBG' arrays
443420
ghbg = gwf.get_package("ghbg_0")
444-
nc_info = ghbg.netcdf_info()
445-
pprint(nc_info)
421+
ds = ghbg.update_dataset(ds)
446422

447-
# create ghbg dataset variables
448-
ds = add_netcdf_vars(ds, nc_info, dimmap)
423+
# ## Update array data
449424

450425
# update bhead netcdf array from flopy perioddata
451426
# timeseries step index is first of stress period
@@ -459,17 +434,7 @@ def _data_shape(shape):
459434
istp = sum(gwf.modeltime.nstp[0:p])
460435
ds["ghbg_0_cond"].values[istp] = ghbg.cond.get_data()[p]
461436

462-
# ## Display generated dataset
463-
464-
# show the dataset
465-
print(ds)
466-
467-
# ## Export generated dataset to NetCDF
468-
469-
# write dataset to netcdf
470-
ds.to_netcdf(
471-
workspace / "netcdf/uzf01.structured.nc", format="NETCDF4", engine="netcdf4"
472-
)
437+
# ## Update MODFLOW 6 package input file
473438

474439
# rewrite mf6 ghbg input to read from netcdf
475440
with open(workspace / "netcdf/uzf01.ghbg", "w") as f:
@@ -486,6 +451,18 @@ def _data_shape(shape):
486451
with open(workspace / "netcdf" / "uzf01.ghbg", "r") as fh:
487452
print(fh.read())
488453

454+
# ## Display generated dataset
455+
456+
# show the dataset
457+
print(ds)
458+
459+
# ## Export generated dataset to NetCDF
460+
461+
# write dataset to netcdf
462+
ds.to_netcdf(
463+
workspace / "netcdf/uzf01.structured.nc", format="NETCDF4", engine="netcdf4"
464+
)
465+
489466
# ## Run MODFLOW 6 simulation with NetCDF input
490467
#
491468
# The simulation generated by this tutorial should be runnable by

.docs/Notebooks/netcdf02_tutorial.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
# display_name: Python 3 (ipykernel)
1313
# language: python
1414
# name: python3
15-
# metadata:
16-
# section: mf6
1715
# ---
1816

1917
# # MODFLOW 6: Generate MODFLOW 6 NetCDF input from existing FloPy sim
@@ -165,7 +163,7 @@ def create_sim(ws):
165163

166164
uzf_spd.update({t: spd})
167165

168-
# Work up the GHB / GHBG boundary
166+
# Work up the GHBG boundary
169167
ghb_ids = [(ncol - 1) + i * ncol for i in range(nrow)]
170168
abhead = np.full((nlay, ncpl), DNODATA, dtype=float)
171169
acond = np.full((nlay, ncpl), DNODATA, dtype=float)
@@ -464,16 +462,6 @@ def _data_shape(shape):
464462
l
465463
].flatten()
466464

467-
# ## Display generated dataset
468-
469-
# show the dataset
470-
print(ds)
471-
472-
# ## Export generated dataset to NetCDF
473-
474-
# write dataset to netcdf
475-
ds.to_netcdf(workspace / "netcdf/uzf02.layered.nc", format="NETCDF4", engine="netcdf4")
476-
477465
# rewrite mf6 ghbg input to read from netcdf
478466
with open(workspace / "netcdf/uzf02.ghbg", "w") as f:
479467
f.write("BEGIN options\n")
@@ -487,6 +475,16 @@ def _data_shape(shape):
487475
with open(workspace / "netcdf" / "uzf02.ghbg", "r") as fh:
488476
print(fh.read())
489477

478+
# ## Display generated dataset
479+
480+
# show the dataset
481+
print(ds)
482+
483+
# ## Export generated dataset to NetCDF
484+
485+
# write dataset to netcdf
486+
ds.to_netcdf(workspace / "netcdf/uzf02.layered.nc", format="NETCDF4", engine="netcdf4")
487+
490488
# ## Run MODFLOW 6 simulation with NetCDF input
491489
#
492490
# The simulation generated by this tutorial should be runnable by

flopy/mf6/mfmodel.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,3 +2245,14 @@ def netcdf_info(self, mesh=None):
22452245
return MFModel.netcdf_model(
22462246
self.name, self.model_type, self.get_grid_type(), mesh
22472247
)
2248+
2249+
def update_dataset(self, dataset, netcdf_info=None, mesh=None):
2250+
if netcdf_info is None:
2251+
nc_info = self.netcdf_info(mesh=mesh)
2252+
else:
2253+
nc_info = netcdf_info
2254+
2255+
for a in nc_info["attrs"]:
2256+
dataset.attrs[a] = nc_info["attrs"][a]
2257+
2258+
return dataset

flopy/mf6/mfpackage.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,6 +3505,8 @@ def _add_entry(tagname, iaux=None, layer=None):
35053505
a["attrs"]["_FillValue"] = FILLNA_DBL
35063506
elif data_item.block_name == "period":
35073507
a["attrs"]["_FillValue"] = DNODATA
3508+
if data_item.longname is not None:
3509+
a["attrs"]["longname"] = data_item.longname
35083510

35093511
# set dictionary
35103512
attrs[key] = a
@@ -3593,6 +3595,50 @@ def netcdf_info(self, mesh=None):
35933595

35943596
return attrs
35953597

3598+
def update_dataset(self, dataset, netcdf_info=None, mesh=None):
3599+
if netcdf_info is None:
3600+
nc_info = self.netcdf_info(mesh=mesh)
3601+
else:
3602+
nc_info = netcdf_info
3603+
3604+
modelgrid = self.model_or_sim.modelgrid
3605+
modeltime = self.model_or_sim.modeltime
3606+
3607+
if mesh is None:
3608+
dimmap = {
3609+
"time": sum(modeltime.nstp),
3610+
"z": modelgrid.nlay,
3611+
"y": modelgrid.nrow,
3612+
"x": modelgrid.ncol,
3613+
}
3614+
elif mesh.upper() == "LAYERED":
3615+
dimmap = {
3616+
"time": sum(gwf.modeltime.nstp),
3617+
"z": gwf.modelgrid.nlay,
3618+
"nmesh_face": gwf.modelgrid.ncpl,
3619+
}
3620+
3621+
def _data_shape(shape):
3622+
dims_l = []
3623+
for d in shape:
3624+
dims_l.append(dimmap[d])
3625+
3626+
return dims_l
3627+
3628+
for v in nc_info:
3629+
varname = nc_info[v]["varname"]
3630+
data = np.full(
3631+
_data_shape(nc_info[v]["netcdf_shape"]),
3632+
nc_info[v]["attrs"]["_FillValue"],
3633+
dtype=nc_info[v]["xarray_type"],
3634+
)
3635+
var_d = {varname: (nc_info[v]["netcdf_shape"], data)}
3636+
dataset = dataset.assign(var_d)
3637+
for a in nc_info[v]["attrs"]:
3638+
dataset[varname].attrs[a] = nc_info[v]["attrs"][a]
3639+
3640+
return dataset
3641+
35963642

35973643
class MFChildPackages:
35983644
"""

flopy/mf6/utils/codegen/filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ def _meta():
320320

321321
def __dfn():
322322
def _var(var: dict) -> List[str]:
323-
exclude = ["longname", "description"]
323+
exclude = ["description"]
324324
name = var["name"]
325325
subpkg = dfn.get("fkeys", dict()).get(name, None)
326326
if subpkg:

0 commit comments

Comments
 (0)