← notes / 2026.06.09
build log: fire egress sim
the tools that define my field — pathfinder, simulex — are black boxes to most of the people who use them. you draw a building, set an occupant load, press run, and trust the number that comes out. that number can end up supporting a real life-safety decision. that bothered me enough to build the model underneath those tools myself, from scratch, in python with the mesa framework.
repo: github.com/njlagana/fire_egress_sim
the idea
occupants are agents. each one waits out its own randomized pre-movement delay (people don’t move the instant an alarm sounds), then heads for an exit, and queues when a door is at capacity. nothing about crowd behavior is scripted — door bottlenecks, exit imbalance, and the spread of evacuation times all emerge from simple per-occupant rules. a single run of a random model proves nothing, so everything is reported as a monte carlo distribution across dozens of runs.
v1: a room with two exits
deliberately simple: a walled room, two doors, nearest-exit logic. its job was to prove the framework before pointing it at anything real. the most important lesson came from one buried assumption — door flow rate. the theoretical max (~1.3 persons per meter per second) produced almost no bottleneck. the honest number for genuinely crowded flow is closer to 0.5, and with it the bottleneck forms and drives the whole result:
| scenario | mean evac time | spread | worst case |
|---|---|---|---|
| frictionless | ~34 s | ~1.2 s | ≈ mean |
| realistic congestion | ~58 s | ~4.0 s | ~68.5 s |
congestion didn’t just slow the average — it tripled the variance. the tail is the risk, which is exactly why life-safety analysis is built around worst cases instead of averages.
v2: a real building
in a prior course (enes-250) i worked through a full nfpa 101 life-safety analysis of a real four-story building by hand, and found its fourth floor egress-deficient: an occupant load of 421 against a combined stair-door capacity of 320. v2 rebuilds that floor cell by cell — 58×67 grid, 1 m cells — and asks what the evacuation actually looks like when those same two 32-inch stair doors are the constraint.
real geometry breaks straight-line exit logic (it routes people through walls), so each stairwell gets its own shortest-path distance field computed by bfs, and occupants walk downhill on their assigned field. pre-movement times come from a right-skewed weibull fit. across 30 monte carlo runs at the real occupant load: ~5.08 min mean fourth-floor evacuation, with a near-linear evacuation curve — the signature of a capacity-limited drain, not a walking-distance problem.
the result i care about most: switching the pre-movement distribution changed the total time by only ~2%. the floor is bottleneck-dominated. the model was built independently of my hand analysis and landed on the same controlling constraint — the stair doors — which is the kind of cross-check a life-safety analysis depends on.
next
- v3: fire and smoke. close. extensive progress already made — a hazard that grows over time and closes routes — it just hasn’t been pushed yet.
- v4: tenability. visibility, temperature, toxic gases; whether a path stays survivable for the time it takes to use it. that’s the question a real analysis ultimately has to answer.
- capacity-aware routing, so the stair split emerges from agents reacting to congestion instead of being imposed.