Exerciseschevron_rightChapter 8chevron_right8.8
fitness_center

Exercise 8.8

Bubble Point vs. Temperature

Level 2
Chapter 8: PVT Correlations
descriptionProblem

A bubble-point number is never a single number; it lives at a reservoir temperature. When you push an OML 58 fluid through the lab at one temperature and then complete the well into a hotter (or cooler) interval, the pressure at which the first gas bubble breaks out moves. Get that wrong and you either flow the well two-phase when you thought it was undersaturated, or you choke it back for no reason.

The fluid here is a representative OML 58 medium crude: API = 30°, gamma_g = 0.78, solution GOR Rs = 500 scf/STB. You'll sweep reservoir temperature from 100°F to 300°F in 20°F steps and watch what Standing's correlation does to the bubble point.

Standing's bubble point is

Pb = 18.2 * ((Rs/gamma_g)**0.83 * 10**(0.00091*T_F - 0.0125*API) - 1.4)

standing_bubble_point is provided. Write:

  • pb_vs_temperature(temps_f, Rs, gamma_g, API): return a dict mapping each

temperature T (a plain Python number, iterate temps_f) to its bubble point Pb in psia. Keys come straight from temps_f; values are floats.

temps_f is already built for you as temps_f = list(range(100, 301, 20)). Call your function once and store the result in pb_by_temp; that's the dict you'll be graded on.

Optional plot (not graded, but good practice): plot Pb vs. T with axis labels and a title.

The physics you must reproduce: the exponent 0.00091*T_F grows with temperature, so Pb rises monotonically with T: every step up in temperature lifts the bubble point. Physically, a hotter oil holds less gas in solution at a given pressure, so it takes a higher pressure to keep the same 500 scf/STB dissolved. Your dict must be strictly increasing in T, and Pb(300°F) must exceed Pb(100°F).

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 representative medium crude ───────────────────────────────────
API = 30.0          # oil gravity, degrees API
GAMMA_G = 0.78      # gas specific gravity (air = 1)
RS_SCF_STB = 500.0  # solution gas-oil ratio, scf/STB

# Reservoir temperatures to sweep: 100, 120, ... 300 degF
temps_f = list(range(100, 301, 20))


def standing_bubble_point(Rs, gamma_g, T_F, API):
    """Standing (1947) bubble-point pressure, psia."""
    exponent = 0.00091 * T_F - 0.0125 * API
    return 18.2 * ((Rs / gamma_g) ** 0.83 * 10 ** exponent - 1.4)


def pb_vs_temperature(temps_f, Rs, gamma_g, API):
    """Map each reservoir temperature (degF) to its bubble point (psia)."""
    return {T: float(standing_bubble_point(Rs, gamma_g, T, API))
            for T in temps_f}


pb_by_temp = pb_vs_temperature(temps_f, RS_SCF_STB, GAMMA_G, API)

# Optional (not graded): plot Pb vs T with axis labels and a title.
import matplotlib.pyplot as plt
_t = list(pb_by_temp.keys())
_pb = [pb_by_temp[t] for t in _t]
plt.figure()
plt.plot(_t, _pb, marker="o")
plt.xlabel("Reservoir temperature (degF)")
plt.ylabel("Bubble point Pb (psia)")
plt.title("Standing bubble point vs. temperature - OML 58 crude")

print("temperatures (degF):", temps_f)
print("bubble point by temperature (psia):", pb_by_temp)

lockCopying code is a Full Access feature.