Science Journaling Club Founded 2024

INTERACTIVE COMPANION · EQUILIBRIUM CHEMISTRY · SPRING 2025

The Buffer Bench

A live model accompanying “What a Buffer Is Actually Resisting”

← Read the full article

Two benches sit below. The first builds any single weak-acid buffer you like and computes its capacity exactly, with no Henderson-Hasselbalch step anywhere. The second sets the carbon dioxide system up twice at blood pH, once in a stoppered bottle and once with a lung attached, and reports the ratio.

Neither calculator approximates anything. Both solve the full charge balance by bisection, the same way analysis/buffer-capacity.py does, and at their default settings they reproduce the article's headline numbers to the digits printed there.

Model 1. Any buffer you like

Capacity is the slope of a titration curve. Add Cb moles of strong base per litre to a solution holding C moles of weak acid, write down charge balance, and you get the amount of base that lands the solution at a given hydrogen ion concentration h:

Cb(h) = Kw/h − h + C·Ka/(Ka + h)

Differentiating with respect to pH, and using dh/dpH = −ln10·h, gives the capacity:

beta(h) = ln10 · [ Kw/h + h + C·Ka·h/(Ka + h)² ]

The plot draws that. The peak is marked, the half-capacity window is shaded, and the readout reports what a real dose of strong base does to the pH at whatever point you have picked. That last number is not computed from the slope. The page adds the base to the model solution and re-solves the equilibrium for the new pH, which is why the linear estimate and the exact answer drift apart as you raise the dose.

peak at pH: beta at peak: beta here: retained: half window: pH after dose:
default peak
ln(10)·C/4
analytic half-width

At the defaults this bench prints a peak of 0.0575651 mol/L per pH unit against an analytic ln10·C/4 of 0.0575646, the difference being the solvent, and a half-capacity window running from pH 6.234424 to 7.765576. Both figures appear in the article's results table, and both come from the same arithmetic.

Model 2. The bottle against the lung

Same chemistry, two boundary conditions. In a stoppered bottle the total dissolved carbonate is conserved, so acid converts bicarbonate into dissolved carbon dioxide and the buffer consumes itself. With respiration switched on, dissolved carbon dioxide is pinned by the partial pressure in the lung, and the capacity becomes

beta_open = ln10 · [ Kw/h + h + K1·S/h + 4·K1·K2·S/h² ]

where S = alpha · pCO₂ is held constant. The third term is just ln10 · [HCO₃−], which is why the open capacity rises with pH instead of peaking: at fixed partial pressure, every pH unit multiplies the bicarbonate by ten.

bicarbonate: beta open: beta closed: ratio: pH after load:
simple prediction
model ratio
total carbonate

The simple prediction shown above is 1 + 10^(pH − pK₁'), which is what you get by dropping the carbonate ion and the water terms from both capacities. At the defaults it reads 20.953 against the full model's 19.498. The gap is the carbonate ion, and it is the reason the article's Monte Carlo puts a wide prior on pK₂'.

Three things worth doing

Set model 1 to pKa 7.000 and slide the working pH to 8.000. The retained fraction reads 0.3306, which is 40/121 exactly, and the article's arithmetic section derives that with a pencil.

Set the dose in model 1 to 20 mmol/L and compare the exact pH against the linear estimate. The slope is an honest guide near the peak and a liar once you have left it.

In model 2, switch respiration off and then slide pCO₂ from 40 to 80. Nothing much happens to the ratio, because both systems scale together. Switch respiration back on and slide pK₁' instead. That is where the physiology actually lives.