mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice S0380.80: SAP 10.2 Table 4c −5% DHW for missing boiler interlock closes cert 000565 HW pin EXACT
Closes cert 000565 hot_water_kwh_per_yr pin: **3517.37 → 3755.03 ✓
EXACT** vs worksheet 3755.0288. Net cumulative HW closure across
S0380.77/78/79/80: +1399 kWh → 0 (100% closed).
## Spec rule
SAP 10.2 Table 4c (PDF p.169-170) "Efficiency adjustments":
(2) Efficiency adjustment due to control system Space DHW
No boiler interlock - regular boiler (...) −5 −5
No boiler interlock - combi −5 0
Note c): "These do not accumulate as no thermostatic control or
presence of a bypass means that there is no boiler interlock."
RdSAP 10 §3 (PDF p.57) "Boiler interlock" definition:
Assumed present if there is a room thermostat and (for stored
hot water systems heated by the boiler) a cylinder thermostat.
Otherwise not interlocked.
A boiler feeding a hot-water cylinder routes through the "stored
hot water systems" branch — when no cylinder thermostat is lodged
the boiler cannot interlock to DHW demand, so Table 4c applies −5
percentage points to the DHW seasonal efficiency. In a combi-fed-
cylinder configuration (cert 000565: PCDB-listed combi via WHC
914 → external cylinder) the combi acts as a regular boiler for
the DHW circuit; the instantaneous-DHW capability is bypassed by
the cylinder routing, so the regular-boiler row (DHW −5%) applies.
## Fix
`cert_to_inputs.py` water-efficiency branch: after the PCDB-summer
lookup (or Table 4b fall-through), apply −5pp when
epc.has_hot_water_cylinder
AND epc.sap_heating.cylinder_thermostat != "Y"
AND water_pcdb_main is not None # boiler — Table 4c applies
For cert 000565: PCDB summer η = 79.0 → 74.0; output (64)/η =
2778.72/0.74 = 3754.99 vs worksheet 3755.03 — within 0.04 kWh.
## Cert 000565 movements at HEAD (post-S0380.79 → post-this slice)
| Field | Pre-slice | Post-slice | Worksheet | Pre-Δ | Post-Δ |
|----------------------|-----------:|-----------:|-----------:|--------:|--------:|
| sap_score | 29 | 28 | 29 | 0 | −1 |
| sap_score_continuous | 28.5652 | 28.4680 | 28.5087 | +0.057 | −0.041 |
| ecf | 5.3810 | 5.3910 | 5.3866 | −0.006 | +0.004 |
| total_fuel_cost_gbp | 4675.23 | 4683.88 | 4680.26 | −5.03 | +3.62 |
| co2_kg | 6388.80 | 6438.71 | 6447.63 | −58.83 | −8.92 |
| **hot_water_kwh** | 3517.37 | **3755.03** | 3755.03 | −237.66 | **✓ 0** |
| space_heating_kwh | 58936.06 | 58936.06 | 59008.35 | −72.29 | −72.29 |
| main_heating_fuel | 34668.27 | 34668.27 | 34710.79 | −42.52 | −42.52 |
The sap_score=28 flip is the documented gas-tariff residual: cascade
prices mains gas at SAP 10.2 Table 12 = £0.0364/kWh, worksheet uses
RdSAP Table 32 = £0.0348/kWh. Over the now-correct 3755.03 HW kWh
that £0.16/100 delta inflates cost by ~£6 — exactly accounts for the
+£3.62 cost residual and the +0.041 continuous SAP deviation. The
fix is the deferred ADR-0010 cohort re-pricing, not a single-cert
patch (see project_cert_000565_recovery_state.md "Open thread #6").
## Cumulative cert 000565 closure across S0380.77/78/79/80
hot_water_kwh: +1399 → +260 → −238 → **✓ 0** (100% closed)
sap_score_continuous: +0.60 → −0.035 → +0.057 → −0.041 (93% closed)
ecf: −0.06 → +0.004 → −0.006 → +0.004 (93% closed)
total_fuel_cost_gbp: −53 → +3.13 → −5.03 → +3.62 (93% closed)
(45)m, (46)m, (57)m, (59)m, (62)m, **(64)/(217)m, (219)**: ALL EXACT vs worksheet
Test baseline: 550 → 551 pass + 9 expected `test_sap_result_pin
[000565-*]` fails — hot_water_kwh now PASSING; sap_score now failing
in the same expected-fail count. Pyright net-zero (45 = 45).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f9551355bb
commit
760a893ce8
2 changed files with 77 additions and 0 deletions
|
|
@ -3638,6 +3638,24 @@ def cert_to_inputs(
|
|||
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 Table 4c row "No boiler interlock — regular boiler:
|
||||
# DHW −5%" (PDF p.169). RdSAP §3 (PDF p.57) defines boiler
|
||||
# interlock as "Assumed present if there is a room thermostat and
|
||||
# (for stored hot water systems heated by the boiler) a cylinder
|
||||
# thermostat. Otherwise not interlocked." A combi-fed cylinder
|
||||
# routes the boiler as a regular boiler for the DHW circuit (the
|
||||
# combi's instantaneous-DHW capability is bypassed), so the
|
||||
# regular-boiler row applies. Note c): the adjustment caps at
|
||||
# −5pp (no thermostatic control and no boiler interlock do not
|
||||
# accumulate). Cert 000565 (cylinder lodged + cyl-stat absent +
|
||||
# WHC 914 to PCDB combi Main 2) closes 79% → 74% — matches
|
||||
# worksheet (217)m exactly.
|
||||
if (
|
||||
epc.has_hot_water_cylinder
|
||||
and epc.sap_heating.cylinder_thermostat != "Y"
|
||||
and water_pcdb_main is not None
|
||||
):
|
||||
water_eff -= 0.05
|
||||
# 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
|
||||
# APM-interpolated η_space and η_water at the dwelling's PSR.
|
||||
|
|
|
|||
|
|
@ -1802,6 +1802,65 @@ def test_cert_with_hot_water_cylinder_computes_primary_loss_59m_from_sap_table_3
|
|||
)
|
||||
|
||||
|
||||
def test_table_4c_no_boiler_interlock_applies_minus_5_dhw_adjustment_when_cylinder_lodged_without_thermostat() -> None:
|
||||
"""SAP 10.2 Table 4c (PDF p.169-170) "Efficiency adjustments":
|
||||
|
||||
(2) Efficiency adjustment due to control system Space DHW
|
||||
No boiler interlock - regular boiler -5 -5
|
||||
No boiler interlock - combi -5 0
|
||||
|
||||
Note c): "These do not accumulate as no thermostatic control or
|
||||
presence of a bypass means that there is no boiler interlock."
|
||||
|
||||
RdSAP 10 §3 (PDF p.57) "Boiler interlock" definition:
|
||||
Assumed present if there is a room thermostat and (for stored
|
||||
hot water systems heated by the boiler) a cylinder thermostat.
|
||||
Otherwise not interlocked.
|
||||
|
||||
A boiler feeding a hot-water cylinder is in the "stored hot water
|
||||
systems heated by the boiler" category — when no cylinder
|
||||
thermostat is lodged, boiler interlock is absent and Table 4c
|
||||
applies -5 percentage points to the DHW seasonal efficiency. This
|
||||
holds regardless of whether the boiler is a combi or regular type;
|
||||
in a combi-fed-cylinder configuration the combi acts as a regular
|
||||
boiler for the DHW circuit (instantaneous DHW capability is
|
||||
bypassed by the cylinder routing), so the regular-boiler row of
|
||||
Table 4c (-5%) applies.
|
||||
|
||||
Cert 000565 (ASHP Main 1 + Vaillant PCDB 15100 combi Main 2 + WHC
|
||||
914 + 160 L cylinder + cylinder thermostat absent) reproduces the
|
||||
pattern. PCDB summer η = 79.0; worksheet (217)m = 74.0; the
|
||||
cascade was returning 79% (PCDB summer unchanged), driving the
|
||||
-238 kWh HW pin over-shoot that survived S0380.79.
|
||||
|
||||
Predicted HW closure: 2778.72 / 0.74 = 3754.99 vs worksheet
|
||||
3755.03 — within 0.04 kWh.
|
||||
"""
|
||||
# Arrange — use the real cert 000565 fixture (Elmhurst extractor +
|
||||
# mapper) so the (62)m demand cascade is the worksheet-pinned
|
||||
# tuple and only the (217)m efficiency step is under test.
|
||||
from domain.sap10_calculator.worksheet.tests._elmhurst_worksheet_000565 import (
|
||||
build_epc as build_cert_000565,
|
||||
)
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
epc = build_cert_000565()
|
||||
|
||||
# Act
|
||||
result = calculate_sap_from_inputs(cert_to_inputs(epc))
|
||||
|
||||
# Assert — cert 000565 worksheet line (219) sum = 3755.0288 (HW
|
||||
# fuel kWh/yr). Pre-fix: 3517.37 (off by −238 from (64)/0.79).
|
||||
# With Table 4c -5% applied: (64)/0.74 = 2778.72/0.74 = 3754.99,
|
||||
# closing to worksheet 3755.03 within 0.04 kWh.
|
||||
expected_hw_kwh = 3755.0288
|
||||
assert abs(result.hot_water_kwh_per_yr - expected_hw_kwh) < 0.1, (
|
||||
f"cert 000565 hot_water_kwh_per_yr: got "
|
||||
f"{result.hot_water_kwh_per_yr!r}, want {expected_hw_kwh!r} per "
|
||||
f"SAP 10.2 Table 4c (No boiler interlock — regular boiler: "
|
||||
f"DHW −5%); RdSAP §3 (no cylinder thermostat → no boiler interlock)"
|
||||
)
|
||||
|
||||
|
||||
def test_cylinder_storage_loss_applies_57m_solar_adjustment_per_sap_4_line_7693() -> None:
|
||||
"""SAP 10.2 §4 line 7693 (PDF p.137):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue