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/constants.py +19 -0
- completor/create_output.py +12 -3
- completor/icv_file_handling.py +362 -0
- completor/icv_functions.py +845 -0
- completor/initialization.py +563 -0
- completor/input_validation.py +63 -0
- completor/logger.py +1 -1
- completor/main.py +88 -19
- completor/parse.py +5 -5
- completor/read_casefile.py +429 -48
- completor/utils.py +133 -2
- {completor-1.4.0.dist-info → completor-1.5.0.dist-info}/METADATA +11 -3
- {completor-1.4.0.dist-info → completor-1.5.0.dist-info}/RECORD +16 -13
- {completor-1.4.0.dist-info → completor-1.5.0.dist-info}/LICENSE +0 -0
- {completor-1.4.0.dist-info → completor-1.5.0.dist-info}/WHEEL +0 -0
- {completor-1.4.0.dist-info → completor-1.5.0.dist-info}/entry_points.txt +0 -0
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.
|
|
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 (
|
|
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:
|
|
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=
|
|
5
|
-
completor/create_output.py,sha256=
|
|
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/
|
|
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
|
|
16
|
-
completor/main.py,sha256=
|
|
17
|
-
completor/parse.py,sha256=
|
|
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=
|
|
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=
|
|
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.
|
|
26
|
-
completor-1.
|
|
27
|
-
completor-1.
|
|
28
|
-
completor-1.
|
|
29
|
-
completor-1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|