Exerciseschevron_rightChapter 12chevron_right12.4
fitness_center

Exercise 12.4

Fetkovich from Multi-Rate Test - Log-Log Deliverability Fit

Level 3
Chapter 12: Nodal Analysis
descriptionProblem

A well was tested at four stabilized rates. Fit the Fetkovich model to determine C and n:

Rate (STB/day)Pwf (psi)
8003,200
1,4002,600
2,0001,900
2,8001,000

Reservoir pressure is 3,800 psi. Plot the fitted IPR.

---

A back-pressure (multi-rate) test on an OML well gives you four stabilized (rate, Pwf) pairs at a known reservoir pressure. The Fetkovich deliverability model says

q=C(Pe2Pwf2)nq = C\,(P_e^2 - P_{wf}^2)^n

Take logs of both sides and it becomes a straight line:

log10q=nlog10(Pe2Pwf2)+log10C\log_{10} q = n\,\log_{10}(P_e^2 - P_{wf}^2) + \log_{10} C

So a single linear least-squares fit in log-log space recovers the deliverability exponent n (the slope) and the deliverability coefficient C (from the intercept). Once you have C and n you can evaluate the IPR at any flowing pressure, including Pwf = 0, which gives the Absolute Open Flow (AOF), the theoretical maximum rate.

The verified fetkovich_ipr(Pe, C, n, Pwf_array) from the chapter is embedded for you. Do not modify it. It returns C (Pe2 - Pwf2)*n.

The test data (verbatim from the Exercise 12.4 table) is embedded as constants:

RATES = np.array([800.0, 1400.0, 2000.0, 2800.0])   # STB/day
PWF   = np.array([3200.0, 2600.0, 1900.0, 1000.0])  # psi
PE    = 3800.0                                       # reservoir pressure, psi

Your tasks:

  1. Write fit_fetkovich(Pe, rates, pwf) that fits C and n by linear

least-squares in log-log space:

  • x = np.log10(Pe2 - pwf2)
  • y = np.log10(rates)
  • n, logC = np.polyfit(x, y, 1) (slope first, intercept second)
  • C = 10**logC
  • Return the tuple (C, n) in that order. (numpy only, no scipy.)
  1. Fit the embedded test data and expose these EXACT output names the tests read:
  • C, n = fit_fetkovich(PE, RATES, PWF)
  • C_fit = float(C) (≈ 8.6648e-5)
  • n_fit = float(n) (≈ 1.04968)
  • aof = float(fetkovich_ipr(PE, C, n, [0.0])[0]) (≈ 2838.02 STB/day, the

Absolute Open Flow at Pwf = 0)

  • q_fitted = fetkovich_ipr(PE, C, n, PWF) (the four predicted rates at the

test pressures, used for residual checks)

> Think about it: the slope of the log-log line is n, and the intercept > is log10(C); no nonlinear solver needed. A well-behaved oil well lands n > in the 0.5–1.0+ band; values far outside it mean the data or the algebra is > off. Why does evaluating the fitted IPR at Pwf = 0 give the largest rate the > well could ever deliver?

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 Fetkovich IPR model (do not edit) ───────────────────────────
def fetkovich_ipr(Pe, C, n, Pwf_array):
    """
    Fetkovich IPR model.

    Parameters
    ----------
    Pe : float
        Average reservoir pressure (psi).
    C : float
        Deliverability coefficient.
    n : float
        Deliverability exponent (0.5 to 1.0).
    Pwf_array : array-like
        Flowing bottomhole pressures (psi).

    Returns
    -------
    numpy.ndarray
        Flow rates (STB/day).
    """
    Pwf = np.asarray(Pwf_array)
    return C * (Pe**2 - Pwf**2)**n


# ── Multi-rate test data (verbatim from Exercise 12.4, do not edit) ───────
RATES = np.array([800.0, 1400.0, 2000.0, 2800.0])   # stabilized rates, STB/day
PWF = np.array([3200.0, 2600.0, 1900.0, 1000.0])    # flowing BHP, psi
PE = 3800.0                                          # reservoir pressure, psi


def fit_fetkovich(Pe, rates, pwf):
    """Fit Fetkovich C and n by linear least-squares in log-log space.

    The Fetkovich law q = C*(Pe**2 - Pwf**2)**n becomes a straight line in
    log10 space:  log10(q) = n*log10(Pe**2 - Pwf**2) + log10(C).
    The slope is n, the intercept is log10(C).

    Returns (C, n).
    """
    x = np.log10(Pe**2 - pwf**2)
    y = np.log10(rates)
    n, logC = np.polyfit(x, y, 1)   # slope first, intercept second
    C = 10**logC
    return C, n


C, n = fit_fetkovich(PE, RATES, PWF)
C_fit = float(C)
n_fit = float(n)
aof = float(fetkovich_ipr(PE, C, n, [0.0])[0])
q_fitted = fetkovich_ipr(PE, C, n, PWF)

print("C_fit:", C_fit, "  n_fit:", n_fit)
print("AOF (STB/day):", aof)
print("fitted rates:", q_fitted)

lockCopying code is a Full Access feature.