Note

Interactive online version: Binder badge

Formatting ASCII output arrays

A quick demo of how to control the ASCII format of numeric arrays written by FloPy

load and run the Freyberg model

[1]:
import sys
import os
from tempfile import TemporaryDirectory

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

# run installed version of flopy or add local path
try:
    import flopy
except:
    fpth = os.path.abspath(os.path.join("..", ".."))
    sys.path.append(fpth)
    import flopy

# Set name of MODFLOW exe
#  assumes executable is in users path statement
version = "mf2005"
exe_name = "mf2005"
mfexe = exe_name

# Set the paths
loadpth = os.path.join("..", "..", "examples", "data", "freyberg")
temp_dir = TemporaryDirectory()
modelpth = temp_dir.name

# make sure modelpth directory exists
if not os.path.isdir(modelpth):
    os.makedirs(modelpth)

print(sys.version)
print("numpy version: {}".format(np.__version__))
print("matplotlib version: {}".format(mpl.__version__))
print("flopy version: {}".format(flopy.__version__))
3.10.10 | packaged by conda-forge | (main, Mar 24 2023, 20:08:06) [GCC 11.3.0]
numpy version: 1.24.3
matplotlib version: 3.7.1
flopy version: 3.3.7
[2]:
ml = flopy.modflow.Modflow.load(
    "freyberg.nam", model_ws=loadpth, exe_name=exe_name, version=version
)
ml.model_ws = modelpth
ml.write_input()
success, buff = ml.run_model(silent=True, report=True)
if success:
    for line in buff:
        print(line)
else:
    raise ValueError("Failed to run.")

files = ["freyberg.hds", "freyberg.cbc"]
for f in files:
    if os.path.isfile(os.path.join(modelpth, f)):
        msg = "Output file located: {}".format(f)
        print(msg)
    else:
        errmsg = "Error. Output file cannot be found: {}".format(f)
        print(errmsg)

                                  MODFLOW-2005
    U.S. GEOLOGICAL SURVEY MODULAR FINITE-DIFFERENCE GROUND-WATER FLOW MODEL
                             Version 1.12.00 2/3/2017

 Using NAME file: freyberg.nam
 Run start date and time (yyyy/mm/dd hh:mm:ss): 2023/05/04 15:59:20

 Solving:  Stress period:     1    Time step:     1    Ground-Water Flow Eqn.
 Run end date and time (yyyy/mm/dd hh:mm:ss): 2023/05/04 15:59:20
 Elapsed run time:  0.011 Seconds

  Normal termination of simulation
Output file located: freyberg.hds
Output file located: freyberg.cbc

Each Util2d instance now has a .format attribute, which is an ArrayFormat instance:

[3]:
print(ml.lpf.hk[0].format)
ArrayFormat: npl:20,format:E,width:15,decimal6,isfree:True,isbinary:False

The ArrayFormat class exposes each of the attributes seen in the ArrayFormat.___str___() call. ArrayFormat also exposes .fortran, .py and .numpy atrributes, which are the respective format descriptors:

[4]:
print(ml.dis.botm[0].format.fortran)
print(ml.dis.botm[0].format.py)
print(ml.dis.botm[0].format.numpy)
(FREE)
(20, '{0:15.6E}')
%15E.6

(re)-setting .format

We can reset the format using a standard fortran type format descriptor

[5]:
ml.dis.botm[0].format.free = False
ml.dis.botm[0].format.fortran = "(20f10.4)"
print(ml.dis.botm[0].format.fortran)
print(ml.dis.botm[0].format.py)
print(ml.dis.botm[0].format.numpy)
print(ml.dis.botm[0].format)
(20F10.4)
(20, '{0:10.4F}')
%10F.4
ArrayFormat: npl:20,format:F,width:10,decimal4,isfree:False,isbinary:False
[6]:
ml.write_input()
success, buff = ml.run_model(silent=True, report=True)
if success:
    for line in buff:
        print(line)
else:
    raise ValueError("Failed to run.")

                                  MODFLOW-2005
    U.S. GEOLOGICAL SURVEY MODULAR FINITE-DIFFERENCE GROUND-WATER FLOW MODEL
                             Version 1.12.00 2/3/2017

 Using NAME file: freyberg.nam
 Run start date and time (yyyy/mm/dd hh:mm:ss): 2023/05/04 15:59:20

 Solving:  Stress period:     1    Time step:     1    Ground-Water Flow Eqn.
 Run end date and time (yyyy/mm/dd hh:mm:ss): 2023/05/04 15:59:20
 Elapsed run time:  0.009 Seconds

  Normal termination of simulation

Let’s load the model we just wrote and check that the desired botm[0].format was used:

[7]:
ml1 = flopy.modflow.Modflow.load("freyberg.nam", model_ws=modelpth)
print(ml1.dis.botm[0].format)
ArrayFormat: npl:20,format:E,width:15,decimal6,isfree:True,isbinary:False

We can also reset individual format components (we can also generate some warnings):

[8]:
ml.dis.botm[0].format.width = 9
ml.dis.botm[0].format.decimal = 1
print(ml1.dis.botm[0].format)
ArrayFormat warning:setting width less than default of 15
ArrayFormat warning: setting decimal less than default of 6
ArrayFormat warning: setting decimal less than current value of 6
ArrayFormat: npl:20,format:E,width:15,decimal6,isfree:True,isbinary:False

We can also select free format. Note that setting to free format resets the format attributes to the default, max precision:

[9]:
ml.dis.botm[0].format.free = True
print(ml1.dis.botm[0].format)
ArrayFormat: npl:20,format:E,width:15,decimal6,isfree:True,isbinary:False
[10]:
ml.write_input()
success, buff = ml.run_model(silent=True, report=True)
if success:
    for line in buff:
        print(line)
else:
    raise ValueError("Failed to run.")

                                  MODFLOW-2005
    U.S. GEOLOGICAL SURVEY MODULAR FINITE-DIFFERENCE GROUND-WATER FLOW MODEL
                             Version 1.12.00 2/3/2017

 Using NAME file: freyberg.nam
 Run start date and time (yyyy/mm/dd hh:mm:ss): 2023/05/04 15:59:20

 Solving:  Stress period:     1    Time step:     1    Ground-Water Flow Eqn.
 Run end date and time (yyyy/mm/dd hh:mm:ss): 2023/05/04 15:59:20
 Elapsed run time:  0.009 Seconds

  Normal termination of simulation
[11]:
ml1 = flopy.modflow.Modflow.load("freyberg.nam", model_ws=modelpth)
print(ml1.dis.botm[0].format)
ArrayFormat: npl:20,format:E,width:15,decimal6,isfree:True,isbinary:False