This page was generated from nwt_option_blocks_tutorial.py. It's also available as a notebook.

Working with MODFLOW-NWT v 1.1 option blocks

In MODFLOW-NWT an option block is present for the WEL file, UZF file, and SFR file. This block takes keyword arguments that are supplied in an option line in other versions of MODFLOW.

The OptionBlock class was created to provide combatibility with the MODFLOW-NWT option block and allow the user to easily edit values within the option block

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

import flopy
from flopy.utils import OptionBlock

print(sys.version)
print(f"flopy version: {flopy.__version__}")
3.9.19 (main, Mar 20 2024, 16:40:02)
[GCC 11.4.0]
flopy version: 3.7.0.dev0
[2]:
load_ws = os.path.join("..", "..", "examples", "data", "options", "sagehen")

# temporary directory
temp_dir = TemporaryDirectory()
model_ws = os.path.join(temp_dir.name, "nwt_options", "output")

Loading a MODFLOW-NWT model that has option block options

It is critical to set the version flag in flopy.modflow.Modflow.load() to version='mfnwt'

We are going to load a modified version of the Sagehen test problem from GSFLOW to illustrate compatibility

[3]:
mfexe = "mfnwt"

ml = flopy.modflow.Modflow.load(
    "sagehen.nam", model_ws=load_ws, exe_name=mfexe, version="mfnwt"
)
ml.change_model_ws(new_pth=model_ws)
ml.write_input()
   loading iuzfbnd array...
   loading vks array...
   loading eps array...
   loading thts array...
stress period 1:
   loading finf array...
stress period 2:

creating model workspace...
   ../../../../../../../tmp/tmp0lq6meb1/nwt_options/output

Let’s look at the options attribute of the UZF object

The uzf.options attribute is an OptionBlock object. The representation of this object is the option block that will be written to output, which allows the user to easily check to make sure the block has the options they want.

[4]:
uzf = ml.get_package("UZF")
uzf.options
[4]:
OPTIONS
NOSURFLEAK
ETSQUARE 0.2
SAVEFINF
END

The OptionBlock object also has attributes which correspond to the option names listed in the online guide to modflow

The user can call and edit the options within the option block

[5]:
print(uzf.options.nosurfleak)
print(uzf.options.savefinf)
True
True
[6]:
uzf.options.etsquare = False
uzf.options
[6]:
OPTIONS
NOSURFLEAK
SAVEFINF
END
[7]:
uzf.options.etsquare = True
uzf.options
[7]:
OPTIONS
NOSURFLEAK
ETSQUARE 0.2
SAVEFINF
END

The user can also see the single line representation of the options

[8]:
uzf.options.single_line_options
[8]:
'NOSURFLEAK ETSQUARE 0.2 SAVEFINF'

And the user can easily change to single line options writing

[9]:
uzf.options.block = False

# write out only the uzf file
uzf_name = "uzf_opt.uzf"
uzf.write_file(os.path.join(model_ws, uzf_name))

Now let’s examine the first few lines of the new UZF file

[10]:
f = open(os.path.join(model_ws, uzf_name))
for ix, line in enumerate(f):
    if ix == 3:
        break
    else:
        print(line)
# UZF package for MODFLOW-NWT generated by Flopy 3.7.0.dev0

NOSURFLEAK ETSQUARE 0.2 SAVEFINF

         3         1         0         0         0         0        15       100         4   1.000000E+00 #NUZTOP IUZFOPT IRUNFLG IETFLG ipakcb IUZFCB2 NTRAIL NSETS NUZGAGES

And let’s load the new UZF file

[11]:
uzf2 = flopy.modflow.ModflowUzf1.load(
    os.path.join(model_ws, uzf_name), ml, check=False
)
   loading iuzfbnd array...
   loading vks array...
   loading eps array...
   loading thts array...
stress period 1:
   loading finf array...
stress period 2:
/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/flopy/mbase.py:668: UserWarning: Two packages of the same type, Replacing existing 'UZF' package.
  warn(

Now we can look at the options object, and check if it’s block or line format

block=False indicates that options will be written as line format

[12]:
print(uzf2.options)
print(uzf2.options.block)
OPTIONS
NOSURFLEAK
ETSQUARE 0.2
SAVEFINF
END

False

Finally we can convert back to block format

[13]:
uzf2.options.block = True
uzf2.write_file(os.path.join(model_ws, uzf_name))
ml.remove_package("UZF")

uzf3 = flopy.modflow.ModflowUzf1.load(
    os.path.join(model_ws, uzf_name), ml, check=False
)
print("\n")
print(uzf3.options)
print(uzf3.options.block)
   loading iuzfbnd array...
   loading vks array...
   loading eps array...
   loading thts array...
stress period 1:
   loading finf array...
stress period 2:


OPTIONS
NOSURFLEAK
ETSQUARE 0.2
SAVEFINF
END

True

We can also look at the WEL object

[14]:
wel = ml.get_package("WEL")
wel.options
[14]:
OPTIONS
SPECIFY 0.1 90
END

Let’s write this out as a single line option block and examine the first few lines

[15]:
wel_name = "wel_opt.wel"
wel.options.block = False

wel.write_file(os.path.join(model_ws, wel_name))


f = open(os.path.join(model_ws, wel_name))
for ix, line in enumerate(f):
    if ix == 4:
        break
    else:
        print(line)
# WEL package for MODFLOW-NWT generated by Flopy 3.7.0.dev0

         5         0 NOPRINT

SPECIFY 0.1 90

         5         0 # stress period 1

And we can load the new single line options WEL file and confirm that it is being read as an option line

[16]:
ml.remove_package("WEL")
wel2 = flopy.modflow.ModflowWel.load(
    os.path.join(model_ws, wel_name), ml, nper=ml.nper, check=False
)

wel2.options
wel2.options.block
[16]:
False

Building an OptionBlock from scratch

The user can also build an OptionBlock object from scratch to add to a ModflowSfr2, ModflowUzf1, or ModflowWel file.

The OptionBlock class has two required parameters and one optional parameter

option_line: a one line, string based representation of the options

package: a modflow package object

block: boolean flag for line based or block based options

[17]:
opt_line = "specify 0.1 20"
options = OptionBlock(opt_line, flopy.modflow.ModflowWel, block=True)
options
[17]:
OPTIONS
SPECIFY 0.1 20
END

from here we can set the noprint flag by using options.noprint

[18]:
options.noprint = True

and the user can also add auxiliary variables by using options.auxiliary

[19]:
options.auxiliary = ["aux", "iface"]

Now we can create a new wel file using this OptionBlock

and write it to output

[20]:
wel3 = flopy.modflow.ModflowWel(
    ml,
    stress_period_data=wel.stress_period_data,
    options=options,
    unitnumber=99,
)

wel3.write_file(os.path.join(model_ws, wel_name))
/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/flopy/mbase.py:668: UserWarning: Two packages of the same type, Replacing existing 'WEL' package.
  warn(

And now let’s examine the first few lines of the file

[21]:
f = open(os.path.join(model_ws, wel_name))
for ix, line in enumerate(f):
    if ix == 8:
        break
    else:
        print(line)
# WEL package for MODFLOW-NWT generated by Flopy 3.7.0.dev0

OPTIONS

SPECIFY 0.1 20

END

         5         0 NOPRINT AUX IFACE

         5         0 # stress period 1

         1        35        12            20.0

         1        36        13            21.0

We can see that everything that the OptionBlock class writes out options in the correct location.

The user can also switch the options over to option line style and write out the output too!

[22]:
wel3.options.block = False
wel3.write_file(os.path.join(model_ws, wel_name))

f = open(os.path.join(model_ws, wel_name))
for ix, line in enumerate(f):
    if ix == 6:
        break
    else:
        print(line)
# WEL package for MODFLOW-NWT generated by Flopy 3.7.0.dev0

         5         0 NOPRINT AUX IFACE

SPECIFY 0.1 20

         5         0 # stress period 1

         1        35        12            20.0

         1        36        13            21.0

[23]:
try:
    # ignore PermissionError on Windows
    temp_dir.cleanup()
except:
    pass