Exercise 12.1
Linear IPR - Straight-Line Inflow for an Undersaturated Reservoir
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:
That single relation, verbatim from the chapter, is all you need here.
Your task: write a function and run the driver:
- 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.
- Using the embedded constants
J = 12.0(STB/day/psi) andPE = 3800.0
(psi), build PWF_TEST = np.array([2000.0, 1000.0, 0.0]) and assign q_test = linear_ipr(PE, J, PWF_TEST).
- Pull out the three exact scalars the tests read:
q_at_2000 = float(q_test[0]), rate at Pwf = 2000 psiq_at_1000 = float(q_test[1]), rate at Pwf = 1000 psiq_at_zero = float(q_test[2]), rate at Pwf = 0 psiaof = 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?
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 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.