completor 1.1.3__py3-none-any.whl → 1.2.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/completion.py +5 -1
- completor/constants.py +14 -1
- completor/create_output.py +28 -0
- completor/input_validation.py +20 -1
- completor/prepare_outputs.py +222 -10
- completor/read_casefile.py +45 -4
- completor/utils.py +1 -0
- completor/visualize_well.py +2 -0
- completor/wells.py +2 -0
- {completor-1.1.3.dist-info → completor-1.2.0.dist-info}/METADATA +1 -1
- {completor-1.1.3.dist-info → completor-1.2.0.dist-info}/RECORD +14 -14
- {completor-1.1.3.dist-info → completor-1.2.0.dist-info}/LICENSE +0 -0
- {completor-1.1.3.dist-info → completor-1.2.0.dist-info}/WHEEL +0 -0
- {completor-1.1.3.dist-info → completor-1.2.0.dist-info}/entry_points.txt +0 -0
completor/completion.py
CHANGED
|
@@ -551,7 +551,7 @@ def get_device(df_well: pd.DataFrame, df_device: pd.DataFrame, device_type: str)
|
|
|
551
551
|
Args:
|
|
552
552
|
df_well: Must contain device type, device number, and the scaling factor.
|
|
553
553
|
df_device: Device table.
|
|
554
|
-
device_type: Device type. `AICD`, `ICD`, `DENSITY`, `VALVE`, `DUALRCP`, `ICV`.
|
|
554
|
+
device_type: Device type. `AICD`, `ICD`, `DENSITY`, `VALVE`, `DUALRCP`, `ICV`, `INJV`.
|
|
555
555
|
|
|
556
556
|
Returns:
|
|
557
557
|
Updated well information with device characteristics.
|
|
@@ -581,6 +581,10 @@ def get_device(df_well: pd.DataFrame, df_device: pd.DataFrame, device_type: str)
|
|
|
581
581
|
# rescale the Cv
|
|
582
582
|
# because no scaling factor in WELL_SEGMENTS_VALVE
|
|
583
583
|
df_well[Headers.FLOW_COEFFICIENT] = -df_well[Headers.FLOW_COEFFICIENT] / df_well[Headers.SCALE_FACTOR]
|
|
584
|
+
elif device_type == Content.INJECTION_VALVE:
|
|
585
|
+
# rescale the Cv
|
|
586
|
+
# because no scaling factor in WELL_SEGMENTS_VALVE
|
|
587
|
+
df_well[Headers.FLOW_COEFFICIENT] = -df_well[Headers.FLOW_COEFFICIENT] / df_well[Headers.SCALE_FACTOR]
|
|
584
588
|
return df_well
|
|
585
589
|
|
|
586
590
|
|
completor/constants.py
CHANGED
|
@@ -78,7 +78,7 @@ class _Headers:
|
|
|
78
78
|
DR = "DR"
|
|
79
79
|
FLAG = "FLAG" # This is actually a header, but OPEN, SHUT, and AUTO are its possible values, see manual on COMPLETION_DATA.
|
|
80
80
|
SHUT = "SHUT"
|
|
81
|
-
|
|
81
|
+
CROSS = "CROSS"
|
|
82
82
|
PRESSURE_TABLE = "PRESSURETABLE"
|
|
83
83
|
DENSITY_CALCULATION_TYPE = "DENSCAL" # Type of density calculation for the wellbore hydrostatic head.
|
|
84
84
|
REGION = "REGION"
|
|
@@ -126,6 +126,7 @@ class _Headers:
|
|
|
126
126
|
# This stops making sense from here on out?
|
|
127
127
|
X = "X"
|
|
128
128
|
Y = "Y"
|
|
129
|
+
Z = "Z"
|
|
129
130
|
# FLAG
|
|
130
131
|
A = "A"
|
|
131
132
|
B = "B"
|
|
@@ -165,6 +166,15 @@ class _Headers:
|
|
|
165
166
|
GAS_HOLDUP_FRACTION_LOW_CUTOFF = "GAS_HOLDUP_FRACTION_LOW_CUTOFF"
|
|
166
167
|
GAS_HOLDUP_FRACTION_HIGH_CUTOFF = "GAS_HOLDUP_FRACTION_HIGH_CUTOFF"
|
|
167
168
|
|
|
169
|
+
# Injection Valve Well Segments (WSEGINJV)
|
|
170
|
+
# DEVICE_NUMBER
|
|
171
|
+
TRIGGER_PARAMETER = "TRIGGER_PARAMETER"
|
|
172
|
+
TRIGGER_VALUE = "TRIGGER_VALUE"
|
|
173
|
+
# FLOW_COEFFICIENT / Cv
|
|
174
|
+
# FLOW_CROSS_SECTIONAL_AREA
|
|
175
|
+
PRIMARY_FLOW_CROSS_SECTIONAL_AREA = "PRIMARY_FLOW_CROSS_SECTIONAL_AREA"
|
|
176
|
+
SECONDARY_FLOW_CROSS_SECTIONAL_AREA = "SECONDARY_FLOW_CROSS_SECTIONAL_AREA"
|
|
177
|
+
|
|
168
178
|
# Miscellaneous
|
|
169
179
|
DEFAULTS = "DEFAULTS"
|
|
170
180
|
MEASURED_DEPTH = "MEASURED_DEPTH"
|
|
@@ -245,6 +255,7 @@ class _Keywords:
|
|
|
245
255
|
INFLOW_CONTROL_DEVICE = "WSEGSICD"
|
|
246
256
|
DENSITY = "WSEGDENSITY"
|
|
247
257
|
DENSITY_ACTIVATED_RECOVERY = "WSEGDAR"
|
|
258
|
+
INJECTION_VALVE = "WSEGINJV"
|
|
248
259
|
LATERAL_TO_DEVICE = "LATERAL_TO_DEVICE"
|
|
249
260
|
JOINT_LENGTH = "JOINTLENGTH"
|
|
250
261
|
SEGMENT_LENGTH = "SEGMENTLENGTH"
|
|
@@ -290,6 +301,7 @@ class _Content:
|
|
|
290
301
|
AUTONOMOUS_INFLOW_CONTROL_DEVICE = "AICD"
|
|
291
302
|
DENSITY = "DENSITY"
|
|
292
303
|
DENSITY_ACTIVATED_RECOVERY = "DAR"
|
|
304
|
+
INJECTION_VALVE = "INJV"
|
|
293
305
|
VALVE = "VALVE"
|
|
294
306
|
DEVICE_TYPES = [
|
|
295
307
|
AUTONOMOUS_INFLOW_CONTROL_DEVICE,
|
|
@@ -297,6 +309,7 @@ class _Content:
|
|
|
297
309
|
AUTONOMOUS_INFLOW_CONTROL_VALVE,
|
|
298
310
|
DENSITY,
|
|
299
311
|
DENSITY_ACTIVATED_RECOVERY,
|
|
312
|
+
INJECTION_VALVE,
|
|
300
313
|
INFLOW_CONTROL_DEVICE,
|
|
301
314
|
VALVE,
|
|
302
315
|
INFLOW_CONTROL_VALVE,
|
completor/create_output.py
CHANGED
|
@@ -41,6 +41,7 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
41
41
|
print_autonomous_inflow_control_device = ""
|
|
42
42
|
print_inflow_control_device = ""
|
|
43
43
|
print_density_driven = ""
|
|
44
|
+
print_injection_valve = ""
|
|
44
45
|
print_dual_rate_controlled_production = ""
|
|
45
46
|
|
|
46
47
|
start_segment = 2
|
|
@@ -111,6 +112,7 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
111
112
|
well.well_name, lateral.df_well, lateral.df_device
|
|
112
113
|
)
|
|
113
114
|
df_density_driven = prepare_outputs.prepare_density_driven(well.well_name, lateral.df_well, lateral.df_device)
|
|
115
|
+
df_injection_valve = prepare_outputs.prepare_injection_valve(well.well_name, lateral.df_well, lateral.df_device)
|
|
114
116
|
df_dual_rate_controlled_production = prepare_outputs.prepare_dual_rate_controlled_production(
|
|
115
117
|
well.well_name, lateral.df_well, lateral.df_device
|
|
116
118
|
)
|
|
@@ -146,6 +148,7 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
146
148
|
well.well_name, lateral.lateral_number, df_inflow_control_valve, first
|
|
147
149
|
)
|
|
148
150
|
print_density_driven += _format_density_driven(well.well_number, df_density_driven)
|
|
151
|
+
print_injection_valve += _format_injection_valve(well.well_number, df_injection_valve)
|
|
149
152
|
print_dual_rate_controlled_production += _format_dual_rate_controlled_production(
|
|
150
153
|
well.well_number, df_dual_rate_controlled_production
|
|
151
154
|
)
|
|
@@ -191,6 +194,16 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
|
|
|
191
194
|
f"{'-' * 100}\n\n\n"
|
|
192
195
|
)
|
|
193
196
|
bonus.append(metadata + print_density_driven + "\n\n\n\n")
|
|
197
|
+
if print_injection_valve:
|
|
198
|
+
metadata = (
|
|
199
|
+
f"{'-' * 100}\n"
|
|
200
|
+
"-- This is how we model INJV technology using sets of ACTIONX keywords.\n"
|
|
201
|
+
"-- The DP paramaters changes according to the trigger parameter.-\n"
|
|
202
|
+
"-- The value of Cv is adjusted according to the segment length and the number of\n"
|
|
203
|
+
"-- devices per joint. The constriction area will change if the parameter is triggered.\n"
|
|
204
|
+
f"{'-' * 100}\n\n\n"
|
|
205
|
+
)
|
|
206
|
+
bonus.append(metadata + print_injection_valve + "\n\n\n\n")
|
|
194
207
|
if print_dual_rate_controlled_production:
|
|
195
208
|
metadata = (
|
|
196
209
|
f"{'-' * 100}\n"
|
|
@@ -450,6 +463,21 @@ def _format_density_driven(well_number: int, df_wsegdensity: pd.DataFrame) -> st
|
|
|
450
463
|
return prepare_outputs.print_wsegdensity(df_wsegdensity, well_number + 1)
|
|
451
464
|
|
|
452
465
|
|
|
466
|
+
def _format_injection_valve(well_number: int, df_wseginjv: pd.DataFrame) -> str:
|
|
467
|
+
"""Formats well-segments for injection valve.
|
|
468
|
+
|
|
469
|
+
Args:
|
|
470
|
+
well_number: The well's number
|
|
471
|
+
df_wsegdinjv: Data to print.
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
Formatted string.
|
|
475
|
+
"""
|
|
476
|
+
if df_wseginjv.empty:
|
|
477
|
+
return ""
|
|
478
|
+
return prepare_outputs.print_wseginjv(df_wseginjv, well_number + 1)
|
|
479
|
+
|
|
480
|
+
|
|
453
481
|
def _format_dual_rate_controlled_production(well_number: int, df_wsegdualrcp: pd.DataFrame) -> str:
|
|
454
482
|
"""Formats the DUALRCP section.
|
|
455
483
|
|
completor/input_validation.py
CHANGED
|
@@ -173,7 +173,7 @@ def _check_for_errors(df_comp: pd.DataFrame, well_name: str, idx: int) -> None:
|
|
|
173
173
|
if df_comp[Headers.DEVICE_TYPE].iloc[idx] not in Content.DEVICE_TYPES:
|
|
174
174
|
raise CompletorError(
|
|
175
175
|
f"{df_comp[Headers.DEVICE_TYPE].iloc[idx]} is not a valid device type. "
|
|
176
|
-
"Valid types are PERF, AICD, ICD, VALVE, DENSITY, DUALRCP, and ICV."
|
|
176
|
+
"Valid types are PERF, AICD, ICD, VALVE, DENSITY, INJV, DUALRCP, and ICV."
|
|
177
177
|
)
|
|
178
178
|
if df_comp[Headers.ANNULUS].iloc[idx] not in Content.ANNULUS_TYPES:
|
|
179
179
|
raise CompletorError(
|
|
@@ -290,6 +290,25 @@ def set_format_wsegdensity(df_temp: pd.DataFrame) -> pd.DataFrame:
|
|
|
290
290
|
return df_temp
|
|
291
291
|
|
|
292
292
|
|
|
293
|
+
def set_format_wseginjv(df_temp: pd.DataFrame) -> pd.DataFrame:
|
|
294
|
+
"""Format the well segments Injection Valve (INJV) data.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
df_temp: Well segments INJV device data.
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Updated data.
|
|
301
|
+
"""
|
|
302
|
+
df_temp[Headers.DEVICE_NUMBER] = df_temp[Headers.DEVICE_NUMBER].astype(np.int64)
|
|
303
|
+
# left out devicenumber and trigger parameter because devicenumber has been formatted as integer
|
|
304
|
+
# trigger parameter is a string
|
|
305
|
+
columns = df_temp.columns.to_numpy()[2:]
|
|
306
|
+
df_temp[columns] = df_temp[columns].astype(np.float64)
|
|
307
|
+
# Create ID device column
|
|
308
|
+
df_temp.insert(0, Headers.DEVICE_TYPE, np.full(df_temp.shape[0], Content.INJECTION_VALVE))
|
|
309
|
+
return df_temp
|
|
310
|
+
|
|
311
|
+
|
|
293
312
|
def set_format_wsegdualrcp(df_temp: pd.DataFrame) -> pd.DataFrame:
|
|
294
313
|
"""Format the well segments Dual RCP (DUALRCP) table.
|
|
295
314
|
|
completor/prepare_outputs.py
CHANGED
|
@@ -120,6 +120,7 @@ def dataframe_tostring(
|
|
|
120
120
|
"END_MD": "{:.3f}".format,
|
|
121
121
|
Headers.FLOW_COEFFICIENT: "{:.10g}".format,
|
|
122
122
|
"CV": "{:.10g}".format,
|
|
123
|
+
Headers.CROSS: "{:.3e}".format,
|
|
123
124
|
Headers.FLOW_CROSS_SECTIONAL_AREA: "{:.3e}".format,
|
|
124
125
|
"FLOW_CROSS_SECTIONAL_AREA": "{:.3e}".format,
|
|
125
126
|
Headers.OIL_FLOW_CROSS_SECTIONAL_AREA: "{:.3e}".format,
|
|
@@ -135,6 +136,13 @@ def dataframe_tostring(
|
|
|
135
136
|
Headers.ALPHA_PILOT: "{:.10g}".format,
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
# Cast floats to str befor headers are messed up (pandas formatter does not work reliably with MultiIndex headers).
|
|
140
|
+
for column, formatter in formatters.items():
|
|
141
|
+
try:
|
|
142
|
+
df_temp[column] = df_temp[column].map(formatter)
|
|
143
|
+
except (KeyError, ValueError):
|
|
144
|
+
pass
|
|
145
|
+
|
|
138
146
|
if header:
|
|
139
147
|
# Modify headers to reduce width.
|
|
140
148
|
column_splits = [tuple(column.split("_")) for column in df_temp.columns]
|
|
@@ -173,9 +181,7 @@ def dataframe_tostring(
|
|
|
173
181
|
df_temp.columns = pd.MultiIndex.from_frame(new_cols)
|
|
174
182
|
|
|
175
183
|
try:
|
|
176
|
-
output_string = df_temp.to_string(
|
|
177
|
-
index=False, justify="justify", formatters=formatters, header=header, sparsify=False
|
|
178
|
-
)
|
|
184
|
+
output_string = df_temp.to_string(index=False, justify="justify", header=header, sparsify=False)
|
|
179
185
|
except ValueError:
|
|
180
186
|
if df_temp.isnull().values.any():
|
|
181
187
|
raise CompletorError("Got NaN values in table, please report if encountered!")
|
|
@@ -184,18 +190,14 @@ def dataframe_tostring(
|
|
|
184
190
|
df_temp = df_temp.replace("1*", np.nan, inplace=False)
|
|
185
191
|
# Probably find columns where this is the case and cast to numeric after replacing with nan?
|
|
186
192
|
df_temp[columns_with_1_star] = df_temp[columns_with_1_star].astype(np.float64, errors="ignore")
|
|
187
|
-
output_string = df_temp.to_string(
|
|
188
|
-
index=False, justify="justify", formatters=formatters, header=header, sparsify=False, na_rep="1*"
|
|
189
|
-
)
|
|
193
|
+
output_string = df_temp.to_string(index=False, justify="justify", header=header, sparsify=False, na_rep="1*")
|
|
190
194
|
|
|
191
195
|
if output_string is None:
|
|
192
196
|
return ""
|
|
193
197
|
|
|
194
198
|
too_long_lines = check_width_lines(output_string, limit)
|
|
195
199
|
if too_long_lines:
|
|
196
|
-
output_string = df_temp.to_string(
|
|
197
|
-
index=False, justify="left", formatters=formatters, header=header, sparsify=False
|
|
198
|
-
)
|
|
200
|
+
output_string = df_temp.to_string(index=False, justify="left", header=header, sparsify=False)
|
|
199
201
|
if output_string is None:
|
|
200
202
|
return ""
|
|
201
203
|
too_long_lines2 = check_width_lines(output_string, limit)
|
|
@@ -454,7 +456,11 @@ def prepare_device_layer(df_well: pd.DataFrame, df_tubing: pd.DataFrame, device_
|
|
|
454
456
|
df_well[Headers.DEVICE_TYPE] == Content.DUAL_RATE_CONTROLLED_PRODUCTION,
|
|
455
457
|
"/ -- DUALRCP types",
|
|
456
458
|
np.where(
|
|
457
|
-
df_well[Headers.DEVICE_TYPE] == Content.
|
|
459
|
+
df_well[Headers.DEVICE_TYPE] == Content.INJECTION_VALVE,
|
|
460
|
+
"/ -- INJV types",
|
|
461
|
+
np.where(
|
|
462
|
+
df_well[Headers.DEVICE_TYPE] == Content.INFLOW_CONTROL_VALVE, "/ -- ICV types", ""
|
|
463
|
+
),
|
|
458
464
|
),
|
|
459
465
|
),
|
|
460
466
|
),
|
|
@@ -1068,6 +1074,8 @@ def prepare_autonomous_inflow_control_device(
|
|
|
1068
1074
|
wsegaicd[Headers.D] = df_merge[Headers.D].to_numpy()
|
|
1069
1075
|
wsegaicd[Headers.E] = df_merge[Headers.E].to_numpy()
|
|
1070
1076
|
wsegaicd[Headers.F] = df_merge[Headers.F].to_numpy()
|
|
1077
|
+
if Headers.Z in df_merge.columns:
|
|
1078
|
+
wsegaicd[Headers.Z] = df_merge[Headers.Z].to_numpy()
|
|
1071
1079
|
wsegaicd[Headers.EMPTY] = "/"
|
|
1072
1080
|
return wsegaicd
|
|
1073
1081
|
|
|
@@ -1303,6 +1311,48 @@ def prepare_density_driven(well_name: str, df_well: pd.DataFrame, df_device: pd.
|
|
|
1303
1311
|
return wsegdensity
|
|
1304
1312
|
|
|
1305
1313
|
|
|
1314
|
+
def prepare_injection_valve(well_name: str, df_well: pd.DataFrame, df_device: pd.DataFrame) -> pd.DataFrame:
|
|
1315
|
+
"""Prepare data frame for INJECTION VALVE.
|
|
1316
|
+
|
|
1317
|
+
Args:
|
|
1318
|
+
well_name: Well name.
|
|
1319
|
+
df_well: Well data.
|
|
1320
|
+
df_device: Device data for this well and lateral.
|
|
1321
|
+
|
|
1322
|
+
Returns:
|
|
1323
|
+
DataFrame for INJECTION VALVE.
|
|
1324
|
+
"""
|
|
1325
|
+
df_well = df_well[(df_well[Headers.DEVICE_TYPE] == Content.PERFORATED) | (df_well[Headers.NUMBER_OF_DEVICES] > 0)]
|
|
1326
|
+
if df_well.shape[0] == 0:
|
|
1327
|
+
return pd.DataFrame()
|
|
1328
|
+
df_merge = pd.merge_asof(
|
|
1329
|
+
left=df_device,
|
|
1330
|
+
right=df_well,
|
|
1331
|
+
left_on=[Headers.MEASURED_DEPTH],
|
|
1332
|
+
right_on=[Headers.TUBING_MEASURED_DEPTH],
|
|
1333
|
+
direction="nearest",
|
|
1334
|
+
)
|
|
1335
|
+
df_merge = df_merge[df_merge[Headers.DEVICE_TYPE] == Content.INJECTION_VALVE]
|
|
1336
|
+
wseginjv = pd.DataFrame()
|
|
1337
|
+
if df_merge.shape[0] > 0:
|
|
1338
|
+
wseginjv[Headers.WELL] = [well_name] * df_merge.shape[0]
|
|
1339
|
+
wseginjv[Headers.START_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
|
|
1340
|
+
# the Cv is already corrected by the scaling factor
|
|
1341
|
+
wseginjv[Headers.FLOW_COEFFICIENT] = df_merge[Headers.FLOW_COEFFICIENT].to_numpy()
|
|
1342
|
+
wseginjv[Headers.PRIMARY_FLOW_CROSS_SECTIONAL_AREA] = df_merge[
|
|
1343
|
+
Headers.PRIMARY_FLOW_CROSS_SECTIONAL_AREA
|
|
1344
|
+
].to_numpy()
|
|
1345
|
+
wseginjv[Headers.SECONDARY_FLOW_CROSS_SECTIONAL_AREA] = df_merge[
|
|
1346
|
+
Headers.SECONDARY_FLOW_CROSS_SECTIONAL_AREA
|
|
1347
|
+
].to_numpy()
|
|
1348
|
+
wseginjv[Headers.TRIGGER_PARAMETER] = df_merge[Headers.TRIGGER_PARAMETER].to_numpy()
|
|
1349
|
+
wseginjv[Headers.TRIGGER_VALUE] = df_merge[Headers.TRIGGER_VALUE].to_numpy()
|
|
1350
|
+
wseginjv[Headers.DEFAULTS] = "5*"
|
|
1351
|
+
wseginjv[Headers.MAX_FLOW_CROSS_SECTIONAL_AREA] = wseginjv[Headers.PRIMARY_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
|
|
1352
|
+
wseginjv[Headers.EMPTY] = "/"
|
|
1353
|
+
return wseginjv
|
|
1354
|
+
|
|
1355
|
+
|
|
1306
1356
|
def prepare_dual_rate_controlled_production(
|
|
1307
1357
|
well_name: str, df_well: pd.DataFrame, df_device: pd.DataFrame
|
|
1308
1358
|
) -> pd.DataFrame:
|
|
@@ -1513,6 +1563,168 @@ def print_wsegdensity(df_wsegdensity: pd.DataFrame, well_number: int) -> str:
|
|
|
1513
1563
|
return action
|
|
1514
1564
|
|
|
1515
1565
|
|
|
1566
|
+
def print_wseginjv(df_wseginjv: pd.DataFrame, well_number: int) -> str:
|
|
1567
|
+
"""Print INJECTION VALVE devices.
|
|
1568
|
+
|
|
1569
|
+
Args:
|
|
1570
|
+
df_wseginjv: Output from function prepare_wseginjv.
|
|
1571
|
+
well_number: Well number.
|
|
1572
|
+
|
|
1573
|
+
Returns:
|
|
1574
|
+
Formatted actions to be included in the output file.
|
|
1575
|
+
|
|
1576
|
+
Raises:
|
|
1577
|
+
CompletorError: If there are to many wells and/or segments with INJECTION VALVE.
|
|
1578
|
+
"""
|
|
1579
|
+
header = [
|
|
1580
|
+
[
|
|
1581
|
+
Headers.WELL,
|
|
1582
|
+
Headers.START_SEGMENT_NUMBER,
|
|
1583
|
+
Headers.FLOW_COEFFICIENT,
|
|
1584
|
+
Headers.SECONDARY_FLOW_CROSS_SECTIONAL_AREA,
|
|
1585
|
+
Headers.DEFAULTS,
|
|
1586
|
+
Headers.MAX_FLOW_CROSS_SECTIONAL_AREA,
|
|
1587
|
+
],
|
|
1588
|
+
[
|
|
1589
|
+
Headers.WELL,
|
|
1590
|
+
Headers.START_SEGMENT_NUMBER,
|
|
1591
|
+
Headers.FLOW_COEFFICIENT,
|
|
1592
|
+
Headers.PRIMARY_FLOW_CROSS_SECTIONAL_AREA,
|
|
1593
|
+
Headers.DEFAULTS,
|
|
1594
|
+
Headers.MAX_FLOW_CROSS_SECTIONAL_AREA,
|
|
1595
|
+
],
|
|
1596
|
+
]
|
|
1597
|
+
|
|
1598
|
+
sign = ["<", ">="]
|
|
1599
|
+
suvtrig = ["0", "1"]
|
|
1600
|
+
action = "UDQ\n"
|
|
1601
|
+
for idx in range(df_wseginjv.shape[0]):
|
|
1602
|
+
segment_number = df_wseginjv[Headers.START_SEGMENT_NUMBER].iloc[idx]
|
|
1603
|
+
well_name = df_wseginjv[Headers.WELL].iloc[idx]
|
|
1604
|
+
action += f" ASSIGN SUVTRIG {well_name} {segment_number} 0 /\n"
|
|
1605
|
+
action += "/\n\n"
|
|
1606
|
+
iaction = 1
|
|
1607
|
+
action += Keywords.WELL_SEGMENTS_VALVE + "\n"
|
|
1608
|
+
header_string = "--"
|
|
1609
|
+
for itm in header[iaction]:
|
|
1610
|
+
header_string += " " + itm
|
|
1611
|
+
action += header_string.rstrip() + "\n"
|
|
1612
|
+
for idx in range(df_wseginjv.shape[0]):
|
|
1613
|
+
segment_number = df_wseginjv[Headers.START_SEGMENT_NUMBER].iloc[idx]
|
|
1614
|
+
print_df = df_wseginjv[df_wseginjv[Headers.START_SEGMENT_NUMBER] == segment_number]
|
|
1615
|
+
print_df = print_df[header[iaction]]
|
|
1616
|
+
print_df = dataframe_tostring(print_df, True, False, False) + "\n"
|
|
1617
|
+
action += print_df
|
|
1618
|
+
action += "/\n\n"
|
|
1619
|
+
for idx in range(df_wseginjv.shape[0]):
|
|
1620
|
+
segment_number = df_wseginjv[Headers.START_SEGMENT_NUMBER].iloc[idx]
|
|
1621
|
+
well_name = df_wseginjv[Headers.WELL].iloc[idx]
|
|
1622
|
+
# Trigger paramater is segment water rate
|
|
1623
|
+
if df_wseginjv[Headers.TRIGGER_PARAMETER].iloc[idx] == "SWFR":
|
|
1624
|
+
water_segment_rate_cutoff = -1 * df_wseginjv[Headers.TRIGGER_VALUE].iloc[idx]
|
|
1625
|
+
iaction = 0
|
|
1626
|
+
act_number = iaction + 1
|
|
1627
|
+
act_name = f"INJVOP{well_number:03d}{segment_number:03d}{act_number:1d}"
|
|
1628
|
+
if len(act_name) > 13:
|
|
1629
|
+
raise CompletorError("Too many wells and/or too many segments with Injection Valve")
|
|
1630
|
+
action += (
|
|
1631
|
+
f"ACTIONX\n{act_name} 1000000 /\n"
|
|
1632
|
+
f"SWFR '{well_name}' {segment_number} "
|
|
1633
|
+
f"{sign[iaction]} {water_segment_rate_cutoff} AND /\n"
|
|
1634
|
+
f"SUVTRIG '{well_name}' {segment_number} "
|
|
1635
|
+
f"= {suvtrig[iaction]} /\n/\n\n"
|
|
1636
|
+
)
|
|
1637
|
+
print_df = df_wseginjv[df_wseginjv[Headers.START_SEGMENT_NUMBER] == segment_number]
|
|
1638
|
+
print_df = print_df[header[iaction]] # type: ignore
|
|
1639
|
+
header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
|
|
1640
|
+
|
|
1641
|
+
for item in header[iaction]:
|
|
1642
|
+
header_string += " " + item
|
|
1643
|
+
header_string = header_string.rstrip() + "\n"
|
|
1644
|
+
print_df = header_string + dataframe_tostring(print_df, True, False, False) # type: ignore
|
|
1645
|
+
print_df += "\n/\n"
|
|
1646
|
+
print_df += f"\nUDQ\n ASSIGN SUVTRIG {well_name} {segment_number} 1 /\n/\n"
|
|
1647
|
+
action += print_df + "\nENDACTIO\n\n"
|
|
1648
|
+
|
|
1649
|
+
iaction = 1
|
|
1650
|
+
act_number = iaction + 1
|
|
1651
|
+
act_name = f"INJVCL{well_number:03d}{segment_number:03d}{act_number:1d}"
|
|
1652
|
+
if len(act_name) > 13:
|
|
1653
|
+
raise CompletorError("Too many wells and/or too many segments with Injection Valve")
|
|
1654
|
+
action += (
|
|
1655
|
+
f"ACTIONX\n{act_name} 1000000 /\n"
|
|
1656
|
+
f"SWFR '{well_name}' {segment_number} "
|
|
1657
|
+
f"{sign[iaction]} {water_segment_rate_cutoff} AND /\n"
|
|
1658
|
+
f"SUVTRIG '{well_name}' {segment_number} "
|
|
1659
|
+
f"= {suvtrig[iaction]} /\n/\n\n"
|
|
1660
|
+
)
|
|
1661
|
+
print_df = df_wseginjv[df_wseginjv[Headers.START_SEGMENT_NUMBER] == segment_number]
|
|
1662
|
+
print_df = print_df[header[iaction]] # type: ignore
|
|
1663
|
+
header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
|
|
1664
|
+
|
|
1665
|
+
for item in header[iaction]:
|
|
1666
|
+
header_string += " " + item
|
|
1667
|
+
header_string = header_string.rstrip() + "\n"
|
|
1668
|
+
print_df = header_string + dataframe_tostring(print_df, True, False, False) # type: ignore
|
|
1669
|
+
print_df += "\n/\n"
|
|
1670
|
+
print_df += f"\nUDQ\n ASSIGN SUVTRIG {well_name} {segment_number} 0 /\n/\n"
|
|
1671
|
+
action += print_df + "\nENDACTIO\n\n"
|
|
1672
|
+
|
|
1673
|
+
# Trigger parameter is segment pressure drop
|
|
1674
|
+
elif df_wseginjv[Headers.TRIGGER_PARAMETER].iloc[idx] == "SPRD":
|
|
1675
|
+
pressure_drop_cutoff = -1 * df_wseginjv[Headers.TRIGGER_VALUE].iloc[idx]
|
|
1676
|
+
iaction = 0
|
|
1677
|
+
act_number = iaction + 1
|
|
1678
|
+
act_name = f"INJVOP{well_number:03d}{segment_number:03d}{act_number:1d}"
|
|
1679
|
+
if len(act_name) > 13:
|
|
1680
|
+
raise CompletorError("Too many wells and/or too many segments with Injection Valve")
|
|
1681
|
+
action += (
|
|
1682
|
+
f"ACTIONX\n{act_name} 1000000 /\n"
|
|
1683
|
+
f"SPRD '{well_name}' {segment_number} "
|
|
1684
|
+
f"{sign[iaction]} {pressure_drop_cutoff} AND /\n"
|
|
1685
|
+
f"SUVTRIG '{well_name}' {segment_number} "
|
|
1686
|
+
f"= {suvtrig[iaction]} /\n/\n\n"
|
|
1687
|
+
)
|
|
1688
|
+
print_df = df_wseginjv[df_wseginjv[Headers.START_SEGMENT_NUMBER] == segment_number]
|
|
1689
|
+
print_df = print_df[header[iaction]] # type: ignore
|
|
1690
|
+
header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
|
|
1691
|
+
|
|
1692
|
+
for item in header[iaction]:
|
|
1693
|
+
header_string += " " + item
|
|
1694
|
+
header_string = header_string.rstrip() + "\n"
|
|
1695
|
+
print_df = header_string + dataframe_tostring(print_df, True, False, False) # type: ignore
|
|
1696
|
+
print_df += "\n/\n"
|
|
1697
|
+
print_df += f"\nUDQ\n ASSIGN SUVTRIG {well_name} {segment_number} 1 /\n/\n"
|
|
1698
|
+
action += print_df + "\nENDACTIO\n\n"
|
|
1699
|
+
|
|
1700
|
+
iaction = 1
|
|
1701
|
+
act_number = iaction + 1
|
|
1702
|
+
act_name = f"INJVCL{well_number:03d}{segment_number:03d}{act_number:1d}"
|
|
1703
|
+
if len(act_name) > 13:
|
|
1704
|
+
raise CompletorError("Too many wells and/or too many segments with Injection Valve")
|
|
1705
|
+
action += (
|
|
1706
|
+
f"ACTIONX\n{act_name} 1000000 /\n"
|
|
1707
|
+
f"SPRD '{well_name}' {segment_number} "
|
|
1708
|
+
f"{sign[iaction]} {pressure_drop_cutoff} AND /\n"
|
|
1709
|
+
f"SUVTRIG '{well_name}' {segment_number} "
|
|
1710
|
+
f"= {suvtrig[iaction]} /\n/\n\n"
|
|
1711
|
+
)
|
|
1712
|
+
print_df = df_wseginjv[df_wseginjv[Headers.START_SEGMENT_NUMBER] == segment_number]
|
|
1713
|
+
print_df = print_df[header[iaction]] # type: ignore
|
|
1714
|
+
header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
|
|
1715
|
+
|
|
1716
|
+
for item in header[iaction]:
|
|
1717
|
+
header_string += " " + item
|
|
1718
|
+
header_string = header_string.rstrip() + "\n"
|
|
1719
|
+
print_df = header_string + dataframe_tostring(print_df, True, False, False) # type: ignore
|
|
1720
|
+
print_df += "\n/\n"
|
|
1721
|
+
print_df += f"\nUDQ\n ASSIGN SUVTRIG {well_name} {segment_number} 0 /\n/\n"
|
|
1722
|
+
action += print_df + "\nENDACTIO\n\n"
|
|
1723
|
+
else:
|
|
1724
|
+
raise CompletorError("Trigger paramater given is not supported")
|
|
1725
|
+
return action
|
|
1726
|
+
|
|
1727
|
+
|
|
1516
1728
|
def print_wsegdualrcp(df_wsegdualrcp: pd.DataFrame, well_number: int) -> str:
|
|
1517
1729
|
"""Print for DUALRCP devices.
|
|
1518
1730
|
|
completor/read_casefile.py
CHANGED
|
@@ -48,7 +48,7 @@ class ReadCasefile:
|
|
|
48
48
|
This class reads the case/input file of the Completor program.
|
|
49
49
|
It reads the following keywords:
|
|
50
50
|
COMPLETION, SEGMENTLENGTH, JOINTLENGTH, AUTONOMOUS_INFLOW_CONTROL_DEVICE, WELL_SEGMENTS_VALVE,
|
|
51
|
-
INFLOW_CONTROL_DEVICE, DENSITY_DRIVEN, DUAL_RATE_CONTROLLED_PRODUCTION, INFLOW_CONTROL_VALVE.
|
|
51
|
+
INFLOW_CONTROL_DEVICE, DENSITY_DRIVEN, INJECTION_VALVE, DUAL_RATE_CONTROLLED_PRODUCTION, INFLOW_CONTROL_VALVE.
|
|
52
52
|
In the absence of some keywords, the program uses the default values.
|
|
53
53
|
|
|
54
54
|
Attributes:
|
|
@@ -64,6 +64,7 @@ class ReadCasefile:
|
|
|
64
64
|
wsegvalv_table (pd.DataFrame): WELL_SEGMENTS_VALVE.
|
|
65
65
|
wsegicv_table (pd.DataFrame): INFLOW_CONTROL_VALVE.
|
|
66
66
|
wsegdensity_table (pd.DataFrame): DENSITY_DRIVEN.
|
|
67
|
+
wseginjv_table (pd.DataFrame): INJECTION_VALVE.
|
|
67
68
|
wsegdualrcp_table (pd.DataFrame): DUAL_RATE_CONTROLLED_PRODUCTION.
|
|
68
69
|
strict (bool): USE_STRICT. If TRUE it will exit if any lateral is not defined in the case-file. Default to TRUE.
|
|
69
70
|
lat2device (pd.DataFrame): LATERAL_TO_DEVICE.
|
|
@@ -99,6 +100,7 @@ class ReadCasefile:
|
|
|
99
100
|
self.wsegsicd_table = pd.DataFrame()
|
|
100
101
|
self.wsegvalv_table = pd.DataFrame()
|
|
101
102
|
self.wsegdensity_table = pd.DataFrame()
|
|
103
|
+
self.wseginjv_table = pd.DataFrame()
|
|
102
104
|
self.wsegdualrcp_table = pd.DataFrame()
|
|
103
105
|
self.wsegicv_table = pd.DataFrame()
|
|
104
106
|
self.lat2device = pd.DataFrame()
|
|
@@ -117,6 +119,7 @@ class ReadCasefile:
|
|
|
117
119
|
self.read_wsegvalv()
|
|
118
120
|
self.read_wsegsicd()
|
|
119
121
|
self.read_wsegdensity()
|
|
122
|
+
self.read_wseginjv()
|
|
120
123
|
self.read_wsegdualrcp()
|
|
121
124
|
self.read_wsegicv()
|
|
122
125
|
self.read_lat2device()
|
|
@@ -449,10 +452,14 @@ class ReadCasefile:
|
|
|
449
452
|
Headers.F,
|
|
450
453
|
Headers.AICD_CALIBRATION_FLUID_DENSITY,
|
|
451
454
|
Headers.AICD_FLUID_VISCOSITY,
|
|
455
|
+
Headers.Z,
|
|
452
456
|
]
|
|
453
|
-
|
|
454
|
-
self._create_dataframe_with_columns(header, start_index, end_index)
|
|
455
|
-
|
|
457
|
+
try:
|
|
458
|
+
df_temp = self._create_dataframe_with_columns(header, start_index, end_index)
|
|
459
|
+
except CaseReaderFormatError:
|
|
460
|
+
header.remove(Headers.Z)
|
|
461
|
+
df_temp = self._create_dataframe_with_columns(header, start_index, end_index)
|
|
462
|
+
self.wsegaicd_table = input_validation.set_format_wsegaicd(df_temp)
|
|
456
463
|
device_checks = self.completion_table[
|
|
457
464
|
self.completion_table[Headers.DEVICE_TYPE] == Content.AUTONOMOUS_INFLOW_CONTROL_DEVICE
|
|
458
465
|
][Headers.DEVICE_NUMBER].to_numpy()
|
|
@@ -514,6 +521,40 @@ class ReadCasefile:
|
|
|
514
521
|
if not check_contents(device_checks, self.wsegdensity_table[Headers.DEVICE_NUMBER].to_numpy()):
|
|
515
522
|
raise CompletorError(f"Not all device in COMPLETION is specified in {key}")
|
|
516
523
|
|
|
524
|
+
def read_wseginjv(self) -> None:
|
|
525
|
+
"""Read the INJECTION_VALVE keyword in the case file.
|
|
526
|
+
|
|
527
|
+
Raises:
|
|
528
|
+
CompletorError: If INJECTION_VALVE is not defined and INJV is used in COMPLETION,
|
|
529
|
+
or if the device number is not found.
|
|
530
|
+
If not all devices in COMPLETION are specified in INJECTION_VALVE.
|
|
531
|
+
"""
|
|
532
|
+
start_index, end_index = parse.locate_keyword(self.content, Keywords.INJECTION_VALVE)
|
|
533
|
+
if start_index == end_index:
|
|
534
|
+
if Content.INJECTION_VALVE in self.completion_table[Headers.DEVICE_TYPE]:
|
|
535
|
+
raise CompletorError(
|
|
536
|
+
f"{Keywords.INJECTION_VALVE} keyword must be defined, if INJV is used in the completion."
|
|
537
|
+
)
|
|
538
|
+
else:
|
|
539
|
+
# Table headers
|
|
540
|
+
header = [
|
|
541
|
+
Headers.DEVICE_NUMBER,
|
|
542
|
+
Headers.TRIGGER_PARAMETER,
|
|
543
|
+
Headers.TRIGGER_VALUE,
|
|
544
|
+
Headers.FLOW_COEFFICIENT,
|
|
545
|
+
Headers.PRIMARY_FLOW_CROSS_SECTIONAL_AREA,
|
|
546
|
+
Headers.SECONDARY_FLOW_CROSS_SECTIONAL_AREA,
|
|
547
|
+
]
|
|
548
|
+
self.wseginjv_table = input_validation.set_format_wseginjv(
|
|
549
|
+
self._create_dataframe_with_columns(header, start_index, end_index)
|
|
550
|
+
)
|
|
551
|
+
# Check if the device in COMPLETION is exist in INJECTION_VALVE
|
|
552
|
+
device_checks = self.completion_table[
|
|
553
|
+
self.completion_table[Headers.DEVICE_TYPE] == Content.INJECTION_VALVE
|
|
554
|
+
][Headers.DEVICE_NUMBER].to_numpy()
|
|
555
|
+
if not check_contents(device_checks, self.wseginjv_table[Headers.DEVICE_NUMBER].to_numpy()):
|
|
556
|
+
raise CompletorError(f"Not all device in COMPLETION is specified in {Keywords.INJECTION_VALVE}")
|
|
557
|
+
|
|
517
558
|
def read_wsegdualrcp(self) -> None:
|
|
518
559
|
"""Read the DUALRCP keyword in the case file.
|
|
519
560
|
|
completor/utils.py
CHANGED
|
@@ -193,6 +193,7 @@ def get_active_wells(completion_table: pd.DataFrame, gp_perf_devicelayer: bool)
|
|
|
193
193
|
Content.AUTONOMOUS_INFLOW_CONTROL_DEVICE,
|
|
194
194
|
Content.DUAL_RATE_CONTROLLED_PRODUCTION,
|
|
195
195
|
Content.DENSITY,
|
|
196
|
+
Content.INJECTION_VALVE,
|
|
196
197
|
Content.INFLOW_CONTROL_DEVICE,
|
|
197
198
|
Content.VALVE,
|
|
198
199
|
Content.INFLOW_CONTROL_VALVE,
|
completor/visualize_well.py
CHANGED
|
@@ -48,6 +48,8 @@ def visualize_device(axs: Axes, df_well: pd.DataFrame) -> Axes:
|
|
|
48
48
|
axs.plot(xpar, ypar, "rv-", markevery=[1])
|
|
49
49
|
elif df_device[Headers.DEVICE_TYPE].iloc[idx] == Content.DENSITY:
|
|
50
50
|
axs.plot(xpar, ypar, "rP-", markevery=[1])
|
|
51
|
+
elif df_device[Headers.DEVICE_TYPE].iloc[idx] == Content.INJECTION_VALVE:
|
|
52
|
+
axs.plot(xpar, ypar, "rP-", markevery=[1])
|
|
51
53
|
elif df_device[Headers.DEVICE_TYPE].iloc[idx] == Content.DUAL_RATE_CONTROLLED_PRODUCTION:
|
|
52
54
|
axs.plot(xpar, ypar, "r*-", markevery=[1])
|
|
53
55
|
return axs
|
completor/wells.py
CHANGED
|
@@ -220,6 +220,8 @@ class Lateral:
|
|
|
220
220
|
df_well = completion.get_device(df_well, case.wsegaicd_table, Content.AUTONOMOUS_INFLOW_CONTROL_DEVICE)
|
|
221
221
|
if Content.DENSITY in active_devices:
|
|
222
222
|
df_well = completion.get_device(df_well, case.wsegdensity_table, Content.DENSITY)
|
|
223
|
+
if Content.INJECTION_VALVE in active_devices:
|
|
224
|
+
df_well = completion.get_device(df_well, case.wseginjv_table, Content.INJECTION_VALVE)
|
|
223
225
|
if Content.DUAL_RATE_CONTROLLED_PRODUCTION in active_devices:
|
|
224
226
|
df_well = completion.get_device(df_well, case.wsegdualrcp_table, Content.DUAL_RATE_CONTROLLED_PRODUCTION)
|
|
225
227
|
if Content.INFLOW_CONTROL_VALVE in active_devices:
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
completor/__init__.py,sha256=k6amf7jhp7KkBIlaw93-NZITxyZjPSzA5McFAZh8yv8,76
|
|
2
|
-
completor/completion.py,sha256
|
|
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=eZPe6cbP8see9f_sJdUkdy6J6HM2eXulgqRCzTCBAqY,13489
|
|
5
|
+
completor/create_output.py,sha256=T0hPnCOns86q2lvRMNuOz8Nz-8zlliYBtxNiiEPMRWs,24101
|
|
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
|
|
9
9
|
completor/get_version.py,sha256=LMzybu7m-O203lUSZvyu86J4bMobbjE9A23fWLDlxaM,168
|
|
10
10
|
completor/hook_implementations/jobs.py,sha256=8Ao8UadfJzEY7jWzj6C_OXm18fHmfXrbCB2_jS7KHiU,2180
|
|
11
|
-
completor/input_validation.py,sha256=
|
|
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
14
|
completor/main.py,sha256=ipARMDXXqPYRtBxYQnlj5MohepwkgrQkX3s2IJEaEcI,9151
|
|
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=YS6p_kfTw_zXi0jKPwxrx45_54wrUaD0ryuZ2qe_S5Q,82582
|
|
17
|
+
completor/read_casefile.py,sha256=qs39CkpwyNXV4cm0tpMi9NOyehBQKOBWmsCjSrWEauM,37578
|
|
18
18
|
completor/read_schedule.py,sha256=IYyCubOggFGg664h1flTl7MUJhJWyibr6JsptnURjUA,18101
|
|
19
|
-
completor/utils.py,sha256=
|
|
19
|
+
completor/utils.py,sha256=9Qayt7xMsimpoVDo5sL86gVaQBbIOezMBRyMXd3haXw,13598
|
|
20
20
|
completor/visualization.py,sha256=ObxThqIyW3fsvVIupxVsgySFI_54n_Di-HTzFtDMSgo,4580
|
|
21
|
-
completor/visualize_well.py,sha256=
|
|
22
|
-
completor/wells.py,sha256=
|
|
23
|
-
completor-1.
|
|
24
|
-
completor-1.
|
|
25
|
-
completor-1.
|
|
26
|
-
completor-1.
|
|
27
|
-
completor-1.
|
|
21
|
+
completor/visualize_well.py,sha256=HLglSN2ce-u9nklJelqwhSxwwaj7n-aU6o8lUScbiI0,8790
|
|
22
|
+
completor/wells.py,sha256=Q2detK0FxIBgusYkCRmomRIfcScBNvNTYX43GFyAHGw,12246
|
|
23
|
+
completor-1.2.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
24
|
+
completor-1.2.0.dist-info/METADATA,sha256=4C5L62K_4i2YRU-SuQxVlcStnd03iTd0bZzVscKJWTg,7979
|
|
25
|
+
completor-1.2.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
26
|
+
completor-1.2.0.dist-info/entry_points.txt,sha256=co5L2_CC2QQWVdEALeMp-NIC4mx4nRpcLcvpVXMYdeI,106
|
|
27
|
+
completor-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|