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/utils.py CHANGED
@@ -5,13 +5,14 @@ from __future__ import annotations
5
5
  import re
6
6
  import sys
7
7
  from collections.abc import Mapping
8
+ from pathlib import Path
8
9
  from typing import Any
9
10
 
10
11
  import numpy as np
11
12
  import numpy.typing as npt
12
13
  import pandas as pd
13
14
 
14
- from completor.constants import Content, Headers, Keywords
15
+ from completor.constants import Content, Headers, ICVMethod, Keywords
15
16
  from completor.exceptions.clean_exceptions import CompletorError
16
17
  from completor.logger import logger
17
18
 
@@ -234,7 +235,7 @@ def check_width_lines(result: str, limit: int) -> list[tuple[int, str]]:
234
235
  cleaned_line = cleaned_line.rsplit("--")[0]
235
236
 
236
237
  if len(cleaned_line) > limit:
237
- too_long_lines.append((line_index, lines[line_index]))
238
+ too_long_lines.append((int(line_index), lines[line_index]))
238
239
  return too_long_lines
239
240
 
240
241
 
@@ -386,3 +387,133 @@ def replace_preprocessing_names(text: str, mapper: Mapping[str, str] | None) ->
386
387
  my_value = start + str(value) + end
387
388
  text = text.replace(my_key, my_value)
388
389
  return text
390
+
391
+
392
+ def sort_string_with_assign_first(input_string: str) -> str:
393
+ """Sort string such that lines starting with "ASSIGN" come before other lines preserving remaining lines.
394
+
395
+ Args:
396
+ input_string: The input string to be sorted.
397
+
398
+ Returns:
399
+ String starting with "ASSIGN" appearing before other lines.
400
+ """
401
+
402
+ assign_lines = []
403
+ other_lines = []
404
+ for line in input_string.splitlines():
405
+ if line.lstrip().startswith("ASSIGN"):
406
+ assign_lines.append(line)
407
+ elif line.strip() != "":
408
+ other_lines.append(line)
409
+
410
+ sorted_lines = assign_lines + other_lines
411
+ return "\n".join(sorted_lines) + "\n"
412
+
413
+
414
+ def reduce_newlines(data: str) -> str:
415
+ """Reduces consecutive occurrences of three or more newline characters to just two newline characters.
416
+
417
+ Args:
418
+ data: String to process.
419
+
420
+ Returns:
421
+ The processed string with reduced newline characters.
422
+ """
423
+
424
+ return re.sub(r"\n{3}", r"\n\n", data)
425
+
426
+
427
+ def remove_duplicates(data: list[str]) -> list[str]:
428
+ """Remove duplicates from a list while preserving the original order.
429
+
430
+ Exclude empty strings from the resulting list.
431
+
432
+ Args:
433
+ data: The input list.
434
+
435
+ Returns:
436
+ The data with duplicates removed inline.
437
+ """
438
+
439
+ return [x for x in dict.fromkeys(data) if x]
440
+
441
+
442
+ def insert_comment_custom_content() -> str:
443
+ """Writes a comment to schedule when loglevel is <= 10.
444
+
445
+ Returns:
446
+ A string to be inserted before the output in format:
447
+ "METHOD_NAME with step 'STEP' and criteria 'CRITERIA'."
448
+ """
449
+
450
+ if logger.level > 10:
451
+ return ""
452
+ return "\n -- This is custom content from CONTROL_CRITERIA keyword:\n"
453
+
454
+
455
+ def insert_comment(method: str | ICVMethod, step: str | int | None = None, criteria: str | int | None = None) -> str:
456
+ """Writes a comment to schedule when loglevel is <= 10.
457
+
458
+ Args:
459
+ method: The method that is producing the current output.
460
+ step: The current step (if applicable).
461
+ criteria: The current criteria (if applicable).
462
+
463
+ Returns:
464
+ A string to be inserted before the output in format:
465
+ "METHOD_NAME with step 'STEP' and criteria 'CRITERIA'."
466
+ """
467
+
468
+ if logger.level > 10:
469
+ return ""
470
+ msg = f"-- {ICVMethod(method).name}"
471
+ if step is not None:
472
+ msg += f" with step '{step}'"
473
+ if criteria is not None:
474
+ if step is None:
475
+ msg += " with"
476
+ else:
477
+ msg += " and"
478
+ msg += f" criteria '{criteria}'"
479
+ return msg + ".\n"
480
+
481
+
482
+ def icvc_keyword_in_file(path: Path | str) -> bool:
483
+ """If file contains ICV keyword.
484
+
485
+ Args:
486
+ path: Path to file to check.
487
+
488
+ Returns:
489
+ True if file contains ICV keyword.
490
+ """
491
+
492
+ path = Path(path)
493
+ with open(path, encoding="utf-8") as file:
494
+ case_file_content = file.read()
495
+
496
+ if Keywords.ICVC_KEYWORD in case_file_content:
497
+ return True
498
+ else:
499
+ return False
500
+
501
+
502
+ def completion_keyword_in_file(path: Path | str) -> bool:
503
+ """If file contains COMPLETION keyword.
504
+
505
+ Args:
506
+ path: Path to file to check.
507
+
508
+ Returns:
509
+ True if file contains COMPLETION keyword.
510
+ """
511
+
512
+ path = Path(path)
513
+ with open(path, encoding="utf-8") as file:
514
+ case_file_content = file.read()
515
+
516
+ if Keywords.COMPLETION in case_file_content:
517
+ return True
518
+ else:
519
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: completor
3
- Version: 1.4.0
3
+ Version: 1.5.0
4
4
  Summary: Advanced multi-segmented well completion tool.
5
5
  Home-page: https://github.com/equinor/completor
6
6
  License: LGPL-3.0-only
@@ -16,14 +16,14 @@ Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
17
  Provides-Extra: ert
18
18
  Provides-Extra: test
19
- Requires-Dist: ert (>=14,<15) ; extra == "ert"
19
+ Requires-Dist: ert (>14) ; extra == "ert"
20
20
  Requires-Dist: matplotlib (>=3.9,<4.0)
21
21
  Requires-Dist: numpy (>=2.0,<3.0)
22
22
  Requires-Dist: pandas (>=2.2,<3.0)
23
23
  Requires-Dist: pytest (>=8.3,<9.0) ; extra == "test"
24
24
  Requires-Dist: pytest-env (>=1,<2) ; extra == "test"
25
25
  Requires-Dist: pytest-xdist (>=3.6,<4.0) ; extra == "test"
26
- Requires-Dist: rstcheck-core (>=1.2,<2.0) ; extra == "test"
26
+ Requires-Dist: scipy (>=1.14,<2.0)
27
27
  Requires-Dist: tqdm (>=4.66,<5.0)
28
28
  Project-URL: Bug Tracker, https://github.com/equinor/completor/issues
29
29
  Project-URL: Documentation, https://equinor.github.io/completor
@@ -76,6 +76,14 @@ This should run for some time and display a help message.
76
76
  ### Create and run your first model
77
77
  Some examples of Completor case file are available in [Examples](documentation/docs/about/examples.mdx) and detailed explanation is available in [Configuration](documentation/docs/about/configuration.mdx).
78
78
 
79
+ ### References
80
+ Some technical paper related to Completor and ICV Control applications are available to read and cite:
81
+ - Handita Sutoyo, Filippo Panini, Cuthbert Shang Wui Ng, Martin Halvorsen, Geir Elseth, Ingvild Berg Martiniussen, Corentin Cochard, Erik Johan Helland, Sean Robert Smith, and Lene Amundsen.
82
+ "Maximize Value from Inflow Control Technology Implementations Through Novel Standardized Workflow and Open-Source Modelling Tool."
83
+ Paper presented at the OTC Brasil, Rio de Janeiro, Brazil, October 2025. doi: [10.4043/36167-MS](https://doi.org/10.4043/36167-MS)
84
+ - Handita Sutoyo, Mathias Bellout, Margrete Hånes, and Rodolfo Oliveira. "Ensemble-Based Proactive Optimization using a Reactive Strategy
85
+ for ICV Control." Paper presented at the SPE Norway Subsurface Conference, Bergen, Norway, April 2024. doi: [10.2118/218472-MS](https://doi.org/10.2118/218472-MS)
86
+
79
87
  ## Getting started as a contributor
80
88
  ### Contribution guide
81
89
  We welcome all kinds of contributions, including code, bug reports, issues, feature requests, and documentation.
@@ -1,8 +1,8 @@
1
1
  completor/__init__.py,sha256=k6amf7jhp7KkBIlaw93-NZITxyZjPSzA5McFAZh8yv8,76
2
2
  completor/completion.py,sha256=quhQOdQREv8MsHW5amT0sG-84Y12KVdT0eylbKCul3g,31177
3
3
  completor/config_jobs/run_completor,sha256=XePKj2xocfGF0XFRqr7sqfpZGrjgWcfaZLHIhVvGFCQ,600
4
- completor/constants.py,sha256=2e1o5Env5lHyhopkrs_C__9DksS5xml1-Ea_X3cLl0E,13521
5
- completor/create_output.py,sha256=6ygglcCUYYII5sWr_ey4cvUCCsXb0UGqXY5GQAzX8fQ,25969
4
+ completor/constants.py,sha256=y6nEtv-u8W-OFz84przKXVhS4as8SL8fwMMlJ38_WRA,13963
5
+ completor/create_output.py,sha256=7B3mx9xFc2Pq8Qo0GYWO3GNgylEa8pvfiHVV_3fs5Hs,26226
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
@@ -10,20 +10,23 @@ completor/get_version.py,sha256=LMzybu7m-O203lUSZvyu86J4bMobbjE9A23fWLDlxaM,168
10
10
  completor/hook_implementations/__init__.py,sha256=4tdNpVj3MNfzTMIGkp2MjP1_z3grIlwJikiA-f1a24g,104
11
11
  completor/hook_implementations/forward_model_steps.py,sha256=48tKeQUE8Kx1jhxs1MCGFR_ndgciuOxe27T74qE4GQM,776
12
12
  completor/hook_implementations/run_completor.py,sha256=WZhry4KmzxIaufXduYa6EO8BQHY3wNJ_gDXRRnPma6Y,2164
13
- completor/input_validation.py,sha256=F17AWi-qR6cX5_1lEFgtYOMOO0Xo3gTtL2ETM5P_uGE,15022
13
+ completor/icv_file_handling.py,sha256=PeZ6eACM38iy7smhViaV5gA8BhddPux-5psnkJeOTnY,15722
14
+ completor/icv_functions.py,sha256=yde_-FsFLG0_TXy3qk4wjDhAOSdaOzQ6elAOgXXcf3I,35156
15
+ completor/initialization.py,sha256=MyKDvvL_ZNJp_KxXivdvxndpMlrF66XU8H6vOAoaSfI,24627
16
+ completor/input_validation.py,sha256=vieorj4Onx4EZPA_nvIkpLkY3LRKS9LaIo5I0NRBC9A,16692
14
17
  completor/launch_args_parser.py,sha256=gb3FcyufZlRnKS3BZkFmgVH1VoSxMD0MbCLsHZKmz4c,1413
15
- completor/logger.py,sha256=gYDbPL8ca5qT_MqYlDKEMKcSfIXW_59QklX8Gss5b2U,4784
16
- completor/main.py,sha256=HlQzv5gpBYdDbYTBLSkAnK7o6d2QfTQnjrNizq3Ym6s,9343
17
- completor/parse.py,sha256=EGlt9CgkrXPqa7woyWQ5t_nh6OWsFrc2SJr8aFr_KsQ,20133
18
+ completor/logger.py,sha256=-sIxcYfnk6CFbBP1BqZtEpnS3NVO0uxXxWx0Fw4HpSw,4791
19
+ completor/main.py,sha256=JDGnVa5CFBh-ytUUlqgMjcTbFXALEpxEyAyUnKKv-NM,12456
20
+ completor/parse.py,sha256=XUCWbhKQeBIBfj8s3p7TNsggQ3Z1euxgQ5Vet9dJIxQ,20118
18
21
  completor/prepare_outputs.py,sha256=o-7SLD0F5jiw5_lnq5kewB1tYOiLa0u2TxGz6kRIO-8,87613
19
- completor/read_casefile.py,sha256=NebZRrO35aqrZIJ7eHcS6buBbAaDWw8wUtc4kBHsV2U,38184
22
+ completor/read_casefile.py,sha256=Pxub_EzfR_5pB00pKqH9jK9EkXln7r2pLQkOE_jyASA,56248
20
23
  completor/read_schedule.py,sha256=IYyCubOggFGg664h1flTl7MUJhJWyibr6JsptnURjUA,18101
21
- completor/utils.py,sha256=9Qayt7xMsimpoVDo5sL86gVaQBbIOezMBRyMXd3haXw,13598
24
+ completor/utils.py,sha256=1goaoJ_vZuCq_QC_BrVcI6agQp-zlzKEeGvRTfrfwQQ,17027
22
25
  completor/visualization.py,sha256=ObxThqIyW3fsvVIupxVsgySFI_54n_Di-HTzFtDMSgo,4580
23
26
  completor/visualize_well.py,sha256=HLglSN2ce-u9nklJelqwhSxwwaj7n-aU6o8lUScbiI0,8790
24
27
  completor/wells.py,sha256=Q2detK0FxIBgusYkCRmomRIfcScBNvNTYX43GFyAHGw,12246
25
- completor-1.4.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
26
- completor-1.4.0.dist-info/METADATA,sha256=CahCvh1VKD17-UNNyhV6DhsmMLkg1pmES92__OETFDc,8018
27
- completor-1.4.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
28
- completor-1.4.0.dist-info/entry_points.txt,sha256=rhRKVhqh_ItG-tD5YrCfMvsGnfv-h0TXP0jX_fB6Kbc,121
29
- completor-1.4.0.dist-info/RECORD,,
28
+ completor-1.5.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
29
+ completor-1.5.0.dist-info/METADATA,sha256=mYt9RURkbLLOSfZJKhUYSwpGfnmW3nB3flF3oZH6uF8,8863
30
+ completor-1.5.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
31
+ completor-1.5.0.dist-info/entry_points.txt,sha256=rhRKVhqh_ItG-tD5YrCfMvsGnfv-h0TXP0jX_fB6Kbc,121
32
+ completor-1.5.0.dist-info/RECORD,,