mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Accrue Table 3 primary-circuit loss for water-only heat-network cylinders 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5f3e9f893f
commit
d10b5210c6
1 changed files with 50 additions and 0 deletions
|
|
@ -1561,6 +1561,56 @@ def test_water_only_heat_network_dhw_fuel_independent_of_plant_type() -> None:
|
|||
assert heat_pump == pytest.approx(boilers, abs=1e-6)
|
||||
|
||||
|
||||
def test_water_only_heat_network_cylinder_accrues_table_3_primary_loss() -> None:
|
||||
# Arrange — SAP 10.2 §4.3 (PDF p.24) scopes itself "Where hot water is
|
||||
# provided by a heat network", then requires: "Primary circuit loss for
|
||||
# insulated pipework and cylinderstat should be included (see Table 3)."
|
||||
# A water-ONLY network (WHC 950) feeds the dwelling-side cylinder via
|
||||
# primary pipework from the network connection, so the loss applies on
|
||||
# the DHW source alone — whatever the SPACE main is.
|
||||
#
|
||||
# The space main here is warm air (Table 4a code 502, category 9),
|
||||
# mirroring cert 9093 (whc 950 + warm-air main). That main is not a
|
||||
# boiler, so no boiler-category branch can accrue the loss on its
|
||||
# behalf: without a WHC-keyed gate the cylinder silently gets (59)m = 0.
|
||||
part = make_building_part(construction_age_band="E")
|
||||
warm_air_main = MainHeatingDetail(
|
||||
has_fghrs=False,
|
||||
main_fuel_type=26,
|
||||
heat_emitter_type=1,
|
||||
emitter_temperature=1,
|
||||
main_heating_control=2106,
|
||||
main_heating_category=9,
|
||||
sap_main_heating_code=502,
|
||||
)
|
||||
epc = make_minimal_sap10_epc(
|
||||
total_floor_area_m2=_TYPICAL_TFA_M2,
|
||||
habitable_rooms_count=4,
|
||||
country_code="ENG",
|
||||
has_hot_water_cylinder=True,
|
||||
sap_building_parts=[part],
|
||||
sap_heating=make_sap_heating(
|
||||
main_heating_details=[warm_air_main],
|
||||
water_heating_code=950, # hot-water-only heat network
|
||||
cylinder_size=2, # Normal / 110 L
|
||||
cylinder_thermostat="Y",
|
||||
),
|
||||
)
|
||||
|
||||
# Act
|
||||
wh_result, _ = _water_heating_worksheet_and_gains(
|
||||
epc=epc,
|
||||
water_efficiency_pct=100.0,
|
||||
is_instantaneous=False,
|
||||
primary_age="E",
|
||||
pcdb_record=None,
|
||||
)
|
||||
|
||||
# Assert — the primary circuit runs, so (59)m is billed every month.
|
||||
assert wh_result is not None
|
||||
assert all(m > 0.0 for m in wh_result.primary_loss_monthly_kwh)
|
||||
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue