Productivity Index and Skin Factor: Step-by-Step Calculation

Productivity index and skin factor calculation showing radial reservoir flow and near-wellbore damage

By Saad Iqbal

Two wells with identical reservoir rock can produce very differently, and the reason is usually written in two numbers: productivity index and skin factor. Productivity index (J) tells you how many barrels per day you get for every psi of drawdown; skin factor (s) tells you how much of your well’s potential is being lost to near-wellbore damage. This tutorial works through both—by hand and in Python—so you can diagnose an underperforming well instead of just watching its decline curve.

Productivity index calculation diagram showing oil well reservoir and wellbore skin factor for drawdown and production rate

Prerequisites

  • Effective permeability, k (millidarcies)
  • Net pay thickness, h (ft)
  • Oil viscosity, μo (cp), and formation volume factor, Bo (rb/stb)
  • Drainage radius, re, and wellbore radius, rw (ft)
  • An estimate of skin factor, s, from a pressure transient (build-up/draw-down) test
  • Python 3 with pandas for tracking J over time as skin changes

The physical picture behind the math is radial flow converging from the drainage boundary down to the wellbore—skin factor is effectively an extra, localized resistance right at that final step:

Diagram of radial flow pattern from reservoir drainage boundary to wellbore illustrating productivity index and skin factor concept

The formula

For a well in pseudo-steady-state radial flow, the productivity index is:

Formula diagram for productivity index J equals 0.00708 times k h over mu Bo times ln re over rw minus 0.75 plus skin factor s

where J is in stb/day/psi, k is permeability in md, h is net pay in ft, μo is oil viscosity in cp, Bo is the formation volume factor in rb/stb, re and rw are drainage and wellbore radii in ft, and s is the dimensionless skin factor (zero for an undamaged well, positive for damage, negative for a stimulated well).

Worked example

Take a well with k = 50 md, h = 30 ft, μo = 1.5 cp, Bo = 1.25 rb/stb, re = 1,000 ft, rw = 0.33 ft, and a build-up test indicating s = 5 (moderate near-wellbore damage):

Worked numerical example showing step by step calculation of productivity index and skin factor using given reservoir and well parameters
import math
k = 50 # md
h = 30 # ft
mu_o = 1.5 # cp
Bo = 1.25 # rb/stb
re = 1000 # ft
rw = 0.33 # ft
s = 5 # skin factor from build-up test
ln_term = math.log(re / rw)
J = 0.00708 * k * h / (mu_o * Bo * (ln_term - 0.75 + s))
print(round(J, 3), "stb/day/psi")
# -> 0.462 stb/day/psi
# compare against an undamaged well (s = 0)
J_ideal = 0.00708 * k * h / (mu_o * Bo * (ln_term - 0.75))
print("PI lost to skin:", round((1 - J / J_ideal) * 100, 1), "%")
# -> 40.8 percent of potential productivity lost to damage

At J = 0.462 stb/day/psi, this well is producing at barely 59% of what an undamaged completion would deliver with the same reservoir properties—a strong economic case for a stimulation treatment or acid wash.

Automating it with Python and pandas

Skin factor isn’t static—it drifts with scale buildup, fines migration, and workovers. Tracking J alongside periodic skin estimates lets you catch degradation (or confirm a successful stimulation) before it shows up as a surprise in the production report:

import pandas as pd
import numpy as np
def productivity_index(k, h, mu_o, Bo, re, rw, s):
"""Vectorized productivity index (stb/day/psi)."""
ln_term = np.log(re / rw)
return 0.00708 * k * h / (mu_o * Bo * (ln_term - 0.75 + s))
# periodic well-test history: one row per build-up/draw-down survey
df = pd.DataFrame({
"test_date": pd.date_range("2026-01-01", periods=8, freq="MS"),
"k_md": 50,
"h_ft": 30,
"mu_o_cp": 1.5,
"Bo_rb_stb": 1.25,
"re_ft": 1000,
"rw_ft": 0.33,
"skin": [2, 2.5, 3.2, 4.0, 5.0, 4.6, 3.1, 2.0], # rises then drops after stimulation
})
df["J_stb_day_psi"] = productivity_index(
df["k_md"], df["h_ft"], df["mu_o_cp"], df["Bo_rb_stb"],
df["re_ft"], df["rw_ft"], df["skin"]
)
print(df[["test_date", "skin", "J_stb_day_psi"]])

Monitoring the trend

Plotted over time, a well with worsening formation damage shows J declining as skin climbs, then recovering sharply after a successful intervention—exactly the signature you want your production-surveillance dashboard to flag automatically:

Line chart showing productivity index trend over time with declining PI due to skin factor increase from formation damage

Tools used

  • Python 3 with pandas and NumPy for batch calculation across a well test history
  • Jupyter Notebook for interactive build-up test analysis
  • Power BI or Looker Studio for dashboarding PI trends across a field
  • Claude or ChatGPT for interpreting ambiguous build-up test shapes before committing to a skin estimate

Verifying your result

Cross-check J against the well’s actual test rate divided by its observed drawdown (q/Δp)—they should be in the same ballpark if your input parameters are representative of current reservoir conditions. A skin factor that comes out strongly negative (below about −5) usually points to a successfully stimulated or naturally fractured well; a value above 10–15 suggests severe damage worth investigating before you trust the number blindly.

Common pitfalls

  • Mixing up re and the wellbore radius. These differ by orders of magnitude; a transposed value silently produces a nonsensical J.
  • Treating skin as permanent. Skin changes with scale, fines, and workovers—re-run build-up tests periodically rather than relying on a value from years ago.
  • Ignoring units on k and h. The 0.00708 constant is calibrated for md, ft, cp, and rb/stb specifically—swap in SI units without converting the constant and the result will be off by orders of magnitude.

Related reading

Want to track this across your whole field? Extend the pandas snippet above with one row per well per test date, then feed the output straight into your production-surveillance dashboard.

Saad Iqbal Avatar

About the author

Saad Iqbal

Petroleum Engineer · Well Intervention & Stimulation Specialist

Saad Iqbal is a petroleum engineer and well intervention and stimulation specialist with more than a decade of field experience in hydraulic fracturing, coiled tubing, CSG, tight sandstone and shale developments. He explores practical AI, automation and data-driven engineering for safer, smarter upstream operations.

Discover more from EnergyMindAI

Subscribe now to keep reading and get access to the full archive.

Continue reading