mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
S0380.183: community-heating HW bills at heat-network rate (§10b) — closes CH2/CH4 fully
SAP 10.2 §10b: hot water for a community-heating dwelling bills at the
heat-network rate, not the cert-lodged fuel. Elmhurst §15.0 lodges
`water_heating_fuel_type = "Mains gas"` (3.48 p/kWh) as a placeholder on
community certs; the worksheet (342) Water-heating cost = (310) × the
S0380.171 CHP heat-fraction blend — the SAME rate as space heating (340).
Per-line walk of the CH2 block 10b:
(340) space = 11837.83 × 0.037955 = 449.3047 (cascade EXACT)
(342) water = 3854.12 × 0.037955 = 146.2830 (cascade billed
3854.12 × 0.0348 = 134.12 → −£12.16, the whole residual)
(350) lighting + (351) standing → (355) 754.1502.
`_hot_water_fuel_cost_gbp_per_kwh`'s `inherit_main_for_community_heating`
path already routes HW cost through `_fuel_cost_gbp_per_kwh(main)` (the
CHP blend), but its gate `_is_community_heating_hw_from_main` excluded
code 302. S0380.182 wired the 302 CO2/PE credit via
`_heat_network_code_302_effective_factor`, which intercepts the HW
CO2/PE helpers ABOVE this predicate's branch — so extending the
predicate to include 302 now affects ONLY the cost path.
Closures:
CH2 (CHP/Gas) SAP +0.5277→−0.0000, cost −£12.16→−£0.00 — FULLY EXACT
CH4 (CHP/Oil) SAP +0.5277→−0.0000, cost −£12.16→−£0.00 — FULLY EXACT
CH6 (CHP/Coal) SAP −7.49→−8.02, cost +£172.68→+£184.84 — its HW now
also bills the blend, compounding the DLF=1.0 quirk
(cascade DLF=1.45); same separate CH6 DLF front.
Corpus now 39 variants EXACT on all four metrics (CH2/CH4 join). Open:
CH3 CO2/PE (code-304 community-HP COP), CH6 all-metric (DLF=1.0 manual
override the Summary doesn't carry). 2225 pass + 1 skip + 0 fail
(tolerances 1e-4 all metrics); pyright net-zero 32→32.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
035303e9f8
commit
ef668ef7e9
2 changed files with 33 additions and 16 deletions
|
|
@ -716,11 +716,23 @@ _EXPECTATIONS: tuple[_CorpusExpectation, ...] = (
|
|||
# / cost −£12.16 is the heat-network cost/standing residual exposed
|
||||
# by S0380.175 (cost-side, untouched by this CO2/PE slice). CH3
|
||||
# unchanged (code 304 community-HP COP front).
|
||||
#
|
||||
# Slice S0380.183 closed the CH2/CH4 HW cost residual: per SAP 10.2
|
||||
# §10b the community-heating HW bills at the heat-network rate, not
|
||||
# the Elmhurst §15.0 "Mains gas" placeholder. Worksheet (342) =
|
||||
# (310) × the S0380.171 CHP heat-fraction blend (= the same rate as
|
||||
# space heating (340)), not (310) × 3.48 p/kWh gas. Extended
|
||||
# `_is_community_heating_hw_from_main` to include code 302 — the
|
||||
# S0380.182 CO2/PE interception sits above this predicate's branch,
|
||||
# so it now affects only the cost path. CH2 + CH4 are FULLY EXACT
|
||||
# on all four metrics. CH6 SAP −7.49→−8.02 / cost +£172.68→+£184.84
|
||||
# (its HW now also bills the blend, compounding the DLF=1.0 quirk —
|
||||
# same root, still the separate CH6 DLF front).
|
||||
_CorpusExpectation(variant='community heating 1', block='11b', expected_sap_resid=+0.0000, expected_cost_resid_gbp=-0.0000, expected_co2_resid_kg=-0.0000, expected_pe_resid_kwh=+0.0000),
|
||||
_CorpusExpectation(variant='community heating 2', block='11b', expected_sap_resid=+0.5277, expected_cost_resid_gbp=-12.1598, expected_co2_resid_kg=+0.0000, expected_pe_resid_kwh=+0.0000),
|
||||
_CorpusExpectation(variant='community heating 2', block='11b', expected_sap_resid=-0.0000, expected_cost_resid_gbp=-0.0000, expected_co2_resid_kg=+0.0000, expected_pe_resid_kwh=+0.0000),
|
||||
_CorpusExpectation(variant='community heating 3', block='11b', expected_sap_resid=+0.0000, expected_cost_resid_gbp=-0.0000, expected_co2_resid_kg=-75.3228, expected_pe_resid_kwh=-249.3161),
|
||||
_CorpusExpectation(variant='community heating 4', block='11b', expected_sap_resid=+0.5277, expected_cost_resid_gbp=-12.1598, expected_co2_resid_kg=-0.0000, expected_pe_resid_kwh=-0.0000),
|
||||
_CorpusExpectation(variant='community heating 6', block='11b', expected_sap_resid=-7.4942, expected_cost_resid_gbp=+172.6778, expected_co2_resid_kg=+2411.5399, expected_pe_resid_kwh=+5023.4766),
|
||||
_CorpusExpectation(variant='community heating 4', block='11b', expected_sap_resid=-0.0000, expected_cost_resid_gbp=-0.0000, expected_co2_resid_kg=-0.0000, expected_pe_resid_kwh=-0.0000),
|
||||
_CorpusExpectation(variant='community heating 6', block='11b', expected_sap_resid=-8.0219, expected_cost_resid_gbp=+184.8376, expected_co2_resid_kg=+2411.5399, expected_pe_resid_kwh=+5023.4766),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1496,24 +1496,26 @@ def _water_heating_fuel_code(epc: EpcPropertyData) -> Optional[int]:
|
|||
|
||||
def _is_community_heating_hw_from_main(epc: EpcPropertyData) -> bool:
|
||||
"""True iff the cert's WHC routes HW from the main heating system
|
||||
(codes 901 / 902 / 914) AND the main is a single-source heat
|
||||
network with a registered heat-source efficiency
|
||||
(`_HEAT_NETWORK_HEAT_SOURCE_EFFICIENCY` — currently SAP code 301
|
||||
boilers and 304 HP).
|
||||
(codes 901 / 902 / 914) AND the main is a heat network the cascade
|
||||
can cost/emission-rate: a registered single-source heat-source
|
||||
efficiency (`_HEAT_NETWORK_HEAT_SOURCE_EFFICIENCY` — SAP code 301
|
||||
boilers / 304 HP) OR code 302 (CHP and boilers).
|
||||
|
||||
Elmhurst Summary §15.0 lodges `water_heating_fuel_type = "Mains gas"`
|
||||
on community-heating certs regardless of the actual heat-network
|
||||
source — without this guard the HW cost / CO2 / PE bills via the
|
||||
Mains-gas Table 12 code (3.48 p/kWh / 0.21 / 1.13) instead of the
|
||||
heat-network code (4.24 p/kWh / Table 12 code 41 / 51).
|
||||
heat-network rate.
|
||||
|
||||
SAP code 302 (CHP+boilers) is excluded because the 35%/65% split
|
||||
requires the displaced-electricity credit line per spec block 13b
|
||||
(464)/(466) on the HW side — same constraint as `_main_heating_
|
||||
co2_factor_kg_per_kwh` (S0380.172). Routing HW through main for
|
||||
SAP 302 without the credit cascade would regress CO2 / PE; both
|
||||
the SH and HW paths converge in a single follow-up slice that
|
||||
wires the CHP credit + boiler-side factor split.
|
||||
SAP code 302 (CHP+boilers) was previously excluded because the
|
||||
35%/65% split needs the displaced-electricity credit line (spec
|
||||
block 12b/13b (364)/(366)/(464)/(466)). S0380.182 wired that credit
|
||||
via `_heat_network_code_302_effective_factor`, which intercepts the
|
||||
HW CO2/PE helpers ABOVE this predicate's branch — so including 302
|
||||
here now affects only the COST path, routing HW cost through
|
||||
`_fuel_cost_gbp_per_kwh(main)` = the S0380.171 CHP heat-fraction
|
||||
blend (the same rate as space heating, worksheet (342) = (310) ×
|
||||
blend). Closes the CH2/CH4 HW cost residual (S0380.183).
|
||||
"""
|
||||
if epc.sap_heating.water_heating_code not in _WATER_INHERIT_FROM_MAIN_CODES:
|
||||
return False
|
||||
|
|
@ -1521,7 +1523,10 @@ def _is_community_heating_hw_from_main(epc: EpcPropertyData) -> bool:
|
|||
if not _is_heat_network_main(main):
|
||||
return False
|
||||
code = main.sap_main_heating_code if main is not None else None
|
||||
return isinstance(code, int) and code in _HEAT_NETWORK_HEAT_SOURCE_EFFICIENCY
|
||||
return isinstance(code, int) and (
|
||||
code in _HEAT_NETWORK_HEAT_SOURCE_EFFICIENCY
|
||||
or code == _SAP_CODE_COMMUNITY_CHP_AND_BOILERS
|
||||
)
|
||||
|
||||
|
||||
def _main_heating_efficiency(epc: EpcPropertyData) -> float:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue