Works out the peak sanitary flow in each pipe of a gravity network from people and area, checks capacity and velocity, and picks pipe sizes.
How the precision is kept
Flows are 64-bit products of population, per-person flow and a peaking factor, plus infiltration. The peaking factor is an empirical formula (Harmon or Babbitt) held between two limits, so the method sets the accuracy. The gallon to cubic foot factor is typed to 9 significant digits. Capacity, normal depth and part-full area come from hydro.js.
Open item. Write the gallon factor as 231 ÷ 1728 so it is exact to 64-bit.
Calculations under this policy
6 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
The factor that turns gallons into cubic feet in feet projects.
1 gal = 0.133680556 ft³
A typed constant with 9 significant digits. A US gallon is 231 cubic inches, so the exact factor is 231 ÷ 1728 = 0.1336805555…; flows in feet projects therefore carry 9 digits from this factor, not 15.
sewer.js
line 30
CivilCraft 0.8.1
export const GAL_FT3 = 0.133680556; // one US gallon in cubic feet
Peaking factor
64-bit
The ratio of peak to average sanitary flow for a population.
Harmon: 1 + 14 ÷ (4 + √P); Babbitt: 5 ÷ P^0.2; P in thousands; held between pfMin and pfMax
One 64-bit expression; the division is safe because zero population returns pfMax before the formula. The formulas are empirical, so their own fit, not the arithmetic, limits the result.
sewer.js
lines 57 to 62
CivilCraft 0.8.1
/** The peaking factor for a population (people, not thousands), held between pfMin and pfMax. Zero people: pfMax. */
export function peakingFactor(pop, sw) {
const P = Math.max(0, pop) / 1000;
const f = !(P > 0) ? sw.pfMax : sw.peak === 'babbitt' ? 5 / Math.pow(P, 0.2) : 1 + 14 / (4 + Math.sqrt(P));
return Math.min(sw.pfMax, Math.max(sw.pfMin, f));
}
Average flow from people
64-bit
People times per-person daily flow, in project flow units.
m: P × L/day ÷ 1000 ÷ 86400; ft: P × gal/day × 0.133680556 ÷ 86400
Multiplications first, then the divisions by 1000 and 86400, which are exact whole numbers. The feet branch uses the rounded gallon factor.
sewer.js
lines 64 to 65
CivilCraft 0.8.1
/** Per person a day and infiltration per area → project flow units (m³/s | cfs). */
const domFlow = (pop, sw, units) => (units === 'm' ? (pop * sw.perCap) / 1000 / 86400 : (pop * sw.perCap * GAL_FT3) / 86400);
Infiltration flow
64-bit
Tributary area times the infiltration allowance, in project flow units.
m: ha × L/s per ha ÷ 1000; ft: ac × gal/day per ac × 0.133680556 ÷ 86400
One 64-bit product and exact divisors; the feet branch uses the rounded gallon factor.
For each pipe in flow order: the people and area above it, the peak flow, the slope, the full capacity, the normal depth and the velocity.
S = (inv up − inv down) ÷ length; Q = q_dom × pf + q_inf; ratio = Q ÷ Q_full; V = Q ÷ A(yn)
People and area are added down the network in flow order in 64-bit. The slope divides by the plan length from Math.hypot and is zero when the length is zero. The over-capacity test adds an absolute 1e-12 to the limit. Percentages in the problem messages are rounded for the text only.
Harmon 1 + 14 ÷ (4 + √P) or Babbitt 5 ÷ P^0.2 with P in thousands; Q = P × per-person flow × peaking factor + infiltration; Manning full-pipe capacity and normal depth from hydro.js.
Number types
64-bit numbers.
Tolerances
A pipe is over its limit when Q > maxFull × capacity + 1e-12 (absolute, in flow units).
Limits
The peaking formulas are empirical. One US gallon is taken as 0.133680556 ft³; the exact value is 231 ÷ 1728 = 0.13368055… (repeating 5). The file header calls the default design values placeholders, not a standard.
Approach: 64-bit, stated limit
The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.