Skip to content

Environment

The room is three fixed numbers — its temperature, and the temperature and pH of the tap. The tank is one number, capacity, from which a single box shape gives both the depth light falls through and the glass a biofilm colonises. Between them run the two passive exchanges nothing has to switch on: heat leaks toward the room, and water leaves for the air.

Mechanic Status Why
Temperature drift settled Newton’s cooling on the standing water, with a volume exponent that is the surface-to-volume ratio of a solid.
Tank geometry settled One 2:1:1 box derived from capacity. Depth and glass area come off the same solid, so they can never disagree.
Evaporation rate settled A continuous fraction of standing volume per hour, doubling every 5.56 °C of differential.
Concentration by evaporation settled Free, and written nowhere: solutes are stored as mass, so less water is more ppm with no code.
Evaporation direction scaffolding The differential is read as an absolute value, so a tank 3 °C below the room evaporates exactly as fast as one 3 °C above it.
Lid classes scaffolding Four hardcoded multipliers outside config/, so no declared range guards them and no tuning session can move them.
Geometry tracks standing water missing Depth and glass area are both derived from capacity. A half-drained tank is lit and colonised as if it were full.
Room conditions vary missing All three are constants the caller sets at construction. Nothing in the tick moves them, so there is no diurnal swing and no season.
Cooling missing There is no chiller. A tank sits below the room only if the room is that cold, and a heatwave has no answer.
Field What it sets Unit
roomTemperature The target temperature drift pulls toward, and the reference evaporation reads its differential against °C
tapWaterTemperature Temperature of every litre added by a water change or the ATO °C
tapWaterPH pH of that same water, blended in through H⁺ concentration rather than by averaging pH

Defaults are 22 °C, 20 °C and 6.5. None of the three is a stock and none of them drifts; they are boundary conditions the tank runs against.

Capacity implies a shape and the shape implies everything else:

height = ∛(capacity / 2) × 10 cm
width = height
length = 2 × height

Glass surface is four walls plus the bottom — the open top is not colonisable — and depth is that same height, which is what light is attenuated through. A tank is therefore described by exactly one number, and no dimension can drift out of agreement with another.

volumeScale = (referenceVolume / water) ^ volumeExponent
drift = −sign(ΔT) × min(|ΔT|, coolingCoefficient × |ΔT| × volumeScale)

The exponent is ⅓ because a box’s surface grows as the ⅔ power of its volume, so area per litre falls as the cube root — which is the whole reason a nano is harder to hold steady than a 300 L. The min is what stops a tick overshooting the room and oscillating. Drift reads standing water, not capacity, so an evaporating tank grows twitchier as it empties.

Volume Gap closed per hour Half-life of a differential
20 L 22.6 % 2.7 h
100 L 13.2 % 4.9 h
300 L 9.2 % 7.2 h
tempFactor = 2 ^ (|ΔT| / tempDoublingInterval)
loss = water × (baseRatePerDay / 24) × tempFactor × lidMultiplier

At thermal equilibrium an open tank loses 1 % of its water a day. A 25 °C tank in a 22 °C room runs a 3 °C differential, which is 1.45 %/day — enough to trip a 99 % ATO inside a day, and to leave an untended tank a fifth empty in about two weeks.

Lid Multiplier
none 1.00
mesh 0.75
full 0.25
sealed 0.00

The lid reaches evaporation and nothing else. A sealed tank exchanges gas with the atmosphere exactly as freely as an open one.

Stock Fills it Drains it Unit
water ATO, top-off, water change — each clamped at capacity Evaporation, and the removal half of a water change L
temperature Heater; blending on an ATO refill or a water change Drift toward the room — which is also its fill when the room is warmer °C

Evaporation removes water without solutes. Every dissolved mass stays exactly where it was, so every ppm rises, and no system had to be told.

Constant Meaning Unit
coolingCoefficient Share of the temperature gap closed per hour at the reference volume 0.132 /hr
referenceVolume The volume coolingCoefficient is quoted at 100 L
volumeExponent How the rate scales with volume — the surface-to-volume power 1/3
baseRatePerDay Water lost per day at zero differential, before the lid 0.01 /day
tempDoublingInterval Differential that doubles the evaporation rate 5.56 °C

The four lid multipliers are module constants rather than tunables, so they sit outside the range-declaration rule the rest of the engine follows.

Neighbour Read Written
Equipment The lid type, for the evaporation multiplier temperature — the heater fights drift on the same volume scale; water — the ATO refills what evaporated, blending toward tap temperature and tap pH as it does
Water & gases temperature sets O₂ saturation, and standing water is the divisor every gas mass passes through
Nitrogen cycle temperature drives the nitrifier Q10; water turns stored mass into the ppm every threshold reads
Light Depth, from the same box capacity implies
Plants · Livestock temperature is a two-sided stressor and a benefit channel for both
Algae Standing water, to turn stored nutrient mass into the ppm the ratio needs
Actions Tap temperature and tap pH are what a water change blends toward
Alerts & logging water below 20 % of capacity raises the critical water-level alert
State & persistence tank.capacity — what every per-litre seed figure resolves against

src/simulation/systems/ for drift and evaporation, src/simulation/config/ for their tunables; the box geometry is derived at the state root.