# "Scenario: a tank in a fire"

# Scenario: a tank in a fire

A sealed steel tank of gas stands beside a crate. A fire burns under it. The wall warms, the gas warms with it, the pressure rises with the absolute temperature, and when the pressure passes what the shell holds the tank bursts: an air blast with a steel casing that flies apart. The crate nearby is pushed. This is the BLEVE that fire services plan around, and it needs no special code: five packages, three of which never heard of each other.

## The chain

| Stage | Capability / object | Hands over |
|---|---|---|
| Fire: a power into the wall | heat (skill `ferret-physics-heat`) `HeatNetwork` part with `power` | the wall temperature |
| Wall to gas | links (skill `ferret-physics-links`) `gasInPart` | heat into a `GasVolume` (media (skill `ferret`)) |
| Gas | `GasVolume` | pressure |
| Shell fails | your rule: `pressure > burstPressure` | the call to `detonate` |
| Blast | explosions (skill `ferret-physics-combustion-explosions`) `detonate({ vessel, casing })` | impulses on bodies, fragment bodies |
| Crate | the physics host | a velocity |

## Building it

The wall is a heat part with a constant power standing for the flame. The gas is a `GasVolume`, and `gasInPart` joins the two with a conductance in W/K:

```ts
const net = new HeatNetwork();
const wall = net.addPart({ name: 'wall', mass: 40, material: steel, T: 293.15, power: 20e3 });
const gas = new GasVolume({ moles: 8, temperature: 293.15, volume: 0.2 });
const link = gasInPart(gas, wall, net, 200);
const burstPressure = 4 * gas.pressure;
```

Each step moves the heat and watches the one number the rule needs:

```ts
net.step(dt);
link.step(dt, host, []);
if (gas.pressure > burstPressure) {
  blast.detonate({ at: tankPosition, vessel: { pressure: gas.pressure, volume: 0.2, gamma: 1.4 },
                   burst: 'air', casing: { mass: 30, shape: 'cylinder' } });
}
```

## What happens

With 20 kW into a 40 kg steel wall the gas takes a few minutes to reach four times its fill pressure. At constant volume that means four times the absolute temperature, so the wall is by then well past red heat. The burst fires `explosion:blast` and then `explosion:fragments` on the world's event bus, and the crate beside the tank leaves with a velocity from the blast.

## What the capabilities said to each other

- **Heat to gas.** `gasInPart` moves `G (T_wall − T_gas) dt` joules from the wall to the gas each step; the wall pays what the gas takes, so the pair keeps its energy. Heat has no pressure model; pressure is the gas's `n R T / V`.
- **Gas to rule to blast.** The only logic you write is `pressure > limit`. The energy of the burst is the gas's expansion work `(p − p₀) V / (γ − 1)`, converted to kilograms of TNT by the explosions capability (the vessel branch of `detonate`).
- **Blast to bodies.** The crate gets `I · A` at its distance (and less if something shields it); the casing becomes fragments that leave at the Gurney velocity and, if a wall has the `armour` value, are stopped or pass by their energy.
- **Time.** The fire is the only clock: with 20 kW and a 40 kg steel wall it takes minutes; with 200 kW, seconds. Change `power` to see the margin an extinguisher or a relief valve buys.

## Variations

| Change | Effect |
|---|---|
| A relief valve: vent the gas with `Orifice` above a set pressure | the tank never reaches the burst pressure; the gas goes out as a jet |
| `power: 0` and water cooling on the wall (`area`, `h` to a cold ambient) | the wall holds the gas near ambient; no burst |
| A liquid inside (`reservoirInPart`) | the liquid takes the heat first, boiling at its plateau, so the tank lasts longer: the reason tanks are filled with liquid |
| `casing.mass` doubled | slower, fewer, heavier fragments (the Gurney speed falls) |
| A plate on the crate's side with the `armour` value | fragments are stopped or ricochet; the blast pressure still pushes |

The complete run, with the numbers it must produce, is in `tests/unit/examples/physics-scenarios-tank-fire.test.ts`.
