From f68798818029f4578e71616489a57a8ad0a80193 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Sun, 22 Jun 2025 17:11:45 +0100 Subject: [PATCH] Adding logic for a heat pump when the property is large enough and handling an edge case for dual heating --- backend/Property.py | 7 +++++++ backend/app/assumptions.py | 3 +++ recommendations/Costs.py | 4 ++-- recommendations/HeatingRecommender.py | 14 ++++++++++++++ sfr/principal_pitch/1_prepare_data.py | 3 ++- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/backend/Property.py b/backend/Property.py index 91c1265a..5b241bdc 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -1233,6 +1233,13 @@ class Property: if "air_source_heat_pump" not in measures: return False + # If we have a house over a floor area threshold, we recommend an ASHP + if ( + self.data["property-type"] in ["House", "Bungalow"] and + self.floor_area > assumptions.ASHP_FLOOR_AREA_THRESHOLD + ): + return True + suitable_house = self.data["property-type"] == "House" and self.data["built-form"] in [ "Detached", "Semi-Detached", "End-Terrace", ] diff --git a/backend/app/assumptions.py b/backend/app/assumptions.py index f1090ef3..95271903 100644 --- a/backend/app/assumptions.py +++ b/backend/app/assumptions.py @@ -65,3 +65,6 @@ DESCRIPTIONS_TO_FUEL_TYPES = { measures_needing_ventilation = [ "internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation" ] + +# If we have a property beyond this size, we assume it's likely large enough to have an ASHP +ASHP_FLOOR_AREA_THRESHOLD = 120 # m2 diff --git a/recommendations/Costs.py b/recommendations/Costs.py index 96eb5d0e..ee384b22 100644 --- a/recommendations/Costs.py +++ b/recommendations/Costs.py @@ -871,10 +871,10 @@ class Costs: if needs_cylinder: # 1000 is the cost of a new hot water cylinder - total_cost = 1200 * number_heated_rooms + 1000 + total_cost = 1300 * number_heated_rooms + 1000 else: # 500 is the cost of a dual immersion heater - a rough estimate - total_cost = 1200 * number_heated_rooms + 500 + total_cost = 1300 * number_heated_rooms + 500 subtotal_before_vat = total_cost / (1 + self.VAT_RATE) vat = total_cost - subtotal_before_vat diff --git a/recommendations/HeatingRecommender.py b/recommendations/HeatingRecommender.py index a776047b..9c44fe4a 100644 --- a/recommendations/HeatingRecommender.py +++ b/recommendations/HeatingRecommender.py @@ -61,6 +61,19 @@ class HeatingRecommender: 'Electric underfloor heating, electric storage heaters': { # For this, we would recommend a heat pump "dual": None + }, + "Room heaters, electric, boiler and radiators, mains gas": { + "hhr": { + "mainheating_description": "Electric storage heaters, radiators", + "recommendation_description": "Install high heat retention electric storage heaters.", + "controls_prefix": "" + }, + "boiler": { + "mainheating_description": "Boiler and radiators, mains gas", + "recommendation_description": "Upgrade to a new condensing boiler.", + "controls_suffix": "" + }, + "dual": None } } @@ -932,6 +945,7 @@ class HeatingRecommender: return recommendations self.heating_recommendations.extend(recommendations) + return None @staticmethod def estimate_boiler_size(property_type, built_form, floor_area, floor_height, num_heated_rooms): diff --git a/sfr/principal_pitch/1_prepare_data.py b/sfr/principal_pitch/1_prepare_data.py index 8e799b9e..43002b88 100644 --- a/sfr/principal_pitch/1_prepare_data.py +++ b/sfr/principal_pitch/1_prepare_data.py @@ -71,6 +71,7 @@ body = { "ashp_cop": 3.5, # This is new - when optimising, we drop scores by a few points to account for SAP 10 "simulate_sap_10": True, - "exclusions": ["external_wall_insulation"] + "exclusions": ["external_wall_insulation"], + "required_measures": ["cavity_wall_insulation", "loft_insulation"] } print(body)