# "Cookbook: fire, heat and reactions"

# Cookbook: fire, heat and reactions

Each recipe says what to build and what to expect. The guides ([heat](../reference/heat.md), chemistry (skill `ferret-physics-chemistry-nuclear`), electric (skill `ferret-physics-electric`), links (skill `ferret-physics-links`)) explain the parts, and the runnable versions, with the numbers they must produce, are in `tests/unit/examples/physics-cookbook-fire-and-heat.test.ts`.

## 1. Boil a pot on a fire

A pot is a heat part fed with the power of a fire. The temperature climbs, **holds at 373.15 K while the latent heat is paid**, and the water is gone only when 2.26 MJ per kilogram have gone in.

```ts
const net = new HeatNetwork();
const water = net.addPart({ name: 'water', mass: 1, material: M.water, T: 293.15, power: 2000 });
net.step(0.5);
water.phase;               // 'liquid', then 'gas' once the latent heat is paid
```

One kilogram on a 2 kW burner reaches the boiling point after about 170 s (80 K at 4186 J/kg K) and boils off 1130 s later. Change `power` for a hotter fire, `mass` for a bigger pot; give the part `area` and `h` and it loses heat to the air, so a weak fire never gets there.

## 2. A steel beam in a fire

Steel does not melt in a building fire; it **loses strength**. At 600 °C (873 K) it holds only 40 % of its cold strength, so a beam that carries its load at room temperature fails. `strengthFactor` gives the fraction left at a temperature:

```ts
const beam = net.addPart({ name: 'beam', mass: 50, material: M.steel, T: 293.15, power: 20e3, area: 1.2, h: 25 });
net.step(1);
if (strengthFactor(M.steel, beam.T) < 0.6) { /* a beam carrying 60 % of its cold strength has failed */ }
```

The beam fails hot but far below the melting point. Put a cladding of insulation (a second part joined with `net.join` and a low conductance) between the fire and the beam, and the same code gives the fire rating of a wall: the minutes until the factor falls below the load.

## 3. A pressure cooker that bursts

A sealed tank is heated from a wall; the pressure follows the temperature. When it passes the wall's limit, the tank is a bomb: hand the numbers to explosions (skill `ferret-physics-combustion-explosions`).

```ts
const wall = net.addPart({ name: 'wall', mass: 3, material: steel, T: 293.15, power: 3000 });
const gas = new GasVolume({ moles: 2, temperature: 293.15, volume: 0.01 });
const link = gasInPart(gas, wall, net, 20);          // 20 W/K between wall and gas
const burstAt = 5 * gas.pressure;                    // the tank holds 5 times its starting pressure
// each step
net.step(dt); link.step(dt, host, []);
if (gas.pressure > burstAt) { const tnt = vesselTnt(gas.pressure, 0.01); }
```

Pressure at constant volume is proportional to absolute temperature, so a vessel at five times its start pressure is five times as hot in kelvin. A 10 litre cooker at that pressure makes a few tens of grams of TNT. Hand `{ pressure: gas.pressure, volume: 0.01 }` to `explosions.detonate({ vessel })` when it goes.

## 4. A kettle on a breaker

A 2.3 kW kettle on 230 V draws 10 A. Add a hair-dryer on the same circuit and the 16 A breaker trips on its thermal curve:

```ts
c.add(new VSource('V', 'a', '0', 230));
const breaker = c.add(new Breaker('B', 'a', 'b', 16, 10, 8));    // 16 A rated, 10 s thermal constant, magnetic at 8 x
c.add(new Heater('Kettle', 'b', '0', 230 * 230 / 2300));
c.add(new Resistor('Dryer', 'b', '0', 230 * 230 / 2000));
c.onEvent = e => { if (e.type === 'trip') { /* ... */ } };
```

The kettle alone is fine. With the dryer the circuit carries 18.7 A on a 16 A breaker and trips after some seconds. The thermal element trips later for a smaller overload and sooner for a larger one; a short circuit trips the magnetic element in a couple of milliseconds.

## 5. A cold pack

An endothermic dissolving reaction cools a drink: the vessel is in contact with the drink, and the drink gives the heat.

```ts
chem.add('b2a', { reactants: { B: 1 }, products: { A: 1 }, A: 0.05, Ea: 0, phase: 'solution' });   // +50 kJ per mole
const pack = new Vessel(chem, { volume: 1e-3, contents: { B: 1, Solvent: 100 }, hA: 5 });
const drink = net.addPart({ name: 'drink', mass: 2, material: water, T: 298.15 });
const link = vesselInPart(pack, drink, net);
// each step
pack.react(dt); net.step(dt); link.step(dt, host, []);
```

One mole at 50 kJ takes about 6 K out of 2 kg of water. The scene's energy stays closed to 0.1 %: put a pack, a drink and the link into a `links` capability account to see it.

## 6. Thermal runaway

An exothermic batch reaction with cooling is stable below a critical ambient temperature and runs away above it. The tipping point is a property of the vessel, not of the reaction alone.

```ts
chem.add('go', { reactants: { A: 1 }, products: { B: 1 }, A: 1e9, Ea: 70e3, phase: 'solution' });
const v = new Vessel(chem, { volume: 1e-3, T: Tenv, Tenv, hA: 3, contents: { A: 1, Solvent: 20 } });
v.react(1);
```

The rise above ambient grows steeply with the ambient temperature; this is the signature of runaway. A batch at 280 K stays modest; the same batch at 340 K heats itself far more. With the capability on, `chem:runaway` fires when the heating rate passes `runaway` (50 K/s by default), which is the hook for an alarm or a relief valve.

## 7. An overloaded wire

A wire at its ampacity settles at its rated temperature rise; above, it reaches the insulation limit on its thermal time constant.

```ts
c.add(new ISource('I', '0', 'a', amps));
c.add(new Wire('W', 'a', '0', 0.01, 5, 10, 100, 343.15, 293.15, 40));    // 10 A rating, 40 K rise, insulation limit 343 K
c.onEvent = e => { if (e.type === 'overheat') { /* ... */ } };
```

At 10 A the wire settles at its rated rise and never overheats; at 15 A it does. Tie `circuit:overheat` to a fire with the `wireFire` link, and put a fuse (skill `ferret-physics-electric`) in series to prevent it: size the fuse's `i2t` below what takes the wire to its limit.

## 8. A glowing brake disc

Braking turns the kinetic energy of the car into heat in the disc. Once the disc passes 798 K it starts to glow, and the glow is what `glow` paints on the mesh.

```ts
const brake = train.brake('brake', car, 3000);
brake.command = 1;
const link = slipHeats(brake, disc, net);
// each step
train.step(dt, 4); net.step(dt); link.step(dt, host, []);
const glowAmount = incandescence(disc.T), colour = blackbody(disc.T);
```

All the kinetic energy goes into the disc: 1.5 MJ in 2 kg of steel is far past the point where it glows red-orange. Hand the disc's `T` to `glow(scene, mesh, () => disc.T)` and the render does the rest. The numbers are exaggerated on purpose (a 2 kg disc, one hard stop): a real car brakes in many pulses with cooling in between.
