mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
coupling heating and heating controls recommendations
This commit is contained in:
parent
d60918b771
commit
be71af909e
4 changed files with 156 additions and 68 deletions
|
|
@ -363,7 +363,7 @@ class Property:
|
|||
"internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation",
|
||||
"loft_insulation", "room_roof_insulation", "flat_roof_insulation",
|
||||
"solid_floor_insulation", "suspended_floor_insulation", "exposed_floor_insulation",
|
||||
"windows_glazing", "solar_pv", "heating_control",
|
||||
"windows_glazing", "solar_pv", "heating", "heating_control",
|
||||
]:
|
||||
raise NotImplementedError("Implement me")
|
||||
|
||||
|
|
|
|||
|
|
@ -10,16 +10,20 @@ class HeatingControlRecommender:
|
|||
self.property = property_instance
|
||||
self.costs = Costs(self.property)
|
||||
|
||||
self.recommendations = []
|
||||
self.recommendation = []
|
||||
|
||||
def recommend(self, heating_description):
|
||||
|
||||
# Reset the recommendations
|
||||
self.recommendation = []
|
||||
|
||||
def recommend(self, phase=0):
|
||||
# This first iteration of the recommender will provide very basic recommendation
|
||||
# We recommend heating controls based on the main heating system
|
||||
if self.property.main_heating["clean_description"] == "Room heaters, electric":
|
||||
self.recommend_room_heaters_electric_controls(phase=phase)
|
||||
if heating_description in ["Room heaters, electric", "Electric storage heaters, radiators"]:
|
||||
self.recommend_room_heaters_electric_controls()
|
||||
return
|
||||
|
||||
def recommend_room_heaters_electric_controls(self, phase):
|
||||
def recommend_room_heaters_electric_controls(self):
|
||||
"""
|
||||
If the home has Room heaters, electric, we start by identifying potential heating controls that could
|
||||
be upgraded, that would provide a practical impact. This will be the least invasive improvement.
|
||||
|
|
@ -57,18 +61,10 @@ class HeatingControlRecommender:
|
|||
# This upgrade will only take the heating system to average energy efficiency
|
||||
simulation_config["mainheatc_energy_eff_ending"] = "Good"
|
||||
|
||||
self.recommendations.append(
|
||||
self.recommendation.append(
|
||||
{
|
||||
"phase": phase,
|
||||
"parts": [
|
||||
# TODO
|
||||
],
|
||||
"type": "heating_control",
|
||||
"description": "Upgrade heating controls to Programmer and Appliance or Smart "
|
||||
"Thermostats for more precise heating control, and prevention of overheating",
|
||||
"starting_u_value": None,
|
||||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
"description": "upgrade heating controls to Programmer and Appliance or Smart Thermostats",
|
||||
**self.costs.programmer_and_appliance_thermostat(has_programmer=has_programmer),
|
||||
"simulation_config": simulation_config
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from recommendations.Costs import Costs
|
|||
from recommendations.recommendation_utils import check_simulation_difference
|
||||
from backend.Property import Property
|
||||
from etl.epc_clean.epc_attributes.MainheatAttributes import MainHeatAttributes
|
||||
from recommendations.HeatingControlRecommender import HeatingControlRecommender
|
||||
|
||||
|
||||
class HeatingRecommender:
|
||||
|
|
@ -13,10 +14,12 @@ class HeatingRecommender:
|
|||
self.recommendations = []
|
||||
|
||||
def recommend(self, phase=0):
|
||||
self.recommendations = []
|
||||
# This first iteration of the recommender will provide very basic recommendation
|
||||
# We recommend heating controls based on the main heating system
|
||||
if self.property.main_heating["clean_description"] == "Room heaters, electric":
|
||||
self.recommend_room_heaters_electric(phase=phase)
|
||||
self.recommend_room_heaters_electric(phase=phase, heating_controls_only=True)
|
||||
self.recommend_electric_storage_heaters(phase=phase, heating_controls_only=False)
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -32,7 +35,128 @@ class HeatingRecommender:
|
|||
|
||||
return differences
|
||||
|
||||
def recommend_room_heaters_electric(self, phase):
|
||||
@staticmethod
|
||||
def combine_heating_and_controls(
|
||||
controls_recommendations, heating_simulation_config, costs, description, phase, heating_controls_only
|
||||
):
|
||||
"""
|
||||
Given a recommendation for heating controls, and a recommendation for the heating system, we combine the two
|
||||
into a single recommendation
|
||||
:param controls_recommendations: The heating controls recommendations
|
||||
:param heating_simulation_config: The simulation configuration for the heating system
|
||||
:param costs: The costs of the heating system
|
||||
:param description: The description of the recommendation
|
||||
:param phase: The phase of the recommendation
|
||||
:param heating_controls_only: If True, we will also add a recommendation for heating controls only
|
||||
:return:
|
||||
"""
|
||||
|
||||
# We produce recommendations with & without heating controls
|
||||
# We will also produce a recommendation for heating controls only
|
||||
heating_controls_switch = [True, False] if controls_recommendations else [False]
|
||||
if not heating_simulation_config:
|
||||
heating_controls_switch = []
|
||||
|
||||
output = []
|
||||
for controls_switch in heating_controls_switch:
|
||||
total_costs = costs.copy()
|
||||
recommendation_simulation_config = heating_simulation_config.copy()
|
||||
if controls_switch:
|
||||
# We add the costs of the heating controls, onto each key in the costs dictionary
|
||||
for key in total_costs:
|
||||
total_costs[key] += controls_recommendations[0][key]
|
||||
|
||||
recommendation_simulation_config = {
|
||||
**recommendation_simulation_config,
|
||||
**controls_recommendations[0]["simulation_config"]
|
||||
}
|
||||
|
||||
description = f"{description} and {controls_recommendations[0]['description']}"
|
||||
|
||||
recommendation = {
|
||||
"phase": phase,
|
||||
"parts": [
|
||||
# TODO
|
||||
],
|
||||
"type": "heating",
|
||||
"description": description,
|
||||
"starting_u_value": None,
|
||||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
**total_costs,
|
||||
"simulation_config": recommendation_simulation_config
|
||||
}
|
||||
|
||||
output.append(recommendation)
|
||||
|
||||
if heating_controls_only and len(controls_recommendations):
|
||||
# Also add on a recommendation for heating controls only
|
||||
heating_control_recommendation = controls_recommendations[0].copy()
|
||||
# Capitalize the first letter of the description
|
||||
heating_control_recommendation["description"] = (
|
||||
heating_control_recommendation["description"][0].upper() +
|
||||
heating_control_recommendation["description"][1:]
|
||||
)
|
||||
|
||||
output.append(
|
||||
{
|
||||
"phase": phase,
|
||||
"starting_u_value": None,
|
||||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
**heating_control_recommendation
|
||||
}
|
||||
)
|
||||
|
||||
return output
|
||||
|
||||
def recommend_electric_storage_heaters(self, phase, heating_controls_only):
|
||||
"""
|
||||
We recommend electric storage heaters as an upgrade to the heating system.
|
||||
:return:
|
||||
"""
|
||||
|
||||
controls_recommender = HeatingControlRecommender(self.property)
|
||||
controls_recommender.recommend(heating_description="Room heaters, electric")
|
||||
|
||||
if self.property.data["mainheat-energy-eff"] not in ["Poor", "Very Poor"]:
|
||||
# We do just heating controls
|
||||
recs = self.combine_heating_and_controls(
|
||||
controls_recommendations=controls_recommender.recommendation,
|
||||
heating_simulation_config={},
|
||||
costs={},
|
||||
description="",
|
||||
phase=phase,
|
||||
heating_controls_only=heating_controls_only
|
||||
)
|
||||
return
|
||||
|
||||
# Set up artefacts, suitable for the simulation and regardless of controls
|
||||
heating_ending_config = MainHeatAttributes("Electric storage heaters, radiators").process()
|
||||
heating_simulation_config = check_simulation_difference(
|
||||
new_config=heating_ending_config, old_config=self.property.main_heating
|
||||
)
|
||||
# This upgrade will only take the heating system to average energy efficiency
|
||||
heating_simulation_config["mainheatc_energy_eff_ending"] = "Good"
|
||||
|
||||
# Upgrade to electric storage heaters
|
||||
costs = self.costs.electric_storage_heaters(
|
||||
number_heated_rooms=self.property.data["number-heated-rooms"]
|
||||
)
|
||||
description = "Install electric storage heaters"
|
||||
|
||||
recommendations = self.combine_heating_and_controls(
|
||||
controls_recommendations=controls_recommender.recommendation,
|
||||
heating_simulation_config=heating_simulation_config,
|
||||
costs=costs,
|
||||
description=description,
|
||||
phase=phase,
|
||||
heating_controls_only=heating_controls_only
|
||||
)
|
||||
|
||||
self.recommendations.extend(recommendations)
|
||||
|
||||
def recommend_room_heaters_electric(self, phase, heating_controls_only):
|
||||
"""
|
||||
If the home has Room heaters, electric, we start by identifying potential heating controls that could
|
||||
be upgraded, that would provide a practical impact. This will be the least invasive improvement.
|
||||
|
|
@ -40,49 +164,24 @@ class HeatingRecommender:
|
|||
We can then consider the heating system itself
|
||||
:return:
|
||||
"""
|
||||
if self.property.data["mainheat-energy-eff"] in ["Poor", "Very Poor"]:
|
||||
# Re recommend two possible upgrades:
|
||||
# 1) Installation of more efficient electic room heaters
|
||||
# 2) Installation of electric storage heaters
|
||||
if self.property.data["mainheat-energy-eff"] not in ["Poor", "Very Poor"]:
|
||||
return
|
||||
|
||||
room_heater_recommendation = {
|
||||
"phase": phase,
|
||||
"parts": [
|
||||
# TODO
|
||||
],
|
||||
"type": "heating",
|
||||
"description": "Upgrade electric room heaters to more electric radiators",
|
||||
"starting_u_value": None,
|
||||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
**self.costs.electric_room_heaters(number_heated_rooms=self.property.data["number-heated-rooms"]),
|
||||
"simulation_config": {"mainheat_energy_eff_ending": "Average"}
|
||||
}
|
||||
controls_recommender = HeatingControlRecommender(self.property)
|
||||
controls_recommender.recommend(heating_description="Room heaters, electric")
|
||||
costs = self.costs.electric_room_heaters(
|
||||
number_heated_rooms=self.property.data["number-heated-rooms"]
|
||||
)
|
||||
description = "Upgrade electric room heaters to more electric radiators"
|
||||
heating_simulation_config = {"mainheat_energy_eff_ending": "Average"}
|
||||
|
||||
ending_config = MainHeatAttributes("Electric storage heaters, radiators").process()
|
||||
simulation_config = check_simulation_difference(
|
||||
new_config=ending_config, old_config=self.property.main_heating
|
||||
)
|
||||
# This upgrade will only take the heating system to average energy efficiency
|
||||
simulation_config["mainheatc_energy_eff_ending"] = "Good"
|
||||
recommendations = self.combine_heating_and_controls(
|
||||
controls_recommender=controls_recommender,
|
||||
heating_simulation_config=heating_simulation_config,
|
||||
costs=costs,
|
||||
description=description,
|
||||
phase=phase,
|
||||
heating_controls_only=heating_controls_only
|
||||
)
|
||||
|
||||
electric_storage_heaters_recommendation = {
|
||||
"phase": phase,
|
||||
"parts": [
|
||||
# TODO
|
||||
],
|
||||
"type": "heating",
|
||||
"description": "Install electric storage heaters",
|
||||
"starting_u_value": None,
|
||||
"new_u_value": None,
|
||||
"sap_points": None,
|
||||
**self.costs.electric_storage_heaters(number_heated_rooms=self.property.data["number-heated-rooms"]),
|
||||
"simulation_config": simulation_config
|
||||
}
|
||||
|
||||
self.recommendations.extend(
|
||||
[room_heater_recommendation, electric_storage_heaters_recommendation]
|
||||
)
|
||||
|
||||
# We don't implement any other recommendations right now
|
||||
return
|
||||
self.recommendations.extend(recommendations)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from recommendations.LightingRecommendations import LightingRecommendations
|
|||
from recommendations.SolarPvRecommendations import SolarPvRecommendations
|
||||
from recommendations.WindowsRecommendations import WindowsRecommendations
|
||||
from recommendations.HeatingRecommender import HeatingRecommender
|
||||
from recommendations.HeatingControlRecommender import HeatingControlRecommender
|
||||
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
|
||||
|
||||
|
||||
|
|
@ -43,7 +42,6 @@ class Recommendations:
|
|||
self.windows_recommender = WindowsRecommendations(property_instance=property_instance, materials=materials)
|
||||
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance)
|
||||
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
|
||||
self.heating_control_recommender = HeatingControlRecommender(property_instance=property_instance)
|
||||
|
||||
def recommend(self):
|
||||
|
||||
|
|
@ -99,11 +97,6 @@ class Recommendations:
|
|||
property_recommendations.append(self.heating_recommender.recommendations)
|
||||
phase += 1
|
||||
|
||||
self.heating_control_recommender.recommend(phase=phase)
|
||||
if self.heating_control_recommender.recommendations:
|
||||
property_recommendations.append(self.heating_control_recommender.recommendations)
|
||||
phase += 1
|
||||
|
||||
self.lighting_recommender.recommend(phase=phase)
|
||||
if self.lighting_recommender.recommendation:
|
||||
property_recommendations.append(self.lighting_recommender.recommendation)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue