Route choice in smoke after Schröder et al. (2015)
Schröder et al. (2015) let agents in an assembly hall choose between two doors and two exits while smoke from a fire in a neighbouring room spreads. We build their geometry, add our own growing fire, and run pyFDS-Evac’s own smoke-aware routing on it with 200 agents and 10 seeds per case:
- Exit and door shares. How the default
gaterouter and theadditiverouter change them in a growing fire, against a smoke-blind crowd. - Door choice by movement start. Why, under
gate, the door an agent takes depends mainly on when it starts moving. - What the router sees. It reads the smoke along the whole route at 1.6 m, including smoke that will arrive later. Schröder’s sensor reads the smoke present in the agent’s room along straight lines at 2.8 m. This difference in perception scope is #125.
Download the files for this page (100 kB zip)
scripts/docs/schroeder2015_route.py and
scripts/docs/schroeder2015_fire_figures.py print every number and draw
every figure on this page; scripts/docs/study_animations.py draws the
animation. The page reports research software applied to
one scenario and gives no design or safety verdict.The result in brief
Main fire a047_pvc_h40, mean of 10 seeds. The no-fire and smoke-blind
arms are identical, so the smoke-blind arm is the reference:
| Arm | Exit-E share | ΔE against smoke-blind (95 % CI) | Door split |
|---|---|---|---|
| no fire = smoke-blind | 0.520 | 0 | boundary at y = 12.54 ± 0.13 m (per seed) |
gate | 0.689 | +0.169 (+0.128, +0.209) | no boundary in metres; Δy > 0 in 10 of 10 seeds (post hoc sign test, p = 0.002) |
additive | 0.447 | −0.074 (−0.088, −0.059) | Δy = −0.90 m (−1.16, −0.64); a valid boundary in 10 of 10 seeds |
Δy is the boundary minus the clear-air boundary of the same seed. A positive Δy moves the boundary toward door B, so more agents use door A. A change in the E share counts if it exceeds 2 × SD of the smoke-blind shares, 0.048.
- Gate sends more agents through door A to exit E than clear air does: E share 0.689 against 0.520, in 10 of 10 seeds.
- (Post hoc) Gate’s door choice follows mainly when an agent starts moving. The door-B share is 0.04 for agents starting at 30–120 s and 0.83 for those starting at 150–300 s. In clear air it is about 0.5 throughout.
- The cause is a hall-wide re-path at 45 s and a wave of fallbacks peaking at 151–155 s. The path search reads the smoke present at decision time, while the route’s τ reads the smoke each point will have when the agent gets there. From 134–136 s every route is refused for the first agents, and the fallback sends most of them to door B and exit F.
- Additive shifts the split by −0.90 m (95 % CI −1.16, −0.64) on the
main fire. Its shift depends on the fire: −0.90 m on the main fire,
+0.25 m on
a047_pvc_h35(95 % CI −0.00 to +0.50, not resolved) and +1.25 m ona012_pvc_h30. - Heat and the 400 s cap. Heat entered neither routing nor tenability. Up to 7 late-starting agents per run were still walking at 400 s.
The building

Tags: [P] published in the paper, [D] digitised from Schröder et al. (2015), Figs. 2–3 and 6 (±0.5–1 m), [A] assumed here.
| Item | Value | Tag |
|---|---|---|
| Room 1, hall | x 0–10.5, y 0–24 m; interior x 0.2–10.6 m (10.4 m, on the 0.2 m grid) | [D] / [A] |
| Room 2, corridor | x −5–0, y −10–35 m; exits E (bottom) and F (top), 2 m wide at x −3.6 to −1.6 m | [D] / [A] |
| Room 3 | y 24–31 m; x not given in the source, taken as the hall’s width | [D] / [A] |
| Doors | all 2 m wide. A at y 0.6–2.6, B at y 20.6–22.6, D at y 26.6–28.6, C at x 4.4–6.4 m; snapped to the 0.2 m grid; 2 m high in FDS | [P] width / [A] |
| Floor | 554 m² meshed in FDS; 545 m² inside the walls; 471 m² walkable | computed |
Departures from the source.
- Room 3 and doors C and D are not walkable and not in the stage graph. They stand in for Schröder’s room-to-corridor sensor. In FDS, C and D are open.
- Doors A and B are waypoints, E and F are exits. Each exit has a 0.8 m deep passage, so agents enter it before they are removed (#349).
- The waypoint split is 50/50 at A and at B, because the engine needs an explicit split where a waypoint has two exits. Route ranking picks each agent’s exit. In clear air nobody crosses over: only A→E and B→F occur.
- Agents start uniformly in the hall, 0.3 m from the walls. Model CFSM,
radius 0.15 m, familiarity
full. - FDS 6.10.1 is used. Schröder used FDS 6.1.2.
The fire
The paper publishes no fire: burner, heat release rate, fuel, soot yield, grid, ceiling height and end time are all unstated. Our fire was set from design-fire practice before any routing run. One of nine variants was then chosen against a smoke target, also before any routing run.
| Item | Main fire a047_pvc_h40 | a047_pvc_h35 | a012_pvc_h30 | Source |
|---|---|---|---|---|
| Growth | t², α = 0.047 kW/s² (fast) | same | α = 0.012 kW/s² (medium) | SFPE Handbook, 6th ed., Ch. 3, Table 3.5 |
| Cap | 1.5 MW: HRRPUA 250 kW/m² on a 3 × 2 m burner centred in Room 3 (x 4–7, y 26.6–28.6 m) | same | same | HRRPUA after DIN EN 1991-1-2/NA, via Schröder (2017), p. 74; cap [A] |
| Cap reached at | 178.6 s | 178.6 s | 353.6 s | computed (TAU_Q) |
| Fuel | PVC: soot yield 0.172, CO yield 0.063 kg/kg, ΔHc 16,400 kJ/kg | same | same | FDS User’s Guide PVC example, on which Schröder (2017), Table 4.5, p. 75, is based |
| Ceiling | 4.0 m | 3.5 m | 3.0 m | [A]; the paper extracts smoke up to 3.0 m (Table 2, p. 334), so its ceiling is above 3 m |
| Grid, time | 0.2 m (dz 0.1944 m at 3.5 m), 480 s, slices every 1 s | same | same | [A] |
Smoke is written at 1.6 m (routing, walking speed and gas dose), and at
2.0 and 2.8 m for comparison. With the 3.5 m ceiling FDS places these at
1.56, 1.94 and 2.72 m; pyFDS-Evac takes the nearest slice and logs the
height mismatch. Runtime with 6 MPI processes: 90 min (a047_pvc_h40),
99 min (a047_pvc_h35), 61 min (a012_pvc_h30).
How the main fire was chosen

- The target was fixed first. It is our reading of the paper’s Fig. 6c (p. 335, the 2.8 m extraction at 165 s, printed without a colour scale): Room 3 and the upper corridor opaque (K ≥ 2.3 1/m), the lower corridor clear (K ≤ 0.23), the lower hall at K 0.7–1.4, the upper hall clear (K ≤ 0.23 [A]).
- Nine runs on the 0.2 m grid: α ∈ {0.012, 0.047} × {PVC, PUR} ×
ceiling ∈ {3.0, 4.0} m, plus the central case
a047_pvc_h35. Each is scored by S, the mean over five regions of the share of nodes that meet the target. - No automatic pick was plausible. The best score, 0.60 for
a012_pvc_h30, equals that of a field with smoke only in Room 3. No variant beats that null field.a012_pvc_h30also reverses the hall pattern: median K 2.0 1/m in the upper hall against 0.99 in the lower. - Smoke enters the hall through door C and piles up at the far, door-A end (details below). Whether the 2.8 m slice shows the lower hall darker depends on how far below the ceiling it sits.
- The maintainer chose
a047_pvc_h40by visual match to Fig. 6c. It is the only variant with the lower hall darker than the upper (median K 1.5 against 0.51 1/m) and an opaque upper corridor (87 % of nodes). It differs from Fig. 6c in four ways: the corridor toward E is smokier (median K 0.94 against ≤ 0.23); the lower hall is patchier and darker; some smoke sits at the top of the hall near C; and its score is 0.48 against the best 0.60.
The comparison fires are a012_pvc_h30 (best score, reversed hall
pattern) and a047_pvc_h35 (the central design fire, smoke almost
everywhere). The fire was chosen against the smoke target only; no route
outcome was known.
The scores of all nine variants

| Variant | S (165 s) | S (160–170 s) | Room 3 | Upper corridor | Lower corridor | Lower hall | Upper hall | Median K: upper corridor / lower corridor / lower hall / upper hall |
|---|---|---|---|---|---|---|---|---|
| a047_pvc_h30 | 0.40 | 0.40 | 1.00 | 1.00 | 0.00 | 0.00 | 0.00 | 8.4 / 4.2 / 4.9 / 6.7 |
| a047_pvc_h35 | 0.40 | 0.40 | 1.00 | 0.98 | 0.00 | 0.00 | 0.00 | 4.7 / 1.6 / 2.8 / 2.4 |
| a047_pvc_h40 | 0.48 | 0.46 | 1.00 | 0.87 | 0.08 | 0.40 | 0.08 | 3.5 / 0.94 / 1.5 / 0.51 |
| a047_pur_h30 | 0.41 | 0.38 | 1.00 | 0.59 | 0.00 | 0.49 | 0.00 | 2.4 / 1.3 / 1.4 / 1.9 |
| a047_pur_h40 | 0.40 | 0.41 | 1.00 | 0.02 | 0.30 | 0.09 | 0.62 | 0.97 / 0.28 / 0.44 / 0.2 |
| a012_pvc_h30 | 0.60 | 0.62 | 1.00 | 0.43 | 1.00 | 0.59 | 0.00 | 2.3 / 0 / 0.99 / 2 |
| a012_pvc_h40 | 0.55 | 0.55 | 1.00 | 0.02 | 1.00 | 0.00 | 0.73 | 0.4 / 0 / 0.0066 / 0.14 |
| a012_pur_h30 | 0.24 | 0.23 | 0.19 | 0.00 | 1.00 | 0.00 | 0.00 | 0.64 / 0 / 0.26 / 0.55 |
| a012_pur_h40 | 0.39 | 0.39 | 0.00 | 0.00 | 1.00 | 0.00 | 0.95 | 0.087 / 0 / 0.0012 / 0.04 |
Region columns are the share of nodes meeting the target; K is in 1/m. Regions are inset by one cell; the corridor beside the hall is not scored. PUR: soot yield 0.056, CO yield 0.122 kg/kg, ΔHc 18,770 kJ/kg (Schröder 2017, Table 4.4 and p. 74). The score uses one LES frame; the thresholds are a reading of a greyscale image.
Where the smoke enters the hall (post hoc)

The decks have no velocity output and no device in door C, so the flow direction is inferred from the order in which the device trees first exceed K = 0.23 1/m. No flux is measured.
- Entry through door C. On the 2.8 m slice the front starts at C and moves toward y = 0.
- Doors A and B are outlets. The hall side of door A is reached 7–20 s before the corridor side in 9 of 9 variants; door B shows the same order in 8 of 9.
- Pile-up at the A end. For the fast PVC fires at 165 s the layer is 1.1–1.3 m deep from C to mid-hall and 2.7–3.3 m deep at the A end.
- So the upper/lower pattern at 2.8 m depends on the slice depth below the ceiling (H − 2.8 m) against the depth of the jet near C. With a 4.0 m ceiling and α = 0.047 the slice lies just below the jet near C and inside the pile-up at the A end.
The crowd and the routers
- 200 agents in the hall [P], placed uniformly at t = 0 [A].
- Walking speed v₀ ~ N(1.0, 0.2) m/s [P], clipped by the engine to 0.1–5.0 m/s.
- Pre-movement with mean 120 s and SD 60 s [P]: Weibull, scale 135.49 s, shape 2.101. The source uses N(120, 60) s, which pyFDS-Evac does not offer.
- Four arms, seeds 1–10 each: no fire; smoke-blind (
--smoke-blind);gate;additivewithw_smoke1.0, the engine default. The cost model is set explicitly in each scenario; at the time a misspelt name selected the additive model (#305). - Routing settings:
anticipate: true,foresight_horizon_sat its default (no limit),base_speed_m_per_s1.0. Routes are re-evaluated every 1 s, also during pre-movement. - Smoke height 1.6 m for routing, speed and gas dose. Schröder’s example extracts at 2.8 m.
- Tenability: gas FED on, heat FED off (both engine defaults).
- Horizon: 400 s against the FDS end of 480 s.
The routing model and the gate in detail explain each setting.
Which pre-movement distribution
pyFDS-Evac offers gamma, lognormal, Weibull, uniform and constant
pre-movement (pyfds_evac/core/premovement_distributions.py). N(120, 60) s
puts 2.3 % of agents below 0 s, so the reference is N(120, 60) truncated at
0. Each family is matched to mean 120 s and SD 60 s:
| Family (engine parameters a, b) | KS distance | W1 [s] | 99th percentile [s] | P(t > 300 s) |
|---|---|---|---|---|
| Weibull 135.49, 2.101 | 0.056 | 6.1 | 280 | 0.005 |
| gamma 4, 30 | 0.079 | 9.1 | 301 | 0.010 |
| uniform 16.1, 223.9 | 0.076 | 9.4 | 222 | 0.000 |
| lognormal 4.676, 0.472 | 0.105 | 12.6 | 322 | 0.015 |
| reference, N(120, 60) truncated at 0 | 260 | 0.001 |
Set both premovement_param_a and premovement_param_b. With only one
set, the engine silently uses its preset.
Results
Exit shares and flows

| Fire | Arm | E share | ΔE against smoke-blind (95 % CI) | Doors A / B | Routes AE / AF / BE / BF |
|---|---|---|---|---|---|
| a047_pvc_h40 | smoke-blind | 0.520 | 0 | 104 / 96 | 104.0 / 0.0 / 0.0 / 96.0 |
| a047_pvc_h40 | gate | 0.689 | +0.169 (+0.128, +0.209) | 145 / 55 | 137.4 / 7.6 / 0.2 / 54.6 |
| a047_pvc_h40 | additive | 0.447 | −0.074 (−0.088, −0.059) | 96 / 104 | 89.2 / 7.0 / 0.0 / 103.6 |
| a047_pvc_h35 | gate | 0.777 | +0.257 (+0.235, +0.279) | 155 / 45 | 155.1 / 0.0 / 0.2 / 44.4 |
| a047_pvc_h35 | additive | 0.532 | +0.012 (+0.002, +0.021) | 106 / 94 | 106.2 / 0.0 / 0.0 / 93.5 |
| a012_pvc_h30 | gate | 0.918 | +0.398 (+0.373, +0.423) | 183 / 17 | 183.2 / 0.0 / 0.3 / 16.4 |
| a012_pvc_h30 | additive | 0.574 | +0.054 (+0.044, +0.064) | 115 / 85 | 114.7 / 0.0 / 0.0 / 85.2 |
Mean of 10 seeds. The smoke-blind arm is the same on every fire.
Door choice follows movement start (gate)

This measure was added after the first results were seen (post hoc). Under
gate, an agent’s door is predicted better by when it starts moving
than by where it starts: area under the ROC curve 0.86 against 0.66, and
McFadden R² 0.30 against 0.05 (0.38 for both together). Position still
matters a little. Under additive, start position stays the better predictor (AUC 0.96).
Door predictors for all fires
| Fire | Arm | AUC start y | AUC start time | R² start y | R² start time | R² both |
|---|---|---|---|---|---|---|
| a047_pvc_h40 | no fire | 1.00 | 0.50 | 0.99 | 0.00 | 0.99 |
| a047_pvc_h40 | gate | 0.66 | 0.86 | 0.05 | 0.30 | 0.38 |
| a047_pvc_h40 | additive | 0.96 | 0.58 | 0.64 | 0.02 | 0.71 |
| a047_pvc_h35 | gate | 0.78 | 0.77 | 0.17 | 0.17 | 0.38 |
| a047_pvc_h35 | additive | 0.98 | 0.54 | 0.73 | 0.01 | 0.76 |
| a012_pvc_h30 | gate | 0.81 | 0.45 | 0.17 | 0.00 | 0.18 |
| a012_pvc_h30 | additive | 0.99 | 0.44 | 0.79 | 0.00 | 0.82 |
Logistic models of door B, seeds pooled. An AUC below 0.5 means later starters use door B less.
Smoke-blind and gate, animated

Main fire a047_pvc_h40, seed 3, 0–398 s at 16 times real time. Left
smoke-blind, right gate; both arms have the same agents, start positions
and start times. Seed 3 has 147 agents through door A under gate, the
median of the 10 seeds. Background: K at 1.6 m, the slice that routing,
walking speed and gas dose use. Open rings: agents in pre-movement. Dots:
walking agents, coloured and sized by their speed factor. Regenerated by
scripts/docs/study_animations.py.
What to watch for:
- 45–145 s. Under
gatealmost every agent that starts walking heads for door A, also from the upper hall. Smoke-blind splits the hall at about y = 12.5 m. By 146 s, 83 agents have passed door A undergateagainst 57 for smoke-blind. - From 134 s. The first agents find every route refused, as smoke at
1.6 m reaches the door-A end of the hall. Under
gate, 10 agents pass door B before 145 s (the last at 70.6 s) and 43 from 149.1 s on. Those 43 all go to F through the smoky upper corridor, where their dots grow and turn red. - The end. Smoke-blind’s last agent leaves at 303.4 s, gate’s at 362.9 s. In this seed nobody is inside at 400 s in either arm.
The route figure below shows the 2.8 m slice for comparison with the paper. The animation shows 1.6 m, the slice that routing and walking speed use.
Why: a hall-wide re-path and a fallback wave
Five facts of the gate code explain the pattern
(pyfds_evac/core/route_graph.py):
- The path search weights each edge by
k_avg·L + 1e-6·L(GatePolicy.edge_weight), so length only breaks ties: any trace of smoke on the shorter path sends the search onto a smoke-free path of any length. - The search starts where the agent stands (#451): the walk to each door is the first leg, charged the smoke on that walk. The smoke in the hall is nearly uniform at these times, so almost every hall agent gets the same door for a given exit: from 50 to 144 s, 97–99 % of the hall agents’ first-ranked routes are A→E, in every seed.
- The search uses the smoke present at decision time
(
_generate_candidates). The τ of each candidate is read point by point at the time the agent would reach that point, counted from where the agent stands (_measure_route, #650); see the routing model. - Routes are ranked by τ first (
GatePolicy.order_key). An exit switch needs the rival’s τ to be lower by more than 6 × 0.1 = 0.6 (_tau_band). A route is refused above τ = 6 for the current exit and 4.8 for a rival exit (RouteCostConfig). τ = 6 comes from the original FDS+Evac. - Two refused routes: the lower τ decides, with a 20 % margin; a switch straight back is blocked for 10 s (#458).
The 45 s re-path happens at the same second in all 10 seeds; the later events vary by a few seconds between seeds:
| Time | Event |
|---|---|
| 45 s | Exit F re-paths via door A. Trace smoke on hall→B→F (router τ 0.08) makes the smoke-free path via A win, at 45.1 m against 24.5 m. E via A (23.5 m) is now more than 10 % shorter in time than F via A, so agents bound for F switch to E (_clears_exit_anchor): 819 exit changes at 45 s over 10 seeds, and 28 more at 74–80 s, all logged shorter_path (#92). No route was refused. |
| 45–134 s | Almost every hall agent heads for A→E. 0.2 B→E agents per seed pass door B, at 71–87 s. Between 72 and 150 s, 6.1 exit changes per seed are logged smoke_reroute. |
| 134–136 s | Every route is refused for the first hall agents: A→E’s τ, read at the time they would reach each point, passes 6 as smoke piles up at the door-A end. The fallback keeps the current route until a rival’s τ is more than 20 % lower. |
| from 150 s | Fallback wave: 307 of the 666 fallback switches over 10 seeds fall in 151–155 s. A→E→B→F 284, B→E→B→F 185, A→E→A→F 141, A→F→A→E 50, B→F→A→E 5, B→E→A→F 1; in all 666 the new route has the lower τ. |
| 156–164 s | Exit E re-paths via door B, but B→E is already refused (router τ 22–31, median per pass, at 158–163 s), so almost nobody turns from A to B→E. Same-exit re-paths (better_path) number 8.3 per seed, at 136–168 s. |
Per seed, 30–47 exit changes return to an exit the agent had left earlier, none within 2 s of leaving it. Between two refused routes the 20 % margin and the 10 s return lockout apply. A fallback switch X→Y is followed by a switch Y→X of the same agent 56 times in 10 seeds (median 34 s later). Route smoke is read once per grid cell since #653 (0.5.0), and the returns remain with it.
These counts, the 28 later shorter_path changes, the 307 fallback
switches in 151–155 s and the time windows of the smoke_reroute and
better_path changes in the table are post hoc: they were read from the
gate route histories (gate_s*_rh.csv) with a separate script, and
schroeder2015_route.py does not print them. A return is an exit change
to an exit the agent left earlier; an undone fallback is a fallback X→Y
followed later by Y→X of the same agent.

τ is read point by point at the time the agent would reach each point. A route appears only while the path search offers it for its exit to at least one agent.
The pre-registered mechanism was refuted; its direction held. Before the runs we predicted that B→E would carry more τ than A→E and so move the boundary toward door B. The boundary did move toward B, and from 130 s B→E does carry more τ than A→E (τ figure), but that comparison does not move the agents: almost nobody takes B→E (0.2 per seed). The shift toward door A comes from the 45 s re-path of exit F, and the later door-B users reach F by the fallback.
Reroutes per seed, main fire
| Arm | Switches | Agents | By reason |
|---|---|---|---|
| gate | 165.8 | 118.2 | 84.8 shorter_path, 66.6 fallback, 8.3 better_path (same exit, new path), 6.1 smoke_reroute |
| additive | 53.3 | 36.3 | 42.6 smoke_reroute, 10.7 shorter_path |
Mean per seed. Since 0.5.0 each exit change is labelled by its cause (#92).
The additive boundary

Under gate, door B is not a monotone function of start y, so a boundary
fitted in metres is not meaningful: its CI lies inside the hall in none of
the 10 seeds on the main fire. Gate is therefore reported by its E share, its
sign count and the door share by start. Under additive every seed has a
valid boundary; the shift is −0.90 m (−1.16, −0.64) on the main fire.
Additive charges length in both path and exit ranking and keeps the
spatial split.
The comparison fires
| Fire | Gate ΔE | Gate sign count | Gate re-path times | Additive Δy (95 % CI) | Additive ΔE |
|---|---|---|---|---|---|
| a047_pvc_h40 (main) | +0.169 | Δy > 0 in 10 of 10; valid boundary in 0 | 45 / 156–164 s; every route refused from 134–136 s | −0.90 m (−1.16, −0.64); 10 of 10 negative | −0.074 |
| a047_pvc_h35 | +0.257 | 10 of 10; valid in 4 | 44 / 156–199 s; every route refused from 127–129 s | +0.25 m (−0.00, +0.50); 9 of 10 positive | +0.012, below 0.048 |
| a012_pvc_h30 | +0.398 | 10 of 10; valid in 0 | F via A 57 s; every route refused from 172–176 s; E via B 221–276 s | +1.25 m (+0.90, +1.59); 10 of 10 positive | +0.054 |
a047_pvc_h35repeats the main-fire order of events: F via A at 44 s, every route refused from 127–129 s, E via B at 156–199 s.a012_pvc_h30reaches the gate’s sign by another route. Most agents take A→E (E share 0.918). Of its 16.7 door-B users per seed, 55 % started before the 57 s re-path; the fallback, from 172–176 s, sends later starters to door B before E re-paths via B at 221–276 s. Start time does not predict door B (AUC 0.45).h35andh40differ only in ceiling height. The evidence is two growth rates and three smoke fields, not three independent fires.- Additive’s shift depends on the fire and is not resolved on
a047_pvc_h35. Its mechanism was not analysed.
Routes of one seed, main fire

The background is the 2.8 m slice at 165 s, for display only. Routing used the 1.6 m slice.
How far to trust the numbers
Pre-registration. The criteria were fixed before the boundary and E-share statistics were computed. This is stated, but cannot be checked. The E-share threshold (0.048) was set after the seed-1 exit counts were seen (114, 137 and 99 via E for smoke-blind, gate and additive, in the first runs), and those counts already gave its sign. The sign test, the door share by start, the predictor table and the boundary validity count are post hoc.
Clear air. Smoke-blind runs are identical to no fire on all three fires. Start positions are the same in every arm, so the comparisons are paired by seed. The deck’s radius is 0.15 m, so 0.5.0 (#408, stage reach from the agent’s own radius) moves the clear-air walks: against the runs of
2a94a8da, every agent keeps its exit, but exit times differ by up to 22.3 s. The E share (0.520), the door counts (104 / 96) and the boundary are unchanged. The clear-air boundary, 12.54 m per seed (12.56 m pooled), lies −0.05 m from the shortest-path boundary at 12.60 m. Before the fix of #350 and #401 the difference was +1.50 m. The clear-air slope comes from perfectly separated data and is not an estimate.Still walking at 400 s. No run raised the FDS horizon error (#356), but the 400 s cap leaves some agents walking:
Fire gate, per run (total in 10 runs) additive a047_pvc_h40 0–3 (21) 0–4 (22) a047_pvc_h35 0–7 (37) 0–7 (36) a012_pvc_h30 0–1 (3) 0–1 (2) They are late starters (median movement start 286 s; 115 of 121 at 250 s or later) walking at a speed factor of 0.10. None is stalled: each walked at least 0.47 m in the last 30 s.
Gas. The largest gas FED of any agent in any run is 0.069; nobody is incapacitated by gas.
Heat. Heat FED was off in all 90 fire-arm runs, so heat entered neither routing nor tenability, and “nobody incapacitated” covers gas only. A post hoc estimate samples the FDS temperature at 1.6 m at the agents’ positions every 1 s. On the main fire, agents meet up to 168 °C, and 25 (gate) and 23 (additive) per run on average go above 60 °C. The convective dose peaks at 0.042 clothed and 0.12 unclothed, with the constants of
pyfds_evac/core/fed.py. The unclothed law is Purser and McAllister (2026), Eq. 70.42, p. 2318; it is somewhat unconservative at higher temperatures, so the unclothed dose at 168 °C may be underestimated. The clothed constants have not been checked against ISO 13571. Radiant heat was not assessed.One LES realisation per fire, on the 0.2 m grid only.
What this does not show
- The study uses the geometry of Schröder et al. (2015) with our own fire, crowd and router. Their results are neither reproduced, calibrated nor validated.
- The sensor settings behind the paper’s route patterns (Fig. 6d, extraction height, grid, time step and frisk) are unpublished, so its route choice cannot be set against ours. The counts of its Fig. 7 are one sensitivity sample.
- pyFDS-Evac has neither Schröder’s sensor (Eq. 4), his edge factor (Eq. 5), frisk, nor his obstruction test (routing model).
- The router reads the smoke along the whole route at 1.6 m, including smoke that will arrive later. Agents could not see that smoke (#125).
- The gate’s τ = 6 comes from FDS+Evac. Schröder’s factor 2 and frisk are chosen, not fitted (p. 332). The page ranks neither rule above the other.
- The door-choice pattern is a property of the model: a lexicographic τ rule with present-time path search from each agent’s position. No occupant behaviour was observed.
- The gate split has no boundary in metres. It is reported by its E share, its sign count and the door share by start.
- The predicted direction held; the pre-registered mechanism did not.
Reproduce
The inputs are in assets/schroeder2015_route/. Run every command from
the repository root, or from the unpacked zip with python instead of
uv run python. DATA is a folder outside the repository.
FDS, 6 MPI processes per deck:
for F in a047_pvc_h40 a047_pvc_h35 a012_pvc_h30; do mkdir -p "$DATA/$F" && cp assets/schroeder2015_route/$F/$F.fds "$DATA/$F/" (cd "$DATA/$F" && mpiexec -n 6 fds $F.fds) doneEvacuation, four arms on the main fire and three on each comparison fire, seeds 1–10. One seed of each arm on the main fire:
C=assets/schroeder2015_route/evac uv run python run.py --scenario $C/config_gate.json --seed 1 # no fire uv run python run.py --scenario $C/config_gate.json --seed 1 --fds-dir "$DATA/a047_pvc_h40" --smoke-blind uv run python run.py --scenario $C/config_gate.json --seed 1 --fds-dir "$DATA/a047_pvc_h40" # gate uv run python run.py --scenario $C/config_additive.json --seed 1 --fds-dir "$DATA/a047_pvc_h40" # additiveassets/schroeder2015_route/run_p1.shruns every seed and adds--output-route-history,--output-exit-history,--output-fed-historyand--output-route-cost-history. A run with agents still walking at the 400 s cap is incomplete, andrun.pyexits with status 2 (Exit status); the script counts such a run as done. It exits non-zero if any run fails. For all seeds at once:PY="uv run python" bash assets/schroeder2015_route/run_p1.sh \ "$DATA/a047_pvc_h40" "$DATA/p1_a047_pvc_h40" 6 --with-nofire PY="uv run python" bash assets/schroeder2015_route/run_p1.sh \ "$DATA/a047_pvc_h35" "$DATA/p1_a047_pvc_h35" 6 PY="uv run python" bash assets/schroeder2015_route/run_p1.sh \ "$DATA/a012_pvc_h30" "$DATA/p1_a012_pvc_h30" 6Each run takes about 25–40 s.
Numbers and figures:
uv run python scripts/docs/schroeder2015_route.py --data "$DATA"It prints the evacuation numbers on this page as Markdown tables (except the post hoc route-history counts below the event table), then this summary, then writes the figures:
main fire, exit-E share: no fire 0.520, gate 0.689, additive 0.447 main fire, additive dy: -0.90 m (-1.16, -0.64) main fire, gate door-B share: 0.04 for starts 30-120 s, 0.83 for starts 150-300 sAnimation of smoke-blind and gate, about 1 min. It needs
ffmpegfor the colour reduction; without it the GIF is larger:uv run python scripts/docs/study_animations.py schroeder2015 --data "$DATA"It prints the seed and the numbers of the caption, then writes the GIF:
- gate door-A counts {1: 148, 2: 137, 3: 147, 4: 154, 5: 143, 6: 145, 7: 150, 8: 131, 9: 147, 10: 148}; seed 3 (147, median 147) wrote site/static/images/studies/schroeder2015/agents_smoke_gate.gif (2.1 MB, 200 frames)Fire choice, optional: it needs all nine fires. Write the decks with
uv run python assets/schroeder2015_route/make_decks.py "$DATA", run each with FDS as in step 1 (about 6 h for the six further decks), thenuv run python scripts/docs/schroeder2015_fire_figures.py --data "$DATA".
Provenance. The evacuation runs on this page were made on main at
c619a046 by steps 2–4 above (seeds 1–10, Python 3.13.4), run by hand from
a clean checkout; each run’s manifest records the commit with
git_dirty: false and agent_seeding: spawn-key-blake2b-v2. The no-fire
and smoke-blind arms give the same E share, door counts and boundary as
the earlier runs of 9c820e0f, 2a94a8da and 828ae8c3; their
trajectories differ (see Clear air above). The FDS
runs used FDS-6.10.1-0-g12efa16-release.
Limits and open issues
The scenario and the fire.
- One 0.2 m grid; a 0.1 m check waits until the case is frozen.
- One LES realisation per fire; the fire choice scores one frame.
- The fire is ours, and its differences from Fig. 6c are listed above. Two one-factor tests are deferred, possibly to a later run on JURECA: door C closed, and a 4.6 m ceiling.
- Heat FED was off; radiant heat was not assessed (#81).
- Up to 7 agents per run are still walking at 400 s.
Engine behaviour seen here.
- The path search uses present-time smoke (routing model).
- One path per exit (#185).
- Perception scope (#125).
- Anticipation horizon (#356).
Open design questions.
- Present-time path search against anticipated τ: the τ of a route is read at the agent’s arrival time at each point (#650), the path search at decision time.
- The 1e-6·L length floor lets the path search react to τ of order 1e-4; the gate page discusses the floor.
Not done yet. A dose-aware or perceived-smoke arm for the late B→F route through the opaque upper corridor.
The paper’s unpublished inputs (its fire deck, the settings behind Fig. 6d, later code versions of the factor 2) are not used. The study uses published sources only.
Sources
Sources
- Schröder, B., Haensel, D., Chraibi, M., Arnold, L., Seyfried, A., & Andresen, E. (2015). Knowledge- and perception-based route choice modelling in case of fire. Proceedings of the 6th International Symposium on Human Behaviour in Fire, Cambridge, UK, 28–30 September 2015, pp. 327–338. Interscience Communications. ISBN 978-0-9933933-0-3. juser.fz-juelich.de/record/255940. Room 3 and the fire in it p. 329; the 2.80 m extraction height p. 330; Eq. 4 p. 331; Eq. 5, the factor 2 and frisk p. 332; Table 2 p. 334; Fig. 6 p. 335; doors 2 m wide and the hall’s smoke “lower as well as more homogenous and delayed” than the corridor toward F p. 336.
- Schröder, B. (2017). Multivariate methods for life safety analysis in case of fire. Dissertation, Bergische Universität Wuppertal (2016). Schriften des Forschungszentrums Jülich, IAS Series 34. ISBN 978-3-95806-254-2. urn:nbn:de:0001-2017081810. Fire in Room 3 p. 55; Fig. 3.9 p. 57; HRRPUA p. 74; Table 4.4 p. 74; Table 4.5 p. 75.
- Fleischmann, C., & Wade, C. (2026). Fire scenarios. SFPE Handbook of Fire Protection Engineering, 6th ed., Ch. 3, Table 3.5. doi:10.1007/978-3-031-59212-6_3
- DIN EN 1991-1-2/NA, for the HRRPUA of 250 kW/m², through Schröder (2017), p. 74. Paraphrased.
- McGrattan, K. et al. Fire Dynamics Simulator User’s Guide, sixth edition, NIST SP 1019, section “Fuels not compatible with simple chemistry” (PVC example).
- Purser, D. A., & McAllister, J. L. (2026). Assessment of hazards to occupants from smoke, toxic gases, and heat. SFPE Handbook of Fire Protection Engineering, 6th ed., Ch. 70, Eq. 70.42, p. 2318 (the running text refers to it as Eq. 70.38). doi:10.1007/978-3-031-59212-6_70
- The original FDS+Evac, for τ = 6.
- Code:
pyfds_evac/core/route_graph.py(GatePolicy.edge_weight,GatePolicy.order_key,_tau_band,_generate_candidates,_measure_route,_clears_exit_anchor,_decide_exit_change,RouteCostConfig),pyfds_evac/core/premovement_distributions.py,pyfds_evac/core/fed.py.
What next
- Routing model: how pyFDS-Evac prices routes in smoke.
- The gate in detail.
- Wayfinding: what agents know and see.
- ASET-RSET maps after Schröder et al. (2020).
- Design fires.
- Perception scope: #125.
pyFDS-Evac is research software, provided without warranty.