test(pcdb): PSR-extension toward 100% above largest / below smallest 🟥

SAP 10.2 Appendix N2 (PDF p.101, footnote 44/45): for an air/ground/water
source heat pump whose plant size ratio exceeds the record's largest PSR,
the efficiency is reciprocal-interpolated between the largest-PSR value and
100% at twice the largest PSR (100% beyond that); below the smallest PSR the
efficiency is 100%. Our interpolator instead clamps to the top/bottom row.

Anchored to the accredited Elmhurst worksheet for cert 100110101713 (golden
fixture case 56, PCDB 100061): PSR 3.10665 over the record's largest 2.0
gives eta_space,1 = 147.011 -> (206) = 0.95 x 147.011 = 139.660, vs the
clamped 352.0 -> 334.4% that over-rates the dwelling by +18 SAP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-29 15:08:15 +00:00
parent 597510b996
commit 3d93c7b7d5

View file

@ -180,3 +180,88 @@ def test_interpolate_heat_pump_efficiency_at_cert_0380_psr_per_sap_app_n() -> No
# ≈ 0.0035077 → eta_water_3 ≈ 285.0861
assert abs(eta_space_1 - 234.5235) < 1e-3
assert abs(eta_water_3 - 285.0861) < 1e-3
def test_interpolate_extends_above_largest_psr_toward_100pct_per_app_n() -> None:
"""SAP 10.2 Appendix N2 (PDF p.101, footnote 44/45) — PSR above the
record's largest value extends the efficiency toward 100%, it is NOT
clamped to the top-of-table value.
"in the case of a heat pump (ground, water or air source), where
the PSR is greater than the largest value in the data record, an
efficiency may be obtained from linear interpolation between that
at the largest PSR in the data record and efficiency 100% at PSR
two times the largest PSR in the data record. If the PSR is
greater than two times the largest PSR in the data record an
efficiency of 100% should be used."
Interpolation is reciprocal-linear (footnote 43). Accredited anchor:
Elmhurst worksheet for cert 100110101713 / "golden fixture debugging"
case 56 (PCDB 100061, ECODAN 8.5 kW, largest PSR row η_space,1=352.0).
The dwelling HLC (39) = 107.8199 W/K and max output 8.106 kW give
PSR = 8.106 × 1000 / (107.8199 × 24.2) = 3.106650
which exceeds the record's largest PSR (2.0). The spec extension to
100% at 2 × 2.0 = 4.0 yields, at t = (3.106650 2.0)/(4.0 2.0):
1/η = (1 t)/352.0 + t/100.0 η_space,1 = 147.011
so that (206) = 0.95 × 147.011 = 139.660 matching the accredited
worksheet exactly. The previous top-of-table clamp returned 352.0
( 334.4%), over-rating the dwelling by +18 SAP.
"""
from domain.sap10_calculator.tables.pcdb.parser import (
interpolate_heat_pump_efficiency_at_psr,
)
record = heat_pump_record(100061)
assert record is not None
assert record.psr_groups[-1].psr == 2.0
assert record.psr_groups[-1].eta_space_1_pct == 352.0
eta_space_1, _eta_water_3 = interpolate_heat_pump_efficiency_at_psr(
record.psr_groups, target_psr=3.106649864134083,
)
assert abs(eta_space_1 - 147.011) < 1e-2
assert abs(0.95 * eta_space_1 - 139.6604) < 1e-2
def test_interpolate_above_twice_largest_psr_is_100pct_per_app_n() -> None:
"""SAP 10.2 Appendix N2 — beyond twice the largest PSR the efficiency
is exactly 100% (the upper terminus of the extension), for both space
and water heating PSR-dependent results."""
from domain.sap10_calculator.tables.pcdb.parser import (
interpolate_heat_pump_efficiency_at_psr,
)
record = heat_pump_record(100061)
assert record is not None
eta_space_1, eta_water_3 = interpolate_heat_pump_efficiency_at_psr(
record.psr_groups, target_psr=9.0, # > 2 × 2.0
)
assert eta_space_1 == 100.0
assert eta_water_3 == 100.0
def test_interpolate_below_smallest_psr_is_100pct_per_app_n() -> None:
"""SAP 10.2 Appendix N2 (PDF p.101) — "For all heat pumps, an
efficiency of 100% should be used if the PSR is less than the smallest
value in the database record." (Not clamped to the smallest row.)"""
from domain.sap10_calculator.tables.pcdb.parser import (
interpolate_heat_pump_efficiency_at_psr,
)
record = heat_pump_record(100061)
assert record is not None
assert record.psr_groups[0].psr == 0.2
eta_space_1, eta_water_3 = interpolate_heat_pump_efficiency_at_psr(
record.psr_groups, target_psr=0.1, # < 0.2
)
assert eta_space_1 == 100.0
assert eta_water_3 == 100.0