Porosity-Permeability Transforms
On this page
Summary
A porosity-permeability transform is a straight line fitted to core on a semi-log plot: log Permeability is linear in Effective porosity. It is the most common and often the best permeability estimate from logs, as long as it is made for one rock type and its scatter is carried with it. The scatter, Porosity-permeability scatter, is not noise to be ignored: it is the uncertainty of the result.
Inputs and outputs
| Item | Units | |
|---|---|---|
| Input | Effective porosity | v/v |
| Input | Porosity-permeability intercept | log10(mD) |
| Input | Porosity-permeability slope | log10(mD) per porosity percent |
| Input | Porosity-permeability scatter | log10 units |
| Output | Permeability | mD |
| Output | Permeability, low estimate | mD |
| Output | Permeability, high estimate | mD |
| Output | Permeability, arithmetic mean | mD |
Equations
The transform is linear in log permeability, with porosity in percent:
so the trend permeability is \(k = 10^{\CpPhiKA + \CpPhiKB (100\,\phie)}\), capped at 10 000 mD in the calculator. This is the median, or geometric mean, of the permeability at that porosity. The scatter of core points about the line is a standard deviation \(\CpPhiKSig\) in log10 units. If it is lognormal, the low and high estimates and the arithmetic mean are:
The factor 1.2816 is the standard normal deviate at the 10th and 90th percentiles. The line is fitted by regressing \(\log_{10}k\) on porosity (permeability is the dependent variable), by least squares.
| Symbol | Variable | Units | Typical range |
|---|---|---|---|
| \(\phi_e\) | Effective porosity | v/v | 0 to 0.35 |
| \(a_\phi\) | Porosity-permeability intercept | log10(mD) | -5 to 0 |
| \(b_\phi\) | Porosity-permeability slope | log10(mD) per porosity percent | 0.1 to 0.5 |
| \(\sigma_k\) | Porosity-permeability scatter | log10 units | 0.2 to 0.8 |
| \(k\) | Permeability | mD | 0.0001 to 10000 |
| \(k_{lo}\) | Permeability, low estimate | mD | |
| \(k_{hi}\) | Permeability, high estimate | mD | |
| \(\bar{k}\) | Permeability, arithmetic mean | mD |
Single-value calculator
Behavior
Permeability changes by a factor of 10^b for each percent of porosity, and with b = 0.25 a four-point porosity change is a decade. At a = -3, b = 0.25 and sigma = 0.4, the trend is 0.1, 1.0, 10 and 100 mD at porosities of 0.08, 0.12, 0.16 and 0.20. At every porosity the low and high estimates are a factor of 10^(1.2816 x 0.4) = 3.26 below and above the trend, so the 10th to 90th percentile range spans a factor of 10.6. The arithmetic mean is 1.53 times the trend, always higher than the geometric mean; for a scatter of 0.4 it is the number that applies when flow goes through layers in parallel.
Parameter guidance
Fit one line per rock type. A single line through mixed rock has a large scatter that is a rock-type signal, not noise. Splitting by facies, hydraulic flow unit or grain size and fitting each reduces the scatter and gives lines with different slopes. Regress log k on porosity, not porosity on log k. The two lines differ, and the first is the one that predicts permeability. Keep the scatter. The regression gives the median trend. Applied to a log, it gives a curve with much less variance than the real permeability, and a smooth curve underestimates the high-permeability beds that carry the flow. State the uncertainty, or add the scatter back when the result goes into a dynamic model. Average with the right mean. Permeability is close to lognormal, so the arithmetic mean of the log curve is biased low for flow in parallel layers and the geometric (log) mean is the central value. Use the arithmetic mean for flow along layers, the harmonic mean across them, and the geometric mean as a neutral central value. Core permeability should be corrected to reservoir confining stress and for Klinkenberg slip before the fit. Porosity should be the same basis as the log.
Worked example
A made-up core data set of 40 plugs generated with a known trend and scatter, to show the fit, the recovered scatter and the difference between the three means:
import numpy as np
rng = np.random.default_rng(7)
phi_pct = rng.uniform(8, 24, 40)
true_a, true_b, true_sigma = -3.0, 0.25, 0.4
logk = true_a + true_b * phi_pct + rng.normal(0, true_sigma, 40)
b, a = np.polyfit(phi_pct, logk, 1)
resid = logk - (a + b * phi_pct)
sigma = resid.std(ddof=2)
print(f"fit: log10 k = {a:.2f} + {b:.3f} x phi% scatter = {sigma:.2f} (true {true_a}, {true_b}, {true_sigma})")
# the wrong regression: porosity on log k, inverted
b_inv, a_inv = np.polyfit(logk, phi_pct, 1)
print(f"inverse regression slope = {1 / b_inv:.3f} per %, against {b:.3f}")
k = 10 ** logk
print(f"geometric mean {10 ** logk.mean():.2f} mD, arithmetic {k.mean():.2f} mD, harmonic {1 / np.mean(1 / k):.2f} mD")
print(f"trend at 16% porosity: {10 ** (a + b * 16):.2f} mD, 10-90 range {10 ** (a + b * 16 - 1.2816 * sigma):.2f} to {10 ** (a + b * 16 + 1.2816 * sigma):.2f}")
Output
fit: log10 k = -3.50 + 0.282 x phi% scatter = 0.32 (true -3.0, 0.25, 0.4)
inverse regression slope = 0.298 per %, against 0.282
geometric mean 7.66 mD, arithmetic 228.67 mD, harmonic 0.25 mD
trend at 16% porosity: 10.36 mD, 10-90 range 4.01 to 26.79
Assumptions and limitations
- Log permeability is a linear function of porosity with a constant scatter (homoscedastic and normal in log space). Real data have a changing scatter, and low-porosity data are often more scattered.
- One line serves one rock type. Mixing types merges separate lines into a wide cloud.
- Core data represent the reservoir. Plug samples are biased to cleaner, more homogeneous rock, and the plug scale is not the log scale.
- The transform holds outside the porosity range of the core. Extrapolating a log-linear line has no support.
QC checks
- Plot log k against porosity with the fitted line and the 10th to 90th percentile band; no clear structure should remain in the residuals.
- Check the residuals against depth, rock type and porosity: a trend means a missing rock type or a nonlinear relation.
- The log-derived permeability, upscaled to the core plug scale, matches core in the cored interval, on a log-log plot with no bias.
- The arithmetic mean of the result over the interval is compared with the test or the kh from pressure transient analysis.
Going Deeper
The semi-log straight line is an empirical convenience. Real porosity-permeability data are often curved on a semi-log plot, and in some rocks (carbonates especially) do not correlate at all without a measure of pore type. Nelson's review of permeability-porosity relationships catalogues the reasons: grain size, sorting, cement and clay all move the line, and the line moves again with confining stress. The model-based alternatives on the other pages, which add Swirr, are attempts to bring in a measure of pore size that porosity does not carry. Their gain over a well-built rock-type transform is usually small, and where it is not, the cause is generally a missing rock type.
References
- Nelson, P.H., 1994. Permeability-porosity relationships in sedimentary rocks. The Log Analyst, 35(3), 38–62.
Python reference implementation
Python reference implementation
The Python reference implementation is available to registered users with a verified email address. Register or sign in to view it.