ISO 20414 status

Status against ISO 20414

ISO 20414:2020 (Fire safety engineering — Verification and validation protocol for building fire evacuation models) defines 21 verification tests (Tests 1–21) and 9 validation tests (Tests 22–30). The table below gives the status of each verification test for pyFDS-Evac. FED means fractional effective dose, and K [1/m] is the extinction coefficient. Everything on this page is verification: it checks that the code reproduces the correlation or hand calculation it implements. None of it is validation against observed evacuations, and none of ISO 20414’s validation tests (22–30) has been run.

Tests 18 and 19: the fire–people interaction tests

These two tests cover the part of the model that pyFDS-Evac adds to JuPedSim. Each has its own page, with the setup, the expected values, the results and the pass criteria:

All verification tests

To run the ISO 20414 cases on your machine (the rows run or partly covered below), use uv run pytest -m "iso20414 and not external_data"; the same command runs in the “ISO 20414” workflow on every push and pull request to main.

“Not yet run” means that the component belongs to pyFDS-Evac, or is configured through it, but no test reproduces the ISO setup. “Inherited” means that the component is JuPedSim’s movement model, which pyFDS-Evac does not change; pyFDS-Evac has not rerun it. “Out of scope” means that pyFDS-Evac does not model the component.

TestTitleStatusReason
18Reduced visibility vs walking speedRun, passesOwn page. Frantzich–Nilsson and Fridolf laws, on the standard’s speed and K grid.
19Occupant incapacitation by fire/smokeRun for CO, CO2, O2Own page. Heat and optional gases not run in this layout.
1Pre-evacuation time assignmentPartly coveredThe four distributions gamma, log-normal, Weibull and uniform are checked against closed-form moments (test_premovement_verif.py); the constant preset is checked to give every agent exactly 10 s, the FDS+Evac default; the ISO room and per-agent start times are not run.
2Walking speed in a corridorInheritedMovement is JuPedSim’s.
3Walking speed on stairsOut of scopeNo stairs; the walkable area is one floor.
4Movement around a cornerInheritedMovement is JuPedSim’s.
5Assigned demographicsNot yet runSpeed distributions (v0_distribution) are set in pyFDS-Evac; their assignment has not been tested in the ISO setup.
6Horizontal counter-flowsInheritedMovement is JuPedSim’s.
7Overtaking people with movement disabilitiesInheritedMovement is JuPedSim’s; slower agents are set with v0.
8Exit route allocationRun, passes (user-defined allocation)23 occupants (radius 0.15 m, pre-evacuation 0 s) in twelve rooms off a 0.9 m corridor, six on each side, each with a 0.8 m door; rooms 1–4 and 7–10 are allocated to the main exit and rooms 5, 6, 11 and 12 to the secondary one (test_iso_test_8_route_allocation.py). The layout, the exits and the allocation by room position follow JuPedSim’s implementation of the test, not Figure 5, which was not checked; the room numbering (1–6 north, 7–12 south, west to east) is our reading, and the walkable area is cut to the corridor and the passage; the 23 are 11 rooms of two and one narrow room of one. Allocation is user-defined: each room’s journey in the scenario JSON names its exit. The check runs under "allocation": "hard" on every journey, which keeps the route graph at the allocated exit. With rerouting off, and with rerouting on in clear air (each route is re-evaluated every second), all 23 leave by the allocated exit, in each room, by the exit recorded for the agent and by the exit nearest to its last position; no agent switches. Default allocation is a preference: a journey’s exit holds unless a rival exit costs less than 0.9 times the allocated route (Routing in practice). At seed 42 the occupants of rooms 4 and 10, whose nearest exit is the secondary one, start at rival-to-allocated path ratios of 0.913–0.926 (hand calculation on the navmesh) and come no lower than 0.904–0.918 along the walk, just above 0.9, so the preference would also keep all 23; the margin is thin, so the standard’s check runs under hard. Two further tests pin an occupant of room 4 at a ratio of 0.885: it switches to the secondary exit under the default, and keeps the main exit under hard. Over seeds 1–10 under the default, 1.7 occupants per seed leave their allocated exit (1.2 at the opening choice, logged as allocation_preference; 0.5 by shorter_path within 1–2 s), and the secondary exit’s share of the 23 rises from 0.348 to 0.422. Without journeys (the predictive reading: the model picks the exit by route cost) the occupants of rooms 4 and 10, whose nearest exit is the secondary one, take it by a path about 0.9 m shorter, so 4 of the 23 leave by an exit other than the allocated one; pyFDS-Evac does not pass the predictive reading in this layout. One layout and one seed (42). Fire variant: a synthetic extinction field (5 /m, switched on at 5 s) fills the main passage, a 2.0 m long box; the router samples every 0.25 m and re-evaluates every second. A main route entered from the corridor then costs τ = 10 against the refusal limit of 6, and the secondary route costs 0. Under the default preference, with anticipate: false, the ten main-allocated occupants not yet in the passage switch to the secondary exit (smoke_reroute) at the first pass, within 1 s + 0.03 s of the smoke; the two already past the box keep the main exit; of the three inside, the one nearest the entry (τ 7.6 ahead against 2.4 on turning back) turns back and two go on. That makes 11 switches, and all 23 leave. With "allocation": "hard" nobody switches (no route row at all): the agents walk through the smoke at 0.596 of the free speed and all 23 leave by the allocated exit, the run ending 1.5 s later than in clear air. A preference also yields at K = 1 /m (τ = 2, below the refusal limit), on the tau band of 0.6 alone. With the default anticipation the router sees the field at the start, so ten occupants choose the secondary exit at t = 0 (allocation_preference) and two more switch later. Passes; one layout and one seed (42). FDS variant (#850, test_iso_test_8_fire.py, assets/iso_test_8_fire/): the same box as prescribed soot (one &INIT) in FDS 6.10.1 decks at K = 5 and 1 /m. An &INIT acts at t = 0, so this covers the allocation at spawn, not the 5 s onset. The deck is frozen at 0.1 s and the run holds that frame (--allow-fds-horizon-hold): nothing in FDS holds the soot in the box, and one cell inside its ends K is 11 % low at 10 s. Read through the FDS slice reader, the box gives the routes and exits of the synthetic box switched on at t = 0 in all four runs: under the preference, 15 allocation_preference rows at t = 0 and all 23 by the secondary exit, at both K and with anticipation (end 19.4 s); under hard, no route row and the clear-air split (end 17.5 s against 17.6 s on the synthetic box and 16.0 s in clear air). The FDS output is external data; CI skips these tests.
9Dynamic availability of exitRun, passesOne occupant (pre-evacuation 0 s, 1 m/s) in a 10 m × 15 m room with two 1 m exits about 5 m away (the start area is 1 m × 1 m, so the exits are equidistant to within 0.5 m); exit 1 is closed after 1 s (closed_after_s). The occupant, first headed for exit 1, is rerouted within 1 s of the closure and leaves by exit 2; without the closure it leaves by exit 1; exit 1 is used by nobody (test_iso_test_9_dynamic_exit.py). A schedule acts only through rerouting and needs routed agents: journey agents are rejected. Fire variant: instead of a schedule, a synthetic extinction field (5 /m, switched on at 1 s) fills the strip x ≤ 2 m, which includes the exit-1 door. Exit 1 then costs τ = K̄·L = 10–12.5 against the refusal limit of 6, and exit 2 costs 0. With anticipation off (anticipate: false) the occupant first heads for exit 1, then switches to exit 2 (smoke_reroute) within 1 s + 0.02 s of the smoke arriving, and leaves by exit 2. With the default anticipation the router reads the field at the predicted arrival time, so the occupant heads for exit 2 from the start and no switch is recorded. Exit 1 is used by nobody in both readings; passes. There is no FDS variant (#850): an &INIT acts at t = 0 and cannot give the onset at 1 s.
10Congestion in front of a flight of stairsOut of scopeNo stairs.
11Maximum flow rates at an opening/exitRun, passes100 occupants (radius 0.15 m, pre-evacuation 0 s) in an 8 m × 5 m room with a 1 m exit centred on the 5 m wall (test_iso_test_11_max_flow.py). The standard reads the test as verification when the maximum flow is user-defined and as validation when it is emergent. Verification reading: exit throttling on at 1.33 p/m/s (the MSC.1/Circ.1238 example); the measured flow (N − 1)/(t_last − t_first) is 1.32 p/m/s, asserted to stay at or below 1.33 p/m/s (1 % tolerance for the 0.1 s frame rounding) and at or above 0.95 × the limit; the throttled flow is the same on seeds 1–5. Validation reading (the default, throttling off): the emergent flow of JuPedSim’s CollisionFreeSpeedModel is 3.78 p/m/s on the tested seed (3.8–4.1 p/m/s over seeds 1–5), reported and not asserted; only the evacuation of all 100 is. Smoke variant (smoke-speed model on, constant extinction K in the whole room, seed 1): throttled, the flow is 1.32 p/m/s at every K ∈ {0.5, 1, 3} /m and under both speed laws, the same as in clear air, so the cap is not counted twice. Unthrottled, the flow relative to clear air (3.78 p/m/s) is, for Lund, 1.00, 0.99 and 0.88 against a speed factor of 0.96, 0.92 and 0.76, and for Fridolf (A = 2) 1.00, 0.88 and 0.58 against 1.00, 0.74 and 0.39 (flows 3.79, 3.75, 3.33 and 3.78, 3.31, 2.18 p/m/s). The flow drops by less than the speed factor: it is limited partly by congestion at the door, not only by the free walking speed. Fridolf at K = 0.5 /m gives no slowing and reproduces the clear-air exit times to one frame. One layout and one seed. There is no FDS variant (#850): the Table 21 case of Test 18 already reads a uniform FDS field through the same path.
12Stair flow ratesOut of scopeNo stairs.
13Flow rate, density and walking speed in a corridorInheritedMovement is JuPedSim’s.
14Group behaviourOut of scopeGroups are not modelled.
15Social influence on exit choiceOut of scopeHerding is not modelled (issue #78).
16Affiliation to familiar exitsRun, passesOne occupant (radius 0.2 m, 1 m/s) in the Test 9 room, two 1 m exits about 5 m away (the start area is 1 m × 1 m, so the exits are equidistant to within 0.5 m) (test_iso_test_16_familiar_exit.py). Mechanism: the cognitive-map model, not a user-defined split. Scenario 1 sets familiarity: "discovery": the occupant knows no exit, there is no sign, so it takes the default route to the nearest exit and the split is set by where the seeded start falls in the start area, not by a preference. Scenario 2 adds entrance: "exit_2": the exit the occupant walked in through is known whatever its familiarity, so its known graph holds exit 2 only. No journey, weight or per-run assignment names the exit. Stopping rule: seeds 1, 2, … are added until the cumulative exit-2 fraction has changed by less than 1 % for ten added runs in a row (cap 500), stricter than the standard’s “less than 1 % per added run”, which a single flat step would meet. Scenario 1: exit 2 used by 49.2 % after 61 runs. Scenario 2: 100 % after 11 runs; this follows from the known graph, which holds exit 2 only, so it shows the mechanism works, not a measured preference. Asserted: scenario 2 exceeds scenario 1 by more than 0.25 (the binomial scatter of scenario 1 is about 0.05 at 100 runs), and scenario 2 is 100 %; with entrance: "exit_1" every run leaves by exit 1, so exit 2 is not favoured by the geometry. The model has no graded preference between known exits here: affiliation is knowledge of an exit, not a probability weight. familiarity as a number in [0, 1] is the chance each exit is known, the same for both exits, so it cannot express affiliation with exit 2: a probe with 0.5 in scenario 2 gave exit 2 in 44.8 % of 67 runs. A graded test needs per-exit familiarity (#136), which is not implemented. Smoke variant (#850, synthetic box field east of x = 6 m, so the route to exit 2 is smoky over 4.5 m and the route to exit 1 is clear; re-evaluation every 1 s; same stopping rule, 11 runs per cell). Exit-2 usage at K = 0.05 / 0.5 / 3 per m (tau = 0.23 / 2.25 / 13.5; a route is refused above tau = 6): an occupant affiliated with exit 2 only (scenario 2 above) 1.0 / 1.0 / 1.0; an occupant with full familiarity and a preference journey toward exit 2 1.0 / 0.0 / 0.0; an occupant with full familiarity and no journey 0.0 / 0.0 / 0.0. An affiliated occupant who knows only exit 2 goes through any smoke, including tau = 13.5, because it knows no other exit; it is slowed (6.2 s instead of 4.9 s at K = 3). Familiarity does not change willingness to enter smoke (#362): the smoke limits are the same for every agent, and familiarity only changes which exits are known. The preference journey yields when the exit-2 tau exceeds the exit-1 tau by more than 0.6, far below the refusal threshold; the test brackets this between K = 0.10 and 0.20 per m. FDS variant (test_iso_test_16_fire.py, assets/iso_test_16_fire/): the same box as prescribed soot in FDS 6.10.1 decks at K = 0.05, 0.10, 0.20, 0.5 and 3 per m. Read through the FDS slice reader, K inside the box is within 1 % of the target up to 10 s, which covers every run (2.5 % low by 30 s), and the cells on the box face read K/2. Every cell of the usage table above is the same as on the synthetic box (11 seeds each); the preference journey yields at K = 0.5 and 3 and not at 0.05; the bracket holds (exit 2 at K = 0.10, exit 1 at 0.20); the affiliated occupant at K = 3 leaves at 6.0 s (6.2 s on the synthetic box, 4.9 s in clear air). The FDS output is external data; CI skips these tests.
17Route choice based on geometric layoutOut of scopeThe ISO layout has two floors.
20Lift usageOut of scopeLifts are not modelled.
21Escalator usageOut of scopeEscalators are not modelled.

Movement is inherited from JuPedSim

pyFDS-Evac does not implement locomotion. Walking, collision avoidance, counter-flow and flow through openings are computed by the JuPedSim model named in the scenario (model_type, default CollisionFreeSpeedModel). pyFDS-Evac sets each agent’s desired speed and target, and it can cap the flow through an exit, but locomotion itself is JuPedSim’s. The movement tests are therefore inherited, and pyFDS-Evac has not rerun them. JuPedSim reports its own status against ISO 20414, RiMEA, NIST TN 1822 and IMO MSC.1/Circ.1533 on its V&V standards coverage dashboard, including the tests it marks as expected failures. That status applies to the models and versions it names, which may differ from the model and version a pyFDS-Evac scenario uses.

Last updated on