diff --git a/domain/sap10_calculator/rdsap/cert_to_inputs.py b/domain/sap10_calculator/rdsap/cert_to_inputs.py index 69b46f15..cb33c153 100644 --- a/domain/sap10_calculator/rdsap/cert_to_inputs.py +++ b/domain/sap10_calculator/rdsap/cert_to_inputs.py @@ -206,6 +206,58 @@ _PUMPS_FANS_KWH_BY_MAIN_CATEGORY: Final[dict[int, float]] = { # entry HP certs fell through to the 130 kWh/yr DEFAULT # and over-billed £17/yr at electricity rate. } + +# SAP 10.2 Table 4f (page 174) — flue fan kWh for a gas-fired boiler +# with fan-assisted flue (row "Gas boiler – flue fan"). Liquid-fuel +# (oil) boilers use 100; gas-fired heat pumps and warm-air also 45. +_TABLE_4F_GAS_FLUE_FAN_KWH: Final[float] = 45.0 + +# SAP 10.2 Table 4f row "Solar thermal system pump, electrically +# powered" — formula `[25 + 5×H1] × 2`. H1 is the solar collector +# aperture area in m². For cert 000565 the lodged 3 m² flat-panel +# array gives 2 × (25 + 15) = 80 kWh; without aperture lodging the +# cohort fall-through uses a 3 m² default. +_TABLE_4F_SOLAR_HW_PUMP_DEFAULT_H1_M2: Final[float] = 3.0 + + +def _table_4f_additive_components(epc: EpcPropertyData) -> float: + """Sum the SAP 10.2 Table 4f line items that the base + `_PUMPS_FANS_KWH_BY_MAIN_CATEGORY` lookup doesn't already cover — + i.e. components driven by per-cert lodgements rather than Main 1's + heating category alone. + + Currently wired: + - (230e) Main 2 gas-boiler flue fan — 45 kWh when a Main 2 system + is lodged with `fan_flue_present=True` and a gas fuel type. + Cert 000565 (Main 1 HP + Main 2 gas combi via WHC 914) is the + first fixture exercising this. + - (230g) Solar HW pump — `[25 + 5×H1] × 2` per Table 4f. H1 + defaults to 3 m² aperture (cert 000565 lodging) when the + schema doesn't carry the lodged value. TODO: parse the + Elmhurst §16 aperture area into the schema. + + Not yet wired: + - (230a) MEV / MVHR — `IUF × SFP × 1.22 × V` per Table 4f + + Table 4g defaults. PCDB MEV / MVHR lookup table is not yet in + the codebase; defer to next slice. + - (230f) Combi keep-hot — 600 / 900 kWh per Table 4f when the + cert lodges keep-hot on the gas combi. + - (230b) Warm-air heating fans + (230c) for warm-air pump. + - (230h) WWHRS pump. + """ + total = 0.0 + details = epc.sap_heating.main_heating_details if epc.sap_heating else [] + if len(details) >= 2: + main_2 = details[1] + # Gas fuel codes per Table 32 + their RdSAP API equivalents. + main_2_fuel_is_gas = main_2.main_fuel_type in {1, 2, 3, 5, 7, 9, 26, 27} + if main_2.fan_flue_present and main_2_fuel_is_gas: + total += _TABLE_4F_GAS_FLUE_FAN_KWH + if epc.solar_water_heating: + total += ( + 25.0 + 5.0 * _TABLE_4F_SOLAR_HW_PUMP_DEFAULT_H1_M2 + ) * 2.0 + return total # SAP10.2 Table 6d note 1: "average or unknown" overshading is the # default for existing dwellings. RdSAP doesn't lodge a per-dwelling # overshading code so §5 always uses AVERAGE → Z_L = 0.83. @@ -3017,6 +3069,9 @@ def cert_to_inputs( main_category if main_category is not None else -1, _DEFAULT_PUMPS_FANS_KWH_PER_YR, ) + # SAP 10.2 Table 4f (p.174) — additive components on top of the + # Main 1 category base. Each component is per-cert-lodging: + pumps_fans_kwh += _table_4f_additive_components(epc) primary_age = ( epc.sap_building_parts[0].construction_age_band if epc.sap_building_parts else None )