mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
added simulation for secondary heating
This commit is contained in:
parent
61584a6320
commit
3ecd7a9742
5 changed files with 102 additions and 14 deletions
|
|
@ -456,7 +456,9 @@ class Property:
|
||||||
"double glazing installed during or after 2002"
|
"double glazing installed during or after 2002"
|
||||||
)
|
)
|
||||||
|
|
||||||
if recommendation["type"] in ["heating", "hot_water_tank_insulation", "heating_control"]:
|
if recommendation["type"] in [
|
||||||
|
"heating", "hot_water_tank_insulation", "heating_control", "secondary_heating"
|
||||||
|
]:
|
||||||
# We update the data, as defined in the recommendaton
|
# We update the data, as defined in the recommendaton
|
||||||
|
|
||||||
simulation_config = recommendation["simulation_config"]
|
simulation_config = recommendation["simulation_config"]
|
||||||
|
|
@ -477,7 +479,7 @@ class Property:
|
||||||
"loft_insulation", "room_roof_insulation", "flat_roof_insulation",
|
"loft_insulation", "room_roof_insulation", "flat_roof_insulation",
|
||||||
"solid_floor_insulation", "suspended_floor_insulation", "exposed_floor_insulation",
|
"solid_floor_insulation", "suspended_floor_insulation", "exposed_floor_insulation",
|
||||||
"windows_glazing", "solar_pv", "heating", "hot_water_tank_insulation",
|
"windows_glazing", "solar_pv", "heating", "hot_water_tank_insulation",
|
||||||
"heating_control",
|
"heating_control", "secondary_heating"
|
||||||
]:
|
]:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Implement me, given type %s" % recommendation["type"]
|
"Implement me, given type %s" % recommendation["type"]
|
||||||
|
|
|
||||||
|
|
@ -1104,6 +1104,28 @@ class Costs:
|
||||||
"labour_days": labour_days,
|
"labour_days": labour_days,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def heater_removal(self, n_rooms):
|
||||||
|
"""
|
||||||
|
Estimates the costs of removal of heaters, including the redecoration costs of the space behind the heater
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
removal_cost = ROOM_HEATER_REMOVAL_COST * n_rooms
|
||||||
|
removal_labour_hours = ROOM_HEATER_REMOVAL_LABOUR_HOURS * n_rooms
|
||||||
|
|
||||||
|
vat = removal_cost * self.VAT_RATE
|
||||||
|
|
||||||
|
subtotal_before_vat = removal_cost
|
||||||
|
total_cost = subtotal_before_vat + vat
|
||||||
|
|
||||||
|
return {
|
||||||
|
"total": total_cost,
|
||||||
|
"subtotal": subtotal_before_vat,
|
||||||
|
"vat": vat,
|
||||||
|
"labour_hours": removal_labour_hours,
|
||||||
|
"labour_days": np.ceil(removal_labour_hours / 8),
|
||||||
|
}
|
||||||
|
|
||||||
def boiler(self, is_combi, size, exising_room_heaters, n_heated_rooms):
|
def boiler(self, is_combi, size, exising_room_heaters, n_heated_rooms):
|
||||||
"""
|
"""
|
||||||
Based on a basic estimate of median value £2600 to install a low carbon combi boiler
|
Based on a basic estimate of median value £2600 to install a low carbon combi boiler
|
||||||
|
|
@ -1114,6 +1136,7 @@ class Costs:
|
||||||
# The unit cost is the cost without VAT
|
# The unit cost is the cost without VAT
|
||||||
# We now need to estimate the cost of the works
|
# We now need to estimate the cost of the works
|
||||||
labour_days = 2
|
labour_days = 2
|
||||||
|
labour_hours = labour_days * 8
|
||||||
labour_rate = 500
|
labour_rate = 500
|
||||||
|
|
||||||
# Average cost of installation is 1 (maybe 2days) at £300 per day
|
# Average cost of installation is 1 (maybe 2days) at £300 per day
|
||||||
|
|
@ -1123,26 +1146,26 @@ class Costs:
|
||||||
# Add contingency and preliminaries
|
# Add contingency and preliminaries
|
||||||
labour_cost = labour_cost * (1 + self.CONTINGENCY + self.PRELIMINARIES)
|
labour_cost = labour_cost * (1 + self.CONTINGENCY + self.PRELIMINARIES)
|
||||||
|
|
||||||
# if there are existing room heaters, we need to add the cost of removing them
|
# labour_days = labour_days + (removal_labour_hours / 8)
|
||||||
if exising_room_heaters:
|
|
||||||
removal_cost = ROOM_HEATER_REMOVAL_COST * n_heated_rooms
|
|
||||||
removal_labour_hours = ROOM_HEATER_REMOVAL_LABOUR_HOURS * n_heated_rooms
|
|
||||||
else:
|
|
||||||
removal_cost = 0
|
|
||||||
removal_labour_hours = 0
|
|
||||||
|
|
||||||
labour_cost = labour_cost + removal_cost
|
|
||||||
labour_days = labour_days + (removal_labour_hours / 8)
|
|
||||||
|
|
||||||
vat = labour_cost * self.VAT_RATE
|
vat = labour_cost * self.VAT_RATE
|
||||||
|
|
||||||
subtotal_before_vat = unit_cost + labour_cost
|
subtotal_before_vat = unit_cost + labour_cost
|
||||||
total_cost = subtotal_before_vat + vat
|
total_cost = subtotal_before_vat + vat
|
||||||
|
|
||||||
|
# if there are existing room heaters, we need to add the cost of removing them
|
||||||
|
if exising_room_heaters:
|
||||||
|
removal_costing = self.heater_removal(n_rooms=n_heated_rooms)
|
||||||
|
# Add the totals to the existing totals
|
||||||
|
total_cost += removal_costing["total"]
|
||||||
|
subtotal_before_vat += removal_costing["subtotal"]
|
||||||
|
labour_hours += removal_costing["labour_hours"]
|
||||||
|
labour_days += removal_costing["labour_days"]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"total": total_cost,
|
"total": total_cost,
|
||||||
"subtotal": subtotal_before_vat,
|
"subtotal": subtotal_before_vat,
|
||||||
"vat": vat,
|
"vat": vat,
|
||||||
"labour_hours": labour_days * 8,
|
"labour_hours": labour_hours,
|
||||||
"labour_days": labour_days,
|
"labour_days": labour_days,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ class HeatingRecommender:
|
||||||
# Otherwise, we recommend a gas condensing boiler, which will server a larger property, that has multiple
|
# Otherwise, we recommend a gas condensing boiler, which will server a larger property, that has multiple
|
||||||
# bathrooms
|
# bathrooms
|
||||||
is_combi = (
|
is_combi = (
|
||||||
(self.property.data["number-heated-rooms"] <= 4) and
|
(self.property.number_of_rooms <= 4) and
|
||||||
(self.property.n_bathrooms in [None, 0, 1])
|
(self.property.n_bathrooms in [None, 0, 1])
|
||||||
)
|
)
|
||||||
if is_combi:
|
if is_combi:
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from recommendations.SolarPvRecommendations import SolarPvRecommendations
|
||||||
from recommendations.WindowsRecommendations import WindowsRecommendations
|
from recommendations.WindowsRecommendations import WindowsRecommendations
|
||||||
from recommendations.HeatingRecommender import HeatingRecommender
|
from recommendations.HeatingRecommender import HeatingRecommender
|
||||||
from recommendations.HotwaterRecommendations import HotwaterRecommendations
|
from recommendations.HotwaterRecommendations import HotwaterRecommendations
|
||||||
|
from recommendations.SecondaryHeating import SecondaryHeating
|
||||||
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
|
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,6 +47,7 @@ class Recommendations:
|
||||||
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance)
|
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance)
|
||||||
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
|
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
|
||||||
self.hotwater_recommender = HotwaterRecommendations(property_instance=property_instance)
|
self.hotwater_recommender = HotwaterRecommendations(property_instance=property_instance)
|
||||||
|
self.secondary_heating_recommender = SecondaryHeating(property_instance=property_instance)
|
||||||
|
|
||||||
def recommend(self):
|
def recommend(self):
|
||||||
|
|
||||||
|
|
@ -130,6 +132,12 @@ class Recommendations:
|
||||||
property_recommendations.append(self.lighting_recommender.recommendation)
|
property_recommendations.append(self.lighting_recommender.recommendation)
|
||||||
phase += 1
|
phase += 1
|
||||||
|
|
||||||
|
if "secondary_heating" not in self.exclusions:
|
||||||
|
self.secondary_heating_recommender.recommend(phase=phase)
|
||||||
|
if self.secondary_heating_recommender.recommendation:
|
||||||
|
property_recommendations.append(self.secondary_heating_recommender.recommendation)
|
||||||
|
phase += 1
|
||||||
|
|
||||||
# Renewables
|
# Renewables
|
||||||
if "solar_pv" not in self.exclusions:
|
if "solar_pv" not in self.exclusions:
|
||||||
self.solar_recommender.recommend(phase=phase)
|
self.solar_recommender.recommend(phase=phase)
|
||||||
|
|
|
||||||
55
recommendations/SecondaryHeating.py
Normal file
55
recommendations/SecondaryHeating.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
from recommendations.Costs import Costs
|
||||||
|
from backend.Property import Property
|
||||||
|
|
||||||
|
|
||||||
|
class SecondaryHeating:
|
||||||
|
"""
|
||||||
|
This class recommends the removal of the secondary heating system for properties that have a primary heating
|
||||||
|
system.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The list of existing heating systems that are accepted
|
||||||
|
ACCEPTED_MAINHEAT_DESCRIPTIONS = ["Boiler and radiators, mains gas"]
|
||||||
|
ACCEPTED_SECONDHEAT_DESCRIPTIONS = ["Room heaters, electric"]
|
||||||
|
# These are the heaters where works are required to remove them
|
||||||
|
FIXED_HEATER_DESCRIPTIONS = ["Room heaters, electric"]
|
||||||
|
|
||||||
|
def __init__(self, property_instance: Property):
|
||||||
|
self.property = property_instance
|
||||||
|
self.costs = Costs(self.property)
|
||||||
|
|
||||||
|
self.recommendation = []
|
||||||
|
|
||||||
|
def recommend(self, phase: int):
|
||||||
|
# Reset
|
||||||
|
self.recommendation = []
|
||||||
|
|
||||||
|
if self.property.main_heating["clean_description"] not in self.ACCEPTED_MAINHEAT_DESCRIPTIONS:
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO: We need to clean secondary data
|
||||||
|
if self.property.data['secondheat-description'] not in self.ACCEPTED_SECONDHEAT_DESCRIPTIONS:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.property.data['secondheat-description'] in self.FIXED_HEATER_DESCRIPTIONS:
|
||||||
|
# We have an associated cost otherwise, there is no cost
|
||||||
|
n_rooms = self.property.data['number-heated-rooms']
|
||||||
|
else:
|
||||||
|
n_rooms = 0
|
||||||
|
|
||||||
|
costs = self.costs.heater_removal(n_rooms=n_rooms)
|
||||||
|
self.recommendation.append(
|
||||||
|
{
|
||||||
|
"phase": phase,
|
||||||
|
"parts": [],
|
||||||
|
"type": "secondary_heating",
|
||||||
|
"description": "Remove the secondary heating system",
|
||||||
|
"starting_u_value": None,
|
||||||
|
"new_u_value": None,
|
||||||
|
"sap_points": None,
|
||||||
|
**costs,
|
||||||
|
"simulation_config": {
|
||||||
|
"secondheat_description_ending": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
Loading…
Add table
Reference in a new issue