Turning Tank Level Into Volume Without Getting the Inventory Wrong
Building a strapping table into SCADA: segment geometry, interpolation spacing, where the calculation runs, and the density trap in hydrostatic level.
920 litres that were never in the tank
The day tank shows 380 mm on the level transmitter and the SCADA inventory tag says 1,470 L. The operator dips it, the tank is horizontal, and the real number is closer to 550 L. Nobody typed a bad range. The transmitter is fine, the scaling is fine, the 4–20 mA loop checked out at commissioning. What happened is that somebody scaled level to volume with a straight line, and a horizontal cylinder is not a straight line.
That's the whole problem in one sentence: level is a height, volume is a shape. They're only proportional in one case — a vertical cylinder with a flat bottom, no dished head, no internal structure. Every other tank on site needs a table.
What the geometry actually does to you
Take a real vessel: 2.5 m diameter, 6 m long, horizontal, ignoring the heads for now. Full shell volume is about 29.4 m³.
Fill it to 5% of the diameter — 125 mm of liquid in the bottom. The wetted cross-section is a circular segment:
A = r²·acos((r−h)/r) − (r−h)·√(2rh − h²)
V = A · L
That works out to 0.55 m³, or 1.9% of the tank. A linear scale would have reported 5%, or 1.47 m³. You've invented 920 litres of product out of arithmetic. At the top of the tank the error flips sign — 95% level is 98.1% volume — so the tank also overflows earlier than the inventory screen suggests.
The middle is where linear scaling looks fine and lulls people into keeping it. At half full, the segment formula and the straight line agree exactly. So the tag validates beautifully at the one point everybody checks and is worst at the two points that matter: nearly empty, and nearly full.
The strapping table, and why the spacing isn't uniform
A strapping table is just a list of (level, volume) pairs from a real tank calibration — manual strapping per API MPMS Chapter 2.2A, or the equivalent ISO 7507-1 method for upright cylindrical tanks, or a liquid calibration for odd shapes. You interpolate between the points. For a fabricated vessel with dished heads you want the measured table rather than a formula, because 2:1 ellipsoidal heads, a sloped bottom, an internal heating coil and a suction well are all in the real numbers and none of them are in your equation.
The tempting implementation is a uniformly spaced table — a point every 100 mm — so you can index it with integer division and skip a search. That's the right instinct in general, and it's wrong at the bottom of a horizontal tank. Here's why: the slope of the volume curve is the chord width, which near the bottom goes as √h. Its derivative blows up as h → 0, and linear interpolation error scales with that curvature.
Numbers on the same 2.5 m tank, 100 mm table spacing:
| Level | True volume | Interpolated from 100 mm table | Error |
|---|---|---|---|
| 50 mm | 141 L | 198 L | +40% |
| 1,250 mm | 14,726 L | 14,726 L | ~0 |
Mid-shell the interpolation is essentially exact. In the first interval it's off by 40%. So: cluster the table points where the curvature is — 10–25 mm steps through the bottom 10% and the top 10%, 100 mm through the straight shell. That costs you the cheap indexing trick and forces a search, which for a 60–120 point table is a handful of comparisons on a scan that has bigger problems. Take the accuracy.
Two more table rules I don't compromise on:
- Clamp, don't extrapolate. Below the first point and above the last, hold the endpoint value and set the quality bad or raise a "level out of table range" flag. Extrapolating a √h curve past its ends produces numbers that look plausible and aren't.
- The table starts at the datum the calibration used, which is usually the tank bottom or a dip plate — not the transmitter's zero. If your radar reads distance from the flange, you need reference height minus distance, and that offset belongs in one place, documented, not folded silently into the table.
Where the calculation lives
Three candidates, and the answer isn't "wherever it's easiest to type."
Put it in the PLC or RTU if anything automatic uses volume: a pump permissive, a batch cut-off, a transfer interlock, a high-level trip on volume rather than height. Control logic should not depend on a value computed by a supervisory system that can drop off the network.
Put it in SCADA if volume is purely for display, reporting and inventory. Most SCADA platforms have a lookup/interpolation function or an expression tag; this is what it's for. A 100-point table in a PLC eats retained memory and is painful to correct after a re-strap, whereas editing a SCADA lookup is a five-minute change with an audit trail.
Do not put it in both. The classic mess is the PLC computing volume for the interlock and SCADA computing its own from raw level with a slightly different table version. They agree for a year, someone re-straps the tank after a repair, one side gets updated, and now the trend and the trip disagree by a few hundred litres with no obvious culprit.
And don't compute it in the historian as a calculated tag if the number is used operationally. Historian calculations run on stored data — they inherit its gaps, its compression deadband and its late arrivals. Fine for a monthly inventory report, bad for anything on the operator's screen.
The density trap
If level comes from a hydrostatic (DP) transmitter, you are not measuring height. You are measuring head pressure:
h = P / (ρ·g)
The device converts to height using a fixed density you configured. Store a product at 800 kg/m³, receive a batch at 810, and the indicated level is 1.25% low across the whole range — which then goes through the strapping table and comes out as a volume error that no amount of table accuracy fixes. Same story with temperature: warm the product and the density drops, the hydrostatic head for the same mass stays put, and the level tag creeps up while nothing physically moved.
If you actually care about inventory, this is the fork in the road:
- Volume only, product density stable — hydrostatic plus strapping table is fine. Document the configured density on the tag description so the next person knows the assumption exists.
- Volume with varying grade or wide temperature swing — go to a level technology that measures geometry, not weight: guided-wave radar or non-contact radar. Radar doesn't care what the density is.
- Mass or standard volume — that's a different job. Correcting gross observed volume to standard volume at 15 °C means volume correction factors per API MPMS Chapter 11.1 (ASTM D1250), plus tank shell thermal expansion, plus a floating-roof adjustment if there is one, all of which live in API MPMS Chapter 12.1. Do not reimplement VCF polynomials in ladder logic. That belongs in a flow computer or a tank inventory package that gets audited.
For custody transfer the whole discussion changes anyway — ISO 4266 and the API standards govern how the level and temperature are measured in the first place, and a SCADA-computed inventory number is a monitoring aid, not a ticket.
Commissioning it
Checking volume against a manual dip at one point proves nothing — as established, the middle of the tank is where every method agrees. Check it where it's hard:
- Near-empty, just above the lowest table point. This is where linear scaling and coarse tables fall apart, and where the strapping table's own accuracy is worst because a millimetre is worth almost nothing until it isn't.
- Near-full, above the shell tangent line if the tank has heads.
- Across a transfer, not absolutely. Run a known quantity in — a metered truck delivery or a timed transfer against a calibrated flow meter — and compare the change in the volume tag. Delta-volume cancels out datum and offset errors and tests the table's shape, which is the part you actually wrote.
One thing that catches people on the historian side: set the deadband on the volume tag in volume units, not as a percentage of level. Near the bottom of a horizontal tank a 5 mm level change is a few litres; mid-shell it's a hundred. A percentage-of-level deadband either floods you with events at mid-shell or blinds you to real movement near empty. Same reason your high-level alarm should stay on the level tag — it's protecting against overflow, which is a height, and putting it on a derived volume adds a calculation between the sensor and the trip for no benefit.
The next thing to check, if the numbers still don't close: tank tilt. A vessel that settled 15 mm out of level over ten years invalidates the bottom of the strapping table long before it affects the middle, and the only fix is a re-strap — not a fudge factor in the SCADA expression, however tempting that is at month end.