mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +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"
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
simulation_config = recommendation["simulation_config"]
|
||||
|
|
@ -477,7 +479,7 @@ class Property:
|
|||
"loft_insulation", "room_roof_insulation", "flat_roof_insulation",
|
||||
"solid_floor_insulation", "suspended_floor_insulation", "exposed_floor_insulation",
|
||||
"windows_glazing", "solar_pv", "heating", "hot_water_tank_insulation",
|
||||
"heating_control",
|
||||
"heating_control", "secondary_heating"
|
||||
]:
|
||||
raise NotImplementedError(
|
||||
"Implement me, given type %s" % recommendation["type"]
|
||||
|
|
|
|||
|
|
@ -1104,6 +1104,28 @@ class Costs:
|
|||
"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):
|
||||
"""
|
||||
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
|
||||
# We now need to estimate the cost of the works
|
||||
labour_days = 2
|
||||
labour_hours = labour_days * 8
|
||||
labour_rate = 500
|
||||
|
||||
# Average cost of installation is 1 (maybe 2days) at £300 per day
|
||||
|
|
@ -1123,26 +1146,26 @@ class Costs:
|
|||
# Add contingency and 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
|
||||
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)
|
||||
# labour_days = labour_days + (removal_labour_hours / 8)
|
||||
|
||||
vat = labour_cost * self.VAT_RATE
|
||||
|
||||
subtotal_before_vat = unit_cost + labour_cost
|
||||
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 {
|
||||
"total": total_cost,
|
||||
"subtotal": subtotal_before_vat,
|
||||
"vat": vat,
|
||||
"labour_hours": labour_days * 8,
|
||||
"labour_hours": labour_hours,
|
||||
"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
|
||||
# bathrooms
|
||||
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])
|
||||
)
|
||||
if is_combi:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from recommendations.SolarPvRecommendations import SolarPvRecommendations
|
|||
from recommendations.WindowsRecommendations import WindowsRecommendations
|
||||
from recommendations.HeatingRecommender import HeatingRecommender
|
||||
from recommendations.HotwaterRecommendations import HotwaterRecommendations
|
||||
from recommendations.SecondaryHeating import SecondaryHeating
|
||||
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
|
||||
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ class Recommendations:
|
|||
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance)
|
||||
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
|
||||
self.hotwater_recommender = HotwaterRecommendations(property_instance=property_instance)
|
||||
self.secondary_heating_recommender = SecondaryHeating(property_instance=property_instance)
|
||||
|
||||
def recommend(self):
|
||||
|
||||
|
|
@ -130,6 +132,12 @@ class Recommendations:
|
|||
property_recommendations.append(self.lighting_recommender.recommendation)
|
||||
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
|
||||
if "solar_pv" not in self.exclusions:
|
||||
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