Exercise 8.5
Gas Volume & Expansion
A dry-gas pool on OML 58 holds 50 Bscf (50e9 standard cubic feet) of gas at initial conditions of Pi = 4500 psia and T = 220 °F, with a gas specific gravity of gamma_g = 0.72. Before you size the gathering line and book the reserve, you need the reservoir volume that gas actually occupies, and how much it swells as the field is drawn down.
Standard cubic feet are measured at surface conditions; in the reservoir each SCF takes up far less room because it is compressed. The bridge is the gas formation volume factor Bg, which depends on the deviation factor Z:
> Bg = 0.02829 Z (T_F + 460) / P (reservoir cubic feet per SCF, T in °R)
The z_factor(gamma_g, P_psia, T_F) correlation (Dranchuk–Abou-Kassem, with the Standing pseudocritical correlations) is provided: call it, don't re-derive it.
Write three functions:
bg_rcf_scf(z_factor_val, T_F, P): apply theBgformula above. It takes
an already-computed Z, the temperature in °F, and pressure in psia.
reservoir_volume_rcf(gas_scf, bg):gas_scf * bg, the reservoir cubic
feet occupied by gas_scf standard cubic feet at that Bg.
analyze(gas_scf, gamma_g, T_F, P): tie it together. ComputeZfrom
z_factor, then Bg, then reservoir volume, and return a dict {"z": ..., "bg": ..., "res_volume_rcf": ...}.
Then evaluate the pool at two pressures (same temperature, same gamma_g):
initial = analyze(50e9, 0.72, 220, 4500)depleted = analyze(50e9, 0.72, 220, 2000)
As pressure falls the gas expands: Bg grows, so the same standard volume fills more reservoir space. Store the expansion as expansion_ratio = depleted["bg"] / initial["bg"]; it should come out greater than 1.
Stuck? Reveal hints one at a time — they progress from nudge to near-solution.
visibilityReveal reference solutionexpand_more
Try solving it yourself first — the hints walk you through it. The solution below is one valid approach; yours may differ and still be correct.
import numpy as np
# ── OML 58 dry-gas pool ──────────────────────────────────────────────────
GAS_SCF = 50e9 # 50 Bscf in place
GAMMA_G = 0.72 # gas specific gravity
T_F = 220.0 # reservoir temperature, deg F
PI_PSIA = 4500.0 # initial pressure, psia
P_DEPLETED_PSIA = 2000.0 # drawn-down pressure, psia
# ── Provided correlations - call them, don't re-derive ───────────────────
def pseudocritical_properties(gamma_g):
Ppc = 756.8 - 131.0 * gamma_g - 3.6 * gamma_g ** 2
Tpc = 169.2 + 349.5 * gamma_g - 74.0 * gamma_g ** 2
return Ppc, Tpc
def z_factor_DAK(Ppr, Tpr, tol=1e-8, max_iter=100):
A1, A2, A3, A4 = 0.3265, -1.0700, -0.5339, 0.01569
A5, A6, A7, A8 = -0.05165, 0.5475, -0.7361, 0.1844
A9, A10, A11 = 0.1056, 0.6134, 0.7210
Z = 1.0
for _ in range(max_iter):
rho_r = 0.27 * Ppr / (Z * Tpr)
c1 = A1 + A2 / Tpr + A3 / Tpr ** 3 + A4 / Tpr ** 4 + A5 / Tpr ** 5
c2 = A6 + A7 / Tpr + A8 / Tpr ** 2
c3 = A9 * (A7 / Tpr + A8 / Tpr ** 2)
c4 = A10 * (1 + A11 * rho_r ** 2) * (rho_r ** 2 / Tpr ** 3) * np.exp(-A11 * rho_r ** 2)
f = Z - 1 - c1 * rho_r - c2 * rho_r ** 2 + c3 * rho_r ** 5 - c4
d_rho_dZ = -rho_r / Z
df = (1 - c1 * d_rho_dZ - 2 * c2 * rho_r * d_rho_dZ + 5 * c3 * rho_r ** 4 * d_rho_dZ
- A10 / Tpr ** 3 * d_rho_dZ * rho_r
* (2 * rho_r * (1 + A11 * rho_r ** 2) - 2 * A11 * rho_r ** 3) * np.exp(-A11 * rho_r ** 2))
Z_new = Z - f / df
if abs(Z_new - Z) < tol:
return Z_new
Z = Z_new
return Z
def z_factor(gamma_g, P_psia, T_F):
Ppc, Tpc = pseudocritical_properties(gamma_g)
return z_factor_DAK(P_psia / Ppc, (T_F + 460.0) / Tpc)
# ── Your work ────────────────────────────────────────────────────────────
def bg_rcf_scf(z_factor_val, T_F, P):
"""Gas formation volume factor (RCF/SCF). Bg = 0.02829 * Z * (T_F+460) / P."""
return 0.02829 * z_factor_val * (T_F + 460.0) / P
def reservoir_volume_rcf(gas_scf, bg):
"""Reservoir cubic feet occupied by gas_scf standard cubic feet."""
return gas_scf * bg
def analyze(gas_scf, gamma_g, T_F, P):
"""Return {"z", "bg", "res_volume_rcf"} for the gas pool at pressure P."""
z = z_factor(gamma_g, P, T_F)
bg = bg_rcf_scf(z, T_F, P)
res = reservoir_volume_rcf(gas_scf, bg)
return {"z": z, "bg": bg, "res_volume_rcf": res}
initial = analyze(GAS_SCF, GAMMA_G, T_F, PI_PSIA)
depleted = analyze(GAS_SCF, GAMMA_G, T_F, P_DEPLETED_PSIA)
expansion_ratio = depleted["bg"] / initial["bg"]
print("initial :", initial)
print("depleted :", depleted)
print("expansion ratio:", expansion_ratio)
lockCopying code is a Full Access feature.