mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice S0380.55: cascade WHC 914 → Main 2 water-heating efficiency routing
Closes the second half of the cert 000565 Main 2 work. After Slice
S0380.54 lodged Main 2 on the EpcPropertyData, the water-heating
cascade still derived efficiency from Main 1 (the heat pump) instead
of Main 2 (the gas combi that actually services DHW).
Per the Elmhurst RdSAP convention, `Water Heating SapCode 914` =
"from second main system" — DHW is generated by Main 2, not Main 1.
The §4 / Appendix D2.1 summer-efficiency lookup must therefore key
off Main 2's PCDB Table 105 record (cert 000565: PCDB 15100 Vaillant
Ecotec plus 415, summer η = 88%) rather than Main 1's HP COP.
Implementation:
- New `_water_heating_main(epc)` helper — returns Main 2 when WHC
is in `_WATER_FROM_SECOND_MAIN_CODES = {914}` AND a second main is
lodged; otherwise returns Main 1 (matches prior behaviour for
single-main certs + WHC 901/902 "from main system")
- The water-eff branch at the §4 cascade now reads `water_pcdb_main
= gas_oil_boiler_record(water_main.main_heating_index_number)`
+ `_water_efficiency_with_category_inherit(water_main.sap_main_
heating_code, water_main.main_heating_category, _main_fuel_code(
water_main))` — same logic as before but parametrised by the
water-heating main rather than hard-coded to Main 1
Cert 000565 cascade impact on hot_water_kwh_per_yr pin:
- Before: actual 1,844.66 kWh/yr (= HW heat / HP COP 1.70 — wrong)
Δ −1,910.36 vs U985-0001-000565.pdf expected 3,755.03
After Slice S0380.54 (Main 2 lodged but cascade still using Main 1):
actual 3,919.91 kWh/yr, Δ +164.88 (regression from the no-cascade
baseline because Main 2 PCDB was lodged but water_eff still came
from Main 1's HP-vs-default fallthrough)
- After this slice: actual 3,969.53 kWh/yr (= HW heat / 0.88)
Δ +214.50 — 89% reduction vs the original Main-1 WHC 914 routing,
remaining gap is fine-grained (FGHRS / solar HW / Table 3a no-keep-
hot territory — separate slice)
For single-main certs (the 14 existing Summary fixtures + 8 ASHP
cohort certs): `_water_heating_main` returns Main 1, identical to
the prior `main` reference. Cohort regression check: 472 pass + 10
expected 000565 fails — no broader regression.
Spec source: SAP 10.2 §4 water-heating cascade + Appendix D2.1 (D1
equation) summer-efficiency override; Elmhurst RdSAP water-heating
code 914 ("from second main system").
Pyright net-zero on cert_to_inputs.py (34 errors before, 34 after).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
6d82f8842d
commit
b8ea20988f
1 changed files with 47 additions and 5 deletions
|
|
@ -556,6 +556,38 @@ def _first_main_heating(epc: EpcPropertyData) -> Optional[MainHeatingDetail]:
|
|||
return details[0] if details else None
|
||||
|
||||
|
||||
# Elmhurst RdSAP water-heating codes that route DHW to a non-Main-1
|
||||
# system. RdSAP code 914 = "from second main system" — DHW is
|
||||
# serviced by Main 2 (typically a gas combi providing DHW only) while
|
||||
# Main 1 handles space heat (e.g. cert 000565: HP Main 1 + gas combi
|
||||
# Main 2 + WHC 914). The water-heating cascade reads Main 2's PCDB
|
||||
# record / SAP code / fuel when this routing applies.
|
||||
_WATER_FROM_SECOND_MAIN_CODES: Final[frozenset[int]] = frozenset({914})
|
||||
|
||||
|
||||
def _water_heating_main(
|
||||
epc: EpcPropertyData,
|
||||
) -> Optional[MainHeatingDetail]:
|
||||
"""The `MainHeatingDetail` that services DHW per the cert's
|
||||
`water_heating_code` routing. WHC 914 ("from second main system")
|
||||
returns Main 2 when present; otherwise returns Main 1.
|
||||
|
||||
The water-heating cascade (Table 4a / Appendix D2.1 summer
|
||||
efficiency, water-heating fuel cost / CO2 / PE) keys off this
|
||||
helper rather than `_first_main_heating` so the right system's
|
||||
efficiency and fuel propagate to DHW.
|
||||
"""
|
||||
details = epc.sap_heating.main_heating_details if epc.sap_heating else []
|
||||
if not details:
|
||||
return None
|
||||
if (
|
||||
epc.sap_heating.water_heating_code in _WATER_FROM_SECOND_MAIN_CODES
|
||||
and len(details) >= 2
|
||||
):
|
||||
return details[1]
|
||||
return details[0]
|
||||
|
||||
|
||||
def _main_heating_efficiency(epc: EpcPropertyData) -> float:
|
||||
"""SAP 10.2 (206) main system 1 efficiency as a 0..1 fraction.
|
||||
|
||||
|
|
@ -2877,14 +2909,24 @@ def cert_to_inputs(
|
|||
# `main_fuel_kwh = q_useful × DLF = q_generated`, matching the spec's
|
||||
# "unit prices per kWh of heat generated" convention.
|
||||
eff = _main_heating_efficiency(epc)
|
||||
if pcdb_main is not None and pcdb_main.summer_efficiency_pct is not None:
|
||||
water_eff = pcdb_main.summer_efficiency_pct / 100.0
|
||||
# Water-heating efficiency reads from the main that ACTUALLY services
|
||||
# DHW per the cert's `water_heating_code` routing (Elmhurst WHC 914
|
||||
# = "from second main system" → Main 2). For single-main certs and
|
||||
# WHC 901/902 this resolves to Main 1, matching the prior behaviour.
|
||||
water_main = _water_heating_main(epc)
|
||||
water_pcdb_main = (
|
||||
gas_oil_boiler_record(water_main.main_heating_index_number)
|
||||
if water_main is not None and water_main.main_heating_index_number is not None
|
||||
else None
|
||||
)
|
||||
if water_pcdb_main is not None and water_pcdb_main.summer_efficiency_pct is not None:
|
||||
water_eff = water_pcdb_main.summer_efficiency_pct / 100.0
|
||||
else:
|
||||
water_eff = _water_efficiency_with_category_inherit(
|
||||
water_heating_code=epc.sap_heating.water_heating_code,
|
||||
main_code=main_code,
|
||||
main_category=main_category,
|
||||
main_fuel=main_fuel,
|
||||
main_code=water_main.sap_main_heating_code if water_main is not None else None,
|
||||
main_category=water_main.main_heating_category if water_main is not None else None,
|
||||
main_fuel=_main_fuel_code(water_main),
|
||||
)
|
||||
# SAP 10.2 Appendix N3.6 + N3.7(a) — when an HP cert lodges a PCDB
|
||||
# Table 362 record, the cascade replaces the Table 4a defaults with
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue