mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
fix(water-heating): 18-/24-hour immersion DHW bills 100% low-rate (Table 12a scope)
SAP 10.2 Table 12a (PDF p.191) is titled "High-rate fractions for systems
using 7-hour and 10-hour tariffs"; its "Immersion water heater" row lists
the tariff as "7-hour or 10-hour" only, routing to Table 13. An 18-hour or
24-hour tariff is OUTSIDE the table's scope — it provides at least 18
hours/day at the low rate, more than enough to heat any immersion cylinder
off-peak, so the high-rate fraction is 0 (all DHW billed at the low rate).
`electric_dhw_high_rate_fraction` previously mapped 18-/24-hour to the
10-hour equations (returning ~0.10 for a 110 L dual immersion) on an
over-literal reading of Table 13 Note 1 ("at least 10 hours"). The Elmhurst
dr87 worksheet for solid fuel 5 (cert 001431: 18-hour meter, 110 L dual
immersion, WHC 903) refutes that: HW (245) high-rate = 0.0 kWh, (246)
low-rate = 100%. Table 12a's title bounds the table to the two named
tariffs; 18-/24-hour fall outside it.
Resolves the Table-13 blocker on the immersion-extractor fix: once the
Summary extractor captures the dual immersion, the 18-hour solid-fuel
corpus certs stay at high_frac=0 (matching their worksheets) instead of
regressing to the 10-hour-column 0.10.
API SAP eval unchanged: 57.6% within 0.5, mean|err| 1.185, signed -0.165
(the cached sample has no 18-hour WHC-903 certs; one 24-hour cert shifts
sub-threshold). Regression gate green (3 pre-existing fails unrelated).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
020ac6f220
commit
0202b045de
2 changed files with 44 additions and 19 deletions
|
|
@ -22,12 +22,24 @@ is needed:
|
|||
Single: [(14530 - 762 N) / (1.5 V) - 80 + 10 N] / 100
|
||||
|
||||
where V is the cylinder volume (litres) and N is the assumed occupancy
|
||||
(Appendix J Table 1b). Per Note 2 the result is clamped to [0, 1]. Per
|
||||
Note 1 the 10-hour equations apply to any tariff providing at least 10
|
||||
hours/day at the low rate (so 18-hour and 24-hour use the 10-hour
|
||||
column). Heat pumps providing water heating only are treated as dual
|
||||
immersion (Note 1) — out of scope of this helper (callers route those
|
||||
via Table 12a).
|
||||
(Appendix J Table 1b). Per Note 2 the result is clamped to [0, 1].
|
||||
|
||||
Table 12a (PDF p.191) — whose title reads "High-rate fractions for
|
||||
systems using 7-hour and 10-hour tariffs" — routes the "Immersion water
|
||||
heater" row to Table 13 for the tariff "7-hour or 10-hour" ONLY. An
|
||||
18-hour or 24-hour tariff is outside Table 12a/13's scope: it provides
|
||||
at least 18 hours/day at the low rate, more than enough to heat any
|
||||
immersion cylinder off-peak, so the high-rate fraction is 0 (all DHW
|
||||
billed at the low rate). The Elmhurst dr87 worksheet for solid fuel 5
|
||||
(cert 001431: 18-hour meter, 110 L dual immersion, WHC 903) confirms
|
||||
this — HW (245) high-rate = 0.0 kWh, (246) low-rate = 100%. (An earlier
|
||||
reading mapped 18-/24-hour to the 10-hour column via Note 1's "at least
|
||||
10 hours"; the worksheet refutes it — Table 12a's title bounds the table
|
||||
to the two named tariffs.)
|
||||
|
||||
Heat pumps providing water heating only are treated as dual immersion
|
||||
(Note 1) — out of scope of this helper (callers route those via Table
|
||||
12a).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -47,13 +59,19 @@ def electric_dhw_high_rate_fraction(
|
|||
|
||||
`single_immersion` selects the single- vs dual-immersion equation
|
||||
(RdSAP10 §10.5 p.54: an immersion is assumed dual on a dual meter).
|
||||
The 7-hour tariff uses the 7-hour equations; every other off-peak
|
||||
tariff (10/18/24-hour, all >= 10 hours low-rate per Note 1) uses the
|
||||
10-hour equations. STANDARD has no off-peak split and is rejected —
|
||||
callers must early-return before this fires.
|
||||
The 7-hour tariff uses the 7-hour equations; the 10-hour tariff uses
|
||||
the 10-hour equations. The 18-hour and 24-hour tariffs are outside
|
||||
Table 12a/13's "7-hour and 10-hour" scope (PDF p.191 title) — they
|
||||
provide >= 18 hours/day at the low rate, so the high-rate fraction is
|
||||
0. STANDARD has no off-peak split and is rejected — callers must
|
||||
early-return before this fires.
|
||||
"""
|
||||
if tariff is Tariff.STANDARD:
|
||||
raise ValueError("Table 13 high-rate fraction is undefined for STANDARD")
|
||||
if tariff in (Tariff.EIGHTEEN_HOUR, Tariff.TWENTY_FOUR_HOUR):
|
||||
# Outside Table 12a's 7-hour/10-hour scope — >= 18 h/day low rate
|
||||
# heats the cylinder entirely off-peak (high-rate fraction 0).
|
||||
return 0.0
|
||||
v = cylinder_volume_l
|
||||
n = occupancy_n
|
||||
if tariff is Tariff.SEVEN_HOUR:
|
||||
|
|
@ -62,7 +80,7 @@ def electric_dhw_high_rate_fraction(
|
|||
else:
|
||||
fraction = ((6.8 - 0.024 * v) * n + 14 - 0.07 * v) / 100
|
||||
else:
|
||||
# >= 10 hours/day at the low rate (10/18/24-hour) — Note 1.
|
||||
# 10-hour tariff (18-/24-hour handled above as out-of-scope).
|
||||
if single_immersion:
|
||||
fraction = ((14530 - 762 * n) / (1.5 * v) - 80 + 10 * n) / 100
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -83,21 +83,28 @@ def test_table_13_large_cylinder_single_immersion_clamps_to_zero() -> None:
|
|||
assert fraction == 0.0
|
||||
|
||||
|
||||
def test_table_13_eighteen_hour_uses_ten_hour_column() -> None:
|
||||
# Arrange — SAP 10.2 Table 13 Note 1 (PDF p.197): the table applies
|
||||
# "for tariffs providing at least 10 hours ... at the low rate", so an
|
||||
# 18-hour tariff resolves to the 10-hour equations, not a separate
|
||||
# column.
|
||||
def test_table_13_eighteen_and_twenty_four_hour_bill_full_low_rate() -> None:
|
||||
# Arrange — SAP 10.2 Table 12a (PDF p.191) is titled "High-rate
|
||||
# fractions for systems using 7-hour and 10-hour tariffs"; its
|
||||
# "Immersion water heater" row lists the tariff as "7-hour or 10-hour"
|
||||
# only, routing to Table 13. An 18-hour / 24-hour tariff is OUTSIDE the
|
||||
# table's scope: it provides at least 18 hours/day at the low rate, more
|
||||
# than enough to heat any immersion cylinder off-peak, so the high-rate
|
||||
# fraction is 0 (100% billed at the low rate). The Elmhurst dr87
|
||||
# worksheet for solid fuel 5 (cert 001431: 18-hour meter, 110 L dual
|
||||
# immersion, WHC 903) bills HW (245) high-rate = 0.0 kWh, (246) low-rate
|
||||
# = 100% — confirming high_frac = 0 for an 18-hour immersion DHW.
|
||||
|
||||
# Act
|
||||
eighteen = electric_dhw_high_rate_fraction(
|
||||
cylinder_volume_l=110.0, occupancy_n=_N_AT_TFA_100,
|
||||
single_immersion=False, tariff=Tariff.EIGHTEEN_HOUR,
|
||||
)
|
||||
ten = electric_dhw_high_rate_fraction(
|
||||
twenty_four = electric_dhw_high_rate_fraction(
|
||||
cylinder_volume_l=110.0, occupancy_n=_N_AT_TFA_100,
|
||||
single_immersion=False, tariff=Tariff.TEN_HOUR,
|
||||
single_immersion=False, tariff=Tariff.TWENTY_FOUR_HOUR,
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert abs(eighteen - ten) <= 1e-9
|
||||
assert eighteen == 0.0
|
||||
assert twenty_four == 0.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue