Exerciseschevron_rightChapter 15chevron_right15.4
fitness_center

Exercise 15.4

Gas Well Deliverability - Backpressure & Forchheimer AOF

Level 2
Chapter 15: Gas Engineering
descriptionProblem

A gas well was tested at four rates. Fit both the backpressure equation and the Forchheimer equation. Calculate AOF using both methods and compare. Which method is more conservative?

Use the following test data:

Rate (Mscf/d)Pwf (psia)
03,200
1,5003,050
3,0002,810
4,5002,480
6,0002,050

---

A gas well on OML 58 was flow-after-flow tested at four stabilized rates, plus a shut-in reading. You will analyze the deliverability two ways: the simplified backpressure equation and the full Forchheimer (quadratic) equation, and report the Absolute Open Flow potential (AOF) from each.

The chapter's ch15-gas-ipr block does this analysis; here you package it into a single reusable function. No chapter function is pre-embedded; you re-code the two correlations directly from the chapter physics.

Write deliverability(q_test, Pwf_test, Pe) that returns a dict. Steps:

  1. Convert inputs to numpy arrays and drop any zero-rate point (the shut-in

(0, Pe) row must not enter the log fit (log10(0) is undefined).

  1. Backpressure equation q = C * (Pe² - Pwf²)^n:
  • dP2 = Pe2 - Pwf2
  • Fit log10(q) = log10(C) + n * log10(dP2) with

np.polyfit(np.log10(dP2), np.log10(q), 1).

  • n = slope, C = 10**intercept.
  • AOF_bp = C (Pe2 - 14.72)*n.
  1. Forchheimer equation Pe² - Pwf² = A*q + B*q², i.e. dP2/q = A + B*q:
  • ratio = dP2 / q
  • Fit np.polyfit(q, ratio, 1)B = slope, A = intercept.
  • Solve the quadratic at Pwf = 14.7 psia:

AOF_forch = (-A + sqrt(A2 + 4*B*(Pe2 - 14.7**2))) / (2*B).

  1. Return dict with keys 'C', 'n', 'A', 'B', 'AOF_bp', 'AOF_forch'.

Embedded test data (from the book table):

Q   = [0.0, 1500.0, 3000.0, 4500.0, 6000.0]   # Mscf/d  (first row is shut-in)
PWF = [3200.0, 3050.0, 2810.0, 2480.0, 2050.0] # psia
PE  = 3200.0                                    # shut-in reservoir pressure, psia

Then call it once and pull out the values the tests read:

dd        = deliverability(Q, PWF, PE)
aof_bp    = dd['AOF_bp']
aof_forch = dd['AOF_forch']
n_exp     = dd['n']

> Think about it: the exponent n should land between 0.5 and 1.0; below 1.0 > means turbulence (non-Darcy flow) is robbing the well of deliverability. That is > exactly why the Forchheimer AOF comes out lower than the backpressure AOF: > the quadratic term B*q² charges the well for that turbulent loss. Which number > would you trust when sizing surface facilities?

lightbulbHints (0/3)

Stuck? Reveal hints one at a time — they progress from nudge to near-solution.

codeYour solution
main.py
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 backpressure (flow-after-flow) test data (do not edit) ─────────
# From the book table: a shut-in reading plus four stabilized flow rates.
Q = [0.0, 1500.0, 3000.0, 4500.0, 6000.0]      # Mscf/d (first row is shut-in)
PWF = [3200.0, 3050.0, 2810.0, 2480.0, 2050.0]  # flowing BHP, psia
PE = 3200.0                                      # shut-in reservoir pressure, psia


def deliverability(q_test, Pwf_test, Pe):
    """Analyze a gas-well backpressure test two ways.

    Returns a dict with keys:
      'C', 'n'             -- backpressure: q = C*(Pe^2 - Pwf^2)^n
      'A', 'B'             -- Forchheimer: Pe^2 - Pwf^2 = A*q + B*q^2
      'AOF_bp', 'AOF_forch'-- Absolute Open Flow (Mscf/d) at Pwf = 14.7 psia
    Drop any zero-rate (shut-in) point before the log fit.
    """
    q = np.asarray(q_test, float)
    Pwf = np.asarray(Pwf_test, float)
    # drop the shut-in (zero-rate) point -- log10(0) is undefined
    mask = q > 0
    q = q[mask]
    Pwf = Pwf[mask]
    dP2 = Pe**2 - Pwf**2

    # Method 1: simplified backpressure equation
    # log10(q) = log10(C) + n * log10(Pe^2 - Pwf^2)
    coeffs = np.polyfit(np.log10(dP2), np.log10(q), 1)
    n = coeffs[0]
    C = 10**coeffs[1]
    AOF_bp = C * (Pe**2 - 14.7**2)**n

    # Method 2: Forchheimer (quadratic)
    # (Pe^2 - Pwf^2)/q = A + B*q
    ratio = dP2 / q
    coeffs_q = np.polyfit(q, ratio, 1)
    B = coeffs_q[0]
    A = coeffs_q[1]
    # AOF is the positive root of B*q^2 + A*q - (Pe^2 - 14.7^2) = 0
    AOF_forch = (-A + np.sqrt(A**2 + 4*B*(Pe**2 - 14.7**2))) / (2*B)

    return dict(C=C, n=n, A=A, B=B, AOF_bp=AOF_bp, AOF_forch=AOF_forch)


dd = deliverability(Q, PWF, PE)
aof_bp = dd['AOF_bp']
aof_forch = dd['AOF_forch']
n_exp = dd['n']

print("deliverability exponent n:", n_exp)
print("AOF (backpressure) Mscf/d:", aof_bp)
print("AOF (Forchheimer) Mscf/d:", aof_forch)

lockCopying code is a Full Access feature.