diff --git a/packages/domain/src/domain/sap/calculator.py b/packages/domain/src/domain/sap/calculator.py index 88aaa360..8f1ae621 100644 --- a/packages/domain/src/domain/sap/calculator.py +++ b/packages/domain/src/domain/sap/calculator.py @@ -346,6 +346,11 @@ def calculate_sap_from_inputs(inputs: CalculatorInputs) -> SapResult: "thermal_bridging_w_per_k": ht.thermal_bridging_w_per_k, "infiltration_ach": inputs.infiltration_ach, "infiltration_w_per_k": hlc_v, + "heat_transfer_coefficient_w_per_k": hlc, + "heat_loss_parameter_w_per_m2k": hlp, + "time_constant_h": tau_h, + "internal_gains_annual_avg_w": sum(e.internal_gains_w for e in monthly) / 12.0, + "mean_internal_temp_annual_avg_c": sum(e.internal_temp_c for e in monthly) / 12.0, } return SapResult( diff --git a/packages/domain/src/domain/sap/tests/test_calculator.py b/packages/domain/src/domain/sap/tests/test_calculator.py index a6dff041..3572674d 100644 --- a/packages/domain/src/domain/sap/tests/test_calculator.py +++ b/packages/domain/src/domain/sap/tests/test_calculator.py @@ -177,6 +177,41 @@ def test_calculate_exposes_ventilation_intermediates() -> None: ) +def test_calculate_exposes_hlc_hlp_and_annual_averages() -> None: + # Arrange — P5 trace mode: HLC (W/K), HLP (W/m²K), time constant, and + # annual-average internal gains + mean internal temperature surface on + # `intermediate`. These are the worksheet-line aggregates §7 / §13 + # depend on; the annual averages let sweep slices verify monthly-loop + # outputs without re-computing the 12-month sum themselves. + inputs = _baseline_inputs() + + # Act + result = calculate_sap_from_inputs(inputs) + + # Assert + expected_hlc = ( + inputs.heat_transmission.total_w_per_k + + inputs.infiltration_ach * inputs.dimensions.volume_m3 * 0.33 + ) + expected_hlp = expected_hlc / inputs.dimensions.total_floor_area_m2 + assert result.intermediate["heat_transfer_coefficient_w_per_k"] == pytest.approx( + expected_hlc, rel=1e-9 + ) + assert result.intermediate["heat_loss_parameter_w_per_m2k"] == pytest.approx( + expected_hlp, rel=1e-9 + ) + assert result.intermediate["time_constant_h"] > 0.0 + + avg_gains = sum(e.internal_gains_w for e in result.monthly) / 12.0 + avg_mit = sum(e.internal_temp_c for e in result.monthly) / 12.0 + assert result.intermediate["internal_gains_annual_avg_w"] == pytest.approx( + avg_gains, rel=1e-9 + ) + assert result.intermediate["mean_internal_temp_annual_avg_c"] == pytest.approx( + avg_mit, rel=1e-9 + ) + + def test_higher_main_heating_efficiency_reduces_fuel_use() -> None: # Arrange — Direction check: doubling the boiler efficiency must halve # the main-heating fuel kWh, holding everything else constant.