Install it, learn the habits that keep a screening result honest, then work through every command with a real output and what to do with it, from a relief valve to a full quantitative risk study.
Engineering Tools · Process Safety · User Guide
How to Use the Process-Safety Design Toolkit: A Complete Walkthrough, Command by Command
Revised
· v1.4.0 · what changed
This is the long version of the guide. It installs the toolkit, explains the few habits that keep a screening result honest, and then goes through the commands by job: relief and venting, fire and explosion, functional safety, regulation, electrical, and the quantitative risk study. Every output below was produced by running the command on 5 November 2026 with illustrative inputs. An asset-specific walk-through of an LPG terminal, with every result, is in section 16.
Try it in the browser first. A clickable design demo, Process Safety Studio, walks through five tasks in the same five steps the command line uses: choose a task, enter inputs with units, run, read the result with its notes and limits, and export. The tasks are a gas relief valve sized to API 520, OSHA PSM applicability, LNG terminal basics, PSM revalidation due dates and fire-and-gas detector coverage. Its results are outputs captured from the command line, not live calculations, so use it to see the workflow and install the toolkit to run your own numbers.
1. Install and orient
git clone https://github.com/herrrickshaw/process-safety-design-toolkit cd process-safety-design-toolkit git checkout feature/ifluids-service-map # until the two open pull requests merge python3 -m unittest discover tests # 173 tests should pass python3 -m process_safety coverage # every topic, its standards, and what is NOT implemented pip install -e . # optional: lets you run it from any folder
Run coverage first and read the lines that say “not implemented”. If you skip the install step and run from another folder, Python answers No module named process_safety; either install it with pip install -e . or run the commands from the repository folder.
2. Six habits that keep a screen honest
- Know which numbers are yours. Latent heat, set pressure, fill rate, failure frequencies and acceptance criteria are inputs. The toolkit will not invent them, and a diesel specific fuel consumption has no default for that reason.
- Check units on the command line. They are in each command’s help:
--p0and--set-gare kPa,blowdown --hole-dis metres,--wall-mmis millimetres. - Read the
noteandwarningsfields. They carry the limits of the result, such as the neutral-plume warning inplume. - Trust the refusals. The toolkit declines to answer outside a method’s range instead of returning a number (examples below).
- Sample before you scale. For the risk study, run
--samplefirst. - Verify against the standard you are held to. The module docstring names it;
coveragesays whether its text was read.
Here are two refusals, both real outputs. The arc-flash command only answers for open-air three-phase cases, and says so for enclosed equipment; the worst-case toxic release tells you when the neutral-plume model is outside its validity.
$ python3 -m process_safety arc-flash --kv 0.48 --ka 20 --t 0.2 --dist-mm 455 --enclosed
{
"applicability": {
"ok": false,
"why": "enclosed three-phase equipment (switchgear, MCC, panels): use IEEE 1584"
}
}
$ python3 -m process_safety rmp-worst chlorine --kg 1200 "release_rate_kg_s": 2.0, "beyond_model_range": true, "warning": "neutral-gas Gaussian screening is outside its validity at 1.5 m/s F-stability ..."
3. Relief and venting
The workflow is a chain. Work out the load for the scenario, then size the valve for that load. Here is a fire on a horizontal vessel (2.5 m by 8 m, liquid level 1.5 m, latent heat 330 kJ/kg), then the relief rate fed straight into the gas valve calculation for propane at 400 K and a 1,000 kPag set pressure.
$ python3 -m process_safety relief-fire --D 2.5 --L 8 --level 1.5 --latent 330 wetted_area_m2: 43.9 heat_input_kW: 960.6 relief_rate_kg_h: 10,480 $ python3 -m process_safety relief-gas --W 10480 --T 400 --set-g 1000 --case fire --M 44 --k 1.13 --Z 0.9 required_area_mm2: 935.8 orifice: K (API 526 letter) regime: critical
The note on the fire result is a reminder that the fire relieving pressure is 1.21 times the set pressure plus atmospheric. The area is the minimum; pick the next API 526 orifice up.
| Task | Command (shortened) | Key outputs (illustrative inputs) | Read it like this |
|---|---|---|---|
| Steam valve | relief-steam --W 5000 --set-g 1500 | Area 557.8 mm², orifice J, regime napier | Note says saturated steam is assumed |
| Liquid valve | relief-liquid --Q 50 --rho 700 --set-g 1000 --back-g 100 | Area 399.7 mm², orifice H, Re 548,689 | Re shows the viscosity correction is near 1 |
| Atmospheric tank, normal venting | tank-normal --volume 5000 --fill 500 --empty 400 --volatile | Outbreathing 1,797 Nm³/h, inbreathing 1,163 Nm³/h | API 2000 5th edition; the notes flag cases that need engineering review |
| Atmospheric tank, fire | tank-fire --shape vertical --D 40 --L 16 --F bare --normal-capacity 1500 | Wetted area 1,149 m², emergency venting 19,897 Nm³/h, extra 18,397 beyond the normal vents | Extra vent capacity is what you must add |
| Vapour-filled vessel in a fire | vapour-fire --volume 15 --area 36 --D 2 --wall-mm 20 --M 20 --k 1.3 --p0-g 1000 --psv-area 500 --psv-set-g 1500 | Rupture at 701 s, relief starts 319 s, peak 1,502 kPag, protected: false | The note says a valve alone is not enough: the wall weakens, so add depressuring or fire protection |
| Depressuring | depressure --volume 30 --p0 5000 --pt 1000 --T0 300 --M 20 --k 1.3 --area 800 | 301 s isothermal, 255 s adiabatic, minimum gas temperature 207 K | Two bounds; the temperature is a screen for minimum design metal temperature, not metal temperature |
| Blowdown through a hole | blowdown --volume 20 --p0 2000 --T0 300 --M 20 --k 1.3 --hole-d 0.025 | Initial rate 1.58 kg/s, 288 of 321 kg released in the 600 s window | Pressure in kPa absolute, hole diameter in metres |
4. Fire, explosion and dispersion
These give you distances to harm levels so you can place people and equipment. All are screening models.
| Task | Command (shortened) | Key outputs (illustrative inputs) | Read it like this |
|---|---|---|---|
| Pool fire | pool-fire --area 300 --hc 44000 --hv 350 --cp 2.2 --tb 400 | Pool diameter 19.5 m, flame height 30.9 m, heat release 1,012 MW, 37.5 kW/m² at 17.3 m, 12.5 at 37.0 m | Point-source distances; wind tilt and spreading are not modelled |
| BLEVE fireball | fireball --mass 20000 --hc 46 | Diameter 157 m, duration 12.2 s, 37.5 kW/m² at 196 m, 4.0 at 663 m | Radiation only; blast and fragments are not covered |
| Flare radiation | flare --mass 20 --lhv 46 --mw 30 --flame-length 40 | Heat release 920 MW, 4.73 kW/m² at about 63.8 m | It warns when a distance is under two flame lengths: the point-source result is unreliable there |
| Gas plume | plume --Q 100 --u 3 --H 2 --stability D --threshold-ppm 50 --M 34 | Peak ground concentration at 24 m, above 50 ppm out to 187 m | Neutral-buoyancy only; dense gases need a dense-gas model |
| Steel in a fire | steel-fire --am-v 150 | Steel reaches 550 °C in about 4 min in a hydrocarbon fire | Unprotected steel fails fast; shows why passive protection is specified |
5. Functional safety and reliability
Layer-of-protection analysis (LOPA) tells you how much risk reduction a safety function must deliver. The probability-of-failure command then checks an architecture against it.
$ python3 -m process_safety lopa --ie 0.1 --ipl 0.1 0.01 --target 1e-6 unmitigated_per_yr: 0.1 mitigated_per_yr: 0.0001 tolerable_per_yr: 1e-06 required_rrf: 100 sil_needed: SIL 1 $ python3 -m process_safety pfd --arch 1oo2 --lambda-du 2e-6 --ti-years 1 --beta 0.05 pfd_avg: 5.30e-04 rrf: 1,886 achieves: SIL 3
A hazard of 0.1 per year with two independent layers still leaves 1e-4 per year against a 1e-6 target, so a safety function with a risk reduction of 100 is required. A 1oo2 architecture with a dangerous undetected failure rate of 2e-6 per hour, a yearly proof test and a 5% common-cause factor gives a probability of failure of 5.3e-4, which meets the need on probability. Probability is not the whole test: the SIL tool also checks the architecture limits, and that is where a single valve usually fails (see section 9).
6. Regulation and management systems
| Task | Command (shortened) | Key outputs (illustrative inputs) | Read it like this |
|---|---|---|---|
| OSHA PSM applicability | psm-check --chemical chlorine --kg 700 | Threshold 680 kg, quantity 700 kg, covered: true | Looks the chemical up in the 134-chemical Appendix A |
| PSM due dates | psm-due --pha 2021-03-15 --audit 2023-06-01 --today 2026-11-05 | PHA revalidation overdue by 235 days, compliance audit overdue by 157 days | Five-year and three-year cadences from the OSHA text |
| Seveso classification | seveso Chlorine:H=6 'Hydrogen sulphide:H=3' | Tier: lower-tier, sum 1.2 against the lower threshold | EU thresholds only; the Indian MSIHC schedules are not implemented |
| US EPA RMP threshold | rmp-check chlorine --kg 1200 | Threshold 1,134 kg, covered: true | The 77 toxics and 63 flammables are parsed from the rule |
| Gas pipeline design | pipeline --smys 448 --wall 12.7 --od 610 --buildings 25 | Design pressure 134.3 bar, impact radius 223 m | US 49 CFR 192 basis, natural gas only |
| LNG terminal | lng --tanks 160000 --heat-kw 4000 --regas-kg-s 50 --sw-dT 5 | Impoundment 176,000 m³, boil-off 7.8 kg/s (1.0% a day), regas 44.4 MW, seawater 2.17 m³/s | Impoundment follows the US rule; siting models are not reproduced |
| LPG properties | lpg propane --fill-C 15 --max-C 50 | 1,616 kPag at 50 °C, density 506 kg/m³, fill ceiling 88% | Codes (API 2510, OISD, IS 2825) set the practical fill limit |
| Peroxide decomposition | h2o2 --kg-h 500 | Oxygen 235 kg/h, heat 401 kW, up to 640 kg/h steam | Pure H₂O₂ basis; a first look at a tank failure case |
7. Electrical, noise and machinery
| Task | Command (shortened) | Key outputs (illustrative inputs) | Read it like this |
|---|---|---|---|
| Arc flash, open air | arc-flash --kv 0.48 --ka 20 --t 0.2 --dist-mm 455 | 4.7 cal/cm², boundary 905 mm | Lee method; enclosed equipment is refused and sent to IEEE 1584 |
| Relay operating time | idmt --i 3000 --pickup 400 --tms 0.2 --curve very_inverse | Operates in 0.42 s at 7.5× pickup | Curve arithmetic; a coordination study is separate |
| Touch and step voltage | earthing --rho-s 3000 --t 0.5 | Touch 902 V, step 3,117 V for a 50 kg person | IEEE 80 tolerable limits; grid design is not implemented |
| Safeguard distance | safeguard --stop-s 0.5 --d-mm 14 | Minimum distance 800 mm | Pre-2024 ISO 13855 form; check your edition |
| Noise exposure | noise 90:8 95:2 | Dose 150%, time-weighted average 92.9 dBA, exceeds limit: true | Items are LEVEL_dBA:HOURS; OSHA 1910.95 basis |
8. The risk study (qra)
The risk study chains six steps: hazard identification, frequency, consequence, risk, evaluation against criteria, and mitigation. Everything is driven by one JSON file. Copy the worked example and edit it.
python3 -m process_safety qra example --out study.json # copy the worked example python3 -m process_safety qra validate study.json # units, sums to 1, references, provenance python3 -m process_safety qra hazid study.json --out hazid/ # registers for the workshop python3 -m process_safety qra run study.json --sample 3 --out sample/ python3 -m process_safety qra run study.json --out qra_out/ python3 -m process_safety qra buildings study.json --out qra_out/ python3 -m process_safety qra emergency study.json --out qra_out/
The study file has these top-level blocks:
| Key | What it holds |
|---|---|
materials | Properties per substance (molar mass, k, liquid density, boiling point, heat of vaporisation, heat of combustion, lower flammable limit, toxic component) |
sections | Isolatable sections with inventory, pressure, temperature, coordinates, and equipment lists; each equipment item with its hole sizes and frequencies and the source of each |
extra_scenarios | Scenarios that are not parts-count, such as a tanker loading failure |
ignition, conventions | Ignition model and the immediate-ignition fraction (a study assumption, not data), thermal exposure time, explosion yield |
weather, wind_rose | Stability class, wind speed and probability for each weather case, and the wind direction probabilities |
grid, receptors, population | The calculation area and step, named receptors with occupancy, and population zones |
indoor_vulnerability, buildings | How indoor occupants are protected, and each building with occupants and a target individual risk |
criteria, alarp | The acceptance preset (UK R2P2, Dutch Bevi or custom) and the cost-benefit settings, including an illustrative value of a prevented fatality |
mitigation | Candidate measures, each with a cost and the change it makes to the study |
emergency | Credible-case frequency cut-off, unit radius, site boundary and toxic levels |
On the worked example the full run takes about 13 seconds and finds 18 loss-of-containment scenarios with a total frequency of 0.0435 per year. Open qra_report.html first, then use the CSV files in Excel.
| Output file | What it tells you |
|---|---|
qra_report.html | The summary report: risk map, F-N curve, receptors, mitigation |
receptors.csv | Individual risk per named receptor and whether it is in the intolerable, ALARP or broadly acceptable region |
fn_curve.csv, lsir_grid.csv | The F-N curve data and the location-specific individual risk grid |
scenarios.csv | Every loss-of-containment scenario with its frequency |
qra_buildings.* | Occupant risk, overpressure and heat exceedance per building |
qra_mcls.csv, qra_emergency.html | Worst-case and credible distances and the emergency zones |
mitigation.csv | Fatalities prevented, cost-benefit ratio and decision for each measure |
hazid_register.csv, hazop_worksheet.csv | Starting registers for the workshop |
How to read the headline results on the example: the loading-bay operator has the highest individual risk (6.0e-4 per year), every receptor is tolerable if ALARP, yet the F-N curve is in the intolerable region against the UK preset. The mitigation table then says what to do: a loading-hose release coupling prevents 0.046 fatalities a year at a cost-benefit ratio of 0.033, so implement; extra shutdown valves and relocating a building are not justified on cost-benefit alone.
--sample N runs N scenarios on a coarser grid, re-runs them at double angular resolution to test convergence, and projects the full-run time. The study found two of its own bugs this way.9. The JSON study tools
Seven further tools each read a JSON file, run input checks, and write CSV or HTML with a checks list. Copy an example with tool example NAME, run it with tool NAME file.json --out folder/.
| Tool | What it does | Result on the shipped example |
|---|---|---|
bowtie | Threats, prevention barriers, top event, mitigation barriers, consequences; barrier importance and the safety-critical element list | Top event 1.7e-4 per year; the independent high-high level trip is the safety-critical element |
sif | SIL from risk reduction, architecture limits (IEC 61511 and 61508 Route 1H), probability of failure, spurious trips, risk graph | Target SIL 2; probability meets SIL 2 but one valve with 40% safe-failure fraction caps it at SIL 1, so it fails |
fg | 2D fire and gas detector coverage and a placement optimiser | Bullet area 2-detector coverage 1.8% against 90%; optimiser adds 18 detectors and reaches 68.7%, still short |
thermal | Runaway screening: time to maximum rate, Stoessel class, storage safety margin | Nitration batch class 3; 53.9 K margin at 35 °C storage |
atex | Zone, equipment protection level and category by release grade; dust class | Powder charging room: zone 21, EPL Db, category 2D, dust class St2 |
ram | Monte Carlo reliability and availability of a production train | Production availability about 97.5% on the example; 574 runs set by the target precision |
pha | CHAZOP, what-if and SWIFT worksheets, action register, revalidation dates | Action closure 33%, one overdue action, one high-risk action still open |
10. Use it from Python
Every module is importable. This is useful for loops, spreadsheets and your own checks.
$ python3 -c "from process_safety import datacentre as dc; print(round(dc.pue(13000, 10000), 2)); print(round(dc.k_of_n_availability(3, 4, 0.99), 6))"
1.3
0.999408
$ python3 -c "from process_safety import hydraulics as h; a=h.wave_speed_m_s(1.0e9, 560, 0.35, 0.0095, 2.0e11); print(round(a,1)); print(h.surge_screen(L_m=300000, a_m_s=a, closure_s=30, rho=560, dv_m_s=1.5))"
1228.0
{'critical_time_s': 488.60704262757326, 'joukowsky_kPa': 1031.5037566582102, 'estimated_kPa': 1031.5037566582102, 'rapid_closure': True}
The second example is a surge screen: a 30-second valve closure on a long liquid line with assumed fluid and wall properties. It reports the wave speed, the critical time (489 s), and a Joukowsky pressure rise of about 1,032 kPa, in the rapid-closure regime. It is a screen, not a transient simulator.
11. When it goes wrong
| What you see | Why | Fix |
|---|---|---|
No module named process_safety | You ran it outside the repository folder without installing it | pip install -e . or run from the repository folder |
KeyError: 'flow' from hazop-csv | HAZOP parameters are case-sensitive | Use Flow Pressure Temperature Level (also Composition, Phase, Reaction, Utilities, Operation/Maintenance) |
An absurd rate from blowdown (a million kg/s) | Pressure is in kPa absolute and the hole diameter is in metres; millimetres inflate it a thousandfold | Pass --hole-d 0.025 for 25 mm |
ok: false from arc-flash | Enclosed equipment or higher voltage is outside the method | Use an IEEE 1584 study |
--gen-hours needs --sfc | Diesel fuel consumption is vendor data with no default | Supply --sfc in g/kWh |
| A result that looks too clean | Inputs are placeholders | Run coverage and read the module docstring before relying on it |
12. Limits, and where to go next
- No dense-gas model. Propane and chlorine clouds spread differently from the neutral plume. Feed validated footprints from a tool such as DNV Phast or RISKCURVES through the
overrideshook. Section 16 shows what this means for a propane terminal. - Paywalled standards. API 752/753, IEC 60079-10-1 and IEEE 1584 were not read, so building-damage curves, zone extents and enclosed arc flash are inputs or refusals.
- No default Indian criteria. The risk study ships UK and Dutch presets; supply a custom criterion for an Indian site.
- Software-class studies. Load flow, harmonics, transient stability, pulsation and illumination are listed as not implemented.
Read next in the repository: docs/QRA.md (the study file and models), docs/STUDIES.md (the seven JSON tools), docs/ELECTRICAL_MECHANICAL.md (what was read versus corroborated), docs/DATACENTRE.md (data-centre helpers) and docs/IFLUIDS_SERVICES.md (consultancy services mapped to modules).
13. What is new in version 0.10
Version 0.10 is on pull request 3, stacked on the two earlier pull requests, and is not yet merged: install from that branch to try it. It adds input checks, a glossary, a restructured command line and an independent cross-check. The short video shows each of them running.
Inputs are checked against ranges
Each numeric input has a hard range (physically impossible outside it: the run stops with exit code 2) and a soft range (atypical: a warning on the error stream, and the run continues). The soft ranges are engineering judgement, there to catch unit slips; they are not a standard’s limits. --no-range-check skips both for a deliberate extreme case.
$ python3 -m process_safety relief-gas --W 5000 --T 300 --set-g 1000 --M 30 --k 2.5
warning: --k=2.5 is outside the typical range (-inf, 1.67] for Cp/Cv (isentropic exponent) (1.67 is monatomic; most process gases are 1.1 to 1.4): check the value
{ "required_area_mm2": 415.42616954563, "orifice": "H", ... } (exit code 0)
$ python3 -m process_safety relief-gas --W 5000 --T -5 --set-g 1000 --M 30 --k 1.3
process_safety: error: --T=-5 K is outside the possible range (0, inf) for absolute temperature (exit code 2, no result)
$ python3 -m process_safety ranges heat_capacity_ratio
{
"name": "heat_capacity_ratio",
"unit": "-",
"description": "Cp/Cv (isentropic exponent)",
"hard_range": "(1, inf)",
"soft_range": "(-inf, 1.67]",
"note": "1.67 is monatomic; most process gases are 1.1 to 1.4"
}
A glossary in the command line
python3 -m process_safety glossary TERM searches about 115 terms and abbreviations; the same table generates docs/GLOSSARY.md. These are working definitions for orientation: the standard named in each entry governs.
$ python3 -m process_safety glossary BLEVE
BLEVE (Boiling-liquid expanding-vapour explosion)
Sudden rupture of a vessel holding liquid above its atmospheric boiling point, usually ending in a fireball.
[Fire, explosion and dispersion; fireball]
Fireball
The rising ball of burning vapour after a BLEVE or a large flash release; harm is by thermal radiation.
[Fire, explosion and dispersion; fireball]
Cleaner structure, same numbers
The command line is now a registry with one class per command instead of a 34-branch conditional. Forty outputs captured before the change are compared after it, within 1e-9, because the last digit of a float differs between platforms. Continuous integration runs on Python 3.10 to 3.13. The lint step found two real bugs, both fixed: an f-string that was a syntax error on Python 3.10 and 3.11, and a missing import in the PSM module.
124 cross-checks, and the differences that remain
$ python3 -m unittest discover tests
Ran 192 tests in 7.346s
OK
$ python3 tests/crosscheck/validate.py
checks: 124 within tolerance: 124 outside: 0 not computed: 0
The references are the fluids, thermo and CoolProp libraries and closed-form formulas from the open literature. Agreement shows the toolkit matches other implementations; it does not show a result is right for your plant. Known differences: liquid relief area runs about 4.7% below fluids in both cases checked and the cause is not resolved, so confirm it against vendor sizing; steam area uses the older Napier constant; and the API 2000 fire heat input has a boundary at 0.07 barg. The full list is in docs/VALIDATION.md.
14. What is new since 0.10: derogations, EU impact, insurance and legal clauses
These additions are on pull request 4, stacked on the earlier pull requests and not yet merged. The command line now has 47 commands, 342 automated tests pass and the cross-check suite has grown to 186 checks, all within tolerance. The new work answers one question: when a design departs from a must clause, who approves it, what does it cost the business, what does European law say about it, what does it do to the insurance, and where does the law set the limit? Every default below (tiers, approval levels, thresholds) is editable and is not any company’s rule.
Must, should, can, and the derogation
Each clause in a standard is graded from its modal verb. A must (shall, must, shall not) is complied with or formally derogated. A should is comply-or-explain. A can is optional, and you record whether you adopted it. A derogation is a formal, approved departure from a must. It needs a justification, a risk assessment reference, at least one compensating measure, an expiry date, a consequence assessment and the sign-offs the matrix requires. A statutory clause cannot be derogated by company sign-off at all; only the regulator can exempt.
$ python3 -m process_safety compliance process_safety/examples/compliance.json --as-of 2026-11-06
"by_tier": MUST complied 1, derogated 3, open 0
SHOULD complied 0, derogated 1, open 1
CAN adopted 0, not-adopted 1
"must_compliance": 1 of 4 satisfied (25.0%)
"ready_for_gate": false (condensed from the JSON)
The example register is deliberately faulty, so that it fails the gate and shows each failure code. A gate that cannot fail would tell you nothing.
The approval matrix: TA1, TA2 and TA3
The class of a derogation is the highest of its safety severity and six management ratings (next section). The class then sets who must sign.
| Tier | low | medium | high | severe |
|---|---|---|---|---|
| MUST | TA2 | TA2 | TA1 | TA1 + TA2 |
| SHOULD | TA3 | TA3 | TA2 | TA1 |
TA1 is taken as the most senior level and TA3 the least: that ordering is an assumption you can edit. A higher level can stand in for a lower one, and each sign-off must come from a different person. With no consequence assessment the class defaults to severe. In the example, clause 4.2.2 is a medium must that needs TA2 but carries only a TA3 sign-off, so the review reports unmet: TA2 and the issue approval-insufficient.
PESTLE: mapping the management consequence
For each derogation the assessor rates six lenses from 0 to 5: political, economic, social, technological, legal and environmental. 0 to 2 is low, 3 medium, 4 high and 5 severe. A rating of 3 or more needs a written management action, and a must derogation must address all six factors and describe the scenario if the derogated clause fails. In the example, clause 4.1.3 rates the economic factor 3 (a pump-house outage of about ten days) and records its action: a spare pump on site and business-interruption cover confirmed. The tool enforces completeness; the ratings themselves are the assessor’s judgement.
EU impact: Seveso III
A company derogation never waives an EU or national requirement. A clause can be marked as restating an EU provision (non-derogable) or implementing one (it needs an equivalence argument and is floored to the high class). The register also records the Seveso tier and screens each derogation against the Article 11 question: is the change significant, was the authority informed, and were the notification, the major-accident prevention policy, the safety management system and, for an upper-tier site, the safety report updated?
"eu_compliance": { "seveso_tier": "upper", "non_derogable_eu_clauses": ["9.1"],
"art11_significant": ["4.1.3"], "art11_unassessed": ["4.2.2"], ... }
issues: 4.1.3 seveso-documents-not-updated, 4.2.2 seveso-not-assessed,
9.1 statutory-no-exemption (condensed from the JSON)
Only the Seveso III articles are encoded. ATEX, the Pressure Equipment Directive, the Industrial Emissions Directive and your member state’s transposition are separate checks.
Insurance impact, from an actuarial perspective
insurance takes an exposure rating, scenario frequencies, loss distributions with an uncertainty (error) factor, and the deductible and limit. It computes the expected loss in the layer, its variance, a technical premium and the retained loss. Each case scales the scenario frequencies by the probability of failure on demand of the derogated safeguard. With the invented inputs shipped as an example:
| Case (USD) | Technical premium | Change | Retained expected loss |
|---|---|---|---|
| baseline | 3,128,810 | 0% | 40,346 |
| derogated | 6,639,142 | +112.2% | 133,464 |
| derogated with compensating measure | 4,205,767 | +34.4% | 63,617 |
In that illustration the present value of the saving from the compensating measure is about 16.8 million dollars against a measure cost of 2.5 million. The inputs are invented, so read this as a method, not a finding. A modelled premium is not a quotation, and no market rates or loss data are shipped.
Legal clauses across eight regimes
legal-clauses searches 55 provisions from eight regimes: India (15), Australia at Commonwealth level (13), Singapore (6), Canada at federal level (6), South Korea (6), the EU (5), the US (3) and Great Britain (1). Each is filed under one of four topics: general duty, change, notify and exemption. Grade A (40 clauses) means the legal text was read. Grade B (15 clauses) means only guidance, a mirror or an OCR copy was seen: confirm it against the legislation. For India, the Manufacture, Storage and Import of Hazardous Chemical Rules 1989 treat a modification likely to cover major accident hazards as a new activity (rule 6) and need a further safety report at least 90 days before a material modification (rule 11), which is the central constraint on a derogation there.
$ python3 -m process_safety legal-clauses --region India --topic change
IN-FA-41A [India; change; grade A] The Factories Act, 1948, s. 41A(1), (2), (5)
IN-MSIHC-6 [India; change; grade B] MSIHC Rules 1989, r. 6(2)(a)(ii)
IN-MSIHC-11 [India; change; grade B] MSIHC Rules 1989, r. 11(1)-(2)
IN-MSIHC-13 [India; change; grade B] MSIHC Rules 1989, r. 13(1)-(3) (condensed)
Not yet read: China, Japan, Brazil, Norway, the Gulf states, and state or provincial law. The entries are paraphrased and are not legal advice.
15. What is new on 6 and 7 November: US units, input templates, a scenario suite, cost and plant tools
These are also on pull request 4, now at version 0.11.0 and still not merged. The command line has 52 commands, 364 automated tests pass, and a new official scenario suite runs 159 scenarios with 787 checks, all passing. Every output below was produced by running the command on 7 November 2026 with illustrative inputs; long JSON is condensed. The rule that runs through all of it is the same as before: no remembered number is typed into the code. Walking speeds, lux targets, unit rates, cost indices and discharge coefficients are inputs, not defaults.
US-customary units, and why gauge and absolute pressure will not convert
Put --units us before any command and type every number in US units: psig, °F, ft, in, lb/h, gpm, Btu/lb. Each is converted to the command’s working unit before the range check, and the result gains US sibling keys next to the SI ones. Every conversion factor is a legal definition (the inch, the pound, standard gravity, the 231 in³ gallon, the International Table Btu), not a remembered number.
$ python3 -m process_safety --units us relief-gas --W 22000 --T 140 --set-g 250 --M 44.1 --k 1.13 --Z 0.85
"required_area_mm2": 518.3,
"required_area_in2": 0.803,
"orifice": "J", "regime": "critical" (condensed)
That is 22,000 lb/h of propane-like vapour at 140 °F and a 250 psig set pressure. Two deliberate refusals protect against the commonest unit mistakes in relief work. A gauge pressure will not convert to an absolute one unless you say so, because the difference is the atmosphere:
$ python3 -m process_safety convert 250 psig psia
error: cannot convert psig (pressure_gauge) to psia (pressure_abs)
$ python3 -m process_safety convert 250 psig psia --across-atmosphere
"result": 264.70
Temperature rises are a separate dimension (dK, dF), so they cannot be pushed through the °F offset by mistake, and standard volumes (scf, Nm³) are not converted at all, because sources use different reference temperatures: give a mass flow instead. docs/UNITS.md lists the ten differences that cause mistakes.
Input templates: fill in a file instead of typing flags
template writes a fill-in JSON (or CSV) for any command, in SI or US units, with each argument’s unit, whether it is required and its valid range. run executes the filled file, and the file’s own units field decides how its numbers are read.
$ python3 -m process_safety template relief-gas --system us > relief_us.json
... fill W, T, set_g, M, k, Z ...
$ python3 -m process_safety run relief_us.json
"required_area_in2": 0.803, "orifice": "J" (same answer as the flags above)
The templates are generated from the command definitions themselves and a test keeps them in step, so a new argument appears in its template the moment it is added.
Two-phase relief from real fluid data
twophase sizes flashing relief by the omega method, and --fluid now reads saturated-liquid properties from a bundled table of 18 fluids at 14 pressures generated with CoolProp. fluid-data shows what is in it.
$ python3 -m process_safety twophase --P0 1500 --fluid propane
"G_kg_m2_s": 9025, "omega": 5.38, "regime": "choked",
"G_hem_reference_kg_m2_s": 9018
"note": "homogeneous equilibrium; Kb/Kc not applied; subcooled and reactive (DIERS) cases need other methods"
The omega flux for saturated propane at 1,500 kPa absolute is within 0.1% of a direct homogeneous-equilibrium integration; across all 252 rows of the table the two agree within 2.2%. There is no default discharge coefficient for two-phase service: to get an area you must give --Kd from your valve data, alongside the relief rate --W. Near the critical point the single-point omega degrades, and the command now warns above half the critical pressure.
Flame radiation by view factor
flame-flux integrates the view factor from a target to a flat, vertical rectangular flame face and multiplies by the surface emissive power you supply.
$ python3 -m process_safety flame-flux --width 10 --height 15 --distance 25 --sep 60
"view_factor": 0.061, "incident_kW_m2": 3.66
A 10 m by 15 m flame face at 60 kW/m², seen from 25 m, delivers about 3.7 kW/m². The toolkit’s own use cases found that its point-source pool-fire distances and this solid-flame method disagree by about four times in the far field, because they imply different radiant fractions. That disagreement is documented, not hidden: use both and say which you relied on.
Escape time and lighting
egress compares the required safe escape time (detection, pre-movement, then travel or queuing at the narrowest exit, whichever is longer) with the available time from your fire or toxic study. illumination applies the lumen method.
$ python3 -m process_safety egress --distance 120 --speed 1.0 --people 40 --width 1.2 \
--specific-flow 1.3 --detect-s 60 --premove-s 90 --aset-s 420
"governing": "travel distance", "rset_s": 270, "margin_s": 150, "escape_before_untenable": true
$ python3 -m process_safety illumination --area 600 --flux 9000 --uf 0.55 --mf 0.8 --target 200
"n_luminaires": 31, "achieved_lux": 204.6
Walking speed, flow per metre of exit, detection and response times, utilisation and maintenance factors and the lux target are all yours to supply. They depend on the occupants and on the standard the site follows, so the toolkit does not guess them.
From recommendations to money: shutdown, cost and LNG capex
Four new studies follow a safety recommendation through to cost and schedule. Each takes an input JSON and ships a worked example (tool example <name> copies it), and every rate, margin and cost index in the examples is a labelled placeholder: the toolkit ships no cost data.
- Shutdown risk (
tool shutdown): schedule and cost risk for a turnaround by Monte Carlo on a critical-path network, with the opportunity cost of lost operating days. Worked example: a 25-day base plan comes out at 31.5 days at P50 and 35.6 days at P80. A 500-run sample was not stable enough, so the tool ran 5,753 runs; the biggest driver is activity A6. - Recommendation cost (
tool recs): the cost of implementing study recommendations by discipline, with contingency, the effect on the shutdown and an ALARP cost-benefit test. Worked example: six recommendations, capex 616 at P50 and 656 at P80 (in cost units); the independent high-level shutdown on the feed drum passes the ALARP test; the shutdown items add about 0.1 day at P80. - Design workflow (
tool workflow): relief screening, resizing, a bill of quantities, capex, opex and ALARP chained in one run. Worked example: the V-101 fire case needs 664 mm² against 506 mm² installed, so the PSV is resized to a J orifice, and the package passes ALARP (cost-benefit ratio 2.5 against a disproportion factor of 3). - LNG capex (
tool lngcost): concept-stage liquefaction capex from public analogs (24 plants used, 2 excluded). Worked example: an illustrative 5 MTPA greenfield train comes out at about $11.1 billion at P50, or $2.2 billion per MTPA. A reference notebook’s unsourced shortcut gives $5.9 billion, below every analog.
The LNG figure is an AACE Class 5 screening number, not a budget. The cost index and location factors are the largest judgements in it, so change them and look at the sensitivity. An optional script, scripts/openpytea_bridge.py, turns equipment you have sized into purchased and installed cost using the open OpenPyTEA correlations, and flags sizes outside a correlation’s range, which OpenPyTEA itself costs without warning. The package stays standard-library only; the bridge sits outside it.
Reading a plant: heat and mass balance, P&ID registers and the PHA
tool plant reads stream tables, equipment and instrument registers (as CSV or Proteus XML) and a PHA register, then runs six scenario types with the existing models and checks the registers against seven P&ID rules. Where an input is missing it reports cannot_assess and names the input, instead of guessing. In the worked example it finds:
- a blocked outlet on V-101 that needs 4,398 mm² of relief area (a Q orifice) against 830 mm² installed;
- depressuring V-101 to atmosphere could chill the gas to about −105 °C against a minimum design metal temperature of −20 °C;
- drum V-102 has no relief device in the register;
- tank T-201’s PSV vents propane and butane to atmosphere.
Each finding is tied to a recommendation type, and gaps that the PHA register does not already cover are listed separately.
Your own documents, incidents and sources
requirements pulls the shall, should and must statements out of standards and specifications you hold (text, Word, or PDF via pdftotext), classifies them and compares them with a PHA register. Because those documents are usually someone else’s copyright, it prints counts unless you ask for the statements, writes only to a file you name, and refuses to write inside a git repository unless the path is ignored. incidents searches 17 U.S. Chemical Safety Board investigations mapped to the toolkit’s modules, and literature searches an index of 93 sources, each marked with whether its content was actually read.
$ python3 -m process_safety incidents --module overfill
2005-03-23 BP America Texas City refinery explosion (Texas City, TX, 15 killed)
2009-10-23 Caribbean Petroleum (CAPECO) refinery tank explosion and fire (Bayamon, PR)
2022-09-20 BP-Husky Oregon (Toledo) refinery chemical release and fire (Oregon, OH, 2 killed)
(condensed: each entry also gives the lesson and the CSB link)
The scenario suite: how the toolkit checks itself
scripts/run_scenarios.py runs 159 scenarios covering 72 of the 77 topics in the coverage map. Each scenario carries up to five kinds of check:
- Bounds: a physical or logical limit holds.
- Oracles: an independent recomputation from first principles agrees.
- Metamorphic relations: doubling the flow doubles the relief area, for example.
- SI against US: the same case typed in both unit systems gives the same answer.
- Regression snapshot: current values are unchanged.
The report says plainly that the snapshot only detects drift and is not evidence of correctness. The five topics without scenarios are the ones still marked not implemented. Writing the suite found a real trap: blowdown --hole-d is in metres, so a hole typed as “25” meaning millimetres was accepted as 25 m and gave a 0.4 ms blowdown. The help text now says metres.
16. Worked example: an LPG terminal, start to finish
An LPG storage and loading terminal is a good test of the toolkit: pressurised propane bullets, transfer pumps, a road-tanker loading bay, a flare, and a control room and village close enough to matter. This section walks that asset through the commands above with the actual outputs, asking the questions a process-safety workshop asks first: how big is the fire relief load, is the overfill trip good enough, where does the risk come from, and how far must emergency planning reach. The individual-risk, F-N and cost-benefit results of the same study are read in section 8.
- How much vapour must the bullet relieve in a pool fire?
relief-fire --D 3.5 --L 14 --level 2.5 --latent 330
Wetted area 119 m², heat input 2,174 kW, relief rate 23,720 kg/h. The geometry and the 330 kJ/kg latent heat are inputs. - What pressure and fill limit does propane set?
lpg propane --fill-C 15 --max-C 50
Vapour pressure 1,616 kPag at 50 °C, liquid density 506 kg/m³ at 15 °C, a thermodynamic fill ceiling of 88%. Codes set the practical limit. - Is the overfill trip good enough?
tool sif sif.json
Target SIL 2. The PFDavg of 6.6e-3 (risk reduction 151) meets SIL 2 by probability, but a single type-A inlet shutdown valve with 40% safe-failure fraction caps the architecture at SIL 1. It fails. - Which barriers carry the risk?
tool bowtie bowtie.json
Top event 1.7e-4 per year. Given a loss of containment: 69% unignited, 21% vapour-cloud explosion or flash fire, 9% jet fire, 1% BLEVE. The independent high-high level trip is the safety-critical element. - Where does individual risk come from?
qra run study.json
Highest location risk 0.012 per year at (120, 40) m; population risk (PLL) 0.051 per year. - How exposed are the buildings?
(same run as above)
Occupant risk per year: control room 5.0e-4, admin building 9.7e-5, loading-bay shelter 6.1e-3. - How far must emergency planning reach?
(same run as above)
Credible case (4-inch line rupture, jet and pool fire): 58, 102 and 179 m to 37.5, 12.5 and 4 kW/m². Worst case (bullet fireball): 296, 551 and 996 m. Vapour-cloud explosion: 621 m to 0.3 bar, 786 m to 0.1 bar.
One reading is worth pausing on. The overfill function passes on probability and fails on architecture, so the fix is a redundant or higher-integrity final element, not a shorter proof-test interval. That comes from a check the toolkit runs, not from judgement added afterwards.
overrides hook. The toolkit then still does the frequency, individual-risk, ALARP and mitigation bookkeeping.The same questions in real projects
iFluids Engineering, a Chennai consultancy, publishes case studies and an all-projects list. Several entries are the same questions the terminal raised. The list below matches each to the toolkit module that screens it, with a real output on illustrative inputs. No result, input or design from any listed project is shown or implied: only the client, title and scope as the iFluids pages state them, and the toolkit is not iFluids’ method.
- GSPL: integrated QRA for LNG transport routes and regasification
Question screened: Impoundment, boil-off and regas duty at a terminal (lng,qra)
Toolkit output (illustrative inputs): For a 160,000 m³ tank, 4,000 kW heat ingress, 50 kg/s regas and 5 K seawater rise: impoundment 176,000 m³, boil-off 7.8 kg/s (1.0% a day), regas duty 44.4 MW, seawater 2.17 m³/s
Where the toolkit stops: Impoundment follows the US rule (49 CFR 193.2181). Siting models and road-transport route risk are not implemented - Kuwait Oil Company thermal testing facility; Jafurah downstream pipeline Phase II: fire and gas mapping
Question screened: Detector coverage of a hazard zone (fg_mapping)
Toolkit output (illustrative inputs): On the toolkit’s example bullet area, two-detector coverage as drawn is 1.8% against a 90% target. The optimiser adds 18 gas detectors and reaches 68.7%, still short
Where the toolkit stops: 2D geographic coverage only. 3D mapping and scenario-based coverage are not implemented - CPCL Manali refinery: PSM gap assessment against the 20 CCPS RBPS elements
Question screened: Scoring and tracking a management system (psm)
Toolkit output (illustrative inputs): Gap scoring (0 to 4 per element) and weakest-element ranking for the 14 OSHA PSM elements and AIGA 99; for dates, a PHA last done 15 Mar 2021 is overdue by 235 days on 5 Nov 2026
Where the toolkit stops: The 20-element RBPS scoring itself is not implemented, only the element list and a crosswalk - NGL pipeline surge analysis (14-inch, about 300 km, in the projects list)
Question screened: Surge pressure on a fast valve closure (hydraulics.surge_screen)
Toolkit output (illustrative inputs): Assuming density 560 kg/m³, bulk modulus 1 GPa and a 9.5 mm wall: wave speed 1,228 m/s, critical time 489 s, a 1.5 m/s stop in 30 s gives 1,032 kPa (Joukowsky)
Where the toolkit stops: A screen, not a transient simulator: no pump trips, column separation or full pipeline model - IOCL Mathura tank conversion (20,000 KL and 5,000 KL tanks)
Question screened: Fire venting of an atmospheric tank (tank_venting)
Toolkit output (illustrative inputs): A bare vertical tank, 40 m by 16 m (about 20,000 m³): wetted area 1,149 m², emergency venting 19,897 Nm³/h, of which 18,397 Nm³/h is beyond a 1,500 Nm³/h normal capacity
Where the toolkit stops: API 2000 5th edition (1998) only; the 7th edition and vent hardware sizing are not implemented - Essar re-HAZOP of P&IDs; Oil India HAZOP and QRA; Qatar Petroleum bow-tie development
Question screened: Registers, revalidation and barrier ranking (hazop,pha,bowtie,qra)
Toolkit output (illustrative inputs): The terminal study above: HAZOP worksheets, barrier importance and the safety-critical element, QRA individual and societal risk
Where the toolkit stops: The study itself is a team exercise; the tools keep the records - HAZID for mining standpipe infrastructure (Pilbara)
Question screened: Hazard identification checklist (qra.hazid)
Toolkit output (illustrative inputs): A HAZID register by section and a loss-of-containment list
Where the toolkit stops: Generic prompts, not standard text; not an oil and gas asset
What this terminal needs next
- Replace the placeholders. Pump and equipment frequencies from a source such as the OGP 434-1 data or the UK HSE FRED rows, local weather and wind data, and the actual population around the site.
- Add a dense-gas footprint. Run the propane releases in a validated tool and feed the footprints through
overrides. - Choose the criteria deliberately. This run used the UK R2P2 preset; no single Indian tolerable-risk criterion exists in the public documents the toolkit read, so an Indian site should supply a custom one.
- Do what the toolkit lists as not implemented. Layout and separation distances, hazardous-area classification extents, and fire-water design to the governing standards remain manual work.
- Hold the workshop. The HAZID and HAZOP registers are a starting point; the studies are a team exercise.
The same flow applies to other oil and gas assets, a gas processing plant, a refinery unit or an offshore platform, with different modules in play (relief and flare systems, hydrocarbon fire, explosion). The terminal here is only the asset the toolkit ships a worked example for.
Sources: the toolkit and its documentation, github.com/herrrickshaw/process-safety-design-toolkit; the browser demo, process-safety-studio-demo.lovable.app (captured outputs, not live calculations) (open pull requests 1 and 2 hold the risk-study, study-tool and data-centre additions; pull request 3 holds version 0.10; pull request 4 holds the derogation, EU, insurance and legal-clause additions and the 6 and 7 November work in section 15). Every output above comes from running the command on 5 November 2026 (section 14: 6 November 2026; section 15: 7 November 2026, at commit b2561ae) with illustrative inputs; results are screening arithmetic and modelled, not measured, and are not a safety case. Section 16: outputs from running the commands on 5 November 2026 on the toolkit’s hypothetical LPG terminal; client names and project scopes as stated on ifluids.com/case-studies and ifluids.com/all-projects, read on 5 November 2026 (the projects page was only partly read).
- v1.4.0 — 10 November 2026 — added section 16, the LPG-terminal worked example (relief, propane limits, the overfill trip, bow-tie, location and building risk, emergency distances, the dense-gas limit and matching consultancy projects), merged in from a separate post that has been retired.
- v1.3.0 — 7 November 2026 — added section 15: US-customary units and the gauge/absolute pressure guard, input templates, two-phase relief from bundled fluid data, view-factor flame radiation, escape-time and lighting checks, the shutdown, recommendation-cost, design-workflow and LNG-capex studies, plant and P&ID ingestion, the requirements extractor, incident and literature search, and the 159-scenario self-check; and a link to the Process Safety Studio browser demo near the top. The toolkit is now at version 0.11.0 with 52 commands and 364 tests; counts quoted in earlier sections and the summary tiles describe the versions those sections were written for.
- v1.2.0 — 6 November 2026 — added section 14: derogations and compliance tiers, the TA1/TA2/TA3 approval matrix, PESTLE consequence rating, EU (Seveso III) impact, actuarial insurance impact and a 55-clause legal index, with a demo video. Sections 1 to 13 are unchanged, so counts quoted there (35 commands, 173 and 192 tests, 124 cross-checks) describe the earlier versions.
- v1.1.0 — 5 November 2026 — added section 13: version 0.10 (input ranges, glossary, restructured command line, 124 cross-checks) with a demo video. The earlier sections describe version 0.9 and are unchanged.
- v1.0.0 — 5 November 2026 — first published (complete walkthrough).
About this article: Researched, written and edited by Umashankar Triplicane Dwarakanathan, with AI research assistance; every figure is meant to trace to the primary source cited. See the Editorial Policy for how sourcing, AI use and corrections work.