Exercise 12.4
Fetkovich from Multi-Rate Test - Log-Log Deliverability Fit
A well was tested at four stabilized rates. Fit the Fetkovich model to determine C and n:
| Rate (STB/day) | Pwf (psi) |
|---|---|
| 800 | 3,200 |
| 1,400 | 2,600 |
| 2,000 | 1,900 |
| 2,800 | 1,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
Take logs of both sides and it becomes a straight line:
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, psiYour tasks:
- Write
fit_fetkovich(Pe, rates, pwf)that fitsCandnby 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.)
- 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?
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
# ── 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.