mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Cohort residual slice 1: 000490 secondary heating cascade closes -£104 cost gap
Lodges `secondary_heating_type=691` (Electricity Electric Panel) on 000490 `build_epc()` to match the U985 worksheet's "Secondary Heating: Electricity Electric Panel, convector or radiant heaters, SAP Code 691, Efficiency 100%". Pre-fix the cert lodged no secondary system → `_secondary_fraction` returned 0.0 → all useful space heat routed to main 1 → main_fuel +1357 kWh over PDF, secondary -1118 under PDF, cost -£104 under PDF (-12.9% residual). Post-fix: Table 11 fraction 0.1000 for gas-combi category cascade fires → main 1 = 11491.89 kWh, secondary = 1126.21 kWh. Total cost £807.42 vs PDF £807.54 (Δ -£0.12, -0.015%). SAP integer 58 vs PDF 57 (delta 1, was 6); continuous 57.57 vs 57.40 (delta 0.18). E2E test updates: - New worksheet-level pin `result.secondary_heating_fuel_kwh_per_yr ≈ U985 (215) = 1118.3275` at abs=10 (loose — absorbs the +0.7% upstream useful space heating overshoot which propagates 1:1 to (215). Tightens to abs=1e-3 when the useful bias closes). - Per-fixture constant `LINE_215_SECONDARY_HEATING_FUEL_KWH = 1118.3275`. - 000490 SAP integer ceiling tightened 3 → 1; continuous 3.0 → 0.5. - Removed xfail on `test_elmhurst_000490_end_to_end_sap_score_currently_ within_3_points` and `test_000490_cert_to_inputs_fuel_cost_closes_to_ within_5pct` — both now pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
fd9df9e502
commit
607e52a354
3 changed files with 45 additions and 29 deletions
|
|
@ -128,6 +128,7 @@ def build_epc() -> EpcPropertyData:
|
|||
main_heating_data_source=1,
|
||||
),
|
||||
],
|
||||
secondary_heating_type=691,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -265,6 +266,12 @@ SECTION_5_PUMP_AGE_STR: str = "Unknown"
|
|||
# inputs.lighting_kwh_per_yr on the cost side.
|
||||
LINE_232_LIGHTING_KWH_PER_YR: float = 171.4217
|
||||
|
||||
# Secondary heating fuel kWh (215) — Σ (215)m monthly tuple.
|
||||
# 000490 lodges secondary heating system "Electricity Electric Panel,
|
||||
# convector or radiant heaters" (SAP Code 691) at 100% efficiency.
|
||||
# Table 11 fraction 0.1000 of total space heat goes to secondary.
|
||||
LINE_215_SECONDARY_HEATING_FUEL_KWH: float = 1118.3275
|
||||
|
||||
LINE_66_M_METABOLIC_W: tuple[float, ...] = (128.8087,) * 12
|
||||
LINE_67_M_LIGHTING_W: tuple[float, ...] = (
|
||||
24.2665, 21.5533, 17.5283, 13.2701, 9.9195, 8.3745,
|
||||
|
|
|
|||
|
|
@ -56,19 +56,6 @@ _ELMHURST_000474_EXPECTED: Final[ElmhurstExpectedSap] = ElmhurstExpectedSap(
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason=(
|
||||
"Appendix L closure on 000490: lighting kWh closes 614→171 (spec-faithful "
|
||||
"U985 (232)=171.4217). Cost drops by ~£60 → £703 vs PDF £807; SAP integer "
|
||||
"climbs 60→63 → delta widens 3→6. Per the e2e validation philosophy "
|
||||
"(feedback-e2e-validation-philosophy): don't widen the ceiling, hunt the "
|
||||
"next broken component. Suspects: fuel pricing for pre-2025-07-01 certs "
|
||||
"(ADR-0010 §3 Validation Cohort), main heating kWh +2.5% overshoot, "
|
||||
"Table D1/D2/D3 Ecodesign corrections. Re-enable when those land and "
|
||||
"SAP integer = PDF integer (delta=0)."
|
||||
),
|
||||
strict=True,
|
||||
)
|
||||
def test_elmhurst_000490_end_to_end_sap_score_currently_within_3_points() -> None:
|
||||
"""Mid-terrace combi-gas dwelling with time-clock keep-hot. After the
|
||||
PCDB Table 105 integration the fixture lodges `main_heating_index_
|
||||
|
|
@ -119,17 +106,19 @@ def test_elmhurst_000490_end_to_end_sap_score_currently_within_3_points() -> Non
|
|||
# Act
|
||||
result = Sap10Calculator().calculate(epc)
|
||||
|
||||
# Assert
|
||||
# Assert — secondary heating cascade closed the £104 cost gap; SAP
|
||||
# integer is now 58 vs PDF 57 (delta 1). The residual delta is from
|
||||
# the +0.7% upstream useful space heating overshoot — next ticket.
|
||||
delta = abs(result.sap_score - _ELMHURST_000490_EXPECTED.sap_rating)
|
||||
assert delta <= 3, (
|
||||
f"SAP rating delta {delta} exceeds current-state ceiling of 3. "
|
||||
assert delta <= 1, (
|
||||
f"SAP rating delta {delta} exceeds current-state ceiling of 1. "
|
||||
f"Actual={result.sap_score}, expected={_ELMHURST_000490_EXPECTED.sap_rating}."
|
||||
)
|
||||
continuous_delta = abs(
|
||||
result.sap_score_continuous - _ELMHURST_000490_EXPECTED.sap_score_continuous
|
||||
)
|
||||
assert continuous_delta <= 3.0, (
|
||||
f"Continuous SAP delta {continuous_delta:.2f} exceeds ceiling 3.0"
|
||||
assert continuous_delta <= 0.5, (
|
||||
f"Continuous SAP delta {continuous_delta:.2f} exceeds ceiling 0.5"
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -221,6 +210,37 @@ def test_elmhurst_end_to_end_lighting_kwh_per_yr_matches_u985_worksheet(
|
|||
assert result.lighting_kwh_per_yr == pytest.approx(expected_kwh, abs=1e-4)
|
||||
|
||||
|
||||
def test_elmhurst_000490_end_to_end_secondary_heating_fuel_kwh_matches_u985_worksheet() -> None:
|
||||
"""Component-level e2e pin on `SapResult.secondary_heating_fuel_kwh_per_yr`
|
||||
for 000490 — cert lodges secondary heating system "Electricity Electric
|
||||
Panel, convector or radiant heaters" (SAP Code 691, 100% efficiency).
|
||||
Table 11 fraction 0.10 of total space heat goes to the secondary
|
||||
system → (215) = 1118.3275 kWh.
|
||||
|
||||
Closes the next 000490 residual after Appendix L: secondary fuel was
|
||||
silently 0 because build_epc didn't lodge secondary_heating_type, so
|
||||
`_secondary_fraction` early-returned 0.0 → all useful space heat
|
||||
routed to main 1 → main_fuel_kwh +1357 kWh over PDF, secondary -1118
|
||||
under PDF. Cost gap was £147 secondary missing minus £47 main
|
||||
overshoot = -£104 (the dominant residual after Appendix L closure).
|
||||
"""
|
||||
# Arrange
|
||||
epc = _w000490.build_epc()
|
||||
|
||||
# Act
|
||||
result = Sap10Calculator().calculate(epc)
|
||||
|
||||
# Assert — tolerance abs=10 absorbs the +0.7% (78 kWh) overshoot in
|
||||
# `result.space_heating_kwh_per_yr` (useful demand) that propagates
|
||||
# proportionally to (215) = useful × 0.1 / 1.0. The secondary cascade
|
||||
# itself is exact (Table 11 fraction lookup + 100% efficiency); the
|
||||
# residual is upstream. Tightens to abs=1e-3 when the useful bias
|
||||
# closes (next ticket — see project memory).
|
||||
assert result.secondary_heating_fuel_kwh_per_yr == pytest.approx(
|
||||
_w000490.LINE_215_SECONDARY_HEATING_FUEL_KWH, abs=10.0
|
||||
)
|
||||
|
||||
|
||||
def test_elmhurst_000490_end_to_end_kwh_within_15pct() -> None:
|
||||
"""Per-end-use kWh sanity check for 000490. Closer-fitting than the
|
||||
SAP score because intermediate values aren't compressed through the
|
||||
|
|
|
|||
|
|
@ -368,17 +368,6 @@ def test_000474_cert_to_inputs_fuel_cost_within_existing_e2e_tolerance() -> None
|
|||
assert inputs.fuel_cost.total_cost_gbp == pytest.approx(655.6949, rel=0.15)
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason=(
|
||||
"Appendix L closure on 000490: lighting kWh closes 614→171 (spec-faithful "
|
||||
"U985 (232)=171.4217). Cost drops ~£60 → £703 vs PDF £807 (-12.9%). The "
|
||||
"Appendix L direction is correct; the residual is a non-lighting broken "
|
||||
"component (suspects per feedback-e2e-validation-philosophy: fuel pricing "
|
||||
"for pre-2025-07-01 certs, main-heating-fuel +2.5% overshoot, Table D1-3 "
|
||||
"Ecodesign). Re-enable when next component closes."
|
||||
),
|
||||
strict=True,
|
||||
)
|
||||
def test_000490_cert_to_inputs_fuel_cost_closes_to_within_5pct() -> None:
|
||||
"""Cert-round-trip conformance: 000490 mid-terrace combi-gas with PV
|
||||
(PDF total fuel cost £807.54). Pre-§10a was £706.23 (-12.5%) —
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue