Price water-only heat-network DHW without a plant-efficiency divisor 🟥

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Daniel Roth 2026-07-15 10:22:37 +00:00
parent 7f68912308
commit bf4af89b3a

View file

@ -1449,6 +1449,62 @@ def test_hot_water_only_heat_network_whc_950_applies_table12c_dlf() -> None:
assert abs(hw_network / baseline - 1.41) <= 0.02
def test_water_only_heat_network_dhw_prices_heat_without_plant_efficiency() -> None:
# Arrange — SAP 10.2 §4.3 (PDF p.24): "The efficiency for water heating
# is incorporated in the price of heat from a heat network in Table 12."
# The dwelling buys DELIVERED heat at the Table 12 fuel-51 rate, so the
# RdSAP Table 4a plant efficiency (950 → 0.80) must NOT also divide on
# the dwelling side — worksheet (310) is "(64) × (305a) × (306)", with
# no efficiency term. C4 (p.53) scopes plant efficiency explicitly: "For
# heat networks not listed in the PCDB, FOR THE CALCULATION OF CO2
# EMISSIONS AND PRIMARY ENERGY, the efficiency to be used is that of the
# heat generator" — i.e. never for delivered energy.
#
# (305a) is the Table 4c(3) "DHW-only system, flat rate charging" row =
# 1.05 (p.169); RdSAP 10 (spec p.59) defaults a non-PCDB water-only
# network to flat-rate charging. (306) is the age-E Table 12c DLF = 1.41.
#
# So HW fuel = q_useful × 1.41 × 1.05, i.e. water_eff = 1/(DLF × 1.05).
# Asserted as fuel ÷ q_useful (the §4 output at 100% efficiency) to pin
# the efficiency absolutely, mirroring the WHC-901 heat-network test
# above. The main is an ordinary gas boiler — NOT a heat network — since
# §4.3 keys on the DHW source ("Where hot water is provided by a heat
# network"), not on the space main.
part = make_building_part(construction_age_band="E")
gas_main = MainHeatingDetail(
has_fghrs=False,
main_fuel_type=26,
heat_emitter_type=1,
emitter_temperature=1,
main_heating_control=2106,
main_heating_category=2,
)
hw_network_epc = make_minimal_sap10_epc(
total_floor_area_m2=_TYPICAL_TFA_M2,
habitable_rooms_count=4,
country_code="ENG",
sap_building_parts=[part],
sap_heating=make_sap_heating(
main_heating_details=[gas_main],
water_heating_code=950, # hot-water-only heat network (boilers)
),
)
# Act
hw_fuel: float = cert_to_inputs(hw_network_epc).hot_water_kwh_per_yr
wh_result, _ = _water_heating_worksheet_and_gains(
epc=hw_network_epc,
water_efficiency_pct=100.0,
is_instantaneous=False,
primary_age="E",
pcdb_record=None,
)
# Assert — delivered HW fuel = q_useful × (305a) × (306); no 1/0.80.
assert wh_result is not None
assert abs(hw_fuel / wh_result.output_kwh_per_yr - 1.41 * 1.05) <= 1e-6
def test_gas_boiler_main_efficiency_unchanged_by_dlf_override() -> None:
# Arrange — regression check: the DLF override only fires for heat-
# network main heating. A standard gas boiler (cat=2, code=102) must