completor 1.1.1__py3-none-any.whl → 1.1.3__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 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`, `DAR`, `VALVE`, `AICV`, `ICV`.
554
+ device_type: Device type. `AICD`, `ICD`, `DENSITY`, `VALVE`, `DUALRCP`, `ICV`.
555
555
 
556
556
  Returns:
557
557
  Updated well information with device characteristics.
@@ -561,7 +561,14 @@ def get_device(df_well: pd.DataFrame, df_device: pd.DataFrame, device_type: str)
561
561
  """
562
562
  columns = [Headers.DEVICE_TYPE, Headers.DEVICE_NUMBER]
563
563
  try:
564
- df_well = pd.merge(df_well, df_device, how="left", on=columns)
564
+ df_well = pd.merge(df_well, df_device, how="left", on=columns, suffixes=("", "_drop"))
565
+ # check for duplicates if merging two WSEGVALV-es
566
+ for col in df_well.columns:
567
+ if col.endswith("_drop"):
568
+ base_col = col.replace("_drop", "")
569
+ if base_col in df_well.columns:
570
+ df_well[base_col] = df_well[base_col].fillna(df_well[col]) # Fill NaN values
571
+ df_well = df_well.drop(columns=[col for col in df_well.columns if col.endswith("_drop")])
565
572
  except KeyError as err:
566
573
  if f"'{Headers.DEVICE_TYPE}'" in str(err):
567
574
  raise ValueError(f"Missing keyword 'DEVICETYPE {device_type}' in input files.") from err
@@ -570,7 +577,7 @@ def get_device(df_well: pd.DataFrame, df_device: pd.DataFrame, device_type: str)
570
577
  # rescale the Cv
571
578
  # because no scaling factor in WELL_SEGMENTS_VALVE
572
579
  df_well[Headers.FLOW_COEFFICIENT] = -df_well[Headers.FLOW_COEFFICIENT] / df_well[Headers.SCALE_FACTOR]
573
- elif device_type == Content.DENSITY_ACTIVATED_RECOVERY:
580
+ elif device_type == Content.DENSITY:
574
581
  # rescale the Cv
575
582
  # because no scaling factor in WELL_SEGMENTS_VALVE
576
583
  df_well[Headers.FLOW_COEFFICIENT] = -df_well[Headers.FLOW_COEFFICIENT] / df_well[Headers.SCALE_FACTOR]
completor/constants.py CHANGED
@@ -153,7 +153,7 @@ class _Headers:
153
153
  # 11. The length of the valve, lVAL (Scale factor).
154
154
  # 12. An integer which determines how the flow scaling factor is calculated.
155
155
 
156
- # Density Activated Recovery Well Segments (WSEGDAR)
156
+ # Density Driven Well Segments (WSEGDENSITY)
157
157
  # DEVICE_NUMBER
158
158
  # FLOW_COEFFICIENT / Cv
159
159
  # FLOW_CROSS_SECTIONAL_AREA
@@ -186,10 +186,10 @@ class _Headers:
186
186
  LATERAL = "LATERAL"
187
187
  NUMBER_OF_DEVICES = "NUMBER_OF_DEVICES"
188
188
  SEGMENT_DESC = "SEGMENT_DESC"
189
- AICV_WATER_CUT = "AICV_WATER_CUT"
190
- AICV_GAS_HOLDUP_FRACTION = "AICV_GAS_HOLDUP_FRACTION"
191
- AICV_CALIBRATION_FLUID_DENSITY = "AICV_CALIBRATION_FLUID_DENSITY"
192
- AICV_FLUID_VISCOSITY = "AICV_FLUID_VISCOSITY"
189
+ DUALRCP_WATER_CUT = "DUALRCP_WATER_CUT"
190
+ DUALRCP_GAS_HOLDUP_FRACTION = "DUALRCP_GAS_HOLDUP_FRACTION"
191
+ DUALRCP_CALIBRATION_FLUID_DENSITY = "DUALRCP_CALIBRATION_FLUID_DENSITY"
192
+ DUALRCP_FLUID_VISCOSITY = "DUALRCP_FLUID_VISCOSITY"
193
193
  AICD_CALIBRATION_FLUID_DENSITY = "AICD_CALIBRATION_FLUID_DENSITY"
194
194
  AICD_FLUID_VISCOSITY = "AICD_FLUID_VISCOSITY"
195
195
  ALPHA_MAIN = "ALPHA_MAIN"
@@ -239,9 +239,11 @@ class _Keywords:
239
239
  WELL_SEGMENTS_LINK = "WSEGLINK"
240
240
  WELL_SEGMENTS_VALVE = "WSEGVALV"
241
241
  AUTONOMOUS_INFLOW_CONTROL_DEVICE = "WSEGAICD"
242
+ DUAL_RATE_CONTROLLED_PRODUCTION = "WSEGDUALRCP"
242
243
  AUTONOMOUS_INFLOW_CONTROL_VALVE = "WSEGAICV"
243
244
  INFLOW_CONTROL_VALVE = "WSEGICV"
244
245
  INFLOW_CONTROL_DEVICE = "WSEGSICD"
246
+ DENSITY = "WSEGDENSITY"
245
247
  DENSITY_ACTIVATED_RECOVERY = "WSEGDAR"
246
248
  LATERAL_TO_DEVICE = "LATERAL_TO_DEVICE"
247
249
  JOINT_LENGTH = "JOINTLENGTH"
@@ -282,14 +284,18 @@ class _Content:
282
284
 
283
285
  PERFORATED = "PERF"
284
286
  INFLOW_CONTROL_VALVE = "ICV"
287
+ DUAL_RATE_CONTROLLED_PRODUCTION = "DUALRCP"
285
288
  AUTONOMOUS_INFLOW_CONTROL_VALVE = "AICV"
286
289
  INFLOW_CONTROL_DEVICE = "ICD"
287
290
  AUTONOMOUS_INFLOW_CONTROL_DEVICE = "AICD"
291
+ DENSITY = "DENSITY"
288
292
  DENSITY_ACTIVATED_RECOVERY = "DAR"
289
293
  VALVE = "VALVE"
290
294
  DEVICE_TYPES = [
291
295
  AUTONOMOUS_INFLOW_CONTROL_DEVICE,
296
+ DUAL_RATE_CONTROLLED_PRODUCTION,
292
297
  AUTONOMOUS_INFLOW_CONTROL_VALVE,
298
+ DENSITY,
293
299
  DENSITY_ACTIVATED_RECOVERY,
294
300
  INFLOW_CONTROL_DEVICE,
295
301
  VALVE,
@@ -40,8 +40,8 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
40
40
  print_inflow_control_valve = ""
41
41
  print_autonomous_inflow_control_device = ""
42
42
  print_inflow_control_device = ""
43
- print_density_activated_recovery = ""
44
- print_autonomous_inflow_control_valve = ""
43
+ print_density_driven = ""
44
+ print_dual_rate_controlled_production = ""
45
45
 
46
46
  start_segment = 2
47
47
  start_branch = 1
@@ -110,10 +110,8 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
110
110
  df_autonomous_inflow_control_device = prepare_outputs.prepare_autonomous_inflow_control_device(
111
111
  well.well_name, lateral.df_well, lateral.df_device
112
112
  )
113
- df_density_activated_recovery = prepare_outputs.prepare_density_activated_recovery(
114
- well.well_name, lateral.df_well, lateral.df_device
115
- )
116
- df_autonomous_inflow_control_valve = prepare_outputs.prepare_autonomous_inflow_control_valve(
113
+ df_density_driven = prepare_outputs.prepare_density_driven(well.well_name, lateral.df_well, lateral.df_device)
114
+ df_dual_rate_controlled_production = prepare_outputs.prepare_dual_rate_controlled_production(
117
115
  well.well_name, lateral.df_well, lateral.df_device
118
116
  )
119
117
  df_inflow_control_valve = prepare_outputs.prepare_inflow_control_valve(
@@ -147,11 +145,9 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
147
145
  print_inflow_control_valve += _format_inflow_control_valve(
148
146
  well.well_name, lateral.lateral_number, df_inflow_control_valve, first
149
147
  )
150
- print_density_activated_recovery += _format_density_activated_recovery(
151
- well.well_number, df_density_activated_recovery
152
- )
153
- print_autonomous_inflow_control_valve += _format_autonomous_inflow_control_valve(
154
- well.well_number, df_autonomous_inflow_control_valve
148
+ print_density_driven += _format_density_driven(well.well_number, df_density_driven)
149
+ print_dual_rate_controlled_production += _format_dual_rate_controlled_production(
150
+ well.well_number, df_dual_rate_controlled_production
155
151
  )
156
152
 
157
153
  if figure_name is not None:
@@ -183,10 +179,10 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
183
179
  bonus.append(f"{Keywords.AUTONOMOUS_INFLOW_CONTROL_DEVICE}{print_autonomous_inflow_control_device}\n/\n\n\n")
184
180
  if print_inflow_control_valve:
185
181
  bonus.append(f"{Keywords.WELL_SEGMENTS_VALVE}{print_inflow_control_valve}\n/\n\n\n")
186
- if print_density_activated_recovery:
182
+ if print_density_driven:
187
183
  metadata = (
188
184
  f"{'-' * 100}\n"
189
- "-- This is how we model DAR technology using sets of ACTIONX keywords.\n"
185
+ "-- This is how we model DENSITY technology using sets of ACTIONX keywords.\n"
190
186
  "-- The segment dP curves changes according to the segment water-\n"
191
187
  "-- and gas volume fractions at downhole condition.\n"
192
188
  "-- The value of Cv is adjusted according to the segment length and the number of\n"
@@ -194,16 +190,16 @@ def format_output(well: Well, case: ReadCasefile, figure_name: str | None = None
194
190
  "-- volume fractions.\n"
195
191
  f"{'-' * 100}\n\n\n"
196
192
  )
197
- bonus.append(metadata + print_density_activated_recovery + "\n\n\n\n")
198
- if print_autonomous_inflow_control_valve:
193
+ bonus.append(metadata + print_density_driven + "\n\n\n\n")
194
+ if print_dual_rate_controlled_production:
199
195
  metadata = (
200
196
  f"{'-' * 100}\n"
201
- "-- This is how we model AICV technology using sets of ACTIONX keyword\n"
197
+ "-- This is how we model DUALRCP technology using sets of ACTIONX keyword\n"
202
198
  "-- the DP parameters change according to the segment water cut (at downhole condition )\n"
203
199
  "-- and gas volume fraction (at downhole condition)\n"
204
200
  f"{'-' * 100}\n\n\n"
205
201
  )
206
- bonus.append(metadata + print_autonomous_inflow_control_valve + "\n\n\n\n")
202
+ bonus.append(metadata + print_dual_rate_controlled_production + "\n\n\n\n")
207
203
 
208
204
  return print_completion_data, print_well_segments, print_completion_segments, "".join(bonus)
209
205
 
@@ -439,34 +435,34 @@ def _format_inflow_control_valve(well_name: str, lateral_number: int, df_wsegicv
439
435
  )
440
436
 
441
437
 
442
- def _format_density_activated_recovery(well_number: int, df_wsegdar: pd.DataFrame) -> str:
443
- """Formats well-segments for density activated recovery valve.
438
+ def _format_density_driven(well_number: int, df_wsegdensity: pd.DataFrame) -> str:
439
+ """Formats well-segments for density driven valve.
444
440
 
445
441
  Args:
446
442
  well_number: The well's number
447
- df_wsegdar: Data to print.
443
+ df_wsegdensity: Data to print.
448
444
 
449
445
  Returns:
450
446
  Formatted string.
451
447
  """
452
- if df_wsegdar.empty:
448
+ if df_wsegdensity.empty:
453
449
  return ""
454
- return prepare_outputs.print_wsegdar(df_wsegdar, well_number + 1)
450
+ return prepare_outputs.print_wsegdensity(df_wsegdensity, well_number + 1)
455
451
 
456
452
 
457
- def _format_autonomous_inflow_control_valve(well_number: int, df_wsegaicv: pd.DataFrame) -> str:
458
- """Formats the AICV section.
453
+ def _format_dual_rate_controlled_production(well_number: int, df_wsegdualrcp: pd.DataFrame) -> str:
454
+ """Formats the DUALRCP section.
459
455
 
460
456
  Args:
461
457
  well_number: The well's number
462
- df_wsegaicv: Data to print.
458
+ df_wsegdualrcp: Data to print.
463
459
 
464
460
  Returns:
465
461
  Formatted string.
466
462
  """
467
- if df_wsegaicv.empty:
463
+ if df_wsegdualrcp.empty:
468
464
  return ""
469
- return prepare_outputs.print_wsegaicv(df_wsegaicv, well_number + 1)
465
+ return prepare_outputs.print_wsegdualrcp(df_wsegdualrcp, well_number + 1)
470
466
 
471
467
 
472
468
  def _branch_revision(
@@ -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, DAR, AICV, and ICV."
176
+ "Valid types are PERF, AICD, ICD, VALVE, DENSITY, DUALRCP, and ICV."
177
177
  )
178
178
  if df_comp[Headers.ANNULUS].iloc[idx] not in Content.ANNULUS_TYPES:
179
179
  raise CompletorError(
@@ -181,6 +181,36 @@ def _check_for_errors(df_comp: pd.DataFrame, well_name: str, idx: int) -> None:
181
181
  )
182
182
 
183
183
 
184
+ def set_density_based(df_comp: pd.DataFrame) -> pd.DataFrame:
185
+ """Set the column data format.
186
+ Args:
187
+ df_comp: Completion data.
188
+ Returns:
189
+ Updated device type to all density based.
190
+ """
191
+ df_comp[Headers.DEVICE_TYPE] = np.where(
192
+ df_comp[Headers.DEVICE_TYPE] == Content.DENSITY_ACTIVATED_RECOVERY,
193
+ Content.DENSITY,
194
+ df_comp[Headers.DEVICE_TYPE],
195
+ )
196
+ return df_comp
197
+
198
+
199
+ def set_dualrcp(df_comp: pd.DataFrame) -> pd.DataFrame:
200
+ """Set the column data format.
201
+ Args:
202
+ df_comp: Completion data.
203
+ Returns:
204
+ Updated device type to all dual RCP based.
205
+ """
206
+ df_comp[Headers.DEVICE_TYPE] = np.where(
207
+ df_comp[Headers.DEVICE_TYPE] == Content.AUTONOMOUS_INFLOW_CONTROL_VALVE,
208
+ Content.DUAL_RATE_CONTROLLED_PRODUCTION,
209
+ df_comp[Headers.DEVICE_TYPE],
210
+ )
211
+ return df_comp
212
+
213
+
184
214
  def set_format_wsegvalv(df_temp: pd.DataFrame) -> pd.DataFrame:
185
215
  """Format the Well Segments Valve (WELSEGS) table.
186
216
 
@@ -242,11 +272,11 @@ def set_format_wsegaicd(df_temp: pd.DataFrame) -> pd.DataFrame:
242
272
  return df_temp
243
273
 
244
274
 
245
- def set_format_wsegdar(df_temp: pd.DataFrame) -> pd.DataFrame:
246
- """Format the well segments Density Activated Recovery (DAR) data.
275
+ def set_format_wsegdensity(df_temp: pd.DataFrame) -> pd.DataFrame:
276
+ """Format the well segments Density Driven (DENSITY) data.
247
277
 
248
278
  Args:
249
- df_temp: Well segments DAR device data.
279
+ df_temp: Well segments DENSITY device data.
250
280
 
251
281
  Returns:
252
282
  Updated data.
@@ -256,15 +286,15 @@ def set_format_wsegdar(df_temp: pd.DataFrame) -> pd.DataFrame:
256
286
  columns = df_temp.columns.to_numpy()[1:]
257
287
  df_temp[columns] = df_temp[columns].astype(np.float64)
258
288
  # Create ID device column
259
- df_temp.insert(0, Headers.DEVICE_TYPE, np.full(df_temp.shape[0], Content.DENSITY_ACTIVATED_RECOVERY))
289
+ df_temp.insert(0, Headers.DEVICE_TYPE, np.full(df_temp.shape[0], Content.DENSITY))
260
290
  return df_temp
261
291
 
262
292
 
263
- def set_format_wsegaicv(df_temp: pd.DataFrame) -> pd.DataFrame:
264
- """Format the well segments Automatic Inflow Control Valve (AICV) table.
293
+ def set_format_wsegdualrcp(df_temp: pd.DataFrame) -> pd.DataFrame:
294
+ """Format the well segments Dual RCP (DUALRCP) table.
265
295
 
266
296
  Args:
267
- df_temp: Well segments automatic inflow control valve table.
297
+ df_temp: Well segments dual RCP table.
268
298
 
269
299
  Returns:
270
300
  Updated data.
@@ -274,7 +304,7 @@ def set_format_wsegaicv(df_temp: pd.DataFrame) -> pd.DataFrame:
274
304
  columns = df_temp.columns.to_numpy()[1:]
275
305
  df_temp[columns] = df_temp[columns].astype(np.float64)
276
306
  # Create ID device column
277
- df_temp.insert(0, Headers.DEVICE_TYPE, np.full(df_temp.shape[0], Content.AUTONOMOUS_INFLOW_CONTROL_VALVE))
307
+ df_temp.insert(0, Headers.DEVICE_TYPE, np.full(df_temp.shape[0], Content.DUAL_RATE_CONTROLLED_PRODUCTION))
278
308
  return df_temp
279
309
 
280
310
 
@@ -448,11 +448,11 @@ def prepare_device_layer(df_well: pd.DataFrame, df_tubing: pd.DataFrame, device_
448
448
  df_well[Headers.DEVICE_TYPE] == Content.VALVE,
449
449
  "/ -- Valve types",
450
450
  np.where(
451
- df_well[Headers.DEVICE_TYPE] == Content.DENSITY_ACTIVATED_RECOVERY,
452
- "/ -- DAR types",
451
+ df_well[Headers.DEVICE_TYPE] == Content.DENSITY,
452
+ "/ -- DENSITY types",
453
453
  np.where(
454
- df_well[Headers.DEVICE_TYPE] == Content.AUTONOMOUS_INFLOW_CONTROL_VALVE,
455
- "/ -- AICV types",
454
+ df_well[Headers.DEVICE_TYPE] == Content.DUAL_RATE_CONTROLLED_PRODUCTION,
455
+ "/ -- DUALRCP types",
456
456
  np.where(
457
457
  df_well[Headers.DEVICE_TYPE] == Content.INFLOW_CONTROL_VALVE, "/ -- ICV types", ""
458
458
  ),
@@ -852,6 +852,7 @@ def prepare_completion_segments(
852
852
  }
853
853
  )
854
854
  compseg[Headers.EMPTY] = "/"
855
+ compseg.sort_values(Headers.START_MEASURED_DEPTH, inplace=True)
855
856
  return compseg
856
857
 
857
858
 
@@ -1249,8 +1250,8 @@ def prepare_inflow_control_valve(
1249
1250
  return wsegicv
1250
1251
 
1251
1252
 
1252
- def prepare_density_activated_recovery(well_name: str, df_well: pd.DataFrame, df_device: pd.DataFrame) -> pd.DataFrame:
1253
- """Prepare data frame for DAR.
1253
+ def prepare_density_driven(well_name: str, df_well: pd.DataFrame, df_device: pd.DataFrame) -> pd.DataFrame:
1254
+ """Prepare data frame for DENSITY.
1254
1255
 
1255
1256
  Args:
1256
1257
  well_name: Well name.
@@ -1258,7 +1259,7 @@ def prepare_density_activated_recovery(well_name: str, df_well: pd.DataFrame, df
1258
1259
  df_device: Device data for this well and lateral.
1259
1260
 
1260
1261
  Returns:
1261
- DataFrame for DAR.
1262
+ DataFrame for DENSITY.
1262
1263
  """
1263
1264
  df_well = df_well[(df_well[Headers.DEVICE_TYPE] == Content.PERFORATED) | (df_well[Headers.NUMBER_OF_DEVICES] > 0)]
1264
1265
  if df_well.shape[0] == 0:
@@ -1270,34 +1271,42 @@ def prepare_density_activated_recovery(well_name: str, df_well: pd.DataFrame, df
1270
1271
  right_on=[Headers.TUBING_MEASURED_DEPTH],
1271
1272
  direction="nearest",
1272
1273
  )
1273
- df_merge = df_merge[df_merge[Headers.DEVICE_TYPE] == Content.DENSITY_ACTIVATED_RECOVERY]
1274
- wsegdar = pd.DataFrame()
1274
+ df_merge = df_merge[df_merge[Headers.DEVICE_TYPE] == Content.DENSITY]
1275
+ wsegdensity = pd.DataFrame()
1275
1276
  if df_merge.shape[0] > 0:
1276
- wsegdar[Headers.WELL] = [well_name] * df_merge.shape[0]
1277
- wsegdar[Headers.START_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
1277
+ wsegdensity[Headers.WELL] = [well_name] * df_merge.shape[0]
1278
+ wsegdensity[Headers.START_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
1278
1279
  # the Cv is already corrected by the scaling factor
1279
- wsegdar[Headers.FLOW_COEFFICIENT] = df_merge[Headers.FLOW_COEFFICIENT].to_numpy()
1280
- wsegdar[Headers.OIL_FLOW_CROSS_SECTIONAL_AREA] = df_merge[Headers.OIL_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
1281
- wsegdar[Headers.GAS_FLOW_CROSS_SECTIONAL_AREA] = df_merge[Headers.GAS_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
1282
- wsegdar[Headers.WATER_FLOW_CROSS_SECTIONAL_AREA] = df_merge[Headers.WATER_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
1283
- wsegdar[Headers.WATER_HOLDUP_FRACTION_LOW_CUTOFF] = df_merge[
1280
+ wsegdensity[Headers.FLOW_COEFFICIENT] = df_merge[Headers.FLOW_COEFFICIENT].to_numpy()
1281
+ wsegdensity[Headers.OIL_FLOW_CROSS_SECTIONAL_AREA] = df_merge[Headers.OIL_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
1282
+ wsegdensity[Headers.GAS_FLOW_CROSS_SECTIONAL_AREA] = df_merge[Headers.GAS_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
1283
+ wsegdensity[Headers.WATER_FLOW_CROSS_SECTIONAL_AREA] = df_merge[
1284
+ Headers.WATER_FLOW_CROSS_SECTIONAL_AREA
1285
+ ].to_numpy()
1286
+ wsegdensity[Headers.WATER_HOLDUP_FRACTION_LOW_CUTOFF] = df_merge[
1284
1287
  Headers.WATER_HOLDUP_FRACTION_LOW_CUTOFF
1285
1288
  ].to_numpy()
1286
- wsegdar[Headers.WATER_HOLDUP_FRACTION_HIGH_CUTOFF] = df_merge[
1289
+ wsegdensity[Headers.WATER_HOLDUP_FRACTION_HIGH_CUTOFF] = df_merge[
1287
1290
  Headers.WATER_HOLDUP_FRACTION_HIGH_CUTOFF
1288
1291
  ].to_numpy()
1289
- wsegdar[Headers.GAS_HOLDUP_FRACTION_LOW_CUTOFF] = df_merge[Headers.GAS_HOLDUP_FRACTION_LOW_CUTOFF].to_numpy()
1290
- wsegdar[Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF] = df_merge[Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF].to_numpy()
1291
- wsegdar[Headers.DEFAULTS] = "5*"
1292
- wsegdar[Headers.MAX_FLOW_CROSS_SECTIONAL_AREA] = wsegdar[Headers.OIL_FLOW_CROSS_SECTIONAL_AREA].to_numpy()
1293
- wsegdar[Headers.EMPTY] = "/"
1294
- return wsegdar
1292
+ wsegdensity[Headers.GAS_HOLDUP_FRACTION_LOW_CUTOFF] = df_merge[
1293
+ Headers.GAS_HOLDUP_FRACTION_LOW_CUTOFF
1294
+ ].to_numpy()
1295
+ wsegdensity[Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF] = df_merge[
1296
+ Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF
1297
+ ].to_numpy()
1298
+ wsegdensity[Headers.DEFAULTS] = "5*"
1299
+ wsegdensity[Headers.MAX_FLOW_CROSS_SECTIONAL_AREA] = wsegdensity[
1300
+ Headers.OIL_FLOW_CROSS_SECTIONAL_AREA
1301
+ ].to_numpy()
1302
+ wsegdensity[Headers.EMPTY] = "/"
1303
+ return wsegdensity
1295
1304
 
1296
1305
 
1297
- def prepare_autonomous_inflow_control_valve(
1306
+ def prepare_dual_rate_controlled_production(
1298
1307
  well_name: str, df_well: pd.DataFrame, df_device: pd.DataFrame
1299
1308
  ) -> pd.DataFrame:
1300
- """Prepare data frame for AICV.
1309
+ """Prepare data frame for DUALRCP.
1301
1310
 
1302
1311
  Args:
1303
1312
  well_name: Well name.
@@ -1305,7 +1314,7 @@ def prepare_autonomous_inflow_control_valve(
1305
1314
  df_device: Device data for this well and lateral.
1306
1315
 
1307
1316
  Returns:
1308
- DataFrame for AICV.
1317
+ DataFrame for DUALRCP.
1309
1318
  """
1310
1319
  df_well = df_well[(df_well[Headers.DEVICE_TYPE] == Content.PERFORATED) | (df_well[Headers.NUMBER_OF_DEVICES] > 0)]
1311
1320
  if df_well.shape[0] == 0:
@@ -1317,53 +1326,53 @@ def prepare_autonomous_inflow_control_valve(
1317
1326
  right_on=[Headers.TUBING_MEASURED_DEPTH],
1318
1327
  direction="nearest",
1319
1328
  )
1320
- df_merge = df_merge[df_merge[Headers.DEVICE_TYPE] == Content.AUTONOMOUS_INFLOW_CONTROL_VALVE]
1321
- wsegaicv = pd.DataFrame()
1329
+ df_merge = df_merge[df_merge[Headers.DEVICE_TYPE] == Content.DUAL_RATE_CONTROLLED_PRODUCTION]
1330
+ wsegdualrcp = pd.DataFrame()
1322
1331
  if df_merge.shape[0] > 0:
1323
- wsegaicv[Headers.WELL] = [well_name] * df_merge.shape[0]
1324
- wsegaicv[Headers.START_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
1325
- wsegaicv[Headers.END_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
1326
- wsegaicv[Headers.ALPHA_MAIN] = df_merge[Headers.ALPHA_MAIN].to_numpy()
1327
- wsegaicv[Headers.SCALE_FACTOR] = df_merge[Headers.SCALE_FACTOR].to_numpy()
1328
- wsegaicv[Headers.CALIBRATION_FLUID_DENSITY] = df_merge[Headers.AICV_CALIBRATION_FLUID_DENSITY].to_numpy()
1329
- wsegaicv[Headers.CALIBRATION_FLUID_VISCOSITY] = df_merge[Headers.AICV_FLUID_VISCOSITY].to_numpy()
1330
- wsegaicv[Headers.DEF] = ["5*"] * df_merge.shape[0]
1331
- wsegaicv[Headers.X_MAIN] = df_merge[Headers.X_MAIN].to_numpy()
1332
- wsegaicv[Headers.Y_MAIN] = df_merge[Headers.Y_MAIN].to_numpy()
1333
- wsegaicv[Headers.FLAG] = [Headers.OPEN] * df_merge.shape[0]
1334
- wsegaicv[Headers.A_MAIN] = df_merge[Headers.A_MAIN].to_numpy()
1335
- wsegaicv[Headers.B_MAIN] = df_merge[Headers.B_MAIN].to_numpy()
1336
- wsegaicv[Headers.C_MAIN] = df_merge[Headers.C_MAIN].to_numpy()
1337
- wsegaicv[Headers.D_MAIN] = df_merge[Headers.D_MAIN].to_numpy()
1338
- wsegaicv[Headers.E_MAIN] = df_merge[Headers.E_MAIN].to_numpy()
1339
- wsegaicv[Headers.F_MAIN] = df_merge[Headers.F_MAIN].to_numpy()
1340
- wsegaicv[Headers.ALPHA_PILOT] = df_merge[Headers.ALPHA_PILOT].to_numpy()
1341
- wsegaicv[Headers.X_PILOT] = df_merge[Headers.X_PILOT].to_numpy()
1342
- wsegaicv[Headers.Y_PILOT] = df_merge[Headers.Y_PILOT].to_numpy()
1343
- wsegaicv[Headers.A_PILOT] = df_merge[Headers.A_PILOT].to_numpy()
1344
- wsegaicv[Headers.B_PILOT] = df_merge[Headers.B_PILOT].to_numpy()
1345
- wsegaicv[Headers.C_PILOT] = df_merge[Headers.C_PILOT].to_numpy()
1346
- wsegaicv[Headers.D_PILOT] = df_merge[Headers.D_PILOT].to_numpy()
1347
- wsegaicv[Headers.E_PILOT] = df_merge[Headers.E_PILOT].to_numpy()
1348
- wsegaicv[Headers.F_PILOT] = df_merge[Headers.F_PILOT].to_numpy()
1349
- wsegaicv[Headers.AICV_WATER_CUT] = df_merge[Headers.AICV_WATER_CUT].to_numpy()
1350
- wsegaicv[Headers.AICV_GAS_HOLDUP_FRACTION] = df_merge[Headers.AICV_GAS_HOLDUP_FRACTION].to_numpy()
1351
- wsegaicv[Headers.EMPTY] = "/"
1352
- return wsegaicv
1353
-
1354
-
1355
- def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1356
- """Print DAR devices.
1332
+ wsegdualrcp[Headers.WELL] = [well_name] * df_merge.shape[0]
1333
+ wsegdualrcp[Headers.START_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
1334
+ wsegdualrcp[Headers.END_SEGMENT_NUMBER] = df_merge[Headers.START_SEGMENT_NUMBER].to_numpy()
1335
+ wsegdualrcp[Headers.ALPHA_MAIN] = df_merge[Headers.ALPHA_MAIN].to_numpy()
1336
+ wsegdualrcp[Headers.SCALE_FACTOR] = df_merge[Headers.SCALE_FACTOR].to_numpy()
1337
+ wsegdualrcp[Headers.CALIBRATION_FLUID_DENSITY] = df_merge[Headers.DUALRCP_CALIBRATION_FLUID_DENSITY].to_numpy()
1338
+ wsegdualrcp[Headers.CALIBRATION_FLUID_VISCOSITY] = df_merge[Headers.DUALRCP_FLUID_VISCOSITY].to_numpy()
1339
+ wsegdualrcp[Headers.DEF] = ["5*"] * df_merge.shape[0]
1340
+ wsegdualrcp[Headers.X_MAIN] = df_merge[Headers.X_MAIN].to_numpy()
1341
+ wsegdualrcp[Headers.Y_MAIN] = df_merge[Headers.Y_MAIN].to_numpy()
1342
+ wsegdualrcp[Headers.FLAG] = [Headers.OPEN] * df_merge.shape[0]
1343
+ wsegdualrcp[Headers.A_MAIN] = df_merge[Headers.A_MAIN].to_numpy()
1344
+ wsegdualrcp[Headers.B_MAIN] = df_merge[Headers.B_MAIN].to_numpy()
1345
+ wsegdualrcp[Headers.C_MAIN] = df_merge[Headers.C_MAIN].to_numpy()
1346
+ wsegdualrcp[Headers.D_MAIN] = df_merge[Headers.D_MAIN].to_numpy()
1347
+ wsegdualrcp[Headers.E_MAIN] = df_merge[Headers.E_MAIN].to_numpy()
1348
+ wsegdualrcp[Headers.F_MAIN] = df_merge[Headers.F_MAIN].to_numpy()
1349
+ wsegdualrcp[Headers.ALPHA_PILOT] = df_merge[Headers.ALPHA_PILOT].to_numpy()
1350
+ wsegdualrcp[Headers.X_PILOT] = df_merge[Headers.X_PILOT].to_numpy()
1351
+ wsegdualrcp[Headers.Y_PILOT] = df_merge[Headers.Y_PILOT].to_numpy()
1352
+ wsegdualrcp[Headers.A_PILOT] = df_merge[Headers.A_PILOT].to_numpy()
1353
+ wsegdualrcp[Headers.B_PILOT] = df_merge[Headers.B_PILOT].to_numpy()
1354
+ wsegdualrcp[Headers.C_PILOT] = df_merge[Headers.C_PILOT].to_numpy()
1355
+ wsegdualrcp[Headers.D_PILOT] = df_merge[Headers.D_PILOT].to_numpy()
1356
+ wsegdualrcp[Headers.E_PILOT] = df_merge[Headers.E_PILOT].to_numpy()
1357
+ wsegdualrcp[Headers.F_PILOT] = df_merge[Headers.F_PILOT].to_numpy()
1358
+ wsegdualrcp[Headers.DUALRCP_WATER_CUT] = df_merge[Headers.DUALRCP_WATER_CUT].to_numpy()
1359
+ wsegdualrcp[Headers.DUALRCP_GAS_HOLDUP_FRACTION] = df_merge[Headers.DUALRCP_GAS_HOLDUP_FRACTION].to_numpy()
1360
+ wsegdualrcp[Headers.EMPTY] = "/"
1361
+ return wsegdualrcp
1362
+
1363
+
1364
+ def print_wsegdensity(df_wsegdensity: pd.DataFrame, well_number: int) -> str:
1365
+ """Print DENSITY devices.
1357
1366
 
1358
1367
  Args:
1359
- df_wsegdar: Output from function prepare_wsegdar.
1368
+ df_wsegdensity: Output from function prepare_wsegdensity.
1360
1369
  well_number: Well number.
1361
1370
 
1362
1371
  Returns:
1363
1372
  Formatted actions to be included in the output file.
1364
1373
 
1365
1374
  Raises:
1366
- CompletorError: If there are to many wells and/or segments with DAR.
1375
+ CompletorError: If there are to many wells and/or segments with DENSITY.
1367
1376
  """
1368
1377
  header = [
1369
1378
  [
@@ -1403,9 +1412,9 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1403
1412
  sign_gas = [">", "<=", "<", ""]
1404
1413
  suvtrig = ["0", "0", "1", "2"]
1405
1414
  action = "UDQ\n"
1406
- for idx in range(df_wsegdar.shape[0]):
1407
- segment_number = df_wsegdar[Headers.START_SEGMENT_NUMBER].iloc[idx]
1408
- well_name = df_wsegdar[Headers.WELL].iloc[idx]
1415
+ for idx in range(df_wsegdensity.shape[0]):
1416
+ segment_number = df_wsegdensity[Headers.START_SEGMENT_NUMBER].iloc[idx]
1417
+ well_name = df_wsegdensity[Headers.WELL].iloc[idx]
1409
1418
  action += f" ASSIGN SUVTRIG {well_name} {segment_number} 0 /\n"
1410
1419
  action += "/\n\n"
1411
1420
  iaction = 3
@@ -1414,25 +1423,25 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1414
1423
  for itm in header[iaction]:
1415
1424
  header_string += " " + itm
1416
1425
  action += header_string.rstrip() + "\n"
1417
- for idx in range(df_wsegdar.shape[0]):
1418
- segment_number = df_wsegdar[Headers.START_SEGMENT_NUMBER].iloc[idx]
1419
- print_df = df_wsegdar[df_wsegdar[Headers.START_SEGMENT_NUMBER] == segment_number]
1426
+ for idx in range(df_wsegdensity.shape[0]):
1427
+ segment_number = df_wsegdensity[Headers.START_SEGMENT_NUMBER].iloc[idx]
1428
+ print_df = df_wsegdensity[df_wsegdensity[Headers.START_SEGMENT_NUMBER] == segment_number]
1420
1429
  print_df = print_df[header[iaction]]
1421
1430
  print_df = dataframe_tostring(print_df, True, False, False) + "\n"
1422
1431
  action += print_df
1423
1432
  action += "/\n\n"
1424
- for idx in range(df_wsegdar.shape[0]):
1425
- segment_number = df_wsegdar[Headers.START_SEGMENT_NUMBER].iloc[idx]
1426
- well_name = df_wsegdar[Headers.WELL].iloc[idx]
1427
- water_holdup_fraction_low_cutoff = df_wsegdar[Headers.WATER_HOLDUP_FRACTION_LOW_CUTOFF].iloc[idx]
1428
- water_holdup_fraction_high_cutoff = df_wsegdar[Headers.WATER_HOLDUP_FRACTION_HIGH_CUTOFF].iloc[idx]
1429
- gas_holdup_fraction_low_cutoff = df_wsegdar[Headers.GAS_HOLDUP_FRACTION_LOW_CUTOFF].iloc[idx]
1430
- gas_holdup_fraction_high_cutoff = df_wsegdar[Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF].iloc[idx]
1433
+ for idx in range(df_wsegdensity.shape[0]):
1434
+ segment_number = df_wsegdensity[Headers.START_SEGMENT_NUMBER].iloc[idx]
1435
+ well_name = df_wsegdensity[Headers.WELL].iloc[idx]
1436
+ water_holdup_fraction_low_cutoff = df_wsegdensity[Headers.WATER_HOLDUP_FRACTION_LOW_CUTOFF].iloc[idx]
1437
+ water_holdup_fraction_high_cutoff = df_wsegdensity[Headers.WATER_HOLDUP_FRACTION_HIGH_CUTOFF].iloc[idx]
1438
+ gas_holdup_fraction_low_cutoff = df_wsegdensity[Headers.GAS_HOLDUP_FRACTION_LOW_CUTOFF].iloc[idx]
1439
+ gas_holdup_fraction_high_cutoff = df_wsegdensity[Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF].iloc[idx]
1431
1440
  for iaction in range(2):
1432
1441
  act_number = iaction + 1
1433
1442
  act_name = f"D{well_number:03d}{segment_number:03d}{act_number:1d}"
1434
1443
  if len(act_name) > 8:
1435
- raise CompletorError("Too many wells and/or too many segments with DAR")
1444
+ raise CompletorError("Too many wells and/or too many segments with DENSITY")
1436
1445
  action += (
1437
1446
  f"ACTIONX\n{act_name} 1000000 /\n"
1438
1447
  f"SWHF '{well_name}' {segment_number} "
@@ -1442,7 +1451,7 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1442
1451
  f"SUVTRIG '{well_name}' {segment_number} "
1443
1452
  f"= {suvtrig[iaction]} /\n/\n\n"
1444
1453
  )
1445
- print_df = df_wsegdar[df_wsegdar[Headers.START_SEGMENT_NUMBER] == segment_number]
1454
+ print_df = df_wsegdensity[df_wsegdensity[Headers.START_SEGMENT_NUMBER] == segment_number]
1446
1455
  print_df = print_df[header[iaction]] # type: ignore
1447
1456
  header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
1448
1457
  for item in header[iaction]:
@@ -1460,7 +1469,7 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1460
1469
  act_number = iaction + 1
1461
1470
  act_name = f"D{well_number:03d}{segment_number:03d}{act_number:1d}"
1462
1471
  if len(act_name) > 8:
1463
- raise CompletorError("Too many wells and/or too many segments with DAR")
1472
+ raise CompletorError("Too many wells and/or too many segments with DENSITY")
1464
1473
  action += (
1465
1474
  f"ACTIONX\n{act_name} 1000000 /\n"
1466
1475
  f"SGHF '{well_name}' {segment_number} "
@@ -1468,7 +1477,7 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1468
1477
  f"SUVTRIG '{well_name}' {segment_number} "
1469
1478
  f"= {suvtrig[iaction]} /\n/\n\n"
1470
1479
  )
1471
- print_df = df_wsegdar[df_wsegdar[Headers.START_SEGMENT_NUMBER] == segment_number]
1480
+ print_df = df_wsegdensity[df_wsegdensity[Headers.START_SEGMENT_NUMBER] == segment_number]
1472
1481
  print_df = print_df[header[iaction]] # type: ignore
1473
1482
  header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
1474
1483
  for item in header[iaction]:
@@ -1483,7 +1492,7 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1483
1492
  act_number = iaction + 1
1484
1493
  act_name = f"D{well_number:03d}{segment_number:03d}{act_number:1d}"
1485
1494
  if len(act_name) > 8:
1486
- raise CompletorError("Too many wells and/or too many segments with DAR")
1495
+ raise CompletorError("Too many wells and/or too many segments with DENSITY")
1487
1496
  action += (
1488
1497
  f"ACTIONX\n{act_name} 1000000 /\n"
1489
1498
  f"SWHF '{well_name}' {segment_number} "
@@ -1491,7 +1500,7 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1491
1500
  f"SUVTRIG '{well_name}' {segment_number} "
1492
1501
  f"= {suvtrig[iaction]} /\n/\n\n"
1493
1502
  )
1494
- print_df = df_wsegdar[df_wsegdar[Headers.START_SEGMENT_NUMBER] == segment_number]
1503
+ print_df = df_wsegdensity[df_wsegdensity[Headers.START_SEGMENT_NUMBER] == segment_number]
1495
1504
  print_df = print_df[header[iaction]] # type: ignore
1496
1505
  header_string = Keywords.WELL_SEGMENTS_VALVE + "\n--"
1497
1506
  for item in header[iaction]:
@@ -1504,18 +1513,18 @@ def print_wsegdar(df_wsegdar: pd.DataFrame, well_number: int) -> str:
1504
1513
  return action
1505
1514
 
1506
1515
 
1507
- def print_wsegaicv(df_wsegaicv: pd.DataFrame, well_number: int) -> str:
1508
- """Print for AICV devices.
1516
+ def print_wsegdualrcp(df_wsegdualrcp: pd.DataFrame, well_number: int) -> str:
1517
+ """Print for DUALRCP devices.
1509
1518
 
1510
1519
  Args:
1511
- df_wsegaicv: Output from function prepare_wsegaicv.
1520
+ df_wsegdualrcp: Output from function prepare_wsegdualrcp.
1512
1521
  well_number: Well number.
1513
1522
 
1514
1523
  Returns:
1515
1524
  Formatted actions to be included in the output file.
1516
1525
 
1517
1526
  Raises:
1518
- CompletorError: If there are too many wells and/or segments with AICV.
1527
+ CompletorError: If there are too many wells and/or segments with DUALRCP.
1519
1528
  """
1520
1529
  header = [
1521
1530
  [
@@ -1583,17 +1592,17 @@ def print_wsegaicv(df_wsegaicv: pd.DataFrame, well_number: int) -> str:
1583
1592
  sign_gas = ["<", ">="]
1584
1593
  operator = ["AND", "OR"]
1585
1594
  action = ""
1586
- for idx in range(df_wsegaicv.shape[0]):
1587
- segment_number = df_wsegaicv[Headers.START_SEGMENT_NUMBER].iloc[idx]
1588
- well_name = df_wsegaicv[Headers.WELL].iloc[idx]
1589
- wct = df_wsegaicv[Headers.AICV_WATER_CUT].iloc[idx]
1590
- ghf = df_wsegaicv[Headers.AICV_GAS_HOLDUP_FRACTION].iloc[idx]
1595
+ for idx in range(df_wsegdualrcp.shape[0]):
1596
+ segment_number = df_wsegdualrcp[Headers.START_SEGMENT_NUMBER].iloc[idx]
1597
+ well_name = df_wsegdualrcp[Headers.WELL].iloc[idx]
1598
+ wct = df_wsegdualrcp[Headers.DUALRCP_WATER_CUT].iloc[idx]
1599
+ ghf = df_wsegdualrcp[Headers.DUALRCP_GAS_HOLDUP_FRACTION].iloc[idx]
1591
1600
  # LOWWCT_LOWGHF
1592
1601
  for iaction in range(2):
1593
1602
  act_number = iaction + 1
1594
1603
  act_name = f"V{well_number:03d}{segment_number:03d}{act_number:1d}"
1595
1604
  if len(act_name) > 8:
1596
- raise CompletorError("Too many wells and/or too many segments with AICV")
1605
+ raise CompletorError("Too many wells and/or too many segments with DUALRCP")
1597
1606
  action += (
1598
1607
  f"ACTIONX\n{act_name} 1000000 /\n"
1599
1608
  f"SUWCT '{well_name}' {segment_number} {sign_water[iaction]} "
@@ -1601,7 +1610,7 @@ def print_wsegaicv(df_wsegaicv: pd.DataFrame, well_number: int) -> str:
1601
1610
  f"SGHF '{well_name}' {segment_number} {sign_gas[iaction]} {ghf} /\n/\n"
1602
1611
  )
1603
1612
 
1604
- print_df = df_wsegaicv[df_wsegaicv[Headers.START_SEGMENT_NUMBER] == segment_number]
1613
+ print_df = df_wsegdualrcp[df_wsegdualrcp[Headers.START_SEGMENT_NUMBER] == segment_number]
1605
1614
  print_df = print_df[header[iaction]]
1606
1615
  print_df.columns = new_column
1607
1616
  print_df = Keywords.AUTONOMOUS_INFLOW_CONTROL_DEVICE + "\n" + dataframe_tostring(print_df, True)
@@ -47,8 +47,8 @@ class ReadCasefile:
47
47
 
48
48
  This class reads the case/input file of the Completor program.
49
49
  It reads the following keywords:
50
- SCHEDULE_FILE, OUT_FILE, COMPLETION, SEGMENTLENGTH, JOINTLENGTH AUTONOMOUS_INFLOW_CONTROL_DEVICE, WELL_SEGMENTS_VALVE,
51
- INFLOW_CONTROL_DEVICE, DENSITY_ACTIVATED_RECOVERY, AUTONOMOUS_INFLOW_CONTROL_VALVE, INFLOW_CONTROL_VALVE, PVTFILE, PVTTABLE.
50
+ COMPLETION, SEGMENTLENGTH, JOINTLENGTH, AUTONOMOUS_INFLOW_CONTROL_DEVICE, WELL_SEGMENTS_VALVE,
51
+ INFLOW_CONTROL_DEVICE, DENSITY_DRIVEN, 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:
@@ -63,8 +63,8 @@ class ReadCasefile:
63
63
  wsegsicd_table (pd.DataFrame): INFLOW_CONTROL_DEVICE.
64
64
  wsegvalv_table (pd.DataFrame): WELL_SEGMENTS_VALVE.
65
65
  wsegicv_table (pd.DataFrame): INFLOW_CONTROL_VALVE.
66
- wsegdar_table (pd.DataFrame): DENSITY_ACTIVATED_RECOVERY.
67
- wsegaicv_table (pd.DataFrame): AUTONOMOUS_INFLOW_CONTROL_VALVE.
66
+ wsegdensity_table (pd.DataFrame): DENSITY_DRIVEN.
67
+ wsegdualrcp_table (pd.DataFrame): DUAL_RATE_CONTROLLED_PRODUCTION.
68
68
  strict (bool): USE_STRICT. If TRUE it will exit if any lateral is not defined in the case-file. Default to TRUE.
69
69
  lat2device (pd.DataFrame): LATERAL_TO_DEVICE.
70
70
  gp_perf_devicelayer (bool): GRAVEL_PACKED_PERFORATED_DEVICELAYER. If TRUE all wells with
@@ -98,8 +98,8 @@ class ReadCasefile:
98
98
  self.wsegaicd_table = pd.DataFrame()
99
99
  self.wsegsicd_table = pd.DataFrame()
100
100
  self.wsegvalv_table = pd.DataFrame()
101
- self.wsegdar_table = pd.DataFrame()
102
- self.wsegaicv_table = pd.DataFrame()
101
+ self.wsegdensity_table = pd.DataFrame()
102
+ self.wsegdualrcp_table = pd.DataFrame()
103
103
  self.wsegicv_table = pd.DataFrame()
104
104
  self.lat2device = pd.DataFrame()
105
105
  self.mapfile: pd.DataFrame | str | None = None
@@ -116,8 +116,8 @@ class ReadCasefile:
116
116
  self.read_wsegaicd()
117
117
  self.read_wsegvalv()
118
118
  self.read_wsegsicd()
119
- self.read_wsegdar()
120
- self.read_wsegaicv()
119
+ self.read_wsegdensity()
120
+ self.read_wsegdualrcp()
121
121
  self.read_wsegicv()
122
122
  self.read_lat2device()
123
123
  self.read_minimum_segment_length()
@@ -155,6 +155,10 @@ class ReadCasefile:
155
155
  df_temp = input_validation.check_default_non_packer(df_temp)
156
156
  # Fix the data types format
157
157
  df_temp = input_validation.set_format_completion(df_temp)
158
+ # Fix the Density based
159
+ df_temp = input_validation.set_density_based(df_temp)
160
+ # Fix the Dual RCP
161
+ df_temp = input_validation.set_dualrcp(df_temp)
158
162
  # Check overall user inputs on completion
159
163
  input_validation.assess_completion(df_temp)
160
164
  df_temp = self.read_icv_tubing(df_temp)
@@ -457,19 +461,25 @@ class ReadCasefile:
457
461
  f"Not all device in COMPLETION is specified in {Keywords.AUTONOMOUS_INFLOW_CONTROL_DEVICE}"
458
462
  )
459
463
 
460
- def read_wsegdar(self) -> None:
461
- """Read the DENSITY_ACTIVATED_RECOVERY keyword in the case file.
464
+ def read_wsegdensity(self) -> None:
465
+ """Read the DENSITY keyword in the case file.
462
466
 
463
467
  Raises:
464
- ValueError: If there are invalid entries in DENSITY_ACTIVATED_RECOVERY.
465
- CompletorError: If not all device in COMPLETION is specified in DENSITY_ACTIVATED_RECOVERY.
466
- If DENSITY_ACTIVATED_RECOVERY keyword not defined, when DAR is used in the completion.
468
+ ValueError: If there are invalid entries in DENSITY.
469
+ CompletorError: If not all device in COMPLETION is specified in DENSITY.
470
+ If DENSITY keyword not defined, when DENSITY is used in the completion.
467
471
  """
468
- start_index, end_index = parse.locate_keyword(self.content, Keywords.DENSITY_ACTIVATED_RECOVERY)
469
- if start_index == end_index:
470
- if Content.DENSITY_ACTIVATED_RECOVERY in self.completion_table[Headers.DEVICE_TYPE]:
472
+ density_index_start, density_index_end = parse.locate_keyword(self.content, Keywords.DENSITY)
473
+ dar_index_start, dar_index_end = parse.locate_keyword(self.content, Keywords.DENSITY_ACTIVATED_RECOVERY)
474
+
475
+ # Determine which keyword is present
476
+ if density_index_start == density_index_end and dar_index_start == dar_index_end:
477
+ if (
478
+ Content.DENSITY in self.completion_table[Headers.DEVICE_TYPE]
479
+ or Content.DENSITY_ACTIVATED_RECOVERY in self.completion_table[Headers.DEVICE_TYPE]
480
+ ):
471
481
  raise CompletorError(
472
- f"{Keywords.DENSITY_ACTIVATED_RECOVERY} keyword must be defined, if DAR is used in the completion"
482
+ f"{Keywords.DENSITY} keyword must be defined, if DENSITY is used in the completion."
473
483
  )
474
484
  else:
475
485
  # Table headers
@@ -485,42 +495,56 @@ class ReadCasefile:
485
495
  Headers.GAS_HOLDUP_FRACTION_HIGH_CUTOFF,
486
496
  ]
487
497
 
498
+ # Get start and end index from correct keyword
499
+ if not density_index_start == density_index_end:
500
+ start_index, end_index = density_index_start, density_index_end
501
+ key = Keywords.DENSITY
502
+ content = Content.DENSITY
503
+ else:
504
+ start_index, end_index = dar_index_start, dar_index_end
505
+ key = Keywords.DENSITY_ACTIVATED_RECOVERY
506
+ content = Content.DENSITY_ACTIVATED_RECOVERY
488
507
  # Fix table format
489
- if self.completion_table[Headers.DEVICE_TYPE].str.contains(Content.DENSITY_ACTIVATED_RECOVERY).any():
490
- self.wsegdar_table = input_validation.set_format_wsegdar(
491
- self._create_dataframe_with_columns(header, start_index, end_index)
492
- )
493
- device_checks = self.completion_table[
494
- self.completion_table[Headers.DEVICE_TYPE] == Content.DENSITY_ACTIVATED_RECOVERY
495
- ][Headers.DEVICE_NUMBER].to_numpy()
496
- if not check_contents(device_checks, self.wsegdar_table[Headers.DEVICE_NUMBER].to_numpy()):
497
- raise CompletorError(
498
- f"Not all device in COMPLETION is specified in {Keywords.DENSITY_ACTIVATED_RECOVERY}"
499
- )
508
+ self.wsegdensity_table = input_validation.set_format_wsegdensity(
509
+ self._create_dataframe_with_columns(header, start_index, end_index)
510
+ )
511
+ device_checks = self.completion_table[self.completion_table[Headers.DEVICE_TYPE] == content][
512
+ Headers.DEVICE_NUMBER
513
+ ].to_numpy()
514
+ if not check_contents(device_checks, self.wsegdensity_table[Headers.DEVICE_NUMBER].to_numpy()):
515
+ raise CompletorError(f"Not all device in COMPLETION is specified in {key}")
500
516
 
501
- def read_wsegaicv(self) -> None:
502
- """Read the AUTONOMOUS_INFLOW_CONTROL_VALVE keyword in the case file.
517
+ def read_wsegdualrcp(self) -> None:
518
+ """Read the DUALRCP keyword in the case file.
503
519
 
504
520
  Raises:
505
- ValueError: If invalid entries in AUTONOMOUS_INFLOW_CONTROL_VALVE.
506
- CompletorError: AUTONOMOUS_INFLOW_CONTROL_VALVE keyword not defined when AICV is used in completion.
507
- If all devices in COMPLETION are not specified in AUTONOMOUS_INFLOW_CONTROL_VALVE.
521
+ ValueError: If invalid entries in DUALRCP.
522
+ CompletorError: DUALRCP keyword not defined when DUALRCP is used in completion.
523
+ If all devices in COMPLETION are not specified in DUALRCP.
508
524
  """
509
- start_index, end_index = parse.locate_keyword(self.content, Keywords.AUTONOMOUS_INFLOW_CONTROL_VALVE)
510
- if start_index == end_index:
511
- if Content.AUTONOMOUS_INFLOW_CONTROL_VALVE in self.completion_table[Headers.DEVICE_TYPE]:
525
+ dualrcp_index_start, dualrcp_index_end = parse.locate_keyword(
526
+ self.content, Keywords.DUAL_RATE_CONTROLLED_PRODUCTION
527
+ )
528
+ aicv_index_start, aicv_index_end = parse.locate_keyword(self.content, Keywords.AUTONOMOUS_INFLOW_CONTROL_VALVE)
529
+
530
+ # Determine which keyword is present
531
+ if dualrcp_index_start == dualrcp_index_end and aicv_index_start == aicv_index_end:
532
+ if (
533
+ Content.DUAL_RATE_CONTROLLED_PRODUCTION in self.completion_table[Headers.DEVICE_TYPE]
534
+ or Content.AUTONOMOUS_INFLOW_CONTROL_VALVE in self.completion_table[Headers.DEVICE_TYPE]
535
+ ):
512
536
  raise CompletorError(
513
- f"{Keywords.AUTONOMOUS_INFLOW_CONTROL_VALVE} keyword must be defined, "
514
- "if AICV is used in the completion."
537
+ f"{Keywords.DUAL_RATE_CONTROLLED_PRODUCTION} keyword must be defined, "
538
+ "if DUALRCP is used in the completion."
515
539
  )
516
540
  else:
517
541
  # Table headers
518
542
  header = [
519
543
  Headers.DEVICE_NUMBER,
520
- Headers.AICV_WATER_CUT,
521
- Headers.AICV_GAS_HOLDUP_FRACTION,
522
- Headers.AICV_CALIBRATION_FLUID_DENSITY,
523
- Headers.AICV_FLUID_VISCOSITY,
544
+ Headers.DUALRCP_WATER_CUT,
545
+ Headers.DUALRCP_GAS_HOLDUP_FRACTION,
546
+ Headers.DUALRCP_CALIBRATION_FLUID_DENSITY,
547
+ Headers.DUALRCP_FLUID_VISCOSITY,
524
548
  Headers.ALPHA_MAIN,
525
549
  Headers.X_MAIN,
526
550
  Headers.Y_MAIN,
@@ -540,18 +564,25 @@ class ReadCasefile:
540
564
  Headers.E_PILOT,
541
565
  Headers.F_PILOT,
542
566
  ]
567
+ # Get start and end index from correct keyword
568
+ if not dualrcp_index_start == dualrcp_index_end:
569
+ start_index, end_index = dualrcp_index_start, dualrcp_index_end
570
+ key = Keywords.DUAL_RATE_CONTROLLED_PRODUCTION
571
+ content = Content.DUAL_RATE_CONTROLLED_PRODUCTION
572
+ else:
573
+ start_index, end_index = aicv_index_start, aicv_index_end
574
+ key = Keywords.AUTONOMOUS_INFLOW_CONTROL_VALVE
575
+ content = Content.AUTONOMOUS_INFLOW_CONTROL_VALVE
543
576
  # Fix table format
544
- self.wsegaicv_table = input_validation.set_format_wsegaicv(
577
+ self.wsegdualrcp_table = input_validation.set_format_wsegdualrcp(
545
578
  self._create_dataframe_with_columns(header, start_index, end_index)
546
579
  )
547
- # Check if the device in COMPLETION is exist in AUTONOMOUS_INFLOW_CONTROL_VALVE
548
- device_checks = self.completion_table[
549
- self.completion_table[Headers.DEVICE_TYPE] == Content.AUTONOMOUS_INFLOW_CONTROL_VALVE
550
- ][Headers.DEVICE_NUMBER].to_numpy()
551
- if not check_contents(device_checks, self.wsegaicv_table[Headers.DEVICE_NUMBER].to_numpy()):
552
- raise CompletorError(
553
- f"Not all devices in COMPLETION are specified in {Keywords.AUTONOMOUS_INFLOW_CONTROL_VALVE}"
554
- )
580
+ # Check if the device in COMPLETION is exist in DUALRCP
581
+ device_checks = self.completion_table[self.completion_table[Headers.DEVICE_TYPE] == content][
582
+ Headers.DEVICE_NUMBER
583
+ ].to_numpy()
584
+ if not check_contents(device_checks, self.wsegdualrcp_table[Headers.DEVICE_NUMBER].to_numpy()):
585
+ raise CompletorError(f"Not all devices in COMPLETION are specified in {key}")
555
586
 
556
587
  def read_wsegicv(self) -> None:
557
588
  """Read INFLOW_CONTROL_VALVE keyword in the case file.
completor/utils.py CHANGED
@@ -191,8 +191,8 @@ def get_active_wells(completion_table: pd.DataFrame, gp_perf_devicelayer: bool)
191
191
  perf_check = completion_table[Headers.DEVICE_TYPE].isin(
192
192
  [
193
193
  Content.AUTONOMOUS_INFLOW_CONTROL_DEVICE,
194
- Content.AUTONOMOUS_INFLOW_CONTROL_VALVE,
195
- Content.DENSITY_ACTIVATED_RECOVERY,
194
+ Content.DUAL_RATE_CONTROLLED_PRODUCTION,
195
+ Content.DENSITY,
196
196
  Content.INFLOW_CONTROL_DEVICE,
197
197
  Content.VALVE,
198
198
  Content.INFLOW_CONTROL_VALVE,
@@ -46,9 +46,9 @@ def visualize_device(axs: Axes, df_well: pd.DataFrame) -> Axes:
46
46
  axs.plot(xpar, ypar, "rs-", markevery=[1])
47
47
  elif df_device[Headers.DEVICE_TYPE].iloc[idx] == Content.VALVE:
48
48
  axs.plot(xpar, ypar, "rv-", markevery=[1])
49
- elif df_device[Headers.DEVICE_TYPE].iloc[idx] == Content.DENSITY_ACTIVATED_RECOVERY:
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.AUTONOMOUS_INFLOW_CONTROL_VALVE:
51
+ elif df_device[Headers.DEVICE_TYPE].iloc[idx] == Content.DUAL_RATE_CONTROLLED_PRODUCTION:
52
52
  axs.plot(xpar, ypar, "r*-", markevery=[1])
53
53
  return axs
54
54
 
completor/wells.py CHANGED
@@ -218,10 +218,10 @@ class Lateral:
218
218
  df_well = completion.get_device(df_well, case.wsegsicd_table, Content.INFLOW_CONTROL_DEVICE)
219
219
  if Content.AUTONOMOUS_INFLOW_CONTROL_DEVICE in active_devices:
220
220
  df_well = completion.get_device(df_well, case.wsegaicd_table, Content.AUTONOMOUS_INFLOW_CONTROL_DEVICE)
221
- if Content.DENSITY_ACTIVATED_RECOVERY in active_devices:
222
- df_well = completion.get_device(df_well, case.wsegdar_table, Content.DENSITY_ACTIVATED_RECOVERY)
223
- if Content.AUTONOMOUS_INFLOW_CONTROL_VALVE in active_devices:
224
- df_well = completion.get_device(df_well, case.wsegaicv_table, Content.AUTONOMOUS_INFLOW_CONTROL_VALVE)
221
+ if Content.DENSITY in active_devices:
222
+ df_well = completion.get_device(df_well, case.wsegdensity_table, Content.DENSITY)
223
+ if Content.DUAL_RATE_CONTROLLED_PRODUCTION in active_devices:
224
+ df_well = completion.get_device(df_well, case.wsegdualrcp_table, Content.DUAL_RATE_CONTROLLED_PRODUCTION)
225
225
  if Content.INFLOW_CONTROL_VALVE in active_devices:
226
226
  df_well = completion.get_device(df_well, case.wsegicv_table, Content.INFLOW_CONTROL_VALVE)
227
227
  return df_well
@@ -1,28 +1,30 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: completor
3
- Version: 1.1.1
4
- Summary: Advanced mulit-segmented well completion tool.
3
+ Version: 1.1.3
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,<3.12
9
+ Requires-Python: >=3.11,<4.0
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
+ Classifier: Programming Language :: Python :: 3.12
15
16
  Provides-Extra: ert
16
- Requires-Dist: docutils (==0.20.1) ; extra == "ert"
17
- Requires-Dist: ert (>11.1.0) ; extra == "ert"
18
- Requires-Dist: matplotlib (>=3.6,<4.0)
19
- Requires-Dist: numpy (<2)
20
- Requires-Dist: pandas (>=2.1.4,<3.0.0)
21
- Requires-Dist: pyqt5-qt5 (==5.15.2) ; extra == "ert"
22
- Requires-Dist: pytest-env (>=1,<2)
23
- Requires-Dist: rstcheck-core (>=1.2.1,<2.0.0) ; extra == "ert"
24
- Requires-Dist: scipy (>=1.10,<2.0)
25
- Requires-Dist: tqdm (>=4.50,<5.0)
17
+ Provides-Extra: test
18
+ Requires-Dist: ert (>=12,<13) ; extra == "ert"
19
+ Requires-Dist: matplotlib (>=3.9,<4.0)
20
+ Requires-Dist: numpy (>=1.26,<3.0)
21
+ Requires-Dist: pandas (>=2.2,<3.0)
22
+ Requires-Dist: pytest (>=8.3,<9.0) ; extra == "test"
23
+ Requires-Dist: pytest-env (>=1,<2) ; extra == "test"
24
+ Requires-Dist: pytest-xdist (>=3.6,<4.0) ; extra == "test"
25
+ Requires-Dist: rstcheck-core (>=1.2,<2.0) ; extra == "test"
26
+ Requires-Dist: scipy (>=1.14,<2.0)
27
+ Requires-Dist: tqdm (>=4.66,<5.0)
26
28
  Project-URL: Bug Tracker, https://github.com/equinor/completor/issues
27
29
  Project-URL: Documentation, https://equinor.github.io/completor
28
30
  Project-URL: Repository, https://github.com/equinor/completor
@@ -1,27 +1,27 @@
1
1
  completor/__init__.py,sha256=k6amf7jhp7KkBIlaw93-NZITxyZjPSzA5McFAZh8yv8,76
2
- completor/completion.py,sha256=COtRZpEdmuf3X_uOvEYYLz428nQSn1Z8QH-7TTREyus,30485
2
+ completor/completion.py,sha256=--c2tN1ItE8r7YjxxOrTeZ71tz0KCVStxzWkjU-ERy4,30925
3
3
  completor/config_jobs/run_completor,sha256=XePKj2xocfGF0XFRqr7sqfpZGrjgWcfaZLHIhVvGFCQ,600
4
- completor/constants.py,sha256=Th7fzID5NPUhyV2RRc5h9qRQ963cKGT3TVCX_bsAtHA,12802
5
- completor/create_output.py,sha256=3IIndoE0aE1ZTKVnjMLi56mJLVbgrYTWkEJs4XkqZDU,23028
4
+ completor/constants.py,sha256=N1u1SrsZap8hSvd4Cs9LCsNZBBIJy_3P2wd9djdTrgg,13028
5
+ completor/create_output.py,sha256=T9W_uNdPzPkW1IyTAXWV38hF8ZvZs5ZrmrxvNHuS-mM,22909
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=OGY5oCdctlqzeg5Z2l4cmRb3ITtSjLp1Ufp0Joj7aKA,13495
11
+ completor/input_validation.py,sha256=jNqYeAZFxrGJy5-xwK-n1Y0t9EKvJ12aA_z6yzN3N5E,14315
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=fenEo3UfDzXF4jaxi9vDI-g-BkYSti0LxILJf7lO84A,72081
17
- completor/read_casefile.py,sha256=ZJj-xrpcTeagJmqqi72UIOIcq9uQJaEZClbCA1lW4yw,34081
16
+ completor/prepare_outputs.py,sha256=GAQsRFrz7SwilExCq0w6f1tZE-4TmpHIeMS6_CwdbCM,72547
17
+ completor/read_casefile.py,sha256=ToE7wGh0bKlS8hNFlRN21sPAufPuhRAvadkZGwB2ky4,35452
18
18
  completor/read_schedule.py,sha256=IYyCubOggFGg664h1flTl7MUJhJWyibr6JsptnURjUA,18101
19
- completor/utils.py,sha256=JFzTvt4wLZm-VUoamneQgUBVfdoPJmNAlgdQ80qOL5Y,13576
19
+ completor/utils.py,sha256=ieqgLXfjbjDXHHSW283bliznj04Qep5KRUYGi_BXQRI,13557
20
20
  completor/visualization.py,sha256=ObxThqIyW3fsvVIupxVsgySFI_54n_Di-HTzFtDMSgo,4580
21
- completor/visualize_well.py,sha256=I2kp2rnM2eFV4RUWnTTysPTqQKNEBicF2S9Z3rrAsNA,8672
22
- completor/wells.py,sha256=oj3e65tSIDFJEpfOKkr_j4H3RyFKpdjZBAcef7sUoaY,12124
23
- completor-1.1.1.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
24
- completor-1.1.1.dist-info/METADATA,sha256=TIfdCVY0R8QPFW2nNseFcfgflD7GVu-vNKwP8VcRU_c,7880
25
- completor-1.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
26
- completor-1.1.1.dist-info/entry_points.txt,sha256=co5L2_CC2QQWVdEALeMp-NIC4mx4nRpcLcvpVXMYdeI,106
27
- completor-1.1.1.dist-info/RECORD,,
21
+ completor/visualize_well.py,sha256=fkrjlEtSLsRrmSHoPYtCKIrCeEvXg4LsYyEEPryAB0I,8653
22
+ completor/wells.py,sha256=GgZyfRa5wpSMIJUl5CPi5F1zdmU0XK6QjSduTzuh2NI,12093
23
+ completor-1.1.3.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
24
+ completor-1.1.3.dist-info/METADATA,sha256=TAE2gJSk-z2H0sRan100EzToaDlrisCAdlo_jVOVFzA,7979
25
+ completor-1.1.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
26
+ completor-1.1.3.dist-info/entry_points.txt,sha256=co5L2_CC2QQWVdEALeMp-NIC4mx4nRpcLcvpVXMYdeI,106
27
+ completor-1.1.3.dist-info/RECORD,,