mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
S0380.228: electric secondary on off-peak bills at Table 12a direct-acting high rate
SAP 10.2 Table 12a Grid 1 (PDF p.191): secondary heating is a direct- acting electric room heater (RdSAP 10 §A.2.2 default), on the "Other systems including direct-acting electric" row — 7-hour high-rate fraction 1.00, 10-hour 0.50. A room heater runs on demand, mostly at the high rate; it does NOT earn the 100%-low-rate of overnight storage charging. `_secondary_fuel_cost_gbp_per_kwh` previously returned the flat off-peak LOW rate (5.50 p, £0.0550) for every off-peak electric secondary, under- charging by 9.79 p/kWh. New `_secondary_off_peak_rate_gbp_per_kwh` mirrors `_space_heating_fuel_cost_gbp_per_kwh`: it blends the Table 12a high-rate fraction (OTHER_DIRECT_ACTING_ELECTRIC) against the Table 32 high/low rates, with the 18-/24-hour fallback to the low rate. Simulated case 19 (electric storage main + electric secondary, Dual/7-hour meter) is the worksheet case (242): "Space heating - secondary (1.00*15.29 + 0.00*5.50)" → 15.29 p/kWh = £0.1529. This was the primary cat-7-cluster cost driver: total cost 1485.68 → 1835.53 (worksheet 1816.58), SAP cont 60.11 → 50.67 (worksheet ~51.22). Remaining +19 cost is HW/space-heating kWh (next slices). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5d4b55d7f9
commit
4911c56200
2 changed files with 75 additions and 2 deletions
|
|
@ -2262,6 +2262,35 @@ def _secondary_efficiency(
|
|||
return seasonal_efficiency(code, None, None)
|
||||
|
||||
|
||||
def _secondary_off_peak_rate_gbp_per_kwh(meter_type: object) -> float:
|
||||
"""SAP 10.2 Table 12a Grid 1 (PDF p.191) blended rate for an electric
|
||||
secondary heater on an off-peak tariff. The secondary is a direct-
|
||||
acting electric room heater (RdSAP 10 §A.2.2 default), so it sits on
|
||||
the "Other systems including direct-acting electric" row — high-rate
|
||||
fraction 1.00 for 7-hour, 0.50 for 10-hour. NOT the 100%-low-rate of
|
||||
storage-charging: a room heater runs on demand, mostly at the high
|
||||
rate. Worksheet evidence — simulated case 19 (242): "Space heating -
|
||||
secondary (1.00*15.29 + 0.00*5.50)" → all at the 7-hour HIGH rate.
|
||||
|
||||
Mirrors `_space_heating_fuel_cost_gbp_per_kwh`: the meter resolves to
|
||||
a tariff (the `_is_off_peak_meter` Unknown-code-3 heuristic falls
|
||||
through to 7-hour, as in `_off_peak_low_rate_gbp_per_kwh_via_meter_
|
||||
heuristic`); 18-/24-hour tariffs (absent from the Grid 1 direct-acting
|
||||
row) fall back to the tariff's Table 32 low rate."""
|
||||
tariff = tariff_from_meter_type(meter_type)
|
||||
if tariff is Tariff.STANDARD:
|
||||
tariff = Tariff.SEVEN_HOUR
|
||||
try:
|
||||
high_frac = space_heating_high_rate_fraction(
|
||||
Table12aSystem.OTHER_DIRECT_ACTING_ELECTRIC, tariff,
|
||||
)
|
||||
except NotImplementedError:
|
||||
return _off_peak_low_rate_gbp_per_kwh(tariff)
|
||||
high_rate, low_rate = _tariff_high_low_rates_p_per_kwh(tariff)
|
||||
blended = high_frac * high_rate + (1.0 - high_frac) * low_rate
|
||||
return blended * _PENCE_TO_GBP
|
||||
|
||||
|
||||
def _secondary_fuel_cost_gbp_per_kwh(
|
||||
sap_heating,
|
||||
main: Optional[MainHeatingDetail],
|
||||
|
|
@ -2277,13 +2306,13 @@ def _secondary_fuel_cost_gbp_per_kwh(
|
|||
# Default to electricity since the default secondary system is
|
||||
# portable electric heaters (code 693).
|
||||
if _is_off_peak_meter(meter_type, fuel_is_electric=True):
|
||||
return _off_peak_low_rate_gbp_per_kwh_via_meter_heuristic(meter_type)
|
||||
return _secondary_off_peak_rate_gbp_per_kwh(meter_type)
|
||||
return prices.standard_electricity_p_per_kwh * _PENCE_TO_GBP
|
||||
# When secondary_fuel_type is electricity, apply off-peak if applicable.
|
||||
if _is_electric_water(sec_fuel) and _is_off_peak_meter(
|
||||
meter_type, fuel_is_electric=True
|
||||
):
|
||||
return _off_peak_low_rate_gbp_per_kwh_via_meter_heuristic(meter_type)
|
||||
return _secondary_off_peak_rate_gbp_per_kwh(meter_type)
|
||||
return prices.unit_price_p_per_kwh(sec_fuel) * _PENCE_TO_GBP
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
|||
_pv_overshading_factor, # pyright: ignore[reportPrivateUsage]
|
||||
_pv_pitch_deg, # pyright: ignore[reportPrivateUsage]
|
||||
_responsiveness, # pyright: ignore[reportPrivateUsage]
|
||||
_secondary_fuel_cost_gbp_per_kwh, # pyright: ignore[reportPrivateUsage]
|
||||
_secondary_heating_fraction_for_category, # pyright: ignore[reportPrivateUsage]
|
||||
_section_12_4_4_summer_immersion_applies, # pyright: ignore[reportPrivateUsage]
|
||||
_separately_timed_dhw, # pyright: ignore[reportPrivateUsage]
|
||||
|
|
@ -1912,6 +1913,49 @@ def test_separately_timed_dhw_excludes_dedicated_water_heater_per_table_2b_note_
|
|||
assert separately_timed is False
|
||||
|
||||
|
||||
def test_secondary_electric_off_peak_bills_at_table_12a_direct_acting_high_rate() -> None:
|
||||
# Arrange — SAP 10.2 Table 12a Grid 1 (PDF p.191): secondary heating
|
||||
# is a direct-acting electric room heater (RdSAP 10 §A.2.2 default),
|
||||
# which sits on the "Other systems including direct-acting electric"
|
||||
# row. For a 7-hour (Economy-7) tariff that row's high-rate fraction
|
||||
# is 1.00 — ALL secondary consumption bills at the high rate, NOT the
|
||||
# off-peak low rate that storage-heater charging earns. Simulated
|
||||
# case 19's worksheet (242) is the evidence: "Space heating -
|
||||
# secondary (1.00*15.29 + 0.00*5.50)" → 15.29 p/kWh = £0.1529. Pre-
|
||||
# slice `_secondary_fuel_cost_gbp_per_kwh` returned the 7-hour low
|
||||
# rate 5.50 p (£0.0550) for every off-peak electric secondary,
|
||||
# under-charging by 9.79 p/kWh × the secondary kWh (~£340 on case 19).
|
||||
storage_heater_main = MainHeatingDetail(
|
||||
has_fghrs=False,
|
||||
main_fuel_type=30, # electricity
|
||||
heat_emitter_type="",
|
||||
emitter_temperature=1,
|
||||
main_heating_control=2402,
|
||||
main_heating_category=None,
|
||||
sap_main_heating_code=402, # electric storage heaters
|
||||
)
|
||||
dual_meter_off_peak_epc = make_minimal_sap10_epc(
|
||||
total_floor_area_m2=_TYPICAL_TFA_M2,
|
||||
habitable_rooms_count=4,
|
||||
country_code="ENG",
|
||||
sap_heating=make_sap_heating(
|
||||
main_heating_details=[storage_heater_main],
|
||||
# secondary_fuel_type omitted → §A.2.2 portable electric default
|
||||
),
|
||||
)
|
||||
|
||||
# Act
|
||||
secondary_rate_gbp_per_kwh = _secondary_fuel_cost_gbp_per_kwh(
|
||||
dual_meter_off_peak_epc.sap_heating,
|
||||
storage_heater_main,
|
||||
1, # Dual meter → 7-hour off-peak tariff
|
||||
SAP_10_2_SPEC_PRICES,
|
||||
)
|
||||
|
||||
# Assert — 1.00 × 15.29 p + 0.00 × 5.50 p = 15.29 p/kWh = £0.1529.
|
||||
assert abs(secondary_rate_gbp_per_kwh - 0.1529) <= 1e-6
|
||||
|
||||
|
||||
def test_water_efficiency_uses_table_4a_water_column_for_heat_pumps_per_sap_10_2() -> None:
|
||||
# Arrange — SAP 10.2 Table 4a (PDF p.163-164) gives heat pumps two
|
||||
# efficiency columns: "space" and "water". For low-temperature
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue