updating solar pv recommendations

This commit is contained in:
Khalim Conn-Kowlessar 2025-08-18 16:49:50 +01:00
parent dba33be174
commit 03854595cd

View file

@ -34,7 +34,7 @@ class SolarPvRecommendations:
]
)
PANEL_SIZES = [400, 435, 440]
PANEL_SIZES = [400, 435, 440, 445]
def __init__(self, property_instance, materials: list):
"""
@ -153,8 +153,6 @@ class SolarPvRecommendations:
if not self.property.is_solar_pv_valid():
return
raise ValueError("DOO BUILDING")
# If we have a buiilding level analysis, we implement separate logic
if self.property.building_id is not None:
self.recommend_building_analysis(phase)
@ -196,36 +194,49 @@ class SolarPvRecommendations:
# We combine each of these configurations with estimates with and without a battery
for rank, recommendation_config in solar_configurations.iterrows():
roof_coverage_percent = round(recommendation_config["panneled_roof_area"] / roof_area * 100)
# We round up to the nearest 5
roof_coverage_percent = np.ceil(roof_coverage_percent / 5) * 5
# Typically, we've observed that every 5% of additional roof coverage will result in at least
# an additional 1 SAP points (though often 2 points) Given this, we can add a reasonable minimum
# for the number of SAP points we might expect. We've observed that for some cases where properties
# are hitting the higher SAP scores (e.g. EPC A and above), the model can sometimes under-predict
# the number of SAP points. This appears to be due to a relatively small number of properties
# actually achieving the upper echelons of EPC rating. This can be the case if we're simulating a
# whole house retrofit where the home is getting complete insulation, a heat pump and solar panels.
# Because panels are the final recommendation, they are often the measure that takes the home
# into the medium to high EPC A ranges and so because of a lack of training data, this means that
# we might sometime under-predict. This minimum is intended to try and reduce the negative impact
# of this. This minimum is used in Recommendations.calculate_recommendation_impact
minimum_sap_points = (roof_coverage_percent / 5) * self.SAP_POINTS_PER_5_PERCENT_ROOF_COVERAGE
n_panels = recommendation_config["n_panels"]
# Different panel sizes: 400, 435, 440
available_products = []
for panel_size in self.PANEL_SIZES:
system_size = (n_panels * panel_size) / 1000
available_products.extend([
prods = [
x for x in self.panels_products if abs(x["size"] - system_size) < 0.01
])
]
for x in prods:
x["panel_size"] = panel_size
available_products.extend(prods)
# Given the available products in the database, we product the possible array of recommendations
for solar_pv_product in available_products:
# we take the paneled roof area and this tells us the roof coverage, based on 400W panels
# We then look at the equivalent for larger panels, which will produce more energy in the same area
paneled_roof_area = recommendation_config["panneled_roof_area"]
roof_coverage_percent = round(
((paneled_roof_area / 400) * solar_pv_product["panel_size"]) / roof_area * 100
)
# We round up to the nearest 5
roof_coverage_percent = np.ceil(roof_coverage_percent / 5) * 5
# Note roof_coverage_percent is based on 400 watt panels, so we need to scale it up based on
# largest panels that will produce more energy in the same area
# Typically, we've observed that every 5% of additional roof coverage will result in at least
# an additional 1 SAP points (though often 2 points) Given this, we can add a reasonable minimum
# for the number of SAP points we might expect. We've observed that for some cases where properties
# are hitting the higher SAP scores (e.g. EPC A and above), the model can sometimes under-predict
# the number of SAP points. This appears to be due to a relatively small number of properties
# actually achieving the upper echelons of EPC rating. This can be the case if we're simulating a
# whole house retrofit where the home is getting complete insulation, a heat pump and solar panels.
# Because panels are the final recommendation, they are often the measure that takes the home
# into the medium to high EPC A ranges and so because of a lack of training data, this means that
# we might sometime under-predict. This minimum is intended to try and reduce the negative impact
# of this. This minimum is used in Recommendations.calculate_recommendation_impact
minimum_sap_points = (roof_coverage_percent / 5) * self.SAP_POINTS_PER_5_PERCENT_ROOF_COVERAGE
n_panels = recommendation_config["n_panels"]
cost_result = self.costs.solar_pv(
product=solar_pv_product,
scaffolding_options=self.scaffolding_options,
@ -252,10 +263,6 @@ class SolarPvRecommendations:
"sap_points": minimum_sap_points,
"already_installed": already_installed,
**cost_result,
# This is required for simulating the SAP impact. solar_pv_percentage is between 0 & 1 so we
# scale
# back up here
"photo_supply": roof_coverage_percent,
"has_battery": has_battery,
"initial_ac_kwh_per_year": recommendation_config["initial_ac_kwh_per_year"],
"description_simulation": {"photo-supply": roof_coverage_percent},