mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
§5 slice 4: (72) water_heating_gains_monthly_w — bridge from §4 (65)m
Pure unit conversion: G_WH,m = 1000 × (65)m / (n_m × 24). The §4 heat_gains_from_water_heating_monthly_kwh output already encodes the 25%/80% spec-recovery factors for delivered-heat vs pipe-side losses; this bridge just lands the kWh/month into watts for the §5 sum. Verified against Elmhurst U985-0001-000490 (72)m row — exact to 4 d.p. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
984a5b18d6
commit
a4d6321f21
2 changed files with 54 additions and 0 deletions
|
|
@ -32,6 +32,9 @@ from typing import Final, Optional
|
|||
|
||||
|
||||
_MONTHS_IN_YEAR: Final[int] = 12
|
||||
_DAYS_PER_MONTH: Final[tuple[int, ...]] = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
_HOURS_PER_DAY: Final[float] = 24.0
|
||||
_KWH_TO_WH: Final[float] = 1000.0
|
||||
_METABOLIC_GAIN_W_PER_OCCUPANT_COL_A: Final[float] = 60.0
|
||||
_LOSSES_W_PER_OCCUPANT_COL_A: Final[float] = -40.0
|
||||
_COOKING_W_BASE_COL_A: Final[float] = 35.0
|
||||
|
|
@ -70,6 +73,23 @@ def cooking_monthly_w(*, n_occupants: float) -> tuple[float, ...]:
|
|||
return tuple(gain for _ in range(_MONTHS_IN_YEAR))
|
||||
|
||||
|
||||
def water_heating_gains_monthly_w(
|
||||
*,
|
||||
heat_gains_from_water_heating_monthly_kwh: tuple[float, ...],
|
||||
) -> tuple[float, ...]:
|
||||
"""SAP 10.2 §5 line (72) — water-heating contribution to internal gains.
|
||||
|
||||
Table 5 row "Water heating": G_WH,m = 1000 × (65)m / (n_m × 24). Pure
|
||||
unit conversion from §4 line (65)m (kWh/month) to watts. (65)m itself
|
||||
already encodes the 25%/80% spec-recovery factors for delivered-heat
|
||||
vs pipe-side losses (see §4 heat_gains_from_water_heating_monthly_kwh).
|
||||
"""
|
||||
return tuple(
|
||||
kwh * _KWH_TO_WH / (days * _HOURS_PER_DAY)
|
||||
for kwh, days in zip(heat_gains_from_water_heating_monthly_kwh, _DAYS_PER_MONTH)
|
||||
)
|
||||
|
||||
|
||||
_METABOLIC_W_PER_OCCUPANT: Final[float] = 60.0
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ from domain.sap.worksheet.internal_gains import (
|
|||
cooking_monthly_w,
|
||||
losses_monthly_w,
|
||||
metabolic_monthly_w,
|
||||
water_heating_gains_monthly_w,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -87,3 +88,36 @@ def test_cooking_gains_match_table_5_col_a_formula() -> None:
|
|||
assert len(monthly) == 12
|
||||
for m, value in enumerate(monthly):
|
||||
assert value == pytest.approx(35.0 + 7.0 * n, abs=1e-9), f"month {m+1}"
|
||||
|
||||
|
||||
def test_water_heating_gains_bridge_converts_kwh_per_month_to_watts() -> None:
|
||||
"""SAP 10.2 §5 line (72) — water-heating contribution to internal gains.
|
||||
|
||||
Table 5 row "Water heating": G_WH,m = 1000 × (65)m / (n_m × 24) where
|
||||
(65)m is the §4 line "Heat gains from water heating" in kWh/month
|
||||
and n_m is days in month m. Pure unit conversion: kWh/month → W.
|
||||
|
||||
Verified against the Elmhurst U985-0001-000490 worksheet:
|
||||
(65) Jan = 75.2034 kWh/month
|
||||
(72) Jan = 75.2034 × 1000 / (24 × 31) = 101.0798 W
|
||||
matches the worksheet (72)m row to 4 d.p.
|
||||
"""
|
||||
# Arrange — 000490's full LINE_65_M tuple feeds the bridge.
|
||||
heat_gains_kwh = (
|
||||
75.2034, 66.4381, 70.4305, 61.5896, 59.4711, 53.3391,
|
||||
52.4705, 54.6991, 55.4582, 62.1383, 66.4342, 74.3403,
|
||||
)
|
||||
expected_w = (
|
||||
101.0798, 98.8663, 94.6647, 85.5412, 79.9343, 74.0821,
|
||||
70.5249, 73.5203, 77.0253, 83.5192, 92.2698, 99.9197,
|
||||
)
|
||||
|
||||
# Act
|
||||
monthly = water_heating_gains_monthly_w(
|
||||
heat_gains_from_water_heating_monthly_kwh=heat_gains_kwh,
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert len(monthly) == 12
|
||||
for m, (actual, exp) in enumerate(zip(monthly, expected_w)):
|
||||
assert actual == pytest.approx(exp, abs=1e-3), f"month {m+1}"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue