mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
implementing partial cavity wall fill recommendation
This commit is contained in:
parent
847370ed39
commit
dbf5f63e44
7 changed files with 74 additions and 25 deletions
2
.idea/Model.iml
generated
2
.idea/Model.iml
generated
|
|
@ -7,7 +7,7 @@
|
|||
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (model_data)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (backend)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyNamespacePackagesService">
|
||||
|
|
|
|||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (model_data)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (backend)" project-jdk-type="Python SDK" />
|
||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from recommendations.recommendation_utils import (
|
|||
r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, update_lowest_selected_u_value,
|
||||
get_recommended_part, get_wall_u_value
|
||||
)
|
||||
from recommendations.config import PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION
|
||||
|
||||
|
||||
class WallRecommendations(Definitions):
|
||||
|
|
@ -35,14 +36,6 @@ class WallRecommendations(Definitions):
|
|||
# we still consider it as an option
|
||||
U_VALUE_ERROR = 0.01
|
||||
|
||||
# TODO: Review this value against RdSAP
|
||||
# Page 19 of rdsap here:
|
||||
# https://files.bregroup.com/bre-co-uk-file-library-copy/filelibrary/SAP/2012/RdSAP-9.93/RdSAP_2012_9.93.pdf
|
||||
# provides default U-values for solid brick walls depending on age band
|
||||
DEFAULT_U_VALUES = {
|
||||
"solid_brick": 2,
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
property_instance: Property,
|
||||
|
|
@ -113,6 +106,7 @@ class WallRecommendations(Definitions):
|
|||
is_granite_or_whinstone=self.property.walls["is_granite_or_whinstone"],
|
||||
is_sandstone_or_limestone=self.property.walls["is_sandstone_or_limestone"],
|
||||
)
|
||||
|
||||
self.estimated_u_value = u_value
|
||||
|
||||
if self.property.walls["is_solid_brick"]:
|
||||
|
|
@ -127,16 +121,13 @@ class WallRecommendations(Definitions):
|
|||
if is_cavity_wall:
|
||||
if u_value >= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
||||
# Test filling cavity
|
||||
self.find_cavity_insulation(u_value)
|
||||
|
||||
if insulation_thickness not in ["none", None]:
|
||||
raise ValueError("Implement me")
|
||||
self.find_cavity_insulation(u_value, insulation_thickness)
|
||||
|
||||
return
|
||||
|
||||
raise NotImplementedError("Not implemented yet")
|
||||
|
||||
def find_cavity_insulation(self, u_value):
|
||||
def find_cavity_insulation(self, u_value, insulation_thickness):
|
||||
"""
|
||||
This method tests different materials to fill the cavity wall, determining which
|
||||
material will give us the best U-value.
|
||||
|
|
@ -150,11 +141,15 @@ class WallRecommendations(Definitions):
|
|||
therefore we'll use 50mm as the base assumption
|
||||
|
||||
:param u_value: u_value of the starting wall
|
||||
:param insulation_thickness: describes the insulation level of the wall. If "below average", we have a partially
|
||||
filled cavity wall
|
||||
"""
|
||||
|
||||
cavity_wall_fills = [m for m in self.materials if m["type"] == "cavity_wall_insulation"]
|
||||
|
||||
cavity_width = 50
|
||||
if insulation_thickness == "below average":
|
||||
cavity_width = 50 * (1 - PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION)
|
||||
|
||||
# Test the different fill options
|
||||
lowest_selected_u_value = None
|
||||
recommendations = []
|
||||
|
|
|
|||
|
|
@ -6,3 +6,11 @@ UPGRADES_MAP = {
|
|||
'Suspended, no insulation (assumed)': 'Suspended, insulated (assumed)',
|
||||
'Solid, no insulation (assumed)': 'Solid, insulated (assumed)',
|
||||
}
|
||||
|
||||
PARTIAL_CAVITY_DESCRIPTIONS = [
|
||||
"Cavity wall, as built, partial insulation",
|
||||
"Cavity wall, partial insulation",
|
||||
]
|
||||
|
||||
# We assume that the cavity is partially filled with insulation, and is filled 25% full
|
||||
PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION = 0.25
|
||||
|
|
|
|||
|
|
@ -226,10 +226,10 @@ epc_wall_description_map = {
|
|||
"Cavity wall, as built, partial insulation": "Filled cavity",
|
||||
"Cavity wall, filled cavity": "Filled cavity",
|
||||
"Cavity wall, as built, no insulation": "Cavity as built",
|
||||
"Cavity wall, as built, insulated": "Unfilled cavity with 100 mm external or internal insulation",
|
||||
"Cavity wall, as built, insulated": "Filled cavity",
|
||||
"Cavity wall, with external insulation": "Unfilled cavity with 100 mm external or internal insulation",
|
||||
"Cavity wall, insulated": "Unfilled cavity with 100 mm external or internal insulation",
|
||||
'Cavity wall, partial insulation': "Unfilled cavity with 50 mm external or internal insulation",
|
||||
"Cavity wall, insulated": "Filled cavity",
|
||||
'Cavity wall, partial insulation': "Filled cavity",
|
||||
|
||||
"Cavity wall,": "Cavity as built", # General case of cavity wall without further details
|
||||
"Cavity wall, filled cavity and external insulation":
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from recommendations.rdsap_tables import (
|
|||
epc_wall_description_map, wall_uvalues_df, default_wall_thickness, table_s9 as s9, table_s10 as s10,
|
||||
table_s11 as s11
|
||||
)
|
||||
from recommendations.config import PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION, PARTIAL_CAVITY_DESCRIPTIONS
|
||||
|
||||
|
||||
def r_value_per_mm_to_u_value(depth_mm: int, r_value_per_mm: float):
|
||||
|
|
@ -146,7 +147,9 @@ def apply_formula_s_5_1_1(is_granite_or_whinstone, is_sandstone_or_limestone, ag
|
|||
raise ValueError("This should only be called when is_granite_or_whinstone or is_sandstone_or_limestone is True")
|
||||
|
||||
|
||||
def get_wall_u_value(clean_description, age_band, is_granite_or_whinstone, is_sandstone_or_limestone):
|
||||
def get_wall_u_value(
|
||||
clean_description, age_band, is_granite_or_whinstone, is_sandstone_or_limestone
|
||||
):
|
||||
"""
|
||||
Given some features about a wall, this function will query the wall u-value table and return the u-value
|
||||
:param clean_description: Cleaned up description of the wall from the EPC data
|
||||
|
|
@ -156,13 +159,23 @@ def get_wall_u_value(clean_description, age_band, is_granite_or_whinstone, is_sa
|
|||
:return:
|
||||
"""
|
||||
|
||||
mapped_description = epc_wall_description_map[clean_description]
|
||||
if clean_description in PARTIAL_CAVITY_DESCRIPTIONS:
|
||||
# If we have a partial cavity fill, we linearly interpolate the u-value. This isn't necessarily the perfect
|
||||
# method and how we do this should be explored, however we want to distinguish between the old
|
||||
filled_uvalue = float(wall_uvalues_df[wall_uvalues_df["Wall_type"] == "Filled cavity"][age_band].values[0])
|
||||
unfilled_uvalue = float(wall_uvalues_df[wall_uvalues_df["Wall_type"] == "Cavity as built"][age_band].values[0])
|
||||
|
||||
mapped_value = wall_uvalues_df[wall_uvalues_df["Wall_type"] == mapped_description][age_band].values[0]
|
||||
mapped_value = str(
|
||||
unfilled_uvalue - (PARTIALLY_FILLED_PERCENTAGE_ASSUMPTION * (unfilled_uvalue - filled_uvalue))
|
||||
)
|
||||
else:
|
||||
mapped_description = epc_wall_description_map[clean_description]
|
||||
|
||||
if pd.isnull(mapped_value) and "Park home" in mapped_description:
|
||||
# We don't know enough in this case so we default to 0
|
||||
return 0
|
||||
mapped_value = wall_uvalues_df[wall_uvalues_df["Wall_type"] == mapped_description][age_band].values[0]
|
||||
|
||||
if pd.isnull(mapped_value) and "Park home" in mapped_description:
|
||||
# We don't know enough in this case so we default to 0
|
||||
return 0
|
||||
|
||||
if mapped_value == "a":
|
||||
# The rdSap documentation indicateswe should use a formula to calculate the u-value
|
||||
|
|
|
|||
|
|
@ -470,3 +470,36 @@ class TestCavityWallRecommensations:
|
|||
|
||||
assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.26)
|
||||
assert np.isclose(recommender.recommendations[1]["cost"], 1250)
|
||||
|
||||
def test_fill_partial_filled_cavity(self):
|
||||
input_property = Property(id=1, postcode="F4k3", address1="123 fake street", epc_client=Mock())
|
||||
input_property.walls = {
|
||||
'original_description': 'Cavity wall, as built, partial insulation (assumed)',
|
||||
'clean_description': 'Cavity wall, as built, partial insulation',
|
||||
'thermal_transmittance': None, 'thermal_transmittance_unit': None,
|
||||
'is_cavity_wall': True, 'is_filled_cavity': False, 'is_solid_brick': False,
|
||||
'is_system_built': False, 'is_timber_frame': False, 'is_granite_or_whinstone': False,
|
||||
'is_as_built': True, 'is_cob': False, 'is_assumed': True,
|
||||
'is_sandstone_or_limestone': False, 'is_park_home': False,
|
||||
'insulation_thickness': 'below average', 'external_insulation': False,
|
||||
'internal_insulation': False
|
||||
}
|
||||
input_property.age_band = "C"
|
||||
input_property.insulation_wall_area = 50
|
||||
|
||||
recommender = WallRecommendations(
|
||||
property_instance=input_property,
|
||||
materials=cavity_wall_insulation_parts
|
||||
)
|
||||
|
||||
assert not recommender.recommendations
|
||||
|
||||
recommender.recommend()
|
||||
|
||||
assert recommender.recommendations
|
||||
assert recommender.estimated_u_value == 1.3
|
||||
assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.56)
|
||||
assert np.isclose(recommender.recommendations[0]["cost"], 1000)
|
||||
|
||||
assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.57)
|
||||
assert np.isclose(recommender.recommendations[1]["cost"], 1250)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue