Basic example of groundwater modeling in MODFLOW 6 with Python - Flopy

BasicExampleMODFLOW6.jpg

MODFLOW 6 is the last version of MODFLOW that brings a set of new tools and a complete rearrange of the model file system. To the date of this post (July 2018) there are limited options for MODFLOW 6 preprocessors and postprocessors; so, whether you construct the MODFLOW 6 files as text files or you use the Flopy options to build, run and visualize groundwater models in MODFLOW 6.

Flopy is the Python package to create, run and post-process MODFLOW models. Flopy supports MODFLOW-2005 and MODFLOW 6 modeling codes and MODFLOW-based models as MODPATH (for particle tracking) and MT3D-USGS (for contaminant transport).

 

Groundwater model

This tutorial show the complete procedure to setup, run and visualize a basic groundwater model in MODFLOW 6 with Flopy. The model has the following characteristics:

  • Temporal discretization of 2 stress periods. One steady period of 1 second and one transient period of 86400 seconds (1 day) divided in 24 time steps.
  • Spatial discretization of 2 layers x 20 rows x 20 columns. Each cell has a horizontal dimension of 4 meters, each layer has a thickness of 20 meters.
  • Two constant head boundary conditions at the sides of the model. Difference in elevation among the two constant head BC is 4 meters and represent regional flow.
  • Two wells pumping on each layer on each time step.

A closer look of the grid and boundary condition distribution can be seen in the following figure:

BasicExampleMODFLOW6_BoundaryConditions.jpg

 

Tutorial

 

Flopy code

This is the Python code used for the tutorial. Libraries and Jupyter notebooks can be found at the bottom part of this article.

Basic Example of Groundwater Modeling with MODFLOW 6 and Flopy

Based on: https://github.com/modflowpy/flopy/blob/develop/examples/Notebooks/flopy3_mf6_tutorial.ipynb

#%ls ..\Exe

import os, flopy

#Going up to the example directory
exampleDir = os.path.dirname(os.getcwd())

simName = 'mf6uzfexamplesim'
simPath = exampleDir + '\Simulation'
exeName = exampleDir + '\Exe\mf6.exe'

sim = flopy.mf6.MFSimulation(sim_name=simName,
                            version='mf6', exe_name=exeName,
                            sim_ws=simPath)
Directory structure already exists for simulation path C:\Users\USER\Documents\Infohataris\BasicExampleMODFLOWUZFFlopy\Simulation

Model creation and solver options

modelName='mf6uzfexample'
model = flopy.mf6.MFModel(sim,modelname=modelName,model_nam_file=modelName+'.nam')
#creation of a Iterative Model Solution (IMS)
imsPackage = flopy.mf6.ModflowIms(sim, print_option='ALL',
                                   complexity='SIMPLE', outer_hclose=0.00001,
                                   outer_maximum=50, under_relaxation='NONE',
                                   inner_maximum=30, inner_hclose=0.00001,
                                   linear_acceleration='CG',
                                   preconditioner_levels=7,
                                   preconditioner_drop_tolerance=0.01,
                                   number_orthogonalizations=2)
#register solution to the sim
sim.register_ims_package(imsPackage,[modelName])

Definition of temporal discretization

1 Steady state period of 1s 1 Transient period of 86400s

#Example temporal discretization in MODFLOW 6
tdis = flopy.mf6.ModflowTdis(sim, time_units='seconds', nper=2,
                            perioddata=((1.0,1,1.0),(86400.0,24,1.0)))

Definition of spatial discretization

disPackage = flopy.mf6.ModflowGwfdis(model, length_units='METERS', 
                                    nlay=2, nrow=20, ncol=20,
                                     delr=4, delc=4, 
                                     top = 100.0, botm=[80.0, 60.0])

Definition of hydraulic conductivity

#hydraulic conductivity constant for each layer
layerStorageTypes = [flopy.mf6.data.mfdata.DataStorageType.internal_constant, 
                       flopy.mf6.data.mfdata.DataStorageType.internal_constant]
#definition of the empty data type, please note that default value is 1e-5
kTemplate = flopy.mf6.ModflowGwfnpf.k.empty(model, True, layerStorageTypes, 1e-5)

#change constant value of layer 0 and 1
kTemplate[0] = 3.5e-4
kTemplate[1] = 7e-5
print(kTemplate)

#create a NFP package with the kTemplate
npfPackage = flopy.mf6.ModflowGwfnpf(model, save_flows=True, icelltype=1, k=kTemplate)
[0.00035, 7e-05]

Definition of initial conditions

#define initial heads for model to 99
icPackage = flopy.mf6.ModflowGwfic(model,strt=99)

Definition of storage parameters

#define dynamic hydraulic parameters, the first layer is convertible and the second is confined
stoPackage = flopy.mf6.ModflowGwfsto(model, save_flows=True, iconvert=[1,0], 
                                     ss=1e-5, sy=0.15, steady_state={0:True}, transient={1:True}) #

Definition of Constant Head Package

stress_period_data = {0:[
    [[0, 0, 0], 95.1],
    [[0, 1, 0], 95.1],
    [[0, 2, 0], 95.1],
    [[0, 3, 0], 95.1],
    [[0, 4, 0], 95.1],
    [[0, 5, 0], 95.1],
    [[0, 6, 0], 95.1],
    [[0, 7, 0], 95.1],
    [[0, 8, 0], 95.1],
    [[0, 9, 0], 95.1],
    [[0, 10, 19], 99.1],
    [[0, 11, 19], 99.1],
    [[0, 12, 19], 99.1],
    [[0, 13, 19], 99.1],
    [[0, 14, 19], 99.1],
    [[0, 15, 19], 99.1],
    [[0, 16, 19], 99.1],
    [[0, 17, 19], 99.1],
    [[0, 18, 19], 99.1],
    [[0, 19, 19], 99.1],
    ]
    }

chdPackage = flopy.mf6.ModflowGwfchd(model, stress_period_data=stress_period_data)

Definition of Well Package

#definition of Wel boundary condition in two layers 
maxbound = 2
#define two wells pumping fron 5 to 10 l/s in two layers
welPeriod = flopy.mf6.ModflowGwfwel.stress_period_data.empty(model, maxbound=maxbound, boundnames=True, stress_periods=[0,1])
# define the two wells for stress period one
welPeriod[0][0] = ((0,8,8), -0.020, 'First Well')
welPeriod[0][1] = ((1,12,16), -0.025, 'Second Well')
# define the two wells for stress period two
welPeriod[1][0] = ((0,8,8), -0.050, 'First Well')
welPeriod[1][1] = ((1,12,16), -0.040, 'Second Well')
# build the well package
welPackage = flopy.mf6.ModflowGwfwel(model, stress_period_data=welPeriod, boundnames=True, save_flows=True)
# Well dictionary
welPeriod
{0: rec.array([((0, 8, 8), -0.02 , 'First Well'),
            ((1, 12, 16), -0.025, 'Second Well')],
           dtype=[('cellid', 'O'), ('q', '<f8'), ('boundnames', 'O')]),
 1: rec.array([((0, 8, 8), -0.05, 'First Well'),
            ((1, 12, 16), -0.04, 'Second Well')],
           dtype=[('cellid', 'O'), ('q', '<f8'), ('boundnames', 'O')])}

Output control options

#set up Output Control Package
printrec_tuple_list = [('HEAD', 'ALL'), ('BUDGET', 'ALL')]
saverec_dict = {0:[('HEAD', 'ALL'), ('BUDGET', 'ALL')],1:[('HEAD', 'ALL'), ('BUDGET', 'ALL')]}
ocPackage = flopy.mf6.ModflowGwfoc(model,
                                   budget_filerecord=[modelName+'.cbc'],
                                   head_filerecord=[modelName+'.hds'],
                                   saverecord=saverec_dict,
                                    printrecord=printrec_tuple_list)

Write simulation and run

# write simulation to new location 
sim.write_simulation()
WARNING: Unable to resolve dimension of ('nam', 'solutiongroup', 'solutiongroup', 'slnmnames') based on shape "nslnmod".
INFORMATION: maxbound in ('gwf6', 'chd', 'dimensions') changed to 20 based on size of stress_period_data
INFORMATION: maxbound in ('gwf6', 'wel', 'dimensions') changed to 2 based on size of stress_period_data
INFORMATION: 0 external files copied
# run simulation
sim.run_simulation()
FloPy is using the following executable to run the model: C:\Users\USER\Documents\Infohataris\BasicExampleMODFLOWUZFFlopy\Exe\mf6.exe
                                   MODFLOW 6
                U.S. GEOLOGICAL SURVEY MODULAR HYDROLOGIC MODEL
                       VERSION mf6.0.2 February 23, 2018

   MODFLOW 6 compiled Feb 21 2018 10:49:51 with IFORT compiler (ver. 18.0.1)

This software has been approved for release by the U.S. Geological 
Survey (USGS). Although the software has been subjected to rigorous 
review, the USGS reserves the right to update the software as needed 
pursuant to further analysis and review. No warranty, expressed or 
implied, is made by the USGS or the U.S. Government as to the 
functionality of the software and related material nor shall the 
fact of release constitute any such warranty. Furthermore, the 
software is released on condition that neither the USGS nor the U.S. 
Government shall be held liable for any damages resulting from its 
authorized or unauthorized use. Also refer to the USGS Water 
Resources Software User Rights Notice for complete use, copyright, 
and distribution information.

 Run start date and time (yyyy/mm/dd hh:mm:ss): 2018/07/24  9:59:47

 Writing simulation list file: mfsim.lst
 Using Simulation name file: mfsim.nam
 Solving:  Stress period:     1    Time step:     1
 Solving:  Stress period:     2    Time step:     1
 Solving:  Stress period:     2    Time step:     2
 Solving:  Stress period:     2    Time step:     3
 Solving:  Stress period:     2    Time step:     4
 Solving:  Stress period:     2    Time step:     5
 Solving:  Stress period:     2    Time step:     6
 Solving:  Stress period:     2    Time step:     7
 Solving:  Stress period:     2    Time step:     8
 Solving:  Stress period:     2    Time step:     9
 Solving:  Stress period:     2    Time step:    10
 Solving:  Stress period:     2    Time step:    11
 Solving:  Stress period:     2    Time step:    12
 Solving:  Stress period:     2    Time step:    13
 Solving:  Stress period:     2    Time step:    14
 Solving:  Stress period:     2    Time step:    15
 Solving:  Stress period:     2    Time step:    16
 Solving:  Stress period:     2    Time step:    17
 Solving:  Stress period:     2    Time step:    18
 Solving:  Stress period:     2    Time step:    19
 Solving:  Stress period:     2    Time step:    20
 Solving:  Stress period:     2    Time step:    21
 Solving:  Stress period:     2    Time step:    22
 Solving:  Stress period:     2    Time step:    23
 Solving:  Stress period:     2    Time step:    24
 Run end date and time (yyyy/mm/dd hh:mm:ss): 2018/07/24  9:59:47
 Elapsed run time:  0.167 Seconds

 Normal termination of simulation.





(True, [])


Output representation

keys = sim.simulation_data.mfdata.output_keys()
('mf6uzfexample', 'CBC', 'STO-SS')
('mf6uzfexample', 'CBC', 'STO-SY')
('mf6uzfexample', 'CBC', 'FLOW-JA-FACE')
('mf6uzfexample', 'CBC', 'WEL')
('mf6uzfexample', 'HDS', 'HEAD')
import matplotlib.pyplot as plt
import numpy as np

# get all head data
head = sim.simulation_data.mfdata['mf6uzfexample', 'HDS', 'HEAD']
# get the head data from the end of the model run
head_end = head[-1]
# plot the head data from the end of the model run
extent = (0.0, 80.0, 80.0, 0.0)
#CS = plt.contour(head_end[0, :, :], extent=extent)
#plt.grid(head_end[0,:,:])
#plt.clabel(CS, inline=1, fontsize=10)
plt.imshow(head_end[0,:,:], interpolation='nearest', cmap=plt.cm.ocean, extent=extent)
plt.colorbar()
plt.show()
# get all head data
head = sim.simulation_data.mfdata['mf6uzfexample', 'HDS', 'HEAD']
# get the head data from the end of the model run
head_end = head[-1]
# plot the head data from the end of the model run
extent = (0.0, 80.0, 80.0, 0.0)
plt.subplot(111)
CS = plt.contour(head_end[1, :, :],extent=extent)
plt.xlabel('Easting')
plt.ylabel('Norting')
plt.clabel(CS, inline=1, fontsize=10)
plt.axes().set_aspect('equal')
plt.show()
C:\WRDAPP\Miniconda\lib\site-packages\matplotlib\cbook\deprecation.py:107: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance.  In a future version, a new instance will always be created and returned.  Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.
  warnings.warn(message, mplDeprecation, stacklevel=1)

 

Input data

You can download the input data for this tutorial here.

Saul Montoya

Saul Montoya es Ingeniero Civil graduado de la Pontificia Universidad Católica del Perú en Lima con estudios de postgrado en Manejo e Ingeniería de Recursos Hídricos (Programa WAREM) de la Universidad de Stuttgart con mención en Ingeniería de Aguas Subterráneas y Hidroinformática.

 

Suscribe to our online newsletter

Subscribe for free newsletter, receive news, interesting facts and dates of our courses in water resources.