Exerciseschevron_rightChapter 12chevron_right12.3
fitness_center

Exercise 12.3

Composite IPR Construction - Bubble-Point Transition Rate

Level 2
Chapter 12: Nodal Analysis
descriptionProblem

A reservoir has Pe = 5,000 psi, Pb = 3,600 psi, and J = 10 STB/day/psi. Construct the composite IPR (linear above Pb, Vogel below). At what rate does the flow regime transition from single-phase to two-phase?

---

This OML-127 well is undersaturated: the reservoir pressure Pe = 5000 psi sits comfortably above the bubble point Pb = 3600 psi, with a productivity index J = 10 STB/day/psi. While the flowing bottomhole pressure stays above Pb, the inflow is plain linear Darcy flow: q = J*(Pe - Pwf). The moment Pwf dips below Pb, gas comes out of solution near the wellbore and the inflow bends over into Vogel's two-phase curve. The composite IPR stitches the two together at the bubble point.

The verified composite_ipr(Pe, Pb, J, Pwf_array) is embedded for you. Do not modify it or re-derive the physics. It is linear above Pb, Vogel below, with the bubble-point rate qb = J*(Pe - Pb) and the absolute open flow qo_max = qb + J*Pb/1.8. The constants (verbatim from Exercise 12.3) are PE = 5000.0, PB = 3600.0, J = 10.0.

Your tasks:

  1. Write transition_rate(Pe, Pb, J), the oil rate at the bubble point, i.e.

the rate at which the flow regime switches from single-phase to two-phase. This is simply qb = J * (Pe - Pb). Return it as a float.

  1. Build the full inflow curve and read off the anchor scalars:
  • q_transition = transition_rate(PE, PB, J)
  • PWF_CURVE = np.linspace(0, PE, 300) and

q_curve = composite_ipr(PE, PB, J, PWF_CURVE) (length 300).

  • qo_max = float(q_transition + J*PB/1.8), the composite AOF (absolute

open flow, the rate at Pwf = 0).

  • q_at_zero = float(composite_ipr(PE, PB, J, [0.0])[0]), the rate at

Pwf = 0; it must equal qo_max.

  • q_above_pb = float(composite_ipr(PE, PB, J, [4000.0])[0]), a point in

the linear region (4000 psi is above Pb), so this is just J*(Pe - 4000).

> Think about it: at Pwf = Pb the two branches must meet. The linear > rate J*(Pe - Pb) and the start of the Vogel branch are the same number, so > the curve is continuous (no jump). Below Pb, why does the composite rate fall > short of the naive linear extrapolation J*(Pe - Pwf)? That gap is the Vogel > gas-interference penalty.

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 composite IPR from the chapter (do not edit) ────────────────
def composite_ipr(Pe, Pb, J, Pwf_array):
    """
    Composite IPR: linear above bubble point, Vogel below.

    This is the standard approach when reservoir pressure
    exceeds the bubble point but flowing pressure may drop below it.
    """
    Pwf = np.asarray(Pwf_array)
    q = np.zeros_like(Pwf, dtype=float)

    # Rate at the bubble point (transition point)
    qb = J * (Pe - Pb)

    # Maximum rate using Vogel below bubble point
    qo_max = qb + J * Pb / 1.8

    for i, pw in enumerate(Pwf):
        if pw >= Pb:
            # Linear region (undersaturated)
            q[i] = J * (Pe - pw)
        else:
            # Vogel region (two-phase near wellbore)
            q[i] = qb + (qo_max - qb) * (1 - 0.2*(pw/Pb) - 0.8*(pw/Pb)**2)

    return q


# ── OML-127 well constants (verbatim from Exercise 12.3, do not edit) ─────
PE = 5000.0   # reservoir pressure, psi
PB = 3600.0   # bubble point, psi
J = 10.0      # productivity index, STB/day/psi


def transition_rate(Pe, Pb, J):
    """Oil rate at the bubble point where flow goes single-phase -> two-phase.

    This is the bubble-point rate qb = J * (Pe - Pb): everything above Pb is
    linear Darcy flow, everything below it bends into Vogel's two-phase curve.
    Return it as a float.
    """
    qb = J * (Pe - Pb)
    return float(qb)


q_transition = transition_rate(PE, PB, J)

PWF_CURVE = np.linspace(0, PE, 300)
q_curve = composite_ipr(PE, PB, J, PWF_CURVE)

qo_max = float(q_transition + J * PB / 1.8)

q_at_zero = float(composite_ipr(PE, PB, J, [0.0])[0])

q_above_pb = float(composite_ipr(PE, PB, J, [4000.0])[0])

print("transition rate qb (STB/day):", q_transition)
print("absolute open flow qo_max (STB/day):", qo_max)
print("rate at Pwf=0 (STB/day):", q_at_zero)
print("rate at Pwf=4000 psi, linear region (STB/day):", q_above_pb)

lockCopying code is a Full Access feature.