mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Added in logic to allow both external and internal wall insulation as options. Currently lots of recommendation combinations can come through however we will trim them later and make them more relevant to the customer
This commit is contained in:
parent
9965767ae6
commit
ee91c8244b
1 changed files with 65 additions and 9 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import pint
|
||||
import re
|
||||
import itertools
|
||||
|
||||
from model_data.Property import Property
|
||||
import pandas as pd
|
||||
from copy import deepcopy
|
||||
|
||||
external_wall_insulation_parts = [
|
||||
{
|
||||
|
|
@ -184,6 +186,8 @@ class WallRecommendations:
|
|||
YEAR_WALLS_BUILT_WITH_INSULATION = 1990
|
||||
U_VALUE_UNIT = 'w/m-¦k'
|
||||
BUILDING_REGULATIONS_PART_L_MAX_U_VALUE = 0.18
|
||||
# Often cited minimum practical u-value
|
||||
DIMINISHING_RETURNS_U_VALUE = 0.15
|
||||
|
||||
# Add some error so that if, for example, a new part we recommend provides a u-value of 0.19,
|
||||
# we still consider it as an option
|
||||
|
|
@ -229,6 +233,7 @@ class WallRecommendations:
|
|||
|
||||
is_cavity_wall = self.property.walls["is_cavity_wall"]
|
||||
is_solid_brick = self.property.walls["is_solid_brick"]
|
||||
insulation_thickness = self.property.walls["insulation_thickness"]
|
||||
|
||||
if u_value:
|
||||
if self.property.walls["thermal_transmittance_unit"] != self.U_VALUE_UNIT:
|
||||
|
|
@ -252,17 +257,22 @@ class WallRecommendations:
|
|||
}
|
||||
)
|
||||
|
||||
if is_solid_brick:
|
||||
if is_solid_brick and insulation_thickness == "none":
|
||||
|
||||
# TODO: what if we recommend both internal and external wall insulation? Individually, they might not
|
||||
# get the wall to the required u-value, but together they might. We need to handle this case
|
||||
|
||||
# This is an estimated figure based on industry standards
|
||||
u_value = self.DEFAULT_U_VALUES["solid_brick"]
|
||||
|
||||
# Recommend external and internal wall insulation
|
||||
part_types = ["external_wall_insulation", "internal_wall_insulation"] if not self.in_converation_area else \
|
||||
["internal_wall_insulation"]
|
||||
ewi_parts = [
|
||||
part for part in wall_parts if part["type"] == "external_wall_insulation"
|
||||
] if not self.in_converation_area else []
|
||||
|
||||
parts = [part for part in wall_parts if part["type"] in part_types]
|
||||
for part in parts:
|
||||
iwi_parts = [part for part in wall_parts if part["type"] == "internal_wall_insulation"]
|
||||
|
||||
# Recommend external and internal wall insulation separately
|
||||
for part in ewi_parts + iwi_parts:
|
||||
|
||||
for depth in part["depths"]:
|
||||
part_u_value = self.r_value_per_mm_to_u_value(depth, part["r_value_per_mm"])
|
||||
|
|
@ -270,17 +280,63 @@ class WallRecommendations:
|
|||
_, new_u_value = self.calculate_u_value_uplift(u_value, part_u_value)
|
||||
new_u_value = round(new_u_value, 2)
|
||||
|
||||
if new_u_value < self.DIMINISHING_RETURNS_U_VALUE:
|
||||
# We don't recommend an overkill solution
|
||||
continue
|
||||
|
||||
# We allow a small tolerance for error so we don't discount the recommendation entirely
|
||||
# if it's close, since this is an estimated new u-value
|
||||
if new_u_value - self.U_VALUE_ERROR <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
||||
self.recommendations.append(
|
||||
{
|
||||
**part, "new_u_value": new_u_value,
|
||||
}
|
||||
self._get_recommended_part(part, depth, new_u_value)
|
||||
)
|
||||
|
||||
# We also can recommend both internal and external wall insulation together
|
||||
for ewi_part in ewi_parts:
|
||||
for iwi_part in iwi_parts:
|
||||
for ewi_depth, iwi_depth in itertools.product(ewi_part["depths"], iwi_part["depths"]):
|
||||
ewi_part_u_value = self.r_value_per_mm_to_u_value(ewi_depth, ewi_part["r_value_per_mm"])
|
||||
iwi_part_u_value = self.r_value_per_mm_to_u_value(iwi_depth, iwi_part["r_value_per_mm"])
|
||||
|
||||
# First calculate the new U-value after applying external wall insulation
|
||||
_, ewi_new_u_value = self.calculate_u_value_uplift(u_value, ewi_part_u_value)
|
||||
# Then calculate the new U-value after applying internal wall insulation
|
||||
_, combined_new_u_value = self.calculate_u_value_uplift(ewi_new_u_value, iwi_part_u_value)
|
||||
combined_new_u_value = round(combined_new_u_value, 2)
|
||||
|
||||
if combined_new_u_value < self.DIMINISHING_RETURNS_U_VALUE:
|
||||
# We don't recommend an overkill solution
|
||||
continue
|
||||
|
||||
# Check if the combined new U-value meets the requirement
|
||||
if combined_new_u_value - self.U_VALUE_ERROR <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
||||
# Here you might want to define a way to add both recommendations together.
|
||||
# For now, I'm adding them as separate items in the list
|
||||
|
||||
recommendation = [
|
||||
self._get_recommended_part(ewi_part, ewi_depth, combined_new_u_value),
|
||||
self._get_recommended_part(iwi_part, iwi_depth, combined_new_u_value)
|
||||
]
|
||||
self.recommendations.append(recommendation)
|
||||
|
||||
raise NotImplementedError("Not implemented yet")
|
||||
|
||||
@staticmethod
|
||||
def _get_recommended_part(part, selected_depth, new_u_value):
|
||||
"""
|
||||
Utility function to return a recommended part with the selected depth.
|
||||
:param part:
|
||||
:param selected_depth:
|
||||
:param new_u_value:
|
||||
:return:
|
||||
"""
|
||||
recommended_part = deepcopy(part)
|
||||
recommended_part["depths"] = [selected_depth]
|
||||
|
||||
return {
|
||||
**recommended_part, "new_u_value": new_u_value,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def calculate_u_value_uplift(u_value, insulation_u_value):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue