mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice S0380.25: SAP codes 2111/2113 are type 2 not type 3 — closes 0652 + 6835
Per SAP 10.2 spec page 171 Table 4e "Heating system controls" — boiler
systems with radiators (Group 1):
2110: "Time and temperature zone control by arrangement of plumbing
and electrical services" → type 3
2111: "TRVs and bypass" → type 2
2112: "Time and temperature zone control by device in PCDB" → type 3
2113: "Room thermostat and TRVs" → type 2
`_CONTROL_TYPE_BY_CODE` previously bucketed 2111 + 2113 with the type 3
codes, but neither lodges any time-zone control — they're TRV-class
controls (closer to programmer + room thermostat). The misclassification
propagated through SAP 10.2 Table 9 to swap the elsewhere-zone
off-period pattern from (7, 8) to (9, 8) — i.e. the spec's "heating
0700-0900 and 1800-2300" pattern (footnote b) instead of "heating
0700-0900 and 1600-2300" (footnote a). Under-counted MIT by ~0.67 °C
across the year, dropping space-heating demand and over-predicting SAP:
- cert 0652-3022-1205-2826-1200: +1.93 → -1e-5
- cert 6835-3920-2509-0933-5226: +0.72 → +0.015
Cohort-2 outcome (38 certs, Summary path):
exact (<1e-4): 21 → **22** (+1: cert 0652 closes)
≤±0.07: 13 → **14** (+1: cert 6835 moves from ±0.5..1)
±0.5..1: 2 → **1** (-1: cert 6835 closes out)
±1..5: 1 → **0** (-1: cert 0652 closes out)
No cohort-1 regressions (all certs there use codes 2106 / 2206;
neither uses 2111/2113).
Pyright net-zero (cert_to_inputs.py 35→35, test 13→13).
Tests: 704 pass (existing control-type test extended; +2 new
assertions for codes 2111/2113), 10 expected fails unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5402dd17e1
commit
474052d303
2 changed files with 25 additions and 5 deletions
|
|
@ -412,15 +412,25 @@ SAP_10_2_SPEC_PRICES: Final[PriceTable] = PriceTable(
|
|||
)
|
||||
|
||||
|
||||
# SAP 10.2 Table 9 main_heating_control codes → control type (1/2/3).
|
||||
# SAP 10.2 Table 4e (page 171) main_heating_control codes → control type
|
||||
# (1/2/3 per Table 9 "Heating control type" column). Type drives the
|
||||
# elsewhere-zone off-hours pattern in Table 9: types 1+2 use (7, 8),
|
||||
# type 3 uses (9, 8) per footnote (b) "heating 0700-0900 and 1800-2300".
|
||||
#
|
||||
# Type 1: no time + temp control, or one but not both.
|
||||
# Type 2: programmer + room thermostat (+/− TRVs).
|
||||
# Type 3: time-and-temperature zone control (e.g. separate living-zone
|
||||
# programmer + thermostat).
|
||||
# Type 2: programmer + room thermostat (+/− TRVs); also bare TRV-class
|
||||
# controls (2111 "TRVs and bypass", 2113 "Room thermostat and
|
||||
# TRVs") — these were misclassified as type 3 pre-S0380.25 and
|
||||
# pushed cert 0652 to +1.93 SAP / cert 6835 to +0.72.
|
||||
# Type 3: time-and-temperature zone control (separate living-zone
|
||||
# schedule via plumbing/electrical arrangement or PCDB device).
|
||||
_CONTROL_TYPE_BY_CODE: Final[dict[int, int]] = {
|
||||
2101: 1, 2102: 1, 2103: 1, 2104: 1,
|
||||
2105: 2, 2106: 2, 2107: 2, 2108: 2, 2109: 2,
|
||||
2110: 3, 2111: 3, 2112: 3, 2113: 3,
|
||||
2110: 3,
|
||||
2111: 2, # TRVs and bypass — Table 4e row "2 0"
|
||||
2112: 3,
|
||||
2113: 2, # Room thermostat and TRVs — Table 4e row "2 0"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -707,11 +707,21 @@ def test_main_heating_control_code_maps_to_sap_control_type() -> None:
|
|||
type_1 = cert_to_inputs(_epc_with_control(2103))
|
||||
type_2 = cert_to_inputs(_epc_with_control(2106))
|
||||
type_3 = cert_to_inputs(_epc_with_control(2110))
|
||||
# Slice S0380.25: SAP 10.2 Table 4e (page 171) classifies codes 2111
|
||||
# ("TRVs and bypass") and 2113 ("Room thermostat and TRVs") as
|
||||
# control type 2, NOT type 3 — they lack the time-zone control that
|
||||
# type 3 requires. Mis-classifying these as type 3 swapped the
|
||||
# elsewhere-zone off-hours from (7, 8) to (9, 8), under-counting MIT
|
||||
# by ~0.67 °C → cert 0652 +1.93 SAP / cert 6835 +0.72 SAP.
|
||||
type_2_via_2111 = cert_to_inputs(_epc_with_control(2111))
|
||||
type_2_via_2113 = cert_to_inputs(_epc_with_control(2113))
|
||||
|
||||
# Assert
|
||||
assert type_1.control_type == 1
|
||||
assert type_2.control_type == 2
|
||||
assert type_3.control_type == 3
|
||||
assert type_2_via_2111.control_type == 2
|
||||
assert type_2_via_2113.control_type == 2
|
||||
|
||||
|
||||
def test_off_peak_meter_routes_electric_costs_to_low_rate() -> None:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue