With and without the fire

Evacuation with and without the fire

Egress tools such as Pathfinder are commonly run without the fire. The required safe escape time (RSET) is taken from that run and compared with the available safe escape time (ASET) from FDS. Engineers we consulted regard this uncoupled comparison as conservative. But Purser (2003, p. 92) noted that most travel-time calculations assumed no interaction between occupants and the fire effluent. This page shows how to make the same comparison with pyFDS-Evac, what a run coupled to the fire adds, and whether the uncoupled run is conservative for one fire: the 2 MW PVC fire of A crowd in a fire.

You need the fire_2MW_PVC FDS output of that page (step 3 there says where to get it) in $FDS. Each run below takes 4 to 6 s.

The answer in short

For this fire and this T-junction, with 100 people placed at t = 0:

  • The workflow carries over exactly. A smoke-blind run with the fire (arm U) gives the same trajectories as a run without it (arm C), and it records the dose along those fire-free paths.
  • RSET. The uncoupled RSET is shorter than the speed-only coupled RSET in every seed. It is shorter than the fully coupled RSET in every seed when people wait 30 or 60 s before moving. With no wait the two are within the seed spread: the coupled RSET is later in 13 of 20 seeds, by a median of 0.7 s (sign test p = 0.26), because nearly everyone in the coupled run takes the far exit and avoids the smoke.
  • Dose. Whether the uncoupled run over- or under-states the dose depends on the metric (see the dose table).
  • Exit usage differs: without the fire everyone takes the near exit B. With smoke-aware routing (arm R), 100 % take the far exit A when people move at once; with 30 s of pre-movement 51 % do, and with 60 s 3 %: by then every route is refused, and the router takes the one with the lowest optical depth, the shorter route to exit B, although it passes the densest smoke by the burner.
  • The pass/fail verdict at a fixed point is the same in every arm for visibility (fails), and in U, S, R and R-na for FED 0.3 (passes). For HCl with no wait, at ISO FEC 1 (an incapacitation-level value, above the design value 0.3), U and R pass at the junction and the branch mouth in every seed and S at the branch mouth in 3 of 20. Summed over seeds and points, U passes 40 times, R 40, R-na 39 and S 3.

This fire has no margin to lose: at every point the visibility limit is reached before the last person gets out, in every arm and seed. So the study shows what the uncoupled run misses once the margin is gone. It cannot tell whether a design that passes without the fire also passes with it. It is one fire in one geometry, run with research software, and it gives no design verdict.

1. The classic comparison: run without the fire

The scenario is assets/t_junction/config_initial_pre0.json: 100 agents spread over the dead-end branch of the T, all familiar with both exits, no pre-movement, and a time limit of 270 s. The two variants config_initial_pre30.json and config_initial_pre60.json differ only in a constant pre-movement of 30 or 60 s.

Arm C, no fire. Leave out --fds-dir:

mkdir -p ww
SC=assets/t_junction/config_initial_pre0.json
uv run python run.py --scenario $SC --seed 4 \
    --output-sqlite ww/c.sqlite --output-exit-history ww/c_exits.csv

The output ends with:

Simulation finished in 50.48 s (100/100 evacuated).

This is the run an egress-only tool gives you. Take RSET from it and compare it with the location ASET from FDS, as in A crowd in a fire › At fixed points.

Arm U, smoke-blind. The same run, with the fire sampled but not acting. --smoke-blind keeps every agent at its free speed and on its fire-free route, and still writes what each agent breathed and saw (#341):

uv run python run.py --scenario $SC --seed 4 --fds-dir "$FDS" --smoke-blind \
    --output-sqlite ww/u.sqlite --output-exit-history ww/u_exits.csv \
    --output-fed-history ww/u_fed.csv --output-smoke-history ww/u_smoke.csv
Smoke-blind: rerouting is off.
Smoke-blind: FED is recorded, incapacitation and FIC slowdown off.
…
Simulation finished in 50.48 s (100/100 evacuated).

fdsreader also logs Module vents: could not convert string to float for this deck. It does not affect the result.

A scenario with an exit that closes (closed_after_s, for example a front door that jams) also runs smoke-blind (#395). An agent whose exit closes chooses again, once for each closure, in clear air, as it chose its first exit; nobody else re-decides. Arm C re-decides through the reroute pass, so with a closure U walks exactly as the no-fire run with --no-enable-rerouting, not necessarily as C.

Read RSET from the trajectory, not from the Simulation finished line. The ensemble how-to explains why and how. For one seed:

import sqlite3

import numpy as np
import pandas as pd

for run in ("c", "u"):
    with sqlite3.connect(f"ww/{run}.sqlite") as con:
        fps = float(con.execute("SELECT value FROM metadata WHERE key='fps'").fetchone()[0])
        last = pd.read_sql("SELECT MAX(frame) AS f FROM trajectory_data GROUP BY id", con).f / fps
    exits = pd.read_csv(f"ww/{run}_exits.csv").exit_id.value_counts().to_dict()
    print(f"{run.upper()}: RSET_last {last.max():.1f} s, "
          f"p95 {np.sort(last)[94]:.1f} s, exits {exits}")
C: RSET_last 50.4 s, p95 48.0 s, exits {'exit_B_right': 100}
U: RSET_last 50.4 s, p95 48.0 s, exits {'exit_B_right': 100}

RSET_last is the last agent out; p95 the 95th of 100. The clock starts at ignition. The run models no detection and no alarm, so RSET here is pre-movement plus travel: with no pre-movement, the agents move at ignition, which no standard timeline assumes. Add tdet and twarn yourself (ISO/TR 16738:2009, Eq. 2, as on ASET and RSET).

If the run stopped at the time limit with people still inside, RSET_last prints the 270 s cap and exits counts the exit assigned to each agent, out or not. That is not an RSET; see Sensitivity arms.

Read the dose along the fire-free paths from U’s histories:

import pandas as pd

fed = pd.read_csv("ww/u_fed.csv")
smoke = pd.read_csv("ww/u_smoke.csv")
hist = fed.merge(smoke[["time_s", "agent_id", "extinction_per_m"]],
                 on=["time_s", "agent_id"])
hist["hcl_ppm"] = 900 * hist.fic  # HCl is the only irritant in this deck
per_agent = hist.groupby("agent_id").agg(
    max_fed=("fed_cumulative", "max"),
    max_fic=("fic", "max"),
    s_hcl300=("hcl_ppm", lambda v: int((v >= 300).sum())),
    s_k03=("extinction_per_m", lambda v: int((v >= 0.3).sum())),
)
print(per_agent.describe().loc[["50%", "max"]].round(2).to_string())
print(f"agents at HCl >= 300 ppm for at least 1 s: {(per_agent.s_hcl300 > 0).sum()}")
     max_fed  max_fic  s_hcl300  s_k03
50%     0.00     1.24       4.0    9.0
max     0.01    11.84       9.0   19.0
agents at HCl >= 300 ppm for at least 1 s: 82

The histories are written once per second, so s_hcl300 and s_k03 are seconds at HCl ≥ 300 ppm and at K ≥ 0.3 1/m. HCl = 900 × fic holds only because HCl is the only irritant of this deck (A crowd in a fire › How the numbers are computed). The classic comparison uses no such dose: it compares location ASET with RSET only. The per-agent dose is extra post-processing, as on A crowd in a fire › Each agent against its own limits.

The location ASET comes from the FDS output alone, so it is the same for every arm. The study uses four points of the location ASET table, times from ignition:

PointK ≥ 0.3 1/mHCl ≥ 300 ppmHCl ≥ 1000 ppmFED ≥ 0.3
Exit B18 s28 s40 snot by 300 s
Junction24 s45 s59 s274 s
Branch mouth46 s51 s68 s275 s
Exit A45 s47 s50 snot by 300 s

The K limit is the Engineers Australia visibility of 10 m with C = 3 (EA 2014, Fig. 8, Tenability Criteria – Short Exposure, p. 15). The HCl limits are ISO FEC 0.3 and 1. Every agent starts in the branch, so every agent passes the branch mouth and the junction.

2. What coupling adds

Two further arms let the fire act, one effect at a time.

Arm S, speed only. Smoke slows the agents, but each keeps the exit it took in U. --replay-exits reads U’s exit history and pairs agents by origin and spawn order (#352):

uv run python run.py --scenario $SC --seed 4 --fds-dir "$FDS" \
    --no-enable-rerouting --disable-tenability --replay-exits ww/u_exits.csv \
    --output-sqlite ww/s.sqlite --output-exit-history ww/s_exits.csv
Replaying the exits of 100 agents from ww/u_exits.csv.
…
Simulation finished in 68.17 s (100/100 evacuated).

Arm R, speed and routing. The default coupled run. Smoke slows the agents and enters their route cost:

uv run python run.py --scenario $SC --seed 4 --fds-dir "$FDS" \
    --disable-tenability \
    --output-sqlite ww/r.sqlite --output-exit-history ww/r_exits.csv
Simulation finished in 54.80 s (100/100 evacuated).

With --debug, C and R also print Reroute debug lines; they do not affect the result.

--disable-tenability in S and R records FED and FIC but lets nobody be incapacitated, so that everyone leaves and RSET stays defined. It also turns off --enable-fic-speed (Usage). The study adds incapacitation and the HCl slowdown as separate arms (below).

Run the RSET snippet above with ("c", "u", "s", "r"):

C: RSET_last 50.4 s, p95 48.0 s, exits {'exit_B_right': 100}
U: RSET_last 50.4 s, p95 48.0 s, exits {'exit_B_right': 100}
S: RSET_last 68.1 s, p95 63.2 s, exits {'exit_B_right': 100}
R: RSET_last 54.7 s, p95 51.0 s, exits {'exit_A_left': 98, 'exit_B_right': 2}

In this seed smoke slows S by 17.7 s (68.1 against 50.4 s). R is 4.3 s slower than U; across seeds R is later than U in 13 of 20 (below). Against S, which keeps exit B, R is faster because 98 of its 100 agents went to the far exit A and avoided B’s smoke. One seed says little: the study below runs 20 seeds with no pre-movement and 10 each with 30 and 60 s.

Reading the arms. U → S isolates the effect of smoke on speed. S → R isolates routing. R against R-na, the same run with the route cost’s look ahead in time off, isolates that look ahead.

Evacuation over time

Three panels, one per pre-movement of 0, 30 and 60 s, each showing agents out of 100 against time since ignition from 0 to 250 s for arms U (blue dashed), S (orange dash-dot) and R (red solid), with shaded min-max bands. Dotted vertical lines at 18, 24 and 45 s mark the location ASET for K at exit B, the junction and exit A. With no pre-movement U and R overlap and end near 53 to 55 s, and S ends near 70 s. At 30 s, U ends first near 83 s, R near 96 s and S near 124 s. At 60 s, U ends near 113 s while S and R end near 162 s and overlap for most of the run

Agents out (of 100) against time since ignition [s], median over seeds (line) and min–max (band); n = 20 seeds with no pre-movement, 10 at 30 and 60 s. Dotted: location ASET for K ≥ 0.3 1/m at exit B, the junction and exit A. Exit times from the trajectory at 0.1 s. Regenerated by scripts/docs/fire_blind_vs_coupled.py.

The last agent out, median [min, max] over seeds, seconds from ignition:

Armpre-movement 0 s30 s60 s
U (= C)53.3 [50.1, 56.9]83.3 [80.4, 85.8]113.3 [110.4, 115.8]
S70.0 [65.9, 80.9]124.2 [113.3, 128.7]162.4 [160.8, 183.8]
R54.5 [50.5, 57.1]95.5 [92.8, 97.5]162.4 [156.9, 171.7]
R-na56.6 [54.4, 60.6]94.6 [90.3, 101.6]164.6 [160.8, 189.1]

Exit usage

Three bar panels, one per pre-movement, showing the percentage of agents leaving by exit A for arms C, U, S, R, R-na, R-det, R-prob and R+FIC, with one dot per seed. C, U and S are at 0 percent in every panel. With no pre-movement R, R-det and R-prob are at 100 percent, R+FIC near 99 percent and R-na near 97 percent. At 30 s R-na is near 95 percent, R, R-det and R-prob near 51 and R+FIC near 34. At 60 s every arm is below 7 percent: R-na near 6, R, R-det and R-prob near 3, R+FIC near 2. A note in the first panel says C, U and S send every agent to exit B, 10 m from the junction

Agents leaving by exit A [%], bar: median over seeds, dots: one seed each. Exit A is 20 m from the junction, exit B 10 m. Regenerated by scripts/docs/fire_blind_vs_coupled.py.

C, U and S send everyone to exit B, the nearer one. R sends 100 % [94, 100] to exit A with no pre-movement, 51 % [49, 55] at 30 s and 3 % [0, 6] at 60 s. The initial exit is chosen in _assign_initial_exit (scenario.py), and R’s route cost prices the smoke each route meets on the way. With foresight on (the default "anticipate": true of RouteCostConfig, route_graph.py), the cost reads the smoke at the time the agent would arrive at each point (_arrival_time), from the whole FDS record (#125). No occupant could perceive that. With the look ahead off (R-na), the cost still reads the current smoke along the whole route, including parts no occupant could see: 97 % [95, 98] go to exit A with no pre-movement, 95 % [91, 99] at 30 s and 6 % [4, 7] at 60 s. At 30 s R takes B far more often than R-na because R also sees the smoke that will reach the long walk to A.

⚠️

When every route is refused before anyone moves, the router takes the route with the lowest optical depth τ. With 60 s of pre-movement, both routes are refused before anyone walks (seed 7: the route to B from 9 s, the route to A from 25 s; at 59–60 s τ is 55–109 on the route to B and 85–144 on the route to A). Between two refused routes the lower τ decides (#458). Here that is the shorter route to exit B (17.7 m against 24.7 m), although it passes the densest smoke near the burner (kmax 7.2–27.3 1/m on B against 6.0–8.4 on A). It is not the safer route: R’s largest max FED at 60 s is 0.19, against 0.06 in U. The effect is strongest at 60 s, where 97 % of R’s agents go past the burner to B; at 0 and 30 s R sends 100 % and 51 % to exit A.

A code-level alternative, fallback_rule="hold", keeps the exit an agent has once every route is refused, whatever the smoke on it, until the current route crosses the FED limit and a rival does not (Route rejection; #750). On the seeds of this page, R under "hold" sends 100 % [100, 100] to exit A at every pre-movement, against 100 % [94, 100], 51 % [49, 55] and 3 % [0, 6] under the default "tau". The median largest max FED is 0.006, 0.024 and 0.100 under "hold", against 0.006, 0.070 and 0.178; the median number of fallback exit changes per run is 0 under "hold", against 0, 195 and 267 (at most 6, 201 and 278). "hold" is experimental: no scenario key or flag sets it, and it is neither recommended nor validated. Whether the rule should send everyone to the exit by the fire is open (#696).

U and R, animated

Animation of arms U (top) and R (bottom) in the T-junction at 8 times real time, pre-movement 30 s. In both, 100 blue dots wait in the dead-end branch while grey smoke spreads from the burner near exit B along the corridor. After 30 s the U dots walk right to exit B, through the smoke and past the burner, staying small and blue; all 100 leave by B, the last at about 80 s. In R, 54 dots turn left to the far exit A and 46 go right to B past the burner; they grow and turn pale and red as the smoke slows them, and the last leaves at about 95 s.

Arms U (top) and R (bottom), pre-movement 30 s, seed 4 (R’s last agent leaves at 95.3 s, the seed closest to the median of 95.5 s), 8 times real time. Background: K from the FDS output, log scale. Dots are coloured and sized by their speed factor, as in The run, animated. Regenerated by scripts/docs/study_animations.py.

Both crowds wait 30 s while the smoke spreads from the burner near exit B. U then walks at free speed through that smoke to exit B, all 100 agents, and the last is out at 80.4 s. In R, 54 agents turn to the far exit A and 46 go to B; the smoke slows them, and the last is out at 95.3 s. The animation shows 30 s of pre-movement because it shows both effects, the exit and the speed. With no wait, the two arms differ mainly in the exit.

Pre-movement does not simply add

RSET_last against a constant pre-movement of 0, 30 and 60 s for arms U, S and R, medians with markers and one faint line per seed. A dashed line of slope 1 through U at 0 s lies on top of U. S and R rise more steeply: at 0 s S is near 70 s and R near 55 s; at 30 s S near 124 s and R near 96 s; at 60 s U is near 113 s and S and R both near 162 s

RSET_last [s from ignition] against constant pre-movement [s], seeds shared by all three pre-movements (n = 10). Thick: median; faint: one seed. Dashed: slope 1 through U at 0 s. S and R are drawn slightly left and right of the tick to keep the markers apart. Regenerated by scripts/docs/fire_blind_vs_coupled.py.

For the same seed, RSET(pre) − pre − RSET(0) is exactly 0.00 s for U and C in every seed. That follows from how the run is built: the pre-movement is constant, everyone starts together, and nothing reacts to the fire. S adds 19.8 s more than the pre-movement at 30 s and 32.0 s more at 60 s; R adds 10.1 s and 47.8 s (medians over seeds). Every seed adds at least 13.3 s in S and 7.6 s in R at 30 s. The fire grows while people wait, so a later start meets thicker smoke. An uncoupled run cannot show that: waiting longer only shifts its curve.

3. Is the uncoupled run conservative here?

What “conservative” means. The decision rests on whether ASET exceeds RSET by an adequate margin (ISO/TR 16738:2009, Eq. 1 and §5.6, as quoted on ASET and RSET). U is conservative relative to another arm X if its error makes the margin look smaller than X does. The reference is a model, R or S, not reality. R’s route cost looks ahead in time, so R-na, without that look ahead, is a second model reference. It is not a perceptual one: it still reads the smoke along the whole route.

MetricU is conservative relative to X if
RSET (last, p95)RSETU ≥ RSETX, tested against S and R separately
Location margin, same point and criterionASET − RSETU ≤ ASET − RSETX; this follows the RSET row, since the location ASET is shared
Per-agent margin (first crossing − own exit)smaller for U than for X, on the same agent
People inside at the location ASETat least as many in U as in X
Dose (peak FIC, time above an HCl level, max FED)at least as large in U as in X
Exit usageneither: it is a scenario assumption, so the page reports how it differs

Counts below are seeds (or agents) in which U is above, equal to, or below X. With 10 seeds, 10 of one sign gives a two-sided sign-test p of 0.002; with 20, 20 of one sign gives 2 × 10⁻⁶. The page runs many such tests, so treat p near 0.05 as no evidence.

RSET

Three strip-plot panels, one per pre-movement, showing per-seed differences S minus U, R minus U and R-na minus U in seconds, with a zero line and a black median bar. With no pre-movement S minus U is above 0 in 20 of 20 seeds, between about 13 and 25 s, R minus U in 13 of 20 with values from about minus 5 to plus 5, R-na minus U in 19 of 20. At 30 and 60 s all differences are above 0 in 10 of 10 seeds, between about 6 and 74 s

RSET_last difference per seed [s], same seed in both arms. Above 0: U gets out earlier. Black bar: median. Regenerated by scripts/docs/fire_blind_vs_coupled.py.

Pairpre-movement 0 s30 s60 s
S − U+17.1 s; S > U in 20/20+40.4 s; 10/10+49.4 s; 10/10
R − U+0.7 s [−5.2, +5.4]; R > U in 13/20 (p = 0.26)+11.8 s; 10/10+49.0 s; 10/10
R − SR < S in 20/20R < S in 10/10 (p = 0.002)R < S in 6/10, R > S in 3/10 (p = 0.51)
R-na − R+2.2 s [−0.7, +5.9]; R-na > R in 16/20, R-na < R in 3/20 (p = 0.004)−0.8 s; R-na > R in 4/10 (p = 0.75)+1.9 s; R-na > R in 6/10, R-na < R in 3/10 (p = 0.51)
  • Against S, U is not conservative at any pre-movement: smoke slows people, and U leaves that out.
  • Against R, U is not conservative at 30 and 60 s. With no pre-movement the two are not resolved. R is later than U in 13 of 20 seeds on the last agent out (p = 0.26) and on p95 in 7 of 20 (median −0.9 s). The median gap on the last agent, 0.7 s, is far smaller than the seed-to-seed spread of U itself (50.1–56.9 s). With no wait almost every R agent goes to exit A and meets little smoke.
  • The gap grows with pre-movement, for R − U from under 1 s to 49 s and for S − U from 17 s to 49 s (medians), because the fire grows while people wait. The largest single R − U, 57.3 s, is at 60 s.
  • R against S: R is faster in 20 of 20 seeds with no pre-movement and in 10 of 10 at 30 s, by avoiding exit B’s smoke. At 60 s R and S take nearly the same exit and are not resolved: R earlier in 6, later in 3 of 10 (p = 0.51).

ASET − RSET at fixed points

A three-by-three grid of panels: rows are the criteria K 0.3 per metre, HCl 300 ppm and HCl 1000 ppm, columns the pre-movements 0, 30 and 60 s. Each panel shows location ASET minus RSET_last for exit A, branch mouth, junction and exit B, one marker per arm U, S, R and R-na with a min-max line, and a vertical line at 0. Almost every marker lies left of 0. With no pre-movement, in the HCl 1000 ppm row U, R and R-na lie right of 0 at the junction and the branch mouth, and S’s range crosses 0 at the branch mouth; in the HCl 300 ppm row the ranges of U and R reach 0 at the branch mouth; an annotation reads junction, seeds that pass of 20: U 20, S 0, R 20, R-na 19

Location ASET − RSET_last [s] at four fixed points, the same points for every arm; marker: median over seeds, line: min–max. Right of 0: the last agent is out before the limit is met there. Regenerated by scripts/docs/fire_blind_vs_coupled.py.

Seeds in which the margin is positive (pass), at exit B / junction / branch mouth / exit A. Bold: the most passes at that point where the arms differ.

Criterionpre-movementUSRR-na
K ≥ 0.3 1/m0, 30, 60 s0/0/0/00/0/0/00/0/0/00/0/0/0
HCl ≥ 300 ppm0 s0/0/2/0 of 200/0/0/00/0/2/00/0/0/0
HCl ≥ 300 ppm30, 60 s0/0/0/00/0/0/00/0/0/00/0/0/0
HCl ≥ 1000 ppm0 s0/20/20/0 of 200/0/3/00/20/20/00/19/20/0
HCl ≥ 1000 ppm30, 60 s0/0/0/00/0/0/00/0/0/00/0/0/0
FED ≥ 0.30, 30, 60 sall passall passall passall pass
  • Visibility fails in every arm, seed and pre-movement; FED 0.3 passes in every seed of U, S, R and R-na. For these criteria the arm changes the size of the margin, not the verdict. R+FIC at 30 and 60 s is undetermined for FED 0.3: its RSET is censored (Sensitivity arms).
  • HCl with no pre-movement. U’s median margin at the junction under HCl 1000 ppm is about +6 s (59 − 53.3), so U passes there in every seed. R passes as often as U (40 point-passes in each), R-na 39 times and S 3 times. Under HCl 300 ppm U and R pass at the branch mouth in 2 of 20 seeds. At every point and criterion U passes at least as often as each coupled arm. These counts hold only to a few seeds: changing nothing but the per-agent random draws (#361) moved them by up to 3 of 20 seeds at a point.
  • The differences sit at HCl 1000 ppm (ISO FEC 1, an incapacitation-level value) and at the branch mouth under FEC 0.3, and the HCl in this deck is probably overestimated (see Limits).

People inside when the junction reaches the visibility limit (24 s): with no pre-movement a median of 72 in U, 72 in S, 78 in R and 90 in R-na; U has fewer than R in 20 of 20 seeds (median 6 fewer). At 30 and 60 s all 100 are inside in every arm. So U is not conservative on this count.

Dose

A three-by-three grid of cumulative distributions, rows for pre-movement 0, 30 and 60 s, columns for max FIC per agent, seconds at HCl 300 ppm or more, and seconds at K 0.3 per metre or more, for arms U, S and R. In the FIC column with no pre-movement the R curve lies far left of U, with almost every R agent below FIC 2, and S lies right of U; at 30 s R lies left of U for most agents with a longer tail to the right, S right of U, and at 60 s R lies on top of S, right of U. In the two time columns S lies right of U in every row; R lies left of U with no pre-movement, with over 70 percent of its agents at 0 s, between U and S at 30 s, and on top of S at 60 s

Share of agents with a value ≤ x, pooled over seeds (2,000 agents with no pre-movement, 1,000 at 30 and 60 s). Curve further right: more dose. Values until each agent’s exit, at z = 2.0 m (the deck’s only slice height; the 1.6 m default resolves to it, see A crowd in a fire › The fire), 1 s resolution. Seconds at K ≥ 0.3 1/m are secondary: obscuration alone is not treated as incapacitating for people who are not performing tasks (ISO 13571:2012, §4.5, note). Regenerated by scripts/docs/fire_blind_vs_coupled.py.

Per seed, U against R. R-na differs from R at 30 s (95 % against 51 % at exit A) and gives nearly the same exits at 0 s (97 % against 100 %) and at 60 s (6 % against 3 %).

Dose metricpre-movement 0 s30 s60 s
Median of the agents’ peak FICU higher in 20/20U higher in 10/10U lower in 10/10
Agent-seconds at HCl ≥ 300 ppmU higher in 19/20U lower in 10/10U lower in 10/10
Agent-seconds at HCl ≥ 1000 ppmU higher in 20/20U lower in 10/10U lower in 10/10
Max FEDU higher in 17/20U lower in 10/10U lower in 10/10
Agents past K 0.3 or HCl 300 ppm before getting outU more in 20/20100 in every arm100 in every arm
  • Against R, “conservative” depends on the metric and the pre-movement. With no pre-movement U over-states every dose metric: the peak FIC and the time above 1000 ppm in 20 of 20 seeds, the time above 300 ppm in 19 and the max FED in 17. U walks into exit B’s HCl, which almost every R agent avoids. At 30 s U still over-states the median peak FIC (10 of 10) but under-states the time above both HCl levels and the max FED in every seed: about half of R’s agents walk to B later, in thicker smoke. At 60 s U under-states every metric in every seed.
  • Against S, U under-states the run totals in every seed, at every pre-movement: agent-seconds at HCl ≥ 300 and ≥ 1000 ppm and at K ≥ 0.3 1/m, and max FED. On single agents it does not always: U’s peak FIC is higher than S’s for 617 of 2,000 agents with no pre-movement, 287 of 1,000 at 30 s and 270 of 1,000 at 60 s.
  • The largest max FED of any agent is 0.06 in U, 0.19 in R and 0.19 in S, each at 60 s. FED 0.3 passes at the four fixed points in every arm (table above), and no agent of U, S, R or R-na reaches it. A FED below 0.3 or 1 is not a statement of tenability: FED 0.3 is a threshold for susceptible people, and FED < 1 does not mean safe (Incapacitation thresholds).

Per-agent margin, first crossing of K 0.3 1/m minus the agent’s own exit, compared on the same agent (seed, origin, spawn order):

pre-movement 0 s30 s60 s
Agents crossing in both U and R566 of 2,0001,000 of 1,0001,000 of 1,000
Median R − U among them−3.8 s (R smaller in 429)−6.3 s (836)−26.6 s (998)
Median S − U, crossing in both−1.8 s (S smaller in 1,551 of 1,894)−14.1 s (972)−27.8 s (998)

With no pre-movement, 1,332 agents cross the limit in U but not in R, and none the other way round. Counting an agent that never crosses as having an infinite margin, R has the larger margin for 1,466 agents and U for 429. So with no pre-movement the direction depends on how agents who never cross are counted; at 30 and 60 s U’s margin is larger (not conservative) for 836 and 998 of 1,000 agents.

Is exit usage conservative?

Exit usage is not conservative or otherwise. Choosing exits is part of the scenario: each design fire scenario is analysed with design occupant scenarios, and the occupants’ initial route choice is one of the variables of such a scenario (Nilsson and Fahy 2016, pp. 2047, 2061). Here the difference is large: exit B for everyone without the fire, exit A for 100 % with it when people move at once, for about half after 30 s of waiting and for few after 60 s. It also drives the dose differences above.

Sensitivity arms

Incapacitation, per-agent thresholds, HCl slowdown and route look ahead
ArmFlags on top of RResult
R-na"anticipate": false in the scenario’s routing block (see below)With no pre-movement 2.2 s later than R in median (R-na > R in 16 of 20, p = 0.004), with 97 % [95, 98] at exit A against 100 % in R. At 30 s: 95 % at A against 51 %, last out 0.8 s earlier in median. At 60 s: 6 % at A against 3 %.
R-dettenability on (FED 1 incapacitates)Identical to R: nobody reaches FED 1.
R-probR-det with --incapacitation-mode probabilisticIdentical to R at 0 and 30 s: nobody is incapacitated. At 60 s, 8 agents are incapacitated in 6 of 10 seeds and 9 are inside at 270 s; RSET is censored (> 270 s) in 6 seeds. The median last exit among the rest is 162.4 s, as in R. Their dose counts only until incapacitation.
R+FICR-det with --enable-fic-speedNo pre-movement: RSET 98.5 s [83.9, 118.3], with 14.5 [8, 24] agents at the 0.3 speed floor. At 30 s: median RSET 225.8 s, censored in 1 of 10 seeds, 1 of 1,000 agents inside at 270 s. At 60 s: censored in 10 of 10 seeds, 397 of 1,000 inside, and 22 agents per seed (median) reach FED 0.3. Max FED reaches 0.48 at 30 and at 60 s.

To build R-na, add the key to a copy of the scenario and save the copy next to a copy of geometry.wkt, which the scenario needs beside it:

mkdir -p ww/na
cp assets/t_junction/geometry.wkt ww/na/
uv run python - <<'EOF'
import json
from pathlib import Path

config = json.loads(Path("assets/t_junction/config_initial_pre0.json").read_text())
config["routing"]["anticipate"] = False
Path("ww/na/config_initial_pre0.json").write_text(json.dumps(config, indent=2))
EOF
uv run python run.py --scenario ww/na/config_initial_pre0.json --seed 4 \
    --fds-dir "$FDS" --disable-tenability \
    --output-sqlite ww/rna.sqlite --output-exit-history ww/rna_exits.csv
Simulation finished in 60.68 s (100/100 evacuated).

97 leave by exit A and 3 by exit B; in R, 98 take exit A and 2 exit B. The study script builds the same files (write_noanticipate).

A censored RSET is only known to exceed 270 s. It is never compared by size with U’s. An agent incapacitated or still inside at 270 s never counts as out, so a coupled RSET cannot look shorter because people dropped out of the count. The R-prob and R+FIC runs that reach 270 s with agents inside are incomplete, and run.py exits with status 2 for them (Exit status). R+FIC is an upper bound: it is mostly censored, its dose stops at the cap, and it rests on HCl that is probably overestimated.

4. Run the whole study

uv run python scripts/docs/fire_blind_vs_coupled.py --data "$FDS" --runs RUNS

RUNS must lie outside the repository. The script runs arms C, U, S, R, R-na, R-det, R-prob and R+FIC for seeds 4–23 with no pre-movement and 4–13 at 30 and 60 s, one run.py process per arm and seed (#198). It skips runs that already exist, prints every number on this page, writes summary_runs.csv and summary_agents.csv into RUNS, and redraws the figures in site/static/images/fire-blind/. At 9c820e0f the 320 runs took 481 s (about 8 min) of wall time on 8 workers, the default of --workers, on an Apple M3 Pro; the analysis alone takes about 20 s. Seeds 1–3 were used for a pilot and are left out.

The animation above is drawn from the same RUNS folder:

uv run python scripts/docs/study_animations.py fire-blind --data "$FDS" --runs RUNS

Provenance. The numbers and figures on this page come from runs of commit c619a046 on main (0.5.0), from a worktree of that commit, made with the two commands above (Python 3.13.4). Each run’s manifest records that commit and agent_seeding: spawn-key-blake2b-v2. The seed-4 walkthrough above gives trajectories identical to those study runs. When the code changes, re-run the study into a new RUNS folder and compare the printed report with this page.

Limits

  • One fire with no margin. Here, at every point, the visibility limit is met before the last person gets out, in every arm. Schröder et al. (2020, §4) state that the effects of smoke, heat and toxic gases on route choice and walking speed “should play a subordinate role as long as the safety margin is sufficiently greater than the limiting state”. In our view, the regime near the limit is where practice decides, and this study does not test it.

  • The size of the S − U and R − U gaps is not measured behaviour. The smoke-speed law is fitted to Frantzich and Nilsson’s data, K ≈ 1.9–7.4 1/m (read from their Fig. 14; see walking speed in smoke), and has a floor of 0.1 from K = 11.1 1/m. Share of moving agent-seconds below / within / above that range, and at the floor:

    Armpre-movement 0 s30 s60 s
    S83 / 11 / 6 %, floor 3 %41 / 37 / 22 %, floor 11 %1 / 46 / 53 %, floor 18 %
    R94 / 6 / 0 %, floor 0 %45 / 46 / 9 %, floor 5 %1 / 47 / 52 %, floor 18 %

    Below 1.9 1/m the law is outside the data too. There it slows people by 2.4 % at K = 0.3 1/m, the visibility limit, rising to about 15 % at 1.9 1/m.

    Left: the speed factor against the extinction coefficient K from 0 to 25 per metre, solid over the Frantzich and Nilsson data range 1.9 to 7.4, dashed outside it, falling from 1 at K 0 to the floor 0.1 at K 11.1 and flat after. Right: histograms of K at moving agents in arms S and R; the largest bin is below 0.5 per metre, with a tail beyond 11; an annotation gives S 26 percent above 7.4 and 10 percent at the floor, R 21 and 8 percent

    Left: speed factor v/v₀ [-] against K [1/m] of the default law; shaded: the data range. Right: K at the moving agent [1/m], share of agent-seconds [%], pooled over all three pre-movements; the last bin holds K ≥ 24.5. “At the floor” counts K ≥ 11.1 1/m. Regenerated by scripts/docs/fire_blind_vs_coupled.py.

  • Route foresight. R’s route cost reads the smoke ahead from the whole FDS record (#125). R’s avoidance of exit B is therefore not a claim that people would see it coming. R-na removes only the look ahead in time: it still reads the current smoke along the whole route, including parts no occupant could see. With no pre-movement it sends 97 % [95, 98] to exit A against 100 % in R, at 30 s 95 % against 51 %, and at 60 s 6 % against 3 %. At 30 s foresight therefore moves agents toward exit B, the exit by the fire, when it sees smoke coming on the longer route.

  • All routes refused before people move. Then the router takes the route with the lowest optical depth τ (#458), here the shorter route to exit B past the burner. It is not the safer route: at 60 s the median over seeds of the largest max FED is 0.18 under the default rule, against 0.10 under the code-level fallback_rule="hold", which keeps everyone on the route to A. At 0 and 30 s most R agents already take exit A. Whether this rule is right is open (#696).

  • HCl is probably overestimated. The deck has no HCl loss to walls (A crowd in a fire › What this does not show). That makes the HCl crossings early and inflates R+FIC.

  • The HCl slowdown is opt-in, off in S and R, and incapacitation uses the FDS+Evac FED (FDS+Evac has no irritant slowdown), not HCl.

  • Constant pre-movement. Everyone waits the same 0, 30 or 60 s. The three values were fixed from the fire before any run: 0 s moves before the junction reaches the visibility limit (24 s), 30 s falls between the first and last of the six points of A crowd in a fire (18–46 s), 60 s after all of them. Babrauskas et al. (2010, pp. 346–347, 351) criticise pre-movement times of 0–80 s used for homes as unrealistic. Citing an NRCC study, they report that healthy occupants of a single-family house at night can need up to 11 min from alarm to exit (p. 346). That figure includes travel and is counted from the alarm, not the fire. Those are residential values and do not transfer to this geometry.

  • Everyone knows both exits (familiarity: "full"). Agents who discover exits could fail to find one, and the familiarity draw depends on the JuPedSim id (#198). For sign loss in this fire, see A crowd in a fire.

  • The time limit is 270 s, 30 s before the end of the FDS output. Route foresight samples ahead of the current time and can read past the end (#356); the longest route, 30 m from the branch to exit A, takes 23 s at the 1.3 m/s the cost assumes. Configured waypoints are not included in that bound.

  • Per agent goes beyond ISO 13571, which treats populations, not individuals (§5.2). The FED is the FDS+Evac FED, not the ISO asphyxiant FED.

  • The ASET side is not built in. The location ASET and the crossings are computed by the script, not by the engine (#210).

Sources
  • Babrauskas, V., Fleming, J. M., & Russell, B. D. (2010). RSET/ASET, a flawed concept for fire safety assessment. Fire and Materials, 34(7), 341–355, pp. 346–347, 351. doi:10.1002/fam.1025
  • Engineers Australia Society of Fire Safety (2014). Practice note for tenability criteria in building fires, version 2.0, §5.2 and Fig. 8, Tenability Criteria – Short Exposure, p. 15. Full reference on ASET and RSET.
  • Frantzich, H., & Nilsson, D. (2003). Utrymning genom tät rök: beteende och förflyttning, Fig. 14. Full reference on walking speed in smoke.
  • ISO 13571:2012, §4.5 (note) and §5.2; ISO/TR 16738:2009, Eq. 1, Eq. 2 and §5.6: paraphrased; see ASET and RSET.
  • Nilsson, D., & Fahy, R. (2016). Selecting scenarios for deterministic fire safety engineering analysis: life safety for occupants. SFPE Handbook of Fire Protection Engineering, 5th ed., Ch. 57, pp. 2047, 2061. doi:10.1007/978-1-4939-2565-0_57
  • Purser, D. A. (2003). ASET and RSET: addressing some issues in relation to occupant behaviour and tenability. Fire Safety Science, 7, 91–102, p. 92. doi:10.3801/IAFSS.FSS.7-91
  • Schröder, B., Arnold, L., & Seyfried, A. (2020). A map representation of the ASET-RSET concept. Fire Safety Journal, 115, 103154, §4. doi:10.1016/j.firesaf.2020.103154
  • Code: _assign_initial_exit in pyfds_evac/core/scenario.py; RouteCostConfig and _arrival_time in pyfds_evac/core/route_graph.py.

What next

Last updated on