Most well pump questions start with "my well is 200 feet deep." Depth is not what sizes the pump. A pump is selected by flow (gpm) and total dynamic head (TDH, in feet). Here is a small Python model that builds TDH from its parts, so you can see which part dominates.
The model
TDH has four components:
- Lift: static water level + drawdown (the pumping water level, not the well depth)
- Elevation rise: wellhead to the highest fixture
- Pressure head: switch cut-out pressure × 2.31 ft/psi
- Friction: Hazen-Williams loss over drop pipe + service line, plus a fitting allowance
PIPE_ID_IN = {"1": 1.049, "1-1/4": 1.380, "1-1/2": 1.610} # PVC Sch 40 inside diameters def friction_per_100ft(gpm, pipe_id_in, c=150): """Hazen-Williams head loss, ft per 100 ft of pipe.""" return 0.2083 * (100 / c) ** 1.852 * gpm ** 1.852 / pipe_id_in ** 4.8655 def tdh(gpm, static_ft, drawdown_ft, rise_ft, cutout_psi, drop_pipe_ft, service_ft, fittings=0.10, pipe="1-1/4"): lift = static_ft + drawdown_ft # pumping water level, not well depth pressure = cutout_psi * 2.31 # psi -> ft of water length = (drop_pipe_ft + service_ft) * (1 + fittings) friction = friction_per_100ft(gpm, PIPE_ID_IN[pipe]) * length / 100 total = lift + rise_ft + pressure + friction return {"lift": lift, "rise": rise_ft, "pressure": pressure, "friction": friction, "tdh": total} def brake_hp(gpm, tdh_ft, efficiency): return gpm * tdh_ft / 3960 / efficiency Running an example
Illustrative inputs: 12 gpm, 80 ft static level, 40 ft drawdown, 15 ft rise, 40/60 psi switch, 160 ft drop pipe, 100 ft service line, 10% fittings, 1¼ in PVC.
base = dict(static_ft=80, drawdown_ft=40, rise_ft=15, cutout_psi=60, drop_pipe_ft=160, service_ft=100) r = tdh(12, **base) for k, v in r.items(): print(f"{k:>9}: {v:6.1f} ft ({v / r['tdh']:.0%})") print(f"BHP range: {brake_hp(12, r['tdh'], 0.55):.2f}-{brake_hp(12, r['tdh'], 0.40):.2f}") Output:
lift: 120.0 ft (43%) rise: 15.0 ft (5%) pressure: 138.6 ft (50%) friction: 5.8 ft (2%) tdh: 279.4 ft (100%) BHP range: 1.54-2.12 The pressure switch contributes half the head. Friction, the term people often worry about most, is 2%.
Three one-line experiments
print(round(tdh(12, **{**base, "cutout_psi": 40})["tdh"], 1)) # cut-in: 233.2 print(round(tdh(12, **base, pipe="1")["friction"], 1)) # 1 in pipe: 22.2 print(round(tdh(10, **base)["tdh"], 1)) # 10 gpm: 277.8 - Cut-in instead of cut-out: TDH drops by 46.2 ft. A pump picked at 233 ft may never reach the 60 psi cut-out.
- 1 in instead of 1¼ in pipe: friction rises about 3.8× at the same flow.
- Yield limit: if the well sustains only 10 gpm, sizing to 12 gpm overpumps it. Size to the yield and add storage for peaks; brake HP falls to roughly 1.3–1.75.
Limits
- Hazen-Williams applies to water at ordinary temperatures in full pipes.
- The efficiency band (40–55% here) is a placeholder; real selection reads the manufacturer's pump curve at your flow and TDH.
- Check submergence: the pump must sit below the pumping water level.
The useful habit is the dictionary of components, not the total. When one term is half the head, that is where design changes pay off.