0037. Several power trays per rack, by voltage class and fill¶
- Status: Accepted
- Date: 2026-10-30
Context¶
cheme layout build ran one power tray along each rack, at lane_fraction of the rack width
left of its centreline, as wide as its cables needed up to the largest of widths_mm. In the
ammonia-1 run (process-library#304, cheme 1.0.1) the 10 kV cables of the compressors K-101,
K-501 and K-701 filled the main-rack power tray to 53-54 % against a 30 % limit. The trays on
PR-10, PR-7, the switchgear room leg and two links were also over the limit. The tray-fill
finding said to run a second tray, but electrical/tray-rules.yaml could not declare one: a
tiers rule only sets a rack's tray elevation. The only way out was to accept the finding, and
the detail gate electrical failed (core#71).
Options considered: a count of power trays per rack; one entry per tray with its voltage class; stacking the trays on tiers of their own instead of side by side; a global rule that splits a tray whenever it overflows. Side by side keeps the generated tray-tier steel (one beam across the rack at each bent) as it is. A per-rack declaration keeps the project in control of what stands on its racks. Voltage classes matter in practice: cables above and below about 1 kV are commonly kept in separate trays. The US National Electrical Code (NFPA 70, 392.20(B)) allows them in one tray only with a solid fixed barrier between them or with the higher-voltage cables of type MC (see EC&M, "Mixing cables over and under 600V in cable tray", https://www.ecmweb.com/national-electrical-code/article/20901257/mixing-cables-over-and-under-600v-in-cable-tray; the 2016 article uses the 600 V limit of that edition).
Decision¶
- The
trayskind (electrical/tray-rules.yaml) gainsrules.power_trays: [{rack, trays}]:traysis a count (1 .. 9, each tray takes any cable) or one voltage class per tray (hv,lv,any).rules.lv_max_v(default 1000 V, the low-voltage limit of IEC 60038) splits the classes: a cable rated above it ishv. A rack not listed has one power tray, as before. - A rack's power trays stand side by side on its tray tier, centred on the power lane, the
largest width plus
spacing_mapart centre to centre. - The build gives each power cable that runs on such a rack one of its trays for its whole way
along that rack, deterministically. It takes the
hvcables first, then the larger cross-section first, then the tag. Each cable goes to a tray of its class, else ananytray, else any other tray. Among those it takes the tray whose fullest piece along the cable's span stays underfill_max_powerat the largest width, then the emptiest, then the first. - Each tray's trunk is cut and sized on its own and is checked for fill and separation like
every tray. Ids:
PT-<rack>-<letter>-<k>(A, B, ... from the centreline out). Room legs and links split with the trays at their ends (PT-<room>-<letter>,PT-<rack>-<rack>-<letters>). A branch starts at its cable's tray. A rack's only tray keeps the old ids. - Model trays of a classed tray record
voltage: hv|lv(optional).cabling.rulesrecordspower_traysandlv_max_vonly when power trays are declared. The cable schedule lists each cable's trays, as before. - New model rule
cheme.layout-tray-voltage(warning): a classed power tray carrying a cable of the other class. The gate requirementtraysfails on it, as ontray-fillandtray-separation.cheme.layout-tray-rackalso coverspower_trays: an unknown or repeated rack is an error, and trays that do not fit on the power half of the rack at the largest width are a warning, on the entry's line. Thetray-fillhint on a rack's power trunk names the number of power trays the rack needs and thepower_traysentry to write. - Without
power_traysthe build is byte-identical to before.
Consequences¶
- Positive: a tray-fill finding on a rack can be fixed in the input, not only accepted. On the
ammonia-1 copy, two power trays on PR-1, PR-10 and PR-7 remove all eight
tray-fillfindings, and gateelectricalpasses. - Positive: HV and LV cables can be kept apart by declaring classed trays. A cable that ends up in a tray of the other class is a finding, not a silent mix.
- Negative: tray ids on a rack with several trays change (letters). Acceptances keyed by the old ids no longer match and need to be reviewed.
- Known limitations: the trays are side by side on one tier, not stacked. The pitch follows the
largest width, not the actual one. The share-out balances cross-section, not the
single-layer width rule that some codes apply to large cables. The share-out happens per
rack, so a cable may change tray position where two racks meet (the link joins the two).
HV-to-LV spacing beyond
spacing_mis not checked.
Evidence¶
- core#71; files:
src/chemeascode/domains/spatial/schemas.py(PowerTrays,TrayRuleSet.power_trays,lv_max_v,ModelTray.voltage),src/chemeascode/domains/spatial/trays.py(Cabling._assign,_plan,tray_findings,_fill_hint),src/chemeascode/domains/spatial/layout_validate.py(power_trays),src/chemeascode/domains/spatial/gates.py(TRAY_RULES),docs/framework/electrical.md, skillelectrical-cabling,tests/test_electrical_trays.py.