mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
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>
88 lines
3.9 KiB
Python
88 lines
3.9 KiB
Python
"""SAP 10.2 Table 13 — high-rate fraction for electric DHW heating.
|
|
|
|
Sourced verbatim from `domain/sap10_calculator/docs/specs/sap-10-2-full-
|
|
specification-2025-03-14.pdf`, page 197 (Table 13). RdSAP10 §10.5 (PDF
|
|
p.54) routes electric immersion water heating here via Table 12a's
|
|
"Immersion water heater" row, whose Water-heating column reads "Fraction
|
|
from Table 13".
|
|
|
|
The table gives the fraction of DHW electricity consumed at the HIGH
|
|
rate for a cylinder with a single or dual immersion heater on an
|
|
off-peak tariff; the remainder is at the low rate. Note 2 of the table
|
|
supplies exact equations equivalent to the tabulated (rounded) grid —
|
|
this module evaluates those equations, so no floor-area interpolation
|
|
is needed:
|
|
|
|
7-hour tariff (>= 7 hours/day at the low rate)
|
|
Dual: [(6.8 - 0.024 V) N + 14 - 0.07 V] / 100
|
|
Single: [(14530 - 762 N) / V - 80 + 10 N] / 100
|
|
|
|
10-hour tariff (>= 10 hours/day at the low rate)
|
|
Dual: [(6.8 - 0.036 V) N + 14 - 0.105 V] / 100
|
|
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].
|
|
|
|
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
|
|
|
|
from domain.sap10_calculator.tables.table_12a import Tariff
|
|
|
|
|
|
def electric_dhw_high_rate_fraction(
|
|
*,
|
|
cylinder_volume_l: float,
|
|
occupancy_n: float,
|
|
single_immersion: bool,
|
|
tariff: Tariff,
|
|
) -> float:
|
|
"""SAP 10.2 Table 13 (PDF p.197) high-rate fraction for an electric
|
|
immersion DHW cylinder on an off-peak tariff.
|
|
|
|
`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; 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:
|
|
if single_immersion:
|
|
fraction = ((14530 - 762 * n) / v - 80 + 10 * n) / 100
|
|
else:
|
|
fraction = ((6.8 - 0.024 * v) * n + 14 - 0.07 * v) / 100
|
|
else:
|
|
# 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:
|
|
fraction = ((6.8 - 0.036 * v) * n + 14 - 0.105 * v) / 100
|
|
return max(0.0, min(1.0, fraction))
|