Skip to content

Environment

The room is a mean temperature it swings around over the day, and the temperature and hardness 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 toward a lit fixture’s warmth — and water leaves for the air.

MechanicStatusWhy
Temperature driftsettledNewton’s cooling on the standing water, with a volume exponent that is the surface-to-volume ratio of a solid.
The room’s dayscaffoldingA cosine around roomTemperature, warmest at 17:00, the same every day. No weather, no season.
Light heats the waterscaffoldingA lit fixture raises the temperature the water drifts toward in proportion to its surface PAR, whatever the tank.
Tank geometrysettledOne 2:1:1 box derived from capacity. Depth, floor and glass area come off the same solid, so they can never disagree.
Evaporation ratesettledA continuous fraction of standing volume per hour, doubling every 5.56 °C of differential.
Concentration by evaporationsettledFree, and written nowhere: solutes are stored as mass, so less water is more ppm with no code.
Evaporation directionscaffoldingThe 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 classesscaffoldingFour hardcoded multipliers outside config/, so no declared range guards them and no tuning session can move them.
Geometry tracks standing watermissingDepth and glass area are both derived from capacity. A half-drained tank is lit and colonised as if it were full.
Seasons and weathermissingThe room’s mean and the tap are constants the caller sets at construction.
CoolingmissingThere is no chiller. A tank sits below the room only if the room is that cold, and a heatwave has no answer.
FieldWhat it setsUnit
roomTemperatureThe room’s daily mean — drift pulls toward it, swung by the hour; evaporation reads its differential against the mean°C
tapWaterTemperatureTemperature of every litre added by a water change or the ATO°C
tapKhCarbonate hardness of that same water — a fresh tank is filled with it, and every litre added brings itdKH
tapGhGeneral hardness of that same water, arriving wherever tapKh doesdGH

Defaults are 22 °C, 20 °C, 4 dKH and 6 dGH. None of the four is a stock; 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. Depth is that same height, which is what light is attenuated through, and the floor, 2 × height², is what the plants’ footprints fill. A tank is therefore described by exactly one number, and no dimension can drift out of agreement with another.

ambient = roomTemperature + roomDailySwing × cos(2π (hour − 17) / 24)
+ lightWarmingPerPar × fixture PAR // while lit
volumeScale = (referenceVolume / water) ^ volumeExponent
drift = −sign(ΔT) × min(|ΔT|, coolingCoefficient × |ΔT| × volumeScale) // ΔT = water − ambient

Light heats the surface in proportion to its flux and the surface sheds heat in proportion to its area, so the warming a fixture holds depends on PAR alone. A heater holds its tank at target through all of it; an unheated tank follows the room, damped and late, by as much as its volume lets it:

Tank, unheatedDay’s swing
5 gal~3.5 °F
20 gal~2.6 °F
75 gal~2 °F

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.

VolumeGap closed per hourHalf-life of a differential
20 L22.6 %2.7 h
100 L13.2 %4.9 h
300 L9.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.

LidMultiplier
none1.00
mesh0.75
full0.25
sealed0.00

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

StockFills itDrains itUnit
waterATO, top-off, water change — each clamped at capacityEvaporation, and the removal half of a water changeL
temperatureHeater; blending on an ATO refill or a water changeDrift 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.

The tunables are listed in the reference under Temperature and Evaporation.

NeighbourReadWritten
EquipmentThe lid type, for the evaporation multipliertemperature — the heater fights drift on the same volume scale; water — the ATO refills what evaporated, blending toward tap temperature and adding tap KH and GH 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
LightThe fixture’s surface PAR, while lit, as heatDepth, from the same box capacity implies
Plants · Livestock—temperature is a two-sided stressor for both and a comfort benefit for plants alone; plants stand in the box’s depth and fill its floor
Algae—Capacity, the litres green water fills and the box whose glass film coats; temperature for each kind’s band and respiration; depth, for the column’s mean light
Actions—Tap temperature, KH and GH are what a water change blends toward
Alerts & logging—water below waterLevelStressThreshold of capacity raises the low 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, src/simulation/core/ for the box geometry.