From 76a59fdbd21f2bc521e024b993cdae70fa2a9b37 Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Sat, 1 Apr 2023 11:47:33 +0200 Subject: [PATCH 1/8] support block ROFT --- toughio/_common.py | 1 + toughio/_io/input/tough/_common.py | 2 ++ toughio/_io/input/tough/_helpers.py | 1 + toughio/_io/input/tough/_read.py | 24 ++++++++++++++++++++++++ toughio/_io/input/tough/_write.py | 17 +++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/toughio/_common.py b/toughio/_common.py index 107a33a1..e4263039 100644 --- a/toughio/_common.py +++ b/toughio/_common.py @@ -41,6 +41,7 @@ "FOFT": {5: "5s", 6: "6s", 7: "7s", 8: "8s", 9: "9s"}, "COFT": {5: "10s", 6: "12s", 7: "14s", 8: "16s", 9: "18s"}, "GOFT": {5: "5s", 6: "6s", 7: "7s", 8: "8s", 9: "9s"}, + "ROFT": "5s,5s", "GENER": { 0: ",".join(4 * ["14f"]), # Last integer is for KTAB value in TOUGHREACT diff --git a/toughio/_io/input/tough/_common.py b/toughio/_io/input/tough/_common.py index c6737558..33a577bc 100644 --- a/toughio/_io/input/tough/_common.py +++ b/toughio/_io/input/tough/_common.py @@ -19,6 +19,7 @@ "FOFT", "COFT", "GOFT", + "ROFT", "GENER", "TIMBC", "DIFFU", @@ -62,6 +63,7 @@ "element_history": [], "connection_history": [], "generator_history": [], + "rock_history": [], "output": {}, "elements": {}, "coordinates": False, diff --git a/toughio/_io/input/tough/_helpers.py b/toughio/_io/input/tough/_helpers.py index a1265543..10fe1f91 100644 --- a/toughio/_io/input/tough/_helpers.py +++ b/toughio/_io/input/tough/_helpers.py @@ -35,6 +35,7 @@ "element_history": "array_like", "connection_history": "array_like", "generator_history": "array_like", + "rock_history": "array_like", "diffusion": "array_like", "output": "dict", "elements": "dict", diff --git a/toughio/_io/input/tough/_read.py b/toughio/_io/input/tough/_read.py index 37f87fa1..237e1bc6 100644 --- a/toughio/_io/input/tough/_read.py +++ b/toughio/_io/input/tough/_read.py @@ -172,6 +172,9 @@ def read_buffer(f, label_length, n_variables, eos, simulator="tough"): oft, label_length = _read_oft(fiter, "GOFT", label_length) parameters.update(oft) + elif line.startswith("ROFT"): + parameters.update(_read_roft(fiter)) + elif line.startswith("GENER"): gener, label_length = _read_gener(fiter, label_length, simulator) parameters.update(gener) @@ -769,6 +772,27 @@ def _read_oft(f, oft, label_length): return history, label_length +def _read_roft(f): + """Read ROFT block data.""" + fmt = block_to_format["ROFT"] + history = {"rock_history": []} + + line = f.next() + while True: + if line.strip(): + data = read_record(line, fmt) + rock1 = data[0] if data[0] else "" + rock2 = data[1] if data[1] else "" + history["rock_history"].append([rock1, rock2]) + + else: + break + + line = f.next() + + return history + + def _read_gener(f, label_length, simulator="tough"): """Read GENER block data.""" diff --git a/toughio/_io/input/tough/_write.py b/toughio/_io/input/tough/_write.py index 0d6cdf35..1acf78c6 100644 --- a/toughio/_io/input/tough/_write.py +++ b/toughio/_io/input/tough/_write.py @@ -332,6 +332,9 @@ def write_buffer( if "GOFT" in blocks and len(parameters["generator_history"]): out += _write_goft(parameters) + if "ROFT" in blocks and len(parameters["rock_history"]): + out += _write_roft(parameters) + if "GENER" in blocks and parameters["generators"]: out += _write_gener(parameters, simulator) @@ -1075,6 +1078,20 @@ def _write_goft(parameters): return out +@block("ROFT", multi=True) +def _write_roft(parameters): + """Write ROFT block data.""" + # Format + fmt = block_to_format["ROFT"] + fmt = str2format(fmt) + + out = [] + for values in parameters["rock_history"]: + out += write_record(values, fmt) + + return out + + @check_parameters(dtypes["GENER"], keys="generators", is_list=True) @block("GENER", multi=True) def _write_gener(parameters, simulator="tough"): From f1a6e80f790be7e6e311231dd71fd26cd366b05e Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Sat, 1 Apr 2023 11:47:45 +0200 Subject: [PATCH 2/8] test block ROFT --- tests/test_input.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_input.py b/tests/test_input.py index 8c2cd85b..65a1089d 100644 --- a/tests/test_input.py +++ b/tests/test_input.py @@ -453,6 +453,16 @@ def test_oft(write_read, oft, n): assert helpers.allclose(parameters_ref, parameters) +@pytest.mark.parametrize("write_read", [write_read_tough, write_read_json]) +def test_roft(write_read): + parameters_ref = { + "rock_history": [[helpers.random_string(5), helpers.random_string(5)] for _ in range(np.random.randint(10) + 1)] + } + parameters = write_read(parameters_ref) + + assert helpers.allclose(parameters_ref, parameters) + + @pytest.mark.parametrize( "write_read, specific_enthalpy, label_length", [ From 9f3aa4852f033dbd6d078fe349193e6b68be2331 Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Sat, 1 Apr 2023 11:52:10 +0200 Subject: [PATCH 3/8] fix title --- toughio/_io/input/tough/_read.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/toughio/_io/input/tough/_read.py b/toughio/_io/input/tough/_read.py index 237e1bc6..42bea3f5 100644 --- a/toughio/_io/input/tough/_read.py +++ b/toughio/_io/input/tough/_read.py @@ -65,14 +65,17 @@ def read_buffer(f, label_length, n_variables, eos, simulator="tough"): line = f.readline().strip() - if line[:5].upper() not in blocks: + if line[:5].rstrip().upper() not in blocks: title.append(line) else: break if title: - parameters["title"] = title[0] if len(title) == 1 else title + title = title[0] if len(title) == 1 else title + + if title: + parameters["title"] = title f.seek(0) From 462a432c13249dbc206d73e8e1ad73f76f854daf Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Sat, 1 Apr 2023 11:53:26 +0200 Subject: [PATCH 4/8] invoke format --- tests/test_input.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_input.py b/tests/test_input.py index 65a1089d..e9ed2c84 100644 --- a/tests/test_input.py +++ b/tests/test_input.py @@ -456,7 +456,10 @@ def test_oft(write_read, oft, n): @pytest.mark.parametrize("write_read", [write_read_tough, write_read_json]) def test_roft(write_read): parameters_ref = { - "rock_history": [[helpers.random_string(5), helpers.random_string(5)] for _ in range(np.random.randint(10) + 1)] + "rock_history": [ + [helpers.random_string(5), helpers.random_string(5)] + for _ in range(np.random.randint(10) + 1) + ] } parameters = write_read(parameters_ref) From c6b7c7a896c3d219340f095a3e68e57620655214 Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Sat, 1 Apr 2023 11:53:37 +0200 Subject: [PATCH 5/8] version bump --- toughio/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toughio/VERSION b/toughio/VERSION index 6f165bc1..69669de6 100644 --- a/toughio/VERSION +++ b/toughio/VERSION @@ -1 +1 @@ -1.12.1 \ No newline at end of file +1.12.2 \ No newline at end of file From c15b3a2790a924ee6dd1acf74d8686e4af262937 Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Mon, 3 Apr 2023 10:23:42 +0200 Subject: [PATCH 6/8] fix table reader for ROFT --- toughio/_io/table/csv/_csv.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/toughio/_io/table/csv/_csv.py b/toughio/_io/table/csv/_csv.py index d973b139..217040f8 100644 --- a/toughio/_io/table/csv/_csv.py +++ b/toughio/_io/table/csv/_csv.py @@ -27,19 +27,26 @@ def read(filename): """ with open_file(filename, "r") as f: + # Read headers line = f.readline().strip() + sep = "," if "," in line else None - if line.startswith('"'): - sep = "," - line = line.replace('"', "") + headers = [] + while True: + hdr = [x.replace('"', "").strip() for x in line.split(sep)] - else: - sep = None + try: + _ = float(hdr[0]) + break - headers = [x.strip() for x in line.split(sep)] + except ValueError: + headers.append(hdr) + line = f.readline().strip() + headers = [" ".join(hdr) for hdr in zip(*headers)] + + # Read data data = [] - line = f.readline().strip() while line: data.append([x.replace('"', "").strip() for x in line.split(sep)]) line = f.readline().strip() From 4d82b50664cc7aa4d623634301a7f1cb8f28e3af Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Mon, 3 Apr 2023 10:28:56 +0200 Subject: [PATCH 7/8] test ROFT --- tests/support_files/outputs/ROFT.csv | 3 +++ tests/test_table.py | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/support_files/outputs/ROFT.csv diff --git a/tests/support_files/outputs/ROFT.csv b/tests/support_files/outputs/ROFT.csv new file mode 100644 index 00000000..a75f8573 --- /dev/null +++ b/tests/support_files/outputs/ROFT.csv @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ea9db64f2fde4f04f404b6868424da203197be20c22c8e8e7025b132b6df63a +size 2424 diff --git a/tests/test_table.py b/tests/test_table.py index dcac5657..f23cc993 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -79,6 +79,17 @@ "csv", {"TIME(S)": 3.06639400e9, "GEN": -27.5, "ENTG": 1.40141971e7, "PWB": 0.0}, ), + ( + "ROFT.csv", + "csv", + { + "TIME (S)": 3.06639400e9, + "PRES (PA)": 1.83000721e8, + "TEMP (C)": 660.0, + "SAT_G (-)": 0.0, + "SAT_L (-)": 22.0, + }, + ), ], ) def test_table(filename, file_format, data_ref): From 6094bb7ec23f0167c18da4b2655f85618dd26490 Mon Sep 17 00:00:00 2001 From: Keurfon Luu Date: Tue, 4 Apr 2023 08:26:23 +0200 Subject: [PATCH 8/8] update doc --- doc/source/guide/input.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/guide/input.rst b/doc/source/guide/input.rst index 2d9641f9..6744dffa 100644 --- a/doc/source/guide/input.rst +++ b/doc/source/guide/input.rst @@ -67,11 +67,12 @@ A TOUGH input file is defined as follows: "selections": dict, "generators": list[dict], "boundary_conditions": list[dict], - "diffusion": list[list], + "diffusion": list[list[float]], "times": list[float], "element_history": list[str], "connection_history": list[str], "generator_history": list[str], + "rock_history": list[list[str]], "output": dict, "elements": dict, "connections": dict, @@ -253,7 +254,7 @@ History ******* Outputs can be generated at specific time steps in ``"times"`` (block TIMES) defined as a list where each value corresponds to a time step at which an output is desired. -Time-dependent outputs at specific element, connection or generator can be requested in ``"element_history"``, ``"connection_history"`` and ``"generator_history"`` as a list where each value is the label associated to the desired elements/connections. +Time-dependent outputs at specific element, connection or generator can be requested in ``"element_history"``, ``"connection_history"`` and ``"generator_history"`` as a list where each value is the label associated to the desired elements/connections. For TOUGH3 v1.1 and above, ``"rock_history"`` can be used to generate rock to rock flow data. Hysteresis options