forked from s_ranjbar/city_retrofit
added domestic hot water parameters in catalog and importers
This commit is contained in:
parent
aa0952969f
commit
9f28c2f93d
|
@ -14,8 +14,9 @@ class DomesticHotWater:
|
||||||
"""
|
"""
|
||||||
DomesticHotWater class
|
DomesticHotWater class
|
||||||
"""
|
"""
|
||||||
def __init__(self, density, service_temperature, schedules):
|
def __init__(self, density, peak_flow, service_temperature, schedules):
|
||||||
self._density = density
|
self._density = density
|
||||||
|
self._peak_flow = peak_flow
|
||||||
self._service_temperature = service_temperature
|
self._service_temperature = service_temperature
|
||||||
self._schedules = schedules
|
self._schedules = schedules
|
||||||
|
|
||||||
|
@ -27,6 +28,14 @@ class DomesticHotWater:
|
||||||
"""
|
"""
|
||||||
return self._density
|
return self._density
|
||||||
|
|
||||||
|
@property
|
||||||
|
def peak_flow(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get domestic hot water peak_flow density in m3 per second and m2
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._peak_flow
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def service_temperature(self) -> Union[None, float]:
|
def service_temperature(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -104,6 +104,7 @@ class ComnetCatalog(Catalog):
|
||||||
density = float(density) * cte.BTU_H_TO_WATTS * occupancy_density
|
density = float(density) * cte.BTU_H_TO_WATTS * occupancy_density
|
||||||
domestic_hot_water_service_temperature = self._schedules[schedule_name]['WtrHtrSetPt'][0].values[0]
|
domestic_hot_water_service_temperature = self._schedules[schedule_name]['WtrHtrSetPt'][0].values[0]
|
||||||
domestic_hot_water = DomesticHotWater(density,
|
domestic_hot_water = DomesticHotWater(density,
|
||||||
|
None,
|
||||||
domestic_hot_water_service_temperature,
|
domestic_hot_water_service_temperature,
|
||||||
self._schedules[schedule_name]['Service Hot Water']
|
self._schedules[schedule_name]['Service Hot Water']
|
||||||
)
|
)
|
||||||
|
|
|
@ -79,10 +79,8 @@ class NrcanCatalog(Catalog):
|
||||||
url = f'{self._base_url}{name["space_types_location"]}'
|
url = f'{self._base_url}{name["space_types_location"]}'
|
||||||
with urllib.request.urlopen(url) as json_file:
|
with urllib.request.urlopen(url) as json_file:
|
||||||
space_types = json.load(json_file)['tables']['space_types']['table']
|
space_types = json.load(json_file)['tables']['space_types']['table']
|
||||||
# space_types = [st for st in space_types if st['building_type'] == 'Space Function']
|
|
||||||
space_types = [st for st in space_types if st['space_type'] == 'WholeBuilding']
|
space_types = [st for st in space_types if st['space_type'] == 'WholeBuilding']
|
||||||
for space_type in space_types:
|
for space_type in space_types:
|
||||||
# usage_type = space_type['space_type']
|
|
||||||
usage_type = space_type['building_type']
|
usage_type = space_type['building_type']
|
||||||
occupancy_schedule_name = space_type['occupancy_schedule']
|
occupancy_schedule_name = space_type['occupancy_schedule']
|
||||||
lighting_schedule_name = space_type['lighting_schedule']
|
lighting_schedule_name = space_type['lighting_schedule']
|
||||||
|
@ -127,14 +125,10 @@ class NrcanCatalog(Catalog):
|
||||||
if appliances_radiative_fraction is not None and appliances_latent_fraction is not None:
|
if appliances_radiative_fraction is not None and appliances_latent_fraction is not None:
|
||||||
appliances_convective_fraction = 1 - appliances_radiative_fraction - appliances_latent_fraction
|
appliances_convective_fraction = 1 - appliances_radiative_fraction - appliances_latent_fraction
|
||||||
|
|
||||||
# peak flow in m3/day/m2
|
# peak flow in gallons/h/ft2
|
||||||
domestic_hot_water_peak_flow = space_type['service_water_heating_peak_flow_per_area']
|
domestic_hot_water_peak_flow = space_type['service_water_heating_peak_flow_per_area'] \
|
||||||
|
* cte.GALLONS_TO_QUBIC_METERS / cte.HOUR_TO_SECONDS * pow(cte.METERS_TO_FEET, 2)
|
||||||
domestic_hot_water_service_temperature = space_type['service_water_heating_target_temperature']
|
domestic_hot_water_service_temperature = space_type['service_water_heating_target_temperature']
|
||||||
average_domestic_hot_water_inlet_temperature = 16.5
|
|
||||||
# result in W/m2
|
|
||||||
domestic_hot_water_density = domestic_hot_water_peak_flow / 24 / 3.6 * 4184 \
|
|
||||||
* (domestic_hot_water_service_temperature -
|
|
||||||
average_domestic_hot_water_inlet_temperature)
|
|
||||||
|
|
||||||
occupancy = Occupancy(occupancy_density,
|
occupancy = Occupancy(occupancy_density,
|
||||||
None,
|
None,
|
||||||
|
@ -157,7 +151,8 @@ class NrcanCatalog(Catalog):
|
||||||
hvac_availability,
|
hvac_availability,
|
||||||
heating_schedule,
|
heating_schedule,
|
||||||
cooling_schedule)
|
cooling_schedule)
|
||||||
domestic_hot_water = DomesticHotWater(domestic_hot_water_density,
|
domestic_hot_water = DomesticHotWater(None,
|
||||||
|
domestic_hot_water_peak_flow,
|
||||||
domestic_hot_water_service_temperature,
|
domestic_hot_water_service_temperature,
|
||||||
domestic_hot_water_load_schedule)
|
domestic_hot_water_load_schedule)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ class DomesticHotWater:
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._density = None
|
self._density = None
|
||||||
|
self._peak_flow = None
|
||||||
self._service_temperature = None
|
self._service_temperature = None
|
||||||
self._schedules = None
|
self._schedules = None
|
||||||
|
|
||||||
|
@ -34,6 +35,22 @@ class DomesticHotWater:
|
||||||
if value is not None:
|
if value is not None:
|
||||||
self._density = float(value)
|
self._density = float(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def peak_flow(self) -> Union[None, float]:
|
||||||
|
"""
|
||||||
|
Get domestic hot water peak_flow density in m3 per second and m2
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
return self._peak_flow
|
||||||
|
|
||||||
|
@peak_flow.setter
|
||||||
|
def peak_flow(self, value):
|
||||||
|
"""
|
||||||
|
Set domestic hot water peak_flow density in m3 per second and m2
|
||||||
|
:return: None or float
|
||||||
|
"""
|
||||||
|
self._peak_flow = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def service_temperature(self) -> Union[None, float]:
|
def service_temperature(self) -> Union[None, float]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -35,6 +35,7 @@ class CityObject:
|
||||||
self._max_z = ConfigurationHelper().min_coordinate
|
self._max_z = ConfigurationHelper().min_coordinate
|
||||||
self._centroid = None
|
self._centroid = None
|
||||||
self._external_temperature = dict()
|
self._external_temperature = dict()
|
||||||
|
self._ground_temperature = dict()
|
||||||
self._global_horizontal = dict()
|
self._global_horizontal = dict()
|
||||||
self._diffuse = dict()
|
self._diffuse = dict()
|
||||||
self._beam = dict()
|
self._beam = dict()
|
||||||
|
@ -158,6 +159,24 @@ class CityObject:
|
||||||
"""
|
"""
|
||||||
self._external_temperature = value
|
self._external_temperature = value
|
||||||
|
|
||||||
|
# todo: this is the new format we will use to get rid of the data frames
|
||||||
|
@property
|
||||||
|
def ground_temperature(self) -> dict:
|
||||||
|
"""
|
||||||
|
Get ground temperature under the city object in Celsius at different depths in meters for different time steps
|
||||||
|
example of use: {month: {0.5: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]}}
|
||||||
|
:return: dict{dict{[float]}}
|
||||||
|
"""
|
||||||
|
return self._ground_temperature
|
||||||
|
|
||||||
|
@ground_temperature.setter
|
||||||
|
def ground_temperature(self, value):
|
||||||
|
"""
|
||||||
|
Set ground temperature under the city object in Celsius at different depths
|
||||||
|
:param value: dict{dict{[float]}}
|
||||||
|
"""
|
||||||
|
self._ground_temperature = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def global_horizontal(self) -> dict:
|
def global_horizontal(self) -> dict:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -17,4 +17,6 @@ convective_heat_transfer_coefficient_exterior = 20
|
||||||
#W/mK
|
#W/mK
|
||||||
soil_conductivity = 3
|
soil_conductivity = 3
|
||||||
#m
|
#m
|
||||||
soil_thickness = 0.5
|
soil_thickness = 0.5
|
||||||
|
#C
|
||||||
|
cold_water_temperature = 10
|
|
@ -138,3 +138,11 @@ class ConfigurationHelper:
|
||||||
:return: 0.5
|
:return: 0.5
|
||||||
"""
|
"""
|
||||||
return self._config.getfloat('buildings', 'soil_thickness').real
|
return self._config.getfloat('buildings', 'soil_thickness').real
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cold_water_temperature(self) -> float:
|
||||||
|
"""
|
||||||
|
Get configured cold water temperature in Celsius
|
||||||
|
:return: 10
|
||||||
|
"""
|
||||||
|
return self._config.getfloat('buildings', 'cold_water_temperature').real
|
||||||
|
|
|
@ -8,13 +8,17 @@ Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
# universal constants
|
# universal constants
|
||||||
|
|
||||||
KELVIN = 273.15
|
KELVIN = 273.15
|
||||||
|
WATER_DENSITY = 1000
|
||||||
|
WATER_HEAT_CAPACITY = 4182
|
||||||
|
|
||||||
# converters
|
# converters
|
||||||
HOUR_TO_MINUTES = 60
|
HOUR_TO_MINUTES = 60
|
||||||
MINUTES_TO_SECONDS = 60
|
MINUTES_TO_SECONDS = 60
|
||||||
|
HOUR_TO_SECONDS = 3600
|
||||||
METERS_TO_FEET = 3.28084
|
METERS_TO_FEET = 3.28084
|
||||||
BTU_H_TO_WATTS = 0.29307107
|
BTU_H_TO_WATTS = 0.29307107
|
||||||
KILO_WATTS_HOUR_TO_JULES = 3600000
|
KILO_WATTS_HOUR_TO_JULES = 3600000
|
||||||
|
GALLONS_TO_QUBIC_METERS = 0.0037854117954011185
|
||||||
|
|
||||||
# time
|
# time
|
||||||
SECOND = 'second'
|
SECOND = 'second'
|
||||||
|
|
|
@ -19,6 +19,7 @@ from hub.city_model_structure.building_demand.domestic_hot_water import Domestic
|
||||||
from hub.city_model_structure.attributes.schedule import Schedule
|
from hub.city_model_structure.attributes.schedule import Schedule
|
||||||
from hub.city_model_structure.building_demand.internal_gain import InternalGain
|
from hub.city_model_structure.building_demand.internal_gain import InternalGain
|
||||||
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
|
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
|
||||||
|
from hub.imports.usage.usage_helper import UsageHelper
|
||||||
|
|
||||||
|
|
||||||
class ComnetUsageParameters:
|
class ComnetUsageParameters:
|
||||||
|
@ -55,7 +56,7 @@ class ComnetUsageParameters:
|
||||||
volume_per_area = internal_zone.volume / internal_zone.area
|
volume_per_area = internal_zone.volume / internal_zone.area
|
||||||
usage = Usage()
|
usage = Usage()
|
||||||
usage.name = usage_name
|
usage.name = usage_name
|
||||||
self._assign_values(usage, archetype_usage, volume_per_area)
|
self._assign_values(usage, archetype_usage, volume_per_area, building.ground_temperature)
|
||||||
usage.percentage = 1
|
usage.percentage = 1
|
||||||
self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
|
self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ class ComnetUsageParameters:
|
||||||
raise KeyError('archetype not found')
|
raise KeyError('archetype not found')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _assign_values(usage, archetype, volume_per_area):
|
def _assign_values(usage, archetype, volume_per_area, ground_temperature):
|
||||||
# Due to the fact that python is not a typed language, the wrong object type is assigned to
|
# Due to the fact that python is not a typed language, the wrong object type is assigned to
|
||||||
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
|
# usage.occupancy when writing usage.occupancy = archetype.occupancy.
|
||||||
# Same happens for lighting and appliances. Therefore, this walk around has been done.
|
# Same happens for lighting and appliances. Therefore, this walk around has been done.
|
||||||
|
@ -105,6 +106,12 @@ class ComnetUsageParameters:
|
||||||
_domestic_hot_water = DomesticHotWater()
|
_domestic_hot_water = DomesticHotWater()
|
||||||
_domestic_hot_water.density = archetype.domestic_hot_water.density
|
_domestic_hot_water.density = archetype.domestic_hot_water.density
|
||||||
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
|
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
|
||||||
|
cold_temperature = UsageHelper().cold_water_temperature(ground_temperature)
|
||||||
|
peak_flow = 0
|
||||||
|
if (archetype.domestic_hot_water.service_temperature - cold_temperature) > 0:
|
||||||
|
peak_flow = archetype.domestic_hot_water.density / cte.WATER_DENSITY / cte.WATER_HEAT_CAPACITY \
|
||||||
|
/ (archetype.domestic_hot_water.service_temperature - cold_temperature)
|
||||||
|
_domestic_hot_water.peak_flow = peak_flow
|
||||||
_domestic_hot_water.schedules = archetype.domestic_hot_water.schedules
|
_domestic_hot_water.schedules = archetype.domestic_hot_water.schedules
|
||||||
usage.domestic_hot_water = _domestic_hot_water
|
usage.domestic_hot_water = _domestic_hot_water
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from hub.city_model_structure.building_demand.appliances import Appliances
|
||||||
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
|
from hub.city_model_structure.building_demand.thermal_control import ThermalControl
|
||||||
from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater
|
from hub.city_model_structure.building_demand.domestic_hot_water import DomesticHotWater
|
||||||
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
|
from hub.catalog_factories.usage_catalog_factory import UsageCatalogFactory
|
||||||
|
from hub.imports.usage.usage_helper import UsageHelper
|
||||||
|
|
||||||
|
|
||||||
class NrcanUsageParameters:
|
class NrcanUsageParameters:
|
||||||
|
@ -62,7 +63,7 @@ class NrcanUsageParameters:
|
||||||
volume_per_area = internal_zone.volume / internal_zone.area
|
volume_per_area = internal_zone.volume / internal_zone.area
|
||||||
usage = Usage()
|
usage = Usage()
|
||||||
usage.name = usage_name
|
usage.name = usage_name
|
||||||
self._assign_values(usage, archetype_usage, volume_per_area)
|
self._assign_values(usage, archetype_usage, volume_per_area, building.ground_temperature)
|
||||||
self._assign_comnet_extra_values(usage, comnet_archetype_usage)
|
self._assign_comnet_extra_values(usage, comnet_archetype_usage)
|
||||||
usage.percentage = 1
|
usage.percentage = 1
|
||||||
self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
|
self._calculate_reduced_values_from_extended_library(usage, archetype_usage)
|
||||||
|
@ -78,7 +79,7 @@ class NrcanUsageParameters:
|
||||||
raise KeyError('archetype not found')
|
raise KeyError('archetype not found')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _assign_values(usage, archetype, volume_per_area):
|
def _assign_values(usage, archetype, volume_per_area, ground_temperature):
|
||||||
if archetype.mechanical_air_change > 0:
|
if archetype.mechanical_air_change > 0:
|
||||||
usage.mechanical_air_change = archetype.mechanical_air_change
|
usage.mechanical_air_change = archetype.mechanical_air_change
|
||||||
elif archetype.ventilation_rate > 0:
|
elif archetype.ventilation_rate > 0:
|
||||||
|
@ -113,8 +114,11 @@ class NrcanUsageParameters:
|
||||||
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
|
_control.hvac_availability_schedules = archetype.thermal_control.hvac_availability_schedules
|
||||||
usage.thermal_control = _control
|
usage.thermal_control = _control
|
||||||
_domestic_hot_water = DomesticHotWater()
|
_domestic_hot_water = DomesticHotWater()
|
||||||
_domestic_hot_water.density = archetype.domestic_hot_water.density
|
_domestic_hot_water.peak_flow = archetype.domestic_hot_water.peak_flow
|
||||||
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
|
_domestic_hot_water.service_temperature = archetype.domestic_hot_water.service_temperature
|
||||||
|
cold_temperature = UsageHelper().cold_water_temperature(ground_temperature)
|
||||||
|
_domestic_hot_water.density = archetype.domestic_hot_water.peak_flow * cte.WATER_DENSITY * cte.WATER_HEAT_CAPACITY \
|
||||||
|
* (archetype.domestic_hot_water.service_temperature - cold_temperature)
|
||||||
_domestic_hot_water.schedules = archetype.domestic_hot_water.schedules
|
_domestic_hot_water.schedules = archetype.domestic_hot_water.schedules
|
||||||
usage.domestic_hot_water = _domestic_hot_water
|
usage.domestic_hot_water = _domestic_hot_water
|
||||||
|
|
||||||
|
|
43
hub/imports/usage/usage_helper.py
Normal file
43
hub/imports/usage/usage_helper.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
"""
|
||||||
|
Usage helper
|
||||||
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||||
|
Copyright © 2023 Concordia CERC group
|
||||||
|
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from hub.hub_logger import logger
|
||||||
|
import hub.helpers.constants as cte
|
||||||
|
from hub.helpers.configuration_helper import ConfigurationHelper as ch
|
||||||
|
|
||||||
|
|
||||||
|
class UsageHelper:
|
||||||
|
"""
|
||||||
|
UsageHelper class
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cold_water_temperature(ground_temperature):
|
||||||
|
keys = ground_temperature.keys()
|
||||||
|
depths = ground_temperature[keys[0]].keys()
|
||||||
|
if keys[0] == cte.YEAR:
|
||||||
|
# taking the deeper temperature available
|
||||||
|
_cold_temperature = ground_temperature[cte.YEAR][depths[len(depths-1)]]
|
||||||
|
elif keys[0] == cte.MONTH:
|
||||||
|
_cold_temperature = 0
|
||||||
|
for i in range(0, 12):
|
||||||
|
# taking the deeper temperature available
|
||||||
|
_cold_temperature += ground_temperature[cte.MONTH][depths[len(depths-1)]] / 12
|
||||||
|
elif keys[0] == cte.HOUR:
|
||||||
|
_cold_temperature = 0
|
||||||
|
for i in range(0, 8760):
|
||||||
|
# taking the deeper temperature available
|
||||||
|
_cold_temperature += ground_temperature[cte.HOUR][depths[len(depths-1)]] / 8760
|
||||||
|
else:
|
||||||
|
_cold_temperature = ch().cold_water_temperature
|
||||||
|
logger.error(f'Cold water temperature could not be calculated. Assigned default value = '
|
||||||
|
f'{ch().cold_water_temperature} degrees Celsius\n')
|
||||||
|
sys.stderr.write(f'Cold water temperature could not be calculated. Assigned default value = '
|
||||||
|
f'{ch().cold_water_temperature} degrees Celsius\n')
|
||||||
|
|
||||||
|
return _cold_temperature
|
|
@ -32,14 +32,13 @@ class EpwWeatherParameters:
|
||||||
_ = file.readline().split(',')
|
_ = file.readline().split(',')
|
||||||
line = file.readline().split(',')
|
line = file.readline().split(',')
|
||||||
number_records = int(line[1])
|
number_records = int(line[1])
|
||||||
depth_measurement_ground_temperature = []
|
ground_temperature = {}
|
||||||
ground_temperature = []
|
|
||||||
for i in range(0, number_records):
|
for i in range(0, number_records):
|
||||||
depth_measurement_ground_temperature.append(line[i*16+2])
|
depth_measurement_ground_temperature = line[i*16+2]
|
||||||
temperatures = []
|
temperatures = []
|
||||||
for j in range(0, 12):
|
for j in range(0, 12):
|
||||||
temperatures.append(line[i*16+j+6])
|
temperatures.append(line[i*16+j+6])
|
||||||
ground_temperature.append(temperatures)
|
ground_temperature[depth_measurement_ground_temperature] = temperatures
|
||||||
file.close()
|
file.close()
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
sys.stderr.write(f'Error: weather file {self._path} not found. Please download it from '
|
sys.stderr.write(f'Error: weather file {self._path} not found. Please download it from '
|
||||||
|
@ -74,6 +73,7 @@ class EpwWeatherParameters:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
for building in self._city.buildings:
|
for building in self._city.buildings:
|
||||||
|
building.ground_temperature[cte.MONTH] = ground_temperature
|
||||||
if cte.HOUR in building.external_temperature:
|
if cte.HOUR in building.external_temperature:
|
||||||
del building.external_temperature[cte.HOUR]
|
del building.external_temperature[cte.HOUR]
|
||||||
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
|
new_value = pd.DataFrame(self._weather_values[['dry_bulb_temperature_c']].to_numpy(), columns=['epw'])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user