diff --git a/domain/building_geometry.py b/domain/building_geometry.py new file mode 100644 index 00000000..a76e0468 --- /dev/null +++ b/domain/building_geometry.py @@ -0,0 +1,33 @@ +"""Building geometry derived purely from an EpcPropertyData. + +Reusable outside the SAP calculator (e.g. for Modelling cost quantities). +Today this re-derives the heat-loss wall area; the calculator computes the +same quantity inline (`heat_transmission._part_geometry`). A later, calculator- +branch-coordinated refactor should DRY the two onto this module so there is a +single source of truth. See the project memory on calculator geometry. +""" + +from datatypes.epc.domain.epc_property_data import ( + BuildingPartIdentifier, + EpcPropertyData, +) + + +def gross_heat_loss_wall_area( + epc: EpcPropertyData, identifier: BuildingPartIdentifier +) -> float: + """Gross external wall area of one building part, in m^2: the sum over its + storeys of heat-loss perimeter x room height. This is the heat-loss area + (party walls are excluded — they are not on the heat-loss perimeter); it is + not netted of window/door openings. + """ + part = next( + candidate + for candidate in epc.sap_building_parts + if candidate.identifier is identifier + ) + area = sum( + fd.heat_loss_perimeter_m * fd.room_height_m + for fd in part.sap_floor_dimensions + ) + return round(area, 2) diff --git a/tests/domain/test_building_geometry.py b/tests/domain/test_building_geometry.py new file mode 100644 index 00000000..816e334d --- /dev/null +++ b/tests/domain/test_building_geometry.py @@ -0,0 +1,22 @@ +"""Behaviour of shared building geometry derived from EpcPropertyData — +reusable outside the SAP calculator (e.g. for Modelling cost quantities).""" + +from datatypes.epc.domain.epc_property_data import BuildingPartIdentifier +from domain.building_geometry import gross_heat_loss_wall_area +from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( + build_epc, +) + + +def test_gross_heat_loss_wall_area_sums_perimeter_times_height_per_storey() -> None: + # Arrange + # 000490 MAIN: floor 0 (perimeter 7.42 m x height 2.95 m) + floor 1 + # (7.42 m x 3.24 m) = 21.889 + 24.0408 = 45.93 m^2. Party walls are + # excluded by construction (heat-loss perimeter, not total perimeter). + epc = build_epc() + + # Act + area: float = gross_heat_loss_wall_area(epc, BuildingPartIdentifier.MAIN) + + # Assert + assert abs(area - 45.93) <= 0.01