mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
SAP 10.2 specification (14-03-2025) §2.6.4 (PDF p.16):
"In the case of decentralised MEV the specific fan power is provided
for each fan and an average value is calculated for the purposes of
the SAP calculations. There are two types of fan, one for kitchens
and one for other wet rooms, and three types of fan location (in
room with ducting, in duct, or through wall with no duct). [...]
The average SFP, including adjustments for the in-use factors, is
given by:
SFPav = Σ(SFP_j × FR_j × IUF_j) / Σ(FR_j) (1)
where the summation is over all the fans, j represents each
individual fan, FR is the flow rate which is 13 l/s for kitchens
and 8 l/s for all other wet rooms, and IUF is the applicable
in-use factor."
And SAP 10.2 §5 Table 4f line (230a):
"Annual electricity for mechanical ventilation fans (kWh/year) =
IUF × SFP × 1.22 × V"
This slice lands the two pure-function cascade primitives:
mev_sfp_av(fan_entries) -> float # equation (1)
mev_decentralised_kwh_per_yr(*, sfp_av, V) -> float # (230a)
`MevFanEntry` carries the per-fan resolved (SFP_w_per_l_per_s, flow_l_
per_s, IUF) triple. Callers (PCDB Table 322 + Table 329 + cert
lodgement of duct type) compose the entries upstream; the cascade
helper does no PCDB resolution itself.
Cert 000565 worksheet line (230a) pinned at 1e-4:
Σ FR = 92.0 l/s (matches worksheet "total flow")
Σ SFP×FR×IUF = 11.7205 W (matches worksheet "total watage")
SFPav = 11.7205 / 92.0 = 0.1274 W/(l/s) ✓ vs ws 0.1274
(230a) = 0.1274 × 1.22 × 820.4385 = 127.5159 ✓ vs ws 127.5159
Pure-function helpers; no cascade integration yet. Next slice
S0380.101 wires HP category mapper; S0380.102 wires cert→inputs
to invoke the cascade. Pyright net-zero per touched file.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
"""SAP 10.2 §2.6.4 — Mechanical Extract Ventilation (MEV) electricity.
|
||
|
||
This module implements the §2.6.4 "Specific fan power" cascade for
|
||
decentralised MEV systems plus the §5 Table 4f line (230a) annual
|
||
electricity formula. Centralised MEV / MVHR / balanced systems share
|
||
the same (230a) shape but pick their per-system SFP differently —
|
||
deferred until a fixture exercises them.
|
||
|
||
Spec references (SAP 10.2 14-03-2025):
|
||
- §2.6.4 page 16 — equation (1) average SFP for decentralised MEV
|
||
- Table 4f page 174 — line (230a) `IUF × SFP × 1.22 × V` annual kWh
|
||
- Table 4g page 176 — default SFP (0.8 W/(l/s)) for unknown PCDB
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from typing import Final
|
||
|
||
|
||
# SAP 10.2 §5 Table 4f line (230a): annual kWh = SFP × 1.22 × V.
|
||
# The "× 1.22" coefficient absorbs continuous-run hours × 0.5 ach
|
||
# (MEV throughput per §2.6.5) × air-density-and-unit conversion.
|
||
_MEV_KWH_COEFF: Final[float] = 1.22
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class MevFanEntry:
|
||
"""One fan in a decentralised MEV installation, with the IUF
|
||
already resolved per the system's lodged ducting type.
|
||
|
||
`sfp_w_per_l_per_s` is the PCDB-lodged Specific Fan Power for the
|
||
fan's (location × wet-room-type) configuration; `flow_rate_l_per_s`
|
||
is the SAP standard flow per wet-room-type (13 l/s kitchens, 8 l/s
|
||
other wet rooms — see SAP 10.2 §2.6.4); `iuf` is the in-use factor
|
||
from PCDB Table 329 for the fan's location (in-room with ducting →
|
||
flexible/rigid IUF; through-wall → no-duct IUF).
|
||
"""
|
||
|
||
sfp_w_per_l_per_s: float
|
||
flow_rate_l_per_s: float
|
||
iuf: float
|
||
|
||
|
||
def mev_sfp_av(fan_entries: tuple[MevFanEntry, ...]) -> float:
|
||
"""SAP 10.2 §2.6.4 equation (1): average SFP for a decentralised
|
||
MEV system.
|
||
|
||
SFPav = Σ(SFP_j × FR_j × IUF_j) / Σ(FR_j)
|
||
|
||
The summation is over every fan in the installation (kitchen +
|
||
each wet room) — each fan carries its own (SFP, FR, IUF) per the
|
||
spec's `MevFanEntry` resolution.
|
||
|
||
Returns 0.0 when no fans are lodged (empty installation — caller
|
||
should not invoke `mev_decentralised_kwh_per_yr` in that case).
|
||
"""
|
||
if not fan_entries:
|
||
return 0.0
|
||
weighted_sum = sum(
|
||
entry.sfp_w_per_l_per_s * entry.flow_rate_l_per_s * entry.iuf
|
||
for entry in fan_entries
|
||
)
|
||
flow_sum = sum(entry.flow_rate_l_per_s for entry in fan_entries)
|
||
if flow_sum == 0.0:
|
||
return 0.0
|
||
return weighted_sum / flow_sum
|
||
|
||
|
||
def mev_decentralised_kwh_per_yr(
|
||
*,
|
||
sfp_av_w_per_l_per_s: float,
|
||
dwelling_volume_m3: float,
|
||
) -> float:
|
||
"""SAP 10.2 §5 Table 4f line (230a) annual electricity for the
|
||
mechanical ventilation fans of a decentralised MEV system:
|
||
|
||
E_fans_kwh = SFPav × 1.22 × V
|
||
|
||
`sfp_av_w_per_l_per_s` is the IUF-adjusted average SFP from
|
||
`mev_sfp_av` (i.e. the IUFs are already folded in via the
|
||
equation (1) numerator). `dwelling_volume_m3` is worksheet line
|
||
(5) — the sum of (3a)+(3b)+...+(3n) across every storey of every
|
||
building part.
|
||
"""
|
||
return sfp_av_w_per_l_per_s * _MEV_KWH_COEFF * dwelling_volume_m3
|