Integrate Peter's head pump branch into master
This commit is contained in:
commit
eeff2eec18
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
||||
/venv/
|
||||
.idea/
|
||||
/development_tests/
|
||||
/data/energy_systems/heat_pumps/*.csv
|
||||
/data/energy_systems/heat_pumps/*.insel
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,240 +14,240 @@ from helpers.configuration_helper import ConfigurationHelper
|
||||
|
||||
|
||||
class Polyhedron:
|
||||
"""
|
||||
"""
|
||||
Polyhedron class
|
||||
"""
|
||||
|
||||
def __init__(self, polygons):
|
||||
self._polygons = polygons
|
||||
self._polyhedron = None
|
||||
self._triangulated_polyhedron = None
|
||||
self._volume = None
|
||||
self._faces = None
|
||||
self._vertices = None
|
||||
self._trimesh = None
|
||||
self._centroid = None
|
||||
self._max_z = None
|
||||
self._max_y = None
|
||||
self._max_x = None
|
||||
self._min_z = None
|
||||
self._min_y = None
|
||||
self._min_x = None
|
||||
def __init__(self, polygons):
|
||||
self._polygons = polygons
|
||||
self._polyhedron = None
|
||||
self._triangulated_polyhedron = None
|
||||
self._volume = None
|
||||
self._faces = None
|
||||
self._vertices = None
|
||||
self._trimesh = None
|
||||
self._centroid = None
|
||||
self._max_z = None
|
||||
self._max_y = None
|
||||
self._max_x = None
|
||||
self._min_z = None
|
||||
self._min_y = None
|
||||
self._min_x = None
|
||||
|
||||
def _position_of(self, point, face):
|
||||
"""
|
||||
def _position_of(self, point, face):
|
||||
"""
|
||||
position of a specific point in the list of points that define a face
|
||||
:return: int
|
||||
"""
|
||||
vertices = self.vertices
|
||||
for i in range(len(vertices)):
|
||||
# ensure not duplicated vertex
|
||||
power = 0
|
||||
vertex2 = vertices[i]
|
||||
for dimension in range(0, 3):
|
||||
power += math.pow(vertex2[dimension] - point[dimension], 2)
|
||||
distance = math.sqrt(power)
|
||||
if i not in face and distance == 0:
|
||||
return i
|
||||
return -1
|
||||
vertices = self.vertices
|
||||
for i in range(len(vertices)):
|
||||
# ensure not duplicated vertex
|
||||
power = 0
|
||||
vertex2 = vertices[i]
|
||||
for dimension in range(0, 3):
|
||||
power += math.pow(vertex2[dimension] - point[dimension], 2)
|
||||
distance = math.sqrt(power)
|
||||
if i not in face and distance == 0:
|
||||
return i
|
||||
return -1
|
||||
|
||||
@property
|
||||
def vertices(self) -> np.ndarray:
|
||||
"""
|
||||
@property
|
||||
def vertices(self) -> np.ndarray:
|
||||
"""
|
||||
Get polyhedron vertices
|
||||
:return: np.ndarray(int)
|
||||
"""
|
||||
if self._vertices is None:
|
||||
vertices, self._vertices = [], []
|
||||
_ = [vertices.extend(s.coordinates) for s in self._polygons]
|
||||
for vertex_1 in vertices:
|
||||
found = False
|
||||
for vertex_2 in self._vertices:
|
||||
found = False
|
||||
power = 0
|
||||
for dimension in range(0, 3):
|
||||
power += math.pow(vertex_2[dimension] - vertex_1[dimension], 2)
|
||||
distance = math.sqrt(power)
|
||||
if distance == 0:
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
self._vertices.append(vertex_1)
|
||||
self._vertices = np.asarray(self._vertices)
|
||||
return self._vertices
|
||||
if self._vertices is None:
|
||||
vertices, self._vertices = [], []
|
||||
_ = [vertices.extend(s.coordinates) for s in self._polygons]
|
||||
for vertex_1 in vertices:
|
||||
found = False
|
||||
for vertex_2 in self._vertices:
|
||||
found = False
|
||||
power = 0
|
||||
for dimension in range(0, 3):
|
||||
power += math.pow(vertex_2[dimension] - vertex_1[dimension], 2)
|
||||
distance = math.sqrt(power)
|
||||
if distance == 0:
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
self._vertices.append(vertex_1)
|
||||
self._vertices = np.asarray(self._vertices)
|
||||
return self._vertices
|
||||
|
||||
@property
|
||||
def faces(self) -> List[List[int]]:
|
||||
"""
|
||||
@property
|
||||
def faces(self) -> List[List[int]]:
|
||||
"""
|
||||
Get polyhedron triangular faces
|
||||
:return: [face]
|
||||
"""
|
||||
if self._faces is None:
|
||||
self._faces = []
|
||||
if self._faces is None:
|
||||
self._faces = []
|
||||
|
||||
for polygon in self._polygons:
|
||||
for polygon in self._polygons:
|
||||
|
||||
face = []
|
||||
points = polygon.coordinates
|
||||
if len(points) != 3:
|
||||
sub_polygons = polygon.triangulate()
|
||||
# todo: I modified this! To be checked @Guille
|
||||
if len(sub_polygons) >= 1:
|
||||
for sub_polygon in sub_polygons:
|
||||
face = []
|
||||
points = sub_polygon.coordinates
|
||||
for point in points:
|
||||
face.append(self._position_of(point, face))
|
||||
self._faces.append(face)
|
||||
else:
|
||||
for point in points:
|
||||
face.append(self._position_of(point, face))
|
||||
self._faces.append(face)
|
||||
return self._faces
|
||||
face = []
|
||||
points = polygon.coordinates
|
||||
if len(points) != 3:
|
||||
sub_polygons = polygon.triangulate()
|
||||
# todo: I modified this! To be checked @Guille
|
||||
if len(sub_polygons) >= 1:
|
||||
for sub_polygon in sub_polygons:
|
||||
face = []
|
||||
points = sub_polygon.coordinates
|
||||
for point in points:
|
||||
face.append(self._position_of(point, face))
|
||||
self._faces.append(face)
|
||||
else:
|
||||
for point in points:
|
||||
face.append(self._position_of(point, face))
|
||||
self._faces.append(face)
|
||||
return self._faces
|
||||
|
||||
@property
|
||||
def trimesh(self) -> Union[Trimesh, None]:
|
||||
"""
|
||||
@property
|
||||
def trimesh(self) -> Union[Trimesh, None]:
|
||||
"""
|
||||
Get polyhedron trimesh
|
||||
:return: Trimesh
|
||||
"""
|
||||
if self._trimesh is None:
|
||||
for face in self.faces:
|
||||
if len(face) != 3:
|
||||
sys.stderr.write('Not able to generate trimesh\n')
|
||||
return None
|
||||
self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces)
|
||||
return self._trimesh
|
||||
if self._trimesh is None:
|
||||
for face in self.faces:
|
||||
if len(face) != 3:
|
||||
sys.stderr.write('Not able to generate trimesh\n')
|
||||
return None
|
||||
self._trimesh = Trimesh(vertices=self.vertices, faces=self.faces)
|
||||
return self._trimesh
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
"""
|
||||
@property
|
||||
def volume(self):
|
||||
"""
|
||||
Get polyhedron volume in cubic meters
|
||||
:return: float
|
||||
"""
|
||||
if self._volume is None:
|
||||
if self.trimesh is None:
|
||||
self._volume = np.inf
|
||||
elif not self.trimesh.is_volume:
|
||||
self._volume = np.inf
|
||||
else:
|
||||
self._volume = self.trimesh.volume
|
||||
return self._volume
|
||||
if self._volume is None:
|
||||
if self.trimesh is None:
|
||||
self._volume = np.inf
|
||||
elif not self.trimesh.is_volume:
|
||||
self._volume = np.inf
|
||||
else:
|
||||
self._volume = self.trimesh.volume
|
||||
return self._volume
|
||||
|
||||
@property
|
||||
def max_z(self):
|
||||
"""
|
||||
@property
|
||||
def max_z(self):
|
||||
"""
|
||||
Get polyhedron maximal z value in meters
|
||||
:return: float
|
||||
"""
|
||||
if self._max_z is None:
|
||||
self._max_z = ConfigurationHelper().min_coordinate
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
self._max_z = max(self._max_z, point[2])
|
||||
return self._max_z
|
||||
if self._max_z is None:
|
||||
self._max_z = ConfigurationHelper().min_coordinate
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
self._max_z = max(self._max_z, point[2])
|
||||
return self._max_z
|
||||
|
||||
@property
|
||||
def max_y(self):
|
||||
"""
|
||||
@property
|
||||
def max_y(self):
|
||||
"""
|
||||
Get polyhedron maximal y value in meters
|
||||
:return: float
|
||||
"""
|
||||
if self._max_y is None:
|
||||
self._max_y = ConfigurationHelper().min_coordinate
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._max_y < point[1]:
|
||||
self._max_y = point[1]
|
||||
return self._max_y
|
||||
if self._max_y is None:
|
||||
self._max_y = ConfigurationHelper().min_coordinate
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._max_y < point[1]:
|
||||
self._max_y = point[1]
|
||||
return self._max_y
|
||||
|
||||
@property
|
||||
def max_x(self):
|
||||
"""
|
||||
@property
|
||||
def max_x(self):
|
||||
"""
|
||||
Get polyhedron maximal x value in meters
|
||||
:return: float
|
||||
"""
|
||||
if self._max_x is None:
|
||||
self._max_x = ConfigurationHelper().min_coordinate
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
self._max_x = max(self._max_x, point[0])
|
||||
return self._max_x
|
||||
if self._max_x is None:
|
||||
self._max_x = ConfigurationHelper().min_coordinate
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
self._max_x = max(self._max_x, point[0])
|
||||
return self._max_x
|
||||
|
||||
@property
|
||||
def min_z(self):
|
||||
"""
|
||||
@property
|
||||
def min_z(self):
|
||||
"""
|
||||
Get polyhedron minimal z value in meters
|
||||
:return: float
|
||||
"""
|
||||
if self._min_z is None:
|
||||
self._min_z = self.max_z
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._min_z > point[2]:
|
||||
self._min_z = point[2]
|
||||
return self._min_z
|
||||
if self._min_z is None:
|
||||
self._min_z = self.max_z
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._min_z > point[2]:
|
||||
self._min_z = point[2]
|
||||
return self._min_z
|
||||
|
||||
@property
|
||||
def min_y(self):
|
||||
"""
|
||||
@property
|
||||
def min_y(self):
|
||||
"""
|
||||
Get polyhedron minimal y value in meters
|
||||
:return: float
|
||||
"""
|
||||
if self._min_y is None:
|
||||
self._min_y = self.max_y
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._min_y > point[1]:
|
||||
self._min_y = point[1]
|
||||
return self._min_y
|
||||
if self._min_y is None:
|
||||
self._min_y = self.max_y
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._min_y > point[1]:
|
||||
self._min_y = point[1]
|
||||
return self._min_y
|
||||
|
||||
@property
|
||||
def min_x(self):
|
||||
"""
|
||||
@property
|
||||
def min_x(self):
|
||||
"""
|
||||
Get polyhedron minimal x value in meters
|
||||
:return: float
|
||||
"""
|
||||
if self._min_x is None:
|
||||
self._min_x = self.max_x
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._min_x > point[0]:
|
||||
self._min_x = point[0]
|
||||
return self._min_x
|
||||
if self._min_x is None:
|
||||
self._min_x = self.max_x
|
||||
for polygon in self._polygons:
|
||||
for point in polygon.coordinates:
|
||||
if self._min_x > point[0]:
|
||||
self._min_x = point[0]
|
||||
return self._min_x
|
||||
|
||||
@property
|
||||
def centroid(self) -> Union[None, List[float]]:
|
||||
"""
|
||||
@property
|
||||
def centroid(self) -> Union[None, List[float]]:
|
||||
"""
|
||||
Get polyhedron centroid
|
||||
:return: [x,y,z]
|
||||
"""
|
||||
if self._centroid is None:
|
||||
trimesh = self.trimesh
|
||||
if trimesh is None:
|
||||
return None
|
||||
self._centroid = self.trimesh.centroid
|
||||
return self._centroid
|
||||
if self._centroid is None:
|
||||
trimesh = self.trimesh
|
||||
if trimesh is None:
|
||||
return None
|
||||
self._centroid = self.trimesh.centroid
|
||||
return self._centroid
|
||||
|
||||
def stl_export(self, full_path):
|
||||
"""
|
||||
def stl_export(self, full_path):
|
||||
"""
|
||||
Export the polyhedron to stl given file
|
||||
:param full_path: str
|
||||
:return: None
|
||||
"""
|
||||
self.trimesh.export(full_path, 'stl_ascii')
|
||||
self.trimesh.export(full_path, 'stl_ascii')
|
||||
|
||||
def obj_export(self, full_path):
|
||||
"""
|
||||
def obj_export(self, full_path):
|
||||
"""
|
||||
Export the polyhedron to obj given file
|
||||
:param full_path: str
|
||||
:return: None
|
||||
"""
|
||||
self.trimesh.export(full_path, 'obj')
|
||||
self.trimesh.export(full_path, 'obj')
|
||||
|
||||
def show(self):
|
||||
"""
|
||||
def show(self):
|
||||
"""
|
||||
Auxiliary function to render the polyhedron
|
||||
:return: None
|
||||
"""
|
||||
self.trimesh.show()
|
||||
self.trimesh.show()
|
||||
|
@ -9,130 +9,131 @@ from typing import Union, List
|
||||
|
||||
|
||||
class Schedule:
|
||||
"""
|
||||
"""
|
||||
Schedule class
|
||||
"""
|
||||
def __init__(self):
|
||||
self._id = None
|
||||
self._type = None
|
||||
self._values = None
|
||||
self._data_type = None
|
||||
self._time_step = None
|
||||
self._time_range = None
|
||||
self._day_types = None
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
def __init__(self):
|
||||
self._id = None
|
||||
self._type = None
|
||||
self._values = None
|
||||
self._data_type = None
|
||||
self._time_step = None
|
||||
self._time_range = None
|
||||
self._day_types = None
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
Get schedule id, an universally unique identifier randomly generated
|
||||
:return: str
|
||||
"""
|
||||
if self._id is None:
|
||||
self._id = uuid.uuid4()
|
||||
return self._id
|
||||
if self._id is None:
|
||||
self._id = uuid.uuid4()
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def type(self) -> Union[None, str]:
|
||||
"""
|
||||
@property
|
||||
def type(self) -> Union[None, str]:
|
||||
"""
|
||||
Get schedule type
|
||||
:return: None or str
|
||||
"""
|
||||
return self._type
|
||||
return self._type
|
||||
|
||||
@type.setter
|
||||
def type(self, value):
|
||||
"""
|
||||
@type.setter
|
||||
def type(self, value):
|
||||
"""
|
||||
Set schedule type
|
||||
:param: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._type = str(value)
|
||||
if value is not None:
|
||||
self._type = str(value)
|
||||
|
||||
@property
|
||||
def values(self):
|
||||
"""
|
||||
@property
|
||||
def values(self):
|
||||
"""
|
||||
Get schedule values
|
||||
:return: [Any]
|
||||
"""
|
||||
return self._values
|
||||
return self._values
|
||||
|
||||
@values.setter
|
||||
def values(self, value):
|
||||
"""
|
||||
@values.setter
|
||||
def values(self, value):
|
||||
"""
|
||||
Set schedule values
|
||||
:param: [Any]
|
||||
"""
|
||||
self._values = value
|
||||
self._values = value
|
||||
|
||||
@property
|
||||
def data_type(self) -> Union[None, str]:
|
||||
"""
|
||||
@property
|
||||
def data_type(self) -> Union[None, str]:
|
||||
"""
|
||||
Get schedule data type from:
|
||||
['any_number', 'fraction', 'on_off', 'temperature', 'humidity', 'control_type']
|
||||
:return: None or str
|
||||
"""
|
||||
return self._data_type
|
||||
return self._data_type
|
||||
|
||||
@data_type.setter
|
||||
def data_type(self, value):
|
||||
"""
|
||||
@data_type.setter
|
||||
def data_type(self, value):
|
||||
"""
|
||||
Set schedule data type
|
||||
:param: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._data_type = str(value)
|
||||
if value is not None:
|
||||
self._data_type = str(value)
|
||||
|
||||
@property
|
||||
def time_step(self) -> Union[None, str]:
|
||||
"""
|
||||
@property
|
||||
def time_step(self) -> Union[None, str]:
|
||||
"""
|
||||
Get schedule time step from:
|
||||
['second', 'minute', 'hour', 'day', 'week', 'month']
|
||||
:return: None or str
|
||||
"""
|
||||
return self._time_step
|
||||
return self._time_step
|
||||
|
||||
@time_step.setter
|
||||
def time_step(self, value):
|
||||
"""
|
||||
@time_step.setter
|
||||
def time_step(self, value):
|
||||
"""
|
||||
Set schedule time step
|
||||
:param: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._time_step = str(value)
|
||||
if value is not None:
|
||||
self._time_step = str(value)
|
||||
|
||||
@property
|
||||
def time_range(self) -> Union[None, str]:
|
||||
"""
|
||||
@property
|
||||
def time_range(self) -> Union[None, str]:
|
||||
"""
|
||||
Get schedule time range from:
|
||||
['minute', 'hour', 'day', 'week', 'month', 'year']
|
||||
:return: None or str
|
||||
"""
|
||||
return self._time_range
|
||||
return self._time_range
|
||||
|
||||
@time_range.setter
|
||||
def time_range(self, value):
|
||||
"""
|
||||
@time_range.setter
|
||||
def time_range(self, value):
|
||||
"""
|
||||
Set schedule time range
|
||||
:param: str
|
||||
"""
|
||||
if value is not None:
|
||||
self._time_range = str(value)
|
||||
if value is not None:
|
||||
self._time_range = str(value)
|
||||
|
||||
@property
|
||||
def day_types(self) -> Union[None, List[str]]:
|
||||
"""
|
||||
@property
|
||||
def day_types(self) -> Union[None, List[str]]:
|
||||
"""
|
||||
Get schedule day types, as many as needed from:
|
||||
['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'holiday', 'winter_design_day',
|
||||
'summer_design_day']
|
||||
:return: None or [str]
|
||||
"""
|
||||
return self._day_types
|
||||
return self._day_types
|
||||
|
||||
@day_types.setter
|
||||
def day_types(self, value):
|
||||
"""
|
||||
@day_types.setter
|
||||
def day_types(self, value):
|
||||
"""
|
||||
Set schedule day types
|
||||
:param: [str]
|
||||
"""
|
||||
if value is not None:
|
||||
self._day_types = [str(i) for i in value]
|
||||
if value is not None:
|
||||
self._day_types = [str(i) for i in value]
|
||||
|
@ -2,6 +2,7 @@
|
||||
City module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
|
||||
Contributor Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import sys
|
||||
@ -21,6 +22,7 @@ from city_model_structure.subway_entrance import SubwayEntrance
|
||||
from city_model_structure.fuel import Fuel
|
||||
from helpers.geometry_helper import GeometryHelper
|
||||
from helpers.location import Location
|
||||
from city_model_structure.energy_system import EnergySystem
|
||||
|
||||
|
||||
class City:
|
||||
|
@ -1,7 +1,8 @@
|
||||
"""
|
||||
EnergySystem module
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2021 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
Contributor Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
from city_model_structure.city_object import CityObject
|
||||
@ -12,11 +13,33 @@ class EnergySystem(CityObject):
|
||||
"""
|
||||
EnergySystem(CityObject) class
|
||||
"""
|
||||
|
||||
def __init__(self, name, lod, surfaces, city_lower_corner):
|
||||
super().__init__(name, lod, surfaces, city_lower_corner)
|
||||
self._heat_pump = None
|
||||
self._type = 'energy_system'
|
||||
|
||||
@property
|
||||
def heat_pump(self) -> HeatPump:
|
||||
"""
|
||||
Heat pump energy system
|
||||
:return:
|
||||
"""
|
||||
return self._heat_pump
|
||||
|
||||
@heat_pump.setter
|
||||
def heat_pump(self, value):
|
||||
"""
|
||||
Set heat pumm for energy system
|
||||
:param value: HeatPump
|
||||
"""
|
||||
if self._heat_pump is None:
|
||||
self._heat_pump = value
|
||||
|
||||
@property
|
||||
def type(self) -> str:
|
||||
"""
|
||||
Type of city object
|
||||
:return: str
|
||||
"""
|
||||
return self._type
|
||||
|
@ -2,45 +2,189 @@
|
||||
heat_pump module defines a heat pump
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
Contributor Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
from typing import Union
|
||||
from typing import List
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class HeatPump:
|
||||
"""
|
||||
HeatPump class
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._model = None
|
||||
self._cooling_pf = None
|
||||
self._cooling_pa = None
|
||||
self._cooling_qw = None
|
||||
self._heating_pf = None
|
||||
self._heating_pa = None
|
||||
self._heating_qw = None
|
||||
self._cooling_capacity = None
|
||||
self._cooling_comp_power = None
|
||||
self._cooling_capacity_coff = None
|
||||
self._cooling_comp_power_coff = None
|
||||
self._heating_capacity = None
|
||||
self._heating_comp_power = None
|
||||
self._heating_capacity_coff = None
|
||||
self._heating_comp_power_coff = None
|
||||
|
||||
@property
|
||||
def model(self):
|
||||
def model(self) -> str:
|
||||
"""
|
||||
Get model name
|
||||
:return: str
|
||||
"""
|
||||
return self._model
|
||||
|
||||
@model.setter
|
||||
def model(self, value):
|
||||
"""
|
||||
Set model (name, indicated in capacity)
|
||||
:param value: str
|
||||
"""
|
||||
if self._model is None:
|
||||
self._model = value
|
||||
|
||||
@property
|
||||
def cooling_pf(self):
|
||||
def cooling_capacity(self) -> List[float]:
|
||||
"""
|
||||
Get cooling capacity in kW
|
||||
:return: [[float]]
|
||||
"""
|
||||
return self._cooling_pf
|
||||
return self._cooling_capacity
|
||||
|
||||
@cooling_pf.setter
|
||||
def cooling_pf(self, value):
|
||||
@cooling_capacity.setter
|
||||
def cooling_capacity(self, value):
|
||||
"""
|
||||
Set cooling capacity in kW
|
||||
:param value: [[float]]
|
||||
"""
|
||||
if self._cooling_pf is None:
|
||||
self._cooling_pf = value
|
||||
if self._cooling_capacity is None:
|
||||
self._cooling_capacity = value
|
||||
|
||||
@property
|
||||
def cooling_comp_power(self) -> List[float]:
|
||||
"""
|
||||
Get cooling compressor power input in kW
|
||||
:return: [[float]]
|
||||
"""
|
||||
return self._cooling_comp_power
|
||||
|
||||
@cooling_comp_power.setter
|
||||
def cooling_comp_power(self, value):
|
||||
"""
|
||||
Set the cooling compressor in kW
|
||||
:param value: [[float]]
|
||||
:return:
|
||||
"""
|
||||
if self._cooling_comp_power is None:
|
||||
self._cooling_comp_power = value
|
||||
|
||||
@property
|
||||
def cooling_capacity_coff(self) -> List[float]:
|
||||
"""
|
||||
Get cooling capacity coefficients
|
||||
:return: [float]
|
||||
"""
|
||||
return self._cooling_capacity_coff
|
||||
|
||||
@cooling_capacity_coff.setter
|
||||
def cooling_capacity_coff(self, value):
|
||||
"""
|
||||
Set the value for cooling capacity coefficients
|
||||
:param value: [float]
|
||||
:return:
|
||||
"""
|
||||
if self._cooling_capacity_coff is None:
|
||||
self._cooling_capacity_coff = value
|
||||
|
||||
@property
|
||||
def cooling_comp_power_coff(self) -> List[float]:
|
||||
"""
|
||||
Get cooling compressor power coefficients
|
||||
:return: [float]
|
||||
"""
|
||||
return self._cooling_comp_power_coff
|
||||
|
||||
@cooling_comp_power_coff.setter
|
||||
def cooling_comp_power_coff(self, value):
|
||||
"""
|
||||
Set the value for cooling compressor power coefficients
|
||||
:param value: [float]
|
||||
:return:
|
||||
"""
|
||||
if self._cooling_comp_power_coff is None:
|
||||
self._cooling_comp_power_coff = value
|
||||
|
||||
|
||||
|
||||
@property
|
||||
def heating_capacity(self) -> List[float]:
|
||||
"""
|
||||
Get heating capacity kW
|
||||
:return: [[float]]
|
||||
"""
|
||||
return self._heating_capacity
|
||||
|
||||
@heating_capacity.setter
|
||||
def heating_capacity(self, value):
|
||||
"""
|
||||
Set the heating capacity in kW
|
||||
:param value: [[float]]
|
||||
:return:
|
||||
"""
|
||||
if self._heating_capacity is None:
|
||||
self._heating_capacity = value
|
||||
|
||||
@property
|
||||
def heating_comp_power(self) -> List[float]:
|
||||
"""
|
||||
Get heating compressor power kW
|
||||
:return: [[float]]
|
||||
"""
|
||||
return self._heating_comp_power
|
||||
|
||||
@heating_comp_power.setter
|
||||
def heating_comp_power(self, value):
|
||||
"""
|
||||
Set the heating compressor power in kW
|
||||
:param value: [[float]]
|
||||
:return:
|
||||
"""
|
||||
if self._heating_comp_power is None:
|
||||
self._heating_comp_power = value
|
||||
|
||||
@property
|
||||
def heating_comp_power_coff(self) -> List[float]:
|
||||
"""
|
||||
Get heating compressor power coefficients
|
||||
:return: [float]
|
||||
"""
|
||||
return self._heating_comp_power_coff
|
||||
|
||||
@heating_comp_power_coff.setter
|
||||
def heating_comp_power_coff(self, value):
|
||||
"""
|
||||
Set the value for heating compressor power coefficients
|
||||
:param value: [float]
|
||||
:return:
|
||||
"""
|
||||
if self._heating_comp_power_coff is None:
|
||||
self._heating_comp_power_coff = value
|
||||
|
||||
@property
|
||||
def heating_capacity_coff(self) -> List[float]:
|
||||
"""
|
||||
Get heating capacity coefficients
|
||||
:return: [float]
|
||||
"""
|
||||
return self._heating_capacity_coff
|
||||
|
||||
@heating_capacity_coff.setter
|
||||
def heating_capacity_coff(self, value):
|
||||
"""
|
||||
Set the value for heating capacity coefficients
|
||||
:param value: [float]
|
||||
:return:
|
||||
"""
|
||||
if self._heating_capacity_coff is None:
|
||||
self._heating_capacity_coff = value
|
||||
|
||||
|
||||
|
20
data/energy_systems/heat_pumps/constants.yaml
Normal file
20
data/energy_systems/heat_pumps/constants.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
# Heat pump performance constants
|
||||
StartMonth: 1
|
||||
StartDay: 1
|
||||
StartHour: 0
|
||||
StartMinute: 0
|
||||
StartSecond: 0
|
||||
EndMonth: 1
|
||||
EndDay: 1
|
||||
EndHour: 0
|
||||
EndMinute: 0
|
||||
EndSecond: 0
|
||||
Cp: 4190
|
||||
Rhow: 1000
|
||||
TESDiameter: 5
|
||||
AuxHeaterEfficiency: 0.9
|
||||
|
||||
# These come from the data model according to other student's work
|
||||
ElecGridEF: 0.5
|
||||
ElectricityPrice: 0.073
|
||||
|
105120
data/energy_systems/heat_pumps/demand.txt
Normal file
105120
data/energy_systems/heat_pumps/demand.txt
Normal file
File diff suppressed because it is too large
Load Diff
816
data/energy_systems/heat_pumps/template.txt
Normal file
816
data/energy_systems/heat_pumps/template.txt
Normal file
@ -0,0 +1,816 @@
|
||||
|
||||
B 10 MUL
|
||||
64.1
|
||||
183.1
|
||||
|
||||
B 11 MUL
|
||||
198.1
|
||||
167.1
|
||||
163.1
|
||||
162.1
|
||||
|
||||
B 12 MUL
|
||||
201.1
|
||||
24.1
|
||||
|
||||
B 13 MUL
|
||||
70.1
|
||||
180.1
|
||||
|
||||
B 14 MUL
|
||||
184.1
|
||||
34.1
|
||||
|
||||
B 15 MUL
|
||||
198.1
|
||||
165.1
|
||||
163.1
|
||||
162.1
|
||||
|
||||
B 16 MUL
|
||||
186.1
|
||||
40.1
|
||||
|
||||
B 17 MUL
|
||||
79.1
|
||||
56.1
|
||||
69.1
|
||||
|
||||
B 18 MUL
|
||||
188.1
|
||||
49.1
|
||||
|
||||
B 19 MUL
|
||||
46.1
|
||||
158.1
|
||||
|
||||
B 20 MUL
|
||||
72.1
|
||||
66.1
|
||||
|
||||
B 21 MUL
|
||||
57.1
|
||||
182.1
|
||||
|
||||
B 22 MUL
|
||||
203.2
|
||||
43.1
|
||||
|
||||
B 23 MUL
|
||||
78.1
|
||||
50.1
|
||||
47.1
|
||||
|
||||
B 24 MUL
|
||||
201.1
|
||||
193.1
|
||||
196.1
|
||||
|
||||
B 25 MUL
|
||||
203.2
|
||||
76.1
|
||||
|
||||
B 26 MUL
|
||||
58.1
|
||||
68.1
|
||||
|
||||
B 27 MUL
|
||||
160.1
|
||||
63.1
|
||||
168.1
|
||||
136.1
|
||||
|
||||
B 28 MUL
|
||||
58.1
|
||||
60.1
|
||||
|
||||
B 29 MUL
|
||||
65.1
|
||||
181.1
|
||||
|
||||
B 30 MUL
|
||||
203.2
|
||||
58.1
|
||||
36.1
|
||||
|
||||
B 31 MUL
|
||||
159.1
|
||||
195.1
|
||||
|
||||
B 32 MUL
|
||||
203.2
|
||||
58.1
|
||||
77.1
|
||||
|
||||
B 33 MUL
|
||||
202.1
|
||||
74.1
|
||||
|
||||
B 34 CONST
|
||||
P 34
|
||||
$ElecGridEF % Constant value
|
||||
|
||||
B 35 CONST
|
||||
P 35
|
||||
5 % Constant value
|
||||
|
||||
B 36 CONST
|
||||
P 36
|
||||
$a3 % Constant value
|
||||
|
||||
B 37 CONST
|
||||
P 37
|
||||
$TemperatureDifference % Constant value
|
||||
|
||||
B 38 CONST
|
||||
P 38
|
||||
42 % Constant value
|
||||
|
||||
B 39 CONST
|
||||
P 39
|
||||
40 % Constant value
|
||||
|
||||
B 40 CONST
|
||||
P 40
|
||||
$ElectricityPrice % Constant value
|
||||
|
||||
B 41 CONST
|
||||
P 41
|
||||
9 % Constant value
|
||||
|
||||
B 42 CONST
|
||||
P 42
|
||||
12 % Constant value
|
||||
|
||||
B 43 CONST
|
||||
P 43
|
||||
$b2 % Constant value
|
||||
|
||||
B 44 CONST
|
||||
P 44
|
||||
$a6 % Constant value
|
||||
|
||||
B 45 CONST
|
||||
P 45
|
||||
55 % Constant value
|
||||
|
||||
B 46 CONST
|
||||
P 46
|
||||
$Cp % Constant value
|
||||
|
||||
B 47 CONST
|
||||
P 47
|
||||
$FuelEF % Constant value
|
||||
|
||||
B 48 CONST
|
||||
P 48
|
||||
2 % Constant value
|
||||
|
||||
B 49 CONST
|
||||
P 49
|
||||
1 % Constant value
|
||||
|
||||
B 50 CONST
|
||||
P 50
|
||||
300 % Constant value
|
||||
|
||||
B 51 CONST
|
||||
P 51
|
||||
10 % Constant value
|
||||
|
||||
B 52 CONST
|
||||
P 52
|
||||
0 % Constant value
|
||||
|
||||
B 53 CONST
|
||||
P 53
|
||||
12 % Constant value
|
||||
|
||||
B 54 CONST
|
||||
P 54
|
||||
$FuelLHV % Constant value
|
||||
|
||||
B 55 CONST
|
||||
P 55
|
||||
2 % Constant value
|
||||
|
||||
B 56 CONST
|
||||
P 56
|
||||
300 % Constant value
|
||||
|
||||
B 57 CONST
|
||||
P 57
|
||||
$b5 % Constant value
|
||||
|
||||
B 58 CONST
|
||||
P 58
|
||||
$HPSupTemp % Constant value
|
||||
|
||||
B 59 CONST
|
||||
P 59
|
||||
40 % Constant value
|
||||
|
||||
B 60 CONST
|
||||
P 60
|
||||
$a4 % Constant value
|
||||
|
||||
B 61 CONST
|
||||
P 61
|
||||
$b6 % Constant value
|
||||
|
||||
B 62 CONST
|
||||
P 62
|
||||
2 % Constant value
|
||||
|
||||
B 63 CONST
|
||||
P 63
|
||||
$Cp % Constant value
|
||||
|
||||
B 64 CONST
|
||||
P 64
|
||||
$b1 % Constant value
|
||||
|
||||
B 65 CONST
|
||||
P 65
|
||||
$a1 % Constant value
|
||||
|
||||
B 66 CONST
|
||||
P 66
|
||||
$TemperatureDifference % Constant value
|
||||
|
||||
B 67 CONST
|
||||
P 67
|
||||
$MaximumHPEnergyInput % Constant value
|
||||
|
||||
B 68 CONST
|
||||
P 68
|
||||
$b4 % Constant value
|
||||
|
||||
B 69 CONST
|
||||
P 69
|
||||
$FuelPrice % Constant value
|
||||
|
||||
B 70 CONST
|
||||
P 70
|
||||
$a5 % Constant value
|
||||
|
||||
B 71 CONST
|
||||
P 71
|
||||
2 % Constant value
|
||||
|
||||
B 72 CONST
|
||||
P 72
|
||||
$Cp % Constant value
|
||||
|
||||
B 73 CONST
|
||||
P 73
|
||||
$BuildingSuppTemp % Constant value
|
||||
|
||||
B 74 CONST
|
||||
P 74
|
||||
25 % Constant value
|
||||
|
||||
B 75 CONST
|
||||
P 75
|
||||
0 % Constant value
|
||||
|
||||
B 76 CONST
|
||||
P 76
|
||||
$a2 % Constant value
|
||||
|
||||
B 77 CONST
|
||||
P 77
|
||||
$b3 % Constant value
|
||||
|
||||
B 78 ATT
|
||||
191.1
|
||||
P 78
|
||||
$FuelDensity % Attenuation factor a
|
||||
|
||||
B 79 ATT
|
||||
191.1
|
||||
P 79
|
||||
$FuelDensity % Attenuation factor a
|
||||
|
||||
B 80 ATT
|
||||
27.1
|
||||
P 80
|
||||
$AuxHeaterEfficiency % Attenuation factor a
|
||||
|
||||
B 81 ATT
|
||||
191.1
|
||||
P 81
|
||||
$FuelDensity % Attenuation factor a
|
||||
|
||||
B 82 ATT
|
||||
11.1
|
||||
P 82
|
||||
12 % Attenuation factor a
|
||||
|
||||
B 83 ATT
|
||||
210.5
|
||||
P 83
|
||||
3600000 % Attenuation factor a
|
||||
|
||||
B 84 ATT
|
||||
161.1
|
||||
P 84
|
||||
3600000 % Attenuation factor a
|
||||
|
||||
B 85 ATT
|
||||
27.1
|
||||
P 85
|
||||
1000 % Attenuation factor a
|
||||
|
||||
|
||||
B 125 WRITE
|
||||
156.1
|
||||
156.2
|
||||
156.3
|
||||
P 125
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut7 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 126 WRITE
|
||||
151.1
|
||||
151.2
|
||||
151.3
|
||||
P 126
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut2 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 127 WRITE
|
||||
154.1
|
||||
154.2
|
||||
154.3
|
||||
P 127
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut3 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 128 WRITE
|
||||
153.1
|
||||
153.2
|
||||
153.3
|
||||
P 128
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut5 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 129 WRITE
|
||||
204.1
|
||||
204.2
|
||||
204.3
|
||||
204.4
|
||||
204.5
|
||||
15.1
|
||||
11.1
|
||||
190.1
|
||||
187.1
|
||||
160.1
|
||||
210.1
|
||||
210.2
|
||||
210.3
|
||||
210.4
|
||||
210.5
|
||||
83.1
|
||||
84.1
|
||||
191.1
|
||||
85.1
|
||||
16.1
|
||||
17.1
|
||||
14.1
|
||||
23.1
|
||||
164.1
|
||||
145.1
|
||||
P 129
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut1 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 130 WRITE
|
||||
204.1
|
||||
204.2
|
||||
204.3
|
||||
152.1
|
||||
152.2
|
||||
P 130
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut10 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 131 WRITE
|
||||
149.1
|
||||
149.2
|
||||
P 131
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut9 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 132 WRITE
|
||||
157.1
|
||||
157.2
|
||||
P 132
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut8 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 133 WRITE
|
||||
150.1
|
||||
150.2
|
||||
P 133
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut4 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 134 WRITE
|
||||
155.1
|
||||
155.2
|
||||
P 134
|
||||
2 % Mode
|
||||
0 % Suppress FNQ inputs
|
||||
$fileOut6 % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 135 LT
|
||||
204.2
|
||||
35.1
|
||||
|
||||
B 136 LT
|
||||
210.1
|
||||
39.1
|
||||
|
||||
%B 137 SCREEN
|
||||
%176.1
|
||||
%P 137
|
||||
%'*' % Format
|
||||
%'Total CO2 Emissions from Electricity Grid (g)' % Headline
|
||||
|
||||
%B 138 SCREEN
|
||||
%178.1
|
||||
%P 138
|
||||
%'*' % Format
|
||||
%'Total Electricity Cost in a Year (CAD)' % Headline
|
||||
|
||||
%B 139 SCREEN
|
||||
%173.1
|
||||
%P 139
|
||||
%'*' % Format
|
||||
%'Total Cost of the Auxiliary Heater Fuel in a Year (CAD)' % Headline
|
||||
|
||||
%B 140 SCREEN
|
||||
%177.1
|
||||
%P 140
|
||||
%'*' % Format
|
||||
%'Total CO2 Emissions from Auxiliary Heater (g)' % Headline
|
||||
|
||||
%B 141 SCREEN
|
||||
%189.1
|
||||
%P 141
|
||||
%'*' % Format
|
||||
%'HP Seasonal COP' % Headline
|
||||
|
||||
%B 142 SCREEN
|
||||
%148.1
|
||||
%P 142
|
||||
%'*' % Format
|
||||
%'Maximum Number of HPs in Operation' % Headline
|
||||
|
||||
%B 143 SCREEN
|
||||
%174.1
|
||||
%P 143
|
||||
%'*' % Format
|
||||
%'Total Electricuty Demand of Heat Pumps in a year (kWh)' % Headline
|
||||
|
||||
%B 144 SCREEN
|
||||
%179.1
|
||||
%P 144
|
||||
%'*' % Format
|
||||
%'Total Fossil Fuel consumption in a Year (m3)' % Headline
|
||||
|
||||
B 145 READ
|
||||
P 145
|
||||
1 % Number of values to be read per record
|
||||
0 % Number of records to be skipped on the first call
|
||||
$HeatingDemand % File name
|
||||
'*' % Fortran format
|
||||
|
||||
B 146 DELAY
|
||||
15.1
|
||||
P 146
|
||||
0 % Initial value
|
||||
|
||||
B 147 DELAY
|
||||
210.5
|
||||
P 147
|
||||
0 % Initial value
|
||||
|
||||
B 148 MAXX
|
||||
198.1
|
||||
|
||||
B 149 CUMC
|
||||
204.3
|
||||
205.1
|
||||
|
||||
B 150 CUMC
|
||||
204.2
|
||||
205.1
|
||||
|
||||
B 151 CUMC
|
||||
204.3
|
||||
14.1
|
||||
23.1
|
||||
|
||||
B 152 CUMC
|
||||
204.4
|
||||
82.1
|
||||
|
||||
B 153 CUMC
|
||||
204.2
|
||||
14.1
|
||||
23.1
|
||||
|
||||
B 154 CUMC
|
||||
204.2
|
||||
16.1
|
||||
17.1
|
||||
|
||||
B 155 CUMC
|
||||
204.3
|
||||
82.1
|
||||
|
||||
B 156 CUMC
|
||||
204.3
|
||||
16.1
|
||||
17.1
|
||||
|
||||
B 157 CUMC
|
||||
204.2
|
||||
82.1
|
||||
|
||||
B 158 SUM
|
||||
58.1
|
||||
169.1
|
||||
|
||||
B 159 SUM
|
||||
170.1
|
||||
210.1
|
||||
|
||||
B 160 SUM
|
||||
18.1
|
||||
75.1
|
||||
|
||||
B 161 SUM
|
||||
210.5
|
||||
172.1
|
||||
|
||||
B 162 SUM
|
||||
12.1
|
||||
200.1
|
||||
|
||||
B 163 SUM
|
||||
135.1
|
||||
197.1
|
||||
|
||||
B 164 SUM
|
||||
31.1
|
||||
33.1
|
||||
|
||||
B 165 SUM
|
||||
29.1
|
||||
25.1
|
||||
30.1
|
||||
28.1
|
||||
13.1
|
||||
44.1
|
||||
|
||||
B 166 SUM
|
||||
51.1
|
||||
203.2
|
||||
|
||||
B 167 SUM
|
||||
10.1
|
||||
22.1
|
||||
32.1
|
||||
26.1
|
||||
21.1
|
||||
61.1
|
||||
|
||||
B 168 SUM
|
||||
73.1
|
||||
171.1
|
||||
|
||||
B 169 CHS
|
||||
210.4
|
||||
|
||||
B 170 CHS
|
||||
37.1
|
||||
|
||||
B 171 CHS
|
||||
210.1
|
||||
|
||||
B 172 CHS
|
||||
147.1
|
||||
|
||||
B 173 CUM
|
||||
17.1
|
||||
|
||||
B 174 CUM
|
||||
82.1
|
||||
|
||||
B 175 CUM
|
||||
15.1
|
||||
11.1
|
||||
|
||||
B 176 CUM
|
||||
14.1
|
||||
|
||||
B 177 CUM
|
||||
23.1
|
||||
|
||||
B 178 CUM
|
||||
16.1
|
||||
|
||||
B 179 CUM
|
||||
205.1
|
||||
|
||||
B 180 EXPG
|
||||
58.1
|
||||
55.1
|
||||
|
||||
B 181 EXPG
|
||||
203.2
|
||||
71.1
|
||||
|
||||
B 182 EXPG
|
||||
58.1
|
||||
48.1
|
||||
|
||||
B 183 EXPG
|
||||
203.2
|
||||
62.1
|
||||
|
||||
B 184 DIV
|
||||
11.1
|
||||
53.1
|
||||
|
||||
B 185 DIV
|
||||
67.1
|
||||
165.1
|
||||
|
||||
B 186 DIV
|
||||
11.1
|
||||
42.1
|
||||
|
||||
B 187 DIV
|
||||
206.1
|
||||
19.1
|
||||
|
||||
B 188 DIV
|
||||
207.1
|
||||
20.1
|
||||
|
||||
B 189 DIV
|
||||
175.1
|
||||
175.2
|
||||
|
||||
B 190 DIV
|
||||
15.1
|
||||
11.1
|
||||
|
||||
B 191 DIV
|
||||
80.1
|
||||
54.1
|
||||
|
||||
B 192 GE
|
||||
210.1
|
||||
45.1
|
||||
P 192
|
||||
0 % Error tolerance
|
||||
|
||||
B 193 GE
|
||||
210.1
|
||||
38.1
|
||||
P 193
|
||||
0 % Error tolerance
|
||||
|
||||
B 194 SOY
|
||||
204.1
|
||||
204.2
|
||||
204.3
|
||||
204.4
|
||||
204.5
|
||||
204.6
|
||||
|
||||
B 195 GT
|
||||
210.1
|
||||
59.1
|
||||
|
||||
B 196 GT
|
||||
146.1
|
||||
52.1
|
||||
|
||||
B 197 GT
|
||||
204.2
|
||||
41.1
|
||||
|
||||
B 198 INT
|
||||
185.1
|
||||
|
||||
B 199 MTM
|
||||
204.2
|
||||
P 199
|
||||
'Montreal' % Location
|
||||
|
||||
B 200 INV
|
||||
193.1
|
||||
|
||||
B 201 INV
|
||||
192.1
|
||||
|
||||
B 202 INV
|
||||
195.1
|
||||
|
||||
B 203 GENGT
|
||||
199.1
|
||||
199.3
|
||||
199.4
|
||||
199.5
|
||||
199.7
|
||||
199.8
|
||||
204.1
|
||||
204.2
|
||||
204.3
|
||||
204.4
|
||||
P 203
|
||||
45.5 % Latitude
|
||||
73.62 % Longitude
|
||||
5 % Time zone
|
||||
1 % Variance factor of the Gordon Reddy correlation
|
||||
0 % Year-to-year variability
|
||||
0.3 % Autocorrelation coefficient lag one
|
||||
0.171 % Autocorrelation coefficient lag two
|
||||
4711 % Initialisation of random number generator
|
||||
2 % Maximum allowed mean temperature deviation
|
||||
100 % Maximum number of iterations
|
||||
|
||||
B 204 CLOCK
|
||||
P 204
|
||||
$StartYear % Start year
|
||||
$StartMonth % Start month
|
||||
$StartDay % Start day
|
||||
$StartHour % Start hour
|
||||
$StartMinute % Start minute
|
||||
$StartSecond % Start second
|
||||
$EndYear % End year
|
||||
$EndMonth % End month
|
||||
$EndDay % End day
|
||||
$EndHour % End hour
|
||||
$EndMinute % End minute
|
||||
$EndSecond % End second
|
||||
5 % Increment
|
||||
'm' % Unit
|
||||
|
||||
B 205 GAIN
|
||||
81.1
|
||||
P 205
|
||||
300 % Gain factor g
|
||||
|
||||
B 206 GAIN
|
||||
15.1
|
||||
P 206
|
||||
1000 % Gain factor g
|
||||
|
||||
B 207 GAIN
|
||||
145.1
|
||||
P 207
|
||||
1000 % Gain factor g
|
||||
|
||||
B 210 TANKST
|
||||
58.1
|
||||
187.1
|
||||
164.1
|
||||
160.1
|
||||
166.1
|
||||
194.1
|
||||
P 210
|
||||
$TESCapacity % Tank volume
|
||||
4 % Number of temperature nodes
|
||||
$TESDiameter % Tank diameter
|
||||
$Cp % Specfic heat of fluid
|
||||
$Rhow % Fluid density
|
||||
0 % Overall heat-loss coefficient
|
||||
1 % Effective heat conductivity
|
||||
30 % Initial tank temperature
|
||||
|
0
exports/energy_systems/__init__.py
Normal file
0
exports/energy_systems/__init__.py
Normal file
216
exports/energy_systems/heat_pump_export.py
Normal file
216
exports/energy_systems/heat_pump_export.py
Normal file
@ -0,0 +1,216 @@
|
||||
"""
|
||||
HeatPumpExport exports heatpump coefficient into several formats
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
import os
|
||||
from typing import List, Tuple, Union, Dict
|
||||
import yaml
|
||||
from string import Template
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class HeatPumpExport:
|
||||
"""
|
||||
Exports heat pump values as coefficients
|
||||
of some defined function
|
||||
"""
|
||||
|
||||
def __init__(self, base_path, city, output_path):
|
||||
self._template_path = (base_path / 'heat_pumps/template.txt')
|
||||
self._constants_path = (base_path / 'heat_pumps/constants.yaml')
|
||||
# needed to compute max demand.
|
||||
self._demand_path = (base_path / 'heat_pumps/demand.txt')
|
||||
self._city = city
|
||||
self._input_data = None
|
||||
self._base_path = base_path
|
||||
self._output_path = output_path
|
||||
|
||||
def run_insel(self, user_input: Dict, hp_model: str, data_type: str) -> None:
|
||||
"""
|
||||
Runs insel and write the necessary files
|
||||
:param user_input: a dictionary containing the user
|
||||
values necessary to run insel
|
||||
:param hp_model: a string that indicates the heat
|
||||
pump model to be used e.g. 012, 015
|
||||
:param data_type: a string that indicates whether
|
||||
insel should run for heat or cooling performance
|
||||
:return:
|
||||
"""
|
||||
self._input_data = user_input
|
||||
# update input data with other data necessary to run insel
|
||||
capacity_coff, comp_power_coff = self._extract_model_coff(hp_model, data_type)
|
||||
self._update_input_data_with_coff(capacity_coff, comp_power_coff)
|
||||
# update input data with constants
|
||||
self._update_input_data_with_constants()
|
||||
# update input data with input and output files for insel
|
||||
self._update_input_data_with_files()
|
||||
insel_file_handler = None
|
||||
insel_template_handler = None
|
||||
try:
|
||||
# run insel
|
||||
insel_template_handler = open(self._template_path, "r")
|
||||
insel_template_content = insel_template_handler.read()
|
||||
insel_template = Template(insel_template_content).substitute(self._input_data)
|
||||
# create the insel file and write the template with substituted values into it
|
||||
insel_file = (self._base_path / 'heat_pumps/dompark_heat_pump.insel')
|
||||
insel_file_handler = open(insel_file, "w")
|
||||
insel_file_handler.write(insel_template)
|
||||
# Now run insel
|
||||
self._delete_existing_output_files()
|
||||
os.system('insel {}'.format(insel_file))
|
||||
# Writer headers to csv output files generated by insel
|
||||
self._write_insel_output_headers()
|
||||
# User output
|
||||
self._get_user_out_put()
|
||||
except IOError as err:
|
||||
print("I/O exception: {}".format(err))
|
||||
finally:
|
||||
insel_file_handler.close()
|
||||
insel_template_handler.close()
|
||||
|
||||
def _write_insel_output_headers(self):
|
||||
"""
|
||||
Write headers to the various csv file generated by insel
|
||||
:return:
|
||||
"""
|
||||
header_data = {
|
||||
self._input_data['fileOut1']: ['Year', ' Month', ' Day', 'Hour', 'Minute', 'HP Heat Output (kW)',
|
||||
'HP Electricity Consumption (kW)', 'HP COP', 'TES Charging Rate (kg/s)',
|
||||
'TES Discharging Rate (kg/s)', 'TES Node 1 Temperature', 'TES Node 2 Temperature',
|
||||
'TES Node 3 Temperature', 'TES Node 4 Temperature', 'TES Energy Content (J)',
|
||||
'TES Energy Content (kWh)', 'TES Energy Content Variation (kWh)',
|
||||
'Auxiliary Heater Fuel Flow Rate (kg/s)', 'Auxiliary Heater Energy Input (kW)',
|
||||
'HP Operational Cost (CAD)', 'Auxiliary Heater Operational Cost (CAD)',
|
||||
'Operational CO2 Emissions of HP (g)',
|
||||
'Operational CO2 Emissions of Auxiliary Heater (g)',
|
||||
'Return Temperature', 'Demand (kW)'],
|
||||
self._input_data['fileOut2']: ['Day', 'Operational Daily Emissions from Heat Pumps (g)',
|
||||
'Operational Daily Emissions from Auxiliary Heater (g)'],
|
||||
self._input_data['fileOut3']: ['Month', 'Monthly Operational Costs of Heat Pumps (CAD)',
|
||||
'Monthly Operational Costs of Auxiliary Heater (CAD)'],
|
||||
self._input_data['fileOut4']: ['Month', 'Monthly Fuel Consumption of Auxiliary Heater (m3)'],
|
||||
self._input_data['fileOut5']: ['Month', 'Operational Monthly Emissions from Heat Pumps (g)',
|
||||
'Operational Monthly Emissions from Auxiliary Heater (g)'],
|
||||
self._input_data['fileOut6']: ['Day', 'Daily HP Electricity Demand (kWh)'],
|
||||
self._input_data['fileOut7']: ['Day', 'Daily Operational Costs of Heat Pumps (CAD)',
|
||||
'Daily Operational Costs of Auxiliary Heater (CAD)'],
|
||||
self._input_data['fileOut8']: ['Month', 'Monthly HP Electricity Demand (kWh)'],
|
||||
self._input_data['fileOut9']: ['Day', 'Daily Fuel Consumption of Auxiliary Heater (m3)'],
|
||||
self._input_data['fileOut10']: ['Year', 'Month', 'Day', 'Hour', 'HP Electricity Demand (kWh)']
|
||||
}
|
||||
for file_path, header in header_data.items():
|
||||
file_path = file_path.strip("'")
|
||||
df = pd.read_csv(file_path, header=None, sep='\s+')
|
||||
df.to_csv(file_path, header=header)
|
||||
|
||||
def _update_input_data_with_files(self):
|
||||
"""
|
||||
Updates input data for insel with some files that will
|
||||
be written to after insel runs. Also specifies and input file
|
||||
which is the Heating Demand (demand.txt) file
|
||||
:return:
|
||||
"""
|
||||
self._input_data["HeatingDemand"] = f"'{str(self._demand_path)}'"
|
||||
self._input_data["fileOut1"] = f"'{str((self._base_path / 'heat_pumps/technical_performance.csv'))}'"
|
||||
self._input_data["fileOut2"] = f"'{str((self._base_path / 'heat_pumps/system_daily_emissions.csv'))}'"
|
||||
self._input_data["fileOut3"] = f"'{str((self._base_path / 'heat_pumps/monthly_operational_costs.csv'))}'"
|
||||
self._input_data["fileOut4"] = f"'{str((self._base_path / 'heat_pumps/monthly_fossil_fuel_consumptions.csv'))}'"
|
||||
self._input_data["fileOut5"] = f"'{str((self._base_path / 'heat_pumps/system_monthly_emissions.csv'))}'"
|
||||
self._input_data["fileOut6"] = f"'{str((self._base_path / 'heat_pumps/daily_hp_electricity_demand.csv'))}'"
|
||||
self._input_data["fileOut7"] = f"'{str((self._base_path / 'heat_pumps/daily_operational_costs.csv'))}'"
|
||||
self._input_data["fileOut8"] = f"'{str((self._base_path / 'heat_pumps/monthly_hp_electricity_demand.csv'))}'"
|
||||
self._input_data["fileOut9"] = f"'{str((self._base_path / 'heat_pumps/daily_fossil_fuel_consumption.csv'))}'"
|
||||
self._input_data["fileOut10"] = f"'{str((self._base_path / 'heat_pumps/hp_hourly_electricity_demand.csv'))}'"
|
||||
|
||||
def _delete_existing_output_files(self):
|
||||
"""
|
||||
Remove existing out files generated by insel before
|
||||
running insel
|
||||
:return:
|
||||
"""
|
||||
for key, file_path in self._input_data.items():
|
||||
if 'fileOut' in key:
|
||||
file_path = file_path.strip("'")
|
||||
try:
|
||||
os.remove(file_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _compute_max_demand(self):
|
||||
"""
|
||||
Retrieves the maximum demand value from
|
||||
the demands text file
|
||||
:return: float
|
||||
"""
|
||||
max_demand = -1
|
||||
with open(self._demand_path) as file_handler:
|
||||
for demand in file_handler.readlines():
|
||||
if float(demand) > max_demand:
|
||||
max_demand = float(demand)
|
||||
return max_demand
|
||||
|
||||
def _update_input_data_with_constants(self):
|
||||
with open(self._constants_path) as file:
|
||||
constants_dict = yaml.load(file, Loader=yaml.FullLoader)
|
||||
for key, value in constants_dict.items():
|
||||
self._input_data[key] = value
|
||||
# compute maximum demand. TODO: This should come from catalog in the future
|
||||
max_demand = self._compute_max_demand()
|
||||
# compute TESCapacity
|
||||
self._input_data["TESCapacity"] = self._input_data["HoursOfStorageAtMaxDemand"] * (max_demand * 3.6) / (
|
||||
(self._input_data["Cp"] / 1000) * self._input_data["TemperatureDifference"])
|
||||
|
||||
def _update_input_data_with_coff(self, capacity_coff: List, comp_power_coff: List):
|
||||
"""
|
||||
Updates the user data with coefficients derived from imports
|
||||
:param capacity_coff: heat or cooling capacity coefficients
|
||||
:param comp_power_coff: heat or cooling comppressor power coefficients
|
||||
:return:
|
||||
"""
|
||||
self._input_data["a1"] = capacity_coff[0]
|
||||
self._input_data["a2"] = capacity_coff[1]
|
||||
self._input_data["a3"] = capacity_coff[2]
|
||||
self._input_data["a4"] = capacity_coff[3]
|
||||
self._input_data["a5"] = capacity_coff[4]
|
||||
self._input_data["a6"] = capacity_coff[5]
|
||||
self._input_data["b1"] = comp_power_coff[0]
|
||||
self._input_data["b2"] = comp_power_coff[1]
|
||||
self._input_data["b3"] = comp_power_coff[2]
|
||||
self._input_data["b4"] = comp_power_coff[3]
|
||||
self._input_data["b5"] = comp_power_coff[4]
|
||||
self._input_data["b6"] = comp_power_coff[5]
|
||||
|
||||
def _extract_model_coff(self, hp_model: str, data_type='heat') -> Union[Tuple[List, List], None]:
|
||||
"""
|
||||
Extracts heat pump coefficient data for a specific
|
||||
model. e.g 012, 140
|
||||
:param hp_model: the model type
|
||||
:param data_type: indicates whether we're extracting cooling
|
||||
or heating perfarmcn coefficients
|
||||
:return:
|
||||
"""
|
||||
for energy_system in self._city.energy_systems:
|
||||
if energy_system.heat_pump.model == hp_model:
|
||||
if data_type == 'heat':
|
||||
return energy_system.heat_pump.heating_capacity_coff, energy_system.heat_pump.heating_comp_power_coff
|
||||
return energy_system.heat_pump.cooling_capacity_coff, energy_system.heat_pump.cooling_comp_power_coff
|
||||
return None
|
||||
|
||||
def _get_user_out_put(self):
|
||||
"""
|
||||
Extracts monthly electricity demand and fossil fuel consumption
|
||||
from output files generated by insel
|
||||
:return:
|
||||
"""
|
||||
|
||||
electricity_df = pd.read_csv(self._input_data['fileOut8'].strip("'")).iloc[:, 2]
|
||||
fossil_df = pd.read_csv(self._input_data['fileOut4'].strip("'")).iloc[:, 2]
|
||||
|
||||
data = [electricity_df, fossil_df]
|
||||
df = pd.concat(data, axis=1)
|
||||
df = df.append(df.agg(['sum']))
|
||||
s = pd.Series(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "Total"])
|
||||
df = df.set_index([s])
|
||||
df.to_csv(self._output_path)
|
||||
|
40
exports/energy_systems_factory.py
Normal file
40
exports/energy_systems_factory.py
Normal file
@ -0,0 +1,40 @@
|
||||
"""
|
||||
EnergySystemsFactory exports energy systems into several formats
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from exports.energy_systems.heat_pump_export import HeatPumpExport
|
||||
|
||||
|
||||
class EnergySystemsExportFactory:
|
||||
"""
|
||||
Exports factory class for energy systems
|
||||
"""
|
||||
|
||||
def __init__(self, city, user_input, hp_model, output_path, data_type='heat', base_path=None):
|
||||
self._city = city
|
||||
if base_path is None:
|
||||
base_path = base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
|
||||
self._base_path = base_path
|
||||
self._user_input = user_input
|
||||
self._hp_model = hp_model
|
||||
self._data_type = data_type
|
||||
self._output_path = output_path
|
||||
|
||||
def _export_heat_pump(self):
|
||||
"""
|
||||
Exports heat pump performance data as coefficients
|
||||
of some objective function
|
||||
:return: None
|
||||
"""
|
||||
HeatPumpExport(self._base_path, self._city, self._output_path)\
|
||||
.run_insel(self._user_input, self._hp_model, self._data_type)
|
||||
|
||||
def export(self):
|
||||
"""
|
||||
Export the city given to the class using the given export type handler
|
||||
:return: None
|
||||
"""
|
||||
return getattr(self, '_export_heat_pump', lambda: None)()
|
@ -1,26 +1,143 @@
|
||||
"""
|
||||
XlsxHeatPumpParameters import the heat pump information
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2020 Project Author
|
||||
Copyright © 2020 Project Author Peter Yefi peteryefi@gmail.com
|
||||
Contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
from typing import Dict
|
||||
from city_model_structure.energy_systems.heat_pump import HeatPump
|
||||
from city_model_structure.energy_system import EnergySystem
|
||||
from scipy.optimize import curve_fit
|
||||
import numpy as np
|
||||
from typing import List
|
||||
import itertools
|
||||
|
||||
|
||||
class XlsxHeatPumpParameters:
|
||||
"""
|
||||
XlsxHeatPumpParameters class
|
||||
"""
|
||||
|
||||
def __init__(self, city, base_path):
|
||||
self._city = city
|
||||
self._base_path = (base_path / 'heat_pumps/Air source.xlsx')
|
||||
self._base_path = (base_path / 'heat_pumps/Air Source.xlsx')
|
||||
|
||||
def _read_file(self):
|
||||
def _read_file(self) -> Dict:
|
||||
"""
|
||||
reads xlsx file containing the heat pump information
|
||||
into a dictionary
|
||||
:return : Dict
|
||||
"""
|
||||
xl_file = pd.ExcelFile(self._base_path)
|
||||
heat_pump_dfs = {sheet_name: xl_file.parse(sheet_name)
|
||||
for sheet_name in xl_file.sheet_names}
|
||||
|
||||
cooling_data = {}
|
||||
heating_data = {}
|
||||
|
||||
for sheet, dataframe in heat_pump_dfs.items():
|
||||
if sheet == "Summary":
|
||||
continue
|
||||
# Remove nan rows and columns and extract cooling and heating data
|
||||
# for each sheet
|
||||
df = heat_pump_dfs[sheet].dropna(axis=1, how='all')
|
||||
cooling_df = df.iloc[4:34, 0:8]
|
||||
heating_df = df.iloc[4:29, 8:20]
|
||||
|
||||
# extract the data into dictionaries each sheet is a key entry in the
|
||||
# dictionary
|
||||
cooling_data[sheet] = {}
|
||||
heating_data[sheet] = {}
|
||||
i = 0
|
||||
# for each sheet extract data for twout/Ta.RU temperatures. Thus, the twout
|
||||
# temp is the key for the values of pf,pa,qw data
|
||||
while i < 25:
|
||||
cooling_data[sheet][cooling_df.iloc[i][0]] = cooling_df.iloc[i + 1:i + 4, 2:8].values.tolist()
|
||||
heating_data[sheet][heating_df.iloc[i][0]] = heating_df.iloc[i + 1:i + 4, 2:8].values.tolist()
|
||||
i = i + 5
|
||||
# extract the last cooling data
|
||||
cooling_data[sheet][cooling_df.iloc[i][0]] = cooling_df.iloc[i + 1:i + 4, 2:8].values.tolist()
|
||||
return {"cooling": cooling_data, "heating": heating_data}
|
||||
|
||||
def enrich_city(self):
|
||||
"""
|
||||
Enriches the city with information from file
|
||||
"""
|
||||
heap_pump_data = self._read_file()
|
||||
for (k_cool, v_cool), (k_heat, v_heat) in \
|
||||
zip(heap_pump_data["cooling"].items(), heap_pump_data["heating"].items()):
|
||||
heat_pump = HeatPump()
|
||||
heat_pump.model = k_cool
|
||||
h_data = self._extract_heat_pump_data(v_heat)
|
||||
c_data = self._extract_heat_pump_data(v_cool)
|
||||
heat_pump.cooling_capacity = c_data[0]
|
||||
heat_pump.cooling_comp_power = c_data[1]
|
||||
heat_pump.cooling_capacity_coff = self._compute_coefficients(c_data[0], "cool")
|
||||
heat_pump.cooling_comp_power_coff = self._compute_coefficients(c_data[1], "cool")
|
||||
heat_pump.heating_capacity = h_data[0]
|
||||
heat_pump.heating_comp_power = h_data[1]
|
||||
heat_pump.heating_capacity_coff = self._compute_coefficients(h_data[0])
|
||||
heat_pump.heating_comp_power_coff = self._compute_coefficients(h_data[1])
|
||||
|
||||
energy_system = EnergySystem('{} capacity heat pump'.format(heat_pump.model), 0, [], None)
|
||||
energy_system.heat_pump = heat_pump
|
||||
self._city.add_city_object(energy_system)
|
||||
return self._city
|
||||
|
||||
def _extract_heat_pump_data(self, heat_pump_capacity_data: Dict) -> [List, List]:
|
||||
"""
|
||||
Fetches a list of metric based data for heat pump for various temperature,
|
||||
eg. cooling capacity data for 12 capacity heat pump
|
||||
for 6,7,8,9,10 and 11 degree celsius
|
||||
:param heat_pump_capacity_data: the heat pump capacity data from the
|
||||
which the metric specific data is fetched: {List}
|
||||
:return: List
|
||||
"""
|
||||
cooling_heating_capacity_data = []
|
||||
compressor_power_data = []
|
||||
for _, metric_data in heat_pump_capacity_data.items():
|
||||
cooling_heating_capacity_data.append(metric_data[0])
|
||||
compressor_power_data.append(metric_data[1])
|
||||
return [cooling_heating_capacity_data, compressor_power_data]
|
||||
|
||||
def _compute_coefficients(self, heat_pump_data: List, data_type="heat") -> List[float]:
|
||||
"""
|
||||
Compute heat output and electrical demand coefficients
|
||||
from heating and cooling performance data
|
||||
:param heat_pump_data: a list of heat pump data. eg. cooling capacity
|
||||
:param data_type: string to indicate if data is cooling performance data
|
||||
or heating performance data
|
||||
:return: Tuple[Dict, Dict]
|
||||
"""
|
||||
# Determine the recurrence of temperature values. 6 repetitions for
|
||||
# cooling performance and 5 repetition for heating performance
|
||||
temp_multiplier = 5 if data_type == "heat" else 6
|
||||
out_temp = [25, 30, 32, 35, 40, 45] * temp_multiplier
|
||||
|
||||
heat_x_values = np.repeat([-5, 0, 7, 10, 15], 6)
|
||||
cool_x_values = np.repeat([6, 7, 8, 9, 10, 11], 6)
|
||||
x_values = heat_x_values if data_type == "heat" else cool_x_values
|
||||
x_values = x_values.tolist()
|
||||
# convert list of lists to one list
|
||||
heat_pump_data = list(itertools.chain.from_iterable(heat_pump_data))
|
||||
|
||||
# Compute heat output coefficients
|
||||
popt, _ = curve_fit(self._objective_function, [x_values, out_temp], heat_pump_data)
|
||||
return popt.tolist()
|
||||
|
||||
def _objective_function(self, xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float) -> float:
|
||||
"""
|
||||
Objective function for computing coefficients
|
||||
:param xdata:
|
||||
:param a1: float
|
||||
:param a2: float
|
||||
:param a3: float
|
||||
:param a4: float
|
||||
:param a5: float
|
||||
:param a6: float
|
||||
:return:
|
||||
"""
|
||||
x, y = xdata
|
||||
return (a1 * x ** 2) + (a2 * x) + (a3 * x * y) + (a4 * y) + (a5 * y ** 2) + a6
|
||||
|
@ -11,6 +11,7 @@ class EnergySystemsFactory:
|
||||
"""
|
||||
EnergySystemsFactory class
|
||||
"""
|
||||
|
||||
def __init__(self, handler, city, base_path=None):
|
||||
if base_path is None:
|
||||
base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
|
||||
@ -18,7 +19,7 @@ class EnergySystemsFactory:
|
||||
self._city = city
|
||||
self._base_path = base_path
|
||||
|
||||
def _xlsxheatpump(self):
|
||||
def _xlsx_heat_pump(self):
|
||||
"""
|
||||
Enrich the city by using xlsx heat pump information
|
||||
"""
|
||||
@ -30,4 +31,3 @@ class EnergySystemsFactory:
|
||||
:return: None
|
||||
"""
|
||||
getattr(self, self._handler, lambda: None)()
|
||||
|
||||
|
@ -9,7 +9,10 @@ geomeppy~=0.11.8
|
||||
pathlib~=1.0.1
|
||||
PyWavefront~=1.3.3
|
||||
xlrd~=2.0.1
|
||||
openpyxl~=3.0.7
|
||||
networkx~=2.5.1
|
||||
parseidf~=1.0.0
|
||||
ply~=3.11
|
||||
rhino3dm~=7.7.0
|
||||
scipy==1.7.1
|
||||
PyYAML==6.0
|
61
unittests/test_energy_systems_factory.py
Normal file
61
unittests/test_energy_systems_factory.py
Normal file
@ -0,0 +1,61 @@
|
||||
"""
|
||||
Test EnergySystemsFactory and various heatpump models
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
import pandas as pd
|
||||
from unittest import TestCase
|
||||
from imports.geometry_factory import GeometryFactory
|
||||
from imports.energy_systems_factory import EnergySystemsFactory
|
||||
from city_model_structure.energy_systems.heat_pump import HeatPump
|
||||
from exports.energy_systems_factory import EnergySystemsExportFactory
|
||||
import os
|
||||
|
||||
|
||||
class TestEnergySystemsFactory(TestCase):
|
||||
"""
|
||||
TestBuilding TestCase 1
|
||||
"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
city_file = "../unittests/tests_data/C40_Final.gml"
|
||||
self._output_path = "../unittests/tests_data/user_output.csv"
|
||||
self._city = GeometryFactory('citygml', city_file).city
|
||||
EnergySystemsFactory('xlsx heat pump', self._city).enrich()
|
||||
|
||||
def test_heat_pump_import(self):
|
||||
self.assertIsNotNone(self._city.energy_systems, 'City has energy systems')
|
||||
self.assertIsInstance(self._city.energy_systems[0].heat_pump, HeatPump)
|
||||
self.assertEqual(self._city.energy_systems[0].heat_pump.model, '012')
|
||||
self.assertEqual(self._city.energy_systems[len(self._city.energy_systems) - 1].heat_pump.model, '140')
|
||||
|
||||
def test_heat_pump_export(self):
|
||||
# User defined paramenters
|
||||
user_input = {
|
||||
'StartYear': 2020,
|
||||
'EndYear': 2021,
|
||||
'MaximumHPEnergyInput': 8000,
|
||||
'HoursOfStorageAtMaxDemand': 1,
|
||||
'BuildingSuppTemp': 40,
|
||||
'TemperatureDifference': 15,
|
||||
'FuelLHV': 47100,
|
||||
'FuelPrice': 0.12,
|
||||
'FuelEF': 1887,
|
||||
'FuelDensity': 0.717,
|
||||
'HPSupTemp': 60
|
||||
}
|
||||
|
||||
EnergySystemsExportFactory(self._city, user_input, '012', self._output_path).export()
|
||||
df = pd.read_csv(self._output_path)
|
||||
self.assertEqual(df.shape, (13, 3))
|
||||
self.assertEqual(df.iloc[0, 1], 3045398.0)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
try:
|
||||
os.remove(self._output_path)
|
||||
except OSError:
|
||||
pass
|
Loading…
Reference in New Issue
Block a user