4.3.1. Python Modules¶
A Python module is used to replace the main program block of MODFLOW 6 for coupled simulation. This replacement permits the calling of modified Fortran routines to allow for interprocess communication with mHSP2.
4.3.1.1. pyMF6py.py¶
pyMF6, python-wrapped, MODFLOW 6 implementation.
This module provides the main entry point for running MODFLOW 6 and the main time loop through Python. To dynamically couple MODFLOW 6 to HSPF, need to be able to break into the time loop at the beginning of each day.
This Python module provides replacement functionality for the Fortran
main program block of MODFLOW 6. There are two main program versions
within this module. The user controls which version is run by
executing ..\coupledMain.py
or ..\standaloneMain.py.
Both “mains”
use functions within this module. Function saMF6TimeLoop is for standalone
execution, and function MF6TimeLoop is for coupled (to HSPF) execution.
The message passing queue functions included in this module are only used
when coupled mode execution is requested. Also the main block
(if __name__ == main():
) in this module is what is launcehd to start
the independent process, spawned by the coupled controller and queue
manager.
- pyMF6py.AUTHKEY = b'authkey'¶
Authorization key for queue access.
This is not currently setup in a secure manner. If you plan on using pyHS2MF6 across a public or partially public network, then you should give some thought to the AUTHKEY and a means of securing this value. AUTHKEY needs to be encoded to a byte string.
- pyMF6py.CLIENTHOST = '127.0.0.1'¶
Host machine for queue clients.
Clients are on the same ‘machine’ as the queue server when local descriptors like ‘localhost’ or ‘127.0.0.1’ are used.
- pyMF6py.HOST = 'localhost'¶
Host machine for queue server.
Localhost means that the process are set-up to be on all the same machine. The queue server and the clients are in different processes on the same ‘machine’.
- pyMF6py.MF6TimeLoop(qMF6, qHSP2)¶
Main MODFLOW6 time loop and all model setup for coupled simulation.
Currently have to run the simulation from the current directory and need to have all of the custom Python files in that directory as well.
- Parameters
qMF6 (pyMF6py.Queue client) – queue for information from MODFLOW 6
qHSP2 (pyMF6py.Queue client) – queue for information from HSP2
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.MF_SIM_NAME = 'mfsim.nam'¶
Standard and fixed MODFLOW 6 simulation name
- pyMF6py.NUM_CPL = 0¶
Number of cells per layer in the MODFLOW 6 model
- pyMF6py.NUM_LAY = 0¶
Number of layers in the MODFLOW 6 model
- pyMF6py.NUM_UZF = 0¶
Number of UZF cells in the MODFLOW 6 model
- pyMF6py.PORT0 = 45492¶
Port number for the HSP2 queue.
Port numbers for queues need to be the same for each independent process for connection. Additionally, ports need to be opened in any firewall software even for local simulation.
- pyMF6py.PORT1 = 45493¶
Port number for the MODFLOW 6 queue.
Port numbers for queues need to be the same for each independent process for connection. Additionally, ports need to be opened in any firewall software even for local simulation.
- pyMF6py.PORT2 = 45494¶
Port number for global error handling and communications queue.
Port numbers for queues need to be the same for each independent process for connection. Additionally, ports need to be opened in any firewall software even for local simulation.
- pyMF6py.QEND_MSG = ['End']¶
End of simulation message
- pyMF6py.QINIT_MSG = ['Hello']¶
Queue intialization and checkin message
- pyMF6py.QREADY_MSG = ['Ready']¶
Queue intialization and checkin message
- pyMF6py.QUEUE_ERROR = ['Error']¶
Error message to put on queues for program termination
- pyMF6py.QUEUE_TIMEOUT = 120.0¶
Queue wait timeout before error in seconds
This is for the from pyMF6 queue and determines the mHSP2 wait time for receipt from MODFLOW 6.
- class pyMF6py.QueueManager(address=None, authkey=None, serializer='pickle', ctx=None)¶
Create the queue manager class.
Needs to be at top level of the module so that is pickleable. Do not need anything here except to subclass SyncManager.
- pyMF6py.QueueServerClient(ThisHost, Porter, CustomAuth)¶
Get a client connection a queue.
The connection is bidirectional and can use this connection for both get and put.
- Parameters
ThisHost (str) – host name. Should be ‘127.0.0.1’ for the same machine
Porter (int) – the port number to listen on
CustomAuth (str) – the custom authorization string
- Returns
the client connection
- Return type
- pyMF6py.SIM_DAYS = 0¶
Total number of days to be simulated
- pyMF6py.SIM_DAYS_SERIES = None¶
Pandas date range series of days in date form to be simulated
- pyMF6py.SIM_MONTHS = 0¶
Total number of months to be simulated
- pyMF6py.SIM_MONTH_SERIES = None¶
Pandas date range series of months in date form to be simulated
- pyMF6py.START_QUEUE_TO = 300.0¶
Queue wait timeout before error in seconds.
This is for program startup communications.
- pyMF6py.TRACK_DIS_OUT = None¶
Numpy recarray with dimension NUM_CPL, SIM_MONTHS for tracking the discharge to ground surface sent to HSPF.
- pyMF6py.TRACK_REJI_OUT = None¶
Numpy recarray with dimension NUM_CPL, SIM_MONTHS for tracking the rejected infiltration sent to HSPF.
- pyMF6py.TRACK_UZF_IN = None¶
Numpy recarray with dimensions NUM_UZF, SIM_MONTHS for tracking the UZF inflows passed from HSPF
- pyMF6py.WriteQueueCheckToLog(qMF6)¶
Write queue checks to log file
- Parameters
qMF6 (pyMF6py.Queue) – the from MODFLOW6 queue
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.metaChecks(mf6root, cwd, start_dt, end_dt, num_lay, num_cpl, num_vert, num_uzf)¶
Check meta data items passed from the queue server as part of initial setup.
Uses flopy to implement these checks.
- Parameters
mf6root (str) – MODFLOW 6 model root name
cwd (str) – MODFLOW 6 model directory
start_dt (dt.datetime) – starting date time
end_dt (dt.datetime) – ending date time
num_lay (int) – number of layers
num_cpl (int) – number of cells per layer
num_vert (int) – number of vertices per layer
num_uzf (int) – number of UZF cells in the model
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.outputTracking()¶
Output all of our tracking collections so that these can be post-processed if desired.
Output to four pickle files.
‘IndexDict.pickle’, dictionary, DI, with keys
‘ncpl’ = NUM_CPL
‘nuzf’ = NUM_UZF
‘sim_day_index’ = SIM_DAYS_SERIES
‘sim_month_index’ = SIM_MONTH_SERIES
‘UZF_from_HSPF.pickle’, TRACK_UZF_IN
‘GSURF_from_MF6.pickle’, TRACK_DIS_OUT
‘REJINF_from_MF6.pickle’, TRACK_REJI_OUT
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.processArrayComm(NpArray)¶
Process the array communication from MODFLOW 6
- Parameters
NpArray (np.array) – the array of discharge to the surface from MODFLOW 6
- Returns
function status; success == 0
- Return type
int
- pyMF6py.processInitMeta(PassList)¶
Process the initial metadata communication received from the queue server.
Call the various routines as required to check start time, end time, and grid specifications.
- Parameters
PassList (list) –
list of metadata items - these are pickled and unpickled and following formats are required.
(str): model directory
(dt.datetime): start time
(dt.datetime): end time
(int): number of layers
(int): number of cells per layer
(int): number of vertices per layer
(str): MODFLOW 6 root file name
(int): number of uzf cells
- Returns
FQDN path for MODFLOW 6 simulation files
- Return type
str
- pyMF6py.processReadyComm(StringList)¶
Process the ready communication with external processes
- Parameters
StringList (list) – list of string items
- Returns
function status; success == 0
- Return type
int
- pyMF6py.saMF6TimeLoop(simdir)¶
Main MODFLOW 6 time loop and all model setup for standalone simulation.
- Parameters
simdir (str) – directory with simulation inputs
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.setupRecarrays(ncpl, nuzf, nmonths)¶
Three recarrays are used to track communications between HSPF and MODFLOW on a grid basis.
These recarrays are instantiated and initialized here
- Parameters
ncpl (int) – number of computational cells in a layer, NCPL
nuzf (int) – number of UZF cells, NUZFCELLS
nmonths (int) – number of months to be simulated
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.updateDischargeRAs(curpTS, tArray)¶
Update the two rec arrays that track discharge to the ground surface
- Parameters
curpTS (pd.Timestamp) – current simulation time/day
tArray (np.array, 2D, (2, NCPL)) – array that extracted from MODFLOW at the end of every time step
- Returns
function status; 0 == success
- Return type
int
- pyMF6py.updateUZFRAs(curpTS, rArray)¶
Update the rec array that tracks inputs from HSPF.
- Parameters
curpTS (pd.Timestamp) – current simulation time/day
rArray (np.array, 1D, NUZF) – array that passed from HSPF after checking
- Returns
function status; 0 == success
- Return type
int
4.3.1.2. pyMFLogger.py¶
pyMF6 custom logger leveraging Python logging
Provides specification and configuration of Python’s logging API to use for debugging and informational purposes.
A log file, specified with LOGNAME, is used for receipt of log statements. Logging level is set with LOG_LEVEL.
- pyMF6Logger.FH = None¶
File handler
- pyMF6Logger.FORMATTER = <logging.Formatter object>¶
Custom formatter
- pyMF6Logger.LOGNAME = 'pyMF6_Log.txt'¶
Log file name
- pyMF6Logger.LOGR = <Logger pyMF6 (DEBUG)>¶
Custom logger
- pyMF6Logger.LOG_LEVEL = 10¶
Logging level
- pyMF6Logger.START_TIME = None¶
MODFLOW 6 model start time
- pyMF6Logger.loggerEnd()¶
End the pyMF6 logger
- pyMF6Logger.loggerStart(LFPath)¶
Start the logger to use for pyMF6