completor 1.4.0__py3-none-any.whl → 1.5.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/main.py CHANGED
@@ -7,6 +7,7 @@ import os
7
7
  import re
8
8
  import sys
9
9
  import time
10
+ from pathlib import Path
10
11
 
11
12
  from matplotlib.backends.backend_pdf import PdfPages # type: ignore
12
13
  from tqdm import tqdm
@@ -15,15 +16,18 @@ from completor import create_output, parse, read_schedule, utils
15
16
  from completor.constants import Keywords, ScheduleData
16
17
  from completor.exceptions.clean_exceptions import CompletorError
17
18
  from completor.get_version import get_version
19
+ from completor.icv_file_handling import IcvFileHandling
20
+ from completor.initialization import Initialization
18
21
  from completor.launch_args_parser import get_parser
19
22
  from completor.logger import handle_error_messages, logger
20
- from completor.read_casefile import ReadCasefile
23
+ from completor.read_casefile import ICVReadCasefile, ReadCasefile
21
24
  from completor.utils import (
22
- abort,
23
25
  clean_file_lines,
24
26
  clean_raw_data,
27
+ completion_keyword_in_file,
25
28
  find_keyword_data,
26
29
  find_well_keyword_data,
30
+ icvc_keyword_in_file,
27
31
  replace_preprocessing_names,
28
32
  )
29
33
  from completor.wells import Well
@@ -76,7 +80,7 @@ def get_content_and_path(case_content: str, file_path: str | None, keyword: str)
76
80
 
77
81
  def create(
78
82
  case_file: str, schedule: str, new_file: str, show_fig: bool = False, paths: tuple[str, str] | None = None
79
- ) -> tuple[ReadCasefile, Well | None]:
83
+ ) -> tuple[ReadCasefile, Well | None, list[tuple[str, int]]]:
80
84
  """Create and write the advanced schedule file from input case- and schedule files.
81
85
 
82
86
  Args:
@@ -87,10 +91,13 @@ def create(
87
91
  paths: Optional additional paths.
88
92
 
89
93
  Returns:
90
- The case and schedule file, the well and output object.
94
+ - ReadCasefile object.
95
+ - Well object or None if no well was found.
96
+ - Well segment list or None if no update of segment list.
91
97
  """
92
98
  case = ReadCasefile(case_file=case_file, schedule_file=schedule, output_file=new_file)
93
99
  active_wells = utils.get_active_wells(case.completion_table, case.gp_perf_devicelayer)
100
+ well_segment_list: list[tuple[str, int]] = []
94
101
  pdf = None
95
102
  figure_name = None
96
103
  if show_fig:
@@ -109,6 +116,7 @@ def create(
109
116
  schedule = re.sub(r"[^\S\r\n]+$", "", schedule, flags=re.MULTILINE)
110
117
  meaningful_data: ScheduleData = {}
111
118
 
119
+ well_segment_list = []
112
120
  try:
113
121
  # Find the old data for each of the four main keywords.
114
122
  for chunk in find_keyword_data(Keywords.WELL_SPECIFICATION, schedule):
@@ -132,7 +140,9 @@ def create(
132
140
  except KeyError:
133
141
  logger.warning(f"Well '{well_name}' is written in case file but does not exist in schedule file.")
134
142
  continue
135
- compdat, welsegs, compsegs, bonus = create_output.format_output(well, case, pdf)
143
+ compdat, welsegs, compsegs, bonus, df_icv = create_output.format_output(well, case, pdf)
144
+ if len(df_icv) > 0:
145
+ get_icv_segment(well_segment_list, df_icv)
136
146
  for keyword in [Keywords.COMPLETION_SEGMENTS, Keywords.WELL_SEGMENTS, Keywords.COMPLETION_DATA]:
137
147
  old_data = find_well_keyword_data(well_name, keyword, schedule)
138
148
  if not old_data:
@@ -166,7 +176,14 @@ def create(
166
176
  if err is not None:
167
177
  raise err
168
178
 
169
- return case, well
179
+ return case, well, well_segment_list
180
+
181
+
182
+ def get_icv_segment(well_segment_list, icv_dataframe):
183
+ for row in range(len(icv_dataframe)):
184
+ well_name = icv_dataframe.iloc[row]["WELL"]
185
+ segment_number = int(icv_dataframe.iloc[row]["START_SEGMENT_NUMBER"])
186
+ well_segment_list.append((well_name, segment_number))
170
187
 
171
188
 
172
189
  def main() -> None:
@@ -197,18 +214,17 @@ def main() -> None:
197
214
  schedule_file_content, inputs.schedulefile = get_content_and_path(
198
215
  case_file_content, inputs.schedulefile, Keywords.SCHEDULE_FILE
199
216
  )
200
-
201
- if isinstance(schedule_file_content, str):
202
- parse.read_schedule_keywords(clean_file_lines(schedule_file_content.splitlines()), Keywords.main_keywords)
217
+ # If ICVC exists, it should not be mandatory to have whole schedule files
218
+ # Check on both schedule and case files first
219
+ if completion_keyword_in_file(inputs.inputfile) and not icvc_keyword_in_file(inputs.inputfile):
220
+ if isinstance(schedule_file_content, str):
221
+ parse.read_schedule_keywords(clean_file_lines(schedule_file_content.splitlines()), Keywords.main_keywords)
203
222
 
204
223
  _, inputs.outputfile = get_content_and_path(case_file_content, inputs.outputfile, Keywords.OUT_FILE)
205
224
 
206
225
  if inputs.outputfile is None:
207
226
  if inputs.schedulefile is None:
208
- raise ValueError(
209
- "Could not find a path to schedule file. "
210
- f"It must be provided as a input argument or within the case files keyword '{Keywords.SCHEDULE_FILE}'."
211
- )
227
+ raise ValueError("Could not find a path to schedule file. It must be provided as a input argument.")
212
228
  inputs.outputfile = inputs.schedulefile.split(".")[0] + "_advanced.wells"
213
229
 
214
230
  paths_input_schedule = (inputs.inputfile, inputs.schedulefile)
@@ -217,16 +233,69 @@ def main() -> None:
217
233
  logger.debug("-" * 60)
218
234
  start_a = time.time()
219
235
 
220
- handle_error_messages(create)(
236
+ case, well, well_start_segments = handle_error_messages(create)(
221
237
  case_file_content, schedule_file_content, inputs.outputfile, inputs.figure, paths=paths_input_schedule
222
238
  )
239
+ if icvc_keyword_in_file(inputs.inputfile):
240
+ # start running ICV Control
241
+ # the input schedule file to second run of ICV Control is the output file from Completor
242
+ # therefore
243
+
244
+ inputs.schedulefile = inputs.outputfile
245
+ inputs.schedulefile = os.path.abspath(inputs.schedulefile)
246
+
247
+ if inputs.outputfile is not None:
248
+
249
+ schedule_content, inputs.schedulefile = get_content_and_path(
250
+ case_file_content, inputs.schedulefile, Keywords.SCHEDULE_FILE
251
+ )
252
+ inputs.outputfile, inputs.outputdirectory = get_output_filename_and_directory(inputs)
253
+
254
+ if inputs.inputfile is not None:
255
+ create_icvc(case_file_content, schedule_content, inputs, well_start_segments)
223
256
 
224
257
  logger.debug("Total runtime: %d", (time.time() - start_a))
225
258
  logger.debug("-" * 60)
226
259
 
227
260
 
228
- if __name__ == "__main__":
229
- try:
230
- main()
231
- except CompletorError as e:
232
- raise abort(str(e)) from e
261
+ def get_output_filename_and_directory(inputs) -> tuple[str, str]:
262
+ """Get the output filename and directory from the user input.
263
+
264
+ Args:
265
+ arguments: Arguments from the command line.
266
+
267
+ Returns:
268
+ output_filename: The output filename.
269
+ output_directory: The output directory.
270
+ """
271
+ if inputs.outputfile:
272
+ output_path = Path(inputs.outputfile)
273
+ output_filename = f"{output_path.name}"
274
+ else:
275
+ output_path = Path(inputs.schedulefile)
276
+ output_filename = f"{output_path.stem}.sch"
277
+
278
+ # use cwd as output directory if the output_path is just a filename. e.g. output.sch
279
+ output_directory = str(Path.cwd() if output_path.parent == Path(".") else output_path.parent)
280
+ return output_filename, output_directory
281
+
282
+
283
+ def create_icvc(case_content: str, schedule_content: str | None, inputs, new_segments: str):
284
+ """
285
+ Create ICV-control schedule- and include files from input case- and schedule files.
286
+
287
+ Args:
288
+ input_case_content: Input case file.
289
+ schedule_content: Input schedule file.
290
+ arguments: Arguments from the command line.
291
+ """
292
+
293
+ case = ICVReadCasefile(case_content, schedule_content, new_segments)
294
+ initials = Initialization(case, schedule_content)
295
+ file_data = {
296
+ "output_file_name": inputs.outputfile,
297
+ "output_directory": inputs.outputdirectory,
298
+ "schedule_file_path": inputs.schedulefile,
299
+ "input_case_file": inputs.inputfile,
300
+ }
301
+ IcvFileHandling(file_data, initials)
completor/parse.py CHANGED
@@ -338,8 +338,8 @@ def get_welsegs_table(collections: list[ContentCollection]) -> tuple[pd.DataFram
338
338
  try:
339
339
  header_table: npt.NDArray[np.unicode_] | pd.DataFrame
340
340
  record_table: npt.NDArray[np.unicode_] | pd.DataFrame
341
- header_table = np.row_stack((header_table, header_collection))
342
- record_table = np.row_stack((record_table, record_collection))
341
+ header_table = np.vstack((header_table, header_collection))
342
+ record_table = np.vstack((record_table, record_collection))
343
343
  except NameError:
344
344
  # First iteration
345
345
  header_table = np.asarray(header_collection)
@@ -394,7 +394,7 @@ def get_welspecs_table(collections: list[ContentCollection]) -> pd.DataFrame:
394
394
  if welspecs_table is None:
395
395
  welspecs_table = np.copy(the_collection)
396
396
  else:
397
- welspecs_table = np.row_stack((welspecs_table, the_collection))
397
+ welspecs_table = np.vstack((welspecs_table, the_collection))
398
398
 
399
399
  if welspecs_table is None:
400
400
  raise ValueError(f"Collection does not contain the '{Keywords.WELL_SPECIFICATION}' keyword")
@@ -424,7 +424,7 @@ def get_compdat_table(collections: list[ContentCollection]) -> pd.DataFrame:
424
424
  if compdat_table is None:
425
425
  compdat_table = np.copy(the_collection)
426
426
  else:
427
- compdat_table = np.row_stack((compdat_table, the_collection))
427
+ compdat_table = np.vstack((compdat_table, the_collection))
428
428
  if compdat_table is None:
429
429
  raise ValueError(f"Collection does not contain the '{Keywords.COMPLETION_DATA}' keyword")
430
430
  compdat_table = pd.DataFrame(
@@ -472,7 +472,7 @@ def get_compsegs_table(collections: list[ContentCollection]) -> pd.DataFrame:
472
472
  if compsegs_table is None:
473
473
  compsegs_table = np.copy(the_collection)
474
474
  else:
475
- compsegs_table = np.row_stack((compsegs_table, the_collection))
475
+ compsegs_table = np.vstack((compsegs_table, the_collection))
476
476
 
477
477
  if compsegs_table is None:
478
478
  raise ValueError(f"Collection does not contain the '{Keywords.COMPLETION_SEGMENTS}' keyword")