Exerciseschevron_rightChapter 15chevron_right15.5
fitness_center

Exercise 15.5

Pipeline Pressure Profile - P² is Linear, Pressure is Not

Level 2
Chapter 15: Gas Engineering
descriptionProblem

For a 100-mile, 24-inch pipeline operating at 1,200 psia inlet and 800 psia outlet, calculate and plot the pressure at every mile along the pipeline. Is the pressure drop linear?

---

We'll trace the pressure foot-by-foot along a 100-mile, 24-inch OML trunk line running at 1,200 psia inlet and 800 psia outlet. Here's the physics that makes a gas line different from a water line: in steady horizontal flow with a constant mass rate q, the General Flow Equation says it is P², not P, that drops linearly along the pipe. Rearranging q ∝ sqrt((P1² − P2²)/L) for a constant q over any partial length x gives the exact local pressure:

P(x) = sqrt( P1**2 - (P1**2 - P2**2) * x / L )

That square-root makes the profile convex: pressure falls slowly near the high-pressure inlet and steeply near the outlet, so the midpoint pressure sits above the naive linear average (P1 + P2)/2. A water engineer who interpolates linearly will under-predict the line-pack and mis-size compression.

The verified pipeline_capacity_general function is embedded for you so you can confirm the line carries a single constant capacity end to end; do not modify it or re-derive the physics.

Your tasks:

  1. Write pressure_profile(P1, P2, L_miles, n_points):
  • Build x = np.linspace(0, L_miles, n_points): distances along the line.
  • For each x[i], compute P[i] = sqrt(P12 - (P12 - P2*2) x[i] / L_miles).

(A vectorized numpy expression over the whole x array is fine.)

  • Return the tuple (x_array, P_array) in that order, both length n_points.
  1. Using the embedded constants P1 = 1200.0, P2 = 800.0, L_MILES = 100.0,

N_POINTS = 101 (a node every mile, 0..100), call the function and unpack: ``python x_mi, p_psia = pressure_profile(P1, P2, L_MILES, N_POINTS) p_mid = float(p_psia[50]) # pressure at mile 50 p_at_25 = float(p_psia[25]) # pressure at mile 25 ``

> Think about it: p_mid comes out near 1019.8 psia, comfortably above > the linear-average 1000; that gap is the whole point. The endpoints must > land exactly on 1200 and 800. If you ever code P(x) as a straight line, the > P²-linearity and convexity checks will catch you. Why is the pressure drop per > mile steeper at the outlet than at the inlet, even though the same gas flows > through every cross-section?

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 General Flow Equation for gas pipeline capacity (do not edit) ──
def pipeline_capacity_general(P1, P2, D_in, L_miles, gamma_g, T_avg_F,
                               Z_avg, efficiency=0.92):
    """
    General Flow Equation for gas pipeline capacity.

    Parameters
    ----------
    P1 : float
        Inlet pressure (psia).
    P2 : float
        Outlet pressure (psia).
    D_in : float
        Pipe internal diameter (inches).
    L_miles : float
        Pipeline length (miles).
    gamma_g : float
        Gas specific gravity.
    T_avg_F : float
        Average gas temperature (deg F).
    Z_avg : float
        Average compressibility factor.
    efficiency : float
        Pipeline efficiency factor (0 to 1).

    Returns
    -------
    float
        Flow rate (MMscf/day).
    """
    Tb = 520  # base temperature, deg R (60 deg F)
    Pb = 14.73  # base pressure, psia
    T_avg_R = T_avg_F + 459.67

    # Assume fully turbulent friction factor (Weymouth approximation)
    f = 0.032 / (D_in**(1/3))

    q_scfd = 77.54 * (Tb/Pb) * (
        (P1**2 - P2**2) * D_in**5 /
        (f * gamma_g * T_avg_R * Z_avg * L_miles)
    )**0.5

    return q_scfd * efficiency / 1e6  # convert to MMscf/day


# ── Pipeline constants (do not edit) ─────────────────────────────────────
P1 = 1200.0       # inlet pressure, psia
P2 = 800.0        # outlet pressure, psia
L_MILES = 100.0   # pipeline length, miles
N_POINTS = 101    # a node every mile, 0..100
D_IN = 24.0       # pipe internal diameter, inches (for the capacity check)
GAMMA_G = 0.65    # gas specific gravity
T_AVG_F = 80.0    # average gas temperature, deg F
Z_AVG = 0.92      # average compressibility factor


def pressure_profile(P1, P2, L_miles, n_points):
    """Pressure at every node along a horizontal gas pipeline.

    In steady flow with constant rate, P**2 is LINEAR in distance, so
        P(x) = sqrt(P1**2 - (P1**2 - P2**2) * x / L_miles).
    Returns (x_array, P_array), both length n_points:
      x_array = numpy.linspace(0, L_miles, n_points)  -- miles from the inlet
      P_array = local pressure at each node (psia)
    """
    x = np.linspace(0, L_miles, n_points)
    P = np.sqrt(P1**2 - (P1**2 - P2**2) * x / L_miles)
    return x, P


x_mi, p_psia = pressure_profile(P1, P2, L_MILES, N_POINTS)
p_mid = float(p_psia[50])    # pressure at mile 50
p_at_25 = float(p_psia[25])  # pressure at mile 25

# The whole line carries one constant capacity end to end (sanity context).
q_line = pipeline_capacity_general(P1, P2, D_IN, L_MILES, GAMMA_G, T_AVG_F, Z_AVG)

print("nodes:", len(x_mi))
print("P at inlet / outlet (psia):", (float(p_psia[0]), float(p_psia[-1])))
print("P at mile 50 (psia):", p_mid, "  linear-average would be:", (P1 + P2) / 2)
print("P at mile 25 (psia):", p_at_25)
print("constant line capacity (MMscf/day):", round(q_line, 2))

lockCopying code is a Full Access feature.