Compare commits
7 Commits
20a801626a
...
ee9dd58f82
Author | SHA1 | Date | |
---|---|---|---|
ee9dd58f82 | |||
e4c761850b | |||
b633dca635 | |||
69a1af535b | |||
b6ec189207 | |||
49a531da8f | |||
d77bd7d337 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,3 +12,5 @@
|
||||
cerc_hub.egg-info
|
||||
/out_files
|
||||
/input_files/output_buildings.geojson
|
||||
*/.pyc
|
||||
*.pyc
|
||||
|
@ -4,16 +4,16 @@ from shapely import Point
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def process_geojson(x, y, diff, expansion=False):
|
||||
def process_geojson(x, y, diff, path, expansion=False):
|
||||
selection_box = Polygon([[x + diff, y - diff],
|
||||
[x - diff, y - diff],
|
||||
[x - diff, y + diff],
|
||||
[x + diff, y + diff]])
|
||||
geojson_file = Path('./data/collinear_clean 2.geojson').resolve()
|
||||
geojson_file = Path(path / 'data/collinear_clean 2.geojson').resolve()
|
||||
if not expansion:
|
||||
output_file = Path('./input_files/output_buildings.geojson').resolve()
|
||||
output_file = Path(path / 'input_files/output_buildings.geojson').resolve()
|
||||
else:
|
||||
output_file = Path('./input_files/output_buildings_expanded.geojson').resolve()
|
||||
output_file = Path(path / 'input_files/output_buildings_expanded.geojson').resolve()
|
||||
buildings_in_region = []
|
||||
|
||||
with open(geojson_file, 'r') as file:
|
||||
|
@ -6,8 +6,6 @@ from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_
|
||||
HeatPumpCooling
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.hvac_dhw_systems_simulation_models.domestic_hot_water_heat_pump_with_tes import \
|
||||
DomesticHotWaterHeatPumpTes
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_model import PVModel
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.electricity_demand_calculator import HourlyElectricityDemand
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
@ -21,10 +19,6 @@ class ArchetypeCluster1:
|
||||
self.heating_results, self.building_heating_hourly_consumption = self.heating_system_simulation()
|
||||
self.cooling_results, self.total_cooling_consumption_hourly = self.cooling_system_simulation()
|
||||
self.dhw_results, self.total_dhw_consumption_hourly = self.dhw_system_simulation()
|
||||
if 'PV' in self.building.energy_systems_archetype_name:
|
||||
self.pv_results = self.pv_system_simulation()
|
||||
else:
|
||||
self.pv_results = None
|
||||
|
||||
def heating_system_simulation(self):
|
||||
building_heating_hourly_consumption = []
|
||||
@ -55,7 +49,7 @@ class ArchetypeCluster1:
|
||||
return results, building_heating_hourly_consumption
|
||||
|
||||
def cooling_system_simulation(self):
|
||||
hp = self.building.energy_systems[1].generation_systems[1]
|
||||
hp = self.building.energy_systems[2].generation_systems[0]
|
||||
cooling_demand_joules = self.building.cooling_demand[cte.HOUR]
|
||||
cooling_peak_load = self.building.cooling_peak_load[cte.YEAR][0]
|
||||
cutoff_temperature = 13
|
||||
@ -71,8 +65,8 @@ class ArchetypeCluster1:
|
||||
|
||||
def dhw_system_simulation(self):
|
||||
building_dhw_hourly_consumption = []
|
||||
hp = self.building.energy_systems[2].generation_systems[0]
|
||||
tes = self.building.energy_systems[2].generation_systems[0].energy_storage_systems[0]
|
||||
hp = self.building.energy_systems[-1].generation_systems[0]
|
||||
tes = self.building.energy_systems[-1].generation_systems[0].energy_storage_systems[0]
|
||||
dhw_demand_joules = self.building.domestic_hot_water_heat_demand[cte.HOUR]
|
||||
upper_limit_tes = 65
|
||||
outdoor_temperature = self.building.external_temperature[cte.HOUR]
|
||||
@ -93,18 +87,6 @@ class ArchetypeCluster1:
|
||||
dhw_consumption = 0
|
||||
return results, building_dhw_hourly_consumption
|
||||
|
||||
def pv_system_simulation(self):
|
||||
results = None
|
||||
pv = self.building.energy_systems[0].generation_systems[0]
|
||||
hourly_electricity_demand = HourlyElectricityDemand(self.building).calculate()
|
||||
model_type = 'fixed_efficiency'
|
||||
if model_type == 'fixed_efficiency':
|
||||
results = PVModel(pv=pv,
|
||||
hourly_electricity_demand_joules=hourly_electricity_demand,
|
||||
solar_radiation=self.building.roofs[0].global_irradiance_tilted[cte.HOUR],
|
||||
installed_pv_area=self.building.roofs[0].installed_solar_collector_area,
|
||||
model_type='fixed_efficiency').fixed_efficiency()
|
||||
return results
|
||||
|
||||
def enrich_building(self):
|
||||
results = self.heating_results | self.cooling_results | self.dhw_results
|
||||
@ -121,19 +103,6 @@ class ArchetypeCluster1:
|
||||
MonthlyValues.get_total_month(self.building.domestic_hot_water_consumption[cte.HOUR]))
|
||||
self.building.domestic_hot_water_consumption[cte.YEAR] = [
|
||||
sum(self.building.domestic_hot_water_consumption[cte.MONTH])]
|
||||
if self.pv_results is not None:
|
||||
self.building.onsite_electrical_production[cte.HOUR] = [x * cte.WATTS_HOUR_TO_JULES for x in
|
||||
self.pv_results['PV Output (W)']]
|
||||
self.building.onsite_electrical_production[cte.MONTH] = MonthlyValues.get_total_month(self.building.onsite_electrical_production[cte.HOUR])
|
||||
self.building.onsite_electrical_production[cte.YEAR] = [sum(self.building.onsite_electrical_production[cte.MONTH])]
|
||||
if self.csv_output:
|
||||
file_name = f'pv_system_simulation_results_{self.building.name}.csv'
|
||||
with open(self.output_path / file_name, 'w', newline='') as csvfile:
|
||||
output_file = csv.writer(csvfile)
|
||||
# Write header
|
||||
output_file.writerow(self.pv_results.keys())
|
||||
# Write data
|
||||
output_file.writerows(zip(*self.pv_results.values()))
|
||||
if self.csv_output:
|
||||
file_name = f'energy_system_simulation_results_{self.building.name}.csv'
|
||||
with open(self.output_path / file_name, 'w', newline='') as csvfile:
|
||||
|
@ -9,7 +9,6 @@ from energy_system_modelling_package.energy_system_modelling_factories.system_si
|
||||
PeakLoadSizing
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.system_sizing_methods.heuristic_sizing import \
|
||||
HeuristicSizing
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_sizing import PVSizing
|
||||
|
||||
|
||||
class EnergySystemsSizingFactory:
|
||||
@ -39,33 +38,6 @@ class EnergySystemsSizingFactory:
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 1
|
||||
|
||||
def _pv_sizing(self):
|
||||
"""
|
||||
Size rooftop, facade or mixture of them for buildings
|
||||
"""
|
||||
system_type = 'rooftop'
|
||||
results = {}
|
||||
if system_type == 'rooftop':
|
||||
surface_azimuth = 180
|
||||
maintenance_factor = 0.1
|
||||
mechanical_equipment_factor = 0.3
|
||||
orientation_factor = 0.1
|
||||
tilt_angle = self._city.latitude
|
||||
pv_sizing = PVSizing(self._city,
|
||||
tilt_angle=tilt_angle,
|
||||
surface_azimuth=surface_azimuth,
|
||||
mechanical_equipment_factor=mechanical_equipment_factor,
|
||||
maintenance_factor=maintenance_factor,
|
||||
orientation_factor=orientation_factor,
|
||||
system_type=system_type)
|
||||
results = pv_sizing.rooftop_sizing()
|
||||
pv_sizing.rooftop_tilted_radiation()
|
||||
|
||||
self._city.level_of_detail.energy_systems = 1
|
||||
for building in self._city.buildings:
|
||||
building.level_of_detail.energy_systems = 1
|
||||
return results
|
||||
|
||||
def _district_heating_cooling_sizing(self):
|
||||
"""
|
||||
Size District Heating and Cooling Network
|
||||
|
@ -6,8 +6,8 @@ class HourlyElectricityDemand:
|
||||
def calculate(self):
|
||||
hourly_electricity_consumption = []
|
||||
energy_systems = self.building.energy_systems
|
||||
appliance = self.building.appliances_electrical_demand[cte.HOUR]
|
||||
lighting = self.building.lighting_electrical_demand[cte.HOUR]
|
||||
appliance = self.building.appliances_electrical_demand[cte.HOUR] if self.building.appliances_electrical_demand else 0
|
||||
lighting = self.building.lighting_electrical_demand[cte.HOUR] if self.building.lighting_electrical_demand else 0
|
||||
elec_heating = 0
|
||||
elec_cooling = 0
|
||||
elec_dhw = 0
|
||||
@ -59,10 +59,12 @@ class HourlyElectricityDemand:
|
||||
else:
|
||||
cooling = self.building.cooling_consumption[cte.HOUR]
|
||||
|
||||
for i in range(len(self.building.heating_demand[cte.HOUR])):
|
||||
for i in range(8760):
|
||||
hourly = 0
|
||||
hourly += appliance[i]
|
||||
hourly += lighting[i]
|
||||
if isinstance(appliance, list):
|
||||
hourly += appliance[i]
|
||||
if isinstance(lighting, list):
|
||||
hourly += lighting[i]
|
||||
if heating is not None:
|
||||
hourly += heating[i]
|
||||
if cooling is not None:
|
||||
|
@ -1,37 +0,0 @@
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from building_modelling.geojson_creator import process_geojson
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.weather_factory import WeatherFactory
|
||||
from hub.imports.results_factory import ResultFactory
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
|
||||
|
||||
def pv_feasibility(current_x, current_y, current_diff, selected_buildings):
|
||||
input_files_path = (Path(__file__).parent.parent.parent.parent / 'input_files')
|
||||
output_path = (Path(__file__).parent.parent.parent.parent / 'out_files').resolve()
|
||||
sra_output_path = output_path / 'sra_outputs' / 'extended_city_sra_outputs'
|
||||
sra_output_path.mkdir(parents=True, exist_ok=True)
|
||||
new_diff = current_diff * 5
|
||||
geojson_file = process_geojson(x=current_x, y=current_y, diff=new_diff, expansion=True)
|
||||
file_path = input_files_path / 'output_buildings.geojson'
|
||||
city = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='height',
|
||||
year_of_construction_field='year_of_construction',
|
||||
function_field='function',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
WeatherFactory('epw', city).enrich()
|
||||
ExportsFactory('sra', city, sra_output_path).export()
|
||||
sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, sra_output_path).enrich()
|
||||
for selected_building in selected_buildings:
|
||||
for building in city.buildings:
|
||||
if selected_building.name == building.name:
|
||||
selected_building.roofs[0].global_irradiance = building.roofs[0].global_irradiance
|
||||
|
||||
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
import math
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class PVModel:
|
||||
def __init__(self, pv, hourly_electricity_demand_joules, solar_radiation, installed_pv_area, model_type, ns=None,
|
||||
np=None):
|
||||
self.pv = pv
|
||||
self.hourly_electricity_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in hourly_electricity_demand_joules]
|
||||
self.solar_radiation = solar_radiation
|
||||
self.installed_pv_area = installed_pv_area
|
||||
self._model_type = '_' + model_type.lower()
|
||||
self.ns = ns
|
||||
self.np = np
|
||||
self.results = {}
|
||||
|
||||
def fixed_efficiency(self):
|
||||
module_efficiency = float(self.pv.electricity_efficiency)
|
||||
variable_names = ["pv_output", "import", "export", "self_sufficiency_ratio"]
|
||||
variables = {name: [0] * len(self.hourly_electricity_demand) for name in variable_names}
|
||||
(pv_out, grid_import, grid_export, self_sufficiency_ratio) = [variables[name] for name in variable_names]
|
||||
for i in range(len(self.hourly_electricity_demand)):
|
||||
pv_out[i] = module_efficiency * self.installed_pv_area * self.solar_radiation[i] / cte.WATTS_HOUR_TO_JULES
|
||||
if pv_out[i] < self.hourly_electricity_demand[i]:
|
||||
grid_import[i] = self.hourly_electricity_demand[i] - pv_out[i]
|
||||
else:
|
||||
grid_export[i] = pv_out[i] - self.hourly_electricity_demand[i]
|
||||
self_sufficiency_ratio[i] = pv_out[i] / self.hourly_electricity_demand[i]
|
||||
self.results['Electricity Demand (W)'] = self.hourly_electricity_demand
|
||||
self.results['PV Output (W)'] = pv_out
|
||||
self.results['Imported from Grid (W)'] = grid_import
|
||||
self.results['Exported to Grid (W)'] = grid_export
|
||||
self.results['Self Sufficiency Ratio'] = self_sufficiency_ratio
|
||||
return self.results
|
||||
|
||||
def enrich(self):
|
||||
"""
|
||||
Enrich the city given to the class using the class given handler
|
||||
:return: None
|
||||
"""
|
||||
return getattr(self, self._model_type, lambda: None)()
|
@ -1,70 +0,0 @@
|
||||
import math
|
||||
import hub.helpers.constants as cte
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.solar_angles import CitySolarAngles
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.radiation_tilted import RadiationTilted
|
||||
|
||||
|
||||
class PVSizing(CitySolarAngles):
|
||||
def __init__(self, city, tilt_angle, surface_azimuth=180, maintenance_factor=0.1, mechanical_equipment_factor=0.3,
|
||||
orientation_factor=0.1, system_type='rooftop'):
|
||||
super().__init__(location_latitude=city.latitude,
|
||||
location_longitude=city.longitude,
|
||||
tilt_angle=tilt_angle,
|
||||
surface_azimuth_angle=surface_azimuth)
|
||||
self.city = city
|
||||
self.maintenance_factor = maintenance_factor
|
||||
self.mechanical_equipment_factor = mechanical_equipment_factor
|
||||
self.orientation_factor = orientation_factor
|
||||
self.angles = self.calculate
|
||||
self.system_type = system_type
|
||||
|
||||
def rooftop_sizing(self):
|
||||
results = {}
|
||||
# Available Roof Area
|
||||
for building in self.city.buildings:
|
||||
for energy_system in building.energy_systems:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.system_type == cte.PHOTOVOLTAIC:
|
||||
module_width = float(generation_system.width)
|
||||
module_height = float(generation_system.height)
|
||||
roof_area = 0
|
||||
for roof in building.roofs:
|
||||
roof_area += roof.perimeter_area
|
||||
pv_module_area = module_width * module_height
|
||||
available_roof = ((self.maintenance_factor + self.orientation_factor + self.mechanical_equipment_factor) *
|
||||
roof_area)
|
||||
# Inter-Row Spacing
|
||||
winter_solstice = self.angles[(self.angles['AST'].dt.month == 12) &
|
||||
(self.angles['AST'].dt.day == 21) &
|
||||
(self.angles['AST'].dt.hour == 12)]
|
||||
solar_altitude = winter_solstice['solar altitude'].values[0]
|
||||
solar_azimuth = winter_solstice['solar azimuth'].values[0]
|
||||
distance = ((module_height * abs(math.cos(math.radians(solar_azimuth)))) /
|
||||
math.tan(math.radians(solar_altitude)))
|
||||
distance = float(format(distance, '.1f'))
|
||||
# Calculation of the number of panels
|
||||
space_dimension = math.sqrt(available_roof)
|
||||
space_dimension = float(format(space_dimension, '.2f'))
|
||||
panels_per_row = math.ceil(space_dimension / module_width)
|
||||
number_of_rows = math.ceil(space_dimension / distance)
|
||||
total_number_of_panels = panels_per_row * number_of_rows
|
||||
total_pv_area = panels_per_row * number_of_rows * pv_module_area
|
||||
building.roofs[0].installed_solar_collector_area = total_pv_area
|
||||
results[f'Building {building.name}'] = {'total_roof_area': roof_area,
|
||||
'PV dedicated area': available_roof,
|
||||
'total_pv_area': total_pv_area,
|
||||
'total_number_of_panels': total_number_of_panels,
|
||||
'number_of_rows': number_of_rows,
|
||||
'panels_per_row': panels_per_row}
|
||||
return results
|
||||
|
||||
def rooftop_tilted_radiation(self):
|
||||
for building in self.city.buildings:
|
||||
RadiationTilted(building=building,
|
||||
solar_angles=self.angles,
|
||||
tilt_angle=self.tilt_angle,
|
||||
ghi=building.roofs[0].global_irradiance[cte.HOUR],
|
||||
).enrich()
|
||||
|
||||
def facade_sizing(self):
|
||||
pass
|
@ -1,59 +0,0 @@
|
||||
import math
|
||||
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.radiation_tilted import RadiationTilted
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class PVSizingSimulation(RadiationTilted):
|
||||
def __init__(self, building, solar_angles, tilt_angle, module_height, module_width, ghi):
|
||||
super().__init__(building, solar_angles, tilt_angle, ghi)
|
||||
self.module_height = module_height
|
||||
self.module_width = module_width
|
||||
self.total_number_of_panels = 0
|
||||
self.enrich()
|
||||
|
||||
def available_space(self):
|
||||
roof_area = self.building.roofs[0].perimeter_area
|
||||
maintenance_factor = 0.1
|
||||
orientation_factor = 0.2
|
||||
if self.building.function == cte.RESIDENTIAL:
|
||||
mechanical_equipment_factor = 0.2
|
||||
else:
|
||||
mechanical_equipment_factor = 0.3
|
||||
available_roof = (maintenance_factor + orientation_factor + mechanical_equipment_factor) * roof_area
|
||||
return available_roof
|
||||
|
||||
def inter_row_spacing(self):
|
||||
winter_solstice = self.df[(self.df['AST'].dt.month == 12) &
|
||||
(self.df['AST'].dt.day == 21) &
|
||||
(self.df['AST'].dt.hour == 12)]
|
||||
solar_altitude = winter_solstice['solar altitude'].values[0]
|
||||
solar_azimuth = winter_solstice['solar azimuth'].values[0]
|
||||
distance = ((self.module_height * abs(math.cos(math.radians(solar_azimuth)))) /
|
||||
math.tan(math.radians(solar_altitude)))
|
||||
distance = float(format(distance, '.1f'))
|
||||
return distance
|
||||
|
||||
def number_of_panels(self, available_roof, inter_row_distance):
|
||||
space_dimension = math.sqrt(available_roof)
|
||||
space_dimension = float(format(space_dimension, '.2f'))
|
||||
panels_per_row = math.ceil(space_dimension / self.module_width)
|
||||
number_of_rows = math.ceil(space_dimension / inter_row_distance)
|
||||
self.total_number_of_panels = panels_per_row * number_of_rows
|
||||
return panels_per_row, number_of_rows
|
||||
|
||||
def pv_output_constant_efficiency(self):
|
||||
radiation = self.total_radiation_tilted
|
||||
pv_module_area = self.module_width * self.module_height
|
||||
available_roof = self.available_space()
|
||||
inter_row_spacing = self.inter_row_spacing()
|
||||
self.number_of_panels(available_roof, inter_row_spacing)
|
||||
self.building.roofs[0].installed_solar_collector_area = pv_module_area * self.total_number_of_panels
|
||||
system_efficiency = 0.2
|
||||
pv_hourly_production = [x * system_efficiency * self.total_number_of_panels * pv_module_area *
|
||||
cte.WATTS_HOUR_TO_JULES for x in radiation]
|
||||
self.building.onsite_electrical_production[cte.HOUR] = pv_hourly_production
|
||||
self.building.onsite_electrical_production[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(self.building.onsite_electrical_production[cte.HOUR]))
|
||||
self.building.onsite_electrical_production[cte.YEAR] = [sum(self.building.onsite_electrical_production[cte.MONTH])]
|
@ -0,0 +1,225 @@
|
||||
import math
|
||||
import csv
|
||||
import hub.helpers.constants as cte
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.electricity_demand_calculator import \
|
||||
HourlyElectricityDemand
|
||||
from hub.catalog_factories.energy_systems_catalog_factory import EnergySystemsCatalogFactory
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class PvSystemAssessment:
|
||||
def __init__(self, building=None, pv_system=None, battery=None, electricity_demand=None, tilt_angle=None,
|
||||
solar_angles=None, pv_installation_type=None, simulation_model_type=None, module_model_name=None,
|
||||
inverter_efficiency=None, system_catalogue_handler=None, roof_percentage_coverage=None,
|
||||
facade_coverage_percentage=None, csv_output=False, output_path=None):
|
||||
"""
|
||||
:param building:
|
||||
:param tilt_angle:
|
||||
:param solar_angles:
|
||||
:param simulation_model_type:
|
||||
:param module_model_name:
|
||||
:param inverter_efficiency:
|
||||
:param system_catalogue_handler:
|
||||
:param roof_percentage_coverage:
|
||||
:param facade_coverage_percentage:
|
||||
"""
|
||||
self.building = building
|
||||
self.electricity_demand = electricity_demand
|
||||
self.tilt_angle = tilt_angle
|
||||
self.solar_angles = solar_angles
|
||||
self.pv_installation_type = pv_installation_type
|
||||
self.simulation_model_type = simulation_model_type
|
||||
self.module_model_name = module_model_name
|
||||
self.inverter_efficiency = inverter_efficiency
|
||||
self.system_catalogue_handler = system_catalogue_handler
|
||||
self.roof_percentage_coverage = roof_percentage_coverage
|
||||
self.facade_coverage_percentage = facade_coverage_percentage
|
||||
self.pv_hourly_generation = None
|
||||
self.t_cell = None
|
||||
self.results = {}
|
||||
self.csv_output = csv_output
|
||||
self.output_path = output_path
|
||||
if pv_system is not None:
|
||||
self.pv_system = pv_system
|
||||
else:
|
||||
for energy_system in self.building.energy_systems:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.system_type == cte.PHOTOVOLTAIC:
|
||||
self.pv_system = generation_system
|
||||
if battery is not None:
|
||||
self.battery = battery
|
||||
else:
|
||||
for energy_system in self.building.energy_systems:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
if generation_system.system_type == cte.PHOTOVOLTAIC and generation_system.energy_storage_systems is not None:
|
||||
for storage_system in generation_system.energy_storage_systems:
|
||||
if storage_system.type_energy_stored == cte.ELECTRICAL:
|
||||
self.battery = storage_system
|
||||
|
||||
@staticmethod
|
||||
def explicit_model(pv_system, inverter_efficiency, number_of_panels, irradiance, outdoor_temperature):
|
||||
inverter_efficiency = inverter_efficiency
|
||||
stc_power = float(pv_system.standard_test_condition_maximum_power)
|
||||
stc_irradiance = float(pv_system.standard_test_condition_radiation)
|
||||
cell_temperature_coefficient = float(pv_system.cell_temperature_coefficient) / 100 if (
|
||||
pv_system.cell_temperature_coefficient is not None) else None
|
||||
stc_t_cell = float(pv_system.standard_test_condition_cell_temperature)
|
||||
nominal_condition_irradiance = float(pv_system.nominal_radiation)
|
||||
nominal_condition_cell_temperature = float(pv_system.nominal_cell_temperature)
|
||||
nominal_t_out = float(pv_system.nominal_ambient_temperature)
|
||||
g_i = irradiance
|
||||
t_out = outdoor_temperature
|
||||
t_cell = []
|
||||
pv_output = []
|
||||
for i in range(len(g_i)):
|
||||
t_cell.append((t_out[i] + (g_i[i] / nominal_condition_irradiance) *
|
||||
(nominal_condition_cell_temperature - nominal_t_out)))
|
||||
pv_output.append((inverter_efficiency * number_of_panels * (stc_power * (g_i[i] / stc_irradiance) *
|
||||
(1 - cell_temperature_coefficient *
|
||||
(t_cell[i] - stc_t_cell)))))
|
||||
return pv_output
|
||||
|
||||
def rooftop_sizing(self):
|
||||
pv_system = self.pv_system
|
||||
if self.module_model_name is not None:
|
||||
self.system_assignation()
|
||||
# System Sizing
|
||||
module_width = float(pv_system.width)
|
||||
module_height = float(pv_system.height)
|
||||
roof_area = 0
|
||||
for roof in self.building.roofs:
|
||||
roof_area += roof.perimeter_area
|
||||
pv_module_area = module_width * module_height
|
||||
available_roof = (self.roof_percentage_coverage * roof_area)
|
||||
# Inter-Row Spacing
|
||||
winter_solstice = self.solar_angles[(self.solar_angles['AST'].dt.month == 12) &
|
||||
(self.solar_angles['AST'].dt.day == 21) &
|
||||
(self.solar_angles['AST'].dt.hour == 12)]
|
||||
solar_altitude = winter_solstice['solar altitude'].values[0]
|
||||
solar_azimuth = winter_solstice['solar azimuth'].values[0]
|
||||
distance = ((module_height * math.sin(math.radians(self.tilt_angle)) * abs(
|
||||
math.cos(math.radians(solar_azimuth)))) / math.tan(math.radians(solar_altitude)))
|
||||
distance = float(format(distance, '.2f'))
|
||||
# Calculation of the number of panels
|
||||
space_dimension = math.sqrt(available_roof)
|
||||
space_dimension = float(format(space_dimension, '.2f'))
|
||||
panels_per_row = math.ceil(space_dimension / module_width)
|
||||
number_of_rows = math.ceil(space_dimension / distance)
|
||||
total_number_of_panels = panels_per_row * number_of_rows
|
||||
total_pv_area = total_number_of_panels * pv_module_area
|
||||
self.building.roofs[0].installed_solar_collector_area = total_pv_area
|
||||
return panels_per_row, number_of_rows
|
||||
|
||||
def system_assignation(self):
|
||||
generation_units_catalogue = EnergySystemsCatalogFactory(self.system_catalogue_handler).catalog
|
||||
catalog_pv_generation_equipments = [component for component in
|
||||
generation_units_catalogue.entries('generation_equipments') if
|
||||
component.system_type == 'photovoltaic']
|
||||
selected_pv_module = None
|
||||
for pv_module in catalog_pv_generation_equipments:
|
||||
if self.module_model_name == pv_module.model_name:
|
||||
selected_pv_module = pv_module
|
||||
if selected_pv_module is None:
|
||||
raise ValueError("No PV module with the provided model name exists in the catalogue")
|
||||
for energy_system in self.building.energy_systems:
|
||||
for idx, generation_system in enumerate(energy_system.generation_systems):
|
||||
if generation_system.system_type == cte.PHOTOVOLTAIC:
|
||||
new_system = selected_pv_module
|
||||
# Preserve attributes that exist in the original but not in the new system
|
||||
for attr in dir(generation_system):
|
||||
# Skip private attributes and methods
|
||||
if not attr.startswith('__') and not callable(getattr(generation_system, attr)):
|
||||
if not hasattr(new_system, attr):
|
||||
setattr(new_system, attr, getattr(generation_system, attr))
|
||||
# Replace the old generation system with the new one
|
||||
energy_system.generation_systems[idx] = new_system
|
||||
|
||||
def grid_tied_system(self):
|
||||
if self.electricity_demand is not None:
|
||||
electricity_demand = self.electricity_demand
|
||||
else:
|
||||
electricity_demand = [demand / cte.WATTS_HOUR_TO_JULES for demand in
|
||||
HourlyElectricityDemand(self.building).calculate()]
|
||||
rooftop_pv_output = [0] * 8760
|
||||
facade_pv_output = [0] * 8760
|
||||
rooftop_number_of_panels = 0
|
||||
if 'rooftop' in self.pv_installation_type.lower():
|
||||
np, ns = self.rooftop_sizing()
|
||||
if self.simulation_model_type == 'explicit':
|
||||
rooftop_number_of_panels = np * ns
|
||||
rooftop_pv_output = self.explicit_model(pv_system=self.pv_system,
|
||||
inverter_efficiency=self.inverter_efficiency,
|
||||
number_of_panels=rooftop_number_of_panels,
|
||||
irradiance=self.building.roofs[0].global_irradiance_tilted[
|
||||
cte.HOUR],
|
||||
outdoor_temperature=self.building.external_temperature[
|
||||
cte.HOUR])
|
||||
|
||||
total_hourly_pv_output = [rooftop_pv_output[i] + facade_pv_output[i] for i in range(8760)]
|
||||
imported_electricity = [0] * 8760
|
||||
exported_electricity = [0] * 8760
|
||||
for i in range(len(electricity_demand)):
|
||||
transfer = total_hourly_pv_output[i] - electricity_demand[i]
|
||||
if transfer > 0:
|
||||
exported_electricity[i] = transfer
|
||||
else:
|
||||
imported_electricity[i] = abs(transfer)
|
||||
|
||||
results = {'building_name': self.building.name,
|
||||
'total_floor_area_m2': self.building.thermal_zones_from_internal_zones[0].total_floor_area,
|
||||
'roof_area_m2': self.building.roofs[0].perimeter_area, 'rooftop_panels': rooftop_number_of_panels,
|
||||
'rooftop_panels_area_m2': self.building.roofs[0].installed_solar_collector_area,
|
||||
'yearly_rooftop_ghi_kW/m2': self.building.roofs[0].global_irradiance[cte.YEAR][0] / 1000,
|
||||
f'yearly_rooftop_tilted_radiation_{self.tilt_angle}_degree_kW/m2':
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.YEAR][0] / 1000,
|
||||
'yearly_rooftop_pv_production_kWh': sum(rooftop_pv_output) / 1000,
|
||||
'yearly_total_pv_production_kWh': sum(total_hourly_pv_output) / 1000,
|
||||
'specific_pv_production_kWh/kWp': sum(rooftop_pv_output) / (
|
||||
float(self.pv_system.standard_test_condition_maximum_power) * rooftop_number_of_panels),
|
||||
'hourly_rooftop_poa_irradiance_W/m2': self.building.roofs[0].global_irradiance_tilted[cte.HOUR],
|
||||
'hourly_rooftop_pv_output_W': rooftop_pv_output, 'T_out': self.building.external_temperature[cte.HOUR],
|
||||
'building_electricity_demand_W': electricity_demand,
|
||||
'total_hourly_pv_system_output_W': total_hourly_pv_output, 'import_from_grid_W': imported_electricity,
|
||||
'export_to_grid_W': exported_electricity}
|
||||
return results
|
||||
|
||||
def enrich(self):
|
||||
system_archetype_name = self.building.energy_systems_archetype_name
|
||||
archetype_name = '_'.join(system_archetype_name.lower().split())
|
||||
if 'grid_tied' in archetype_name:
|
||||
self.results = self.grid_tied_system()
|
||||
hourly_pv_output = self.results['total_hourly_pv_system_output_W']
|
||||
self.building.onsite_electrical_production[cte.HOUR] = hourly_pv_output
|
||||
self.building.onsite_electrical_production[cte.MONTH] = MonthlyValues.get_total_month(hourly_pv_output)
|
||||
self.building.onsite_electrical_production[cte.YEAR] = [sum(hourly_pv_output)]
|
||||
if self.csv_output:
|
||||
self.save_to_csv(self.results, self.output_path, f'{self.building.name}_pv_system_analysis.csv')
|
||||
|
||||
@staticmethod
|
||||
def save_to_csv(data, output_path, filename='rooftop_system_results.csv'):
|
||||
# Separate keys based on whether their values are single values or lists
|
||||
single_value_keys = [key for key, value in data.items() if not isinstance(value, list)]
|
||||
list_value_keys = [key for key, value in data.items() if isinstance(value, list)]
|
||||
|
||||
# Check if all lists have the same length
|
||||
list_lengths = [len(data[key]) for key in list_value_keys]
|
||||
if not all(length == list_lengths[0] for length in list_lengths):
|
||||
raise ValueError("All lists in the dictionary must have the same length")
|
||||
|
||||
# Get the length of list values (assuming all lists are of the same length, e.g., 8760 for hourly data)
|
||||
num_rows = list_lengths[0] if list_value_keys else 1
|
||||
|
||||
# Open the CSV file for writing
|
||||
with open(output_path / filename, mode='w', newline='') as csv_file:
|
||||
writer = csv.writer(csv_file)
|
||||
# Write single-value data as a header section
|
||||
for key in single_value_keys:
|
||||
writer.writerow([key, data[key]])
|
||||
# Write an empty row for separation
|
||||
writer.writerow([])
|
||||
# Write the header for the list values
|
||||
writer.writerow(list_value_keys)
|
||||
# Write each row for the lists
|
||||
for i in range(num_rows):
|
||||
row = [data[key][i] for key in list_value_keys]
|
||||
writer.writerow(row)
|
@ -1,110 +0,0 @@
|
||||
import pandas as pd
|
||||
import math
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class RadiationTilted:
|
||||
def __init__(self, building, solar_angles, tilt_angle, ghi, solar_constant=1366.1, maximum_clearness_index=1,
|
||||
min_cos_zenith=0.065, maximum_zenith_angle=87):
|
||||
self.building = building
|
||||
self.ghi = ghi
|
||||
self.tilt_angle = tilt_angle
|
||||
self.zeniths = solar_angles['zenith'].tolist()[:-1]
|
||||
self.incidents = solar_angles['incident angle'].tolist()[:-1]
|
||||
self.date_time = solar_angles['DateTime'].tolist()[:-1]
|
||||
self.ast = solar_angles['AST'].tolist()[:-1]
|
||||
self.solar_azimuth = solar_angles['solar azimuth'].tolist()[:-1]
|
||||
self.solar_altitude = solar_angles['solar altitude'].tolist()[:-1]
|
||||
data = {'DateTime': self.date_time, 'AST': self.ast, 'solar altitude': self.solar_altitude, 'zenith': self.zeniths,
|
||||
'solar azimuth': self.solar_azimuth, 'incident angle': self.incidents, 'ghi': self.ghi}
|
||||
self.df = pd.DataFrame(data)
|
||||
self.df['DateTime'] = pd.to_datetime(self.df['DateTime'])
|
||||
self.df['AST'] = pd.to_datetime(self.df['AST'])
|
||||
self.df.set_index('DateTime', inplace=True)
|
||||
self.solar_constant = solar_constant
|
||||
self.maximum_clearness_index = maximum_clearness_index
|
||||
self.min_cos_zenith = min_cos_zenith
|
||||
self.maximum_zenith_angle = maximum_zenith_angle
|
||||
self.i_on = []
|
||||
self.i_oh = []
|
||||
self.k_t = []
|
||||
self.fraction_diffuse = []
|
||||
self.diffuse_horizontal = []
|
||||
self.beam_horizontal = []
|
||||
self.dni = []
|
||||
self.beam_tilted = []
|
||||
self.diffuse_tilted = []
|
||||
self.total_radiation_tilted = []
|
||||
self.calculate()
|
||||
|
||||
def dni_extra(self):
|
||||
for i in range(len(self.df)):
|
||||
self.i_on.append(self.solar_constant * (1 + 0.033 * math.cos(math.radians(360 * self.df.index.dayofyear[i] / 365))))
|
||||
|
||||
self.df['extraterrestrial normal radiation (Wh/m2)'] = self.i_on
|
||||
|
||||
def clearness_index(self):
|
||||
for i in range(len(self.df)):
|
||||
self.i_oh.append(self.i_on[i] * max(math.cos(math.radians(self.zeniths[i])), self.min_cos_zenith))
|
||||
self.k_t.append(self.ghi[i] / self.i_oh[i])
|
||||
self.k_t[i] = max(0, self.k_t[i])
|
||||
self.k_t[i] = min(self.maximum_clearness_index, self.k_t[i])
|
||||
self.df['extraterrestrial radiation on horizontal (Wh/m2)'] = self.i_oh
|
||||
self.df['clearness index'] = self.k_t
|
||||
|
||||
def diffuse_fraction(self):
|
||||
for i in range(len(self.df)):
|
||||
if self.k_t[i] <= 0.22:
|
||||
self.fraction_diffuse.append(1 - 0.09 * self.k_t[i])
|
||||
elif self.k_t[i] <= 0.8:
|
||||
self.fraction_diffuse.append(0.9511 - 0.1604 * self.k_t[i] + 4.388 * self.k_t[i] ** 2 -
|
||||
16.638 * self.k_t[i] ** 3 + 12.336 * self.k_t[i] ** 4)
|
||||
else:
|
||||
self.fraction_diffuse.append(0.165)
|
||||
if self.zeniths[i] > self.maximum_zenith_angle:
|
||||
self.fraction_diffuse[i] = 1
|
||||
|
||||
self.df['diffuse fraction'] = self.fraction_diffuse
|
||||
|
||||
def radiation_components_horizontal(self):
|
||||
for i in range(len(self.df)):
|
||||
self.diffuse_horizontal.append(self.ghi[i] * self.fraction_diffuse[i])
|
||||
self.beam_horizontal.append(self.ghi[i] - self.diffuse_horizontal[i])
|
||||
self.dni.append((self.ghi[i] - self.diffuse_horizontal[i]) / math.cos(math.radians(self.zeniths[i])))
|
||||
if self.zeniths[i] > self.maximum_zenith_angle or self.dni[i] < 0:
|
||||
self.dni[i] = 0
|
||||
|
||||
self.df['diffuse horizontal (Wh/m2)'] = self.diffuse_horizontal
|
||||
self.df['dni (Wh/m2)'] = self.dni
|
||||
self.df['beam horizontal (Wh/m2)'] = self.beam_horizontal
|
||||
|
||||
def radiation_components_tilted(self):
|
||||
for i in range(len(self.df)):
|
||||
self.beam_tilted.append(self.dni[i] * math.cos(math.radians(self.incidents[i])))
|
||||
self.beam_tilted[i] = max(self.beam_tilted[i], 0)
|
||||
self.diffuse_tilted.append(self.diffuse_horizontal[i] * ((1 + math.cos(math.radians(self.tilt_angle))) / 2))
|
||||
self.total_radiation_tilted.append(self.beam_tilted[i] + self.diffuse_tilted[i])
|
||||
|
||||
self.df['beam tilted (Wh/m2)'] = self.beam_tilted
|
||||
self.df['diffuse tilted (Wh/m2)'] = self.diffuse_tilted
|
||||
self.df['total radiation tilted (Wh/m2)'] = self.total_radiation_tilted
|
||||
|
||||
def calculate(self) -> pd.DataFrame:
|
||||
self.dni_extra()
|
||||
self.clearness_index()
|
||||
self.diffuse_fraction()
|
||||
self.radiation_components_horizontal()
|
||||
self.radiation_components_tilted()
|
||||
return self.df
|
||||
|
||||
def enrich(self):
|
||||
tilted_radiation = self.total_radiation_tilted
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.HOUR] = tilted_radiation
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.MONTH] = (
|
||||
MonthlyValues.get_total_month(self.building.roofs[0].global_irradiance_tilted[cte.HOUR]))
|
||||
self.building.roofs[0].global_irradiance_tilted[cte.YEAR] = \
|
||||
[sum(self.building.roofs[0].global_irradiance_tilted[cte.MONTH])]
|
||||
|
||||
|
||||
|
@ -1,145 +0,0 @@
|
||||
import math
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class CitySolarAngles:
|
||||
def __init__(self, location_latitude, location_longitude, tilt_angle, surface_azimuth_angle,
|
||||
standard_meridian=-75):
|
||||
self.location_latitude = location_latitude
|
||||
self.location_longitude = location_longitude
|
||||
self.location_latitude_rad = math.radians(location_latitude)
|
||||
self.surface_azimuth_angle = surface_azimuth_angle
|
||||
self.surface_azimuth_rad = math.radians(surface_azimuth_angle)
|
||||
self.tilt_angle = tilt_angle
|
||||
self.tilt_angle_rad = math.radians(tilt_angle)
|
||||
self.standard_meridian = standard_meridian
|
||||
self.longitude_correction = (location_longitude - standard_meridian) * 4
|
||||
self.timezone = 'Etc/GMT+5'
|
||||
|
||||
self.eot = []
|
||||
self.ast = []
|
||||
self.hour_angles = []
|
||||
self.declinations = []
|
||||
self.solar_altitudes = []
|
||||
self.solar_azimuths = []
|
||||
self.zeniths = []
|
||||
self.incidents = []
|
||||
self.beam_tilted = []
|
||||
self.factor = []
|
||||
self.times = pd.date_range(start='2023-01-01', end='2024-01-01', freq='h', tz=self.timezone)
|
||||
self.df = pd.DataFrame(index=self.times)
|
||||
self.day_of_year = self.df.index.dayofyear
|
||||
|
||||
def solar_time(self, datetime_val, day_of_year):
|
||||
b = (day_of_year - 81) * 2 * math.pi / 364
|
||||
eot = 9.87 * math.sin(2 * b) - 7.53 * math.cos(b) - 1.5 * math.sin(b)
|
||||
self.eot.append(eot)
|
||||
|
||||
# Calculate Local Solar Time (LST)
|
||||
lst_hour = datetime_val.hour
|
||||
lst_minute = datetime_val.minute
|
||||
lst_second = datetime_val.second
|
||||
lst = lst_hour + lst_minute / 60 + lst_second / 3600
|
||||
|
||||
# Calculate Apparent Solar Time (AST) in decimal hours
|
||||
ast_decimal = lst + eot / 60 + self.longitude_correction / 60
|
||||
ast_hours = int(ast_decimal)
|
||||
ast_minutes = round((ast_decimal - ast_hours) * 60)
|
||||
|
||||
# Ensure ast_minutes is within valid range
|
||||
if ast_minutes == 60:
|
||||
ast_hours += 1
|
||||
ast_minutes = 0
|
||||
elif ast_minutes < 0:
|
||||
ast_minutes = 0
|
||||
ast_time = datetime(year=datetime_val.year, month=datetime_val.month, day=datetime_val.day,
|
||||
hour=ast_hours, minute=ast_minutes)
|
||||
self.ast.append(ast_time)
|
||||
return ast_time
|
||||
|
||||
def declination_angle(self, day_of_year):
|
||||
declination = 23.45 * math.sin(math.radians(360 / 365 * (284 + day_of_year)))
|
||||
declination_radian = math.radians(declination)
|
||||
self.declinations.append(declination)
|
||||
return declination_radian
|
||||
|
||||
def hour_angle(self, ast_time):
|
||||
hour_angle = ((ast_time.hour * 60 + ast_time.minute) - 720) / 4
|
||||
hour_angle_radian = math.radians(hour_angle)
|
||||
self.hour_angles.append(hour_angle)
|
||||
return hour_angle_radian
|
||||
|
||||
def solar_altitude(self, declination_radian, hour_angle_radian):
|
||||
solar_altitude_radians = math.asin(math.cos(self.location_latitude_rad) * math.cos(declination_radian) *
|
||||
math.cos(hour_angle_radian) + math.sin(self.location_latitude_rad) *
|
||||
math.sin(declination_radian))
|
||||
solar_altitude = math.degrees(solar_altitude_radians)
|
||||
self.solar_altitudes.append(solar_altitude)
|
||||
return solar_altitude_radians
|
||||
|
||||
def zenith(self, solar_altitude_radians):
|
||||
solar_altitude = math.degrees(solar_altitude_radians)
|
||||
zenith_degree = 90 - solar_altitude
|
||||
zenith_radian = math.radians(zenith_degree)
|
||||
self.zeniths.append(zenith_degree)
|
||||
return zenith_radian
|
||||
|
||||
def solar_azimuth_analytical(self, hourangle, declination, zenith):
|
||||
numer = (math.cos(zenith) * math.sin(self.location_latitude_rad) - math.sin(declination))
|
||||
denom = (math.sin(zenith) * math.cos(self.location_latitude_rad))
|
||||
if math.isclose(denom, 0.0, abs_tol=1e-8):
|
||||
cos_azi = 1.0
|
||||
else:
|
||||
cos_azi = numer / denom
|
||||
|
||||
cos_azi = max(-1.0, min(1.0, cos_azi))
|
||||
|
||||
sign_ha = math.copysign(1, hourangle)
|
||||
solar_azimuth_radians = sign_ha * math.acos(cos_azi) + math.pi
|
||||
solar_azimuth_degrees = math.degrees(solar_azimuth_radians)
|
||||
self.solar_azimuths.append(solar_azimuth_degrees)
|
||||
return solar_azimuth_radians
|
||||
|
||||
def incident_angle(self, solar_altitude_radians, solar_azimuth_radians):
|
||||
incident_radian = math.acos(math.cos(solar_altitude_radians) *
|
||||
math.cos(abs(solar_azimuth_radians - self.surface_azimuth_rad)) *
|
||||
math.sin(self.tilt_angle_rad) + math.sin(solar_altitude_radians) *
|
||||
math.cos(self.tilt_angle_rad))
|
||||
incident_angle_degrees = math.degrees(incident_radian)
|
||||
self.incidents.append(incident_angle_degrees)
|
||||
return incident_radian
|
||||
|
||||
@property
|
||||
def calculate(self) -> pd.DataFrame:
|
||||
for i in range(len(self.times)):
|
||||
datetime_val = self.times[i]
|
||||
day_of_year = self.day_of_year[i]
|
||||
declination_radians = self.declination_angle(day_of_year)
|
||||
ast_time = self.solar_time(datetime_val, day_of_year)
|
||||
hour_angle_radians = self.hour_angle(ast_time)
|
||||
solar_altitude_radians = self.solar_altitude(declination_radians, hour_angle_radians)
|
||||
zenith_radians = self.zenith(solar_altitude_radians)
|
||||
solar_azimuth_radians = self.solar_azimuth_analytical(hour_angle_radians, declination_radians, zenith_radians)
|
||||
incident_angle_radian = self.incident_angle(solar_altitude_radians, solar_azimuth_radians)
|
||||
|
||||
self.df['DateTime'] = self.times
|
||||
self.df['AST'] = self.ast
|
||||
self.df['hour angle'] = self.hour_angles
|
||||
self.df['eot'] = self.eot
|
||||
self.df['declination angle'] = self.declinations
|
||||
self.df['solar altitude'] = self.solar_altitudes
|
||||
self.df['zenith'] = self.zeniths
|
||||
self.df['solar azimuth'] = self.solar_azimuths
|
||||
self.df['incident angle'] = self.incidents
|
||||
|
||||
return self.df
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,221 @@
|
||||
import math
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.monthly_values import MonthlyValues
|
||||
|
||||
|
||||
class SolarCalculator:
|
||||
def __init__(self, city, tilt_angle, surface_azimuth_angle, standard_meridian=-75,
|
||||
solar_constant=1366.1, maximum_clearness_index=1, min_cos_zenith=0.065, maximum_zenith_angle=87):
|
||||
"""
|
||||
A class to calculate the solar angles and solar irradiance on a tilted surface in the City
|
||||
:param city: An object from the City class -> City
|
||||
:param tilt_angle: tilt angle of surface -> float
|
||||
:param surface_azimuth_angle: The orientation of the surface. 0 is North -> float
|
||||
:param standard_meridian: A standard meridian is the meridian whose mean solar time is the basis of the time of day
|
||||
observed in a time zone -> float
|
||||
:param solar_constant: The amount of energy received by a given area one astronomical unit away from the Sun. It is
|
||||
constant and must not be changed
|
||||
:param maximum_clearness_index: This is used to calculate the diffuse fraction of the solar irradiance -> float
|
||||
:param min_cos_zenith: This is needed to avoid unrealistic values in tilted irradiance calculations -> float
|
||||
:param maximum_zenith_angle: This is needed to avoid negative values in tilted irradiance calculations -> float
|
||||
"""
|
||||
self.city = city
|
||||
self.location_latitude = city.latitude
|
||||
self.location_longitude = city.longitude
|
||||
self.location_latitude_rad = math.radians(self.location_latitude)
|
||||
self.surface_azimuth_angle = surface_azimuth_angle
|
||||
self.surface_azimuth_rad = math.radians(surface_azimuth_angle)
|
||||
self.tilt_angle = tilt_angle
|
||||
self.tilt_angle_rad = math.radians(tilt_angle)
|
||||
self.standard_meridian = standard_meridian
|
||||
self.longitude_correction = (self.location_longitude - standard_meridian) * 4
|
||||
self.solar_constant = solar_constant
|
||||
self.maximum_clearness_index = maximum_clearness_index
|
||||
self.min_cos_zenith = min_cos_zenith
|
||||
self.maximum_zenith_angle = maximum_zenith_angle
|
||||
timezone_offset = int(-standard_meridian / 15)
|
||||
self.timezone = f'Etc/GMT{"+" if timezone_offset < 0 else "-"}{abs(timezone_offset)}'
|
||||
self.eot = []
|
||||
self.ast = []
|
||||
self.hour_angles = []
|
||||
self.declinations = []
|
||||
self.solar_altitudes = []
|
||||
self.solar_azimuths = []
|
||||
self.zeniths = []
|
||||
self.incidents = []
|
||||
self.i_on = []
|
||||
self.i_oh = []
|
||||
self.times = pd.date_range(start='2023-01-01', end='2023-12-31 23:00', freq='h', tz=self.timezone)
|
||||
self.solar_angles = pd.DataFrame(index=self.times)
|
||||
self.day_of_year = self.solar_angles.index.dayofyear
|
||||
|
||||
def solar_time(self, datetime_val, day_of_year):
|
||||
b = (day_of_year - 81) * 2 * math.pi / 364
|
||||
eot = 9.87 * math.sin(2 * b) - 7.53 * math.cos(b) - 1.5 * math.sin(b)
|
||||
self.eot.append(eot)
|
||||
|
||||
# Calculate Local Solar Time (LST)
|
||||
lst_hour = datetime_val.hour
|
||||
lst_minute = datetime_val.minute
|
||||
lst_second = datetime_val.second
|
||||
lst = lst_hour + lst_minute / 60 + lst_second / 3600
|
||||
|
||||
# Calculate Apparent Solar Time (AST) in decimal hours
|
||||
ast_decimal = lst + eot / 60 + self.longitude_correction / 60
|
||||
ast_hours = int(ast_decimal) % 24 # Adjust hours to fit within 0–23 range
|
||||
ast_minutes = round((ast_decimal - ast_hours) * 60)
|
||||
|
||||
# Ensure ast_minutes is within valid range
|
||||
if ast_minutes == 60:
|
||||
ast_hours += 1
|
||||
ast_minutes = 0
|
||||
elif ast_minutes < 0:
|
||||
ast_minutes = 0
|
||||
ast_time = datetime(year=datetime_val.year, month=datetime_val.month, day=datetime_val.day,
|
||||
hour=ast_hours, minute=ast_minutes)
|
||||
self.ast.append(ast_time)
|
||||
return ast_time
|
||||
|
||||
def declination_angle(self, day_of_year):
|
||||
declination = 23.45 * math.sin(math.radians(360 / 365 * (284 + day_of_year)))
|
||||
declination_radian = math.radians(declination)
|
||||
self.declinations.append(declination)
|
||||
return declination_radian
|
||||
|
||||
def hour_angle(self, ast_time):
|
||||
hour_angle = ((ast_time.hour * 60 + ast_time.minute) - 720) / 4
|
||||
hour_angle_radian = math.radians(hour_angle)
|
||||
self.hour_angles.append(hour_angle)
|
||||
return hour_angle_radian
|
||||
|
||||
def solar_altitude(self, declination_radian, hour_angle_radian):
|
||||
solar_altitude_radians = math.asin(math.cos(self.location_latitude_rad) * math.cos(declination_radian) *
|
||||
math.cos(hour_angle_radian) + math.sin(self.location_latitude_rad) *
|
||||
math.sin(declination_radian))
|
||||
solar_altitude = math.degrees(solar_altitude_radians)
|
||||
self.solar_altitudes.append(solar_altitude)
|
||||
return solar_altitude_radians
|
||||
|
||||
def zenith(self, solar_altitude_radians):
|
||||
solar_altitude = math.degrees(solar_altitude_radians)
|
||||
zenith_degree = 90 - solar_altitude
|
||||
zenith_radian = math.radians(zenith_degree)
|
||||
self.zeniths.append(zenith_degree)
|
||||
return zenith_radian
|
||||
|
||||
def solar_azimuth_analytical(self, hourangle, declination, zenith):
|
||||
numer = (math.cos(zenith) * math.sin(self.location_latitude_rad) - math.sin(declination))
|
||||
denom = (math.sin(zenith) * math.cos(self.location_latitude_rad))
|
||||
if math.isclose(denom, 0.0, abs_tol=1e-8):
|
||||
cos_azi = 1.0
|
||||
else:
|
||||
cos_azi = numer / denom
|
||||
|
||||
cos_azi = max(-1.0, min(1.0, cos_azi))
|
||||
|
||||
sign_ha = math.copysign(1, hourangle)
|
||||
solar_azimuth_radians = sign_ha * math.acos(cos_azi) + math.pi
|
||||
solar_azimuth_degrees = math.degrees(solar_azimuth_radians)
|
||||
self.solar_azimuths.append(solar_azimuth_degrees)
|
||||
return solar_azimuth_radians
|
||||
|
||||
def incident_angle(self, solar_altitude_radians, solar_azimuth_radians):
|
||||
incident_radian = math.acos(math.cos(solar_altitude_radians) *
|
||||
math.cos(abs(solar_azimuth_radians - self.surface_azimuth_rad)) *
|
||||
math.sin(self.tilt_angle_rad) + math.sin(solar_altitude_radians) *
|
||||
math.cos(self.tilt_angle_rad))
|
||||
incident_angle_degrees = math.degrees(incident_radian)
|
||||
self.incidents.append(incident_angle_degrees)
|
||||
return incident_radian
|
||||
|
||||
def dni_extra(self, day_of_year, zenith_radian):
|
||||
i_on = self.solar_constant * (1 + 0.033 * math.cos(math.radians(360 * day_of_year / 365)))
|
||||
i_oh = i_on * max(math.cos(zenith_radian), self.min_cos_zenith)
|
||||
self.i_on.append(i_on)
|
||||
self.i_oh.append(i_oh)
|
||||
return i_on, i_oh
|
||||
|
||||
def clearness_index(self, ghi, i_oh):
|
||||
k_t = ghi / i_oh
|
||||
k_t = max(0, k_t)
|
||||
k_t = min(self.maximum_clearness_index, k_t)
|
||||
return k_t
|
||||
|
||||
def diffuse_fraction(self, k_t, zenith):
|
||||
if k_t <= 0.22:
|
||||
fraction_diffuse = 1 - 0.09 * k_t
|
||||
elif k_t <= 0.8:
|
||||
fraction_diffuse = (0.9511 - 0.1604 * k_t + 4.388 * k_t ** 2 - 16.638 * k_t ** 3 + 12.336 * k_t ** 4)
|
||||
else:
|
||||
fraction_diffuse = 0.165
|
||||
if zenith > self.maximum_zenith_angle:
|
||||
fraction_diffuse = 1
|
||||
return fraction_diffuse
|
||||
|
||||
def radiation_components_horizontal(self, ghi, fraction_diffuse, zenith):
|
||||
diffuse_horizontal = ghi * fraction_diffuse
|
||||
dni = (ghi - diffuse_horizontal) / math.cos(math.radians(zenith))
|
||||
if zenith > self.maximum_zenith_angle or dni < 0:
|
||||
dni = 0
|
||||
return diffuse_horizontal, dni
|
||||
|
||||
def radiation_components_tilted(self, diffuse_horizontal, dni, incident_angle):
|
||||
beam_tilted = dni * math.cos(math.radians(incident_angle))
|
||||
beam_tilted = max(beam_tilted, 0)
|
||||
diffuse_tilted = diffuse_horizontal * ((1 + math.cos(math.radians(self.tilt_angle))) / 2)
|
||||
total_radiation_tilted = beam_tilted + diffuse_tilted
|
||||
return total_radiation_tilted
|
||||
|
||||
def solar_angles_calculator(self, csv_output=False):
|
||||
for i in range(len(self.times)):
|
||||
datetime_val = self.times[i]
|
||||
day_of_year = self.day_of_year[i]
|
||||
declination_radians = self.declination_angle(day_of_year)
|
||||
ast_time = self.solar_time(datetime_val, day_of_year)
|
||||
hour_angle_radians = self.hour_angle(ast_time)
|
||||
solar_altitude_radians = self.solar_altitude(declination_radians, hour_angle_radians)
|
||||
zenith_radians = self.zenith(solar_altitude_radians)
|
||||
solar_azimuth_radians = self.solar_azimuth_analytical(hour_angle_radians, declination_radians, zenith_radians)
|
||||
self.incident_angle(solar_altitude_radians, solar_azimuth_radians)
|
||||
self.dni_extra(day_of_year=day_of_year, zenith_radian=zenith_radians)
|
||||
self.solar_angles['DateTime'] = self.times
|
||||
self.solar_angles['AST'] = self.ast
|
||||
self.solar_angles['hour angle'] = self.hour_angles
|
||||
self.solar_angles['eot'] = self.eot
|
||||
self.solar_angles['declination angle'] = self.declinations
|
||||
self.solar_angles['solar altitude'] = self.solar_altitudes
|
||||
self.solar_angles['zenith'] = self.zeniths
|
||||
self.solar_angles['solar azimuth'] = self.solar_azimuths
|
||||
self.solar_angles['incident angle'] = self.incidents
|
||||
self.solar_angles['extraterrestrial normal radiation (Wh/m2)'] = self.i_on
|
||||
self.solar_angles['extraterrestrial radiation on horizontal (Wh/m2)'] = self.i_oh
|
||||
if csv_output:
|
||||
self.solar_angles.to_csv('solar_angles_new.csv')
|
||||
|
||||
def tilted_irradiance_calculator(self):
|
||||
if self.solar_angles.empty:
|
||||
self.solar_angles_calculator()
|
||||
for building in self.city.buildings:
|
||||
hourly_tilted_irradiance = []
|
||||
roof_ghi = building.roofs[0].global_irradiance[cte.HOUR]
|
||||
for i in range(len(roof_ghi)):
|
||||
k_t = self.clearness_index(ghi=roof_ghi[i], i_oh=self.i_oh[i])
|
||||
fraction_diffuse = self.diffuse_fraction(k_t, self.zeniths[i])
|
||||
diffuse_horizontal, dni = self.radiation_components_horizontal(ghi=roof_ghi[i],
|
||||
fraction_diffuse=fraction_diffuse,
|
||||
zenith=self.zeniths[i])
|
||||
hourly_tilted_irradiance.append(int(self.radiation_components_tilted(diffuse_horizontal=diffuse_horizontal,
|
||||
dni=dni,
|
||||
incident_angle=self.incidents[i])))
|
||||
|
||||
building.roofs[0].global_irradiance_tilted[cte.HOUR] = hourly_tilted_irradiance
|
||||
building.roofs[0].global_irradiance_tilted[cte.MONTH] = (MonthlyValues.get_total_month(
|
||||
building.roofs[0].global_irradiance_tilted[cte.HOUR]))
|
||||
building.roofs[0].global_irradiance_tilted[cte.YEAR] = [sum(building.roofs[0].global_irradiance_tilted[cte.MONTH])]
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -29,19 +29,41 @@ residential_systems_percentage = {'system 1 gas': 15,
|
||||
'system 8 electricity': 35}
|
||||
|
||||
residential_new_systems_percentage = {
|
||||
'Central 4 Pipes Air to Water Heat Pump and Gas Boiler with Independent Water Heating and PV': 100,
|
||||
'Central 4 Pipes Air to Water Heat Pump and electrical Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and Gas Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and electrical Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and Gas Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and electrical Boiler with Independent Water Heating and PV': 0,
|
||||
'Central 4 Pipes Air to Water Heat Pump and Gas Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Air to Water Heat Pump and electrical Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and Gas Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Ground to Water Heat Pump and electrical Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and Gas Boiler with Independent Water Heating': 0,
|
||||
'Central 4 Pipes Water to Water Heat Pump and electrical Boiler with Independent Water Heating': 0,
|
||||
'Rooftop PV System': 0
|
||||
'Central Hydronic Air and Gas Source Heating System with Unitary Split Cooling and Air Source HP DHW and Grid Tied PV': 100,
|
||||
'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,
|
||||
'Grid Tied PV System': 0,
|
||||
'system 1 gas': 0,
|
||||
'system 1 gas grid tied pv': 0,
|
||||
'system 1 electricity': 0,
|
||||
'system 1 electricity grid tied pv': 0,
|
||||
'system 2 gas': 0,
|
||||
'system 2 gas grid tied pv': 0,
|
||||
'system 2 electricity': 0,
|
||||
'system 2 electricity grid tied pv': 0,
|
||||
'system 3 and 4 gas': 0,
|
||||
'system 3 and 4 gas grid tied pv': 0,
|
||||
'system 3 and 4 electricity': 0,
|
||||
'system 3 and 4 electricity grid tied pv': 0,
|
||||
'system 6 gas': 0,
|
||||
'system 6 gas grid tied pv': 0,
|
||||
'system 6 electricity': 0,
|
||||
'system 6 electricity grid tied pv': 0,
|
||||
'system 8 gas': 0,
|
||||
'system 8 gas grid tied pv': 0,
|
||||
'system 8 electricity': 0,
|
||||
'system 8 electricity grid tied pv': 0,
|
||||
}
|
||||
|
||||
non_residential_systems_percentage = {'system 1 gas': 0,
|
||||
@ -118,4 +140,3 @@ def call_random(_buildings: [Building], _systems_percentage):
|
||||
_buildings[_selected_buildings[_position]].energy_systems_archetype_name = case['system']
|
||||
_position += 1
|
||||
return _buildings
|
||||
|
||||
|
@ -3,8 +3,10 @@ import subprocess
|
||||
from building_modelling.ep_run_enrich import energy_plus_workflow
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.montreal_energy_system_archetype_modelling_factory import \
|
||||
MontrealEnergySystemArchetypesSimulationFactory
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_feasibility import \
|
||||
pv_feasibility
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_system_assessment import \
|
||||
PvSystemAssessment
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.solar_calculator import \
|
||||
SolarCalculator
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
@ -22,9 +24,10 @@ from costing_package.constants import SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
|
||||
# Specify the GeoJSON file path
|
||||
main_path = Path(__file__).parent.resolve()
|
||||
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 = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.00006, path=main_path)
|
||||
geojson_file_path = input_files_path / 'output_buildings.geojson'
|
||||
output_path = (Path(__file__).parent / 'out_files').resolve()
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
@ -34,6 +37,8 @@ simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_res
|
||||
simulation_results_path.mkdir(parents=True, exist_ok=True)
|
||||
sra_output_path = output_path / 'sra_outputs'
|
||||
sra_output_path.mkdir(parents=True, exist_ok=True)
|
||||
pv_assessment_path = output_path / 'pv_outputs'
|
||||
pv_assessment_path.mkdir(parents=True, exist_ok=True)
|
||||
cost_analysis_output_path = output_path / 'cost_analysis'
|
||||
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
|
||||
city = GeometryFactory(file_type='geojson',
|
||||
@ -49,7 +54,6 @@ ExportsFactory('sra', city, sra_output_path).export()
|
||||
sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
ResultFactory('sra', city, sra_output_path).enrich()
|
||||
pv_feasibility(-73.5681295982132, 45.49218262677643, 0.0001, selected_buildings=city.buildings)
|
||||
energy_plus_workflow(city, energy_plus_output_path)
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_systems_percentage)
|
||||
EnergySystemsFactory('montreal_custom', city).enrich()
|
||||
@ -65,12 +69,35 @@ for building in city.buildings:
|
||||
current_status_life_cycle_cost[f'{building.name}'] = cost_data(building, lcc_dataframe, cost_retrofit_scenario)
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
|
||||
EnergySystemsFactory('montreal_future', city).enrich()
|
||||
EnergySystemsSizingFactory('pv_sizing', city).enrich()
|
||||
EnergySystemsSizingFactory('peak_load_sizing', city).enrich()
|
||||
# # Initialize solar calculation parameters (e.g., azimuth, altitude) and compute irradiance and solar angles
|
||||
tilt_angle = 37
|
||||
solar_parameters = SolarCalculator(city=city,
|
||||
surface_azimuth_angle=180,
|
||||
tilt_angle=tilt_angle,
|
||||
standard_meridian=-75)
|
||||
solar_angles = solar_parameters.solar_angles # Obtain solar angles for further analysis
|
||||
solar_parameters.tilted_irradiance_calculator() # Calculate the solar radiation on a tilted surface
|
||||
for building in city.buildings:
|
||||
MontrealEnergySystemArchetypesSimulationFactory(f'archetype_cluster_{building.energy_systems_archetype_cluster_id}',
|
||||
building,
|
||||
simulation_results_path).enrich()
|
||||
if 'PV' in building.energy_systems_archetype_name:
|
||||
PvSystemAssessment(building=building,
|
||||
pv_system=None,
|
||||
battery=None,
|
||||
electricity_demand=None,
|
||||
tilt_angle=tilt_angle,
|
||||
solar_angles=solar_angles,
|
||||
pv_installation_type='rooftop',
|
||||
simulation_model_type='explicit',
|
||||
module_model_name=None,
|
||||
inverter_efficiency=0.95,
|
||||
system_catalogue_handler=None,
|
||||
roof_percentage_coverage=0.75,
|
||||
facade_coverage_percentage=0,
|
||||
csv_output=False,
|
||||
output_path=pv_assessment_path).enrich()
|
||||
retrofitted_energy_consumption = consumption_data(city)
|
||||
retrofitted_life_cycle_cost = {}
|
||||
for building in city.buildings:
|
||||
|
0
example_codes/pv_potential_assessment.py
Normal file
0
example_codes/pv_potential_assessment.py
Normal file
86
example_codes/pv_system_assessment.py
Normal file
86
example_codes/pv_system_assessment.py
Normal file
@ -0,0 +1,86 @@
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from building_modelling.ep_run_enrich import energy_plus_workflow
|
||||
from energy_system_modelling_package import random_assignation
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.pv_system_assessment import \
|
||||
PvSystemAssessment
|
||||
from energy_system_modelling_package.energy_system_modelling_factories.pv_assessment.solar_calculator import \
|
||||
SolarCalculator
|
||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||
from hub.imports.geometry_factory import GeometryFactory
|
||||
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.results_factory import ResultFactory
|
||||
from building_modelling.geojson_creator import process_geojson
|
||||
from hub.exports.exports_factory import ExportsFactory
|
||||
import hub.helpers.constants as cte
|
||||
# Define paths for input and output directories, ensuring directories are created if they do not exist
|
||||
main_path = Path(__file__).parent.parent.resolve()
|
||||
input_files_path = (Path(__file__).parent.parent / 'input_files')
|
||||
input_files_path.mkdir(parents=True, exist_ok=True)
|
||||
output_path = (Path(__file__).parent.parent / 'out_files').resolve()
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
# Define specific paths for outputs from EnergyPlus and SRA (Simplified Radiosity Algorith) and PV calculation processes
|
||||
energy_plus_output_path = output_path / 'energy_plus_outputs'
|
||||
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
|
||||
sra_output_path = output_path / 'sra_outputs'
|
||||
sra_output_path.mkdir(parents=True, exist_ok=True)
|
||||
pv_assessment_path = output_path / 'pv_outputs'
|
||||
pv_assessment_path.mkdir(parents=True, exist_ok=True)
|
||||
# Generate a GeoJSON file for city buildings based on latitude, longitude, and building dimensions
|
||||
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, path=main_path, diff=0.0001)
|
||||
geojson_file_path = input_files_path / 'output_buildings.geojson'
|
||||
# Initialize a city object from the geojson file, mapping building functions using a predefined dictionary
|
||||
city = GeometryFactory(file_type='geojson',
|
||||
path=geojson_file_path,
|
||||
height_field='height',
|
||||
year_of_construction_field='year_of_construction',
|
||||
function_field='function',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
# Enrich city data with construction, usage, and weather information specific to the location
|
||||
ConstructionFactory('nrcan', city).enrich()
|
||||
UsageFactory('nrcan', city).enrich()
|
||||
WeatherFactory('epw', city).enrich()
|
||||
# Execute the EnergyPlus workflow to simulate building energy performance and generate output
|
||||
# energy_plus_workflow(city, energy_plus_output_path)
|
||||
# Export the city data in SRA-compatible format to facilitate solar radiation assessment
|
||||
ExportsFactory('sra', city, sra_output_path).export()
|
||||
# Run SRA simulation using an external command, passing the generated SRA XML file path as input
|
||||
sra_path = (sra_output_path / f'{city.name}_sra.xml').resolve()
|
||||
subprocess.run(['sra', str(sra_path)])
|
||||
# Enrich city data with SRA simulation results for subsequent analysis
|
||||
ResultFactory('sra', city, sra_output_path).enrich()
|
||||
# Assign PV system archetype name to the buildings in city
|
||||
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
|
||||
# Enrich city model with Montreal future systems parameters
|
||||
EnergySystemsFactory('montreal_future', city).enrich()
|
||||
# # Initialize solar calculation parameters (e.g., azimuth, altitude) and compute irradiance and solar angles
|
||||
tilt_angle = 37
|
||||
solar_parameters = SolarCalculator(city=city,
|
||||
surface_azimuth_angle=180,
|
||||
tilt_angle=tilt_angle,
|
||||
standard_meridian=-75)
|
||||
solar_angles = solar_parameters.solar_angles # Obtain solar angles for further analysis
|
||||
solar_parameters.tilted_irradiance_calculator() # Calculate the solar radiation on a tilted surface
|
||||
# # PV modelling building by building
|
||||
#List of available PV modules ['RE400CAA Pure 2', 'RE410CAA Pure 2', 'RE420CAA Pure 2', 'RE430CAA Pure 2',
|
||||
# 'REC600AA Pro M', 'REC610AA Pro M', 'REC620AA Pro M', 'REC630AA Pro M', 'REC640AA Pro M']
|
||||
for building in city.buildings:
|
||||
PvSystemAssessment(building=building,
|
||||
pv_system=None,
|
||||
battery=None,
|
||||
tilt_angle=tilt_angle,
|
||||
solar_angles=solar_angles,
|
||||
pv_installation_type='rooftop',
|
||||
simulation_model_type='explicit',
|
||||
module_model_name='REC640AA Pro M',
|
||||
inverter_efficiency=0.95,
|
||||
system_catalogue_handler='montreal_future',
|
||||
roof_percentage_coverage=0.75,
|
||||
facade_coverage_percentage=0,
|
||||
csv_output=False,
|
||||
output_path=pv_assessment_path).enrich()
|
||||
|
||||
|
@ -22,6 +22,7 @@ class EilatCatalog(Catalog):
|
||||
"""
|
||||
Eilat catalog class
|
||||
"""
|
||||
|
||||
def __init__(self, path):
|
||||
_path_archetypes = Path(path / 'eilat_archetypes.json').resolve()
|
||||
_path_constructions = (path / 'eilat_constructions.json').resolve()
|
||||
@ -121,8 +122,14 @@ class EilatCatalog(Catalog):
|
||||
construction_period = archetype['period_of_construction']
|
||||
average_storey_height = archetype['average_storey_height']
|
||||
extra_loses_due_to_thermal_bridges = archetype['extra_loses_due_thermal_bridges']
|
||||
infiltration_rate_for_ventilation_system_off = archetype['infiltration_rate_for_ventilation_system_off'] / cte.HOUR_TO_SECONDS
|
||||
infiltration_rate_for_ventilation_system_on = archetype['infiltration_rate_for_ventilation_system_on'] / cte.HOUR_TO_SECONDS
|
||||
infiltration_rate_for_ventilation_system_off = archetype[
|
||||
'infiltration_rate_for_ventilation_system_off'] / cte.HOUR_TO_SECONDS
|
||||
infiltration_rate_for_ventilation_system_on = archetype[
|
||||
'infiltration_rate_for_ventilation_system_on'] / cte.HOUR_TO_SECONDS
|
||||
infiltration_rate_area_for_ventilation_system_off = archetype[
|
||||
'infiltration_rate_area_for_ventilation_system_off']
|
||||
infiltration_rate_area_for_ventilation_system_on = archetype[
|
||||
'infiltration_rate_area_for_ventilation_system_on']
|
||||
|
||||
archetype_constructions = []
|
||||
for archetype_construction in archetype['constructions']:
|
||||
@ -160,7 +167,9 @@ class EilatCatalog(Catalog):
|
||||
extra_loses_due_to_thermal_bridges,
|
||||
None,
|
||||
infiltration_rate_for_ventilation_system_off,
|
||||
infiltration_rate_for_ventilation_system_on))
|
||||
infiltration_rate_for_ventilation_system_on,
|
||||
infiltration_rate_area_for_ventilation_system_off,
|
||||
infiltration_rate_area_for_ventilation_system_on))
|
||||
return _catalog_archetypes
|
||||
|
||||
def names(self, category=None):
|
||||
|
@ -128,6 +128,12 @@ class NrcanCatalog(Catalog):
|
||||
infiltration_rate_for_ventilation_system_on = (
|
||||
archetype['infiltration_rate_for_ventilation_system_on'] / cte.HOUR_TO_SECONDS
|
||||
)
|
||||
infiltration_rate_area_for_ventilation_system_off = (
|
||||
archetype['infiltration_rate_area_for_ventilation_system_off'] * 1
|
||||
)
|
||||
infiltration_rate_area_for_ventilation_system_on = (
|
||||
archetype['infiltration_rate_area_for_ventilation_system_on'] * 1
|
||||
)
|
||||
|
||||
archetype_constructions = []
|
||||
for archetype_construction in archetype['constructions']:
|
||||
@ -153,7 +159,6 @@ class NrcanCatalog(Catalog):
|
||||
_window)
|
||||
archetype_constructions.append(_construction)
|
||||
break
|
||||
|
||||
_catalog_archetypes.append(Archetype(archetype_id,
|
||||
name,
|
||||
function,
|
||||
@ -165,7 +170,10 @@ class NrcanCatalog(Catalog):
|
||||
extra_loses_due_to_thermal_bridges,
|
||||
None,
|
||||
infiltration_rate_for_ventilation_system_off,
|
||||
infiltration_rate_for_ventilation_system_on))
|
||||
infiltration_rate_for_ventilation_system_on,
|
||||
infiltration_rate_area_for_ventilation_system_off,
|
||||
infiltration_rate_area_for_ventilation_system_on
|
||||
))
|
||||
return _catalog_archetypes
|
||||
|
||||
def names(self, category=None):
|
||||
|
@ -129,6 +129,12 @@ class NrelCatalog(Catalog):
|
||||
infiltration_rate_for_ventilation_system_on = float(
|
||||
archetype['infiltration_rate_for_ventilation_system_on']['#text']
|
||||
) / cte.HOUR_TO_SECONDS
|
||||
infiltration_rate_area_for_ventilation_system_off = float(
|
||||
archetype['infiltration_rate_area_for_ventilation_system_on']['#text']
|
||||
)
|
||||
infiltration_rate_area_for_ventilation_system_on = float(
|
||||
archetype['infiltration_rate_area_for_ventilation_system_on']['#text']
|
||||
)
|
||||
|
||||
archetype_constructions = []
|
||||
for archetype_construction in archetype['constructions']['construction']:
|
||||
@ -162,7 +168,9 @@ class NrelCatalog(Catalog):
|
||||
extra_loses_due_to_thermal_bridges,
|
||||
indirect_heated_ratio,
|
||||
infiltration_rate_for_ventilation_system_off,
|
||||
infiltration_rate_for_ventilation_system_on))
|
||||
infiltration_rate_for_ventilation_system_on,
|
||||
infiltration_rate_area_for_ventilation_system_off,
|
||||
infiltration_rate_area_for_ventilation_system_on))
|
||||
return _catalog_archetypes
|
||||
|
||||
def names(self, category=None):
|
||||
|
@ -23,7 +23,10 @@ class Archetype:
|
||||
extra_loses_due_to_thermal_bridges,
|
||||
indirect_heated_ratio,
|
||||
infiltration_rate_for_ventilation_system_off,
|
||||
infiltration_rate_for_ventilation_system_on):
|
||||
infiltration_rate_for_ventilation_system_on,
|
||||
infiltration_rate_area_for_ventilation_system_off,
|
||||
infiltration_rate_area_for_ventilation_system_on
|
||||
):
|
||||
self._id = archetype_id
|
||||
self._name = name
|
||||
self._function = function
|
||||
@ -36,6 +39,8 @@ class Archetype:
|
||||
self._indirect_heated_ratio = indirect_heated_ratio
|
||||
self._infiltration_rate_for_ventilation_system_off = infiltration_rate_for_ventilation_system_off
|
||||
self._infiltration_rate_for_ventilation_system_on = infiltration_rate_for_ventilation_system_on
|
||||
self._infiltration_rate_area_for_ventilation_system_off = infiltration_rate_area_for_ventilation_system_off
|
||||
self._infiltration_rate_area_for_ventilation_system_on = infiltration_rate_area_for_ventilation_system_on
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
@ -133,6 +138,22 @@ class Archetype:
|
||||
"""
|
||||
return self._infiltration_rate_for_ventilation_system_on
|
||||
|
||||
@property
|
||||
def infiltration_rate_area_for_ventilation_system_off(self):
|
||||
"""
|
||||
Get archetype infiltration rate for ventilation system off in m3/sm2
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_area_for_ventilation_system_off
|
||||
|
||||
@property
|
||||
def infiltration_rate_area_for_ventilation_system_on(self):
|
||||
"""
|
||||
Get archetype infiltration rate for ventilation system on in m3/sm2
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_for_ventilation_system_on
|
||||
|
||||
def to_dictionary(self):
|
||||
"""Class content to dictionary"""
|
||||
_constructions = []
|
||||
@ -149,6 +170,8 @@ class Archetype:
|
||||
'indirect heated ratio': self.indirect_heated_ratio,
|
||||
'infiltration rate for ventilation off [1/s]': self.infiltration_rate_for_ventilation_system_off,
|
||||
'infiltration rate for ventilation on [1/s]': self.infiltration_rate_for_ventilation_system_on,
|
||||
'infiltration rate area for ventilation off [m3/sm2]': self.infiltration_rate_area_for_ventilation_system_off,
|
||||
'infiltration rate area for ventilation on [m3/sm2]': self.infiltration_rate_area_for_ventilation_system_on,
|
||||
'constructions': _constructions
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ class ThermalStorageSystem(EnergyStorageSystem):
|
||||
'height [m]': self.height,
|
||||
'layers': _layers,
|
||||
'maximum operating temperature [Celsius]': self.maximum_operating_temperature,
|
||||
'storage_medium': self.storage_medium.to_dictionary(),
|
||||
'storage_medium': _medias,
|
||||
'heating coil capacity [W]': self.heating_coil_capacity
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
path = str(path / 'montreal_future_systems.xml')
|
||||
with open(path, 'r', encoding='utf-8') as xml:
|
||||
self._archetypes = xmltodict.parse(xml.read(),
|
||||
force_list=['pv_generation_component', 'templateStorages', 'demand'])
|
||||
force_list=['pv_generation_component', 'templateStorages', 'demand',
|
||||
'system', 'system_id'])
|
||||
|
||||
self._storage_components = self._load_storage_components()
|
||||
self._generation_components = self._load_generation_components()
|
||||
@ -49,7 +50,7 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
'non_pv_generation_component']
|
||||
if non_pv_generation_components is not None:
|
||||
for non_pv in non_pv_generation_components:
|
||||
system_id = non_pv['system_id']
|
||||
system_id = non_pv['generation_system_id']
|
||||
name = non_pv['name']
|
||||
system_type = non_pv['system_type']
|
||||
model_name = non_pv['model_name']
|
||||
@ -181,7 +182,7 @@ class MontrealFutureSystemCatalogue(Catalog):
|
||||
'pv_generation_component']
|
||||
if pv_generation_components is not None:
|
||||
for pv in pv_generation_components:
|
||||
system_id = pv['system_id']
|
||||
system_id = pv['generation_system_id']
|
||||
name = pv['name']
|
||||
system_type = pv['system_type']
|
||||
model_name = pv['model_name']
|
||||
|
@ -840,53 +840,55 @@ class Building(CityObject):
|
||||
Get energy consumption of different sectors
|
||||
return: dict
|
||||
"""
|
||||
fuel_breakdown = {cte.ELECTRICITY: {cte.LIGHTING: self.lighting_electrical_demand[cte.YEAR][0],
|
||||
cte.APPLIANCES: self.appliances_electrical_demand[cte.YEAR][0]}}
|
||||
fuel_breakdown = {cte.ELECTRICITY: {cte.LIGHTING: self.lighting_electrical_demand[cte.YEAR][0] if self.lighting_electrical_demand else 0,
|
||||
cte.APPLIANCES: self.appliances_electrical_demand[cte.YEAR][0] if self.appliances_electrical_demand else 0}}
|
||||
energy_systems = self.energy_systems
|
||||
for energy_system in energy_systems:
|
||||
demand_types = energy_system.demand_types
|
||||
generation_systems = energy_system.generation_systems
|
||||
for demand_type in demand_types:
|
||||
for generation_system in generation_systems:
|
||||
if generation_system.system_type != cte.PHOTOVOLTAIC:
|
||||
if generation_system.fuel_type not in fuel_breakdown:
|
||||
fuel_breakdown[generation_system.fuel_type] = {}
|
||||
if demand_type in generation_system.energy_consumption:
|
||||
fuel_breakdown[f'{generation_system.fuel_type}'][f'{demand_type}'] = (
|
||||
generation_system.energy_consumption)[f'{demand_type}'][cte.YEAR][0]
|
||||
storage_systems = generation_system.energy_storage_systems
|
||||
if storage_systems:
|
||||
for storage_system in storage_systems:
|
||||
if storage_system.type_energy_stored == 'thermal' and storage_system.heating_coil_capacity is not None:
|
||||
fuel_breakdown[cte.ELECTRICITY][f'{demand_type}'] += storage_system.heating_coil_energy_consumption[f'{demand_type}'][cte.YEAR][0]
|
||||
#TODO: When simulation models of all energy system archetypes are created, this part can be removed
|
||||
heating_fuels = []
|
||||
dhw_fuels = []
|
||||
for energy_system in self.energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
heating_fuels.append(generation_system.fuel_type)
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
dhw_fuels.append(generation_system.fuel_type)
|
||||
for key in fuel_breakdown:
|
||||
if key == cte.ELECTRICITY and cte.COOLING not in fuel_breakdown[key]:
|
||||
for energy_system in energy_systems:
|
||||
if cte.COOLING in energy_system.demand_types and cte.COOLING not in fuel_breakdown[key]:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
fuel_breakdown[generation_system.fuel_type][cte.COOLING] = self.cooling_consumption[cte.YEAR][0]
|
||||
for fuel in heating_fuels:
|
||||
if cte.HEATING not in fuel_breakdown[fuel]:
|
||||
if energy_systems is not None:
|
||||
for energy_system in energy_systems:
|
||||
demand_types = energy_system.demand_types
|
||||
generation_systems = energy_system.generation_systems
|
||||
for demand_type in demand_types:
|
||||
for generation_system in generation_systems:
|
||||
if generation_system.system_type != cte.PHOTOVOLTAIC:
|
||||
if generation_system.fuel_type not in fuel_breakdown:
|
||||
fuel_breakdown[generation_system.fuel_type] = {}
|
||||
if demand_type in generation_system.energy_consumption:
|
||||
fuel_breakdown[f'{generation_system.fuel_type}'][f'{demand_type}'] = (
|
||||
generation_system.energy_consumption)[f'{demand_type}'][cte.YEAR][0]
|
||||
storage_systems = generation_system.energy_storage_systems
|
||||
if storage_systems:
|
||||
for storage_system in storage_systems:
|
||||
if storage_system.type_energy_stored == 'thermal' and storage_system.heating_coil_energy_consumption:
|
||||
fuel_breakdown[cte.ELECTRICITY][f'{demand_type}'] += (
|
||||
storage_system.heating_coil_energy_consumption)[f'{demand_type}'][cte.YEAR][0]
|
||||
#TODO: When simulation models of all energy system archetypes are created, this part can be removed
|
||||
heating_fuels = []
|
||||
dhw_fuels = []
|
||||
for energy_system in self.energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
heating_fuels.append(generation_system.fuel_type)
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
dhw_fuels.append(generation_system.fuel_type)
|
||||
for key in fuel_breakdown:
|
||||
if key == cte.ELECTRICITY and cte.COOLING not in fuel_breakdown[key]:
|
||||
for energy_system in energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
fuel_breakdown[generation_system.fuel_type][cte.HEATING] = self.heating_consumption[cte.YEAR][0]
|
||||
for fuel in dhw_fuels:
|
||||
if cte.DOMESTIC_HOT_WATER not in fuel_breakdown[fuel]:
|
||||
for energy_system in energy_systems:
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
for generation_system in energy_system.generation_systems:
|
||||
fuel_breakdown[generation_system.fuel_type][cte.DOMESTIC_HOT_WATER] = self.domestic_hot_water_consumption[cte.YEAR][0]
|
||||
if cte.COOLING in energy_system.demand_types and cte.COOLING not in fuel_breakdown[key]:
|
||||
if self.cooling_consumption:
|
||||
fuel_breakdown[energy_system.generation_systems[0].fuel_type][cte.COOLING] = self.cooling_consumption[cte.YEAR][0]
|
||||
for fuel in heating_fuels:
|
||||
if cte.HEATING not in fuel_breakdown[fuel]:
|
||||
for energy_system in energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
if self.heating_consumption:
|
||||
fuel_breakdown[energy_system.generation_systems[0].fuel_type][cte.HEATING] = self.heating_consumption[cte.YEAR][0]
|
||||
for fuel in dhw_fuels:
|
||||
if cte.DOMESTIC_HOT_WATER not in fuel_breakdown[fuel]:
|
||||
for energy_system in energy_systems:
|
||||
if cte.DOMESTIC_HOT_WATER in energy_system.demand_types:
|
||||
if self.domestic_hot_water_consumption:
|
||||
fuel_breakdown[energy_system.generation_systems[0].fuel_type][cte.DOMESTIC_HOT_WATER] = self.domestic_hot_water_consumption[cte.YEAR][0]
|
||||
self._fuel_consumption_breakdown = fuel_breakdown
|
||||
return self._fuel_consumption_breakdown
|
||||
|
||||
|
@ -132,6 +132,8 @@ class InternalZone:
|
||||
_thermal_boundary = ThermalBoundary(surface, surface.solid_polygon.area, windows_areas)
|
||||
surface.associated_thermal_boundaries = [_thermal_boundary]
|
||||
_thermal_boundaries.append(_thermal_boundary)
|
||||
if self.thermal_archetype is None:
|
||||
return None # there are no archetype
|
||||
_number_of_storeys = int(self.volume / self.area / self.thermal_archetype.average_storey_height)
|
||||
_thermal_zone = ThermalZone(_thermal_boundaries, self, self.volume, self.area, _number_of_storeys)
|
||||
for thermal_boundary in _thermal_zone.thermal_boundaries:
|
||||
|
@ -18,6 +18,7 @@ from hub.city_model_structure.attributes.point import Point
|
||||
from hub.city_model_structure.greenery.vegetation import Vegetation
|
||||
from hub.city_model_structure.building_demand.thermal_boundary import ThermalBoundary
|
||||
import hub.helpers.constants as cte
|
||||
from hub.helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
|
||||
class Surface:
|
||||
@ -41,7 +42,7 @@ class Surface:
|
||||
self._short_wave_reflectance = None
|
||||
self._long_wave_emittance = None
|
||||
self._inverse = None
|
||||
self._associated_thermal_boundaries = []
|
||||
self._associated_thermal_boundaries = None
|
||||
self._vegetation = None
|
||||
self._percentage_shared = None
|
||||
self._solar_collectors_area_reduction_factor = None
|
||||
@ -167,10 +168,10 @@ class Surface:
|
||||
"""
|
||||
if self._type is None:
|
||||
inclination_cos = math.cos(self.inclination)
|
||||
# 170 degrees
|
||||
# 170 degrees
|
||||
if inclination_cos <= -0.98:
|
||||
self._type = 'Ground'
|
||||
# between 80 and 100 degrees
|
||||
# between 80 and 100 degrees
|
||||
elif abs(inclination_cos) <= 0.17:
|
||||
self._type = 'Wall'
|
||||
else:
|
||||
@ -365,12 +366,12 @@ class Surface:
|
||||
_protected_building_restriction = 1
|
||||
# 10 degrees range
|
||||
if abs(math.sin(self.inclination)) < 0.17:
|
||||
# horizontal
|
||||
# horizontal
|
||||
_construction_restriction = 0.8
|
||||
_separation_of_panels = 0.46
|
||||
_shadow_between_panels = 0.7
|
||||
else:
|
||||
# tilted
|
||||
# tilted
|
||||
_construction_restriction = 0.9
|
||||
_separation_of_panels = 0.9
|
||||
_shadow_between_panels = 1
|
||||
@ -417,4 +418,4 @@ class Surface:
|
||||
Set installed solar collector area in m2
|
||||
:return: dict
|
||||
"""
|
||||
self._installed_solar_collector_area = value
|
||||
self._installed_solar_collector_area = value
|
@ -20,6 +20,8 @@ class ThermalArchetype:
|
||||
self._indirect_heated_ratio = None
|
||||
self._infiltration_rate_for_ventilation_system_off = None
|
||||
self._infiltration_rate_for_ventilation_system_on = None
|
||||
self._infiltration_rate_area_for_ventilation_system_off = None
|
||||
self._infiltration_rate_area_for_ventilation_system_on = None
|
||||
|
||||
@property
|
||||
def constructions(self) -> [Construction]:
|
||||
@ -132,3 +134,35 @@ class ThermalArchetype:
|
||||
:param value: float
|
||||
"""
|
||||
self._infiltration_rate_for_ventilation_system_on = value
|
||||
|
||||
@property
|
||||
def infiltration_rate_area_for_ventilation_system_off(self):
|
||||
"""
|
||||
Get infiltration rate for ventilation system off in l/s/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_area_for_ventilation_system_off
|
||||
|
||||
@infiltration_rate_area_for_ventilation_system_off.setter
|
||||
def infiltration_rate_area_for_ventilation_system_off(self, value):
|
||||
"""
|
||||
Set infiltration rate for ventilation system off in l/s/m2
|
||||
:param value: float
|
||||
"""
|
||||
self._infiltration_rate_area_for_ventilation_system_off = value
|
||||
|
||||
@property
|
||||
def infiltration_rate_area_for_ventilation_system_on(self):
|
||||
"""
|
||||
Get infiltration rate for ventilation system on in l/s/m2
|
||||
:return: float
|
||||
"""
|
||||
return self._infiltration_rate_area_for_ventilation_system_on
|
||||
|
||||
@infiltration_rate_area_for_ventilation_system_on.setter
|
||||
def infiltration_rate_area_for_ventilation_system_on(self, value):
|
||||
"""
|
||||
Set infiltration rate for ventilation system on in l/s/m2
|
||||
:param value: float
|
||||
"""
|
||||
self._infiltration_rate_area_for_ventilation_system_on = value
|
||||
|
@ -44,6 +44,8 @@ class ThermalZone:
|
||||
self._indirectly_heated_area_ratio = None
|
||||
self._infiltration_rate_system_on = None
|
||||
self._infiltration_rate_system_off = None
|
||||
self._infiltration_rate_area_system_on = None
|
||||
self._infiltration_rate_area_system_off = None
|
||||
self._volume = volume
|
||||
self._ordinate_number = None
|
||||
self._view_factors_matrix = None
|
||||
@ -166,6 +168,24 @@ class ThermalZone:
|
||||
self._infiltration_rate_system_off = self._parent_internal_zone.thermal_archetype.infiltration_rate_for_ventilation_system_off
|
||||
return self._infiltration_rate_system_off
|
||||
|
||||
@property
|
||||
def infiltration_rate_area_system_on(self):
|
||||
"""
|
||||
Get thermal zone infiltration rate system on in air changes per second (1/s)
|
||||
:return: None or float
|
||||
"""
|
||||
self._infiltration_rate_area_system_on = self._parent_internal_zone.thermal_archetype.infiltration_rate_area_for_ventilation_system_on
|
||||
return self._infiltration_rate_area_system_on
|
||||
|
||||
@property
|
||||
def infiltration_rate_area_system_off(self):
|
||||
"""
|
||||
Get thermal zone infiltration rate system off in air changes per second (1/s)
|
||||
:return: None or float
|
||||
"""
|
||||
self._infiltration_rate_area_system_off = self._parent_internal_zone.thermal_archetype.infiltration_rate_area_for_ventilation_system_off
|
||||
return self._infiltration_rate_area_system_off
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
"""
|
||||
|
@ -8,6 +8,8 @@
|
||||
"extra_loses_due_thermal_bridges": 0.1,
|
||||
"infiltration_rate_for_ventilation_system_on": 0,
|
||||
"infiltration_rate_for_ventilation_system_off": 0.9,
|
||||
"infiltration_rate_area_for_ventilation_system_on": 0,
|
||||
"infiltration_rate_area_for_ventilation_system_off": 0.006,
|
||||
"constructions": {
|
||||
"OutdoorsWall": {
|
||||
"opaque_surface_name": "residential_1000_1980_BWh",
|
||||
@ -42,6 +44,8 @@
|
||||
"extra_loses_due_thermal_bridges": 0.1,
|
||||
"infiltration_rate_for_ventilation_system_on": 0,
|
||||
"infiltration_rate_for_ventilation_system_off": 0.31,
|
||||
"infiltration_rate_area_for_ventilation_system_on": 0,
|
||||
"infiltration_rate_area_for_ventilation_system_off": 0.002,
|
||||
"constructions": {
|
||||
"OutdoorsWall": {
|
||||
"opaque_surface_name": "dormitory_2011_3000_BWh",
|
||||
@ -76,6 +80,8 @@
|
||||
"extra_loses_due_thermal_bridges": 0.09,
|
||||
"infiltration_rate_for_ventilation_system_on": 0,
|
||||
"infiltration_rate_for_ventilation_system_off": 0.65,
|
||||
"infiltration_rate_area_for_ventilation_system_on": 0,
|
||||
"infiltration_rate_area_for_ventilation_system_off": 0.004,
|
||||
"constructions": {
|
||||
"OutdoorsWall": {
|
||||
"opaque_surface_name": "hotel_employees_1981_2010_BWh",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.5</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="2" building_type="medium office" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -44,6 +46,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="3" building_type="large office" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -67,6 +71,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="4" building_type="primary school" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -89,6 +95,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="5" building_type="secondary school" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -111,6 +119,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="6" building_type="stand-alone retail" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -133,6 +143,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="7" building_type="strip mall" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -155,6 +167,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="8" building_type="supermarket" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -177,6 +191,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="9" building_type="quick service restaurant" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -199,6 +215,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="10" building_type="full service restaurant" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -221,6 +239,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="11" building_type="small hotel" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -243,6 +263,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="12" building_type="large hotel" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -265,6 +287,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="13" building_type="hospital" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -287,6 +311,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="14" building_type="outpatient healthcare" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -309,6 +335,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="15" building_type="warehouse" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -331,6 +359,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="16" building_type="midrise apartment" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -353,6 +383,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="17" building_type="high-rise apartment" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -375,6 +407,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="18" building_type="small office" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -397,6 +431,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="19" building_type="medium office" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -419,6 +455,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="20" building_type="large office" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -441,6 +479,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="21" building_type="primary school" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -463,6 +503,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="22" building_type="secondary school" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -485,6 +527,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="23" building_type="stand-alone retail" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -507,6 +551,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="24" building_type="strip mall" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -529,6 +575,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.1</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="25" building_type="supermarket" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -551,6 +599,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="26" building_type="quick service restaurant" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -573,6 +623,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="27" building_type="full service restaurant" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -595,6 +647,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="28" building_type="small hotel" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -617,6 +671,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="29" building_type="large hotel" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -639,6 +695,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="30" building_type="hospital" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -661,6 +719,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="31" building_type="outpatient healthcare" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -683,6 +743,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="32" building_type="warehouse" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -705,6 +767,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="33" building_type="midrise apartment" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -727,6 +791,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="34" building_type="high-rise apartment" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -749,6 +815,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="35" building_type="residential" reference_standard="ASHRAE 189.1_2009" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -771,6 +839,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="36" building_type="residential" reference_standard="ASHRAE 90.1_2004" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -793,6 +863,8 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.50</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.003</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
<archetype id="37" building_type="industry" reference_standard="non_standard_dompark" climate_zone="ASHRAE_2004:4A">
|
||||
<constructions>
|
||||
@ -815,5 +887,7 @@
|
||||
<indirect_heated_ratio units="-">0.15</indirect_heated_ratio>
|
||||
<infiltration_rate_for_ventilation_system_off units="ACH">0.10</infiltration_rate_for_ventilation_system_off>
|
||||
<infiltration_rate_for_ventilation_system_on units="ACH">0</infiltration_rate_for_ventilation_system_on>
|
||||
<infiltration_rate_area_for_ventilation_system_off units="ACH">0.0005</infiltration_rate_area_for_ventilation_system_off>
|
||||
<infiltration_rate_area_for_ventilation_system_on units="ACH">0</infiltration_rate_area_for_ventilation_system_on>
|
||||
</archetype>
|
||||
</archetypes>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -392,9 +392,9 @@ class Idf:
|
||||
thermostat = self._add_thermostat(thermal_zone)
|
||||
self._idf.newidfobject(self._IDEAL_LOAD_AIR_SYSTEM,
|
||||
Zone_Name=zone_name,
|
||||
System_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}',
|
||||
Heating_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}',
|
||||
Cooling_Availability_Schedule_Name=f'HVAC AVAIL SCHEDULES {thermal_zone.usage_name}',
|
||||
System_Availability_Schedule_Name=f'Thermostat_availability schedules {thermal_zone.usage_name}',
|
||||
Heating_Availability_Schedule_Name=f'Thermostat_availability schedules {thermal_zone.usage_name}',
|
||||
Cooling_Availability_Schedule_Name=f'Thermostat_availability schedules {thermal_zone.usage_name}',
|
||||
Template_Thermostat_Name=thermostat.Name)
|
||||
|
||||
def _add_occupancy(self, thermal_zone, zone_name):
|
||||
@ -454,7 +454,7 @@ class Idf:
|
||||
)
|
||||
|
||||
def _add_infiltration(self, thermal_zone, zone_name):
|
||||
schedule = f'Infiltration schedules {thermal_zone.usage_name}'
|
||||
schedule = f'INF_CONST schedules {thermal_zone.usage_name}'
|
||||
_infiltration = thermal_zone.infiltration_rate_system_off * cte.HOUR_TO_SECONDS
|
||||
self._idf.newidfobject(self._INFILTRATION,
|
||||
Name=f'{zone_name}_infiltration',
|
||||
@ -464,6 +464,17 @@ class Idf:
|
||||
Air_Changes_per_Hour=_infiltration
|
||||
)
|
||||
|
||||
def _add_infiltration_surface(self, thermal_zone, zone_name):
|
||||
schedule = f'INF_CONST schedules {thermal_zone.usage_name}'
|
||||
_infiltration = thermal_zone.infiltration_rate_area_system_off*cte.INFILTRATION_75PA_TO_4PA
|
||||
self._idf.newidfobject(self._INFILTRATION,
|
||||
Name=f'{zone_name}_infiltration',
|
||||
Zone_or_ZoneList_or_Space_or_SpaceList_Name=zone_name,
|
||||
Schedule_Name=schedule,
|
||||
Design_Flow_Rate_Calculation_Method='Flow/ExteriorWallArea',
|
||||
Flow_Rate_per_Exterior_Surface_Area=_infiltration
|
||||
)
|
||||
|
||||
def _add_ventilation(self, thermal_zone, zone_name):
|
||||
schedule = f'Ventilation schedules {thermal_zone.usage_name}'
|
||||
_air_change = thermal_zone.mechanical_air_change * cte.HOUR_TO_SECONDS
|
||||
@ -549,9 +560,12 @@ class Idf:
|
||||
self._add_schedules(usage, 'DHW_prof', thermal_zone.domestic_hot_water.schedules)
|
||||
_new_schedules = self._create_yearly_values_schedules('cold_temp', building.cold_water_temperature[cte.HOUR])
|
||||
self._add_schedules(usage, 'cold_temp', _new_schedules)
|
||||
|
||||
_new_schedules = self._create_constant_value_schedules('DHW_temp', service_temperature)
|
||||
self._add_schedules(usage, 'DHW_temp', _new_schedules)
|
||||
_new_schedules = self._create_constant_value_schedules('INF_CONST', 1)
|
||||
self._add_schedules(usage, 'INF_CONST', _new_schedules)
|
||||
_new_schedules = self._create_constant_value_schedules('Thermostat_availability', 1)
|
||||
self._add_schedules(usage, 'Thermostat_availability', _new_schedules)
|
||||
_occ = thermal_zone.occupancy
|
||||
if _occ.occupancy_density == 0:
|
||||
_total_heat = 0
|
||||
@ -562,7 +576,7 @@ class Idf:
|
||||
self._add_schedules(usage, 'Activity Level', _new_schedules)
|
||||
self._add_zone(thermal_zone, building.name)
|
||||
self._add_heating_system(thermal_zone, building.name)
|
||||
self._add_infiltration(thermal_zone, building.name)
|
||||
self._add_infiltration_surface(thermal_zone, building.name)
|
||||
self._add_ventilation(thermal_zone, building.name)
|
||||
self._add_occupancy(thermal_zone, building.name)
|
||||
self._add_lighting(thermal_zone, building.name)
|
||||
@ -611,6 +625,18 @@ class Idf:
|
||||
Reporting_Frequency="Hourly",
|
||||
)
|
||||
|
||||
self._idf.newidfobject(
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Zone Air Temperature",
|
||||
Reporting_Frequency="Hourly",
|
||||
)
|
||||
|
||||
self._idf.newidfobject(
|
||||
"OUTPUT:VARIABLE",
|
||||
Variable_Name="Zone Air Relative Humidity",
|
||||
Reporting_Frequency="Hourly",
|
||||
)
|
||||
|
||||
# post-process to erase windows associated to adiabatic walls
|
||||
windows_list = []
|
||||
for window in self._idf.idfobjects[self._WINDOW]:
|
||||
|
@ -1,4 +1,4 @@
|
||||
!IDD_Version 23.2.0
|
||||
!IDD_Version 24.1.0
|
||||
!IDD_BUILD 7636e6b3e9
|
||||
! ***************************************************************************
|
||||
! This file is the Input Data Dictionary (IDD) for EnergyPlus.
|
||||
@ -30002,10 +30002,10 @@ People,
|
||||
A7 , \field Mean Radiant Temperature Calculation Type
|
||||
\note optional (only required for thermal comfort runs)
|
||||
\type choice
|
||||
\key ZoneAveraged
|
||||
\key EnclosureAveraged
|
||||
\key SurfaceWeighted
|
||||
\key AngleFactor
|
||||
\default ZoneAveraged
|
||||
\default EnclosureAveraged
|
||||
A8 , \field Surface Name/Angle Factor List Name
|
||||
\type object-list
|
||||
\object-list AllHeatTranAngFacNames
|
||||
|
@ -13,7 +13,7 @@
|
||||
! HVAC: None.
|
||||
!
|
||||
|
||||
Version,23.2;
|
||||
Version,24.1;
|
||||
|
||||
Timestep,4;
|
||||
|
||||
@ -154,4 +154,4 @@
|
||||
Output:Meter,InteriorLights:Electricity,hourly;
|
||||
|
||||
OutputControl:IlluminanceMap:Style,
|
||||
Comma; !- Column separator
|
||||
Comma; !- Column separator
|
||||
|
@ -20,9 +20,10 @@ class EnergyBuildingsExportsFactory:
|
||||
"""
|
||||
Energy Buildings exports factory class
|
||||
"""
|
||||
def __init__(self, handler, city, path, custom_insel_block='d18599', target_buildings=None):
|
||||
def __init__(self, handler, city, path, custom_insel_block='d18599', target_buildings=None, weather_file=None):
|
||||
self._city = city
|
||||
self._export_type = '_' + handler.lower()
|
||||
self._weather_file = weather_file
|
||||
validate_import_export_type(EnergyBuildingsExportsFactory, handler)
|
||||
if isinstance(path, str):
|
||||
path = Path(path)
|
||||
@ -53,12 +54,13 @@ class EnergyBuildingsExportsFactory:
|
||||
"""
|
||||
idf_data_path = (Path(__file__).parent / './building_energy/idf_files/').resolve()
|
||||
url = wh().epw_file(self._city.region_code)
|
||||
weather_path = (Path(__file__).parent.parent / f'data/weather/epw/{url.rsplit("/", 1)[1]}').resolve()
|
||||
if not weather_path.exists():
|
||||
with open(weather_path, 'wb') as epw_file:
|
||||
if self._weather_file is None:
|
||||
self._weather_file = (Path(__file__).parent.parent / f'data/weather/epw/{url.rsplit("/", 1)[1]}').resolve()
|
||||
if not self._weather_file.exists():
|
||||
with open(self._weather_file, 'wb') as epw_file:
|
||||
epw_file.write(requests.get(url, allow_redirects=True).content)
|
||||
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path,
|
||||
target_buildings=self._target_buildings)
|
||||
return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'),
|
||||
self._weather_file, target_buildings=self._target_buildings)
|
||||
|
||||
@property
|
||||
def _insel_monthly_energy_balance(self):
|
||||
|
@ -24,6 +24,8 @@ BTU_H_TO_WATTS = 0.29307107
|
||||
KILO_WATTS_HOUR_TO_JULES = 3600000
|
||||
WATTS_HOUR_TO_JULES = 3600
|
||||
GALLONS_TO_QUBIC_METERS = 0.0037854117954011185
|
||||
INFILTRATION_75PA_TO_4PA = (4/75)**0.65
|
||||
|
||||
|
||||
# time
|
||||
SECOND = 'second'
|
||||
@ -301,6 +303,7 @@ GRID = 'Grid'
|
||||
ONSITE_ELECTRICITY = 'Onsite Electricity'
|
||||
PHOTOVOLTAIC = 'Photovoltaic'
|
||||
BOILER = 'Boiler'
|
||||
FURNACE = 'Furnace'
|
||||
HEAT_PUMP = 'Heat Pump'
|
||||
BASEBOARD = 'Baseboard'
|
||||
ELECTRICITY_GENERATOR = 'Electricity generator'
|
||||
|
@ -66,6 +66,8 @@ class EilatPhysicsParameters:
|
||||
thermal_archetype.indirect_heated_ratio = 0
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
|
||||
thermal_archetype.infiltration_rate_area_for_ventilation_system_on = catalog_archetype.infiltration_rate_area_for_ventilation_system_on
|
||||
thermal_archetype.infiltration_rate_area_for_ventilation_system_off = catalog_archetype.infiltration_rate_area_for_ventilation_system_off
|
||||
effective_thermal_capacity = 0
|
||||
_constructions = []
|
||||
for catalog_construction in catalog_archetype.constructions:
|
||||
|
@ -78,6 +78,9 @@ class NrcanPhysicsParameters:
|
||||
thermal_archetype.indirect_heated_ratio = 0
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
|
||||
thermal_archetype.infiltration_rate_area_for_ventilation_system_on = catalog_archetype.infiltration_rate_area_for_ventilation_system_on
|
||||
thermal_archetype.infiltration_rate_area_for_ventilation_system_off = catalog_archetype.infiltration_rate_area_for_ventilation_system_off
|
||||
|
||||
_constructions = []
|
||||
for catalog_construction in catalog_archetype.constructions:
|
||||
construction = Construction()
|
||||
|
@ -69,6 +69,8 @@ class NrelPhysicsParameters:
|
||||
thermal_archetype.indirect_heated_ratio = catalog_archetype.indirect_heated_ratio
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_on = catalog_archetype.infiltration_rate_for_ventilation_system_on
|
||||
thermal_archetype.infiltration_rate_for_ventilation_system_off = catalog_archetype.infiltration_rate_for_ventilation_system_off
|
||||
thermal_archetype.infiltration_rate_area_for_ventilation_system_on = catalog_archetype.infiltration_rate_area_for_ventilation_system_on
|
||||
thermal_archetype.infiltration_rate_area_for_ventilation_system_off = catalog_archetype.infiltration_rate_area_for_ventilation_system_off
|
||||
_constructions = []
|
||||
for catalog_construction in catalog_archetype.constructions:
|
||||
construction = Construction()
|
||||
|
@ -136,3 +136,7 @@ class City(Repository):
|
||||
except SQLAlchemyError as err:
|
||||
logging.error('Error while fetching city by name %s', err)
|
||||
raise SQLAlchemyError from err
|
||||
|
||||
def get_by_id(self, city_id) -> Model:
|
||||
with Session(self.engine) as session:
|
||||
return session.execute(select(Model).where(Model.id == city_id)).first()[0]
|
@ -1,863 +0,0 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56769087843276,
|
||||
45.49251875903776
|
||||
],
|
||||
[
|
||||
-73.56765050367694,
|
||||
45.492560280202284
|
||||
],
|
||||
[
|
||||
-73.5677794213865,
|
||||
45.49262188364245
|
||||
],
|
||||
[
|
||||
-73.56781916241786,
|
||||
45.49258006136105
|
||||
],
|
||||
[
|
||||
-73.56769087843276,
|
||||
45.49251875903776
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 173347,
|
||||
"properties": {
|
||||
"name": "01044617",
|
||||
"address": "rue Victor-Hugo (MTL) 1666",
|
||||
"function": "1000",
|
||||
"height": 9,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56765050367694,
|
||||
45.492560280202284
|
||||
],
|
||||
[
|
||||
-73.56761436875776,
|
||||
45.49259744179384
|
||||
],
|
||||
[
|
||||
-73.5676075694645,
|
||||
45.49260454199484
|
||||
],
|
||||
[
|
||||
-73.56773226889548,
|
||||
45.49266394156485
|
||||
],
|
||||
[
|
||||
-73.56773726906921,
|
||||
45.49266624130272
|
||||
],
|
||||
[
|
||||
-73.5677794213865,
|
||||
45.49262188364245
|
||||
],
|
||||
[
|
||||
-73.56765050367694,
|
||||
45.492560280202284
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 173348,
|
||||
"properties": {
|
||||
"name": "01044619",
|
||||
"address": "rue Victor-Hugo (MTL) 1670",
|
||||
"function": "1000",
|
||||
"height": 9,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56829026835214,
|
||||
45.492524742569145
|
||||
],
|
||||
[
|
||||
-73.56849646900322,
|
||||
45.49262354174874
|
||||
],
|
||||
[
|
||||
-73.56861067001111,
|
||||
45.492505541343576
|
||||
],
|
||||
[
|
||||
-73.56864076915663,
|
||||
45.492519941474434
|
||||
],
|
||||
[
|
||||
-73.56866246900178,
|
||||
45.49249754209202
|
||||
],
|
||||
[
|
||||
-73.56867696946317,
|
||||
45.49250454136644
|
||||
],
|
||||
[
|
||||
-73.56867726964143,
|
||||
45.49250414255471
|
||||
],
|
||||
[
|
||||
-73.56881486931461,
|
||||
45.492362042624144
|
||||
],
|
||||
[
|
||||
-73.56881686903772,
|
||||
45.492359941181455
|
||||
],
|
||||
[
|
||||
-73.5688004699483,
|
||||
45.49235084193039
|
||||
],
|
||||
[
|
||||
-73.56882097012145,
|
||||
45.4923320417195
|
||||
],
|
||||
[
|
||||
-73.56879846891101,
|
||||
45.49232034109352
|
||||
],
|
||||
[
|
||||
-73.56883736970825,
|
||||
45.492284841271946
|
||||
],
|
||||
[
|
||||
-73.56886806888434,
|
||||
45.492256240993704
|
||||
],
|
||||
[
|
||||
-73.56885337003277,
|
||||
45.49224914198001
|
||||
],
|
||||
[
|
||||
-73.56890226932418,
|
||||
45.49219894164121
|
||||
],
|
||||
[
|
||||
-73.56851866897392,
|
||||
45.49201434154299
|
||||
],
|
||||
[
|
||||
-73.56837326884313,
|
||||
45.492163841620254
|
||||
],
|
||||
[
|
||||
-73.56864696910176,
|
||||
45.49229554163243
|
||||
],
|
||||
[
|
||||
-73.5685268682051,
|
||||
45.49241904187041
|
||||
],
|
||||
[
|
||||
-73.56825396962694,
|
||||
45.49228824183907
|
||||
],
|
||||
[
|
||||
-73.56810906858335,
|
||||
45.49243794104013
|
||||
],
|
||||
[
|
||||
-73.56829026835214,
|
||||
45.492524742569145
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 173403,
|
||||
"properties": {
|
||||
"name": "01044334",
|
||||
"address": "rue Saint-Jacques (MTL) 1460",
|
||||
"function": "1000",
|
||||
"height": 15,
|
||||
"year_of_construction": 1985
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.5683896684674,
|
||||
45.491800342137736
|
||||
],
|
||||
[
|
||||
-73.56838616878639,
|
||||
45.49180414157881
|
||||
],
|
||||
[
|
||||
-73.56850686988925,
|
||||
45.49185994152571
|
||||
],
|
||||
[
|
||||
-73.56851286844197,
|
||||
45.4918626410622
|
||||
],
|
||||
[
|
||||
-73.56855549071014,
|
||||
45.49181750806087
|
||||
],
|
||||
[
|
||||
-73.56842962331187,
|
||||
45.49175738300567
|
||||
],
|
||||
[
|
||||
-73.5683896684674,
|
||||
45.491800342137736
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 174898,
|
||||
"properties": {
|
||||
"name": "01044590",
|
||||
"address": "rue Victor-Hugo (MTL) 1600",
|
||||
"function": "1000",
|
||||
"height": 9,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.5680637695714,
|
||||
45.49212884162544
|
||||
],
|
||||
[
|
||||
-73.56802228176146,
|
||||
45.49217205619571
|
||||
],
|
||||
[
|
||||
-73.56815668696326,
|
||||
45.49223626189717
|
||||
],
|
||||
[
|
||||
-73.56815766959974,
|
||||
45.49223524178655
|
||||
],
|
||||
[
|
||||
-73.56818746886172,
|
||||
45.49224944155107
|
||||
],
|
||||
[
|
||||
-73.56822816806918,
|
||||
45.49220694186927
|
||||
],
|
||||
[
|
||||
-73.5680637695714,
|
||||
45.49212884162544
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 175785,
|
||||
"properties": {
|
||||
"name": "01044602",
|
||||
"address": "rue Victor-Hugo (MTL) 1630",
|
||||
"function": "1000",
|
||||
"height": 12,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56850793693103,
|
||||
45.49167318076048
|
||||
],
|
||||
[
|
||||
-73.56846877951091,
|
||||
45.4917152818903
|
||||
],
|
||||
[
|
||||
-73.56859506290321,
|
||||
45.491775605518725
|
||||
],
|
||||
[
|
||||
-73.56863463503653,
|
||||
45.491733702062774
|
||||
],
|
||||
[
|
||||
-73.56850793693103,
|
||||
45.49167318076048
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 175910,
|
||||
"properties": {
|
||||
"name": "01044586",
|
||||
"address": "rue Victor-Hugo (MTL) 1590",
|
||||
"function": "1000",
|
||||
"height": 9,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56817543449134,
|
||||
45.49201384773851
|
||||
],
|
||||
[
|
||||
-73.56813497596143,
|
||||
45.49205532773507
|
||||
],
|
||||
[
|
||||
-73.56826745951075,
|
||||
45.492118613912375
|
||||
],
|
||||
[
|
||||
-73.56830763251781,
|
||||
45.49207699906335
|
||||
],
|
||||
[
|
||||
-73.56817543449134,
|
||||
45.49201384773851
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 176056,
|
||||
"properties": {
|
||||
"name": "01044599",
|
||||
"address": "rue Victor-Hugo (MTL) 1620",
|
||||
"function": "1000",
|
||||
"height": 8,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56772876855176,
|
||||
45.49247194194522
|
||||
],
|
||||
[
|
||||
-73.56773406949068,
|
||||
45.492474341387755
|
||||
],
|
||||
[
|
||||
-73.56773125185198,
|
||||
45.492477239659124
|
||||
],
|
||||
[
|
||||
-73.56785890467093,
|
||||
45.492538239964624
|
||||
],
|
||||
[
|
||||
-73.56789966910456,
|
||||
45.49249534173201
|
||||
],
|
||||
[
|
||||
-73.56776616865103,
|
||||
45.49243264153464
|
||||
],
|
||||
[
|
||||
-73.56772876855176,
|
||||
45.49247194194522
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 176261,
|
||||
"properties": {
|
||||
"name": "01044613",
|
||||
"address": "rue Victor-Hugo (MTL) 1656",
|
||||
"function": "1000",
|
||||
"height": 10,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56802228176146,
|
||||
45.49217205619571
|
||||
],
|
||||
[
|
||||
-73.56798225825526,
|
||||
45.492213743742184
|
||||
],
|
||||
[
|
||||
-73.56811660206223,
|
||||
45.49227791893211
|
||||
],
|
||||
[
|
||||
-73.56815668696326,
|
||||
45.49223626189717
|
||||
],
|
||||
[
|
||||
-73.56802228176146,
|
||||
45.49217205619571
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 176293,
|
||||
"properties": {
|
||||
"name": "01044604",
|
||||
"address": "rue Victor-Hugo (MTL) 1636",
|
||||
"function": "1000",
|
||||
"height": 12,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56790222258577,
|
||||
45.49229712328457
|
||||
],
|
||||
[
|
||||
-73.56785996900595,
|
||||
45.49234104192853
|
||||
],
|
||||
[
|
||||
-73.56799446861396,
|
||||
45.49240484193282
|
||||
],
|
||||
[
|
||||
-73.56803643080562,
|
||||
45.49236123475947
|
||||
],
|
||||
[
|
||||
-73.56790222258577,
|
||||
45.49229712328457
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 176296,
|
||||
"properties": {
|
||||
"name": "01044611",
|
||||
"address": "rue Victor-Hugo (MTL) 1650",
|
||||
"function": "1000",
|
||||
"height": 10,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56798225825526,
|
||||
45.492213743742184
|
||||
],
|
||||
[
|
||||
-73.56794223597048,
|
||||
45.4922554321734
|
||||
],
|
||||
[
|
||||
-73.56807651582375,
|
||||
45.49231957685336
|
||||
],
|
||||
[
|
||||
-73.56811660206223,
|
||||
45.49227791893211
|
||||
],
|
||||
[
|
||||
-73.56798225825526,
|
||||
45.492213743742184
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 176298,
|
||||
"properties": {
|
||||
"name": "01044607",
|
||||
"address": "rue Victor-Hugo (MTL) 1640",
|
||||
"function": "1000",
|
||||
"height": 12,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56742736898599,
|
||||
45.49184704208998
|
||||
],
|
||||
[
|
||||
-73.56761256873325,
|
||||
45.491896142437554
|
||||
],
|
||||
[
|
||||
-73.56766926915839,
|
||||
45.4917902412014
|
||||
],
|
||||
[
|
||||
-73.56766956853903,
|
||||
45.49179024192391
|
||||
],
|
||||
[
|
||||
-73.56792966911675,
|
||||
45.49183254222432
|
||||
],
|
||||
[
|
||||
-73.56793006788594,
|
||||
45.491831141828406
|
||||
],
|
||||
[
|
||||
-73.56794526884076,
|
||||
45.49174634219527
|
||||
],
|
||||
[
|
||||
-73.56794516904765,
|
||||
45.49174634225465
|
||||
],
|
||||
[
|
||||
-73.56753896905731,
|
||||
45.491638642248425
|
||||
],
|
||||
[
|
||||
-73.56742736898599,
|
||||
45.49184704208998
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 176918,
|
||||
"properties": {
|
||||
"name": "01097185",
|
||||
"address": "rue Victor-Hugo (MTL) 1591",
|
||||
"function": "1000",
|
||||
"height": 10,
|
||||
"year_of_construction": 1987
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56773125185198,
|
||||
45.492477239659124
|
||||
],
|
||||
[
|
||||
-73.56769087843276,
|
||||
45.49251875903776
|
||||
],
|
||||
[
|
||||
-73.56781916241786,
|
||||
45.49258006136105
|
||||
],
|
||||
[
|
||||
-73.56785890467093,
|
||||
45.492538239964624
|
||||
],
|
||||
[
|
||||
-73.56773125185198,
|
||||
45.492477239659124
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 178164,
|
||||
"properties": {
|
||||
"name": "01044615",
|
||||
"address": "rue Victor-Hugo (MTL) 1660",
|
||||
"function": "1000",
|
||||
"height": 9,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56846877951091,
|
||||
45.4917152818903
|
||||
],
|
||||
[
|
||||
-73.56842962331187,
|
||||
45.49175738300567
|
||||
],
|
||||
[
|
||||
-73.56855549071014,
|
||||
45.49181750806087
|
||||
],
|
||||
[
|
||||
-73.56859506290321,
|
||||
45.491775605518725
|
||||
],
|
||||
[
|
||||
-73.56846877951091,
|
||||
45.4917152818903
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 179679,
|
||||
"properties": {
|
||||
"name": "01044588",
|
||||
"address": "rue Victor-Hugo (MTL) 1596",
|
||||
"function": "1000",
|
||||
"height": 9,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56825635009473,
|
||||
45.49193088860213
|
||||
],
|
||||
[
|
||||
-73.56821589168355,
|
||||
45.491972368627906
|
||||
],
|
||||
[
|
||||
-73.5683477837006,
|
||||
45.4920353716151
|
||||
],
|
||||
[
|
||||
-73.56838787594006,
|
||||
45.49199371809223
|
||||
],
|
||||
[
|
||||
-73.56825635009473,
|
||||
45.49193088860213
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 179789,
|
||||
"properties": {
|
||||
"name": "01044595",
|
||||
"address": "rue Victor-Hugo (MTL) 1610",
|
||||
"function": "1000",
|
||||
"height": 8,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56821589168355,
|
||||
45.491972368627906
|
||||
],
|
||||
[
|
||||
-73.56817543449134,
|
||||
45.49201384773851
|
||||
],
|
||||
[
|
||||
-73.56830763251781,
|
||||
45.49207699906335
|
||||
],
|
||||
[
|
||||
-73.5683477837006,
|
||||
45.4920353716151
|
||||
],
|
||||
[
|
||||
-73.56821589168355,
|
||||
45.491972368627906
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 181310,
|
||||
"properties": {
|
||||
"name": "01044597",
|
||||
"address": "rue Victor-Hugo (MTL) 1616",
|
||||
"function": "1000",
|
||||
"height": 8,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56809506939487,
|
||||
45.49209624228538
|
||||
],
|
||||
[
|
||||
-73.56809246893268,
|
||||
45.4920988416879
|
||||
],
|
||||
[
|
||||
-73.56821287000538,
|
||||
45.49216124158406
|
||||
],
|
||||
[
|
||||
-73.56822186852654,
|
||||
45.49216584161625
|
||||
],
|
||||
[
|
||||
-73.56826745951075,
|
||||
45.492118613912375
|
||||
],
|
||||
[
|
||||
-73.56813497596143,
|
||||
45.49205532773507
|
||||
],
|
||||
[
|
||||
-73.56809506939487,
|
||||
45.49209624228538
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 182393,
|
||||
"properties": {
|
||||
"name": "01044601",
|
||||
"address": "rue Victor-Hugo (MTL) 1626",
|
||||
"function": "1000",
|
||||
"height": 8,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56790756893894,
|
||||
45.492291541967774
|
||||
],
|
||||
[
|
||||
-73.56790222258577,
|
||||
45.49229712328457
|
||||
],
|
||||
[
|
||||
-73.56803643080562,
|
||||
45.49236123475947
|
||||
],
|
||||
[
|
||||
-73.56807651582375,
|
||||
45.49231957685336
|
||||
],
|
||||
[
|
||||
-73.56794223597048,
|
||||
45.4922554321734
|
||||
],
|
||||
[
|
||||
-73.56790756893894,
|
||||
45.492291541967774
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 182442,
|
||||
"properties": {
|
||||
"name": "01044609",
|
||||
"address": "rue Victor-Hugo (MTL) 1646",
|
||||
"function": "1000",
|
||||
"height": 11,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-73.56829706912258,
|
||||
45.49188914205178
|
||||
],
|
||||
[
|
||||
-73.56825635009473,
|
||||
45.49193088860213
|
||||
],
|
||||
[
|
||||
-73.56838787594006,
|
||||
45.49199371809223
|
||||
],
|
||||
[
|
||||
-73.56842846901456,
|
||||
45.49195154234486
|
||||
],
|
||||
[
|
||||
-73.56829706912258,
|
||||
45.49188914205178
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"id": 182546,
|
||||
"properties": {
|
||||
"name": "01044592",
|
||||
"address": "rue Victor-Hugo (MTL) 1606",
|
||||
"function": "1000",
|
||||
"height": 8,
|
||||
"year_of_construction": 1986
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -39,11 +39,11 @@ class TestSystemsCatalog(TestCase):
|
||||
|
||||
catalog_categories = catalog.names()
|
||||
archetypes = catalog.names()
|
||||
self.assertEqual(13, len(archetypes['archetypes']))
|
||||
self.assertEqual(34, len(archetypes['archetypes']))
|
||||
systems = catalog.names('systems')
|
||||
self.assertEqual(17, len(systems['systems']))
|
||||
self.assertEqual(39, len(systems['systems']))
|
||||
generation_equipments = catalog.names('generation_equipments')
|
||||
self.assertEqual(27, len(generation_equipments['generation_equipments']))
|
||||
self.assertEqual(49, len(generation_equipments['generation_equipments']))
|
||||
with self.assertRaises(ValueError):
|
||||
catalog.names('unknown')
|
||||
|
||||
@ -54,4 +54,4 @@ class TestSystemsCatalog(TestCase):
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
catalog.get_entry('unknown')
|
||||
print(catalog.entries())
|
||||
|
||||
|
@ -114,8 +114,8 @@ class TestSystemsFactory(TestCase):
|
||||
ResultFactory('insel_monthly_energy_balance', self._city, self._output_path).enrich()
|
||||
|
||||
for building in self._city.buildings:
|
||||
building.energy_systems_archetype_name = ('Central 4 Pipes Air to Water Heat Pump and Gas Boiler with '
|
||||
'Independent Water Heating and PV')
|
||||
building.energy_systems_archetype_name = ('Central Hydronic Air and Gas Source Heating System with Unitary Split '
|
||||
'Cooling and Air Source HP DHW and Grid Tied PV')
|
||||
EnergySystemsFactory('montreal_future', self._city).enrich()
|
||||
# Need to assign energy systems to buildings:
|
||||
for building in self._city.buildings:
|
||||
@ -123,13 +123,14 @@ class TestSystemsFactory(TestCase):
|
||||
for energy_system in building.energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
_generation_system = cast(NonPvGenerationSystem, energy_system.generation_systems[0])
|
||||
_generation_system.heat_power = building.heating_peak_load[cte.YEAR][0]
|
||||
_generation_system.nominal_heat_output = building.heating_peak_load[cte.YEAR][0]
|
||||
if cte.COOLING in energy_system.demand_types:
|
||||
_generation_system = cast(NonPvGenerationSystem, energy_system.generation_systems[0])
|
||||
_generation_system.cooling_power = building.cooling_peak_load[cte.YEAR][0]
|
||||
_generation_system.nominal_cooling_output = building.cooling_peak_load[cte.YEAR][0]
|
||||
|
||||
for building in self._city.buildings:
|
||||
self.assertLess(0, building.heating_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.cooling_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.domestic_hot_water_consumption[cte.YEAR][0])
|
||||
self.assertLess(0, building.onsite_electrical_production[cte.YEAR][0])
|
||||
if 'PV' in building.energy_systems_archetype_name:
|
||||
self.assertLess(0, building.onsite_electrical_production[cte.YEAR][0])
|
Loading…
Reference in New Issue
Block a user