Exerciseschevron_rightChapter 12chevron_right12.1
fitness_center

Exercise 12.1

Linear IPR - Straight-Line Inflow for an Undersaturated Reservoir

Level 1
Chapter 12: Nodal Analysis
descriptionProblem

A well has a productivity index of 12 STB/day/psi and a reservoir pressure of 3,800 psi. Calculate and plot the IPR curve. Determine the flow rate at Pwf = 2,000 psi, 1,000 psi, and 0 psi.

---

This is the supply side of nodal analysis: the inflow performance relationship (IPR). For an undersaturated reservoir, where the flowing bottomhole pressure stays above the bubble point, the rate the reservoir delivers is a straight line in pressure:

qo=J×(PePwf)q_o = J \times (P_e - P_{wf})

That single relation, verbatim from the chapter, is all you need here.

Your task: write a function and run the driver:

  1. Write linear_ipr(Pe, J, Pwf_array) that returns a numpy array of oil

rates qo = J * (Pe - Pwf_array), the straight-line IPR. Accept Pwf_array as anything array-like (a numpy array or a plain list) and return a numpy array of the same length.

  1. Using the embedded constants J = 12.0 (STB/day/psi) and PE = 3800.0

(psi), build PWF_TEST = np.array([2000.0, 1000.0, 0.0]) and assign q_test = linear_ipr(PE, J, PWF_TEST).

  1. Pull out the three exact scalars the tests read:
  • q_at_2000 = float(q_test[0]), rate at Pwf = 2000 psi
  • q_at_1000 = float(q_test[1]), rate at Pwf = 1000 psi
  • q_at_zero = float(q_test[2]), rate at Pwf = 0 psi
  • aof = float(q_at_zero), the absolute open flow (rate when Pwf = 0)

The names the grader reads are: linear_ipr, q_test, q_at_2000, q_at_1000, q_at_zero, and aof.

> Think about it: the straight line has a constant slope equal to J, > every psi of extra drawdown buys you exactly J more STB/day. The absolute > open flow aof = J * PE is the rate if you could pull Pwf all the way to > zero. But notice the chapter's bubble point sits at Pb = 3200 psi: at > Pwf = 2000, 1000, and 0 you are well below Pb, so in reality the > curve would bend (gas comes out of solution and chokes the oil). The linear > model is only strictly valid above the bubble point; here we compute it > anyway as the reference straight line. Why does a stronger drawdown always > add the same J barrels per psi, no matter where you are on the line?

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 reservoir constants (do not edit) ────────────────────────────────
# Book Exercise 12.1: J = 12 STB/day/psi, reservoir pressure Pe = 3,800 psi.
J = 12.0             # productivity index, STB/day/psi
PE = 3800.0          # average reservoir pressure, psi
PB = 3200.0          # bubble point pressure, psi (linear model valid above Pb)


# ── Verified linear-IPR relation (do not edit the form) ──────────────────
# Straight-line inflow for an undersaturated reservoir, copied verbatim from
# the chapter:   qo = J * (Pe - Pwf)
def linear_ipr(Pe, J, Pwf_array):
    """Straight-line IPR for an undersaturated reservoir.

    Parameters
    ----------
    Pe : float
        Average reservoir pressure (psi).
    J : float
        Productivity index (STB/day/psi).
    Pwf_array : array-like
        Flowing bottomhole pressures (psi).

    Returns
    -------
    np.ndarray
        Oil rates qo = J * (Pe - Pwf) (STB/day), one per Pwf.
    """
    Pwf = np.asarray(Pwf_array, dtype=float)
    return J * (Pe - Pwf)


# Driver: evaluate the IPR at three drawdowns and read off the key rates.
PWF_TEST = np.array([2000.0, 1000.0, 0.0])

q_test = linear_ipr(PE, J, PWF_TEST)
q_at_2000 = float(q_test[0])
q_at_1000 = float(q_test[1])
q_at_zero = float(q_test[2])
aof = float(q_at_zero)   # absolute open flow (Pwf = 0)

print("Rate at Pwf=2000 psi:", q_at_2000, "STB/day")
print("Rate at Pwf=1000 psi:", q_at_1000, "STB/day")
print("Rate at Pwf=0    psi:", q_at_zero, "STB/day")
print("Absolute open flow:  ", aof, "STB/day")

lockCopying code is a Full Access feature.