this class has been extracted from the monthly_energy_balance project and a complete project to manage the interaction with sra has been created (this one)
This commit is contained in:
parent
a4d3fbaab9
commit
b585e6cac2
4
cache/.gitignore
vendored
Normal file
4
cache/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
37
helper/helper.py
Normal file
37
helper/helper.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
"""
|
||||||
|
Helper class for SRA
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
import helpers.constants as cte
|
||||||
|
|
||||||
|
|
||||||
|
class Helper:
|
||||||
|
def __init__(self):
|
||||||
|
self._month_hour = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def month_hour(self):
|
||||||
|
"""
|
||||||
|
returns a DataFrame that has x values of the month number (January = 1, February = 2...),
|
||||||
|
being x the number of hours of the corresponding month
|
||||||
|
:return: DataFrame(int)
|
||||||
|
"""
|
||||||
|
array = []
|
||||||
|
for i in range(0, 12):
|
||||||
|
total_hours = cte.days_of_month[i] * 24
|
||||||
|
array = np.concatenate((array, np.full(total_hours, i + 1)))
|
||||||
|
self._month_hour = pd.DataFrame(array, columns=['month'])
|
||||||
|
return self._month_hour
|
||||||
|
|
||||||
|
def get_mean_values(self, values):
|
||||||
|
out = None
|
||||||
|
if values is not None:
|
||||||
|
if 'month' not in values.columns:
|
||||||
|
values = pd.concat([self.month_hour, pd.DataFrame(values)], axis=1)
|
||||||
|
out = values.groupby('month', as_index=False).mean()
|
||||||
|
del out['month']
|
||||||
|
return out
|
157
simplified_radiosity_algorithm.py
Normal file
157
simplified_radiosity_algorithm.py
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
"""
|
||||||
|
SimplifiedRadiosityAlgorithm manage the interaction with the third party software CitySim_SRA
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar_monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
import pandas as pd
|
||||||
|
import subprocess
|
||||||
|
from subprocess import SubprocessError, TimeoutExpired, CalledProcessError
|
||||||
|
|
||||||
|
from exports.exports_factory import ExportsFactory
|
||||||
|
from imports.weather_factory import WeatherFactory
|
||||||
|
from helper.helper import Helper as mv
|
||||||
|
|
||||||
|
|
||||||
|
class SimplifiedRadiosityAlgorithm:
|
||||||
|
"""
|
||||||
|
SimplifiedRadiosityAlgorithm factory class
|
||||||
|
"""
|
||||||
|
# todo: define executable as configurable parameter
|
||||||
|
# _executable = 'citysim_sra' # for linux
|
||||||
|
_executable = 'shortwave_integer' # for windows
|
||||||
|
|
||||||
|
def __init__(self, city, sra_working_path, weather_file_name):
|
||||||
|
self._city = city
|
||||||
|
self._sra_working_path = sra_working_path
|
||||||
|
self._weather_file_name = weather_file_name
|
||||||
|
self._sra_in_file_name = self._city.name + '_sra.xml'
|
||||||
|
self._sra_out_file_name = self._city.name + '_sra_SW.out'
|
||||||
|
|
||||||
|
self._tmp_path = (sra_working_path / 'tmp').resolve()
|
||||||
|
Path(self._tmp_path).mkdir(parents=True, exist_ok=True)
|
||||||
|
# Ensure tmp file is empty
|
||||||
|
for child in self._tmp_path.glob('*'):
|
||||||
|
if child.is_file():
|
||||||
|
child.unlink()
|
||||||
|
|
||||||
|
self._cache_path = (sra_working_path / 'cache').resolve()
|
||||||
|
Path(self._cache_path).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
self._results = None
|
||||||
|
self._radiation = []
|
||||||
|
|
||||||
|
def call_sra(self, keep_files=False):
|
||||||
|
"""
|
||||||
|
creates required input files and calls the software
|
||||||
|
"""
|
||||||
|
self._create_cli_file()
|
||||||
|
ExportsFactory('sra', self._city, self._tmp_path).export()
|
||||||
|
try:
|
||||||
|
completed = subprocess.run([self._executable, str(Path(self._tmp_path / self._sra_in_file_name).resolve())])
|
||||||
|
except (SubprocessError, TimeoutExpired, CalledProcessError) as error:
|
||||||
|
raise Exception(error)
|
||||||
|
file = (self._tmp_path / self._sra_out_file_name).resolve()
|
||||||
|
new_path = (self._cache_path / self._sra_out_file_name).resolve()
|
||||||
|
try:
|
||||||
|
shutil.move(str(file), str(new_path))
|
||||||
|
except Exception:
|
||||||
|
raise Exception('No SRA output file found')
|
||||||
|
if not keep_files:
|
||||||
|
os.remove(Path(self._tmp_path / f'{self._city.name}_sra.xml').resolve())
|
||||||
|
return completed
|
||||||
|
|
||||||
|
@property
|
||||||
|
def results(self):
|
||||||
|
if self._results is None:
|
||||||
|
try:
|
||||||
|
path = (self._cache_path / self._sra_out_file_name).resolve()
|
||||||
|
self._results = pd.read_csv(path, sep='\s+', header=0)
|
||||||
|
except Exception:
|
||||||
|
raise Exception('No SRA output file found')
|
||||||
|
return self._results
|
||||||
|
|
||||||
|
@property
|
||||||
|
def radiation(self) -> []:
|
||||||
|
if len(self._radiation) == 0:
|
||||||
|
id_building = ''
|
||||||
|
header_building = []
|
||||||
|
for column in self.results.columns.values:
|
||||||
|
if id_building != column.split(':')[1]:
|
||||||
|
id_building = column.split(':')[1]
|
||||||
|
if len(header_building) > 0:
|
||||||
|
self._radiation.append(pd.concat([mv().month_hour, self.results[header_building]],
|
||||||
|
axis=1))
|
||||||
|
header_building = [column]
|
||||||
|
else:
|
||||||
|
header_building.append(column)
|
||||||
|
self._radiation.append(pd.concat([mv().month_hour, self.results[header_building]], axis=1))
|
||||||
|
return self._radiation
|
||||||
|
|
||||||
|
def set_irradiance_surfaces(self, city, mode=0, building_name=None):
|
||||||
|
"""
|
||||||
|
saves in building surfaces the correspondent irradiance at different time-scales depending on the mode
|
||||||
|
if building is None, it saves all buildings' surfaces in file, if building is specified, it saves only that
|
||||||
|
specific building values
|
||||||
|
mode = 0, set only monthly values
|
||||||
|
mode = 1, set only hourly values
|
||||||
|
mode = 2, set both
|
||||||
|
:parameter city: city
|
||||||
|
:parameter mode: str (time-scale definition)
|
||||||
|
:parameter building_name: str
|
||||||
|
:return: none
|
||||||
|
"""
|
||||||
|
for radiation in self.radiation:
|
||||||
|
city_object_name = radiation.columns.values.tolist()[1].split(':')[1]
|
||||||
|
if building_name is not None:
|
||||||
|
if city_object_name != building_name:
|
||||||
|
# todo: in case there is a specific building name defined, then assign values only to that specific building
|
||||||
|
continue
|
||||||
|
|
||||||
|
building = city.city_object(city_object_name)
|
||||||
|
for column in radiation.columns.values:
|
||||||
|
if column == 'month':
|
||||||
|
continue
|
||||||
|
header_id = column
|
||||||
|
surface_id = header_id.split(':')[2]
|
||||||
|
surface = building.surface_by_id(surface_id)
|
||||||
|
new_value = pd.DataFrame(radiation[[header_id]].to_numpy(), columns=['sra'])
|
||||||
|
if mode == 0 or mode == 2:
|
||||||
|
month_new_value = mv().get_mean_values(new_value)
|
||||||
|
if 'month' not in surface.global_irradiance:
|
||||||
|
surface.global_irradiance['month'] = month_new_value
|
||||||
|
else:
|
||||||
|
pd.concat([surface.global_irradiance['month'], month_new_value], axis=1)
|
||||||
|
if mode == 1 or mode == 2:
|
||||||
|
if 'hour' not in surface.global_irradiance:
|
||||||
|
surface.global_irradiance['hour'] = new_value
|
||||||
|
else:
|
||||||
|
pd.concat([surface.global_irradiance['hour'], new_value], axis=1)
|
||||||
|
|
||||||
|
def _create_cli_file(self):
|
||||||
|
file = self._city.climate_file
|
||||||
|
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||||
|
WeatherFactory('epw', self._city, file_name=self._weather_file_name).enrich()
|
||||||
|
content = self._city.name + '\n'
|
||||||
|
content += str(self._city.latitude) + ',' + str(self._city.longitude) + ',0.0,' + str(self._city.time_zone) + '\n'
|
||||||
|
content += '\ndm m h G_Dh G_Bn\n'
|
||||||
|
total_days = 0
|
||||||
|
for month in range(1, 13):
|
||||||
|
if month > 1:
|
||||||
|
total_days += days_in_month[month - 2]
|
||||||
|
for day in range(1, days_in_month[month-1]+1):
|
||||||
|
for hour in range(1, 25):
|
||||||
|
if month == 1:
|
||||||
|
i = 24 * (day-1) + hour - 1
|
||||||
|
else:
|
||||||
|
i = (total_days+day-1)*24 + hour - 1
|
||||||
|
representative_building = self._city.buildings[0]
|
||||||
|
content += str(day) + ' ' + str(month) + ' ' + str(hour) + ' ' \
|
||||||
|
+ str(representative_building.global_horizontal['hour'].epw[i]) + ' ' \
|
||||||
|
+ str(representative_building.beam['hour'].epw[i]) + '\n'
|
||||||
|
with open(file, "w") as file:
|
||||||
|
file.write(content)
|
||||||
|
return
|
4
tmp/.gitignore
vendored
Normal file
4
tmp/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
Loading…
Reference in New Issue
Block a user