completor 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- completor/constants.py +1 -0
- completor/create_output.py +57 -16
- completor/main.py +8 -2
- completor/prepare_outputs.py +141 -0
- completor/read_casefile.py +14 -0
- {completor-1.2.0.dist-info → completor-1.3.0.dist-info}/METADATA +7 -7
- {completor-1.2.0.dist-info → completor-1.3.0.dist-info}/RECORD +10 -10
- {completor-1.2.0.dist-info → completor-1.3.0.dist-info}/LICENSE +0 -0
- {completor-1.2.0.dist-info → completor-1.3.0.dist-info}/WHEEL +0 -0
- {completor-1.2.0.dist-info → completor-1.3.0.dist-info}/entry_points.txt +0 -0
completor/constants.py
CHANGED
|
@@ -254,6 +254,7 @@ class _Keywords:
|
|
|
254
254
|
INFLOW_CONTROL_VALVE = "WSEGICV"
|
|
255
255
|
INFLOW_CONTROL_DEVICE = "WSEGSICD"
|
|
256
256
|
DENSITY = "WSEGDENSITY"
|
|
257
|
+
PYTHON_DEPENDENT = "PYTHON"
|
|
257
258
|
DENSITY_ACTIVATED_RECOVERY = "WSEGDAR"
|
|
258
259
|
INJECTION_VALVE = "WSEGINJV"
|
|
259
260
|
LATERAL_TO_DEVICE = "LATERAL_TO_DEVICE"
|
completor/create_output.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import getpass
|
|
6
6
|
from datetime import datetime
|
|
7
7
|
|
|
8
|
+
import matplotlib.pyplot as plt # type: ignore
|
|
8
9
|
import numpy as np
|
|
9
10
|
import numpy.typing as npt
|
|
10
11
|
import pandas as pd
|
|
@@ -20,13 +21,13 @@ from completor.visualize_well import visualize_well
|
|
|
20
21
|
from completor.wells import Lateral, Well
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def format_output(well: Well, case: ReadCasefile,
|
|
24
|
+
def format_output(well: Well, case: ReadCasefile, pdf: PdfPages | None = None) -> tuple[str, str, str, str]:
|
|
24
25
|
"""Formats the finished output string to be written to a file.
|
|
25
26
|
|
|
26
27
|
Args:
|
|
27
28
|
well: Well data.
|
|
28
29
|
case: Case data.
|
|
29
|
-
|
|
30
|
+
pdf: The name of the figure, if None, no figure is printed. Defaults to None.
|
|
30
31
|
|
|
31
32
|
Returns:
|
|
32
33
|
Properly formatted output data for completion data, well segments, completion segments, and bonus.
|
|
@@ -41,8 +42,10 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
41
42
|
print_autonomous_inflow_control_device = ""
|
|
42
43
|
print_inflow_control_device = ""
|
|
43
44
|
print_density_driven = ""
|
|
45
|
+
print_density_driven_include = ""
|
|
44
46
|
print_injection_valve = ""
|
|
45
47
|
print_dual_rate_controlled_production = ""
|
|
48
|
+
print_density_driven_pyaction = ""
|
|
46
49
|
|
|
47
50
|
start_segment = 2
|
|
48
51
|
start_branch = 1
|
|
@@ -147,23 +150,35 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
147
150
|
print_inflow_control_valve += _format_inflow_control_valve(
|
|
148
151
|
well.well_name, lateral.lateral_number, df_inflow_control_valve, first
|
|
149
152
|
)
|
|
150
|
-
print_density_driven += _format_density_driven(well.well_number, df_density_driven)
|
|
151
153
|
print_injection_valve += _format_injection_valve(well.well_number, df_injection_valve)
|
|
152
154
|
print_dual_rate_controlled_production += _format_dual_rate_controlled_production(
|
|
153
155
|
well.well_number, df_dual_rate_controlled_production
|
|
154
156
|
)
|
|
157
|
+
# output using ACTIONX (if-else) logic is dual RCP, density driven, and injection valve
|
|
158
|
+
if case.python_dependent:
|
|
159
|
+
# print the python file out
|
|
160
|
+
# append all laterals for density driven, dual RCP, and injection valve
|
|
161
|
+
# TODO(#274): Add functionality for dual RCP
|
|
162
|
+
print_density_driven_pyaction = _format_density_driven_pyaction(df_density_driven)
|
|
163
|
+
output_directory = prepare_outputs.print_python_file(
|
|
164
|
+
print_density_driven_pyaction, str(case.output_file), well.well_name, lateral.lateral_number
|
|
165
|
+
)
|
|
166
|
+
print_density_driven_include += prepare_outputs.print_wsegdensity_include(
|
|
167
|
+
output_directory, well.well_name, lateral.lateral_number
|
|
168
|
+
)
|
|
169
|
+
else:
|
|
170
|
+
print_density_driven += _format_density_driven(well.well_number, df_density_driven)
|
|
155
171
|
|
|
156
|
-
if
|
|
157
|
-
logger.info(f"Creating figure for lateral {lateral.lateral_number}.")
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
)
|
|
165
|
-
logger.info("Creating schematics: %s.pdf", figure_name)
|
|
172
|
+
if pdf is not None:
|
|
173
|
+
logger.info(f"Creating figure for well {well.well_name}, lateral {lateral.lateral_number}.")
|
|
174
|
+
fig = visualize_well(
|
|
175
|
+
well.well_name, well.df_well_all_laterals, well.df_reservoir_all_laterals, case.segment_length
|
|
176
|
+
)
|
|
177
|
+
pdf.savefig(fig, orientation="landscape")
|
|
178
|
+
plt.close(fig)
|
|
179
|
+
logger.info("Creating schematics: %s", pdf)
|
|
166
180
|
first = False
|
|
181
|
+
|
|
167
182
|
print_completion_data = "\n".join(completion_data_list)
|
|
168
183
|
if print_well_segments:
|
|
169
184
|
print_well_segments = f"{print_well_segments}\n/\n\n"
|
|
@@ -185,7 +200,7 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
185
200
|
if print_density_driven:
|
|
186
201
|
metadata = (
|
|
187
202
|
f"{'-' * 100}\n"
|
|
188
|
-
"-- This is how we model
|
|
203
|
+
"-- This is how we model density driven technology using sets of ACTIONX keywords.\n"
|
|
189
204
|
"-- The segment dP curves changes according to the segment water-\n"
|
|
190
205
|
"-- and gas volume fractions at downhole condition.\n"
|
|
191
206
|
"-- The value of Cv is adjusted according to the segment length and the number of\n"
|
|
@@ -197,7 +212,7 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
197
212
|
if print_injection_valve:
|
|
198
213
|
metadata = (
|
|
199
214
|
f"{'-' * 100}\n"
|
|
200
|
-
"-- This is how we model
|
|
215
|
+
"-- This is how we model autonomous injection valve technology using sets of ACTIONX keywords.\n"
|
|
201
216
|
"-- The DP paramaters changes according to the trigger parameter.-\n"
|
|
202
217
|
"-- The value of Cv is adjusted according to the segment length and the number of\n"
|
|
203
218
|
"-- devices per joint. The constriction area will change if the parameter is triggered.\n"
|
|
@@ -207,12 +222,24 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
207
222
|
if print_dual_rate_controlled_production:
|
|
208
223
|
metadata = (
|
|
209
224
|
f"{'-' * 100}\n"
|
|
210
|
-
"-- This is how we model
|
|
225
|
+
"-- This is how we model dual RCP curves using sets of ACTIONX keyword\n"
|
|
211
226
|
"-- the DP parameters change according to the segment water cut (at downhole condition )\n"
|
|
212
227
|
"-- and gas volume fraction (at downhole condition)\n"
|
|
213
228
|
f"{'-' * 100}\n\n\n"
|
|
214
229
|
)
|
|
215
230
|
bonus.append(metadata + print_dual_rate_controlled_production + "\n\n\n\n")
|
|
231
|
+
if print_density_driven_pyaction:
|
|
232
|
+
metadata = (
|
|
233
|
+
f"{'-' * 100}\n"
|
|
234
|
+
"-- This is how we model density driven technology for python dependent keyword.\n"
|
|
235
|
+
"-- The segment dP curves changes according to the segment water-\n"
|
|
236
|
+
"-- and gas volume fractions at downhole condition.\n"
|
|
237
|
+
"-- The value of Cv is adjusted according to the segment length and the number of\n"
|
|
238
|
+
"-- devices per joint. The constriction area varies according to values of\n"
|
|
239
|
+
"-- volume fractions.\n"
|
|
240
|
+
f"{'-' * 100}\n\n\n"
|
|
241
|
+
)
|
|
242
|
+
bonus.append(metadata + print_density_driven_include + "\n\n\n\n")
|
|
216
243
|
|
|
217
244
|
return print_completion_data, print_well_segments, print_completion_segments, "".join(bonus)
|
|
218
245
|
|
|
@@ -463,6 +490,20 @@ def _format_density_driven(well_number: int, df_wsegdensity: pd.DataFrame) -> st
|
|
|
463
490
|
return prepare_outputs.print_wsegdensity(df_wsegdensity, well_number + 1)
|
|
464
491
|
|
|
465
492
|
|
|
493
|
+
def _format_density_driven_pyaction(df_wsegdensity: pd.DataFrame) -> str:
|
|
494
|
+
"""Formats well-segments for density driven valve.
|
|
495
|
+
|
|
496
|
+
Args:
|
|
497
|
+
df_wsegdensity: Data to print.
|
|
498
|
+
|
|
499
|
+
Returns:
|
|
500
|
+
Formatted string.
|
|
501
|
+
"""
|
|
502
|
+
if df_wsegdensity.empty:
|
|
503
|
+
return ""
|
|
504
|
+
return prepare_outputs.print_wsegdensity_pyaction(df_wsegdensity)
|
|
505
|
+
|
|
506
|
+
|
|
466
507
|
def _format_injection_valve(well_number: int, df_wseginjv: pd.DataFrame) -> str:
|
|
467
508
|
"""Formats well-segments for injection valve.
|
|
468
509
|
|
completor/main.py
CHANGED
|
@@ -5,8 +5,10 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
7
|
import re
|
|
8
|
+
import sys
|
|
8
9
|
import time
|
|
9
10
|
|
|
11
|
+
from matplotlib.backends.backend_pdf import PdfPages # type: ignore
|
|
10
12
|
from tqdm import tqdm
|
|
11
13
|
|
|
12
14
|
from completor import create_output, parse, read_schedule, utils
|
|
@@ -89,6 +91,7 @@ def create(
|
|
|
89
91
|
"""
|
|
90
92
|
case = ReadCasefile(case_file=case_file, schedule_file=schedule, output_file=new_file)
|
|
91
93
|
active_wells = utils.get_active_wells(case.completion_table, case.gp_perf_devicelayer)
|
|
94
|
+
pdf = None
|
|
92
95
|
figure_name = None
|
|
93
96
|
if show_fig:
|
|
94
97
|
figure_no = 1
|
|
@@ -96,6 +99,7 @@ def create(
|
|
|
96
99
|
while os.path.isfile(figure_name):
|
|
97
100
|
figure_no += 1
|
|
98
101
|
figure_name = f"Well_schematic_{figure_no:03d}.pdf"
|
|
102
|
+
pdf = PdfPages(figure_name)
|
|
99
103
|
|
|
100
104
|
err: Exception | None = None
|
|
101
105
|
well = None
|
|
@@ -122,13 +126,13 @@ def create(
|
|
|
122
126
|
for chunk in find_keyword_data(Keywords.COMPLETION_SEGMENTS, schedule):
|
|
123
127
|
clean_data = clean_raw_data(chunk, Keywords.COMPLETION_SEGMENTS)
|
|
124
128
|
meaningful_data = read_schedule.set_compsegs(meaningful_data, clean_data)
|
|
125
|
-
for i, well_name in tqdm(enumerate(active_wells.tolist()), total=len(active_wells)):
|
|
129
|
+
for i, well_name in tqdm(enumerate(active_wells.tolist()), total=len(active_wells), file=sys.stdout):
|
|
126
130
|
try:
|
|
127
131
|
well = Well(well_name, i, case, meaningful_data[well_name])
|
|
128
132
|
except KeyError:
|
|
129
133
|
logger.warning(f"Well '{well_name}' is written in case file but does not exist in schedule file.")
|
|
130
134
|
continue
|
|
131
|
-
compdat, welsegs, compsegs, bonus = create_output.format_output(well, case,
|
|
135
|
+
compdat, welsegs, compsegs, bonus = create_output.format_output(well, case, pdf)
|
|
132
136
|
for keyword in [Keywords.COMPLETION_SEGMENTS, Keywords.WELL_SEGMENTS, Keywords.COMPLETION_DATA]:
|
|
133
137
|
old_data = find_well_keyword_data(well_name, keyword, schedule)
|
|
134
138
|
if not old_data:
|
|
@@ -156,6 +160,8 @@ def create(
|
|
|
156
160
|
schedule = replace_preprocessing_names(schedule, case.mapper)
|
|
157
161
|
with open(new_file, "w", encoding="utf-8") as file:
|
|
158
162
|
file.write(schedule)
|
|
163
|
+
if pdf is not None:
|
|
164
|
+
pdf.close()
|
|
159
165
|
|
|
160
166
|
if err is not None:
|
|
161
167
|
raise err
|
completor/prepare_outputs.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import math
|
|
4
4
|
from collections.abc import MutableMapping
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
import numpy as np
|
|
@@ -1828,3 +1829,143 @@ def print_wsegdualrcp(df_wsegdualrcp: pd.DataFrame, well_number: int) -> str:
|
|
|
1828
1829
|
print_df = Keywords.AUTONOMOUS_INFLOW_CONTROL_DEVICE + "\n" + dataframe_tostring(print_df, True)
|
|
1829
1830
|
action += f"{print_df}\n/\nENDACTIO\n\n"
|
|
1830
1831
|
return action
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
def print_wsegdensity_pyaction(df_wsegdensity: pd.DataFrame) -> str:
|
|
1835
|
+
"""Create PYACTION code.
|
|
1836
|
+
|
|
1837
|
+
Args:
|
|
1838
|
+
df_wsegdensity: Output from function prepare_wsegdensity.
|
|
1839
|
+
|
|
1840
|
+
Returns:
|
|
1841
|
+
Final code output formatted in PYACTION.
|
|
1842
|
+
"""
|
|
1843
|
+
data_dict = df_wsegdensity.to_dict(orient="list")
|
|
1844
|
+
final_code = f"""
|
|
1845
|
+
import opm_embedded
|
|
1846
|
+
|
|
1847
|
+
ecl_state = opm_embedded.current_ecl_state
|
|
1848
|
+
schedule = opm_embedded.current_schedule
|
|
1849
|
+
report_step = opm_embedded.current_report_step
|
|
1850
|
+
summary_state = opm_embedded.current_summary_state
|
|
1851
|
+
|
|
1852
|
+
if 'setup_done' not in locals():
|
|
1853
|
+
execution_counter = dict()
|
|
1854
|
+
executed = False
|
|
1855
|
+
setup_done = True
|
|
1856
|
+
|
|
1857
|
+
data={data_dict}
|
|
1858
|
+
|
|
1859
|
+
for i in range(len(data["WELL"])):
|
|
1860
|
+
well_name = data["WELL"][i]
|
|
1861
|
+
segment_number = data["START_SEGMENT_NUMBER"][i]
|
|
1862
|
+
flow_coefficient = data["FLOW_COEFFICIENT"][i]
|
|
1863
|
+
oil_flow_area = data["OIL_FLOW_CROSS_SECTIONAL_AREA"][i]
|
|
1864
|
+
gas_flow_area = data["GAS_FLOW_CROSS_SECTIONAL_AREA"][i]
|
|
1865
|
+
water_flow_area = data["WATER_FLOW_CROSS_SECTIONAL_AREA"][i]
|
|
1866
|
+
max_flow_area = data["MAX_FLOW_CROSS_SECTIONAL_AREA"][i]
|
|
1867
|
+
water_low = data["WATER_HOLDUP_FRACTION_LOW_CUTOFF"][i]
|
|
1868
|
+
water_high = data["WATER_HOLDUP_FRACTION_HIGH_CUTOFF"][i]
|
|
1869
|
+
gas_low = data["GAS_HOLDUP_FRACTION_LOW_CUTOFF"][i]
|
|
1870
|
+
gas_high = data["GAS_HOLDUP_FRACTION_HIGH_CUTOFF"][i]
|
|
1871
|
+
defaults = data["DEFAULTS"][i]
|
|
1872
|
+
|
|
1873
|
+
swhf = summary_state[f"SWHF:{{well_name}}:{{segment_number}}"]
|
|
1874
|
+
sghf = summary_state[f"SGHF:{{well_name}}:{{segment_number}}"]
|
|
1875
|
+
suvtrig = summary_state[f"SUVTRIG:{{well_name}}:{{segment_number}}"]
|
|
1876
|
+
|
|
1877
|
+
keyword_oil = (
|
|
1878
|
+
f"WSEGVALV\\n"
|
|
1879
|
+
f" '{{well_name}}' {{segment_number}} {{flow_coefficient}} {{oil_flow_area}} {{defaults}} {{max_flow_area}} /\\n/"
|
|
1880
|
+
)
|
|
1881
|
+
keyword_water = (
|
|
1882
|
+
f"WSEGVALV\\n"
|
|
1883
|
+
f" '{{well_name}}' {{segment_number}} {{flow_coefficient}} {{water_flow_area}} {{defaults}} {{max_flow_area}} /\\n/"
|
|
1884
|
+
)
|
|
1885
|
+
keyword_gas = (
|
|
1886
|
+
f"WSEGVALV\\n"
|
|
1887
|
+
f" '{{well_name}}' {{segment_number}} {{flow_coefficient}} {{gas_flow_area}} {{defaults}} {{max_flow_area}} /\\n/"
|
|
1888
|
+
)
|
|
1889
|
+
|
|
1890
|
+
key = (well_name, segment_number)
|
|
1891
|
+
execution_counter.setdefault(key, 0)
|
|
1892
|
+
|
|
1893
|
+
if execution_counter[key] == 0:
|
|
1894
|
+
schedule.insert_keywords(keyword_oil, report_step)
|
|
1895
|
+
summary_state[f"SUVTRIG:{{well_name}}:{{segment_number}}"] = 0
|
|
1896
|
+
|
|
1897
|
+
if execution_counter[key] < 1000000:
|
|
1898
|
+
if swhf is not None and sghf is not None:
|
|
1899
|
+
if swhf <= water_high and sghf > gas_high and suvtrig == 0:
|
|
1900
|
+
schedule.insert_keywords(keyword_gas, report_step)
|
|
1901
|
+
summary_state[f"SUVTRIG:{{well_name}}:{{segment_number}}"] = 1
|
|
1902
|
+
execution_counter[key] += 1
|
|
1903
|
+
|
|
1904
|
+
elif swhf > water_high and sghf <= gas_high and suvtrig == 0:
|
|
1905
|
+
schedule.insert_keywords(keyword_water, report_step)
|
|
1906
|
+
summary_state[f"SUVTRIG:{{well_name}}:{{segment_number}}"] = 2
|
|
1907
|
+
execution_counter[key] += 1
|
|
1908
|
+
|
|
1909
|
+
elif sghf < gas_low and suvtrig == 1:
|
|
1910
|
+
schedule.insert_keywords(keyword_oil, report_step)
|
|
1911
|
+
summary_state[f"SUVTRIG:{{well_name}}:{{segment_number}}"] = 0
|
|
1912
|
+
execution_counter[key] += 1
|
|
1913
|
+
|
|
1914
|
+
elif swhf < water_low and suvtrig == 2:
|
|
1915
|
+
schedule.insert_keywords(keyword_oil, report_step)
|
|
1916
|
+
summary_state[f"SUVTRIG:{{well_name}}:{{segment_number}}"] = 0
|
|
1917
|
+
execution_counter[key] += 1
|
|
1918
|
+
"""
|
|
1919
|
+
return final_code
|
|
1920
|
+
|
|
1921
|
+
|
|
1922
|
+
def print_python_file(code: str, dir: str, well_name: str, lateral_number: int) -> str:
|
|
1923
|
+
"""Print Python PYACTION file.
|
|
1924
|
+
|
|
1925
|
+
Args:
|
|
1926
|
+
code: Final code output formatted in PYACTION.
|
|
1927
|
+
dir: Output path.
|
|
1928
|
+
well_name: Well name.
|
|
1929
|
+
lateral_number: Lateral number.
|
|
1930
|
+
|
|
1931
|
+
Returns:
|
|
1932
|
+
Python file with PYACTION format, output directory with FMU format.
|
|
1933
|
+
"""
|
|
1934
|
+
base_dir = Path.cwd() if Path(dir).parent == Path(".") else Path(dir).parent
|
|
1935
|
+
fmu_path = Path("eclipse/include/")
|
|
1936
|
+
if str(fmu_path) in str(base_dir):
|
|
1937
|
+
base_include_path = Path("../include/schedule")
|
|
1938
|
+
else:
|
|
1939
|
+
base_include_path = Path("")
|
|
1940
|
+
output_directory = f"{base_include_path}/wsegdensity_{well_name}_{lateral_number}.py"
|
|
1941
|
+
python_file = base_dir / f"wsegdensity_{well_name}_{lateral_number}.py"
|
|
1942
|
+
with open(python_file, "w") as file:
|
|
1943
|
+
file.writelines(code)
|
|
1944
|
+
return output_directory
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
def print_wsegdensity_include(output_directory: str, well_name: str, lateral_number: int) -> str:
|
|
1948
|
+
"""Formatted PYACTION include in the output file.
|
|
1949
|
+
|
|
1950
|
+
Args:
|
|
1951
|
+
output_directory: Include file path in FMU relative format.
|
|
1952
|
+
well_name: Well name.
|
|
1953
|
+
lateral_number: Lateral number.
|
|
1954
|
+
|
|
1955
|
+
Returns:
|
|
1956
|
+
Include file output for the output file.
|
|
1957
|
+
"""
|
|
1958
|
+
action = f"""
|
|
1959
|
+
-------------------------------------
|
|
1960
|
+
-- START OF PYACTION SECTION
|
|
1961
|
+
|
|
1962
|
+
PYACTION
|
|
1963
|
+
WSEGDENSITY_{well_name}_{lateral_number} UNLIMITED /
|
|
1964
|
+
|
|
1965
|
+
'{output_directory}' /
|
|
1966
|
+
|
|
1967
|
+
-- END OF PYACTION SECTION
|
|
1968
|
+
-------------------------------------
|
|
1969
|
+
"""
|
|
1970
|
+
|
|
1971
|
+
return action
|
completor/read_casefile.py
CHANGED
|
@@ -91,6 +91,7 @@ class ReadCasefile:
|
|
|
91
91
|
self.minimum_segment_length: float = 0.0
|
|
92
92
|
self.strict = True
|
|
93
93
|
self.gp_perf_devicelayer = False
|
|
94
|
+
self.python_dependent = False
|
|
94
95
|
self.schedule_file = schedule_file
|
|
95
96
|
self.output_file = output_file
|
|
96
97
|
self.completion_table = pd.DataFrame()
|
|
@@ -119,6 +120,7 @@ class ReadCasefile:
|
|
|
119
120
|
self.read_wsegvalv()
|
|
120
121
|
self.read_wsegsicd()
|
|
121
122
|
self.read_wsegdensity()
|
|
123
|
+
self.read_python_dependent()
|
|
122
124
|
self.read_wseginjv()
|
|
123
125
|
self.read_wsegdualrcp()
|
|
124
126
|
self.read_wsegicv()
|
|
@@ -555,6 +557,18 @@ class ReadCasefile:
|
|
|
555
557
|
if not check_contents(device_checks, self.wseginjv_table[Headers.DEVICE_NUMBER].to_numpy()):
|
|
556
558
|
raise CompletorError(f"Not all device in COMPLETION is specified in {Keywords.INJECTION_VALVE}")
|
|
557
559
|
|
|
560
|
+
def read_python_dependent(self) -> None:
|
|
561
|
+
"""Read PYTHON keyword. Accepts TRUE or just '/' as True."""
|
|
562
|
+
start_index, end_index = parse.locate_keyword(self.content, Keywords.PYTHON_DEPENDENT)
|
|
563
|
+
|
|
564
|
+
if end_index == start_index + 1:
|
|
565
|
+
# Keyword followed directly by '/', no value = True
|
|
566
|
+
self.python_dependent = True
|
|
567
|
+
elif end_index == start_index + 2:
|
|
568
|
+
val = self.content[start_index + 1]
|
|
569
|
+
if val.upper() == "TRUE":
|
|
570
|
+
self.python_dependent = True
|
|
571
|
+
|
|
558
572
|
def read_wsegdualrcp(self) -> None:
|
|
559
573
|
"""Read the DUALRCP keyword in the case file.
|
|
560
574
|
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: completor
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Advanced multi-segmented well completion tool.
|
|
5
5
|
Home-page: https://github.com/equinor/completor
|
|
6
6
|
License: LGPL-3.0-only
|
|
7
7
|
Author: Equinor ASA
|
|
8
8
|
Author-email: opensource@equinor.com
|
|
9
|
-
Requires-Python: >=3.11,<
|
|
9
|
+
Requires-Python: >=3.11,<3.14
|
|
10
10
|
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
|
|
11
11
|
Classifier: Natural Language :: English
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
17
|
Provides-Extra: ert
|
|
17
18
|
Provides-Extra: test
|
|
18
|
-
Requires-Dist: ert (>=
|
|
19
|
+
Requires-Dist: ert (>=14,<15) ; extra == "ert"
|
|
19
20
|
Requires-Dist: matplotlib (>=3.9,<4.0)
|
|
20
|
-
Requires-Dist: numpy (>=
|
|
21
|
+
Requires-Dist: numpy (>=2.0,<3.0)
|
|
21
22
|
Requires-Dist: pandas (>=2.2,<3.0)
|
|
22
23
|
Requires-Dist: pytest (>=8.3,<9.0) ; extra == "test"
|
|
23
24
|
Requires-Dist: pytest-env (>=1,<2) ; extra == "test"
|
|
24
25
|
Requires-Dist: pytest-xdist (>=3.6,<4.0) ; extra == "test"
|
|
25
26
|
Requires-Dist: rstcheck-core (>=1.2,<2.0) ; extra == "test"
|
|
26
|
-
Requires-Dist: scipy (>=1.14,<2.0)
|
|
27
27
|
Requires-Dist: tqdm (>=4.66,<5.0)
|
|
28
28
|
Project-URL: Bug Tracker, https://github.com/equinor/completor/issues
|
|
29
29
|
Project-URL: Documentation, https://equinor.github.io/completor
|
|
@@ -44,7 +44,7 @@ Detailed documentation for usage of completor can be found at https://equinor.gi
|
|
|
44
44
|
## Getting started as a user
|
|
45
45
|
|
|
46
46
|
### Prerequisites
|
|
47
|
-
* [Python](https://www.python.org/), version 3.11
|
|
47
|
+
* [Python](https://www.python.org/), version 3.11 or 3.13.
|
|
48
48
|
* [ERT](https://github.com/equinor/ert) (optional, and only available on Linux.)
|
|
49
49
|
|
|
50
50
|
### Installation
|
|
@@ -85,7 +85,7 @@ and making a pull request.
|
|
|
85
85
|
See [Contribution Document](documentation/docs/contribution_guide.mdx) on how to contribute.
|
|
86
86
|
|
|
87
87
|
### Install completor as dev
|
|
88
|
-
In order to run Completor® you need to have versions of [Python 3.11](https://www.python.org/downloads/) installed.
|
|
88
|
+
In order to run Completor® you need to have versions of [Python 3.11, 3.12 or 3.13](https://www.python.org/downloads/) installed.
|
|
89
89
|
#### Source code
|
|
90
90
|
Clone the [Completor® repository](https://github.com/equinor/completor) to get the source code.
|
|
91
91
|
```bash
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
completor/__init__.py,sha256=k6amf7jhp7KkBIlaw93-NZITxyZjPSzA5McFAZh8yv8,76
|
|
2
2
|
completor/completion.py,sha256=quhQOdQREv8MsHW5amT0sG-84Y12KVdT0eylbKCul3g,31177
|
|
3
3
|
completor/config_jobs/run_completor,sha256=XePKj2xocfGF0XFRqr7sqfpZGrjgWcfaZLHIhVvGFCQ,600
|
|
4
|
-
completor/constants.py,sha256=
|
|
5
|
-
completor/create_output.py,sha256=
|
|
4
|
+
completor/constants.py,sha256=2e1o5Env5lHyhopkrs_C__9DksS5xml1-Ea_X3cLl0E,13521
|
|
5
|
+
completor/create_output.py,sha256=6ygglcCUYYII5sWr_ey4cvUCCsXb0UGqXY5GQAzX8fQ,25969
|
|
6
6
|
completor/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
completor/exceptions/clean_exceptions.py,sha256=uQ2jgGfvUDAoS56JBWh-8ZCPIMB4hvYxLF-snA-_-pg,373
|
|
8
8
|
completor/exceptions/exceptions.py,sha256=eS00mVzmC4gQ7MUyGSknvKotmo2XzNGyp007mhjLMy0,5081
|
|
@@ -11,17 +11,17 @@ completor/hook_implementations/jobs.py,sha256=8Ao8UadfJzEY7jWzj6C_OXm18fHmfXrbCB
|
|
|
11
11
|
completor/input_validation.py,sha256=F17AWi-qR6cX5_1lEFgtYOMOO0Xo3gTtL2ETM5P_uGE,15022
|
|
12
12
|
completor/launch_args_parser.py,sha256=gb3FcyufZlRnKS3BZkFmgVH1VoSxMD0MbCLsHZKmz4c,1413
|
|
13
13
|
completor/logger.py,sha256=gYDbPL8ca5qT_MqYlDKEMKcSfIXW_59QklX8Gss5b2U,4784
|
|
14
|
-
completor/main.py,sha256=
|
|
14
|
+
completor/main.py,sha256=HlQzv5gpBYdDbYTBLSkAnK7o6d2QfTQnjrNizq3Ym6s,9343
|
|
15
15
|
completor/parse.py,sha256=EGlt9CgkrXPqa7woyWQ5t_nh6OWsFrc2SJr8aFr_KsQ,20133
|
|
16
|
-
completor/prepare_outputs.py,sha256=
|
|
17
|
-
completor/read_casefile.py,sha256=
|
|
16
|
+
completor/prepare_outputs.py,sha256=o-7SLD0F5jiw5_lnq5kewB1tYOiLa0u2TxGz6kRIO-8,87613
|
|
17
|
+
completor/read_casefile.py,sha256=NebZRrO35aqrZIJ7eHcS6buBbAaDWw8wUtc4kBHsV2U,38184
|
|
18
18
|
completor/read_schedule.py,sha256=IYyCubOggFGg664h1flTl7MUJhJWyibr6JsptnURjUA,18101
|
|
19
19
|
completor/utils.py,sha256=9Qayt7xMsimpoVDo5sL86gVaQBbIOezMBRyMXd3haXw,13598
|
|
20
20
|
completor/visualization.py,sha256=ObxThqIyW3fsvVIupxVsgySFI_54n_Di-HTzFtDMSgo,4580
|
|
21
21
|
completor/visualize_well.py,sha256=HLglSN2ce-u9nklJelqwhSxwwaj7n-aU6o8lUScbiI0,8790
|
|
22
22
|
completor/wells.py,sha256=Q2detK0FxIBgusYkCRmomRIfcScBNvNTYX43GFyAHGw,12246
|
|
23
|
-
completor-1.
|
|
24
|
-
completor-1.
|
|
25
|
-
completor-1.
|
|
26
|
-
completor-1.
|
|
27
|
-
completor-1.
|
|
23
|
+
completor-1.3.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
24
|
+
completor-1.3.0.dist-info/METADATA,sha256=IL5-ncKANt09P_kbEZeJu0DV3YpjAS4RiFtCThhHBKM,8018
|
|
25
|
+
completor-1.3.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
26
|
+
completor-1.3.0.dist-info/entry_points.txt,sha256=co5L2_CC2QQWVdEALeMp-NIC4mx4nRpcLcvpVXMYdeI,106
|
|
27
|
+
completor-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|