Exerciseschevron_rightChapter 13chevron_right13.4
fitness_center

Exercise 13.4

Gas Lift Marginal Analysis - Diminishing Returns

Level 1
Chapter 13: Production Optimization
descriptionProblem

For a well with gas lift response q = 300 + 600 × G / (200 + G), calculate the marginal oil gain (dq/dG) at injection rates of 100, 300, 500, 1000, and 2000 Mscf/d. At what injection rate does the marginal gain fall below 0.1 STB per Mscf?

---

The verified chapter function gas_lift_response(q_base, gas_inj, a, b) is embedded for you under the do-not-edit banner. It returns the diminishing-returns performance curve

q_oil = q_base + a * gas_inj / (b + gas_inj)

We study the single well from the book: q = 300 + 600 × G / (200 + G), i.e. Q_BASE = 300.0 STB/d natural rate, A_GAIN = 600.0 STB/d maximum incremental oil, B_HALF = 200.0 Mscf/d half-response gas rate. You will evaluate the marginal oil gain (the slope dq/dG) at TEST_RATES = [100, 300, 500, 1000, 2000] Mscf/d, and find where the marginal gain falls below MARGINAL_THRESHOLD = 0.1 STB per Mscf.

Your tasks:

  1. Write marginal_gain(gas_inj, a, b): the analytic derivative of

gas_lift_response. Differentiating a*G/(b+G) with respect to G gives

`` dq/dG = a b / (b + gas_inj)*2 # STB per Mscf ``

It must work on scalars and numpy arrays (just use the formula directly).

  1. Write gas_rate_at_marginal(target_marginal, a, b): invert the marginal

curve to find the injection rate where dq/dG == target_marginal. Setting a*b/(b+G)**2 = target and solving for G:

`` G = sqrt(a * b / target_marginal) - b ``

  1. Assign the two output variables the tests read:

``python marginals = marginal_gain(TEST_RATES, A_GAIN, B_HALF) # array of 5 g_threshold = gas_rate_at_marginal(MARGINAL_THRESHOLD, A_GAIN, B_HALF) ``

> Think about it: the marginal gain starts at a/b = 3.0 STB/Mscf when > G = 0 and decays like 1/(b+G)**2: every extra Mscf of lift gas buys less > oil than the last. Beyond about 895 Mscf/d each additional Mscf returns less > than 0.1 STB. Why does that diminishing-returns shape mean there is always an > economic injection rate beyond which more gas is not worth pumping?

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


# ── Verified gas lift performance curve (do not edit) ────────────────────
def gas_lift_response(q_base, gas_inj, a, b):
    """
    Gas lift performance curve.

    Returns the total oil rate as a function of gas injection rate.
    The response follows a diminishing-returns curve:
        q_oil = q_base + a * gas_inj / (b + gas_inj)

    Parameters
    ----------
    q_base : float
        Natural flow rate without gas lift (STB/day).
    gas_inj : float
        Gas injection rate (Mscf/day).
    a : float
        Maximum incremental oil gain (STB/day).
    b : float
        Gas rate at half-maximum response (Mscf/day).
    """
    return q_base + a * gas_inj / (b + gas_inj)


# ── Single-well gas lift constants (do not edit) ─────────────────────────
Q_BASE = 300.0   # natural rate, STB/d
A_GAIN = 600.0   # max incremental oil, STB/d
B_HALF = 200.0   # half-response gas rate, Mscf/d
TEST_RATES = np.array([100.0, 300.0, 500.0, 1000.0, 2000.0])  # Mscf/d to evaluate
MARGINAL_THRESHOLD = 0.1  # STB per Mscf


def marginal_gain(gas_inj, a, b):
    """Return dq/dG = a*b / (b + gas_inj)**2  (STB per Mscf).

    Closed-form derivative of gas_lift_response; works on scalars and
    numpy arrays.
    """
    return a * b / (b + gas_inj) ** 2


def gas_rate_at_marginal(target_marginal, a, b):
    """Return the injection rate G where dq/dG == target_marginal.

    Invert a*b/(b+G)**2 = target  ->  G = sqrt(a*b/target) - b.
    """
    return np.sqrt(a * b / target_marginal) - b


marginals = marginal_gain(TEST_RATES, A_GAIN, B_HALF)
g_threshold = gas_rate_at_marginal(MARGINAL_THRESHOLD, A_GAIN, B_HALF)

print("marginal gains (STB/Mscf):", marginals)
print("gas rate at 0.1 STB/Mscf threshold:", g_threshold)

lockCopying code is a Full Access feature.