mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
§5 slice 8: (73) total_internal_gains_monthly_w + InternalGainsResult
Closes the §5 leaf-function surface:
- total_internal_gains_monthly_w sums (66) + (67) + (68) + (69)
+ (70) + (71) + (72) element-wise. (71) carries negative sign so the
losses term subtracts.
- InternalGainsResult frozen dataclass bundles all 7 line refs plus the
total as 12-tuples — the typed payload returned by the orchestrator.
Verified against Elmhurst U985-0001-000490 (73)m to ≤1e-2 W/month.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f77229e4b4
commit
53aba1332e
2 changed files with 119 additions and 0 deletions
|
|
@ -297,6 +297,57 @@ def pumps_fans_monthly_w(
|
|||
)
|
||||
|
||||
|
||||
def total_internal_gains_monthly_w(
|
||||
*,
|
||||
metabolic_monthly_w: tuple[float, ...],
|
||||
lighting_monthly_w: tuple[float, ...],
|
||||
appliances_monthly_w: tuple[float, ...],
|
||||
cooking_monthly_w: tuple[float, ...],
|
||||
pumps_fans_monthly_w: tuple[float, ...],
|
||||
losses_monthly_w: tuple[float, ...],
|
||||
water_heating_gains_monthly_w: tuple[float, ...],
|
||||
) -> tuple[float, ...]:
|
||||
"""SAP10.2 §5 line (73) — total internal gains.
|
||||
|
||||
(73)m = (66)m + (67)m + (68)m + (69)m + (70)m + (71)m + (72)m
|
||||
|
||||
Pure element-wise sum across the seven gain streams. (71)m carries a
|
||||
negative sign (losses) so the contribution is a subtraction.
|
||||
"""
|
||||
return tuple(
|
||||
m + l + a + c + p + s + w
|
||||
for m, l, a, c, p, s, w in zip(
|
||||
metabolic_monthly_w,
|
||||
lighting_monthly_w,
|
||||
appliances_monthly_w,
|
||||
cooking_monthly_w,
|
||||
pumps_fans_monthly_w,
|
||||
losses_monthly_w,
|
||||
water_heating_gains_monthly_w,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class InternalGainsResult:
|
||||
"""SAP10.2 §5 line refs (66)..(73), each a 12-tuple of watts per month.
|
||||
|
||||
Returned by `internal_gains_from_cert`. Downstream §6/§7/§9 calculators
|
||||
consume `total_internal_gains_monthly_w` directly; the per-line tuples
|
||||
are exposed for worksheet conformance + audit. Field names mirror the
|
||||
SAP10.2 line refs.
|
||||
"""
|
||||
|
||||
metabolic_monthly_w: tuple[float, ...] # line (66)
|
||||
lighting_monthly_w: tuple[float, ...] # line (67)
|
||||
appliances_monthly_w: tuple[float, ...] # line (68)
|
||||
cooking_monthly_w: tuple[float, ...] # line (69)
|
||||
pumps_fans_monthly_w: tuple[float, ...] # line (70)
|
||||
losses_monthly_w: tuple[float, ...] # line (71)
|
||||
water_heating_gains_monthly_w: tuple[float, ...] # line (72)
|
||||
total_internal_gains_monthly_w: tuple[float, ...] # line (73)
|
||||
|
||||
|
||||
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 (
|
||||
InternalGainsResult,
|
||||
PumpDateCategory,
|
||||
appliances_monthly_w,
|
||||
balanced_mv_no_hr_fan_w,
|
||||
|
|
@ -26,6 +27,7 @@ from domain.sap.worksheet.internal_gains import (
|
|||
metabolic_monthly_w,
|
||||
piv_fan_w,
|
||||
pumps_fans_monthly_w,
|
||||
total_internal_gains_monthly_w,
|
||||
warm_air_heating_fan_w,
|
||||
water_heating_gains_monthly_w,
|
||||
)
|
||||
|
|
@ -344,3 +346,69 @@ def test_heat_interface_unit_converts_kwh_per_day_to_constant_watts() -> None:
|
|||
|
||||
# Assert
|
||||
assert w == pytest.approx(20.0, abs=1e-9)
|
||||
|
||||
|
||||
def test_total_internal_gains_sums_seven_components_per_month_for_000490() -> None:
|
||||
"""SAP10.2 §5 line (73): G_total,m = G_M + G_L + G_A + G_C + G_pumps
|
||||
+ G_losses + G_WH per month. (71) is negative — net subtraction.
|
||||
|
||||
Verified against Elmhurst U985-0001-000490 worksheet (73)m row.
|
||||
"""
|
||||
# Arrange — component tuples from the 000490 worksheet rows (66)..(72)
|
||||
metabolic = (128.8087,) * 12
|
||||
lighting = (24.2665, 21.5533, 17.5283, 13.2701, 9.9195, 8.3745,
|
||||
9.0489, 11.7621, 15.7871, 20.0454, 23.3959, 24.9410)
|
||||
appliances = (280.4965, 283.4071, 276.0723, 260.4574, 240.7463, 222.2207,
|
||||
209.8445, 206.9338, 214.2686, 229.8835, 249.5946, 268.1202)
|
||||
cooking = (50.0277,) * 12
|
||||
pumps = (7.0, 7.0, 7.0, 7.0, 7.0, 0.0, 0.0, 0.0, 0.0, 7.0, 7.0, 7.0)
|
||||
losses = (-85.8725,) * 12
|
||||
water_heating = (101.0798, 98.8663, 94.6647, 85.5412, 79.9343, 74.0821,
|
||||
70.5249, 73.5203, 77.0253, 83.5192, 92.2698, 99.9197)
|
||||
expected_total = (
|
||||
505.8067, 503.7906, 488.2293, 459.2325, 430.5641, 397.6412,
|
||||
382.3822, 385.1801, 400.0449, 433.4120, 465.2242, 492.9448,
|
||||
)
|
||||
|
||||
# Act
|
||||
total = total_internal_gains_monthly_w(
|
||||
metabolic_monthly_w=metabolic,
|
||||
lighting_monthly_w=lighting,
|
||||
appliances_monthly_w=appliances,
|
||||
cooking_monthly_w=cooking,
|
||||
pumps_fans_monthly_w=pumps,
|
||||
losses_monthly_w=losses,
|
||||
water_heating_gains_monthly_w=water_heating,
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert len(total) == 12
|
||||
for m, (actual, exp) in enumerate(zip(total, expected_total)):
|
||||
assert actual == pytest.approx(exp, abs=1e-2), f"month {m+1}"
|
||||
|
||||
|
||||
def test_internal_gains_result_dataclass_holds_all_seven_lines_plus_total() -> None:
|
||||
"""InternalGainsResult bundles every line (66)..(73) as a 12-tuple so
|
||||
downstream §6/§7/§9 callers receive a single typed payload from the
|
||||
orchestrator. Field names mirror the worksheet line refs."""
|
||||
# Arrange
|
||||
zeros = (0.0,) * 12
|
||||
|
||||
# Act
|
||||
result = InternalGainsResult(
|
||||
metabolic_monthly_w=zeros,
|
||||
lighting_monthly_w=zeros,
|
||||
appliances_monthly_w=zeros,
|
||||
cooking_monthly_w=zeros,
|
||||
pumps_fans_monthly_w=zeros,
|
||||
losses_monthly_w=zeros,
|
||||
water_heating_gains_monthly_w=zeros,
|
||||
total_internal_gains_monthly_w=zeros,
|
||||
)
|
||||
|
||||
# Assert — every field is a 12-tuple
|
||||
assert all(len(getattr(result, f)) == 12 for f in (
|
||||
"metabolic_monthly_w", "lighting_monthly_w", "appliances_monthly_w",
|
||||
"cooking_monthly_w", "pumps_fans_monthly_w", "losses_monthly_w",
|
||||
"water_heating_gains_monthly_w", "total_internal_gains_monthly_w",
|
||||
))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue