Heat
Package @ferret/physics-heat, capability name heat, phase stretch (order 1000: it runs at the very end of the step).
What it is for#
Things that get hot and cold: a block of ice that melts, a pot of water that boils, a steel beam that sags in a fire, a bar held between two walls that buckles when heated, a brake disc that warms by the work of braking, a wall that insulates. Heat is the bookkeeper of energy: work lost in contacts (friction, inelastic hits) turns into heat in the parts that touched, so the energy of a scene closes. Other capabilities hand heat to it: a fire heats a pot (see links), a reaction heats a vessel.
The model#
A HeatNetwork is lumped parts joined by conductances. A part (a body, a wall segment, a gas, a reservoir) has mass, a material, a temperature T, and an enthalpy H (J, counted from 0 K as a solid). The state is the enthalpy, so a phase change holds the temperature while its latent heat is paid, and the energy balance closes exactly. The network is stepped by Crank–Nicolson (second order, stable at any step); parts run in insertion order, so a replay gives the same temperatures.
Heat moves by:
| Path | Law | Dials |
|---|---|---|
| conduction between joined parts | Q = G (T₁ − T₂) | conductance G (W/K); a wall of layers in series: wallConductance = A / Σ(Lᵢ/kᵢ) |
| convection to the surroundings | Q = h A (T − T_amb) | h (W/m²K) and area; EXAMPLE_CONVECTION has still-air and flowing values |
| radiation | Stefan–Boltzmann ε σ A (T⁴ − T_amb⁴) | radiates: true, emissivity |
| sources | power (W) or add(part, joules) | continuous heating or a pulse |
| mechanical loss | share frictionToHeat of the energy lost in a contact | friction, rolling, inelastic hits |
A material (HeatMaterial): density, c (specific heat J/kgK), k (conductivity), emissivity, melt and boil ({T, latent, c}: the temperature, the latent heat J/kg and the specific heat of what comes after), alpha (linear expansion 1/K), E (Young's modulus), sigmaMax and strengthCurve (stress held, and its fall with temperature as [K, factor] points), ignition (K). EXAMPLE_HEAT_MATERIALS: steel, copper, aluminium, concrete, brick, wood, glass, insulation, water, ice.
First use: ice melts, water warms#
import { HeatNetwork, EXAMPLE_HEAT_MATERIALS as M } from '@ferret/physics-heat';
const net = new HeatNetwork();
net.ambient = 293.15;
const ice = net.addPart({ name: 'ice', mass: 1, material: M.ice, T: 263.15, power: 1000 }); // 1 kg at -10 C, heated with 1 kW
const phases: string[] = [];
net.onEvent = e => { if (e.kind === 'phase') phases.push(e.to); };
let reached = -1, liquid = -1, t = 0;
while (t < 2000 && liquid < 0) {
net.step(0.25); t += 0.25;
if (reached < 0 && ice.T >= 273.15 - 1e-9) reached = t;
if (ice.phase === 'liquid') liquid = t;
}
const plateau = (liquid - reached) * 1000; // J paid at the melting point
The temperature sits at 273.15 K until the latent heat (334 kJ for 1 kg) has been paid, to within 1 %, then rises as water at 4186 J/kgK. Boiling does the same at 373.15 K with 2.26 MJ/kg. Events: heat:phase { part, to, from }, heat:over { part, limit, value } (a limit of temperature or 'stress'), heat:ignite { part } (a part with an ignition temperature passes it).
Recipes#
Cooling to the surroundings#
A part with area and h cools as T_env + (T₀ − T_env) e^(−t/τ) with τ = m c / (h A). Give ambient per part when one object sits in a different environment (a freezer), or set the world's ambient (293.15 K by default).
Two things in contact#
net.join(a, b, G) makes them exchange heat; they reach the heat-capacity-weighted mean and the stored energy stays constant within 0.1 %. In a world, contactConductance (W/K, 0 = none) makes parts that touch exchange heat.
A wall with layers, a rod with a transient#
net.grid({ name, material, nx, dx, thickness, edge: { left: T, right: T } }) builds a rod of cells between held ends; steady conduction is k A ΔT / L, a multi-layer wall is the series resistance, and the transient follows the error-function solution within 3 %. wallConductance is the quick way to get G for join.
A bar that cannot grow#
A free bar grows by α L ΔT (expansion); a held bar (held: true, length) carries a thermal stress E α ΔT (compression when heated), reported by net.stress(part) and thermalStress. Past sigmaMax (times strengthFactor(material, T) when the material has a strengthCurve) the part raises heat:over with limit: 'stress', and with strength on it breaks the body. A steel beam therefore fails sooner in a fire than on a hot day: its curve takes strength away (strengthFactor(steel, 873 K) = 0.4).
import { HeatNetwork, EXAMPLE_HEAT_MATERIALS as M, expansion, thermalStress, type HeatMaterial } from '@ferret/physics-heat';
const flat: HeatMaterial = { ...M.steel, strengthCurve: undefined };
const net = new HeatNetwork(); net.ambient = 293.15;
const bar = net.addPart({ name: 'bar', mass: 1, material: flat, T: 293.15, length: 1, held: true, power: 490 }); // 1 K per second
let breaksAt = -1;
net.onEvent = e => { if (e.kind === 'over' && e.limit === 'stress') breaksAt = e.part.T; };
for (let t = 0; t < 400; t += 0.5) net.step(0.5);
const expected = 293.15 + 400e6 / (200e9 * 12e-6); // sigmaMax / (E alpha)
Friction turns into heat#
With the capability on, a body given a temperature (cap.attach(entity, { material: 'steel', T: 293.15 })) warms by exactly the mechanical energy lost: a 2 kg block sliding at 5 m/s to rest warms by ½ m v² / (m c) and the energy of the scene closes. frictionToHeat (default 1) is the share that becomes heat; lower it if you want some to be sound.
In a world#
heat() is a capability with its own network and material library; cap.attach(entity, def) gives a rigid body's entity a part (and cap.partOf(entity) reads it). Commands: heat.part.add {name, material, mass|volume, T?, area?, h?, radiates?, fixed?, power?}, heat.set {part, T}, heat.add {part, joules?|watts?}, heat.join {a, b, conductance}, heat.state (temperatures, phase, stored energy), heat.info, heat.step {dt}.
Parameters#
| Capability value | Default | Effect |
|---|---|---|
ambient | 293.15 K | temperature of the surroundings |
frictionToHeat | 1 | share of lost mechanical energy that becomes heat |
contactConductance | 0 | W/K between parts that touch |
PartDef | Meaning |
|---|---|
mass or volume | kg, or volume with the material's density |
T, ambient | start temperature, K; its own surroundings |
area, h, radiates | exposure to the surroundings |
fixed | a heat bath held at its temperature |
power | continuous heating, W |
length, held, reference | bar for thermal stress; stress-free temperature |
limit | temperature that raises over once |
Interplay#
linksjoin heat to other capabilities:vesselInPart(a chemical vessel sits in a part),gasInPart(a hot wall warms a tank's gas and raises its pressure),slipHeats(a slipping clutch heats its housing).strength: a part over its stress limit breaks the body (when strength is on).combustionandchemistryproduce heat for parts;nuclearproduces decay heat.- A material
ignitiontemperature raisesheat:ignite: what burns is the job of combustion.
Budget#
Linear in parts and links: hundreds of parts per step are cheap; a grid of 1000 cells is still well below a millisecond. Crank–Nicolson is stable at any step, so you can step the network at a coarser rate than physics when only slow heating matters.
Debugging#
| Symptom | Cause |
|---|---|
| Temperature never changes | no source, no link, no convection area: heat has nowhere to flow; check area and h |
| Phase never changes | the material has no melt or boil, or the part has not stored the latent heat yet (the plateau is correct) |
| Energy does not close | you changed a part's T by hand (setTemperature) or a held/fixed part exchanged heat with the boundary: see the boundary count |
| A held bar never breaks | sigmaMax missing, or the temperature rise is below σ/(E α) (about 170 K for steel) |
| Heat from friction is absent | the body has no part (attach) or the heat capability is off |
| Stress is positive | cooled and held: tension |
Reference#
heat, HeatCapability, HeatNetwork, PartDef, HeatMaterial, HeatLibrary, EXAMPLE_HEAT_MATERIALS, expansion, thermalStress, strengthFactor, wallConductance, HEAT_DEFAULTS, @ferret/physics-heat.