mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
S0380.206: Eq D1 Q_space uses the DHW boiler's own (204) share, not (202)
SAP 10.2 Appendix D §D2.1(2) Equation D1 blends the monthly water-heater efficiency by the ratio of the boiler's space-heating load to its water load. On a dual-main cert the DHW boiler does only its OWN share of space heating ((204) for Main 1, (205) for Main 2), but the cascade fed Eq D1 the dwelling total ((202) = 1 − secondary). That over-weighted η_winter and under-stated HW fuel — simulated case 6 (Main 1 serves DHW + 51% of space heat) was HW −78 kWh vs the worksheet. New `_water_heating_main_space_fraction` returns the DHW main's total- space share via `_water_heating_main` (WHC-901 → Main 1 (204); WHC-914 → Main 2 (205)); single-main / WHC-901 single systems get (202) = 1 − (201), so they are unchanged. Case 6 (219) HW now 4902.8601 EXACT. With S0380.205 (demand exact), case 6 now closes to 1e-4 on EVERY metric: SAP cont 71.6597, ECF 2.0316, cost 1162.5374, (211)+(213) 14736.9564, (219) 4902.8601, (231) 356, (232) 357.6571, CO2 5953.6679 (rating) / 4895.2137 (demand). Re-pin: 0240 (dual combi, WHC 901, Main 1 51%) HW rises slightly → PE +1.6893 → +1.8687, CO2 +0.0815 → +0.0907 (SAP 72 unchanged). Single-main certs unchanged (2360 pass + 0 fail). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e440e2df2e
commit
d1ae87c7e9
4 changed files with 69 additions and 4 deletions
|
|
@ -1479,6 +1479,35 @@ def _water_heating_main(
|
|||
return details[0]
|
||||
|
||||
|
||||
def _water_heating_main_space_fraction(
|
||||
epc: EpcPropertyData, secondary_fraction: float
|
||||
) -> float:
|
||||
"""Fraction of TOTAL space heating provided by the DHW boiler — the
|
||||
SAP 10.2 Appendix D §D2.1(2) Equation D1 Q_space weight.
|
||||
|
||||
Eq D1's monthly water-heater efficiency blends η_winter / η_summer by
|
||||
the ratio of the boiler's space-heating load to its water load. On a
|
||||
single-main / WHC-901 cert that load is the whole main share,
|
||||
(202) = 1 − (201). On a dual-main cert the DHW boiler does ONLY its
|
||||
own share — (204) for Main 1, (205) for Main 2 — so feeding it the
|
||||
dwelling total over-weights η_winter and under-states HW fuel
|
||||
(simulated case 6: Main 1 serves DHW + 51% of space heat; using 100%
|
||||
of demand gave HW −78 kWh vs the worksheet)."""
|
||||
details = epc.sap_heating.main_heating_details if epc.sap_heating else []
|
||||
main_fraction = 1.0 - secondary_fraction # (202)
|
||||
if len(details) < 2:
|
||||
return main_fraction
|
||||
main_2 = details[1]
|
||||
main_2_of_main = (
|
||||
main_2.main_heating_fraction / 100.0
|
||||
if main_2.main_heating_fraction is not None
|
||||
else 0.0
|
||||
)
|
||||
if _water_heating_main(epc) is details[1]:
|
||||
return main_fraction * main_2_of_main # (205) — DHW from Main 2
|
||||
return main_fraction * (1.0 - main_2_of_main) # (204) — DHW from Main 1
|
||||
|
||||
|
||||
def _rdsap_tariff(epc: EpcPropertyData) -> Tariff:
|
||||
"""Resolve the cert's Table 12a tariff column via RdSAP 10 §12
|
||||
Rules 1-4 (page 62). Consults BOTH main heating systems — §12
|
||||
|
|
@ -6329,8 +6358,14 @@ def cert_to_inputs(
|
|||
# Q_space (kWh/month) per spec = (98c)m × (204) = (98c)m × (1 −
|
||||
# sec_frac) for single-main fixtures.
|
||||
if wh_result is not None:
|
||||
# Eq D1 Q_space is the DHW boiler's OWN space-heating load — its
|
||||
# (204)/(205) share of total — not the dwelling total (202). See
|
||||
# `_water_heating_main_space_fraction`.
|
||||
water_main_space_fraction = _water_heating_main_space_fraction(
|
||||
epc, secondary_fraction_value
|
||||
)
|
||||
space_heating_monthly_useful_kwh = tuple(
|
||||
q * (1.0 - secondary_fraction_value)
|
||||
q * water_main_space_fraction
|
||||
for q in space_heating_result.total_space_heating_monthly_kwh
|
||||
)
|
||||
hw_kwh = _apply_water_efficiency(
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ _EXPECTATIONS: tuple[_GoldenExpectation, ...] = (
|
|||
cert_number="0240-0200-5706-2365-8010",
|
||||
actual_sap=73,
|
||||
expected_sap_resid=-1,
|
||||
expected_pe_resid_kwh_per_m2=+1.6893,
|
||||
expected_co2_resid_tonnes_per_yr=+0.0815,
|
||||
expected_pe_resid_kwh_per_m2=+1.8687,
|
||||
expected_co2_resid_tonnes_per_yr=+0.0907,
|
||||
notes=(
|
||||
"Detached house, TFA 118, age J, oil boiler PCDB-listed + PV + "
|
||||
"RR on BP[0]. Mapper DOES extract sap_room_in_roof.room_in_roof_"
|
||||
|
|
@ -176,7 +176,14 @@ _EXPECTATIONS: tuple[_GoldenExpectation, ...] = (
|
|||
"two-control blend. Lowers MIT ~0.037 °C → space-heating demand "
|
||||
"falls → PE +2.1519 → +1.6893, CO2 +0.1051 → +0.0815 (both "
|
||||
"closer to zero; SAP integer 72 unchanged). Verified 1e-4 "
|
||||
"against the case-6 worksheet (87)/(90)/(98c)."
|
||||
"against the case-6 worksheet (87)/(90)/(98c). "
|
||||
"Slice S0380.206 fed Eq D1 the DHW boiler's OWN (204) space "
|
||||
"share (Main 1 = 51%) instead of the dwelling total (202) — "
|
||||
"the worksheet-validated case-6 fix that lands its (219) HW "
|
||||
"exact. For 0240 this raises HW fuel slightly → PE +1.6893 → "
|
||||
"+1.8687, CO2 +0.0815 → +0.0907 (SAP 72 unchanged). The lodged "
|
||||
"73 carries Elmhurst's own residual; case 6 is the spec "
|
||||
"authority per [[feedback-worksheet-not-api-reference]]."
|
||||
),
|
||||
),
|
||||
_GoldenExpectation(
|
||||
|
|
|
|||
|
|
@ -92,6 +92,12 @@ LINE_231_PUMPS_FANS_KWH: Final[float] = 356.0
|
|||
LINE_211_MAIN_1_FUEL_KWH: Final[float] = 7741.6458
|
||||
LINE_213_MAIN_2_FUEL_KWH: Final[float] = 6995.3106
|
||||
|
||||
# Worksheet (219) water-heating fuel (kWh/yr). The DHW boiler is Main 1
|
||||
# (WHC 901), which provides only 51% of space heating, so SAP 10.2
|
||||
# Appendix D Eq D1 weights η_winter by Main 1's (204) share — not the
|
||||
# dwelling total — when blending the monthly water-heater efficiency.
|
||||
LINE_219_HOT_WATER_FUEL_KWH: Final[float] = 4902.8601
|
||||
|
||||
# Worksheet (70) "Pumps, fans" internal-gain (W), heating-season only
|
||||
# (Jun-Sep = 0). = 10 W = the two-main-system central-heating-pump pair
|
||||
# per SAP 10.2 Table 5a note a): Main 1 ("2013 or later" → 3 W) + Main 2
|
||||
|
|
|
|||
|
|
@ -301,6 +301,23 @@ def test_case6_main_2_emitter_and_control_extracted() -> None:
|
|||
assert main_2.main_heating_control == 2110
|
||||
|
||||
|
||||
def test_section_4_hot_water_fuel_case6_match_pdf() -> None:
|
||||
"""(219) water-heating fuel for simulated case 6. The DHW boiler (Main
|
||||
1, WHC 901) provides only 51% of space heating, so SAP 10.2 Appendix D
|
||||
§D2.1(2) Equation D1 must weight η_winter by Main 1's (204) share, not
|
||||
the dwelling total (202). Pre-S0380.206 the cascade fed Eq D1 the full
|
||||
dwelling space load → over-weighted η_winter → HW −78 kWh."""
|
||||
# Arrange / Act — real cascade (the §2.4 helper skips the cylinder gate).
|
||||
ci = cert_to_inputs(_w001431_case6.build_epc())
|
||||
|
||||
# Assert
|
||||
_pin(
|
||||
ci.hot_water_kwh_per_yr,
|
||||
_w001431_case6.LINE_219_HOT_WATER_FUEL_KWH,
|
||||
"§4 (219) case6",
|
||||
)
|
||||
|
||||
|
||||
def test_section_9a_per_system_fuel_case6_match_pdf() -> None:
|
||||
"""(211)/(213) per-system space-heating fuel for simulated case 6. The
|
||||
dual oil boiler heats different parts (Main 1 radiators/2106 living,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue