mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
P5.13: SapResult.intermediate exposes per-end-use CO2 breakdown
Closes the second §11-sketch gap noted in HANDOVER_SYSTEMATIC_REVIEW
("primary energy AND CO2 per end-use"). Lifts the single co2 = total
× factor expression into five named locals (main_heating, secondary,
hot_water, pumps_fans, lighting) and exposes them on `intermediate`.
The five components sum exactly to the top-level co2_kg_per_yr — no
PV deduction in the current implementation.
This commit is contained in:
parent
f09e83b6a1
commit
0fa39e859c
2 changed files with 57 additions and 2 deletions
|
|
@ -328,7 +328,19 @@ def calculate_sap_from_inputs(inputs: CalculatorInputs) -> SapResult:
|
|||
ecf = energy_cost_factor(total_cost_gbp=total_cost, total_floor_area_m2=tfa)
|
||||
sap_int = sap_rating_integer(ecf=ecf)
|
||||
sap_cont = sap_rating(ecf=ecf)
|
||||
co2 = delivered_fuel_kwh * inputs.co2_factor_kg_per_kwh
|
||||
co2_factor = inputs.co2_factor_kg_per_kwh
|
||||
main_heating_co2 = main_fuel_kwh * co2_factor
|
||||
secondary_heating_co2 = secondary_fuel_kwh * co2_factor
|
||||
hot_water_co2 = inputs.hot_water_kwh_per_yr * co2_factor
|
||||
pumps_fans_co2 = inputs.pumps_fans_kwh_per_yr * co2_factor
|
||||
lighting_co2 = inputs.lighting_kwh_per_yr * co2_factor
|
||||
co2 = (
|
||||
main_heating_co2
|
||||
+ secondary_heating_co2
|
||||
+ hot_water_co2
|
||||
+ pumps_fans_co2
|
||||
+ lighting_co2
|
||||
)
|
||||
|
||||
space_heating_primary_kwh = (
|
||||
main_fuel_kwh + secondary_fuel_kwh
|
||||
|
|
@ -379,7 +391,12 @@ def calculate_sap_from_inputs(inputs: CalculatorInputs) -> SapResult:
|
|||
"ecf": ecf,
|
||||
"deflator": ENERGY_COST_DEFLATOR,
|
||||
"delivered_fuel_kwh_per_yr": delivered_fuel_kwh,
|
||||
"co2_factor_kg_per_kwh": inputs.co2_factor_kg_per_kwh,
|
||||
"co2_factor_kg_per_kwh": co2_factor,
|
||||
"main_heating_co2_kg_per_yr": main_heating_co2,
|
||||
"secondary_heating_co2_kg_per_yr": secondary_heating_co2,
|
||||
"hot_water_co2_kg_per_yr": hot_water_co2,
|
||||
"pumps_fans_co2_kg_per_yr": pumps_fans_co2,
|
||||
"lighting_co2_kg_per_yr": lighting_co2,
|
||||
"space_heating_pe_kwh_per_m2": space_heating_primary_kwh / tfa if tfa > 0 else 0.0,
|
||||
"hot_water_pe_kwh_per_m2": hot_water_primary_kwh / tfa if tfa > 0 else 0.0,
|
||||
"other_pe_kwh_per_m2": other_primary_kwh / tfa if tfa > 0 else 0.0,
|
||||
|
|
|
|||
|
|
@ -352,6 +352,44 @@ def test_calculate_exposes_primary_energy_breakdown() -> None:
|
|||
)
|
||||
|
||||
|
||||
def test_calculate_exposes_per_end_use_co2() -> None:
|
||||
# Arrange — P5 trace mode: §11 sketch lists "primary energy AND CO2
|
||||
# per end-use". The calculator applies a single co2_factor_kg_per_kwh
|
||||
# to total delivered fuel (no PV deduction on CO2 in the current
|
||||
# implementation), so per-end-use CO2 is fuel_kwh × factor and the
|
||||
# five components sum exactly to the top-level co2_kg_per_yr.
|
||||
inputs = _baseline_inputs()
|
||||
|
||||
# Act
|
||||
result = calculate_sap_from_inputs(inputs)
|
||||
|
||||
# Assert
|
||||
factor = inputs.co2_factor_kg_per_kwh
|
||||
assert result.intermediate["main_heating_co2_kg_per_yr"] == pytest.approx(
|
||||
result.main_heating_fuel_kwh_per_yr * factor, rel=1e-9
|
||||
)
|
||||
assert result.intermediate["secondary_heating_co2_kg_per_yr"] == pytest.approx(
|
||||
result.secondary_heating_fuel_kwh_per_yr * factor, rel=1e-9
|
||||
)
|
||||
assert result.intermediate["hot_water_co2_kg_per_yr"] == pytest.approx(
|
||||
result.hot_water_kwh_per_yr * factor, rel=1e-9
|
||||
)
|
||||
assert result.intermediate["pumps_fans_co2_kg_per_yr"] == pytest.approx(
|
||||
result.pumps_fans_kwh_per_yr * factor, rel=1e-9
|
||||
)
|
||||
assert result.intermediate["lighting_co2_kg_per_yr"] == pytest.approx(
|
||||
result.lighting_kwh_per_yr * factor, rel=1e-9
|
||||
)
|
||||
breakdown_sum = (
|
||||
result.intermediate["main_heating_co2_kg_per_yr"]
|
||||
+ result.intermediate["secondary_heating_co2_kg_per_yr"]
|
||||
+ result.intermediate["hot_water_co2_kg_per_yr"]
|
||||
+ result.intermediate["pumps_fans_co2_kg_per_yr"]
|
||||
+ result.intermediate["lighting_co2_kg_per_yr"]
|
||||
)
|
||||
assert breakdown_sum == pytest.approx(result.co2_kg_per_yr, rel=1e-9)
|
||||
|
||||
|
||||
def test_calculate_exposes_pv_export_credit() -> None:
|
||||
# Arrange — P5 trace mode: total_fuel_cost_gbp = sum(per-end-use
|
||||
# costs) − pv_export_credit, floored at 0. The PV credit is the only
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue