2024-11-26 05:43:11 -05:00
|
|
|
"""
|
|
|
|
This project aims to assign energy systems archetype names to Montreal buildings.
|
|
|
|
The random assignation is based on statistical information extracted from different sources, being:
|
|
|
|
- For residential buildings:
|
|
|
|
- SHEU 2015: https://oee.nrcan.gc.ca/corporate/statistics/neud/dpa/menus/sheu/2015/tables.cfm
|
|
|
|
- For non-residential buildings:
|
|
|
|
- Montreal dataportal: https://dataportalforcities.org/north-america/canada/quebec/montreal
|
|
|
|
- https://www.eia.gov/consumption/commercial/data/2018/
|
|
|
|
"""
|
|
|
|
import json
|
|
|
|
import random
|
|
|
|
|
|
|
|
from hub.city_model_structure.building import Building
|
|
|
|
|
|
|
|
energy_systems_format = 'montreal_future'
|
|
|
|
|
|
|
|
# parameters:
|
|
|
|
residential_systems_percentage = {
|
2024-12-03 10:40:50 -05:00
|
|
|
'Central Hydronic Air and Gas Source Heating System with Unitary Split Cooling and Air Source HP DHW and Grid Tied PV': 0,
|
2024-11-26 05:43:11 -05:00
|
|
|
'Central Hydronic Air and Electricity Source Heating System with Unitary Split Cooling and Air Source HP DHW and Grid Tied PV': 0,
|
|
|
|
'Central Hydronic Ground and Gas Source Heating System with Unitary Split Cooling and Air Source HP DHW and Grid Tied PV': 0,
|
|
|
|
'Central Hydronic Ground and Electricity Source Heating System with Unitary Split Cooling and Air Source HP DHW '
|
|
|
|
'and Grid Tied PV': 0,
|
|
|
|
'Central Hydronic Water and Gas Source Heating System with Unitary Split Cooling and Air Source HP DHW and Grid Tied PV': 0,
|
|
|
|
'Central Hydronic Water and Electricity Source Heating System with Unitary Split Cooling and Air Source HP DHW '
|
|
|
|
'and Grid Tied PV': 0,
|
|
|
|
'Central Hydronic Air and Gas Source Heating System with Unitary Split and Air Source HP DHW': 0,
|
|
|
|
'Central Hydronic Air and Electricity Source Heating System with Unitary Split and Air Source HP DHW': 0,
|
|
|
|
'Central Hydronic Ground and Gas Source Heating System with Unitary Split and Air Source HP DHW': 0,
|
|
|
|
'Central Hydronic Ground and Electricity Source Heating System with Unitary Split and Air Source HP DHW': 0,
|
|
|
|
'Central Hydronic Water and Gas Source Heating System with Unitary Split and Air Source HP DHW': 0,
|
|
|
|
'Central Hydronic Water and Electricity Source Heating System with Unitary Split and Air Source HP DHW': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'Grid Tied PV System': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 1 gas': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 1 gas grid tied pv': 5,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 1 electricity': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 1 electricity grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 2 gas': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 2 gas grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 2 electricity': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 2 electricity grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 3 and 4 gas': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 3 and 4 gas grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 3 and 4 electricity': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 3 and 4 electricity grid tied pv': 5,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 6 gas': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 6 gas grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 6 electricity': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 6 electricity grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 8 gas': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 8 gas grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
'system 8 electricity': 0,
|
2024-12-03 10:40:50 -05:00
|
|
|
'system 8 electricity grid tied pv': 10,
|
2024-11-26 05:43:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
non_residential_systems_percentage = {'system 1 gas': 0,
|
|
|
|
'system 1 electricity': 0,
|
|
|
|
'system 2 gas': 0,
|
|
|
|
'system 2 electricity': 0,
|
|
|
|
'system 3 and 4 gas': 39,
|
|
|
|
'system 3 and 4 electricity': 36,
|
|
|
|
'system 5 gas': 0,
|
|
|
|
'system 5 electricity': 0,
|
|
|
|
'system 6 gas': 13,
|
|
|
|
'system 6 electricity': 12,
|
|
|
|
'system 8 gas': 0,
|
|
|
|
'system 8 electricity': 0}
|
|
|
|
|
|
|
|
|
|
|
|
def _retrieve_buildings(path, year_of_construction_field=None,
|
|
|
|
function_field=None, function_to_hub=None, aliases_field=None):
|
|
|
|
_buildings = []
|
|
|
|
with open(path, 'r', encoding='utf8') as json_file:
|
|
|
|
_geojson = json.loads(json_file.read())
|
|
|
|
for feature in _geojson['features']:
|
|
|
|
_building = {}
|
|
|
|
year_of_construction = None
|
|
|
|
if year_of_construction_field is not None:
|
|
|
|
year_of_construction = int(feature['properties'][year_of_construction_field])
|
|
|
|
function = None
|
|
|
|
if function_field is not None:
|
|
|
|
function = feature['properties'][function_field]
|
|
|
|
if function_to_hub is not None:
|
|
|
|
# use the transformation dictionary to retrieve the proper function
|
|
|
|
if function in function_to_hub:
|
|
|
|
function = function_to_hub[function]
|
|
|
|
building_name = ''
|
|
|
|
building_aliases = []
|
|
|
|
if 'id' in feature:
|
|
|
|
building_name = feature['id']
|
|
|
|
if aliases_field is not None:
|
|
|
|
for alias_field in aliases_field:
|
|
|
|
building_aliases.append(feature['properties'][alias_field])
|
|
|
|
_building['year_of_construction'] = year_of_construction
|
|
|
|
_building['function'] = function
|
|
|
|
_building['building_name'] = building_name
|
|
|
|
_building['building_aliases'] = building_aliases
|
|
|
|
_buildings.append(_building)
|
|
|
|
return _buildings
|
|
|
|
|
|
|
|
|
|
|
|
def call_random(_buildings: [Building], _systems_percentage):
|
|
|
|
_buildings_with_systems = []
|
|
|
|
_systems_distribution = []
|
2024-12-03 10:40:50 -05:00
|
|
|
_selected_buildings = list(range(len(_buildings)))
|
2024-11-26 05:43:11 -05:00
|
|
|
random.shuffle(_selected_buildings)
|
2024-12-03 10:40:50 -05:00
|
|
|
|
2024-11-26 05:43:11 -05:00
|
|
|
total = 0
|
|
|
|
maximum = 0
|
|
|
|
add_to = 0
|
|
|
|
for _system in _systems_percentage:
|
|
|
|
if _systems_percentage[_system] > 0:
|
|
|
|
number_of_buildings = round(_systems_percentage[_system] / 100 * len(_selected_buildings))
|
|
|
|
_systems_distribution.append({'system': _system, 'number': _systems_percentage[_system],
|
|
|
|
'number_of_buildings': number_of_buildings})
|
|
|
|
if number_of_buildings > maximum:
|
|
|
|
maximum = number_of_buildings
|
|
|
|
add_to = len(_systems_distribution) - 1
|
|
|
|
total += number_of_buildings
|
2024-12-03 10:40:50 -05:00
|
|
|
|
|
|
|
missing = len(_selected_buildings) - total
|
|
|
|
if missing > 0:
|
2024-11-26 05:43:11 -05:00
|
|
|
_systems_distribution[add_to]['number_of_buildings'] += missing
|
2024-12-03 10:40:50 -05:00
|
|
|
elif missing < 0:
|
|
|
|
for case in sorted(_systems_distribution, key=lambda x: -x['number_of_buildings']):
|
|
|
|
if case['number_of_buildings'] > 0:
|
|
|
|
reduce_by = min(-missing, case['number_of_buildings'])
|
|
|
|
case['number_of_buildings'] -= reduce_by
|
|
|
|
missing += reduce_by
|
|
|
|
if missing == 0:
|
|
|
|
break
|
|
|
|
total = sum(case['number_of_buildings'] for case in _systems_distribution)
|
|
|
|
assert total == len(_selected_buildings), f"Final total {total} does not match available {len(_selected_buildings)}"
|
|
|
|
|
2024-11-26 05:43:11 -05:00
|
|
|
_position = 0
|
|
|
|
for case in _systems_distribution:
|
2024-12-03 10:40:50 -05:00
|
|
|
for _ in range(case['number_of_buildings']):
|
2024-11-26 05:43:11 -05:00
|
|
|
_buildings[_selected_buildings[_position]].energy_systems_archetype_name = case['system']
|
|
|
|
_position += 1
|
|
|
|
return _buildings
|