From c6464801f16d72e0057cbf11205d374e09608577 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 26 Jun 2023 18:30:13 +0100 Subject: [PATCH] Added new floor recommendation --- model_data/app.py | 12 +-- .../recommendations/FloorRecommendations.py | 90 ++++++++++++++++--- 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/model_data/app.py b/model_data/app.py index 4d8bd342..c293c79f 100644 --- a/model_data/app.py +++ b/model_data/app.py @@ -123,10 +123,10 @@ def handler(): [{"address1": p.address1, **p.floor} for p in input_properties] ) - input_properties[3].data["address1"] - input_properties[3].data["postcode"] - floors_df["address1"].values[3] - floors_df["original_description"].values[3] + input_properties[4].data["address1"] + input_properties[4].data["postcode"] + floors_df["address1"].values[4] + floors_df["original_description"].values[4] df = pd.DataFrame( [ @@ -136,7 +136,9 @@ def handler(): df["property-type"].unique() from model_data.recommendations.FloorRecommendations import FloorRecommendations - self = FloorRecommendations(property_instance=input_properties[3], uvalue_estimates=uvalue_estimates) + self = FloorRecommendations(property_instance=input_properties[4], uvalue_estimates=uvalue_estimates) + self.recommendations + self.recommend() # We need to deduce a U-value for "Good" energy effieciency diff --git a/model_data/recommendations/FloorRecommendations.py b/model_data/recommendations/FloorRecommendations.py index 09d5b8e6..8cb2ba6b 100644 --- a/model_data/recommendations/FloorRecommendations.py +++ b/model_data/recommendations/FloorRecommendations.py @@ -45,7 +45,28 @@ suspended_floor_insulation_parts = [ }, ] -parts = suspended_floor_insulation_parts +solid_floor_insulation_parts = [ + { + # Example product + # https://www.insulationexpress.co.uk/floor-insulation/solid-floor-insulation/k103-100mm + # All product types here: + # https://www.insulationexpress.co.uk/floor-insulation/solid-floor-insulation?brand=7015&p=1 + # Example screed https://www.screwfix.com/p/mapei-ultraplan-3240-self-levelling-compound-25kg/4959f + "type": "solid_floor_insulation", + "description": "Rigid Insulation Foam Boards with floor screed", + "depths": [25, 50, 70, 75, 100], + "depth_unit": "mm", + "cost": None, + "cost_unit": None, + "r_value_per_mm": 0.04545454545454546, + "r_value_unit": "square_meter_kelvin_per_watt", + "thermal_conductivity": 0.052631578947368425, + "thermal_conductivity_unit": "watt_per_meter_kelvin" + }, + +] + +parts = suspended_floor_insulation_parts + solid_floor_insulation_parts class FloorRecommendations(BaseUtility): @@ -62,6 +83,10 @@ class FloorRecommendations(BaseUtility): PART_L_YEAR_CUTOFF = 2002 + FLOOR_LEVELS = { + "Ground": 0 + } + def __init__(self, property_instance: Property, uvalue_estimates: UvalueEstimations): self.property = property_instance self.uvalue_estimates = uvalue_estimates @@ -149,19 +174,20 @@ class FloorRecommendations(BaseUtility): u_value = self.property.floor["thermal_transmittance"] is_suspended = self.property.floor["is_suspended"] insulation_thickness = self.property.floor["insulation_thickness"] - - # Check which floor the property is on + is_solid = self.property.floor["is_solid"] + floor_level = self.FLOOR_LEVELS[self.property.data["floor-level"]] + property_type = self.property.data["property-type"] year_built = self.property.year_built - self.property.data["floor-energy-eff"] - self.property.data["floor-env-eff"] - - # TODO: We neeed to know if the property is ground floor or not if self.property.floor["another_property_below"]: # If there's another property below, it's likely impractical to recommend a floor upgrade return + # If the property is a flat that isn't at ground level, it's likely impractical to recommend a floor upgrade + if (floor_level != 0) and (property_type == "Flat"): + return + if u_value: if self.property.data["property-type"] != "House": raise NotImplementedError("Implement me") @@ -175,6 +201,12 @@ class FloorRecommendations(BaseUtility): # The floor is already compliant return + # For these methods, we need to know the wall material + if self.property.walls["is_solid_brick"]: + wall_type = "solid brick" + else: + raise NotImplementedError("Implement me") + if is_suspended: total_floor_area = float(self.property.data["total-floor-area"]) number_of_rooms = float(self.property.data["number-habitable-rooms"]) @@ -195,7 +227,7 @@ class FloorRecommendations(BaseUtility): floor_area=total_floor_area / num_floors, number_of_rooms=number_of_rooms / num_floors, insulation_thickness=0, - wall_type='solid brick', + wall_type=wall_type, region=region, age_band=age_band, ) @@ -203,7 +235,39 @@ class FloorRecommendations(BaseUtility): u_value = self._get_floors_uvalue_estimate() # Given the U-value, we recommend underfloor insulation - self.recommend_suspended_floor_insulation(u_value=u_value) + self.recommend_floor_insulation(u_value=u_value, parts=suspended_floor_insulation_parts) + + if is_solid: + total_floor_area = float(self.property.data["total-floor-area"]) + number_of_rooms = float(self.property.data["number-habitable-rooms"]) + + if self.property.data["property-type"] == "House": + num_floors = self._estimate_floors(total_floor_area, number_of_rooms) + elif self.property.data["property-type"] == "Flat": + num_floors = 1 + else: + raise NotImplementedError("Implement me") + + if insulation_thickness == "none": + + region_str, age_band = self.property.data["construction-age-band"].split(":") + region_str = region_str.strip() + age_band = age_band.strip() + region = self.REGION_LOOKUP[region_str] + + u_value = self._estimate_suspended_floor_u_value( + floor_area=total_floor_area / num_floors, + number_of_rooms=number_of_rooms / num_floors, + insulation_thickness=0, + wall_type=wall_type, + region=region, + age_band=age_band, + ) + else: + u_value = self._get_floors_uvalue_estimate() + + # Given the U-value, we recommend solid floor insulation options which are usually solid foam + self.recommend_floor_insulation(u_value=u_value, parts=solid_floor_insulation_parts) def _get_floors_uvalue_estimate(self): @@ -253,7 +317,7 @@ class FloorRecommendations(BaseUtility): return u_value_estimate["median_thermal_transmittance"].mean() - def recommend_suspended_floor_insulation(self, u_value): + def recommend_floor_insulation(self, u_value, parts): """ This method is tasked with estimating the impact of performing suspended floor insulation :return: @@ -274,9 +338,9 @@ class FloorRecommendations(BaseUtility): if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE: lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value) - self.recommendations.append( - get_recommended_part(part, depth, new_u_value) - ) + self.recommendations.append( + get_recommended_part(part, depth, new_u_value) + ) @staticmethod def _estimate_floors(floor_area, num_rooms):