Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve toughio.run #156

Merged
merged 11 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
],
)
def test_run(exec, workers, docker, wsl, cmd):
toughio._run._check_exec = False
status = toughio.run(
exec,
{},
Expand Down
2 changes: 1 addition & 1 deletion toughio/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.13.2
1.14.0
2 changes: 2 additions & 0 deletions toughio/_io/input/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def read(filename, file_format=None, **kwargs):

Other Parameters
----------------
blocks : list of str or None, optional, default None
Only if ``file_format = "tough"``. Blocks to read. If None, all blocks are read.
label_length : int or None, optional, default None
Only if ``file_format = "tough"``. Number of characters in cell labels.
n_variables : int or None, optional, default None
Expand Down
161 changes: 110 additions & 51 deletions toughio/_io/input/tough/_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,23 @@
}


def read(filename, label_length=None, n_variables=None, eos=None, simulator="tough"):
def read(
filename,
blocks=None,
label_length=None,
n_variables=None,
eos=None,
simulator="tough",
):
"""
Read TOUGH input file.

Parameters
----------
filename : str, pathlike or buffer
Input file name or buffer.
blocks : list of str or None, optional, default None
Blocks to read. If None, all blocks are read.
label_length : int or None, optional, default None
Number of characters in cell labels.
n_variables : int or None, optional, default None
Expand All @@ -46,39 +55,46 @@
raise ValueError()

with open_file(filename, "r") as f:
out = read_buffer(f, label_length, n_variables, eos, simulator)
out = read_buffer(f, blocks, label_length, n_variables, eos, simulator)

return out


def read_buffer(f, label_length, n_variables, eos, simulator="tough"):
def read_buffer(f, block_stack, label_length, n_variables, eos, simulator="tough"):
"""Read TOUGH input file."""
from ._common import blocks

# Block filters
block_stack = block_stack if block_stack is not None else blocks
block_stack = set(block_stack)

parameters = {}
flag = False

# Title
title = []
while True:
if len(title) >= 100:
raise ValueError()
if "TITLE" in block_stack:
block_stack.remove("TITLE")

line = f.readline().strip()
title = []
while True:
if len(title) >= 100:
raise ValueError()

Check warning on line 81 in toughio/_io/input/tough/_read.py

View check run for this annotation

Codecov / codecov/patch

toughio/_io/input/tough/_read.py#L81

Added line #L81 was not covered by tests

if line[:5].rstrip().upper() not in blocks:
title.append(line)
line = f.readline().strip()

else:
break
if line[:5].rstrip().upper() not in blocks:
title.append(line)

else:
break

Check warning on line 89 in toughio/_io/input/tough/_read.py

View check run for this annotation

Codecov / codecov/patch

toughio/_io/input/tough/_read.py#L89

Added line #L89 was not covered by tests

if title:
title = title[0] if len(title) == 1 else title
if title:
title = title[0] if len(title) == 1 else title

if title:
parameters["title"] = title
if title:
parameters["title"] = title

f.seek(0)
f.seek(0)

# Loop over blocks
# Some blocks (INCON, INDOM, PARAM) need to rewind to previous line but tell and seek are disabled by next
Expand All @@ -87,13 +103,16 @@

try:
for line in fiter:
if line.startswith("DIMEN"):
if line.startswith("DIMEN") and "DIMEN" in block_stack:
block_stack.remove("DIMEN")
parameters.update(_read_dimen(fiter))

elif line.startswith("ROCKS"):
elif line.startswith("ROCKS") and "ROCKS" in block_stack:
block_stack.remove("ROCKS")
parameters.update(_read_rocks(fiter, simulator))

elif line.startswith("RPCAP"):
elif line.startswith("RPCAP") and "RPCAP" in block_stack:
block_stack.remove("RPCAP")
rpcap = _read_rpcap(fiter)

if "default" in parameters:
Expand All @@ -102,43 +121,53 @@
else:
parameters["default"] = rpcap

elif line.startswith("REACT"):
elif line.startswith("REACT") and "REACT" in block_stack:
block_stack.remove("REACT")
react = _read_react(fiter)

if "react" in parameters:
parameters["react"].update(react["react"])

else:
parameters.update(react)

elif line.startswith("FLAC"):
elif line.startswith("FLAC") and "FLAC" in block_stack:
block_stack.remove("FLAC")
flac = _read_flac(fiter, parameters["rocks"])
parameters["flac"] = flac["flac"]

for k, v in flac["rocks"].items():
parameters["rocks"][k].update(v)

elif line.startswith("CHEMP"):
elif line.startswith("CHEMP") and "CHEMP" in block_stack:
block_stack.remove("CHEMP")
parameters.update(_read_chemp(fiter))

elif line.startswith("NCGAS"):
elif line.startswith("NCGAS") and "NCGAS" in block_stack:
block_stack.remove("NCGAS")
parameters.update(_read_ncgas(fiter))

elif line.startswith("MULTI"):
elif line.startswith("MULTI") and "MULTI" in block_stack:
block_stack.remove("MULTI")
parameters.update(_read_multi(fiter))

if not n_variables:
n_variables = parameters["n_component"] + 1

elif line.startswith("SOLVR"):
elif line.startswith("SOLVR") and "SOLVR" in block_stack:
block_stack.remove("SOLVR")
parameters.update(_read_solvr(fiter))

elif line.startswith("INDEX"):
elif line.startswith("INDEX") and "INDEX" in block_stack:
block_stack.remove("INDEX")
parameters["index"] = True

elif line.startswith("START"):
elif line.startswith("START") and "START" in block_stack:
block_stack.remove("START")
parameters["start"] = True

elif line.startswith("PARAM"):
elif line.startswith("PARAM") and "PARAM" in block_stack:
block_stack.remove("PARAM")
param, n_variables = _read_param(fiter, n_variables, eos)
parameters["options"] = param["options"]
parameters["extra_options"] = param["extra_options"]
Expand All @@ -149,83 +178,103 @@
else:
parameters["default"] = param["default"]

elif line.startswith("SELEC"):
elif line.startswith("SELEC") and "SELEC" in block_stack:
block_stack.remove("SELEC")
parameters.update(_read_selec(fiter))

elif line.startswith("INDOM"):
elif line.startswith("INDOM") and "INDOM" in block_stack:
block_stack.remove("INDOM")
indom, n_variables = _read_indom(fiter, n_variables, eos)

for k, v in indom["rocks"].items():
parameters["rocks"][k].update(v)

elif line.startswith("MOMOP"):
elif line.startswith("MOMOP") and "MOMOP" in block_stack:
block_stack.remove("MOMOP")
parameters.update(_read_momop(fiter))

elif line.startswith("TIMES"):
elif line.startswith("TIMES") and "TIMES" in block_stack:
block_stack.remove("TIMES")
parameters.update(_read_times(fiter))

elif line.startswith("HYSTE"):
elif line.startswith("HYSTE") and "HYSTE" in block_stack:
block_stack.remove("HYSTE")
parameters.update(_read_hyste(fiter))

elif line.startswith("FOFT"):
elif line.startswith("FOFT") and "FOFT" in block_stack:
block_stack.remove("FOFT")
oft, label_length = _read_oft(fiter, "FOFT", label_length)
parameters.update(oft)

elif line.startswith("COFT"):
elif line.startswith("COFT") and "COFT" in block_stack:
block_stack.remove("COFT")
oft, label_length = _read_oft(fiter, "COFT", label_length)
parameters.update(oft)

elif line.startswith("GOFT"):
elif line.startswith("GOFT") and "GOFT" in block_stack:
block_stack.remove("GOFT")
oft, label_length = _read_oft(fiter, "GOFT", label_length)
parameters.update(oft)

elif line.startswith("ROFT"):
elif line.startswith("ROFT") and "ROFT" in block_stack:
block_stack.remove("ROFT")
parameters.update(_read_roft(fiter))

elif line.startswith("GENER"):
elif line.startswith("GENER") and "GENER" in block_stack:
block_stack.remove("GENER")
gener, flag, label_length = _read_gener(fiter, label_length, simulator)
parameters.update(gener)

if flag:
break

elif line.startswith("TIMBC"):
elif line.startswith("TIMBC") and "TIMBC" in block_stack:
block_stack.remove("TIMBC")
parameters.update(_read_timbc(fiter))

elif line.startswith("DIFFU"):
elif line.startswith("DIFFU") and "DIFFU" in block_stack:
block_stack.remove("DIFFU")
parameters.update(_read_diffu(fiter))

elif line.startswith("OUTPT"):
elif line.startswith("OUTPT") and "OUTPT" in block_stack:
block_stack.remove("OUTPT")
outpt = _read_outpt(fiter)

if "react" in parameters:
parameters["react"].update(outpt["react"])

else:
parameters.update(outpt)

elif line.startswith("OUTPU"):
elif line.startswith("OUTPU") and "OUTPU" in block_stack:
block_stack.remove("OUTPU")
parameters.update(_read_outpu(fiter))

elif line.startswith("ELEME"):
elif line.startswith("ELEME") and "ELEME" in block_stack:
block_stack.remove("ELEME")
eleme, label_length = _read_eleme(fiter, label_length)
parameters.update(eleme)
parameters["coordinates"] = False

elif line.startswith("COORD"):
elif line.startswith("COORD") and "COORD" in block_stack:
block_stack.remove("COORD")
coord = _read_coord(fiter)

for k, v in zip(parameters["elements"], coord):
parameters["elements"][k]["center"] = v

parameters["coordinates"] = True

elif line.startswith("CONNE"):
elif line.startswith("CONNE") and "CONNE" in block_stack:
block_stack.remove("CONNE")
conne, flag, label_length = _read_conne(fiter, label_length)
parameters.update(conne)

if flag:
break

elif line.startswith("INCON"):
elif line.startswith("INCON") and "INCON" in block_stack:
block_stack.remove("INCON")
incon, flag, label_length, n_variables = _read_incon(
fiter, label_length, n_variables, eos, simulator
)
Expand All @@ -234,25 +283,35 @@
if flag:
break

elif line.startswith("MESHM"):
elif line.startswith("MESHM") and "MESHM" in block_stack:
block_stack.remove("MESHM")
parameters.update(_read_meshm(fiter))

elif line.startswith("POISE"):
elif line.startswith("POISE") and "POISE" in block_stack:
block_stack.remove("POISE")
poise = _read_poise(fiter)

if "react" in parameters:
parameters["react"].update(poise["react"])

else:
parameters.update(poise)

elif line.startswith("NOVER"):
elif line.startswith("NOVER") and "NOVER" in block_stack:
block_stack.remove("NOVER")
parameters["nover"] = True

elif line.startswith("ENDCY"):
elif line.startswith("ENDCY") and "ENDCY" in block_stack:
block_stack.remove("ENDCY")
end_comments = read_end_comments(fiter)

if end_comments:
parameters["end_comments"] = end_comments

# Stop reading if block stack is empty
if not block_stack:
break

Check warning on line 313 in toughio/_io/input/tough/_read.py

View check run for this annotation

Codecov / codecov/patch

toughio/_io/input/tough/_read.py#L313

Added line #L313 was not covered by tests

except:
raise ReadError(f"failed to parse line {fiter.count}.")

Expand Down
Loading
Loading