A cut-away of a 7.3 m bin. Fill it with harvest-moist grain, pick the weather and a fan, and watch the drying front climb through the bed while the air's humidity, the grain's equilibrium moisture and the mould clock decide whether the crop is safe.
Compares the code with textbook psychrometric values, closed-form Page drying, a hand-computed Shedd value, the fan operating point, a water mass balance and the drying-front speed formula.
The science
Psychrometrics. Moist air is described by dry-bulb temperature T and humidity ratio W (kg water per kg dry air). Saturation pressure follows the Hyland–Wexler fit; with pv = RH·psat:
W = 0.622 · pv / (P − pv) h = 1.006 T + W (2501 + 1.86 T) [kJ/kg]
Wet-bulb temperature is the adiabatic-saturation temperature, found by solving the ASHRAE enthalpy balance. Heating air at constant W lowers its RH: that is why a few degrees of heat make air thirsty.
Equilibrium moisture content (EMC). Grain sits at a moisture that depends only on the air's RH and temperature. Modified Henderson (ASAE D245 form), Me in % dry basis:
1 − RH = exp[ −K (T + C) MeN ]
The modified Halsey curve RH = exp[−exp(A + B T) M−C] is fitted here to the Henderson curve (RH 30–85 %, 5–35 °C), so the two can be compared; they agree within about 0.7 moisture points. If the air's EMC is below the grain's moisture the grain dries; above it, the grain re-wets.
Thin-layer drying (Page). One kernel layer in constant air follows the moisture ratio
MR = (M − Me)/(M0 − Me) = exp(−k tn), k = k25 exp[Ea/R (1/298 − 1/T)]
Because air and Me change as the air passes up the bed, each layer is advanced with the equivalent-time method (invert MR for the time already spent, add Δt, evaluate again).
Deep bed. The bin is marched layer by layer (48 layers). Air at dry-air mass flux G enters a layer, grain and air exchange heat (>99 % complete in a layer), evaporation takes latent heat hfg (with a bound-water correction), and the humidity gained is ΔW = evaporated mass / (G Δt). Air may leave a layer at most in equilibrium with that layer's grain. The result is a drying front that moves up at about
v ≈ G · (Wout − Win) / [ ρdry (M0 − Me) ] (m/s)
so doubling the airflow doubles the speed, and each extra point of moisture to remove is paid for in time or energy. Grain below the front stays dry; grain above stays wet and keeps respiring.
Airflow and fan. Resistance of grain to airflow follows Shedd's equation (ASAE D272 form):
ΔP / L = a q2 / ln(1 + b q) (Pa/m, q in m/s)
with a 10 % allowance for the perforated floor and plenum. The centrifugal fan is modelled as P = P0(1 − (Q/Q0)2) with a hump-shaped efficiency (peak 65 %); the operating point is where the fan curve crosses the bed's resistance curve, so a deeper bed or a finer crop gives less air for the same fan. A rule of thumb for natural-air drying is about 1 m³/min per tonne (≈ 1 cfm/bu).
Safe storage time. Our rule-of-thumb fit (not a published equation) estimates the days to ~0.5 % dry-matter loss, the first measurable quality loss:
t = 150 d · 2−(T−15)/5.5 · 2−(RHeq−70)/4 (no mould growth below RHeq = 65 %)
Each layer accumulates D = ∫ dt / t; D = 1 marks the layer as spoiled. It captures the well-known trends (storage time halves for every ~5.5 °C or ~1 moisture point) but is not a substitute for published storage tables.
Honest simplifications. Constant bed volume (no shrinkage), no respiration heat or moisture, no insects, no wall/top-surface moisture exchange except a slow temperature leak to the outside mean, the grain heap peak is drawn but not modelled, uniform fill, crop parameters are typical values rather than variety-specific, electricity and fuel costs are illustrative. Not agronomic advice.
Baked 3D scene. The bin, fan, heater, elevator, grain wagon and combine, and their baked albedo, normal and ambient-occlusion maps come from Blender 5.2. The terrain (harvested stubble field with swath stripes), bale, tree and stubble scatter and the baked occlusion & sun-shadow lightmap come from Unity 6. Three.js r160 runs the live part.