MOsman #1
|
@ -1,36 +1,90 @@
|
|||
# from hub.city_model_structure.building import Building
|
||||
# from hub.city_model_structure.city import City
|
||||
# import hub.helpers.constants as cte
|
||||
# import copy
|
||||
|
||||
# class RetrofitFactory:
|
||||
# def __init__(self, retrofit_type, city):
|
||||
# self._retrofit_type = retrofit_type
|
||||
# self._city = city
|
||||
|
||||
# def apply_retrofit(self, wall_u_value=None, roof_u_value=None, ground_u_value=None):
|
||||
# for building in self._city.buildings:
|
||||
# self._apply_retrofit_to_building(building, wall_u_value, roof_u_value, ground_u_value)
|
||||
|
||||
# def _apply_retrofit_to_building(self, building: Building, wall_u_value, roof_u_value, ground_u_value):
|
||||
# for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
# for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
# if wall_u_value is not None and thermal_boundary.type == cte.WALL and thermal_boundary.u_value > wall_u_value:
|
||||
# self._change_thermal_resistance(thermal_boundary, wall_u_value)
|
||||
# thermal_boundary.u_value = wall_u_value
|
||||
# elif roof_u_value is not None and thermal_boundary.type == cte.ROOF:
|
||||
# self._change_thermal_resistance(thermal_boundary, roof_u_value)
|
||||
# thermal_boundary.u_value = roof_u_value
|
||||
# elif ground_u_value is not None and thermal_boundary.type == cte.GROUND:
|
||||
# self._change_thermal_resistance(thermal_boundary, ground_u_value)
|
||||
# thermal_boundary.u_value = ground_u_value
|
||||
# print("thermal_boundary.u_value",thermal_boundary.u_value, thermal_boundary.type)
|
||||
|
||||
|
||||
# def _change_thermal_resistance(self, thermal_boundary, new_u_value):
|
||||
# old_u_value = thermal_boundary.u_value
|
||||
# new_u_value = new_u_value
|
||||
# if new_u_value < old_u_value:
|
||||
# delta_r = (1 / new_u_value) - (1 / old_u_value)
|
||||
# for layer in thermal_boundary.layers:
|
||||
# if "virtual_no_mass" in layer.material_name.lower():
|
||||
# new_thermal_resistance = layer.thermal_resistance + delta_r
|
||||
# layer.thermal_resistance = new_thermal_resistance
|
||||
# else:
|
||||
# print("New U-value:", new_u_value, "is not less than old U-value:", old_u_value, "for thermal boundary type:", thermal_boundary.type)
|
||||
|
||||
# def enrich(self, wall_u_value=None, roof_u_value=None, ground_u_value=None):
|
||||
# # This method can be expanded to include different retrofit strategies
|
||||
# if self._retrofit_type == 'basic':
|
||||
# self.apply_retrofit(wall_u_value=0.247, roof_u_value=0.138, ground_u_value=0.156)
|
||||
# elif self._retrofit_type == 'advanced':
|
||||
# self.apply_retrofit(wall_u_value=0.11, roof_u_value=0.08, ground_u_value=0.1)
|
||||
# #add option for custom wall only, roof only, ground only, the user choose the values
|
||||
# elif self._retrofit_type == 'custom':
|
||||
# # Use user-defined custom values (if provided)
|
||||
# self.apply_retrofit(wall_u_value=wall_u_value, roof_u_value=roof_u_value, ground_u_value=ground_u_value)
|
||||
# else:
|
||||
# print("Invalid retrofit type:", self._retrofit_type)
|
||||
from hub.city_model_structure.building import Building
|
||||
from hub.city_model_structure.city import City
|
||||
import hub.helpers.constants as cte
|
||||
import copy
|
||||
|
||||
class RetrofitFactory:
|
||||
def __init__(self, retrofit_type, city):
|
||||
self._retrofit_type = retrofit_type
|
||||
def __init__(self, retrofit_types, city):
|
||||
"""
|
||||
:param retrofit_types: List of retrofit types to apply. Options are 'construction', 'windows', 'infiltration'.
|
||||
:param city: The City object containing the buildings to retrofit.
|
||||
"""
|
||||
self._retrofit_types = retrofit_types
|
||||
self._city = city
|
||||
|
||||
def apply_retrofit(self, wall_u_value=None, roof_u_value=None, ground_u_value=None):
|
||||
def apply_construction_retrofit(self, wall_u_value=None, roof_u_value=None, ground_u_value=None):
|
||||
for building in self._city.buildings:
|
||||
self._apply_retrofit_to_building(building, wall_u_value, roof_u_value, ground_u_value)
|
||||
self._apply_construction_retrofit_to_building(building, wall_u_value, roof_u_value, ground_u_value)
|
||||
|
||||
def _apply_retrofit_to_building(self, building: Building, wall_u_value, roof_u_value, ground_u_value):
|
||||
def _apply_construction_retrofit_to_building(self, building: Building, wall_u_value, roof_u_value, ground_u_value):
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
if wall_u_value is not None and thermal_boundary.type == cte.WALL and thermal_boundary.u_value > wall_u_value:
|
||||
self._change_thermal_resistance(thermal_boundary, wall_u_value)
|
||||
print("u_value",thermal_boundary.u_value)
|
||||
thermal_boundary.u_value = wall_u_value
|
||||
elif roof_u_value is not None and thermal_boundary.type == cte.ROOF:
|
||||
elif roof_u_value is not None and thermal_boundary.type == cte.ROOF and thermal_boundary.u_value > roof_u_value:
|
||||
self._change_thermal_resistance(thermal_boundary, roof_u_value)
|
||||
thermal_boundary.u_value = roof_u_value
|
||||
elif ground_u_value is not None and thermal_boundary.type == cte.GROUND:
|
||||
self._change_thermal_resistance(thermal_boundary, ground_u_value)
|
||||
elif ground_u_value is not None and thermal_boundary.type == cte.GROUND and thermal_boundary.u_value > ground_u_value:
|
||||
self._change_thermal_resistance(thermal_boundary, ground_u_value)
|
||||
thermal_boundary.u_value = ground_u_value
|
||||
print("thermal_boundary.u_value",thermal_boundary.u_value, thermal_boundary.type)
|
||||
print("thermal_boundary.u_value", thermal_boundary.u_value, thermal_boundary.type)
|
||||
|
||||
def _change_thermal_resistance(self, thermal_boundary, new_u_value):
|
||||
|
||||
def _change_thermal_resistance(self, thermal_boundary, new_u_value):
|
||||
old_u_value = thermal_boundary.u_value
|
||||
new_u_value = new_u_value
|
||||
if new_u_value < old_u_value:
|
||||
delta_r = (1 / new_u_value) - (1 / old_u_value)
|
||||
for layer in thermal_boundary.layers:
|
||||
|
@ -40,9 +94,54 @@ class RetrofitFactory:
|
|||
else:
|
||||
print("New U-value:", new_u_value, "is not less than old U-value:", old_u_value, "for thermal boundary type:", thermal_boundary.type)
|
||||
|
||||
def enrich(self):
|
||||
# This method can be expanded to include different retrofit strategies
|
||||
if self._retrofit_type == 'basic':
|
||||
self.apply_retrofit(wall_u_value=0.247, roof_u_value=0.138, ground_u_value=0.156)
|
||||
elif self._retrofit_type == 'advanced':
|
||||
self.apply_retrofit(wall_u_value=0.11, roof_u_value=0.08, ground_u_value=0.1)
|
||||
def reduce_infiltration_rate_by_percentage(self, percentage):
|
||||
"""
|
||||
Reduce the infiltration_rate_system_off of each thermal zone by the given percentage.
|
||||
:param percentage: Percentage by which to reduce the infiltration rate (e.g., 20 for 20%)
|
||||
"""
|
||||
for building in self._city.buildings:
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
old_rate = thermal_zone.infiltration_rate_system_off
|
||||
new_rate = old_rate * (1 - percentage / 100)
|
||||
thermal_zone.infiltration_rate_system_off = new_rate
|
||||
print(f"Reduced infiltration rate from {old_rate} to {new_rate} in thermal zone {thermal_zone}")
|
||||
|
||||
def apply_window_retrofit(self, overall_u_value=None, g_value=None):
|
||||
"""
|
||||
Apply window retrofit by changing window overall U-value and g-value.
|
||||
:param overall_u_value: New overall U-value for the windows (if not None).
|
||||
:param g_value: New g-value (solar heat gain coefficient) for the windows (if not None).
|
||||
"""
|
||||
for building in self._city.buildings:
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
# Only apply to walls (and roofs if skylights are considered)
|
||||
if thermal_boundary.type in [cte.WALL]: # Add cte.ROOF if skylights are present
|
||||
if hasattr(thermal_boundary, 'thermal_openings') and thermal_boundary.thermal_openings:
|
||||
for opening in thermal_boundary.thermal_openings:
|
||||
if overall_u_value is not None and overall_u_value != 0:
|
||||
old_u_value = opening.overall_u_value
|
||||
opening.overall_u_value = overall_u_value
|
||||
print(f"Changed window overall_u_value from {old_u_value} to {opening.overall_u_value} in opening {opening}")
|
||||
if g_value is not None and g_value != 0:
|
||||
old_g_value = opening.g_value
|
||||
opening.g_value = g_value
|
||||
print(f"Changed window g_value from {old_g_value} to {opening.g_value} in opening {opening}")
|
||||
else:
|
||||
print(f"No thermal openings in thermal boundary {thermal_boundary} of type {thermal_boundary.type}")
|
||||
else:
|
||||
# Skip thermal boundaries that are not walls or roofs
|
||||
continue
|
||||
|
||||
def enrich(self, wall_u_value=None, roof_u_value=None, ground_u_value=None,
|
||||
infiltration_rate_percentage_reduction=None,
|
||||
window_overall_u_value=None, window_g_value=None):
|
||||
"""
|
||||
Apply selected retrofits to the city.
|
||||
"""
|
||||
if 'construction' in self._retrofit_types:
|
||||
self.apply_construction_retrofit(wall_u_value, roof_u_value, ground_u_value)
|
||||
if 'infiltration' in self._retrofit_types and infiltration_rate_percentage_reduction is not None:
|
||||
self.reduce_infiltration_rate_by_percentage(infiltration_rate_percentage_reduction)
|
||||
if 'windows' in self._retrofit_types:
|
||||
self.apply_window_retrofit(overall_u_value=window_overall_u_value, g_value=window_g_value)
|
|
@ -1,63 +1,105 @@
|
|||
from hub.city_model_structure.building import Building
|
||||
from hub.city_model_structure.city import City
|
||||
from hub.city_model_structure.building_demand.thermal_archetype import ThermalArchetype
|
||||
from hub.city_model_structure.building_demand.construction import Construction
|
||||
from hub.catalog_factories.construction_catalog_factory import ConstructionCatalogFactory
|
||||
import hub.helpers.constants as cte
|
||||
|
||||
class RetrofitFactoryVirtual:
|
||||
def __init__(self, retrofit_type, city):
|
||||
self._retrofit_type = retrofit_type
|
||||
class RetrofitFactory:
|
||||
def __init__(self, retrofit_data, city):
|
||||
"""
|
||||
:param retrofit_data: Dictionary mapping building IDs to their retrofit data.
|
||||
:param city: The City object containing the buildings to retrofit.
|
||||
"""
|
||||
self._retrofit_data = retrofit_data
|
||||
self._city = city
|
||||
self._cerc_catalog = ConstructionCatalogFactory('cerc').catalog
|
||||
|
||||
def apply_retrofit(self, **u_values):
|
||||
for building in self._city.buildings:
|
||||
for internal_zone in building.internal_zones:
|
||||
self._apply_retrofit_to_thermal_archetype(internal_zone.thermal_archetype, u_values)
|
||||
|
||||
def _apply_retrofit_to_thermal_archetype(self, thermal_archetype: ThermalArchetype, u_values):
|
||||
for construction in thermal_archetype.constructions:
|
||||
if construction.type in u_values and any(surface in construction.type.lower() for surface in ['wall', 'roof', 'ground']):
|
||||
self._update_construction_u_value(construction, u_values[construction.type])
|
||||
|
||||
def _update_construction_u_value(self, construction: Construction, new_u_value):
|
||||
virtual_no_mass_layer = next((layer for layer in construction.layers if "virtual_no_mass" in layer.material_name.lower()), None)
|
||||
|
||||
if virtual_no_mass_layer:
|
||||
old_r_value = 1 / construction.u_value
|
||||
new_r_value = 1 / new_u_value
|
||||
delta_r = new_r_value - old_r_value
|
||||
|
||||
virtual_no_mass_layer.thermal_resistance += delta_r
|
||||
print(f"Updated {construction.type} - New thermal resistance: {virtual_no_mass_layer.thermal_resistance}")
|
||||
construction.u_value = new_u_value
|
||||
|
||||
def modify_thermal_resistance(self, new_thermal_resistance):
|
||||
import sys
|
||||
|
||||
for building in self._city.buildings:
|
||||
for zone in building.thermal_zones_from_internal_zones:
|
||||
for boundary in zone.thermal_boundaries:
|
||||
if any(surface in boundary.type.lower() for surface in ['wall', 'roof', 'ground']):
|
||||
layers = getattr(boundary, 'get_layers', lambda: [])()
|
||||
sys.stderr.write(f"Checking boundary type: {boundary.type}, found {len(layers)} layers\n")
|
||||
for layer in layers:
|
||||
if layer and hasattr(layer, 'material_name'):
|
||||
sys.stderr.write(f"Checking layer: {layer.material_name}\n")
|
||||
if "virtual_no_mass" in layer.material_name.lower():
|
||||
layer.thermal_resistance = new_thermal_resistance
|
||||
sys.stderr.write(f"Set thermal resistance to {new_thermal_resistance} for {layer.material_name} in {boundary.type}\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
def enrich(self):
|
||||
if self._retrofit_type == 'basic':
|
||||
self.apply_retrofit(
|
||||
OutdoorsWall=0.85,
|
||||
GroundWall=0.85,
|
||||
OutdoorsRoofCeiling=0.95,
|
||||
GroundRoofCeiling=0.95,
|
||||
OutdoorsFloor=0.95,
|
||||
GroundFloor=0.95
|
||||
)
|
||||
# After applying the retrofit, set a specific thermal resistance
|
||||
self.modify_thermal_resistance(2.0)
|
||||
# Add more retrofit types as needed
|
||||
for building in self._city.buildings:
|
||||
building_id = str(building.name) # Convert ID to string to match JSON keys
|
||||
if building_id in self._retrofit_data:
|
||||
print(f"Applying retrofits to building ID {building_id}")
|
||||
building_retrofit_data = self._retrofit_data[building_id]
|
||||
retrofit_types = building_retrofit_data.get('retrofit_types', [])
|
||||
self._apply_retrofits_to_building(building, retrofit_types, building_retrofit_data)
|
||||
else:
|
||||
print(f"No retrofit data for building ID {building_id}")
|
||||
|
||||
def _apply_retrofits_to_building(self, building, retrofit_types, retrofit_params):
|
||||
if 'construction' in retrofit_types:
|
||||
self._apply_construction_retrofit_to_building(building, retrofit_params)
|
||||
if 'infiltration' in retrofit_types:
|
||||
self._reduce_infiltration_rate_by_percentage(building, retrofit_params)
|
||||
if 'windows' in retrofit_types:
|
||||
self._apply_window_retrofit_to_building(building, retrofit_params)
|
||||
|
||||
def _apply_construction_retrofit_to_building(self, building: Building, retrofit_params):
|
||||
wall_u_value = retrofit_params.get('wall_u_value')
|
||||
roof_u_value = retrofit_params.get('roof_u_value')
|
||||
ground_u_value = retrofit_params.get('ground_u_value')
|
||||
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
if wall_u_value is not None and thermal_boundary.type == cte.WALL and thermal_boundary.u_value > wall_u_value:
|
||||
self._change_thermal_resistance(thermal_boundary, wall_u_value)
|
||||
thermal_boundary.u_value = wall_u_value
|
||||
print(f"Updated wall U-value to {wall_u_value} in building {building.name}")
|
||||
elif roof_u_value is not None and thermal_boundary.type == cte.ROOF and thermal_boundary.u_value > roof_u_value:
|
||||
self._change_thermal_resistance(thermal_boundary, roof_u_value)
|
||||
thermal_boundary.u_value = roof_u_value
|
||||
print(f"Updated roof U-value to {roof_u_value} in building {building.name}")
|
||||
elif ground_u_value is not None and thermal_boundary.type == cte.GROUND and thermal_boundary.u_value > ground_u_value:
|
||||
self._change_thermal_resistance(thermal_boundary, ground_u_value)
|
||||
thermal_boundary.u_value = ground_u_value
|
||||
print(f"Updated ground U-value to {ground_u_value} in building {building.name}")
|
||||
|
||||
def _change_thermal_resistance(self, thermal_boundary, new_u_value):
|
||||
old_u_value = thermal_boundary.u_value
|
||||
if new_u_value < old_u_value:
|
||||
delta_r = (1 / new_u_value) - (1 / old_u_value)
|
||||
for layer in thermal_boundary.layers:
|
||||
if "virtual_no_mass" in layer.material_name.lower():
|
||||
new_thermal_resistance = layer.thermal_resistance + delta_r
|
||||
layer.thermal_resistance = new_thermal_resistance
|
||||
print(f"Increased thermal resistance by {delta_r} in layer {layer.material_name}")
|
||||
else:
|
||||
print(f"New U-value {new_u_value} is not less than old U-value {old_u_value} for thermal boundary type {thermal_boundary.type}")
|
||||
|
||||
def _reduce_infiltration_rate_by_percentage(self, building: Building, retrofit_params):
|
||||
percentage = retrofit_params.get('infiltration_reduction')
|
||||
if percentage is None:
|
||||
return
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
#change infiltration rate in thermal_zone.parent_internal_zone.thermal_archetype.
|
||||
thermal_archetype = thermal_zone.parent_internal_zone.thermal_archetype
|
||||
old_rate = thermal_archetype.infiltration_rate_for_ventilation_system_off
|
||||
new_rate = old_rate * (1 - percentage / 100)
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_off = new_rate
|
||||
print(f"Reduced infiltration rate from {old_rate} to {new_rate} in building {building.name}")
|
||||
|
||||
|
||||
|
||||
def _apply_window_retrofit_to_building(self, building: Building, retrofit_params):
|
||||
overall_u_value = retrofit_params.get('window_u_value')
|
||||
g_value = retrofit_params.get('window_g_value')
|
||||
|
||||
for thermal_zone in building.thermal_zones_from_internal_zones:
|
||||
for thermal_boundary in thermal_zone.thermal_boundaries:
|
||||
if thermal_boundary.type == cte.WALL:
|
||||
#change window u_value and g_value in _construction_archetype
|
||||
construction_archetype = thermal_boundary._construction_archetype
|
||||
construction_archetype.window_overall_u_value = overall_u_value
|
||||
construction_archetype.window_g_value = g_value
|
||||
|
||||
if hasattr(thermal_boundary, 'thermal_openings') and thermal_boundary.thermal_openings:
|
||||
for opening in thermal_boundary.thermal_openings:
|
||||
if overall_u_value is not None and overall_u_value != 0:
|
||||
old_u_value = opening.overall_u_value
|
||||
opening.overall_u_value = overall_u_value
|
||||
print(f"Changed window U-value from {old_u_value} to {opening.overall_u_value} in building {building.name}")
|
||||
if g_value is not None and g_value != 0:
|
||||
old_g_value = opening.g_value
|
||||
opening.g_value = g_value
|
||||
print(f"Changed window g-value from {old_g_value} to {opening.g_value} in building {building.name}")
|
||||
else:
|
||||
print(f"No thermal openings in thermal boundary {thermal_boundary} of type {thermal_boundary.type} in building {building.name}")
|
||||
else:
|
||||
# Skip thermal boundaries that are not walls
|
||||
continue
|
20
input_files/retrofit_scenarios.json
Normal file
20
input_files/retrofit_scenarios.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"175785": {
|
||||
"retrofit_types": ["construction", "windows", "infiltration"],
|
||||
"wall_u_value": 0.2,
|
||||
"roof_u_value": 0.15,
|
||||
"ground_u_value": 0.18,
|
||||
"infiltration_reduction": 30,
|
||||
"window_u_value": 1.1,
|
||||
"window_g_value": 0.6
|
||||
},
|
||||
"175786": {
|
||||
"retrofit_types": ["windows"],
|
||||
"window_u_value": 1.3,
|
||||
"window_g_value": 0.5
|
||||
},
|
||||
"175787": {
|
||||
"retrofit_types": ["infiltration"],
|
||||
"infiltration_reduction": 25
|
||||
}
|
||||
}
|
15
main.py
15
main.py
|
@ -6,13 +6,17 @@ from hub.helpers.dictionaries import Dictionaries
|
|||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.usage_factory import UsageFactory
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.imports.retrofit_factory import RetrofitFactory
|
||||
|
||||
from hub.imports.retrofit_factory_virtual import RetrofitFactory
|
||||
import json
|
||||
# Specify the GeoJSON file path
|
||||
input_files_path = (Path(__file__).parent / 'input_files')
|
||||
input_files_path.mkdir(parents=True, exist_ok=True)
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
|
||||
geojson_file_path = input_files_path / 'input_one_buildings.geojson'
|
||||
|
||||
retrofit_json_file_path = input_files_path / 'retrofit_scenarios.json'
|
||||
with open(retrofit_json_file_path, 'r') as f:
|
||||
retrofit_data = json.load(f)
|
||||
output_path = (Path(__file__).parent / 'out_files').resolve()
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
# Create city object from GeoJSON file
|
||||
|
@ -23,9 +27,10 @@ city = GeometryFactory('geojson',
|
|||
function_field='function',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
# Enrich city data
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
RetrofitFactory('basic', city).enrich()
|
||||
ConstructionFactory('cerc', city).enrich()
|
||||
UsageFactory('cerc', city).enrich()
|
||||
# Apply retrofits based on JSON data using building IDs
|
||||
RetrofitFactory(retrofit_data, city).enrich()
|
||||
|
||||
WeatherFactory('epw', city).enrich()
|
||||
energy_plus_workflow(city)
|
||||
|
|
Loading…
Reference in New Issue
Block a user