completor 0.1.2__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/__init__.py +3 -0
- completor/completion.py +1042 -0
- completor/config_jobs/run_completor +18 -0
- completor/constants.py +256 -0
- completor/create_output.py +462 -0
- completor/create_wells.py +314 -0
- completor/exceptions/__init__.py +4 -0
- completor/exceptions/clean_exceptions.py +10 -0
- completor/exceptions/exceptions.py +134 -0
- completor/hook_implementations/jobs.py +63 -0
- completor/input_validation.py +340 -0
- completor/launch_args_parser.py +41 -0
- completor/logger.py +138 -0
- completor/main.py +486 -0
- completor/parse.py +581 -0
- completor/prepare_outputs.py +1473 -0
- completor/pvt_model.py +14 -0
- completor/read_casefile.py +677 -0
- completor/read_schedule.py +160 -0
- completor/utils.py +185 -0
- completor/visualization.py +164 -0
- completor/visualize_well.py +217 -0
- completor-0.1.2.dist-info/LICENSE +165 -0
- completor-0.1.2.dist-info/METADATA +205 -0
- completor-0.1.2.dist-info/RECORD +27 -0
- completor-0.1.2.dist-info/WHEEL +4 -0
- completor-0.1.2.dist-info/entry_points.txt +6 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- This is the forward model job which calls Completor.
|
|
2
|
+
-- It is called from the ERT config file as a regular forward model.
|
|
3
|
+
|
|
4
|
+
-- Arguments:
|
|
5
|
+
-- CASE: Completor configuration file (*.case file) describing completion configuration.
|
|
6
|
+
-- INPUT_SCH: Tubing schedule file defining multi-segmented well in terms of WELSPECS, WELSEGS, COMPSEGS, COMPDAT.
|
|
7
|
+
-- OUTPUT_SCH: Well schedule generated by Completor, including advanced completion.
|
|
8
|
+
|
|
9
|
+
EXECUTABLE completor
|
|
10
|
+
|
|
11
|
+
ARGLIST -i <CASE> -s <INPUT_SCH> -o <OUTPUT_SCH>
|
|
12
|
+
|
|
13
|
+
MIN_ARG 2
|
|
14
|
+
MAX_ARG 3
|
|
15
|
+
|
|
16
|
+
ARG_TYPE 0 STRING
|
|
17
|
+
ARG_TYPE 1 STRING
|
|
18
|
+
ARG_TYPE 2 STRING
|
completor/constants.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Define custom enumerations and methods."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import Enum, auto
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Headers:
|
|
10
|
+
"""Headers for DataFrames."""
|
|
11
|
+
|
|
12
|
+
WATER_CUT = "WCT"
|
|
13
|
+
OPEN = "OPEN"
|
|
14
|
+
RHO = "RHO"
|
|
15
|
+
VISCOSITY = "VIS"
|
|
16
|
+
DEVICE = "DEVICE"
|
|
17
|
+
SF = "SF" # Saturation functions?
|
|
18
|
+
THERM = "THERM"
|
|
19
|
+
PERFDEPTH = "PERFDEPTH" # Perforation depth?
|
|
20
|
+
ENDGRID = "ENDGRID"
|
|
21
|
+
VSEG = "VSEG" # Vertical Segments?
|
|
22
|
+
TUBING_INNER_DIAMETER = "TUBINGID"
|
|
23
|
+
MPMODEL = "MPMODEL"
|
|
24
|
+
PDROPCOMP = "PDROPCOMP" # Pressure drop completion?
|
|
25
|
+
WBVOLUME = "WBVOLUME" # Well bore volume?
|
|
26
|
+
ITEM_8 = "ITEM8"
|
|
27
|
+
ITEM_9 = "ITEM9"
|
|
28
|
+
ITEM_10 = "ITEM10"
|
|
29
|
+
ITEM_11 = "ITEM11"
|
|
30
|
+
ITEM_12 = "ITEM12"
|
|
31
|
+
ITEM_13 = "ITEM13"
|
|
32
|
+
ITEM_14 = "ITEM14"
|
|
33
|
+
ITEM_15 = "ITEM15"
|
|
34
|
+
ITEM_16 = "ITEM16"
|
|
35
|
+
ITEM_17 = "ITEM17"
|
|
36
|
+
REGION = "REGION"
|
|
37
|
+
DENSCAL = "DENSCAL" # Calculated density / Density calculated?
|
|
38
|
+
PRESSURE_TABLE = "PRESSURETABLE"
|
|
39
|
+
CROSS = "CROSS"
|
|
40
|
+
SHUT = "SHUT"
|
|
41
|
+
DR = "DR"
|
|
42
|
+
PHASE = "PHASE"
|
|
43
|
+
BHP_DEPTH = "BHP_DEPTH" # Bottom hole pressure depth?
|
|
44
|
+
GROUP = "GROUP"
|
|
45
|
+
MARKER = "MARKER"
|
|
46
|
+
SCALING_FACTOR = "SCALINGFACTOR"
|
|
47
|
+
LENGTH = "LENGTH"
|
|
48
|
+
ADDITIONAL_SEGMENT = "AdditionalSegment"
|
|
49
|
+
ORIGINAL_SEGMENT = "OriginalSegment"
|
|
50
|
+
TUBING_SEGMENT_2 = "TUBINGSEGMENT2"
|
|
51
|
+
INFO_TYPE = "INFOTYPE"
|
|
52
|
+
TUBING_OUTLET = "TUBINGOUTLET"
|
|
53
|
+
SAT = "SAT" # Saturation?
|
|
54
|
+
FLAG = "FLAG" # This is actually a header, but OPEN, SHUT, and AUTO are its possible values, see manual on COMPDAT.
|
|
55
|
+
DEF = "DEF"
|
|
56
|
+
DIRECTION = "DIR"
|
|
57
|
+
SEG = "SEG" # Duplicate, ish
|
|
58
|
+
SEG2 = "SEG2"
|
|
59
|
+
OUT = "OUT"
|
|
60
|
+
COMPSEGS_DIRECTION = "COMPSEGS_DIRECTION"
|
|
61
|
+
LATERAL = "LATERAL"
|
|
62
|
+
NUMBER_OF_DEVICES = "NDEVICES"
|
|
63
|
+
I = "I" # noqa: E741
|
|
64
|
+
J = "J"
|
|
65
|
+
K = "K"
|
|
66
|
+
K2 = "K2"
|
|
67
|
+
STATUS = "STATUS"
|
|
68
|
+
SATURATION_FUNCTION_REGION_NUMBERS = "SATNUM"
|
|
69
|
+
CONNECTION_FACTOR = "CF" # Transmissibility factor for the connection. If defaulted or set to zero,
|
|
70
|
+
# the connection transmissibility factor is calculated using the remaining items of data in this record. See "The
|
|
71
|
+
# connection transmissibility factor" in the ECLIPSE Technical Description for an account of the methods used in
|
|
72
|
+
# Cartesian and radial geometries. The well bore diameter must be set in item 9.
|
|
73
|
+
|
|
74
|
+
DIAMETER = "DIAM"
|
|
75
|
+
FORAMTION_PERMEABILITY_THICKNESS = "KH" # The product of formation permeability, k, and producing formation
|
|
76
|
+
# thickness, h, in a producing well, referred to as kh.
|
|
77
|
+
SKIN = "SKIN" # A dimensionless factor calculated to determine the production efficiency of a well by comparing
|
|
78
|
+
# actual conditions with theoretical or ideal conditions. A positive skin value indicates some damage or
|
|
79
|
+
# influences that are impairing well productivity. A negative skin value indicates enhanced productivity,
|
|
80
|
+
# typically resulting from stimulation.
|
|
81
|
+
DFACT = "DFACT"
|
|
82
|
+
COMPDAT_DIRECTION = "COMPDAT_DIRECTION"
|
|
83
|
+
RO = "RO"
|
|
84
|
+
|
|
85
|
+
TUB_TVD = "TUB_TVD" # Same as TUBINGTVD
|
|
86
|
+
TVD = "TVD"
|
|
87
|
+
TUBINGMD = "TUBINGMD"
|
|
88
|
+
TUBINGTVD = "TUBINGTVD"
|
|
89
|
+
SEGMENTTVD = "SEGMENTTVD"
|
|
90
|
+
SEGMENTMD = "SEGMENTMD"
|
|
91
|
+
SEGMENT_DESC = "SEGMENT_DESC"
|
|
92
|
+
SEGMENT = "SEGMENT"
|
|
93
|
+
VISCAL_ICD = "VISCAL_ICD"
|
|
94
|
+
RHOCAL_ICD = "RHOCAL_ICD"
|
|
95
|
+
STRENGTH = "STRENGTH"
|
|
96
|
+
|
|
97
|
+
WCT_AICV = "WCT_AICV"
|
|
98
|
+
GHF_AICV = "GHF_AICV"
|
|
99
|
+
RHOCAL_AICV = "RHOCAL_AICV"
|
|
100
|
+
VISCAL_AICV = "VISCAL_AICV"
|
|
101
|
+
ALPHA_MAIN = "ALPHA_MAIN"
|
|
102
|
+
X_MAIN = "X_MAIN"
|
|
103
|
+
Y_MAIN = "Y_MAIN"
|
|
104
|
+
A_MAIN = "A_MAIN"
|
|
105
|
+
B_MAIN = "B_MAIN"
|
|
106
|
+
C_MAIN = "C_MAIN"
|
|
107
|
+
D_MAIN = "D_MAIN"
|
|
108
|
+
E_MAIN = "E_MAIN"
|
|
109
|
+
F_MAIN = "F_MAIN"
|
|
110
|
+
ALPHA_PILOT = "ALPHA_PILOT"
|
|
111
|
+
X_PILOT = "X_PILOT"
|
|
112
|
+
Y_PILOT = "Y_PILOT"
|
|
113
|
+
A_PILOT = "A_PILOT"
|
|
114
|
+
B_PILOT = "B_PILOT"
|
|
115
|
+
C_PILOT = "C_PILOT"
|
|
116
|
+
D_PILOT = "D_PILOT"
|
|
117
|
+
E_PILOT = "E_PILOT"
|
|
118
|
+
F_PILOT = "F_PILOT"
|
|
119
|
+
|
|
120
|
+
CV_DAR = "CV_DAR"
|
|
121
|
+
AC_OIL = "AC_OIL"
|
|
122
|
+
AC_GAS = "AC_GAS"
|
|
123
|
+
AC_WATER = "AC_WATER"
|
|
124
|
+
WHF_LCF_DAR = "WHF_LCF_DAR"
|
|
125
|
+
WHF_HCF_DAR = "WHF_HCF_DAR"
|
|
126
|
+
GHF_LCF_DAR = "GHF_LCF_DAR"
|
|
127
|
+
GHF_HCF_DAR = "GHF_HCF_DAR"
|
|
128
|
+
|
|
129
|
+
ALPHA = "ALPHA"
|
|
130
|
+
X = "X"
|
|
131
|
+
Y = "Y"
|
|
132
|
+
A = "A"
|
|
133
|
+
B = "B"
|
|
134
|
+
C = "C"
|
|
135
|
+
D = "D"
|
|
136
|
+
E = "E"
|
|
137
|
+
F = "F"
|
|
138
|
+
RHOCAL_AICD = "RHOCAL_AICD"
|
|
139
|
+
VISCAL_AICD = "VISCAL_AICD"
|
|
140
|
+
|
|
141
|
+
DEFAULTS = "DEFAULTS"
|
|
142
|
+
AC_MAX = "AC_MAX"
|
|
143
|
+
|
|
144
|
+
CV = "CV"
|
|
145
|
+
AC = "AC"
|
|
146
|
+
L = "L"
|
|
147
|
+
|
|
148
|
+
BRANCH = "BRANCH"
|
|
149
|
+
|
|
150
|
+
TUBINGBRANCH = "TUBINGBRANCH"
|
|
151
|
+
MD = "MD"
|
|
152
|
+
|
|
153
|
+
# from `test_completion.py`
|
|
154
|
+
TUB_MD = "TUB_MD"
|
|
155
|
+
|
|
156
|
+
# Completion
|
|
157
|
+
START_MEASURED_DEPTH = "STARTMD"
|
|
158
|
+
END_MEASURED_DEPTH = "ENDMD"
|
|
159
|
+
ANNULUS = "ANNULUS"
|
|
160
|
+
ANNULUS_ZONE = "ANNULUS_ZONE"
|
|
161
|
+
VALVES_PER_JOINT = "NVALVEPERJOINT"
|
|
162
|
+
INNER_DIAMETER = "INNER_DIAMETER"
|
|
163
|
+
OUTER_DIAMETER = "OUTER_DIAMETER"
|
|
164
|
+
ROUGHNESS = "ROUGHNESS"
|
|
165
|
+
DEVICE_TYPE = "DEVICETYPE"
|
|
166
|
+
DEVICE_NUMBER = "DEVICENUMBER"
|
|
167
|
+
WELL = "WELL"
|
|
168
|
+
|
|
169
|
+
# Well segments
|
|
170
|
+
TUBING_MD = "TUBINGMD"
|
|
171
|
+
TUBING_TVD = "TUBINGTVD"
|
|
172
|
+
SEGMENT_MD = "SEGMENTMD"
|
|
173
|
+
SEGMENT_TVD = "SEGMENTTVD"
|
|
174
|
+
TUBING_SEGMENT = "TUBINGSEGMENT"
|
|
175
|
+
TUBING_SEGMENT2 = "TUBINGSEGMENT2"
|
|
176
|
+
TUBING_BRANCH = "TUBINGBRANCH"
|
|
177
|
+
TUBING_ROUGHNESS = "TUBINGROUGHNESS"
|
|
178
|
+
|
|
179
|
+
EMPTY = ""
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@dataclass(frozen=True)
|
|
183
|
+
class _Keywords:
|
|
184
|
+
"""Define keywords used in the schedule file.
|
|
185
|
+
|
|
186
|
+
Used as constants, and to check if a given word / string is a keyword.
|
|
187
|
+
|
|
188
|
+
Attributes:
|
|
189
|
+
_items: Private helper to iterate through all keywords.
|
|
190
|
+
_members: Private helper to check membership.
|
|
191
|
+
main_keywords: collection of the main keywords: welspecs, compdat, welsegs, and compsegs.
|
|
192
|
+
segments: Set of keywords that are used in a segment.
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
WELSPECS = "WELSPECS"
|
|
196
|
+
COMPDAT = "COMPDAT"
|
|
197
|
+
WELSEGS = "WELSEGS"
|
|
198
|
+
COMPSEGS = "COMPSEGS"
|
|
199
|
+
|
|
200
|
+
COMPLETION = "COMPLETION"
|
|
201
|
+
|
|
202
|
+
WELSEGS_H = "WELSEGS_H"
|
|
203
|
+
WSEGLINK = "WSEGLINK"
|
|
204
|
+
WSEGVALV = "WSEGVALV"
|
|
205
|
+
WSEGAICD = "WSEGAICD"
|
|
206
|
+
WSEGAICV = "WSEGAICV"
|
|
207
|
+
WSEGICV = "WSEGICV"
|
|
208
|
+
WSEGSICD = "WSEGSICD"
|
|
209
|
+
WSEGDAR = "WSEGDAR"
|
|
210
|
+
|
|
211
|
+
SCHFILE = "SCHFILE"
|
|
212
|
+
OUTFILE = "OUTFILE"
|
|
213
|
+
|
|
214
|
+
main_keywords = [WELSPECS, COMPDAT, WELSEGS, COMPSEGS]
|
|
215
|
+
|
|
216
|
+
_items = [WELSPECS, COMPDAT, WELSEGS, COMPSEGS]
|
|
217
|
+
_members = set(_items)
|
|
218
|
+
|
|
219
|
+
segments = {WELSEGS, COMPSEGS}
|
|
220
|
+
|
|
221
|
+
def __iter__(self):
|
|
222
|
+
return self._items.__iter__()
|
|
223
|
+
|
|
224
|
+
def __contains__(self, item):
|
|
225
|
+
return item in self._members
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
Keywords = _Keywords()
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class Method(Enum):
|
|
232
|
+
"""An enumeration of legal methods to create wells."""
|
|
233
|
+
|
|
234
|
+
CELLS = auto()
|
|
235
|
+
FIX = auto()
|
|
236
|
+
USER = auto()
|
|
237
|
+
WELSEGS = auto()
|
|
238
|
+
|
|
239
|
+
def __eq__(self, other: object) -> bool:
|
|
240
|
+
"""Implement the equality function to compare enums with their string literal.
|
|
241
|
+
|
|
242
|
+
Arguments:
|
|
243
|
+
other: Item to compare with.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
Whether enums are equal.
|
|
247
|
+
|
|
248
|
+
Example:
|
|
249
|
+
>>>Method.CELLS == "CELLS"
|
|
250
|
+
>>>True
|
|
251
|
+
"""
|
|
252
|
+
if isinstance(other, Enum):
|
|
253
|
+
return self.__class__ == other.__class__ and self.value == other.value and self.name == other.name
|
|
254
|
+
elif isinstance(other, str):
|
|
255
|
+
return self.name == other
|
|
256
|
+
return False
|