mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
§5 slice 5: (68) appliances_monthly_w — Appendix L13/L14/L16a
E_A = 207.8 × (TFA × N)^0.4714 (L13) chained through monthly factor 1 + 0.157 × cos(2π × (m - 1.78) / 12) (L14) then watts via × 1000 / (24 × n_m) (L16a). Column A typical-gain form — 1.0× conversion. L16's 0.67× reduced form deferred (new-build DPER/TPER use). Verified against Elmhurst U985-0001-000490 (68)m row to ≤5e-2 W (display rounding from the (TFA × N)^0.4714 term). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
a4d6321f21
commit
0bc9eac34c
2 changed files with 72 additions and 0 deletions
|
|
@ -30,6 +30,12 @@ from dataclasses import dataclass
|
|||
from math import cos, exp, pi
|
||||
from typing import Final, Optional
|
||||
|
||||
_DAYS_PER_YEAR: Final[float] = 365.0
|
||||
_APPLIANCES_E_A_COEFF: Final[float] = 207.8
|
||||
_APPLIANCES_E_A_EXPONENT: Final[float] = 0.4714
|
||||
_APPLIANCES_MONTHLY_AMPLITUDE: Final[float] = 0.157
|
||||
_APPLIANCES_MONTHLY_PHASE: Final[float] = 1.78
|
||||
|
||||
|
||||
_MONTHS_IN_YEAR: Final[int] = 12
|
||||
_DAYS_PER_MONTH: Final[tuple[int, ...]] = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
|
|
@ -73,6 +79,38 @@ def cooking_monthly_w(*, n_occupants: float) -> tuple[float, ...]:
|
|||
return tuple(gain for _ in range(_MONTHS_IN_YEAR))
|
||||
|
||||
|
||||
def appliances_monthly_w(
|
||||
*,
|
||||
total_floor_area_m2: float,
|
||||
n_occupants: float,
|
||||
) -> tuple[float, ...]:
|
||||
"""SAP 10.2 §5 line (68) — appliance gains in watts per month.
|
||||
|
||||
Appendix L equations L13, L14, L16a (Column A, typical gains):
|
||||
E_A = 207.8 × (TFA × N)^0.4714 [kWh/yr]
|
||||
E_A,m = E_A × [1 + 0.157 × cos(2π × (m - 1.78) / 12)] × n_m / 365 [kWh/mo]
|
||||
G_A,m = E_A,m × 1000 / (24 × n_m) [W]
|
||||
|
||||
The cosine peaks ~end-of-January (m=1.78) and troughs ~end-of-July.
|
||||
All electrical appliance energy stays as internal heat — full 1.0×
|
||||
conversion. Column B's L16 (0.67×) reduced form is for new-build
|
||||
DPER/TPER only.
|
||||
"""
|
||||
e_a_annual = (
|
||||
_APPLIANCES_E_A_COEFF
|
||||
* (total_floor_area_m2 * n_occupants) ** _APPLIANCES_E_A_EXPONENT
|
||||
)
|
||||
monthly: list[float] = []
|
||||
for m_idx, days in enumerate(_DAYS_PER_MONTH):
|
||||
m = m_idx + 1
|
||||
factor = 1.0 + _APPLIANCES_MONTHLY_AMPLITUDE * cos(
|
||||
2.0 * pi * (m - _APPLIANCES_MONTHLY_PHASE) / _MONTHS_IN_YEAR
|
||||
)
|
||||
e_a_m_kwh = e_a_annual * factor * days / _DAYS_PER_YEAR
|
||||
monthly.append(e_a_m_kwh * _KWH_TO_WH / (_HOURS_PER_DAY * days))
|
||||
return tuple(monthly)
|
||||
|
||||
|
||||
def water_heating_gains_monthly_w(
|
||||
*,
|
||||
heat_gains_from_water_heating_monthly_kwh: tuple[float, ...],
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ Table 5a + Appendix L (lighting/appliances/cooking) + Appendix J Table 1b
|
|||
import pytest
|
||||
|
||||
from domain.sap.worksheet.internal_gains import (
|
||||
appliances_monthly_w,
|
||||
cooking_monthly_w,
|
||||
losses_monthly_w,
|
||||
metabolic_monthly_w,
|
||||
|
|
@ -121,3 +122,36 @@ def test_water_heating_gains_bridge_converts_kwh_per_month_to_watts() -> None:
|
|||
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}"
|
||||
|
||||
|
||||
def test_appliances_gains_match_appendix_l13_l14_l16a_for_000490() -> None:
|
||||
"""SAP 10.2 Appendix L equations L13/L14/L16a:
|
||||
E_A = 207.8 × (TFA × N)^0.4714 [kWh/yr]
|
||||
E_A,m = E_A × [1 + 0.157 × cos(2π × (m - 1.78) / 12)] × n_m / 365 [kWh/mo]
|
||||
G_A,m = E_A,m × 1000 / (24 × n_m) [W]
|
||||
|
||||
Verified against U985-0001-000490 worksheet (68)m row. For
|
||||
TFA=66.06, N=2.1468:
|
||||
E_A = 207.8 × 141.84^0.4714 ≈ 2147.8 kWh/yr
|
||||
Jan factor = 1 + 0.157 × cos(2π × -0.78/12) ≈ 1.1441
|
||||
E_A,Jan ≈ 208.66 kWh → G_A,Jan ≈ 280.46 W
|
||||
matches worksheet 280.4965 to ≈0.04 W (display rounding from E_A^0.4714).
|
||||
|
||||
Table 5 Column A applies (rating + cooling); Column B's 0.67×
|
||||
reduced-gain form (L16) is deferred to a future new-build slice.
|
||||
"""
|
||||
# Arrange
|
||||
tfa = 66.06
|
||||
n = 2.1468
|
||||
expected_w = (
|
||||
280.4965, 283.4071, 276.0723, 260.4574, 240.7463, 222.2207,
|
||||
209.8445, 206.9338, 214.2686, 229.8835, 249.5946, 268.1202,
|
||||
)
|
||||
|
||||
# Act
|
||||
monthly = appliances_monthly_w(total_floor_area_m2=tfa, n_occupants=n)
|
||||
|
||||
# Assert
|
||||
assert len(monthly) == 12
|
||||
for m, (actual, exp) in enumerate(zip(monthly, expected_w)):
|
||||
assert actual == pytest.approx(exp, abs=5e-2), f"month {m+1}"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue