Exerciseschevron_rightChapter 9chevron_right9.9
fitness_center

Exercise 9.9

DCA vs Volumetric Reserves

Level 2
Chapter 9: Decline Curve Analysis
descriptionProblem

Volumetric OOIP is calculated as N=7758×A×h×ϕ×(1Sw)BoN = \frac{7758 \times A \times h \times \phi \times (1 - S_w)}{B_o}. For a well with drainage area 160 acres, net pay 30 ft, porosity 0.18, water saturation 0.25, and BoB_o = 1.2, calculate the OOIP. Assuming a recovery factor of 15%, calculate the expected EUR. Compare this to the DCA-based EUR from this chapter. Why might they differ?

---

A reserves estimate is only as trustworthy as the two independent roads that lead to it. Decline-curve analysis (DCA) reads the well's own production history and extrapolates it to an economic limit. It knows what the rock has actually given up. Volumetric estimation works the other way: it counts the oil originally in place from rock and fluid properties, then multiplies by a recovery factor. When the two agree you book with confidence. When they disagree, the gap is telling you something physical about the reservoir.

Well OD-009 on OML 58 drains a block with these volumetric inputs:

quantityvalue
area_acres160 acres
h_ft30 ft net pay
phi0.18
sw0.25
bo1.2 RB/STB

The standard-condition OOIP (original oil in place, STB) is

N = 7758 * area_acres * h_ft * phi * (1 - sw) / bo

where 7758 converts acre-ft of pore volume to barrels.

Write three functions:

  • volumetric_ooip(area_acres, h_ft, phi, sw, bo) -> OOIP in STB (the formula

above).

  • volumetric_eur(ooip, rf) -> ooip * rf, the recoverable volume at recovery

factor rf.

  • reconcile(area_acres, h_ft, phi, sw, bo, rf, dca_eur_bbl) -> a dict:
keyvalue
ooipvolumetric_ooip(...)
eur_volvolumetric_eur(ooip, rf)
eur_dcadca_eur_bbl (the DCA EUR you carry in, float)
ratioeur_dca / eur_vol

For OD-009 use a recovery factor RF = 0.15 and the chapter's DCA result DCA_EUR_BBL = 540000.0 bbl. Call reconcile(...) on these inputs and store the result in report.

You should find ooip = 4,189,320 STB, eur_vol = 628,398 STB, and a ratio ≈ 0.86: the DCA forecast is about 14% below the volumetric expectation. That gap is not an error; it is the honest spread between two methods. Why might they differ? The drainage area area_acres is an assumption; the well may be draining less rock than the 160-acre spacing unit implies, which would lower the true OOIP and pull volumetric down toward DCA. The recovery factor rf is itself uncertain (drive mechanism, sweep efficiency, well count), so the volumetric EUR carries a wide band. DCA, by contrast, only sees the volume connected to this wellbore over the produced history. A ratio below 1 often means the spacing unit overstates the drainage volume or the assumed RF is optimistic for the recovery seen so far.

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


# ── OD-009 volumetric inputs (OML 58) + chapter DCA result ───────────────
AREA_ACRES = 160.0
H_FT = 30.0
PHI = 0.18
SW = 0.25
BO = 1.2
RF = 0.15
DCA_EUR_BBL = 540000.0


def volumetric_ooip(area_acres, h_ft, phi, sw, bo):
    """Original oil in place (STB): 7758 * A * h * phi * (1 - Sw) / Bo."""
    return 7758.0 * area_acres * h_ft * phi * (1.0 - sw) / bo


def volumetric_eur(ooip, rf):
    """Recoverable volume (STB) at recovery factor rf: ooip * rf."""
    return ooip * rf


def reconcile(area_acres, h_ft, phi, sw, bo, rf, dca_eur_bbl):
    """Compare volumetric EUR to a DCA EUR; return {ooip, eur_vol, eur_dca, ratio}."""
    ooip = volumetric_ooip(area_acres, h_ft, phi, sw, bo)
    eur_vol = volumetric_eur(ooip, rf)
    ratio = dca_eur_bbl / eur_vol
    return {
        "ooip": float(ooip),
        "eur_vol": float(eur_vol),
        "eur_dca": float(dca_eur_bbl),
        "ratio": float(ratio),
    }


report = reconcile(AREA_ACRES, H_FT, PHI, SW, BO, RF, DCA_EUR_BBL)

print(f"OOIP     = {report['ooip']:,.0f} STB")
print(f"EUR_vol  = {report['eur_vol']:,.0f} STB")
print(f"EUR_dca  = {report['eur_dca']:,.0f} bbl")
print(f"ratio    = {report['ratio']:.4f}  (DCA / volumetric)")

lockCopying code is a Full Access feature.