monthly_energy_balance/main.py

158 lines
6.8 KiB
Python
Raw Normal View History

2021-02-04 11:17:31 -05:00
"""
Monthly energy balance main
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Pilar Monsalvete Álvarez de Uribarri pilar.monsalvete@concordia.ca
2021-02-04 11:17:31 -05:00
"""
import sys
from pathlib import Path
from argparse import ArgumentParser
import ast
import pandas as pd
import datetime
2021-02-04 11:17:31 -05:00
from helpers import monthly_values as mv
from populate import Populate
from simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm
2021-03-02 18:58:06 -05:00
from imports.geometry_factory import GeometryFactory
from imports.weather_factory import WeatherFactory
2021-02-04 11:17:31 -05:00
from city_model_structure.city import City
from monthly_demand_calculation import MonthlyDemandCalculation
2021-02-04 11:17:31 -05:00
parser = ArgumentParser(description='Monthly energy balance workflow v0.1.')
required = parser.add_argument_group('required arguments')
parser.add_argument('--geometry_type', '-g', help='Geometry type {citygml}', default='citygml')
required.add_argument('--input_geometry_file', '-i', help='Input geometry file', required=True)
parser.add_argument('--use_pickle_file', '-p', help='Use pickle file instead of importing geometry file', default=False,
required=True)
parser.add_argument('--populated_step_in_pickle', '-ps', help='Physics and usage parameters already in pickle file',
default=False, required=True)
parser.add_argument('--weather_step_in_pickle', '-ws', help='Weather parameters already in pickle file',
default=False, required=True)
parser.add_argument('--use_cached_sra_file', '-u', help='Use sra files from cache, instead of freshly calculated sra '
'files', default=False)
required.add_argument('--project_folder', '-f', help='Project folder', required=True)
required.add_argument('--weather_file_name', '-w', help='Weather file', required=True)
required.add_argument('--climate_reference_city', '-c', help='Closest city with climate weather', required=True)
2021-02-04 11:17:31 -05:00
try:
args = parser.parse_args()
except SystemExit:
sys.exit()
keep_files = True
2021-03-02 18:58:06 -05:00
print('begin_time', datetime.datetime.now())
2021-02-04 11:17:31 -05:00
# Step 1: Initialize the city model
pickle_file = ''
if ast.literal_eval(args.use_pickle_file):
pickle_file = Path(args.input_geometry_file).resolve()
city = City.load(pickle_file)
else:
2021-03-02 18:58:06 -05:00
file = Path(args.input_geometry_file).resolve()
pickle_file = Path(str(file).replace('.gml', '.pickle'))
city = GeometryFactory(args.geometry_type, file).city
print(len(city.buildings))
for building in city.buildings:
volume = building.volume
if str(volume) == 'inf':
sys.stderr.write(f'Building {building.name} has geometry errors. It has been removed from the city\n')
city.remove_city_object(building)
2021-03-02 18:58:06 -05:00
city.save(pickle_file)
2021-02-04 11:17:31 -05:00
print('begin_populating_time', datetime.datetime.now())
2021-02-04 11:17:31 -05:00
# Step 2: Populate city adding thermal- and usage-related parameters
populated_step_in_pickle = ast.literal_eval(args.populated_step_in_pickle)
if populated_step_in_pickle:
populated_city = city
else:
populated_city = Populate(city).populated_city
pickle_file = Path(str(pickle_file).replace('.pickle', '_populated.pickle'))
populated_city.save(pickle_file)
if populated_city.buildings is None:
print('No building to be calculated')
sys.exit()
print('begin_weather_time', datetime.datetime.now())
2021-02-04 11:17:31 -05:00
# Step 3: Populate city adding climate-related parameters
weather_format = 'epw'
2021-02-04 11:17:31 -05:00
weather_step_in_pickle = ast.literal_eval(args.weather_step_in_pickle)
if not weather_step_in_pickle:
city.climate_reference_city = args.climate_reference_city
path = (Path(args.project_folder) / 'tmp').resolve()
city.climate_file = (path / f'{args.climate_reference_city}.cli').resolve()
WeatherFactory(weather_format, populated_city, file_name=args.weather_file_name).enrich()
2021-02-04 11:17:31 -05:00
for building in populated_city.buildings:
if 'hour' not in building.external_temperature:
print('No external temperature found')
sys.exit()
if 'month' not in building.external_temperature:
building.external_temperature['month'] = mv.MonthlyValues().\
get_mean_values(building.external_temperature['hour'][[weather_format]])
2021-02-04 11:17:31 -05:00
max_buildings_handled_by_sra = 500
for building in city.buildings:
for surface in building.surfaces:
surface.swr = 0.2
sra = SimplifiedRadiosityAlgorithm(city, Path(args.project_folder).resolve(), args.weather_file_name)
2021-02-04 11:17:31 -05:00
if ast.literal_eval(args.use_cached_sra_file):
sra.results()
sra.set_irradiance_surfaces(populated_city)
else:
total_number_of_buildings = len(city.buildings)
if total_number_of_buildings > max_buildings_handled_by_sra:
radius = 80
2021-02-04 11:17:31 -05:00
for building in city.buildings:
new_city = city.region(building.centroid, radius)
sra_new = SimplifiedRadiosityAlgorithm(new_city, Path(args.project_folder).resolve(), args.weather_file_name)
sra_new.call_sra(weather_format, keep_files=True)
sra_new.set_irradiance_surfaces(populated_city, building_name=building.name)
2021-02-04 11:17:31 -05:00
else:
sra.call_sra(weather_format, keep_files=keep_files)
2021-02-04 11:17:31 -05:00
sra.set_irradiance_surfaces(populated_city)
pickle_file = Path(str(pickle_file).replace('.pickle', '_weather.pickle'))
populated_city.save(pickle_file)
print('begin_user_assignment_time', datetime.datetime.now())
# Step 4: Assign user defined parameters
for building in populated_city.buildings:
building.heated = True
building.cooled = False
building.attic_heated = 2
building.basement_heated = 0
2021-03-02 18:58:06 -05:00
print('begin_insel_time', datetime.datetime.now())
# Step 5: Demand calculation calling INSEL
MonthlyDemandCalculation(city, args.project_folder, weather_format).monthly_demand()
print('begin_write_results_time', datetime.datetime.now())
# Step 5: Print results
2021-02-04 11:17:31 -05:00
print_results = None
file = 'city name: ' + city.name + '\n'
2021-02-04 11:17:31 -05:00
for building in populated_city.buildings:
insel_file_name = building.name + '.insel'
building_results = building.heating['month'].rename(columns={'INSEL': building.name})
if print_results is None:
print_results = building_results
else:
print_results = pd.concat([print_results, building_results], axis='columns')
file += '\n'
file += 'name: ' + building.name + '\n'
file += 'year of construction: ' + building.year_of_construction + '\n'
file += 'function: ' + building.function + '\n'
file += 'floor area: ' + str(building.thermal_zones[0].floor_area) + '\n'
file += 'storeys: ' + str(building.storeys_above_ground) + '\n'
file += 'heated_volume: ' + str(building.volume) + '\n'
file += 'volume: ' + str(building.volume) + '\n'
2021-02-04 11:17:31 -05:00
full_path_results = Path(args.project_folder + '/outputs/heating_demand.csv').resolve()
print_results.to_csv(full_path_results)
full_path_metadata = Path(args.project_folder + '/outputs/metadata.csv').resolve()
with open(full_path_metadata, 'w') as metadata_file:
metadata_file.write(file)
2021-03-02 18:58:06 -05:00
pickle_file = Path(str(pickle_file).replace('.pickle', '_demand.pickle'))
populated_city.save(pickle_file)
2021-03-02 18:58:06 -05:00
print('end_time', datetime.datetime.now())