pyrestoolbox 2.2__tar.gz → 2.2.2__tar.gz
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.
- {pyrestoolbox-2.2/pyrestoolbox.egg-info → pyrestoolbox-2.2.2}/PKG-INFO +1 -1
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/brine/brine.py +136 -13
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/brine.rst +102 -1
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/changelist.rst +5 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/gas.rst +3 -19
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/library.rst +2 -2
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/oil.rst +14 -15
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/simtools.rst +17 -13
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/gas/gas.py +216 -174
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/library/library.py +10 -2
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/shared_fns/shared_fns.py +77 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/run_all_tests.py +1 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/test_brine.py +57 -0
- pyrestoolbox-2.2.2/pyrestoolbox/tests/test_doc_examples.py +556 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2/pyrestoolbox.egg-info}/PKG-INFO +1 -1
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox.egg-info/SOURCES.txt +1 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/setup.cfg +1 -1
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/setup.py +1 -1
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/LICENSE +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/MANIFEST.in +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/README.md +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/README.rst +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyproject.toml +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/brine/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/classes/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/classes/classes.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/constants/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/constants/constants.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/bot.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/bot_PVTO.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/bot_img.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/dry_gas.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/grid_sat_df.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/influence.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/properties_df.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/sgof.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/img/swof.png +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/docs/layer.rst +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/gas/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/layer/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/layer/layer.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/library/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/library/component_library.xlsx +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/oil/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/oil/oil.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/shared_fns/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/simtools/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/simtools/simtools.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/test_gas.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/test_layer.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/test_oil.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/tests/test_simtools.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/validate/__init__.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox/validate/validate.py +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox.egg-info/dependency_links.txt +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox.egg-info/requires.txt +0 -0
- {pyrestoolbox-2.2 → pyrestoolbox-2.2.2}/pyrestoolbox.egg-info/top_level.txt +0 -0
|
@@ -23,12 +23,14 @@
|
|
|
23
23
|
|
|
24
24
|
import numpy as np
|
|
25
25
|
import numpy.typing as npt
|
|
26
|
+
import pandas as pd
|
|
26
27
|
|
|
27
28
|
from typing import Tuple
|
|
29
|
+
from tabulate import tabulate
|
|
28
30
|
|
|
29
31
|
import pyrestoolbox.gas as gas # Needed for Z-Factor
|
|
30
32
|
from pyrestoolbox.classes import z_method, c_method, pb_method, rs_method, bo_method, uo_method, deno_method, co_method, kr_family, kr_table, class_dic
|
|
31
|
-
from pyrestoolbox.shared_fns import convert_to_numpy, process_output
|
|
33
|
+
from pyrestoolbox.shared_fns import convert_to_numpy, process_output, halley_solve_cubic
|
|
32
34
|
from pyrestoolbox.validate import validate_methods
|
|
33
35
|
from pyrestoolbox.constants import R, psc, tsc, degF2R, tscr, scf_per_mol, CUFTperBBL, WDEN, MW_CO2, MW_H2S, MW_N2, MW_AIR, MW_H2
|
|
34
36
|
|
|
@@ -719,31 +721,40 @@ class CO2_Brine_Mixture():
|
|
|
719
721
|
# Cubic Polynomial Solver: f(Z) = Z**3 + E2*Z**2 + E1*Z + E1 = 0
|
|
720
722
|
#=======================================================================
|
|
721
723
|
self.repeat = False
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
724
|
+
|
|
725
|
+
# Try Halley for all roots
|
|
726
|
+
roots = halley_solve_cubic(e2, e1, e0, flag=0)
|
|
727
|
+
|
|
728
|
+
# Fallback to np.roots if Halley returned None
|
|
729
|
+
if roots is None:
|
|
730
|
+
Z = np.roots(np.array([1.0, e2, e1, e0]))
|
|
731
|
+
Z = np.array([x for x in Z if np.isreal(x)]) # Keep only real results
|
|
732
|
+
roots = np.real(Z)
|
|
733
|
+
|
|
734
|
+
if len(roots) > 1: # Evaluate which root to use per Eqs 25 and 26 in Spycher & Pruess (2003)
|
|
735
|
+
vgas, vliq = max(roots), min(roots)
|
|
736
|
+
|
|
727
737
|
w1 = self.pBar*(vgas - vliq)
|
|
728
738
|
w2 = RGASCON * self.tKel * np.log((vgas - self.bMix)/(vliq - self.bMix)) + self.aMix/(self.tKel**0.5 * self.bMix) * np.log((vgas + self.bMix) * vliq / ((vliq + self.bMix) * vgas))
|
|
729
|
-
|
|
739
|
+
|
|
730
740
|
if w2 - w1 > 0:
|
|
731
|
-
|
|
741
|
+
result = max(roots)
|
|
732
742
|
if self.CO2_sat: # CO2 was saturated in previous iteration, but now its not
|
|
733
743
|
self.CO2_sat = False
|
|
734
744
|
self.repeat = True
|
|
735
745
|
else:
|
|
736
|
-
|
|
746
|
+
result = min(roots)
|
|
737
747
|
if not self.CO2_sat:
|
|
738
748
|
self.CO2_sat = True
|
|
739
749
|
self.repeat = True
|
|
740
750
|
else:
|
|
751
|
+
result = roots[0]
|
|
741
752
|
if self.CO2_sat: # CO2 was saturated in previous iteration, but now its not
|
|
742
753
|
self.CO2_sat = False
|
|
743
754
|
self.repeat = True
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
return np.real(
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
return np.real(result)
|
|
747
758
|
|
|
748
759
|
|
|
749
760
|
def MolarVolume(self):
|
|
@@ -1236,4 +1247,116 @@ class CO2_Brine_Mixture():
|
|
|
1236
1247
|
# Undersaturated compressibility = 1/V dV/dP
|
|
1237
1248
|
c_usat = 1 - sg_CO2_Brine / sg_CO2_Brine_ # 1/Bar
|
|
1238
1249
|
|
|
1239
|
-
return ([sg_CO2_Brine, sg_brine, rhowtp], [cP_CO2_brine, cP_brine, cP_freshwater], viscosblty, [bw, brine_res_vol, bw_freshwater], rs, c_usat)
|
|
1250
|
+
return ([sg_CO2_Brine, sg_brine, rhowtp], [cP_CO2_brine, cP_brine, cP_freshwater], viscosblty, [bw, brine_res_vol, bw_freshwater], rs, c_usat)
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
def make_pvtw_table(
|
|
1254
|
+
pi: float,
|
|
1255
|
+
degf: float,
|
|
1256
|
+
wt: float = 0,
|
|
1257
|
+
ch4_sat: float = 0,
|
|
1258
|
+
pmin: float = 500,
|
|
1259
|
+
pmax: float = 10000,
|
|
1260
|
+
nrows: int = 20,
|
|
1261
|
+
export: bool = False,
|
|
1262
|
+
) -> dict:
|
|
1263
|
+
""" Generates a PVTW (water PVT) table over a pressure range using brine_props (Spivey correlation).
|
|
1264
|
+
Follows the pattern of make_bot_og from the oil module.
|
|
1265
|
+
|
|
1266
|
+
pi: Initial (reference) pressure (psia)
|
|
1267
|
+
degf: Temperature (deg F)
|
|
1268
|
+
wt: Salt wt% (0-100), default 0
|
|
1269
|
+
ch4_sat: Degree of methane saturation (0 - 1), default 0
|
|
1270
|
+
pmin: Minimum pressure for table (psia), default 500
|
|
1271
|
+
pmax: Maximum pressure for table (psia), default 10000
|
|
1272
|
+
nrows: Number of rows in table, default 20
|
|
1273
|
+
export: If True, writes PVTW.INC (ECLIPSE keyword) and pvtw_table.xlsx
|
|
1274
|
+
|
|
1275
|
+
Returns dict with keys:
|
|
1276
|
+
table: pandas DataFrame with columns Pressure, Bw, Density, Viscosity, Cw, Rsw
|
|
1277
|
+
pref: Reference pressure (psia)
|
|
1278
|
+
bw_ref: Bw at reference pressure (rb/stb)
|
|
1279
|
+
cw_ref: Compressibility at reference pressure (1/psi)
|
|
1280
|
+
visw_ref: Viscosity at reference pressure (cP)
|
|
1281
|
+
rsw_ref: Rsw at reference pressure (scf/stb)
|
|
1282
|
+
den_ref: Density (sg) at reference pressure
|
|
1283
|
+
"""
|
|
1284
|
+
# Build pressure grid, ensuring pi is included
|
|
1285
|
+
pressures = list(np.linspace(pmin, pmax, nrows))
|
|
1286
|
+
if pi not in pressures:
|
|
1287
|
+
pressures.append(pi)
|
|
1288
|
+
pressures = sorted(set(pressures))
|
|
1289
|
+
|
|
1290
|
+
bws, dens, visws, cws, rsws = [], [], [], [], []
|
|
1291
|
+
for p in pressures:
|
|
1292
|
+
bw, lden, visw, cw, rsw = brine_props(p=p, degf=degf, wt=wt, ch4_sat=ch4_sat)
|
|
1293
|
+
bws.append(bw)
|
|
1294
|
+
dens.append(lden)
|
|
1295
|
+
visws.append(visw)
|
|
1296
|
+
cws.append(cw)
|
|
1297
|
+
rsws.append(rsw)
|
|
1298
|
+
|
|
1299
|
+
df = pd.DataFrame()
|
|
1300
|
+
df["Pressure (psia)"] = pressures
|
|
1301
|
+
df["Bw (rb/stb)"] = bws
|
|
1302
|
+
df["Density (sg)"] = dens
|
|
1303
|
+
df["Viscosity (cP)"] = visws
|
|
1304
|
+
df["Cw (1/psi)"] = cws
|
|
1305
|
+
df["Rsw (scf/stb)"] = rsws
|
|
1306
|
+
|
|
1307
|
+
# Reference properties at pi
|
|
1308
|
+
bw_ref, den_ref, visw_ref, cw_ref, rsw_ref = brine_props(
|
|
1309
|
+
p=pi, degf=degf, wt=wt, ch4_sat=ch4_sat
|
|
1310
|
+
)
|
|
1311
|
+
|
|
1312
|
+
if export:
|
|
1313
|
+
# Write ECLIPSE PVTW keyword
|
|
1314
|
+
# PVTW format: Pref Bw Cw Visw Viscosibility
|
|
1315
|
+
# Viscosibility set to 0 (constant viscosity assumption)
|
|
1316
|
+
pvtw_line = f" {pi:.1f} {bw_ref:.6f} {cw_ref:.6e} {visw_ref:.4f} 0.0"
|
|
1317
|
+
fileout = f"-- Generated by pyResToolbox make_pvtw_table\n"
|
|
1318
|
+
fileout += f"-- Temperature: {degf:.1f} deg F, Salt: {wt:.1f} wt%, CH4 sat: {ch4_sat:.2f}\n"
|
|
1319
|
+
fileout += f"PVTW\n{pvtw_line} /\n"
|
|
1320
|
+
with open("PVTW.INC", "w") as f:
|
|
1321
|
+
f.write(fileout)
|
|
1322
|
+
|
|
1323
|
+
# Write full table to Excel
|
|
1324
|
+
df.to_excel("pvtw_table.xlsx", index=False)
|
|
1325
|
+
|
|
1326
|
+
return {
|
|
1327
|
+
"table": df,
|
|
1328
|
+
"pref": pi,
|
|
1329
|
+
"bw_ref": bw_ref,
|
|
1330
|
+
"cw_ref": cw_ref,
|
|
1331
|
+
"visw_ref": visw_ref,
|
|
1332
|
+
"rsw_ref": rsw_ref,
|
|
1333
|
+
"den_ref": den_ref,
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
class SoreideWhitson:
|
|
1338
|
+
""" Soreide-Whitson (1992) model for gas solubility in water/brine.
|
|
1339
|
+
|
|
1340
|
+
Planned support for multicomponent gas mixtures containing:
|
|
1341
|
+
C1, C2, C3, nC4, CO2, H2S, N2, H2
|
|
1342
|
+
|
|
1343
|
+
Will calculate:
|
|
1344
|
+
- Mole fraction of dissolved gas components in aqueous phase
|
|
1345
|
+
- Mole fraction of vaporised water in gas phase
|
|
1346
|
+
- Water content of gas (stb/mmscf)
|
|
1347
|
+
- Gas solubility in water (scf/stb)
|
|
1348
|
+
|
|
1349
|
+
Supports fresh and saline water (NaCl equivalent).
|
|
1350
|
+
|
|
1351
|
+
Reference:
|
|
1352
|
+
Soreide, I. and Whitson, C.H., "Peng-Robinson Predictions for Hydrocarbons,
|
|
1353
|
+
CO2, N2, and H2S with Pure Water and NaCl Brine", Fluid Phase Equilibria,
|
|
1354
|
+
77, 217-240, 1992.
|
|
1355
|
+
"""
|
|
1356
|
+
|
|
1357
|
+
def __init__(self, **kwargs):
|
|
1358
|
+
raise NotImplementedError(
|
|
1359
|
+
"SoreideWhitson model is not yet implemented. "
|
|
1360
|
+
"Planned support includes multicomponent gas (C1, C2, C3, nC4, CO2, H2S, N2, H2) "
|
|
1361
|
+
"solubility in fresh/saline water using the Soreide-Whitson (1992) PR-EOS approach."
|
|
1362
|
+
)
|
|
@@ -161,5 +161,106 @@ Usage example for 175 Bara x 85 degC and 0% NaCl brine:
|
|
|
161
161
|
|
|
162
162
|
>>> mix = brine.CO2_Brine_Mixture(pres = 175, temp = 85)
|
|
163
163
|
>>> mix.Rs # Returns sm3 dissolved CO2 / sm3 Brine
|
|
164
|
-
24.742923469934272
|
|
164
|
+
24.742923469934272
|
|
165
|
+
|
|
166
|
+
pyrestoolbox.brine.make_pvtw_table
|
|
167
|
+
======================
|
|
168
|
+
|
|
169
|
+
.. code-block:: python
|
|
170
|
+
|
|
171
|
+
make_pvtw_table(pi, degf, wt=0, ch4_sat=0, pmin=500, pmax=10000, nrows=20, export=False) -> dict
|
|
172
|
+
|
|
173
|
+
Generates a PVTW (water PVT) table over a pressure range using the Spivey correlation (brine_props).
|
|
174
|
+
Optionally exports ECLIPSE PVTW keyword file and Excel spreadsheet.
|
|
175
|
+
|
|
176
|
+
.. list-table:: Inputs
|
|
177
|
+
:widths: 10 15 40
|
|
178
|
+
:header-rows: 1
|
|
179
|
+
|
|
180
|
+
* - Parameter
|
|
181
|
+
- Type
|
|
182
|
+
- Description
|
|
183
|
+
* - pi
|
|
184
|
+
- float
|
|
185
|
+
- Initial (reference) pressure (psia)
|
|
186
|
+
* - degf
|
|
187
|
+
- float
|
|
188
|
+
- Temperature (deg F)
|
|
189
|
+
* - wt
|
|
190
|
+
- float
|
|
191
|
+
- Salt weight% in the brine (0 - 100). Default 0
|
|
192
|
+
* - ch4_sat
|
|
193
|
+
- float
|
|
194
|
+
- Degree of methane saturation (0 - 1). Default 0
|
|
195
|
+
* - pmin
|
|
196
|
+
- float
|
|
197
|
+
- Minimum table pressure (psia). Default 500
|
|
198
|
+
* - pmax
|
|
199
|
+
- float
|
|
200
|
+
- Maximum table pressure (psia). Default 10000
|
|
201
|
+
* - nrows
|
|
202
|
+
- int
|
|
203
|
+
- Number of table rows. Default 20
|
|
204
|
+
* - export
|
|
205
|
+
- bool
|
|
206
|
+
- If True, writes PVTW.INC and pvtw_table.xlsx. Default False
|
|
207
|
+
|
|
208
|
+
.. list-table:: Return dict keys
|
|
209
|
+
:widths: 10 15 40
|
|
210
|
+
:header-rows: 1
|
|
211
|
+
|
|
212
|
+
* - Key
|
|
213
|
+
- Type
|
|
214
|
+
- Description
|
|
215
|
+
* - table
|
|
216
|
+
- DataFrame
|
|
217
|
+
- Pressure, Bw, Density, Viscosity, Cw, Rsw
|
|
218
|
+
* - pref
|
|
219
|
+
- float
|
|
220
|
+
- Reference pressure (psia)
|
|
221
|
+
* - bw_ref
|
|
222
|
+
- float
|
|
223
|
+
- Bw at reference pressure (rb/stb)
|
|
224
|
+
* - cw_ref
|
|
225
|
+
- float
|
|
226
|
+
- Compressibility at reference pressure (1/psi)
|
|
227
|
+
* - visw_ref
|
|
228
|
+
- float
|
|
229
|
+
- Viscosity at reference pressure (cP)
|
|
230
|
+
* - rsw_ref
|
|
231
|
+
- float
|
|
232
|
+
- Rsw at reference pressure (scf/stb)
|
|
233
|
+
* - den_ref
|
|
234
|
+
- float
|
|
235
|
+
- Density (sg) at reference pressure
|
|
236
|
+
|
|
237
|
+
Examples:
|
|
238
|
+
|
|
239
|
+
.. code-block:: python
|
|
240
|
+
|
|
241
|
+
>>> from pyrestoolbox import brine
|
|
242
|
+
>>> result = brine.make_pvtw_table(pi=3000, degf=200, wt=0, ch4_sat=0)
|
|
243
|
+
>>> print(result['bw_ref'])
|
|
244
|
+
>>> print(result['table'].head())
|
|
245
|
+
|
|
246
|
+
pyrestoolbox.brine.SoreideWhitson
|
|
247
|
+
======================
|
|
248
|
+
|
|
249
|
+
.. code-block:: python
|
|
250
|
+
|
|
251
|
+
SoreideWhitson(**kwargs) -> raises NotImplementedError
|
|
252
|
+
|
|
253
|
+
Placeholder for the Soreide-Whitson (1992) PR-EOS model for gas solubility in water/brine.
|
|
254
|
+
|
|
255
|
+
Planned support includes multicomponent gas mixtures (C1, C2, C3, nC4, CO2, H2S, N2, H2)
|
|
256
|
+
solubility in fresh and saline water.
|
|
257
|
+
|
|
258
|
+
Planned return values:
|
|
259
|
+
- Mole fraction of dissolved gas components in aqueous phase
|
|
260
|
+
- Mole fraction of vaporised water in gas phase
|
|
261
|
+
- Water content of gas (stb/mmscf)
|
|
262
|
+
- Gas solubility in water (scf/stb)
|
|
263
|
+
|
|
264
|
+
Reference: Soreide, I. and Whitson, C.H., "Peng-Robinson Predictions for Hydrocarbons,
|
|
265
|
+
CO2, N2, and H2S with Pure Water and NaCl Brine", Fluid Phase Equilibria, 77, 217-240, 1992.
|
|
165
266
|
|
|
@@ -210,22 +210,7 @@ Examples:
|
|
|
210
210
|
|
|
211
211
|
>>> gas.gas_z(p=[1000, 2000], sg=0.75, degf=160, cmethod='SUT', n2 = 0.02, co2 = 0.17)
|
|
212
212
|
array([0.91920553, 0.87196032])
|
|
213
|
-
|
|
214
|
-
def gas_ug(
|
|
215
|
-
p: npt.ArrayLike,
|
|
216
|
-
sg: float,
|
|
217
|
-
degf: float,
|
|
218
|
-
zmethod: z_method = z_method.DAK,
|
|
219
|
-
cmethod: c_method = c_method.PMC,
|
|
220
|
-
co2: float = 0,
|
|
221
|
-
h2s: float = 0,
|
|
222
|
-
n2: float = 0,
|
|
223
|
-
h2: float = 0,
|
|
224
|
-
tc: float = 0,
|
|
225
|
-
pc: float = 0,
|
|
226
|
-
zee: float = 0,
|
|
227
|
-
ugz = False
|
|
228
|
-
|
|
213
|
+
|
|
229
214
|
pyrestoolbox.gas.gas_ug
|
|
230
215
|
===================
|
|
231
216
|
|
|
@@ -741,7 +726,7 @@ pyrestoolbox.gas.gas_rate_radial
|
|
|
741
726
|
gas_rate_radial(k, h, pr, pwf, r_w, r_ext, degf, zmethod='DAK, cmethod='PMC', S = 0, D = 0, sg = 0.75, n2 = 0, co2 = 0, h2s = 0, tc = 0, pc = 0) -> float or np.array
|
|
742
727
|
|
|
743
728
|
Returns gas rate (mscf/day) for radial flow using Darcy pseudo steady state equation & gas pseudopressure.
|
|
744
|
-
Arrays can be used for any one of k, h, pr or pwf, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
729
|
+
Arrays can be used for any one of k, h, pr or pwf, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
745
730
|
|
|
746
731
|
.. list-table:: Inputs
|
|
747
732
|
:widths: 10 15 40
|
|
@@ -806,7 +791,6 @@ Examples:
|
|
|
806
791
|
|
|
807
792
|
.. code-block:: python
|
|
808
793
|
|
|
809
|
-
>>> from pyrestoolbox import pyrestoolbox as rtb
|
|
810
794
|
>>> gas.gas_rate_radial(k=5, h=50, pr=2000, pwf=750, r_w=0.3, r_ext=1500, degf=180, sg = 0.75, D = 0.01, S=5)
|
|
811
795
|
10269.669190157822
|
|
812
796
|
|
|
@@ -822,7 +806,7 @@ pyrestoolbox.gas.gas_rate_linear
|
|
|
822
806
|
gas_rate_linear(k, pr, pwf, area, length, degf, zmethod='DAK, cmethod='PMC', sg = 0.75, n2 = 0, co2 = 0, h2s = 0, tc = 0, pc = 0) -> float or np.array
|
|
823
807
|
|
|
824
808
|
Returns gas rate (mscf/day) for linear flow using Darcy steady state equation & gas pseudopressure.
|
|
825
|
-
Arrays can be used for any one of k, pr, pwf or area, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
809
|
+
Arrays can be used for any one of k, pr, pwf or area, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
826
810
|
|
|
827
811
|
|
|
828
812
|
.. list-table:: Inputs
|
|
@@ -65,7 +65,7 @@ Examples:
|
|
|
65
65
|
|
|
66
66
|
.. code-block:: python
|
|
67
67
|
|
|
68
|
-
>>> library.prop(comp = 'C3', prop = 'VTran'),
|
|
68
|
+
>>> library.prop(comp = 'C3', prop = 'VTran'), library.prop(comp = 'C3', prop = 'VTran', model='SRK')
|
|
69
69
|
(-0.06381, 0.09075)
|
|
70
70
|
|
|
71
71
|
|
|
@@ -158,5 +158,5 @@ Example:
|
|
|
158
158
|
|
|
159
159
|
>>> library.df
|
|
160
160
|
|
|
161
|
-
.. image::
|
|
161
|
+
.. image:: img/properties_df.png
|
|
162
162
|
:alt: DataFrame of Component Library data
|
|
@@ -57,7 +57,7 @@ pyResToolBox uses class objects to track calculation options through the functio
|
|
|
57
57
|
- Method for calculating oil formation volume factor. Defaults to 'MCAIN'
|
|
58
58
|
Options are:
|
|
59
59
|
+ 'STAN': Standing Correlation
|
|
60
|
-
+ 'MCAIN': McCain approach, calculating from densities � Default
|
|
60
|
+
+ 'MCAIN': McCain approach, calculating from densities � Default
|
|
61
61
|
|
|
62
62
|
Users can specify which calculation method to use either by passing an option string, or a class object to any given function. The implementation of class objects should make it easier to program in an IDE that supports type hinting
|
|
63
63
|
|
|
@@ -148,7 +148,7 @@ Examples:
|
|
|
148
148
|
|
|
149
149
|
.. code-block:: python
|
|
150
150
|
|
|
151
|
-
>>> oil.
|
|
151
|
+
>>> oil.oil_ja_sg(mw=150, ja=0.5)
|
|
152
152
|
0.8583666666666667
|
|
153
153
|
|
|
154
154
|
pyrestoolbox.oil.oil_twu_props
|
|
@@ -239,7 +239,7 @@ pyrestoolbox.oil.oil_pbub
|
|
|
239
239
|
|
|
240
240
|
.. code-block:: python
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
oil_pbub(api, degf, rsb, sg_g =0, sg_sp =0, pbmethod ='VALMC') -> float
|
|
243
243
|
|
|
244
244
|
Returns bubble point pressure (psia) calculated with different correlations.
|
|
245
245
|
At least one of sg_g and sg_sp must be supplied. This function will make simple assumption to estimate missing gas sg if only one is provided.
|
|
@@ -344,15 +344,15 @@ Returns solution gas oil ratio (scf/stb) calculated with different correlations.
|
|
|
344
344
|
* - degf
|
|
345
345
|
- float
|
|
346
346
|
- Oil Temperature (deg F)
|
|
347
|
-
* -
|
|
347
|
+
* - sg_sp
|
|
348
348
|
- float
|
|
349
|
-
-
|
|
349
|
+
- Separator gas gravity (relative to air).
|
|
350
350
|
* - p
|
|
351
351
|
- float
|
|
352
|
-
- Pressure (psia).
|
|
352
|
+
- Pressure (psia).
|
|
353
353
|
* - pb
|
|
354
354
|
- float
|
|
355
|
-
- Original bubble point pressure (psia)
|
|
355
|
+
- Original bubble point pressure (psia)
|
|
356
356
|
* - rsb
|
|
357
357
|
- float
|
|
358
358
|
- Original solution GOR at original bubble point pressure (scf/stb)
|
|
@@ -367,7 +367,7 @@ Examples:
|
|
|
367
367
|
|
|
368
368
|
.. code-block:: python
|
|
369
369
|
|
|
370
|
-
>>> oil.oil_rs(api = 43, degf = 185, sg_sp
|
|
370
|
+
>>> oil.oil_rs(api = 43, degf = 185, sg_sp=0.72, p = 3000, pb = 5179.5, rsb = 2370)
|
|
371
371
|
1017.9424240354475
|
|
372
372
|
|
|
373
373
|
>>> oil.oil_rs(api=43, degf=185, sg_sp=0.72, p=3000, rsb =2370)
|
|
@@ -610,7 +610,7 @@ pyrestoolbox.oil.make_bot_og
|
|
|
610
610
|
|
|
611
611
|
.. code-block:: python
|
|
612
612
|
|
|
613
|
-
make_bot_og(pi, api, degf, sg_g, pmax, pb =0, rsb =0, pmin =14.7, nrows = 20, wt =0, ch4_sat =0, comethod='EXPLT', zmethod='DAK', rsmethod='VELAR', cmethod'PMC', denomethod='SWMH', bomethod='MCAIN', pbmethod='VALMC', export=False) -> tuple
|
|
613
|
+
make_bot_og(pi, api, degf, sg_g, pmax, pb =0, rsb =0, pmin =14.7, nrows = 20, wt =0, ch4_sat =0, comethod='EXPLT', zmethod='DAK', rsmethod='VELAR', cmethod='PMC', denomethod='SWMH', bomethod='MCAIN', pbmethod='VALMC', export=False) -> tuple
|
|
614
614
|
|
|
615
615
|
Creates data required for Oil-Gas-Water black oil tables. Returns dictionary of results, with index:
|
|
616
616
|
- bot: Pandas table of blackoil data (for PVTO == False), or Saturated properties to pmax (if PVTO == True)
|
|
@@ -709,7 +709,7 @@ Examples:
|
|
|
709
709
|
>>> results = oil.make_bot_og(pvto=False, pi=4000, api=38, degf=175, sg_g=0.68, pmax=5500, pb=4500, nrows=10, export=True)
|
|
710
710
|
>>> df, st_deno, st_deng, res_denw, res_cw, visw, pb, rsb, rsb_frac, usat = results['bot'], results['deno'], results['deng'], results['denw'], results['cw'], results['uw'], results['pb'], results['rsb'], results['rsb_scale'], results['usat']
|
|
711
711
|
>>> df
|
|
712
|
-
.. image::
|
|
712
|
+
.. image:: img/bot_img.png
|
|
713
713
|
:alt: Black Oil Table DataFrame
|
|
714
714
|
|
|
715
715
|
pyrestoolbox.oil.sg_evolved_gas
|
|
@@ -749,9 +749,8 @@ Examples:
|
|
|
749
749
|
|
|
750
750
|
.. code-block:: python
|
|
751
751
|
|
|
752
|
-
>>> oil.
|
|
753
|
-
|
|
754
|
-
|
|
752
|
+
>>> oil.sg_evolved_gas(p=2000, degf=185, rsb=2370, api=43, sg_sp=0.72)
|
|
753
|
+
0.7872810977386344
|
|
755
754
|
|
|
756
755
|
pyrestoolbox.oil.sg_st_gas
|
|
757
756
|
=======================
|
|
@@ -891,7 +890,7 @@ pyrestoolbox.oil.oil_rate_radial
|
|
|
891
890
|
oil_rate_radial(k, h, pr, pwf, r_w, r_ext, uo, bo, S = 0, vogel = False, pb = 0) -> float or np.array
|
|
892
891
|
|
|
893
892
|
Returns liquid rate (stb/day) for radial flow using Darcy pseudo steady state equation with optional Vogel correction.
|
|
894
|
-
Arrays can be used for any one of k, h, pr or pwf, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
893
|
+
Arrays can be used for any one of k, h, pr or pwf, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
895
894
|
|
|
896
895
|
.. list-table:: Inputs
|
|
897
896
|
:widths: 10 15 40
|
|
@@ -952,7 +951,7 @@ pyrestoolbox.oil.oil_rate_linear
|
|
|
952
951
|
oil_rate_linear(k, pr, pwf, area, length, uo, bo, vogel = False, pb = 0) -> float or np.array
|
|
953
952
|
|
|
954
953
|
Returns liquid rate (stb/day) for linear flow using Darcy steady state equation with optional Vogel correction.
|
|
955
|
-
Arrays can be used for any one of k, pr, pwf or area, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
954
|
+
Arrays can be used for any one of k, pr, pwf or area, returning corresponding 1-D array of rates. Using more than one input array � while not prohibited - will not return expected results
|
|
956
955
|
|
|
957
956
|
.. list-table:: Inputs
|
|
958
957
|
:widths: 10 15 40
|
|
@@ -52,7 +52,8 @@ Examples:
|
|
|
52
52
|
|
|
53
53
|
.. code-block:: python
|
|
54
54
|
|
|
55
|
-
>>>
|
|
55
|
+
>>> from pyrestoolbox import simtools
|
|
56
|
+
>>> results = simtools.ix_extract_problem_cells()
|
|
56
57
|
>>> wells, grid_pres, grid_sat, grid_comp = results
|
|
57
58
|
>>> grid_sat
|
|
58
59
|
Processing TEST.PRT
|
|
@@ -64,7 +65,7 @@ Examples:
|
|
|
64
65
|
Grid Saturation Change 310 32,121,24 13
|
|
65
66
|
Grid Composition Change 1627 35,212,25 544
|
|
66
67
|
|
|
67
|
-
.. image::
|
|
68
|
+
.. image:: img/grid_sat_df.png
|
|
68
69
|
:alt: DSorted ataFrame of grid blocks with saturation related convergence issues
|
|
69
70
|
|
|
70
71
|
|
|
@@ -112,10 +113,10 @@ Examples:
|
|
|
112
113
|
|
|
113
114
|
.. code-block:: python
|
|
114
115
|
|
|
115
|
-
>>> from pyrestoolbox import
|
|
116
|
+
>>> from pyrestoolbox import simtools
|
|
116
117
|
>>> import matplotlib.pyplot as plt
|
|
117
118
|
>>> ReDs = [1.5, 2, 3, 5, 10, 25, 1000]
|
|
118
|
-
>>> tds, pds =
|
|
119
|
+
>>> tds, pds = simtools.influence_tables(ReDs=ReDs, export=True)
|
|
119
120
|
>>>
|
|
120
121
|
>>> for p, pd in enumerate(pds):
|
|
121
122
|
>>> plt.plot(tds, pd, label = str(ReDs[p]))
|
|
@@ -129,7 +130,7 @@ Examples:
|
|
|
129
130
|
>>> plt.title('Constant Terminal Rate Solution')
|
|
130
131
|
>>> plt.show()
|
|
131
132
|
|
|
132
|
-
.. image::
|
|
133
|
+
.. image:: img/influence.png
|
|
133
134
|
:alt: Constant Terminal Rate influence tables
|
|
134
135
|
|
|
135
136
|
|
|
@@ -173,10 +174,10 @@ Examples:
|
|
|
173
174
|
|
|
174
175
|
.. code-block:: python
|
|
175
176
|
|
|
176
|
-
>>>
|
|
177
|
+
>>> simtools.zip_check_sim_deck(['FIELD_A.DATA', 'FIELD_B.afi'], console_summary=False)
|
|
177
178
|
['INCLUDE/GridOpts.inc', 'INCLUDE/ZCORN_COORD.GRDECL', 'EPS.ixf']
|
|
178
179
|
|
|
179
|
-
>>>
|
|
180
|
+
>>> simtools.zip_check_sim_deck()
|
|
180
181
|
Index File Name
|
|
181
182
|
------- ------------
|
|
182
183
|
0 FIELD_A.DATA
|
|
@@ -247,7 +248,7 @@ Examples:
|
|
|
247
248
|
|
|
248
249
|
.. code-block:: python
|
|
249
250
|
|
|
250
|
-
>>>
|
|
251
|
+
>>> simtools.rr_solver(zi =np.array([0.7, 0.15, 0.1, 0.05]), ki = np.array([50, 5, 0.5, 0.01]))
|
|
251
252
|
(6,
|
|
252
253
|
array([0.7406252 , 0.1570315 , 0.09469948, 0.00764382]),
|
|
253
254
|
array([0.0148125 , 0.0314063 , 0.18939896, 0.76438224]),
|
|
@@ -342,9 +343,12 @@ pyrestoolbox.simtools.rel_perm_table
|
|
|
342
343
|
|
|
343
344
|
|
|
344
345
|
Examples:
|
|
345
|
-
|
|
346
|
+
|
|
347
|
+
.. code-block:: python
|
|
348
|
+
|
|
349
|
+
>>> from pyrestoolbox import simtools
|
|
346
350
|
>>> import matplotlib.pyplot as plt
|
|
347
|
-
>>> df =
|
|
351
|
+
>>> df = simtools.rel_perm_table(rows=25, krtable='SGOF', krfamily='LET', kromax =1, krgmax =1, swc =0.2, sorg =0.15, Lo=2.5, Eo = 1.25, To = 1.75, Lg = 1.2, Eg = 1.5, Tg = 2.0)
|
|
348
352
|
>>> plt.plot(df['Sg'], df['Krgo'], c = 'r', label='Gas')
|
|
349
353
|
>>> plt.plot(df['Sg'], df['Krog'], c = 'g', label='Oil')
|
|
350
354
|
>>> plt.title('SGOF Gas Oil LET Relative Permeability Curves')
|
|
@@ -354,12 +358,12 @@ Examples:
|
|
|
354
358
|
>>> plt.grid('both')
|
|
355
359
|
>>> plt.plot()
|
|
356
360
|
|
|
357
|
-
.. image::
|
|
361
|
+
.. image:: img/sgof.png
|
|
358
362
|
:alt: SGOF Relative Permeability Curves
|
|
359
363
|
|
|
360
364
|
.. code-block:: python
|
|
361
365
|
|
|
362
|
-
>>> df =
|
|
366
|
+
>>> df = simtools.rel_perm_table(rows=25, krtable='SWOF', kromax =1, krwmax =0.25, swc =0.15, swcr = 0.2, sorw =0.15, no=2.5, nw=1.5)
|
|
363
367
|
>>> plt.plot(df['Sw'], df['Krow'], c = 'g', label='Oil')
|
|
364
368
|
>>> plt.plot(df['Sw'], df['Krwo'], c = 'b', label='Water')
|
|
365
369
|
>>> plt.title('SWOF Water Oil Corey Relative Permeability Curves')
|
|
@@ -369,7 +373,7 @@ Examples:
|
|
|
369
373
|
>>> plt.grid('both')
|
|
370
374
|
>>> plt.plot()
|
|
371
375
|
|
|
372
|
-
.. image::
|
|
376
|
+
.. image:: img/swof.png
|
|
373
377
|
:alt: SWOF Relative Permeability Curves
|
|
374
378
|
|
|
375
379
|
|