debugging the model for number dual heating systens

This commit is contained in:
Khalim Conn-Kowlessar 2025-06-22 18:30:15 +01:00
parent f687988180
commit 49b1baa4a9
6 changed files with 43 additions and 16 deletions

View file

@ -217,6 +217,9 @@ class Property:
self.eco4_eligibility = None
self.whlg_eligibility = None
# Ventilation
self.has_ventilation = self.identify_ventilation()
@classmethod
def extract_kwargs(cls, kwargs):
"""
@ -1349,3 +1352,12 @@ class Property:
self.gbis_eligibiltiy = funding_calulator.gbis_eligibiltiy
self.eco4_eligibility = funding_calulator.eco4_eligibility
self.whlg_eligibility = funding_calulator.whlg_eligibility
def identify_ventilation(self):
ventilation_descriptions = [
'mechanical, extract only',
'mechanical, supply and extract'
]
return self.data["mechanical-ventilation"] in ventilation_descriptions

View file

@ -58,6 +58,11 @@ DESCRIPTIONS_TO_FUEL_TYPES = {
"Room heaters, wood logs": {"fuel": "Wood Logs", "cop": 1},
"Boiler and radiators, coal": {"fuel": "Coal", "cop": 0.85},
"From main system, no cylinderstat": {"fuel": "Natural Gas", "cop": 0.85},
"Room heaters, coal": {"fuel": "Coal", "cop": 0.85},
"Electric underfloor heating, Electric storage heaters": {"fuel": "Electricity", "cop": 1},
'Room heaters, electric, Boiler and radiators, mains gas': {"fuel": "Natural Gas", "cop": 0.85},
'Boiler and radiators, mains gas, Boiler and radiators, mains gas': {"fuel": "Natural Gas", "cop": 0.85},
'Room heaters, electric, Electric storage heaters': {"fuel": "Electricity", "cop": 1},
}
# These are the measure types where if there is a ventilation recommendation, we force the inclusion of it

View file

@ -727,7 +727,8 @@ async def model_engine(body: PlanTriggerRequest):
# Additionally, if we have required measures, they should also be included. Therefore
# we can discount the number of points required to get to the target SAP band (or increase)
# in the case of ventilation
needs_ventilation = any(x in property_measure_types for x in assumptions.measures_needing_ventilation)
needs_ventilation = any(
x in property_measure_types for x in assumptions.measures_needing_ventilation) and not p.has_ventilation
input_measures = prepare_input_measures(measures_to_optimise, body.goal, needs_ventilation)
@ -771,6 +772,10 @@ async def model_engine(body: PlanTriggerRequest):
epc_to_sap_lower_bound(body.goal_value) - current_sap_points
) - fixed_gain
if body.simulate_sap_10:
# We add 3 additional SAP points to the required gain to account for SAP 10
sap_gain += 3
if not body.optimise:
if body.goal != "Increasing EPC":
raise NotImplementedError("Only EPC optimisation is currently supported")
@ -825,7 +830,11 @@ async def model_engine(body: PlanTriggerRequest):
)
# If wall insulation is selected, we also include mechanical ventilation as a best practice measure
if any(x in [r["type"] for r in solution] for x in assumptions.measures_needing_ventilation):
ventilation_selected = [
r for r in solution if "+mechanical_ventilation" in r["type"]
]
if (any(x in [r["type"] for r in solution] for x in assumptions.measures_needing_ventilation) or
len(ventilation_selected)):
ventilation_rec = next(
(r[0] for r in recommendations[p.id] if r[0]["type"] == "mechanical_ventilation"),
None

View file

@ -74,6 +74,14 @@ class HeatingRecommender:
"controls_suffix": ""
},
"dual": None
},
"Room heaters, electric, electric storage heaters": {
"hhr": {
"mainheating_description": "Electric storage heaters, radiators",
"recommendation_description": "Install high heat retention electric storage heaters.",
"controls_prefix": ""
},
"dual": None
}
}
@ -186,7 +194,8 @@ class HeatingRecommender:
) and
(not ashp_only_heating_recommendation) and
("boiler_upgrade" in measures) and
(not self.has_ashp)
(not self.has_ashp) and
(not self.property.main_heating["has_warm_air"])
)
return is_valid, has_gas_boiler

View file

@ -10,11 +10,6 @@ class VentilationRecommendations(Definitions):
crucial for prevent overheating risks in warmer months
"""
VENTILATION_DESCRIPTIONS = [
'mechanical, extract only',
'mechanical, supply and extract'
]
def __init__(
self,
property_instance: Property,
@ -26,9 +21,6 @@ class VentilationRecommendations(Definitions):
self.recommendation = None
self.materials = [part for part in materials if part["type"] == "mechanical_ventilation"]
def identify_ventilation(self):
self.has_ventilaion = self.property.data["mechanical-ventilation"] in self.VENTILATION_DESCRIPTIONS
def recommend(self, phase):
"""
If there is no ventilation, we recommend installing ventilation
@ -38,8 +30,8 @@ class VentilationRecommendations(Definitions):
:return:
"""
self.identify_ventilation()
if self.has_ventilaion:
self.property.identify_ventilation()
if self.property.has_ventilaion:
return
if len(self.materials) != 1:

View file

@ -47,19 +47,19 @@ def prepare_input_measures(property_recommendations, goal, needs_ventilation):
# We bundle the impact of ventilation with the measure
total = (
rec["total"] + ventilation_recommendation["total"]
if rec["type"] in assumptions.measures_needing_ventilation
if rec["type"] in assumptions.measures_needing_ventilation and needs_ventilation
else rec["total"]
)
gain = (
rec[goal_key] + ventilation_recommendation[goal_key]
if rec["type"] in assumptions.measures_needing_ventilation
if rec["type"] in assumptions.measures_needing_ventilation and needs_ventilation
else rec[goal_key]
)
rec_type = (
"+".join(
[rec["type"], ventilation_recommendation["type"]]
) if rec["type"] in assumptions.measures_needing_ventilation
) if rec["type"] in assumptions.measures_needing_ventilation and needs_ventilation
else rec["type"]
)