From a8e5563acec28b5c5913a8838284f00346660d30 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Sun, 7 Jun 2026 20:26:32 +0000 Subject: [PATCH] =?UTF-8?q?fix(warm-air):=20Table=2011=20secondary=20fract?= =?UTF-8?q?ion=20for=20category=209=20=E2=86=92=200.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit main_heating_category=9 (warm-air systems, NOT heat pump) had no entry in _SECONDARY_HEATING_FRACTION_BY_CATEGORY, so a warm-air main with a lodged secondary raised UnmappedSapCode in _secondary_heating_fraction_for_category — the last calc_raise in the API sample (cert 0380-2197-2590-2996-2715: warm air mains gas code 506 + electric room-heater secondary). SAP 10.2 Table 11 (p.188): a gas/oil warm-air unit falls under "All gas, liquid and solid fuel systems" (0.10), and electric warm air under "Other electric systems" (also 0.10) — so 0.10 regardless of fuel. The warm-air efficiency (Table 4a code→eff: 506→0.70) and Table 4f fan energy were already wired; this was the only missing dispatch entry. 0380 now computes: SAP 78.1 vs lodged 77 (+1.1; the residual is per-cert fabric/PV, not the warm-air dispatch — a faithful 0380 worksheet isn't available, sim case 28 diverges at SAP 57 / code 502 / condensing unit). Eval: zero raises remain, computed 908→909; mean|err| 1.703→1.702. Regression green (2448 pass incl. golden 6035 + cohort); pyright net-zero (44=44). Co-Authored-By: Claude Opus 4.8 --- domain/sap10_calculator/rdsap/cert_to_inputs.py | 6 ++++++ tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/domain/sap10_calculator/rdsap/cert_to_inputs.py b/domain/sap10_calculator/rdsap/cert_to_inputs.py index f39b006d..5298b0c5 100644 --- a/domain/sap10_calculator/rdsap/cert_to_inputs.py +++ b/domain/sap10_calculator/rdsap/cert_to_inputs.py @@ -792,6 +792,12 @@ _SECONDARY_HEATING_FRACTION_BY_CATEGORY: Final[dict[int, float]] = { 5: 0.10, 6: 0.10, 7: 0.15, + 9: 0.10, # Warm-air systems (NOT heat pump): a gas/oil warm-air unit + # is an "All gas, liquid and solid fuel systems" row (0.10), + # and electric warm air is "Other electric systems" (also + # 0.10) — so 0.10 regardless of fuel (SAP 10.2 Table 11 + # p.188). Cert 0380 (warm air mains gas, code 506, + + # electric room-heater secondary) raised here before. 10: 0.20, } _SECONDARY_HEATING_FRACTION_DEFAULT: Final[float] = 0.10 diff --git a/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py b/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py index 4b2d13c3..08a25d75 100644 --- a/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py +++ b/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py @@ -3352,6 +3352,13 @@ def test_secondary_heating_fraction_for_category_full_table_11_coverage() -> Non assert _secondary_heating_fraction_for_category(5) == 0.10 assert _secondary_heating_fraction_for_category(6) == 0.10 assert _secondary_heating_fraction_for_category(7) == 0.15 + # Category 9 = warm-air systems (NOT heat pump). A gas/oil warm-air + # unit is an "All gas, liquid and solid fuel systems" row (0.10); + # electric warm air is "Other electric systems" (also 0.10) — so 0.10 + # regardless of fuel (SAP 10.2 Table 11 p.188). Cert 0380-2197-2590- + # 2996-2715 (warm air mains gas, code 506, + electric room-heater + # secondary) previously raised UnmappedSapCode here, blocking it. + assert _secondary_heating_fraction_for_category(9) == 0.10 assert _secondary_heating_fraction_for_category(10) == 0.20 # Absent assert _secondary_heating_fraction_for_category(None) == 0.10