From 1c8ffcfee0a273188e2f9ff2798d4dcff9ffc498 Mon Sep 17 00:00:00 2001 From: Pilar Monsalvete Date: Fri, 27 Aug 2021 21:31:49 +0000 Subject: [PATCH] Revert "Restore repo" This reverts commit c60aca4c070f521ba48a3d4d42de29f5639b6293 --- .../building_demand/building_from_trimesh.py | 27 - city_model_structure/building_demand/help.py | 26 - .../city_model_structure/attributes/edge.py | 45 - .../city_model_structure/attributes/node.py | 46 - .../city_model_structure/attributes/plane.py | 57 - .../city_model_structure/attributes/point.py | 35 - .../attributes/polygon.py | 646 - .../attributes/polyhedron.py | 252 - .../attributes/schedule_value.py | 31 - .../city_model_structure/bixi_feature.py | 33 - .../city_model_structure/building.py | 353 - .../building_demand/building_from_trimesh.py | 27 - .../building_demand/help.py | 26 - .../building_demand/internal_gains.py | 81 - .../building_demand/layer.py | 59 - .../building_demand/material.py | 165 - .../building_demand/occupants.py | 217 - .../building_demand/storey.py | 93 - .../building_demand/surface.py | 295 - .../building_demand/thermal_boundary.py | 394 - .../building_demand/thermal_opening.py | 279 - .../building_demand/thermal_zone.py | 200 - .../building_demand/usage_zone.py | 379 - .../city_model_structure/buildings_cluster.py | 38 - .../city_model_structure/city.py | 366 - .../city_model_structure/city_object.py | 229 - .../city_objects_cluster.py | 72 - .../city_model_structure/composting_plant.py | 33 - .../energy_systems/heat_pump.py | 46 - .../energy_systems/pv_system.py | 114 - .../iot/concordia_energy_sensor.py | 42 - .../iot/concordia_gas_flow_sensor.py | 42 - .../iot/concordia_temperature_sensor.py | 42 - .../city_model_structure/iot/sensor.py | 73 - .../city_model_structure/network.py | 51 - .../parts_consisting_building.py | 36 - .../city_model_structure/subway_entrance.py | 44 - .../transport/connection.py | 119 - .../transport/crossing.py | 70 - .../city_model_structure/transport/join.py | 27 - .../city_model_structure/transport/lane.py | 136 - .../city_model_structure/transport/phase.py | 125 - .../transport/traffic_edge.py | 135 - .../transport/traffic_light.py | 70 - .../transport/traffic_network.py | 25 - .../transport/traffic_node.py | 84 - .../transport/walkway_node.py | 36 - .../city_model_structure/tree.py | 33 - exports/exports/exports_factory.py | 84 - exports/exports/formats/energy_ade.py | 378 - exports/exports/formats/idf.py | 278 - exports/exports/formats/idf_files/Energy+.idd | 103532 --------------- exports/exports/formats/idf_files/Minimal.idf | 151 - exports/exports/formats/obj.py | 32 - .../formats/simplified_radiosity_algorithm.py | 88 - exports/exports/formats/stl.py | 15 - exports/exports/formats/triangular.py | 31 - helpers/helpers/configuration_helper.py | 41 - helpers/helpers/constants.py | 57 - helpers/helpers/enrich_city.py | 99 - helpers/helpers/geometry_helper.py | 196 - helpers/helpers/location.py | 29 - helpers/helpers/monthly_to_hourly_demand.py | 137 - .../helpers/storeys_generation.py | 157 - .../construction/ca_physics_parameters.py | 79 - .../data_classes/nrel_building_achetype.py | 97 - .../data_classes/nrel_layer_archetype.py | 63 - .../nrel_thermal_boundary_archetype.py | 95 - .../nrel_thermal_opening_archetype.py | 54 - .../helpers/construction_helper.py | 152 - .../helpers/storeys_generation.py | 157 - .../construction/nrel_physics_interface.py | 184 - .../construction/us_physics_parameters.py | 107 - imports/imports/construction_factory.py | 38 - imports/imports/geometry/citygml.py | 112 - .../geometry/citygml_classes/citygml_base.py | 48 - .../geometry/citygml_classes/citygml_lod1.py | 55 - .../geometry/citygml_classes/citygml_lod2.py | 69 - .../geometry/helpers/geometry_helper.py | 322 - imports/imports/geometry/obj.py | 81 - imports/imports/geometry/osm_subway.py | 54 - imports/imports/geometry_factory.py | 39 - .../schedules/comnet_schedules_parameters.py | 42 - imports/imports/schedules/doe_idf.py | 114 - .../schedules/helpers/schedules_helper.py | 39 - imports/imports/schedules_factory.py | 37 - .../sensors/concordia_energy_consumption.py | 35 - .../imports/sensors/concordia_file_report.py | 79 - imports/imports/sensors/concordia_gas_flow.py | 36 - .../imports/sensors/concordia_temperature.py | 35 - imports/imports/sensors_factory.py | 37 - imports/imports/usage/ca_usage_parameters.py | 78 - .../hft_internal_gains_archetype.py | 49 - .../data_classes/hft_usage_zone_archetype.py | 144 - imports/imports/usage/helpers/usage_helper.py | 38 - imports/imports/usage/hft_usage_interface.py | 141 - imports/imports/usage/hft_usage_parameters.py | 78 - imports/imports/usage_factory.py | 38 - .../imports/weather/dat_weather_parameters.py | 56 - .../imports/weather/epw_weather_parameters.py | 111 - imports/imports/weather/helpers/weather.py | 29 - .../imports/weather/xls_weather_parameters.py | 47 - imports/imports/weather_factory.py | 38 - 103 files changed, 114266 deletions(-) delete mode 100644 city_model_structure/building_demand/building_from_trimesh.py delete mode 100644 city_model_structure/building_demand/help.py delete mode 100644 city_model_structure/city_model_structure/attributes/edge.py delete mode 100644 city_model_structure/city_model_structure/attributes/node.py delete mode 100644 city_model_structure/city_model_structure/attributes/plane.py delete mode 100644 city_model_structure/city_model_structure/attributes/point.py delete mode 100644 city_model_structure/city_model_structure/attributes/polygon.py delete mode 100644 city_model_structure/city_model_structure/attributes/polyhedron.py delete mode 100644 city_model_structure/city_model_structure/attributes/schedule_value.py delete mode 100644 city_model_structure/city_model_structure/bixi_feature.py delete mode 100644 city_model_structure/city_model_structure/building.py delete mode 100644 city_model_structure/city_model_structure/building_demand/building_from_trimesh.py delete mode 100644 city_model_structure/city_model_structure/building_demand/help.py delete mode 100644 city_model_structure/city_model_structure/building_demand/internal_gains.py delete mode 100644 city_model_structure/city_model_structure/building_demand/layer.py delete mode 100644 city_model_structure/city_model_structure/building_demand/material.py delete mode 100644 city_model_structure/city_model_structure/building_demand/occupants.py delete mode 100644 city_model_structure/city_model_structure/building_demand/storey.py delete mode 100644 city_model_structure/city_model_structure/building_demand/surface.py delete mode 100644 city_model_structure/city_model_structure/building_demand/thermal_boundary.py delete mode 100644 city_model_structure/city_model_structure/building_demand/thermal_opening.py delete mode 100644 city_model_structure/city_model_structure/building_demand/thermal_zone.py delete mode 100644 city_model_structure/city_model_structure/building_demand/usage_zone.py delete mode 100644 city_model_structure/city_model_structure/buildings_cluster.py delete mode 100644 city_model_structure/city_model_structure/city.py delete mode 100644 city_model_structure/city_model_structure/city_object.py delete mode 100644 city_model_structure/city_model_structure/city_objects_cluster.py delete mode 100644 city_model_structure/city_model_structure/composting_plant.py delete mode 100644 city_model_structure/city_model_structure/energy_systems/heat_pump.py delete mode 100644 city_model_structure/city_model_structure/energy_systems/pv_system.py delete mode 100644 city_model_structure/city_model_structure/iot/concordia_energy_sensor.py delete mode 100644 city_model_structure/city_model_structure/iot/concordia_gas_flow_sensor.py delete mode 100644 city_model_structure/city_model_structure/iot/concordia_temperature_sensor.py delete mode 100644 city_model_structure/city_model_structure/iot/sensor.py delete mode 100644 city_model_structure/city_model_structure/network.py delete mode 100644 city_model_structure/city_model_structure/parts_consisting_building.py delete mode 100644 city_model_structure/city_model_structure/subway_entrance.py delete mode 100644 city_model_structure/city_model_structure/transport/connection.py delete mode 100644 city_model_structure/city_model_structure/transport/crossing.py delete mode 100644 city_model_structure/city_model_structure/transport/join.py delete mode 100644 city_model_structure/city_model_structure/transport/lane.py delete mode 100644 city_model_structure/city_model_structure/transport/phase.py delete mode 100644 city_model_structure/city_model_structure/transport/traffic_edge.py delete mode 100644 city_model_structure/city_model_structure/transport/traffic_light.py delete mode 100644 city_model_structure/city_model_structure/transport/traffic_network.py delete mode 100644 city_model_structure/city_model_structure/transport/traffic_node.py delete mode 100644 city_model_structure/city_model_structure/transport/walkway_node.py delete mode 100644 city_model_structure/city_model_structure/tree.py delete mode 100644 exports/exports/exports_factory.py delete mode 100644 exports/exports/formats/energy_ade.py delete mode 100644 exports/exports/formats/idf.py delete mode 100644 exports/exports/formats/idf_files/Energy+.idd delete mode 100644 exports/exports/formats/idf_files/Minimal.idf delete mode 100644 exports/exports/formats/obj.py delete mode 100644 exports/exports/formats/simplified_radiosity_algorithm.py delete mode 100644 exports/exports/formats/stl.py delete mode 100644 exports/exports/formats/triangular.py delete mode 100644 helpers/helpers/configuration_helper.py delete mode 100644 helpers/helpers/constants.py delete mode 100644 helpers/helpers/enrich_city.py delete mode 100644 helpers/helpers/geometry_helper.py delete mode 100644 helpers/helpers/location.py delete mode 100644 helpers/helpers/monthly_to_hourly_demand.py delete mode 100644 imports/construction/helpers/storeys_generation.py delete mode 100644 imports/imports/construction/ca_physics_parameters.py delete mode 100644 imports/imports/construction/data_classes/nrel_building_achetype.py delete mode 100644 imports/imports/construction/data_classes/nrel_layer_archetype.py delete mode 100644 imports/imports/construction/data_classes/nrel_thermal_boundary_archetype.py delete mode 100644 imports/imports/construction/data_classes/nrel_thermal_opening_archetype.py delete mode 100644 imports/imports/construction/helpers/construction_helper.py delete mode 100644 imports/imports/construction/helpers/storeys_generation.py delete mode 100644 imports/imports/construction/nrel_physics_interface.py delete mode 100644 imports/imports/construction/us_physics_parameters.py delete mode 100644 imports/imports/construction_factory.py delete mode 100644 imports/imports/geometry/citygml.py delete mode 100644 imports/imports/geometry/citygml_classes/citygml_base.py delete mode 100644 imports/imports/geometry/citygml_classes/citygml_lod1.py delete mode 100644 imports/imports/geometry/citygml_classes/citygml_lod2.py delete mode 100644 imports/imports/geometry/helpers/geometry_helper.py delete mode 100644 imports/imports/geometry/obj.py delete mode 100644 imports/imports/geometry/osm_subway.py delete mode 100644 imports/imports/geometry_factory.py delete mode 100644 imports/imports/schedules/comnet_schedules_parameters.py delete mode 100644 imports/imports/schedules/doe_idf.py delete mode 100644 imports/imports/schedules/helpers/schedules_helper.py delete mode 100644 imports/imports/schedules_factory.py delete mode 100644 imports/imports/sensors/concordia_energy_consumption.py delete mode 100644 imports/imports/sensors/concordia_file_report.py delete mode 100644 imports/imports/sensors/concordia_gas_flow.py delete mode 100644 imports/imports/sensors/concordia_temperature.py delete mode 100644 imports/imports/sensors_factory.py delete mode 100644 imports/imports/usage/ca_usage_parameters.py delete mode 100644 imports/imports/usage/data_classes/hft_internal_gains_archetype.py delete mode 100644 imports/imports/usage/data_classes/hft_usage_zone_archetype.py delete mode 100644 imports/imports/usage/helpers/usage_helper.py delete mode 100644 imports/imports/usage/hft_usage_interface.py delete mode 100644 imports/imports/usage/hft_usage_parameters.py delete mode 100644 imports/imports/usage_factory.py delete mode 100644 imports/imports/weather/dat_weather_parameters.py delete mode 100644 imports/imports/weather/epw_weather_parameters.py delete mode 100644 imports/imports/weather/helpers/weather.py delete mode 100644 imports/imports/weather/xls_weather_parameters.py delete mode 100644 imports/imports/weather_factory.py diff --git a/city_model_structure/building_demand/building_from_trimesh.py b/city_model_structure/building_demand/building_from_trimesh.py deleted file mode 100644 index 2c0b9e31..00000000 --- a/city_model_structure/building_demand/building_from_trimesh.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Building module a new implementation option -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from city_model_structure.building_demand.surface import Surface -from city_model_structure.city_object import CityObject -from city_model_structure.attributes.polygon import Polygon - - -class Building(CityObject): - """ - Building(CityObject) class - """ - def __init__(self, name, lod, trimesh, year_of_construction, function, city_lower_corner): - surfaces = [] - for face in trimesh.faces: - # todo: review for obj with windows - points = [] - for vertex_index in face: - points.append(trimesh.vertices[vertex_index]) - solid_polygon = Polygon(points) - perimeter_polygon = solid_polygon - surface = Surface(solid_polygon, perimeter_polygon) - surfaces.append(surface) - super().__init__(name, lod, surfaces, city_lower_corner) diff --git a/city_model_structure/building_demand/help.py b/city_model_structure/building_demand/help.py deleted file mode 100644 index 7670b030..00000000 --- a/city_model_structure/building_demand/help.py +++ /dev/null @@ -1,26 +0,0 @@ - -# from surfaces to thermal_zones - -#zone_surfaces = [] -# these should be the virtual internal surfaces (What about the internal walls??) -#for surface_id in zone_surfaces_ids: -# zone_surfaces.append(self.surface(surface_id)) -#self._thermal_zones.append(ThermalZone(zone_surfaces)) - -#for t_zones in self._thermal_zones: -# t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces] - -from city_model_structure.attributes.polygon import Polygon -from city_model_structure.attributes.plane import Plane -from city_model_structure.attributes.point import Point -import numpy as np - -coordinates = [np.array([1, 0, 0]), np.array([0, 0, 0]), np.array([0, 0, 1]), np.array([1, 0, 1])] -polygon = Polygon(coordinates) -origin = Point([0, 0, 0.5]) -normal = np.array([0, 0, 1]) -plane = Plane(normal=normal, origin=origin) -intersection, polygon_1, polygon_2 = polygon.divide(plane) -print('final polygon') -print(polygon_1.coordinates) -print(polygon_2.coordinates) diff --git a/city_model_structure/city_model_structure/attributes/edge.py b/city_model_structure/city_model_structure/attributes/edge.py deleted file mode 100644 index c1b36165..00000000 --- a/city_model_structure/city_model_structure/attributes/edge.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Node module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -""" -import uuid -from typing import List -from city_model_structure.attributes.node import Node - - -class Edge: - """ - Generic edge class to be used as base for the network edges - """ - def __init__(self, name, nodes=None): - if nodes is None: - nodes = [] - self._name = name - self._id = None - self._nodes = nodes - - @property - def name(self): - """ - Edge name - """ - return self._name - - @property - def id(self): - """ - Edge id, an universally unique identifier randomly generated - :return: str - """ - if self._id is None: - self._id = uuid.uuid4() - return self._id - - @property - def nodes(self) -> List[Node]: - """ - Delimiting nodes for the edge - """ - return self._nodes diff --git a/city_model_structure/city_model_structure/attributes/node.py b/city_model_structure/city_model_structure/attributes/node.py deleted file mode 100644 index 12dba288..00000000 --- a/city_model_structure/city_model_structure/attributes/node.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Node module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -""" - -import uuid -from typing import List -from city_model_structure.attributes.edge import Edge - - -class Node: - """ - Generic node class to be used as base for the network nodes - """ - def __init__(self, name, edges=None): - if edges is None: - edges = [] - self._name = name - self._id = None - self._edges = edges - - @property - def name(self): - """ - Node name - """ - return self._name - - @property - def id(self): - """ - Node id, an universally unique identifier randomly generated - :return: str - """ - if self._id is None: - self._id = uuid.uuid4() - return self._id - - @property - def edges(self) -> List[Edge]: - """ - Edges delimited by the node - """ - return self._edges diff --git a/city_model_structure/city_model_structure/attributes/plane.py b/city_model_structure/city_model_structure/attributes/plane.py deleted file mode 100644 index f653d6c7..00000000 --- a/city_model_structure/city_model_structure/attributes/plane.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Plane module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from typing import TypeVar -import numpy as np - -Point = TypeVar('Point') - - -class Plane: - """ - Plane class - """ - - def __init__(self, origin=None, normal=None): - # todo: other options to define the plane: - # by two lines - # by three points - self._origin = origin - self._normal = normal - self._opposite_normal = None - - @property - def origin(self) -> Point: - """ - Point origin of the plane - return Point - """ - if self._origin is None: - raise NotImplementedError - return self._origin - - @property - def normal(self): - """ - Plane normal [x, y, z] - return np.ndarray - """ - if self._normal is None: - raise NotImplementedError - return self._normal - - @property - def opposite_normal(self): - """ - Plane normal in the opposite direction [x, y, z] - return np.ndarray - """ - if self._opposite_normal is None: - coordinates = [] - for coordinate in self.normal: - coordinates.append(-coordinate) - self._opposite_normal = np.array(coordinates) - return self._opposite_normal diff --git a/city_model_structure/city_model_structure/attributes/point.py b/city_model_structure/city_model_structure/attributes/point.py deleted file mode 100644 index 71c3d987..00000000 --- a/city_model_structure/city_model_structure/attributes/point.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Point module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -import math - - -class Point: - """ - Point class - """ - - def __init__(self, coordinates): - self._coordinates = coordinates - - @property - def coordinates(self): - """ - Point coordinates - """ - return self._coordinates - - def distance_to_point(self, other_point): - """ - distance between points in an n-D Euclidean space - :param other_point: point or vertex - :return: float - """ - power = 0 - for dimension in range(0, len(self.coordinates)): - power += math.pow(other_point.coordinates[dimension]-self.coordinates[dimension], 2) - distance = math.sqrt(power) - return distance diff --git a/city_model_structure/city_model_structure/attributes/polygon.py b/city_model_structure/city_model_structure/attributes/polygon.py deleted file mode 100644 index e82359b3..00000000 --- a/city_model_structure/city_model_structure/attributes/polygon.py +++ /dev/null @@ -1,646 +0,0 @@ -""" -Polygon module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - - -from __future__ import annotations -import math -import sys -from typing import List -import numpy as np -from trimesh import Trimesh -import trimesh.intersections -from city_model_structure.attributes.point import Point - - -class Polygon: - """ - Polygon class - """ - - def __init__(self, coordinates): - - self._area = None - self._points = None - self._points_list = None - self._normal = None - self._inverse = None - self._edges = None - self._coordinates = coordinates - self._triangles = None - self._vertices = None - self._faces = None - - @property - def points(self) -> List[Point]: - """ - List of points belonging to the polygon [[x, y, z],...] - :return: List[Point] - """ - if self._points is None: - self._points = [] - for coordinate in self.coordinates: - self._points.append(Point(coordinate)) - return self._points - - @property - def coordinates(self) -> List[np.ndarray]: - """ - List of points in the shape of its coordinates belonging to the polygon [[x, y, z],...] - :return: [np.ndarray] - """ - return self._coordinates - - @property - def points_list(self) -> np.ndarray: - """ - Solid surface point coordinates list [x, y, z, x, y, z,...] - :return: np.ndarray - """ - if self._points_list is None: - s = self.coordinates - self._points_list = np.reshape(s, len(s) * 3) - return self._points_list - - @property - def edges(self): - """ - Polygon edges list - """ - if self._edges is None: - self._edges = [] - for i in range(0, len(self.points)-1): - point_1 = self.points[i] - point_2 = self.points[i+1] - self._edges.append([point_1, point_2]) - self._edges.append([self.points[len(self.points)-1], self.points[0]]) - return self._edges - - @property - def area(self): - """ - Surface area in square meters - :return: float - """ - # New method to calculate area - if self._area is None: - if len(self.points) < 3: - sys.stderr.write('Warning: the area of a line or point cannot be calculated 1. Area = 0\n') - return 0 - alpha = 0 - vec_1 = self.points[1].coordinates - self.points[0].coordinates - for i in range(2, len(self.points)): - vec_2 = self.points[i].coordinates - self.points[0].coordinates - alpha += self._angle_between_vectors(vec_1, vec_2) - if alpha == 0: - sys.stderr.write('Warning: the area of a line or point cannot be calculated 2. Area = 0\n') - return 0 - horizontal_points = self._points_rotated_to_horizontal - area = 0 - for i in range(0, len(horizontal_points)-1): - point = horizontal_points[i] - next_point = horizontal_points[i+1] - area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0]) - next_point = horizontal_points[0] - point = horizontal_points[len(horizontal_points)-1] - area += (next_point[1] + point[1]) / 2 * (next_point[0] - point[0]) - self._area = abs(area) - return self._area - - @property - def _points_rotated_to_horizontal(self): - """ - polygon points rotated to horizontal - :return: [float] - """ - z_vector = [0, 0, 1] - normal_vector = self.normal - horizontal_points = [] - x = normal_vector[0] - y = normal_vector[1] - - if x == 0 and y == 0: - # Already horizontal - for point in self.points: - horizontal_points.append([point.coordinates[0], point.coordinates[1], 0]) - else: - alpha = self._angle_between_vectors(normal_vector, z_vector) - rotation_line = np.cross(normal_vector, z_vector) - third_axis = np.cross(normal_vector, rotation_line) - w_1 = rotation_line / np.linalg.norm(rotation_line) - w_2 = normal_vector - w_3 = third_axis / np.linalg.norm(third_axis) - rotation_matrix = np.array([[1, 0, 0], - [0, np.cos(alpha), -np.sin(alpha)], - [0, np.sin(alpha), np.cos(alpha)]]) - base_matrix = np.array([w_1, w_2, w_3]) - rotation_base_matrix = np.matmul(base_matrix.transpose(), rotation_matrix.transpose()) - rotation_base_matrix = np.matmul(rotation_base_matrix, base_matrix) - - if rotation_base_matrix is None: - sys.stderr.write('Warning: rotation base matrix returned None\n') - else: - for point in self.points: - new_point = np.matmul(rotation_base_matrix, point.coordinates) - horizontal_points.append(new_point) - return horizontal_points - - @property - def normal(self) -> np.ndarray: - """ - Surface normal vector - :return: np.ndarray - """ - if self._normal is None: - points = self.coordinates - # todo: IF THE FIRST ONE IS 0, START WITH THE NEXT - point_origin = points[len(points)-2] - vector_1 = points[len(points)-1] - point_origin - vector_2 = points[0] - point_origin - vector_3 = points[1] - point_origin - cross_product = np.cross(vector_1, vector_2) - if np.linalg.norm(cross_product) != 0: - cross_product = cross_product / np.linalg.norm(cross_product) - alpha = self._angle_between_vectors(vector_1, vector_2) - else: - cross_product = [0, 0, 0] - alpha = 0 - if len(points) == 3: - return cross_product - if np.linalg.norm(cross_product) == 0: - return cross_product - alpha += self._angle(vector_2, vector_3, cross_product) - for i in range(0, len(points)-4): - vector_1 = points[i+1] - point_origin - vector_2 = points[i+2] - point_origin - alpha += self._angle(vector_1, vector_2, cross_product) - vector_1 = points[len(points) - 1] - point_origin - vector_2 = points[0] - point_origin - if alpha < 0: - cross_product = np.cross(vector_2, vector_1) - else: - cross_product = np.cross(vector_1, vector_2) - self._normal = cross_product / np.linalg.norm(cross_product) - return self._normal - - @staticmethod - def _angle(vector_1, vector_2, cross_product): - """ - alpha angle in radians - :param vector_1: [float] - :param vector_2: [float] - :param cross_product: [float] - :return: float - """ - accepted_normal_difference = 0.01 - cross_product_next = np.cross(vector_1, vector_2) - if np.linalg.norm(cross_product_next) != 0: - cross_product_next = cross_product_next / np.linalg.norm(cross_product_next) - alpha = Polygon._angle_between_vectors(vector_1, vector_2) - else: - cross_product_next = [0, 0, 0] - alpha = 0 - delta_normals = 0 - for j in range(0, 3): - delta_normals += cross_product[j] - cross_product_next[j] - if np.abs(delta_normals) < accepted_normal_difference: - return alpha - return -alpha - - def triangulate(self) -> List[Polygon]: - """ - triangulates a polygon following the ear clipping methodology - :return: list[triangles] - """ - # todo: review triangulate_polygon in - # https://github.com/mikedh/trimesh/blob/dad11126742e140ef46ba12f8cb8643c83356467/trimesh/creation.py#L415, - # it had a problem with a class called 'triangle', but, if solved, - # it could be a very good substitute of this method - # this method is very dirty and has an infinite loop solved with a counter!! - if self._triangles is None: - points_list = self.points_list - normal = self.normal - if np.linalg.norm(normal) == 0: - sys.stderr.write('Not able to triangulate polygon\n') - return [self] - # are points concave or convex? - total_points_list, concave_points, convex_points = self._starting_lists(points_list, normal) - - # list of ears - ears = [] - j = 0 - while (len(concave_points) > 3 or len(convex_points) != 0) and j < 100: - j += 1 - for i in range(0, len(concave_points)): - ear = self._triangle(points_list, total_points_list, concave_points[i]) - rest_points = [] - for points in total_points_list: - rest_points.append(list(self.coordinates[points])) - if self._is_ear(ear, rest_points): - ears.append(ear) - point_to_remove = concave_points[i] - previous_point_in_list, next_point_in_list = self._enveloping_points(point_to_remove, total_points_list) - total_points_list.remove(point_to_remove) - concave_points.remove(point_to_remove) - # Was any of the adjacent points convex? -> check if changed status to concave - for convex_point in convex_points: - if convex_point == previous_point_in_list: - concave_points, convex_points, end_loop = self._if_concave_change_status(normal, points_list, - convex_point, - total_points_list, - concave_points, convex_points, - previous_point_in_list) - if end_loop: - break - continue - if convex_point == next_point_in_list: - concave_points, convex_points, end_loop = self._if_concave_change_status(normal, points_list, - convex_point, - total_points_list, - concave_points, convex_points, - next_point_in_list) - if end_loop: - break - continue - break - if len(total_points_list) <= 3 and len(convex_points) > 0: - sys.stderr.write('Not able to triangulate polygon\n') - return [self] - if j >= 100: - sys.stderr.write('Not able to triangulate polygon\n') - return [self] - last_ear = self._triangle(points_list, total_points_list, concave_points[1]) - ears.append(last_ear) - self._triangles = ears - return self._triangles - - @staticmethod - def _starting_lists(points_list, normal) -> [List[float], List[float], List[float]]: - """ - creates the list of vertices (points) that define the polygon (total_points_list), together with other two lists - separating points between convex and concave - :param points_list: points_list - :param normal: normal - :return: list[point], list[point], list[point] - """ - concave_points = [] - convex_points = [] - # lists of concave and convex points - # case 1: first point - point = points_list[0:3] - previous_point = points_list[len(points_list) - 3:] - next_point = points_list[3:6] - index = 0 - total_points_list = [index] - if Polygon._point_is_concave(normal, point, previous_point, next_point): - concave_points.append(index) - else: - convex_points.append(index) - # case 2: all points except first and last - for i in range(0, int((len(points_list)-6)/3)): - point = points_list[(i+1)*3:(i+2)*3] - previous_point = points_list[i*3:(i+1)*3] - next_point = points_list[(i+2)*3:(i+3)*3] - index = i+1 - total_points_list.append(index) - if Polygon._point_is_concave(normal, point, previous_point, next_point): - concave_points.append(index) - else: - convex_points.append(index) - # case 3: last point - point = points_list[len(points_list) - 3:] - previous_point = points_list[len(points_list) - 6:len(points_list) - 3] - next_point = points_list[0:3] - index = int(len(points_list)/3) - 1 - total_points_list.append(index) - if Polygon._point_is_concave(normal, point, previous_point, next_point): - concave_points.append(index) - else: - convex_points.append(index) - return total_points_list, concave_points, convex_points - - @staticmethod - def _triangle(points_list, total_points_list, point_position) -> Polygon: - """ - creates a triangular polygon out of three points - :param points_list: points_list - :param total_points_list: [point] - :param point_position: int - :return: polygon - """ - index = point_position * 3 - previous_point_index, next_point_index = Polygon._enveloping_points_indices(point_position, total_points_list) - points = points_list[previous_point_index:previous_point_index + 3] - points = np.append(points, points_list[index:index + 3]) - points = np.append(points, points_list[next_point_index:next_point_index + 3]) - rows = points.size // 3 - points = points.reshape(rows, 3) - triangle = Polygon(points) - return triangle - - @staticmethod - def _enveloping_points_indices(point_position, total_points_list): - """ - due to the fact that the lists are not circular, a method to find the previous and next points - of an specific one is needed - :param point_position: int - :param total_points_list: [point] - :return: int, int - """ - previous_point_index = None - next_point_index = None - if point_position == total_points_list[0]: - previous_point_index = total_points_list[len(total_points_list) - 1] * 3 - next_point_index = total_points_list[1] * 3 - if point_position == total_points_list[len(total_points_list) - 1]: - previous_point_index = total_points_list[len(total_points_list) - 2] * 3 - next_point_index = total_points_list[0] * 3 - for i in range(1, len(total_points_list)-1): - if point_position == total_points_list[i]: - previous_point_index = total_points_list[i - 1] * 3 - next_point_index = total_points_list[i + 1] * 3 - return previous_point_index, next_point_index - - @staticmethod - def _enveloping_points(point_to_remove, total_points_list): - """ - due to the fact that the lists are not circular, a method to find the previous and next points - of an specific one is needed - :param point_to_remove: point - :param total_points_list: [point] - :return: point, point - """ - index = total_points_list.index(point_to_remove) - if index == 0: - previous_point_in_list = total_points_list[len(total_points_list) - 1] - next_point_in_list = total_points_list[1] - elif index == len(total_points_list) - 1: - previous_point_in_list = total_points_list[len(total_points_list) - 2] - next_point_in_list = total_points_list[0] - else: - previous_point_in_list = total_points_list[index - 1] - next_point_in_list = total_points_list[index + 1] - return previous_point_in_list, next_point_in_list - - @staticmethod - def _is_ear(ear, points) -> bool: - """ - finds whether a triangle is an ear of the polygon - :param ear: polygon - :param points: [point] - :return: boolean - """ - area_ear = ear.area - for point in points: - area_points = 0 - point_is_not_vertex = True - for i in range(0, 3): - if abs(np.linalg.norm(point) - np.linalg.norm(ear.coordinates[i])) < 0.0001: - point_is_not_vertex = False - break - if point_is_not_vertex: - for i in range(0, 3): - if i != 2: - new_points = ear.coordinates[i][:] - new_points = np.append(new_points, ear.coordinates[i + 1][:]) - new_points = np.append(new_points, point[:]) - else: - new_points = ear.coordinates[i][:] - new_points = np.append(new_points, point[:]) - new_points = np.append(new_points, ear.coordinates[0][:]) - rows = new_points.size // 3 - new_points = new_points.reshape(rows, 3) - new_triangle = Polygon(new_points) - area_points += new_triangle.area - if abs(area_points - area_ear) < 1e-6: - # point_inside_ear = True - return False - return True - - @staticmethod - def _if_concave_change_status(normal, points_list, convex_point, total_points_list, - concave_points, convex_points, point_in_list) -> [List[float], List[float], bool]: - """ - checks whether an convex specific point change its status to concave after removing one ear in the polygon - returning the new convex and concave points lists together with a flag advising that the list of total points - already 3 and, therefore, the triangulation must be finished. - :param normal: normal - :param points_list: points_list - :param convex_point: int - :param total_points_list: [point] - :param concave_points: [point] - :param convex_points: [point] - :param point_in_list: int - :return: list[points], list[points], boolean - """ - end_loop = False - point = points_list[point_in_list * 3:(point_in_list + 1) * 3] - pointer = total_points_list.index(point_in_list) - 1 - if pointer < 0: - pointer = len(total_points_list) - 1 - previous_point = points_list[total_points_list[pointer] * 3:total_points_list[pointer] * 3 + 3] - pointer = total_points_list.index(point_in_list) + 1 - if pointer >= len(total_points_list): - pointer = 0 - next_point = points_list[total_points_list[pointer] * 3:total_points_list[pointer] * 3 + 3] - if Polygon._point_is_concave(normal, point, previous_point, next_point): - if concave_points[0] > convex_point: - concave_points.insert(0, convex_point) - elif concave_points[len(concave_points) - 1] < convex_point: - concave_points.append(convex_point) - else: - for point_index in range(0, len(concave_points) - 1): - if concave_points[point_index] < convex_point < concave_points[point_index + 1]: - concave_points.insert(point_index + 1, convex_point) - convex_points.remove(convex_point) - end_loop = True - return concave_points, convex_points, end_loop - - @staticmethod - def _point_is_concave(normal, point, previous_point, next_point) -> bool: - """ - returns whether a point is concave - :param normal: normal - :param point: point - :param previous_point: point - :param next_point: point - :return: boolean - """ - is_concave = False - accepted_error = 0.1 - points = np.append(previous_point, point) - points = np.append(points, next_point) - rows = points.size // 3 - points = points.reshape(rows, 3) - triangle = Polygon(points) - error_sum = 0 - for i in range(0, len(normal)): - error_sum += triangle.normal[i] - normal[i] - if np.abs(error_sum) < accepted_error: - is_concave = True - return is_concave - - @staticmethod - def _angle_between_vectors(vec_1, vec_2): - """ - angle between vectors in radians - :param vec_1: vector - :param vec_2: vector - :return: float - """ - if np.linalg.norm(vec_1) == 0 or np.linalg.norm(vec_2) == 0: - sys.stderr.write("Warning: impossible to calculate angle between planes' normal. Return 0\n") - return 0 - cosine = np.dot(vec_1, vec_2) / np.linalg.norm(vec_1) / np.linalg.norm(vec_2) - if cosine > 1 and cosine-1 < 1e-5: - cosine = 1 - elif cosine < -1 and cosine+1 > -1e-5: - cosine = -1 - alpha = math.acos(cosine) - return alpha - - @property - def inverse(self): - """ - Flips the order of the coordinates - :return: [np.ndarray] - """ - if self._inverse is None: - self._inverse = self.coordinates[::-1] - return self._inverse - - def divide(self, plane): - """ - Divides the polygon in two by a plane - :param plane: plane that intersects with self to divide it in two parts (Plane) - :return: Polygon, Polygon, [Point] - """ - tri_polygons = Trimesh(vertices=self.vertices, faces=self.faces) - intersection = trimesh.intersections.mesh_plane(tri_polygons, plane.normal, plane.origin.coordinates) - polys_1 = trimesh.intersections.slice_mesh_plane(tri_polygons, plane.opposite_normal, plane.origin.coordinates) - polys_2 = trimesh.intersections.slice_mesh_plane(tri_polygons, plane.normal, plane.origin.coordinates) - triangles_1 = [] - for triangle in polys_1.triangles: - triangles_1.append(Polygon(triangle)) - polygon_1 = self._reshape(triangles_1) - triangles_2 = [] - for triangle in polys_2.triangles: - triangles_2.append(Polygon(triangle)) - polygon_2 = self._reshape(triangles_2) - return polygon_1, polygon_2, intersection - - def _reshape(self, triangles) -> Polygon: - edges_list = [] - for i in range(0, len(triangles)): - for edge in triangles[i].edges: - if not self._edge_in_edges_list(edge, edges_list): - edges_list.append(edge) - else: - edges_list = self._remove_from_list(edge, edges_list) - points = self._order_points(edges_list) - return Polygon(points) - - @staticmethod - def _edge_in_edges_list(edge, edges_list): - for edge_element in edges_list: - if (edge_element[0].distance_to_point(edge[0]) == 0 and edge_element[1].distance_to_point(edge[1]) == 0) or\ - (edge_element[1].distance_to_point(edge[0]) == 0 and edge_element[0].distance_to_point(edge[1]) == 0): - return True - return False - - @staticmethod - def _order_points(edges_list): - # todo: not sure that this method works for any case -> RECHECK - points = edges_list[0] - for _ in range(0, len(points)): - for i in range(1, len(edges_list)): - point_1 = edges_list[i][0] - point_2 = points[len(points)-1] - if point_1.distance_to_point(point_2) == 0: - points.append(edges_list[i][1]) - points.remove(points[len(points)-1]) - array_points = [] - for point in points: - array_points.append(point.coordinates) - return np.array(array_points) - - @staticmethod - def _remove_from_list(edge, edges_list): - new_list = [] - for edge_element in edges_list: - if not((edge_element[0].distance_to_point(edge[0]) == 0 and edge_element[1].distance_to_point(edge[1]) == 0) or - (edge_element[1].distance_to_point(edge[0]) == 0 and edge_element[0].distance_to_point(edge[1]) == 0)): - new_list.append(edge_element) - return new_list - - @property - def vertices(self) -> np.ndarray: - """ - Polyhedron vertices - :return: np.ndarray(int) - """ - if self._vertices is None: - vertices, self._vertices = [], [] - _ = [vertices.extend(s.coordinates) for s in self.triangulate()] - 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]]: - """ - Polyhedron triangular faces - :return: [face] - """ - if self._faces is None: - self._faces = [] - - for polygon in self.triangulate(): - 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 - - 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 diff --git a/city_model_structure/city_model_structure/attributes/polyhedron.py b/city_model_structure/city_model_structure/attributes/polyhedron.py deleted file mode 100644 index f0f225c0..00000000 --- a/city_model_structure/city_model_structure/attributes/polyhedron.py +++ /dev/null @@ -1,252 +0,0 @@ -""" -Polyhedron module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from typing import List, Union -import sys -import math -import numpy as np -from trimesh import Trimesh -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 _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 - - @property - def vertices(self) -> np.ndarray: - """ - 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 - - @property - def faces(self) -> List[List[int]]: - """ - Polyhedron triangular faces - :return: [face] - """ - if self._faces is None: - self._faces = [] - - 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 - - @property - def trimesh(self) -> Union[Trimesh, None]: - """ - Get 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 - - @property - def volume(self): - """ - 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 - - @property - def max_z(self): - """ - 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 - - @property - def max_y(self): - """ - 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 - - @property - def max_x(self): - """ - 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 - - @property - def min_z(self): - """ - 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 - - @property - def min_y(self): - """ - 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 - - @property - def min_x(self): - """ - 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 - - @property - def centroid(self): - """ - 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 - - 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') - - 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') - - def show(self): - """ - Auxiliary function to render the polyhedron - """ - self.trimesh.show() diff --git a/city_model_structure/city_model_structure/attributes/schedule_value.py b/city_model_structure/city_model_structure/attributes/schedule_value.py deleted file mode 100644 index 87d422b2..00000000 --- a/city_model_structure/city_model_structure/attributes/schedule_value.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Building module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca -""" - - -class ScheduleValue: - """ - Schedule Values class - """ - - def __init__(self, hour, probability): - self._hour = hour - self._probability = probability - - @property - def hour(self): - """ - Get hours - :return: hour of a day - """ - return self._hour - - @property - def probability(self): - """ - Get probabilities of occupants' presence - :return: occupants' presence probabilities - """ - return self._probability diff --git a/city_model_structure/city_model_structure/bixi_feature.py b/city_model_structure/city_model_structure/bixi_feature.py deleted file mode 100644 index ae175a0c..00000000 --- a/city_model_structure/city_model_structure/bixi_feature.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -bixi_feature module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from city_model_structure.city_object import CityObject - - -class BixiFeature(CityObject): - """ - BixiFeature(CityObject) class - """ - def __init__(self, lod, surfaces, name, feature_type, coordinates): - super().__init__(lod, surfaces, name, []) - self._feature_type = feature_type - self._coordinates = coordinates - self._type = 'bixi_feature' - - @property - def feature_type(self): - """ - Get type of bixi feature - :return: feature_type - """ - return self._feature_type - - @property - def gps_coordinates(self): - """ - Get bixi feature coordinates - :return: [x, y, z] - """ - return self._coordinates diff --git a/city_model_structure/city_model_structure/building.py b/city_model_structure/city_model_structure/building.py deleted file mode 100644 index c04acb42..00000000 --- a/city_model_structure/city_model_structure/building.py +++ /dev/null @@ -1,353 +0,0 @@ -""" -Building module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from typing import List -import numpy as np -from city_model_structure.building_demand.surface import Surface -from city_model_structure.building_demand.thermal_zone import ThermalZone -from city_model_structure.building_demand.thermal_boundary import ThermalBoundary -from city_model_structure.building_demand.usage_zone import UsageZone -from city_model_structure.building_demand.storey import Storey -from city_model_structure.city_object import CityObject - - -class Building(CityObject): - """ - Building(CityObject) class - """ - def __init__(self, name, lod, surfaces, year_of_construction, function, - city_lower_corner, terrains=None): - super().__init__(name, lod, surfaces, city_lower_corner) - self._basement_heated = None - self._attic_heated = None - self._terrains = terrains - self._year_of_construction = year_of_construction - self._function = function - self._average_storey_height = None - self._storeys_above_ground = None - self._floor_area = None - self._roof_type = None - self._storeys = None - self._thermal_zones = [] - self._thermal_boundaries = None - self._usage_zones = [] - self._type = 'building' - self._heating = dict() - self._cooling = dict() - self._eave_height = None - self._grounds = [] - self._roofs = [] - self._walls = [] - self._internal_walls = [] - for surface_id, surface in enumerate(self.surfaces): - self._min_x = min(self._min_x, surface.lower_corner[0]) - self._min_y = min(self._min_y, surface.lower_corner[1]) - self._min_z = min(self._min_z, surface.lower_corner[2]) - surface.id = surface_id - # todo: consider all type of surfaces, not only these four - if surface.type == 'Ground': - self._grounds.append(surface) - elif surface.type == 'Wall': - self._walls.append(surface) - elif surface.type == 'Roof': - self._roofs.append(surface) - else: - self._internal_walls.append(surface) - - self._pv_plus_hp_installation = None - - @property - def grounds(self) -> [Surface]: - """ - Building ground surfaces - """ - return self._grounds - - @property - def is_heated(self): - """ - Get building heated flag - :return: Boolean - """ - for usage_zone in self.usage_zones: - if usage_zone.is_heated: - return usage_zone.is_heated - return False - - @property - def is_cooled(self): - """ - Get building cooled flag - :return: Boolean - """ - for usage_zone in self.usage_zones: - if usage_zone.is_cooled: - return usage_zone.is_cooled - return False - - @property - def roofs(self) -> [Surface]: - """ - Building roof surfaces - """ - return self._roofs - - @property - def walls(self) -> [Surface]: - """ - Building wall surfaces - """ - return self._walls - - @property - def usage_zones(self) -> List[UsageZone]: - """ - Get city object usage zones - :return: [UsageZone] - """ - if len(self._usage_zones) == 0: - for thermal_zone in self.thermal_zones: - self._usage_zones.extend(thermal_zone.usage_zones) - return self._usage_zones - - @property - def terrains(self) -> List[Surface]: - """ - Get city object terrain surfaces - :return: [Surface] - """ - return self._terrains - - @property - def attic_heated(self): - """ - Get if the city object attic is heated - :return: Boolean - """ - return self._attic_heated - - @attic_heated.setter - def attic_heated(self, value): - """ - Set if the city object attic is heated - :param value: Boolean - :return: None - """ - self._attic_heated = value - - @property - def basement_heated(self): - """ - Get if the city object basement is heated - :return: Boolean - """ - return self._basement_heated - - @basement_heated.setter - def basement_heated(self, value): - """ - Set if the city object basement is heated - :param value: Boolean - :return: None - """ - self._basement_heated = value - - @property - def name(self): - """ - City object name - :return: str - """ - return self._name - - @property - def thermal_zones(self) -> List[ThermalZone]: - """ - City object thermal zones - :return: [ThermalZone] - """ - if len(self._thermal_zones) == 0: - for storey in self.storeys: - self._thermal_zones.append(storey.thermal_zone) - return self._thermal_zones - - @property - def heated_volume(self): - """ - City object heated volume in cubic meters - :return: float - """ - # ToDo: this need to be calculated based on the basement and attic heated values - raise NotImplementedError - - @property - def year_of_construction(self): - """ - City object year of construction - :return: int - """ - return self._year_of_construction - - @property - def function(self): - """ - City object function - :return: str - """ - return self._function - - @function.setter - def function(self, value): - """ - Set building function - :param value: string - :return: None - """ - self._function = value - - @property - def average_storey_height(self): - """ - Get city object average storey height in meters - :return: float - """ - return self._average_storey_height - - @average_storey_height.setter - def average_storey_height(self, value): - """ - Set city object average storey height in meters - :param value: float - :return: None - """ - self._average_storey_height = value - - @property - def storeys_above_ground(self): - """ - Get city object storeys number above ground - :return: int - """ - return self._storeys_above_ground - - @storeys_above_ground.setter - def storeys_above_ground(self, value): - """ - Set city object storeys number above ground - :param value: int - :return: - """ - self._storeys_above_ground = value - - @staticmethod - def _tuple_to_point(xy_tuple): - return [xy_tuple[0], xy_tuple[1], 0.0] - - @property - def heating(self) -> dict: - """ - heating demand in Wh - :return: dict{DataFrame(float)} - """ - return self._heating - - @heating.setter - def heating(self, value): - """ - heating demand in Wh - :param value: dict{DataFrame(float)} - """ - self._heating = value - - @property - def cooling(self) -> dict: - """ - cooling demand in Wh - :return: dict{DataFrame(float)} - """ - return self._cooling - - @cooling.setter - def cooling(self, value): - """ - cooling demand in Wh - :param value: dict{DataFrame(float)} - """ - self._cooling = value - - @property - def eave_height(self): - """ - building eave height in meters - :return: float - """ - if self._eave_height is None: - self._eave_height = 0 - for wall in self.walls: - self._eave_height = max(self._eave_height, wall.upper_corner[2]) - return self._eave_height - - @property - def storeys(self) -> [Storey]: - """ - Storeys inside the building - :return: [Storey] - """ - return self._storeys - - @storeys.setter - def storeys(self, value): - """ - Storeys inside the building - :param value: [Storey] - """ - self._storeys = value - - @property - def roof_type(self): - """ - Roof type for the building flat or pitch - """ - if self._roof_type is None: - self._roof_type = 'flat' - for roof in self.roofs: - grads = np.rad2deg(roof.inclination) - if 355 > grads > 5: - self._roof_type = 'pitch' - break - return self._roof_type - - @property - def floor_area(self): - """ - Floor area of the building m2 - :return: float - """ - if self._floor_area is None: - self._floor_area = 0 - for surface in self.surfaces: - if surface.type == 'Ground': - self._floor_area += surface.perimeter_polygon.area - return self._floor_area - - @property - def thermal_boundaries(self) -> List[ThermalBoundary]: - """ - List of all thermal boundaries associated to the building's thermal zones - :return: [ThermalBoundary] - """ - if self._thermal_boundaries is None: - self._thermal_boundaries = [] - for thermal_zone in self.thermal_zones: - _thermal_boundary_duplicated = False - for thermal_boundary in thermal_zone.thermal_boundaries: - if len(thermal_boundary.thermal_zones) > 1: - if thermal_zone != thermal_boundary.thermal_zones[1]: - self._thermal_boundaries.append(thermal_boundary) - else: - self._thermal_boundaries.append(thermal_boundary) - return self._thermal_boundaries diff --git a/city_model_structure/city_model_structure/building_demand/building_from_trimesh.py b/city_model_structure/city_model_structure/building_demand/building_from_trimesh.py deleted file mode 100644 index 2c0b9e31..00000000 --- a/city_model_structure/city_model_structure/building_demand/building_from_trimesh.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Building module a new implementation option -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from city_model_structure.building_demand.surface import Surface -from city_model_structure.city_object import CityObject -from city_model_structure.attributes.polygon import Polygon - - -class Building(CityObject): - """ - Building(CityObject) class - """ - def __init__(self, name, lod, trimesh, year_of_construction, function, city_lower_corner): - surfaces = [] - for face in trimesh.faces: - # todo: review for obj with windows - points = [] - for vertex_index in face: - points.append(trimesh.vertices[vertex_index]) - solid_polygon = Polygon(points) - perimeter_polygon = solid_polygon - surface = Surface(solid_polygon, perimeter_polygon) - surfaces.append(surface) - super().__init__(name, lod, surfaces, city_lower_corner) diff --git a/city_model_structure/city_model_structure/building_demand/help.py b/city_model_structure/city_model_structure/building_demand/help.py deleted file mode 100644 index 7670b030..00000000 --- a/city_model_structure/city_model_structure/building_demand/help.py +++ /dev/null @@ -1,26 +0,0 @@ - -# from surfaces to thermal_zones - -#zone_surfaces = [] -# these should be the virtual internal surfaces (What about the internal walls??) -#for surface_id in zone_surfaces_ids: -# zone_surfaces.append(self.surface(surface_id)) -#self._thermal_zones.append(ThermalZone(zone_surfaces)) - -#for t_zones in self._thermal_zones: -# t_zones.bounded = [ThermalBoundary(s, [t_zones]) for s in t_zones.surfaces] - -from city_model_structure.attributes.polygon import Polygon -from city_model_structure.attributes.plane import Plane -from city_model_structure.attributes.point import Point -import numpy as np - -coordinates = [np.array([1, 0, 0]), np.array([0, 0, 0]), np.array([0, 0, 1]), np.array([1, 0, 1])] -polygon = Polygon(coordinates) -origin = Point([0, 0, 0.5]) -normal = np.array([0, 0, 1]) -plane = Plane(normal=normal, origin=origin) -intersection, polygon_1, polygon_2 = polygon.divide(plane) -print('final polygon') -print(polygon_1.coordinates) -print(polygon_2.coordinates) diff --git a/city_model_structure/city_model_structure/building_demand/internal_gains.py b/city_model_structure/city_model_structure/building_demand/internal_gains.py deleted file mode 100644 index 7debf06b..00000000 --- a/city_model_structure/city_model_structure/building_demand/internal_gains.py +++ /dev/null @@ -1,81 +0,0 @@ -""" -InternalGains module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - - -class InternalGains: - """ - InternalGains class - """ - - def __init__(self): - self._average_internal_gain = None - self._convective_fraction = None - self._radiative_fraction = None - self._latent_fraction = None - - @property - def average_internal_gain(self): - """ - Get internal gains average internal gain in W/m2 - :return: float - """ - return self._average_internal_gain - - @average_internal_gain.setter - def average_internal_gain(self, value): - """ - Set internal gains average internal gain in W/m2 - :param value: float - """ - self._average_internal_gain = value - - @property - def convective_fraction(self): - """ - Get internal gains convective fraction - :return: float - """ - return self._convective_fraction - - @convective_fraction.setter - def convective_fraction(self, value): - """ - Set internal gains convective fraction - :param value: float - """ - self._convective_fraction = value - - @property - def radiative_fraction(self): - """ - Get internal gains radiative fraction - :return: float - """ - return self._radiative_fraction - - @radiative_fraction.setter - def radiative_fraction(self, value): - """ - Set internal gains convective fraction - :param value: float - """ - self._radiative_fraction = value - - @property - def latent_fraction(self): - """ - Get internal gains latent fraction - :return: float - """ - return self._latent_fraction - - @latent_fraction.setter - def latent_fraction(self, value): - """ - Set internal gains latent fraction - :param value: float - """ - self._latent_fraction = value diff --git a/city_model_structure/city_model_structure/building_demand/layer.py b/city_model_structure/city_model_structure/building_demand/layer.py deleted file mode 100644 index 69860270..00000000 --- a/city_model_structure/city_model_structure/building_demand/layer.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Layers module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" -import uuid -from city_model_structure.building_demand.material import Material - - -class Layer: - """ - Layer class - """ - def __init__(self): - self._material = None - self._thickness = None - self._id = None - - @property - def id(self): - """ - Get layer id, an universally unique identifier randomly generated - :return: str - """ - if self._id is None: - self._id = uuid.uuid4() - return self._id - - @property - def material(self) -> Material: - """ - Get layer material - :return: Material - """ - return self._material - - @material.setter - def material(self, value): - """ - Set layer material - :param value: Material - """ - self._material = value - - @property - def thickness(self): - """ - Get layer thickness in meters - :return: float - """ - return self._thickness - - @thickness.setter - def thickness(self, value): - """ - Get layer thickness in meters - :param value: float - """ - self._thickness = value diff --git a/city_model_structure/city_model_structure/building_demand/material.py b/city_model_structure/city_model_structure/building_demand/material.py deleted file mode 100644 index 3aee0735..00000000 --- a/city_model_structure/city_model_structure/building_demand/material.py +++ /dev/null @@ -1,165 +0,0 @@ -""" -Material module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - - -class Material: - """ - Material class - """ - def __init__(self): - self._name = None - self._conductivity = None - self._specific_heat = None - self._density = None - self._solar_absorptance = None - self._thermal_absorptance = None - self._visible_absorptance = None - self._no_mass = False - self._thermal_resistance = None - - @property - def name(self): - """ - Get material name - :return: string - """ - return self._name - - @name.setter - def name(self, value): - """ - Set material name - :param value: string - """ - self._name = value - - @property - def conductivity(self): - """ - Get material conductivity in W/mK - :return: float - """ - return self._conductivity - - @conductivity.setter - def conductivity(self, value): - """ - Set material conductivity in W/mK - :param value: float - """ - self._conductivity = value - - @property - def specific_heat(self): - """ - Get material conductivity in J/kgK - :return: float - """ - return self._specific_heat - - @specific_heat.setter - def specific_heat(self, value): - """ - Get material conductivity in J/kgK - :param value: float - """ - self._specific_heat = value - - @property - def density(self): - """ - Get material density in kg/m3 - :return: float - """ - return self._density - - @density.setter - def density(self, value): - """ - Set material density in kg/m3 - :param value: float - """ - self._density = value - - @property - def solar_absorptance(self): - """ - Get material solar absorptance - :return: float - """ - return self._solar_absorptance - - @solar_absorptance.setter - def solar_absorptance(self, value): - """ - Set material solar absorptance - :param value: float - """ - self._solar_absorptance = value - - @property - def thermal_absorptance(self): - """ - Get material thermal absorptance - :return: float - """ - return self._thermal_absorptance - - @thermal_absorptance.setter - def thermal_absorptance(self, value): - """ - Set material thermal absorptance - :param value: float - """ - self._thermal_absorptance = value - - @property - def visible_absorptance(self): - """ - Get material visible absorptance - :return: float - """ - return self._visible_absorptance - - @visible_absorptance.setter - def visible_absorptance(self, value): - """ - Set material visible absorptance - :param value: float - """ - self._visible_absorptance = value - - @property - def no_mass(self): - """ - Get material no mass flag - :return: Boolean - """ - return self._no_mass - - @no_mass.setter - def no_mass(self, value): - """ - Set material no mass flag - :param value: Boolean - """ - self._no_mass = value - - @property - def thermal_resistance(self): - """ - Get material thermal resistance in m2K/W - :return: float - """ - return self._thermal_resistance - - @thermal_resistance.setter - def thermal_resistance(self, value): - """ - Set material thermal resistance in m2K/W - :param value: float - """ - self._thermal_resistance = value diff --git a/city_model_structure/city_model_structure/building_demand/occupants.py b/city_model_structure/city_model_structure/building_demand/occupants.py deleted file mode 100644 index f11cc770..00000000 --- a/city_model_structure/city_model_structure/building_demand/occupants.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -Occupants module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Sanam Dabirian sanam.dabirian@mail.concordia.ca -Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from typing import TypeVar -import calendar as cal - -UsageZone = TypeVar('UsageZone') - - -class Occupants: - """ - Occupants class - """ - - def __init__(self): - """ - Constructor - """ - - self._heat_dissipation = None - self._occupancy_rate = None - self._occupant_type = None - self._usage_zone = None - self._occupant_schedule = None - self._number_of_occupants = None - self._arrival_time = None - self._departure_time = None - self._break_time = None - self._day_of_week = None - self._pd_of_meetings_duration = None - self._complete_year_schedule = None - - @property - def heat_dissipation(self): - """ - Get heat dissipation of occupants in W/person - :return: float - """ - return self._heat_dissipation - - @heat_dissipation.setter - def heat_dissipation(self, value): - """ - Set heat dissipation of occupants in W/person - :param value: float - """ - self._heat_dissipation = value - - @property - def occupancy_rate(self): - """ - Get rate of schedules - :return: float - """ - return self._occupancy_rate - - @occupancy_rate.setter - def occupancy_rate(self, value): - """ - Set rate of schedules - :param value: float - """ - self._occupancy_rate = value - - @property - def occupant_type(self): - """ - Get type of schedules - :return: string - """ - return self._occupant_type - - @occupant_type.setter - def occupant_type(self, value): - """ - Set type of schedules - :param value: float - """ - self._occupant_type = value - - @property - def usage_zone(self) -> UsageZone: - """ - Get the zone an occupant is in - :return: UsageZone - """ - return self._usage_zone - - @property - def occupant_schedule(self): - """ - Get the schedules when an occupant is in a zone (24 values, 1 per hour of the day) - :return: [float] - """ - return self._occupant_schedule - - @occupant_schedule.setter - def occupant_schedule(self, value): - """ - Set the schedules when an occupant is in a zone (24 values, 1 per hour of the day) - :param value: [float] - """ - self._occupant_schedule = value - - @property - def number_of_occupants(self): - """ - Get the number of occupants - :return: int - """ - return self._number_of_occupants - - @number_of_occupants.setter - def number_of_occupants(self, value): - """ - Set the number of occupants - :param value: int - """ - self._number_of_occupants = value - - @property - def arrival_time(self): - """ - Get the arrival time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss - :return: time - """ - return self._arrival_time - - @arrival_time.setter - def arrival_time(self, value): - """ - Set the arrival time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss - :param value: time - """ - self._arrival_time = value - - @property - def departure_time(self): - """ - Get the departure time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss - :return: time - """ - return self._departure_time - - @departure_time.setter - def departure_time(self, value): - """ - Set the departure time of the occupant (for office building) in UTC with format YYYYMMDD HH:mm:ss - :param value: time - """ - self._departure_time = value - - @property - def break_time(self): - """ - Get the lunch or break time of the occupant (for office building) in UTC with format ???? - :return: break time - """ - # todo @Sanam: define this format, is it the starting time? is it a list with both, starting and ending time? - return self._break_time - - @property - def day_of_week(self): - """ - Get the day of the week (MON, TUE, WED, THU, FRI, SAT, SUN) - :return: string - """ - # todo @Sanam: is this a property or should it be a function - # to get the day of the week of an specific day of the year? - return self._day_of_week - - @property - def pd_of_meetings_duration(self): - """ - Get the probability distribution of the meeting duration - :return: ?? - """ - # todo @Sanam: what format are you expecting here?? - return self._pd_of_meetings_duration - - @pd_of_meetings_duration.setter - def pd_of_meetings_duration(self, value): - """ - Get the probability distribution of the meeting duration - :param value: ?? - :return: - """ - # todo @Sanam: what format are you expecting here?? - self._pd_of_meetings_duration = value - - def get_complete_year_schedule(self, schedules): - """ - Get the a non-leap year (8760 h), starting on Monday schedules out of archetypal days of week - :return: [float] - """ - if self._complete_year_schedule is None: - self._complete_year_schedule = [] - for i in range(1, 13): - month_range = cal.monthrange(2015, i)[1] - for day in range(1, month_range+1): - if cal.weekday(2015, i, day) < 5: - for j in range(0, 24): - week_schedule = schedules['WD'][j] - self._complete_year_schedule.append(week_schedule) - elif cal.weekday(2015, i, day) == 5: - for j in range(0, 24): - week_schedule = schedules['Sat'][j] - self._complete_year_schedule.append(week_schedule) - else: - for j in range(0, 24): - week_schedule = schedules['Sun'][j] - self._complete_year_schedule.append(week_schedule) - return self._complete_year_schedule diff --git a/city_model_structure/city_model_structure/building_demand/storey.py b/city_model_structure/city_model_structure/building_demand/storey.py deleted file mode 100644 index ad3e841e..00000000 --- a/city_model_structure/city_model_structure/building_demand/storey.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -Storey module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from __future__ import annotations -from typing import List -from city_model_structure.building_demand.surface import Surface -from city_model_structure.building_demand.thermal_boundary import ThermalBoundary -from city_model_structure.building_demand.thermal_zone import ThermalZone - - -class Storey: - # todo: rethink this class for buildings with windows - """ - Storey class - """ - def __init__(self, name, storey_surfaces, neighbours, volume): - # todo: the information of the parent surface is lost -> need to recover it - self._name = name - self._storey_surfaces = storey_surfaces - self._thermal_boundaries = None - self._virtual_surfaces = None - self._thermal_zone = None - self._neighbours = neighbours - self._volume = volume - - @property - def name(self): - """ - Storey's name - :return: str - """ - return self._name - - @property - def surfaces(self) -> List[Surface]: - """ - External surfaces enclosing the storey - :return: [Surface] - """ - return self._storey_surfaces - - @property - def neighbours(self): - """ - Neighbour storeys' names - :return: [str] - """ - return self._neighbours - - @property - def thermal_boundaries(self) -> List[ThermalBoundary]: - """ - Thermal boundaries bounding the thermal zone - :return: [ThermalBoundary] - """ - if self._thermal_boundaries is None: - self._thermal_boundaries = [] - for surface in self.surfaces: - self._thermal_boundaries.append(ThermalBoundary(surface)) - return self._thermal_boundaries - - @property - def virtual_surfaces(self) -> List[Surface]: - """ - Internal surfaces enclosing the thermal zone - :return: [Surface] - """ - if self._virtual_surfaces is None: - self._virtual_surfaces = [] - for thermal_boundary in self.thermal_boundaries: - self._virtual_surfaces.append(thermal_boundary.virtual_internal_surface) - return self._virtual_surfaces - - @property - def thermal_zone(self) -> ThermalZone: - """ - Thermal zone inside the storey - :return: ThermalZone - """ - if self._thermal_zone is None: - self._thermal_zone = ThermalZone(self.thermal_boundaries, self.volume) - return self._thermal_zone - - @property - def volume(self): - """ - Storey's volume - :return: float - """ - return self._volume diff --git a/city_model_structure/city_model_structure/building_demand/surface.py b/city_model_structure/city_model_structure/building_demand/surface.py deleted file mode 100644 index 3c18f2fc..00000000 --- a/city_model_structure/city_model_structure/building_demand/surface.py +++ /dev/null @@ -1,295 +0,0 @@ -""" -Surface module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from __future__ import annotations -import uuid -import numpy as np -from city_model_structure.attributes.polygon import Polygon -from city_model_structure.attributes.plane import Plane -from city_model_structure.attributes.point import Point -from city_model_structure.energy_systems.pv_system import PvSystem -import helpers.constants as cte - - -class Surface: - """ - Surface class - """ - def __init__(self, solid_polygon, perimeter_polygon, holes_polygons=None, name=None, surface_type=None, swr=None): - self._type = surface_type - self._swr = swr - self._name = name - self._id = None - self._azimuth = None - self._inclination = None - self._area_above_ground = None - self._area_below_ground = None - self._lower_corner = None - self._upper_corner = None - self._shared_surfaces = [] - self._global_irradiance = dict() - self._perimeter_polygon = perimeter_polygon - self._holes_polygons = holes_polygons - self._solid_polygon = solid_polygon - self._pv_system_installed = None - self._inverse = None - # todo: do I need it??? - self._associated_thermal_boundaries = None - - @property - def name(self): - """ - Surface name - :return: str - """ - if self._name is None: - self._name = str(uuid.uuid4()) - return self._name - - @property - def id(self): - """ - Surface id - :return str - """ - if self._id is None: - raise ValueError('Undefined surface id') - return self._id - - @property - def share_surfaces(self): - """ - Raises not implemented error - """ - raise NotImplementedError - - @id.setter - def id(self, value): - """ - Surface id - """ - self._id = value - - @property - def swr(self): - """ - Get surface short wave reflectance - :return: float - """ - return self._swr - - @swr.setter - def swr(self, value): - """ - Set surface short wave reflectance - :param value: float - """ - self._swr = value - - def _max_coord(self, axis): - if axis == 'x': - axis = 0 - elif axis == 'y': - axis = 1 - else: - axis = 2 - max_coordinate = '' - for point in self.perimeter_polygon.coordinates: - if max_coordinate == '': - max_coordinate = point[axis] - elif max_coordinate < point[axis]: - max_coordinate = point[axis] - return max_coordinate - - def _min_coord(self, axis): - if axis == 'x': - axis = 0 - elif axis == 'y': - axis = 1 - else: - axis = 2 - min_coordinate = '' - for point in self.perimeter_polygon.coordinates: - if min_coordinate == '': - min_coordinate = point[axis] - elif min_coordinate > point[axis]: - min_coordinate = point[axis] - return min_coordinate - - @property - def lower_corner(self): - """ - Surface's lower corner [x, y, z] - :return: [float] - """ - if self._lower_corner is None: - self._lower_corner = [self._min_coord('x'), self._min_coord('y'), self._min_coord('z')] - return self._lower_corner - - @property - def upper_corner(self): - """ - Surface's upper corner [x, y, z] - :return: [float] - """ - if self._upper_corner is None: - self._upper_corner = [self._max_coord('x'), self._max_coord('y'), self._max_coord('z')] - return self._upper_corner - - @property - def area_above_ground(self): - """ - Surface area above ground in square meters - :return: float - """ - if self._area_above_ground is None: - self._area_above_ground = self.perimeter_polygon.area - self.area_below_ground - return self._area_above_ground - - # todo: to be implemented when adding terrains - @property - def area_below_ground(self): - """ - Surface area below ground in square meters - :return: float - """ - return 0.0 - - @property - def azimuth(self): - """ - Surface azimuth in radians - :return: float - """ - if self._azimuth is None: - normal = self.perimeter_polygon.normal - self._azimuth = np.arctan2(normal[1], normal[0]) - return self._azimuth - - @property - def inclination(self): - """ - Surface inclination in radians - :return: float - """ - if self._inclination is None: - self._inclination = np.arccos(self.perimeter_polygon.normal[2]) - return self._inclination - - @property - def type(self): - """ - Surface type Ground, Wall or Roof - :return: str - """ - if self._type is None: - grad = np.rad2deg(self.inclination) - if grad >= 170: - self._type = 'Ground' - elif 80 <= grad <= 100: - self._type = 'Wall' - else: - self._type = 'Roof' - return self._type - - @property - def global_irradiance(self) -> dict: - """ - global irradiance on surface in Wh/m2 - :return: dict{DataFrame(float)} - """ - return self._global_irradiance - - @global_irradiance.setter - def global_irradiance(self, value): - """ - global irradiance on surface in Wh/m2 - :param value: dict{DataFrame(float)} - """ - self._global_irradiance = value - - @property - def perimeter_polygon(self) -> Polygon: - """ - total surface defined by the perimeter, merging solid and holes - :return: Polygon - """ - return self._perimeter_polygon - - @property - def solid_polygon(self) -> Polygon: - """ - solid surface - :return: Polygon - """ - return self._solid_polygon - - @property - def holes_polygons(self) -> [Polygon]: - """ - hole surfaces, a list of hole polygons found in the surface - :return: None, [] or [Polygon] - None -> not known whether holes exist in reality or not due to low level of detail of input data - [] -> no holes in the surface - [Polygon] -> one or more holes in the surface - """ - return self._holes_polygons - - @property - def pv_system_installed(self) -> PvSystem: - """ - PV system installed on the surface - :return: PvSystem - """ - return self._pv_system_installed - - @pv_system_installed.setter - def pv_system_installed(self, value): - """ - PV system installed on the surface - :param value: PvSystem - """ - self._pv_system_installed = value - - @property - def inverse(self) -> Surface: - """ - Returns the same surface pointing backwards - :return: Surface - """ - if self._inverse is None: - new_solid_polygon = Polygon(self.solid_polygon.inverse) - new_perimeter_polygon = Polygon(self.perimeter_polygon.inverse) - new_holes_polygons = [] - if self.holes_polygons is not None: - for hole in self.holes_polygons: - new_holes_polygons.append(Polygon(hole.inverse)) - else: - new_holes_polygons = None - self._inverse = Surface(new_solid_polygon, new_perimeter_polygon, new_holes_polygons, cte.VIRTUAL_INTERNAL) - return self._inverse - - def shared_surfaces(self): - """ - Raises not implemented error - """ - # todo: check https://trimsh.org/trimesh.collision.html as an option to implement this method - raise NotImplementedError - - def divide(self, z): - """ - Divides a surface at Z plane - """ - # todo: recheck this method for LoD3 (windows) - origin = Point([0, 0, z]) - normal = np.array([0, 0, 1]) - plane = Plane(normal=normal, origin=origin) - polygon = self.perimeter_polygon - part_1, part_2, intersection = polygon.divide(plane) - surface_child = Surface(part_1, part_1, name=self.name, surface_type=self.type) - rest_surface = Surface(part_2, part_2, name=self.name, surface_type=self.type) - return surface_child, rest_surface, intersection diff --git a/city_model_structure/city_model_structure/building_demand/thermal_boundary.py b/city_model_structure/city_model_structure/building_demand/thermal_boundary.py deleted file mode 100644 index 878a9124..00000000 --- a/city_model_structure/city_model_structure/building_demand/thermal_boundary.py +++ /dev/null @@ -1,394 +0,0 @@ -""" -ThermalBoundary module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from typing import List, TypeVar, Union -from city_model_structure.building_demand.layer import Layer -from city_model_structure.building_demand.thermal_opening import ThermalOpening -from city_model_structure.building_demand.thermal_zone import ThermalZone -from city_model_structure.building_demand.surface import Surface - -Polygon = TypeVar('Polygon') - - -class ThermalBoundary: - """ - ThermalBoundary class - """ - def __init__(self, surface): - self._surface = surface - self._thermal_zones = None - # ToDo: up to at least LOD2 will be just one thermal opening per Thermal boundary only if window_ratio > 0, - # review for LOD3 and LOD4 - self._thermal_openings = None - self._layers = None - self._outside_solar_absorptance = None - self._outside_thermal_absorptance = None - self._outside_visible_absorptance = None - self._u_value = None - self._shortwave_reflectance = None - self._construction_name = None - self._hi = 3.5 - self._he = 20 - self._window_ratio = None - self._refurbishment_measure = None - self._surface_geometry = None - self._thickness = None - self._virtual_internal_surface = None - self._inside_emissivity = None - self._alpha_coefficient = None - self._radiative_coefficient = None - - @property - def surface(self) -> Surface: - """ - Get the surface that belongs to the thermal boundary - :return: Surface - """ - # todo: in LoD4 this property will be a list of surfaces, not only one - return self._surface - - @property - def thermal_zones(self) -> List[ThermalZone]: - """ - Get the thermal zones delimited by the thermal boundary - :return: [ThermalZone] - """ - return self._thermal_zones - - @thermal_zones.setter - def thermal_zones(self, value): - """ - Thermal zones delimited by the thermal boundary - :param value: [ThermalZone] - """ - self._thermal_zones = value - - @property - def azimuth(self): - """ - Thermal boundary azimuth in radians - :return: float - """ - return self._surface.azimuth - - @property - def inclination(self): - """ - Thermal boundary inclination in radians - :return: float - """ - return self._surface.inclination - - @property - def area(self): - """ - Thermal boundary area in square meters - :return: float - """ - # to check the lod without depending on that parameter - if float(self.surface.solid_polygon.area) - float(self.surface.perimeter_polygon.area) < 1e-3: - area = float(self.surface.perimeter_polygon.area) * (1 - float(self.window_ratio)) - else: - area = self.surface.solid_polygon.area - return area - - @property - def _total_area_including_windows(self): - """ - Thermal boundary plus windows area in square meters - :return: float - """ - return self.surface.perimeter_polygon.area - - @property - def thickness(self): - """ - Thermal boundary thickness in meters - :return: float - """ - if self._thickness is None: - self._thickness = 0.0 - if self.layers is not None: - for layer in self.layers: - self._thickness += layer.thickness - return self._thickness - - @property - def outside_solar_absorptance(self): - """ - Get thermal boundary outside solar absorptance - :return: float - """ - return self._outside_solar_absorptance - - @outside_solar_absorptance.setter - def outside_solar_absorptance(self, value): - """ - Set thermal boundary outside solar absorptance - :param value: float - """ - self._outside_solar_absorptance = value - self._shortwave_reflectance = 1.0 - float(value) - - @property - def outside_thermal_absorptance(self): - """ - Get thermal boundary outside thermal absorptance - :return: float - """ - return self._outside_thermal_absorptance - - @outside_thermal_absorptance.setter - def outside_thermal_absorptance(self, value): - """ - Set thermal boundary outside thermal absorptance - :param value: float - """ - self._outside_thermal_absorptance = value - - @property - def outside_visible_absorptance(self): - """ - Get thermal boundary outside visible absorptance - :return: float - """ - return self._outside_visible_absorptance - - @outside_visible_absorptance.setter - def outside_visible_absorptance(self, value): - """ - Set thermal boundary outside visible absorptance - :param value: float - """ - self._outside_visible_absorptance = value - - @property - def thermal_openings(self) -> List[ThermalOpening]: - """ - Get thermal boundary thermal openings - :return: [ThermalOpening] - """ - if self._thermal_openings is None: - if float(self.window_ratio) > 0: - thermal_opening = ThermalOpening() - thermal_opening.area = float(self._total_area_including_windows) * float(self.window_ratio) - thermal_opening.hi = self.hi - thermal_opening.he = self.he - self._thermal_openings = [thermal_opening] - else: - self._thermal_openings = [] - return self._thermal_openings - - @thermal_openings.setter - def thermal_openings(self, value): - """ - Set thermal boundary thermal openings - :param value: [ThermalOpening] - """ - self._thermal_openings = value - - @property - def construction_name(self): - """ - Get construction name - :return: str - """ - return self._construction_name - - @construction_name.setter - def construction_name(self, value): - """ - Set construction name - :param value: str - """ - self._construction_name = value - - @property - def layers(self) -> List[Layer]: - """ - Get thermal boundary layers - :return: [Layers] - """ - return self._layers - - @layers.setter - def layers(self, value): - """ - Set thermal boundary layers - :param value: [Layer] - """ - self._layers = value - - @property - def type(self): - """ - Thermal boundary surface type - :return: str - """ - return self._surface.type - - @property - def window_ratio(self): - """ - Get thermal boundary window ratio - :return: float - """ - return self._window_ratio - - @window_ratio.setter - def window_ratio(self, value): - """ - Set thermal boundary window ratio - :param value: float - """ - self._window_ratio = value - - # todo: what if I just want to assign a number?? @Guille - @property - def u_value(self): - """ - Get thermal boundary U-value in W/m2K - internal and external convective coefficient in W/m2K values, can be configured at configuration.ini - :return: float - """ - if self._u_value is None: - h_i = self.hi - h_e = self.he - r_value = 1.0/h_i + 1.0/h_e - try: - for layer in self.layers: - if layer.material.no_mass: - r_value += float(layer.material.thermal_resistance) - else: - r_value = r_value + float(layer.material.conductivity) / float(layer.thickness) - self._u_value = 1.0/r_value - except TypeError: - raise Exception('Constructions layers are not initialized') from TypeError - return self._u_value - - @u_value.setter - def u_value(self, value): - """ - Set thermal boundary U-value in W/m2K - :param value: float - """ - self._u_value = value - - @property - def shortwave_reflectance(self): - """ - Get thermal boundary shortwave reflectance - :return: float - """ - return self._shortwave_reflectance - - @shortwave_reflectance.setter - def shortwave_reflectance(self, value): - """ - Set thermal boundary shortwave reflectance - :param value: float - """ - self._shortwave_reflectance = value - self._outside_solar_absorptance = 1.0 - float(value) - - @property - def hi(self): - """ - Get internal convective heat transfer coefficient (W/m2K) - :return: float - """ - return self._hi - - @hi.setter - def hi(self, value): - """ - Set internal convective heat transfer coefficient (W/m2K) - :param value: internal convective heat transfer coefficient (W/m2K) - """ - self._hi = value - - @property - def he(self): - """ - Get external convective heat transfer coefficient (W/m2K) - :return: float - """ - return self._he - - @he.setter - def he(self, value): - """ - Set external convective heat transfer coefficient (W/m2K) - :param value: external convective heat transfer coefficient (W/m2K) - """ - self._he = value - - @property - def surface_geometry(self) -> Union[NotImplementedError, Polygon]: - """ - Get the polygon that defines the thermal boundary - :return: Polygon - """ - raise NotImplementedError - - @property - def virtual_internal_surface(self) -> Surface: - """ - Get the internal surface of the thermal boundary - :return: Surface - """ - if self._virtual_internal_surface is None: - self._virtual_internal_surface = self.surface.inverse - return self._virtual_internal_surface - - # todo: need extract information from construction library or assume them at the beginning of workflows - @property - def inside_emissivity(self): - """ - Get the short wave emissivity factor of the thermal boundary's internal surface (-) - :return: float - """ - return self._inside_emissivity - - @inside_emissivity.setter - def inside_emissivity(self, value): - """ - Set short wave emissivity factor of the thermal boundary's internal surface (-) - :param value: float - """ - self._inside_emissivity = value - - @property - def alpha_coefficient(self): - """ - Get the long wave emissivity factor of the thermal boundary's internal surface (-) - :return: float - """ - return self._alpha_coefficient - - @alpha_coefficient.setter - def alpha_coefficient(self, value): - """ - Set long wave emissivity factor of the thermal boundary's internal surface (-) - :param value: float - """ - self._alpha_coefficient = value - - @property - def radiative_coefficient(self): - """ - Get the radiative coefficient of the thermal boundary's external surface (-) - :return: float - """ - return self._radiative_coefficient - - @radiative_coefficient.setter - def radiative_coefficient(self, value): - """ - Set radiative coefficient of the thermal boundary's external surface (-) - :param value: float - """ - self._radiative_coefficient = value diff --git a/city_model_structure/city_model_structure/building_demand/thermal_opening.py b/city_model_structure/city_model_structure/building_demand/thermal_opening.py deleted file mode 100644 index 9897820c..00000000 --- a/city_model_structure/city_model_structure/building_demand/thermal_opening.py +++ /dev/null @@ -1,279 +0,0 @@ -""" -ThermalOpening module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from typing import TypeVar - -Polygon = TypeVar('Polygon') - - -class ThermalOpening: - """ - ThermalOpening class - """ - def __init__(self): - self._area = None - self._openable_ratio = None - self._conductivity = None - self._frame_ratio = None - self._g_value = None - self._thickness = None - self._front_side_solar_transmittance_at_normal_incidence = None - self._back_side_solar_transmittance_at_normal_incidence = None - self._overall_u_value = None - self._hi = None - self._he = None - self._surface_geometry = None - self._inside_emissivity = None - self._alpha_coefficient = None - self._radiative_coefficient = None - - @property - def area(self): - """ - Thermal opening area in square meters - :return: float - """ - return self._area - - @area.setter - def area(self, value): - """ - Thermal opening area in square meters setter - :param value: float - """ - self._area = value - - @property - def openable_ratio(self): - """ - Get thermal opening openable ratio, NOT IMPLEMENTED - :return: Exception - """ - raise NotImplementedError - - @openable_ratio.setter - def openable_ratio(self, value): - """ - Set thermal opening openable ratio, NOT IMPLEMENTED - :param value: Any - :return: Exception - """ - raise NotImplementedError - - @property - def conductivity(self): - """ - Get thermal opening conductivity in W/mK - :return: float - """ - return self._conductivity - - @conductivity.setter - def conductivity(self, value): - """ - Get thermal opening conductivity in W/mK - :param value: float - """ - # The code to calculate overall_u_value is duplicated here and in thickness_m. - # This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read. - self._conductivity = value - if self._overall_u_value is None and self.thickness is not None: - h_i = self.hi - h_e = self.he - r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness) - self._overall_u_value = 1 / r_value - - @property - def frame_ratio(self): - """ - Get thermal opening frame ratio - :return: float - """ - return self._frame_ratio - - @frame_ratio.setter - def frame_ratio(self, value): - """ - Set thermal opening frame ratio - :param value: float - """ - self._frame_ratio = value - - @property - def g_value(self): - """ - Get thermal opening g-value - :return: float - """ - return self._g_value - - @g_value.setter - def g_value(self, value): - """ - Set thermal opening g-value - :param value: float - """ - self._g_value = value - - @property - def thickness(self): - """ - Get thermal opening thickness in meters - :return: float - """ - return self._thickness - - @thickness.setter - def thickness(self, value): - """ - Set thermal opening thickness in meters - :param value: float - """ - # The code to calculate overall_u_value is duplicated here and in conductivity. - # This ensures a more robust code that returns the overall_u_value regardless the order the parameters are read. - self._thickness = value - if self._overall_u_value is None and self.conductivity is not None: - h_i = self.hi - h_e = self.he - r_value = 1 / h_i + 1 / h_e + float(self.conductivity) / float(self.thickness) - self._overall_u_value = 1 / r_value - - @property - def front_side_solar_transmittance_at_normal_incidence(self): - """ - Get thermal opening front side solar transmittance at normal incidence - :return: float - """ - return self._front_side_solar_transmittance_at_normal_incidence - - @front_side_solar_transmittance_at_normal_incidence.setter - def front_side_solar_transmittance_at_normal_incidence(self, value): - """ - Set thermal opening front side solar transmittance at normal incidence - :param value: float - """ - self._front_side_solar_transmittance_at_normal_incidence = value - - @property - def back_side_solar_transmittance_at_normal_incidence(self): - """ - Get thermal opening back side solar transmittance at normal incidence - :return: float - """ - return self._back_side_solar_transmittance_at_normal_incidence - - @back_side_solar_transmittance_at_normal_incidence.setter - def back_side_solar_transmittance_at_normal_incidence(self, value): - """ - Set thermal opening back side solar transmittance at normal incidence - :param value: float - """ - self._back_side_solar_transmittance_at_normal_incidence = value - - @property - def overall_u_value(self): - """ - Get thermal opening overall U-value in W/m2K - :return: float - """ - return self._overall_u_value - - @overall_u_value.setter - def overall_u_value(self, value): - """ - Get thermal opening overall U-value in W/m2K - :param value: float - """ - self._overall_u_value = value - - @property - def hi(self): - """ - Get internal convective heat transfer coefficient (W/m2K) - :return: float - """ - return self._hi - - @hi.setter - def hi(self, value): - """ - Set internal convective heat transfer coefficient (W/m2K) - :param value: internal convective heat transfer coefficient (W/m2K) - """ - self._hi = value - - @property - def he(self): - """ - Get external convective heat transfer coefficient (W/m2K) - :return: float - """ - return self._he - - @he.setter - def he(self, value): - """ - Set external convective heat transfer coefficient (W/m2K) - :param value: external convective heat transfer coefficient (W/m2K) - """ - self._he = value - - @property - def surface_geometry(self) -> Polygon: - """ - Get the polygon that defines the thermal opening - :return: Polygon - """ - return self._surface_geometry - - # todo: need extract information from construction library or assume them at the beginning of workflows - @property - def inside_emissivity(self): - """ - Get the short wave emissivity factor of the thermal opening's internal surface (-) - :return: float - """ - return self._inside_emissivity - - @inside_emissivity.setter - def inside_emissivity(self, value): - """ - Set short wave emissivity factor of the thermal opening's internal surface (-) - :param value: float - """ - self._inside_emissivity = value - - @property - def alpha_coefficient(self): - """ - Get the long wave emissivity factor of the thermal opening's internal surface (-) - :return: float - """ - return self._alpha_coefficient - - @alpha_coefficient.setter - def alpha_coefficient(self, value): - """ - Set long wave emissivity factor of the thermal opening's internal surface (-) - :param value: float - """ - self._alpha_coefficient = value - - @property - def radiative_coefficient(self): - """ - Get the radiative coefficient of the thermal opening's external surface (-) - :return: float - """ - return self._radiative_coefficient - - @radiative_coefficient.setter - def radiative_coefficient(self, value): - """ - Set radiative coefficient of the thermal opening's external surface (-) - :param value: float - """ - self._radiative_coefficient = value diff --git a/city_model_structure/city_model_structure/building_demand/thermal_zone.py b/city_model_structure/city_model_structure/building_demand/thermal_zone.py deleted file mode 100644 index ddf23f4d..00000000 --- a/city_model_structure/city_model_structure/building_demand/thermal_zone.py +++ /dev/null @@ -1,200 +0,0 @@ -""" -ThermalZone module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributors Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -import uuid -from typing import List, TypeVar -from city_model_structure.building_demand.usage_zone import UsageZone - -ThermalBoundary = TypeVar('ThermalBoundary') -Polyhedron = TypeVar('Polyhedron') - - -class ThermalZone: - """ - ThermalZone class - """ - def __init__(self, thermal_boundaries, volume): - self._floor_area = None - self._thermal_boundaries = thermal_boundaries - self._is_mechanically_ventilated = None - self._additional_thermal_bridge_u_value = None - self._effective_thermal_capacity = None - self._indirectly_heated_area_ratio = None - self._infiltration_rate_system_on = None - self._infiltration_rate_system_off = None - self._usage_zones = [] - self._volume = volume - self._volume_geometry = None - self._id = None - self._ordinate_number = None - - @property - def id(self): - """ - Get thermal zone id, an universally unique identifier randomly generated - :return: str - """ - if self._id is None: - self._id = uuid.uuid4() - return self._id - - @property - def is_mechanically_ventilated(self): - """ - Get thermal zone mechanical ventilation flag - :return: Boolean - """ - return self._is_mechanically_ventilated - - @property - def floor_area(self): - """ - Get thermal zone floor area in m2 - :return: float - """ - if self._floor_area is None: - self._floor_area = 0 - for thermal_boundary in self.thermal_boundaries: - s = thermal_boundary.surface - if s.type == 'Ground': - self._floor_area += s.perimeter_polygon.area - return self._floor_area - - @property - def thermal_boundaries(self) -> List[ThermalBoundary]: - """ - Get thermal boundaries bounding with the thermal zone - :return: [ThermalBoundary] - """ - return self._thermal_boundaries - - @property - def additional_thermal_bridge_u_value(self): - """ - Get thermal zone additional thermal bridge u value W/m2K - :return: float - """ - return self._additional_thermal_bridge_u_value - - @additional_thermal_bridge_u_value.setter - def additional_thermal_bridge_u_value(self, value): - """ - Set thermal zone additional thermal bridge u value W/m2K - :param value: float - """ - self._additional_thermal_bridge_u_value = value - - @property - def effective_thermal_capacity(self): - """ - Get thermal zone effective thermal capacity in J/m2K - :return: float - """ - return self._effective_thermal_capacity - - @effective_thermal_capacity.setter - def effective_thermal_capacity(self, value): - """ - Set thermal zone effective thermal capacity in J/m2K - :param value: float - """ - self._effective_thermal_capacity = value - - @property - def indirectly_heated_area_ratio(self): - """ - Get thermal zone indirectly heated area ratio - :return: float - """ - return self._indirectly_heated_area_ratio - - @indirectly_heated_area_ratio.setter - def indirectly_heated_area_ratio(self, value): - """ - Set thermal zone indirectly heated area ratio - :param value: float - """ - self._indirectly_heated_area_ratio = value - - @property - def infiltration_rate_system_on(self): - """ - Get thermal zone infiltration rate system on in air changes per hour (ACH) - :return: float - """ - return self._infiltration_rate_system_on - - @infiltration_rate_system_on.setter - def infiltration_rate_system_on(self, value): - """ - Set thermal zone infiltration rate system on in air changes per hour (ACH) - :param value: float - """ - self._infiltration_rate_system_on = value - - @property - def infiltration_rate_system_off(self): - """ - Get thermal zone infiltration rate system off in air changes per hour (ACH) - :return: float - """ - return self._infiltration_rate_system_off - - @infiltration_rate_system_off.setter - def infiltration_rate_system_off(self, value): - """ - Set thermal zone infiltration rate system on in air changes per hour (ACH) - :param value: float - """ - self._infiltration_rate_system_off = value - - @property - def usage_zones(self) -> List[UsageZone]: - """ - Get thermal zone usage zones - :return: [UsageZone] - """ - return self._usage_zones - - @usage_zones.setter - def usage_zones(self, values): - """ - Set thermal zone usage zones - :param values: [UsageZone] - """ - self._usage_zones = values - - @property - def volume(self): - """ - Get thermal zone volume - :return: float - """ - return self._volume - - @property - def volume_geometry(self) -> Polyhedron: - """ - Get the polyhedron defined by the thermal zone - :return: Polyhedron - """ - return self._volume_geometry - - @property - def ordinate_number(self): - """ - In case the thermal_zones need to be enumerated and their order saved, this property saves that order - :return: int - """ - return self._ordinate_number - - @ordinate_number.setter - def ordinate_number(self, value): - """ - Sets an specific order of the zones to be called - :param value: int - """ - self._ordinate_number = value diff --git a/city_model_structure/city_model_structure/building_demand/usage_zone.py b/city_model_structure/city_model_structure/building_demand/usage_zone.py deleted file mode 100644 index 5ad104ca..00000000 --- a/city_model_structure/city_model_structure/building_demand/usage_zone.py +++ /dev/null @@ -1,379 +0,0 @@ -""" -UsageZone module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributors Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" -import uuid -from typing import List, TypeVar - -InternalGains = TypeVar('InternalGains') -Occupants = TypeVar('Occupants') -Polyhedron = TypeVar('Polyhedron') - - -class UsageZone: - """ - UsageZone class - """ - def __init__(self): - self._id = None - self._usage = None - self._internal_gains = None - self._heating_setpoint = None - self._heating_setback = None - self._cooling_setpoint = None - self._occupancy_density = None - self._hours_day = None - self._days_year = None - self._dhw_average_volume_pers_day = None - self._dhw_preparation_temperature = None - self._electrical_app_average_consumption_sqm_year = None - self._mechanical_air_change = None - self._occupants = None - self._heating_schedule = None - self._cooling_schedule = None - self._ventilation_schedule = None - self._schedules = None - self._volume = None - self._volume_geometry = None - self._is_heated = False - self._is_cooled = False - - @property - def id(self): - """ - Get usage zone id, an universally unique identifier randomly generated - :return: str - """ - if self._id is None: - self._id = uuid.uuid4() - return self._id - - @property - def internal_gains(self) -> List[InternalGains]: - """ - Get usage zone internal gains - :return: [InternalGains] - """ - return self._internal_gains - - @internal_gains.setter - def internal_gains(self, value): - """ - Set usage zone internal gains - :param value: [InternalGains] - """ - self._internal_gains = value - - @property - def heating_setpoint(self): - """ - Get usage zone heating set point in celsius grads - :return: float - """ - return self._heating_setpoint - - @heating_setpoint.setter - def heating_setpoint(self, value): - """ - Set usage zone heating set point in celsius grads - :param value: float - """ - self._heating_setpoint = value - - @property - def heating_setback(self): - """ - Get usage zone heating setback in celsius grads - :return: float - """ - return self._heating_setback - - @heating_setback.setter - def heating_setback(self, value): - """ - Set usage zone heating setback in celsius grads - :param value: float - """ - self._heating_setback = value - - @property - def cooling_setpoint(self): - """ - Get usage zone cooling setpoint in celsius grads - :return: float - """ - return self._cooling_setpoint - - @cooling_setpoint.setter - def cooling_setpoint(self, value): - """ - Set usage zone cooling setpoint in celsius grads - :param value: float - """ - self._cooling_setpoint = value - - @property - def hours_day(self): - """ - Get usage zone usage hours per day - :return: float - """ - return self._hours_day - - @hours_day.setter - def hours_day(self, value): - """ - Set usage zone usage hours per day - :param value: float - """ - self._hours_day = value - - @property - def days_year(self): - """ - Get usage zone usage days per year - :return: float - """ - return self._days_year - - @days_year.setter - def days_year(self, value): - """ - Set usage zone usage days per year - :param value: float - """ - self._days_year = value - - @property - def mechanical_air_change(self): - """ - Set usage zone mechanical air change in air change per hour (ACH) - :return: float - """ - return self._mechanical_air_change - - @mechanical_air_change.setter - def mechanical_air_change(self, value): - """ - Get usage zone mechanical air change in air change per hour (ACH) - :param value: float - """ - self._mechanical_air_change = value - - @property - def usage(self): - """ - Get usage zone usage - :return: str - """ - return self._usage - - @usage.setter - def usage(self, value): - """ - Get usage zone usage - :param value: str - """ - self._usage = value - - @property - def occupants(self) -> List[Occupants]: - """ - Get occupants data - :return: [Occupants] - """ - return self._occupants - - @occupants.setter - def occupants(self, values): - """ - Set occupants data - :param values: [Occupants] - """ - self._occupants = values - - @property - def heating_schedule(self) -> dict: - """ - Get heating schedules: list of 0, 1 that define whether the heating system should be OFF or ON - :return: dict{DataFrame(int)} - """ - return self._heating_schedule - - @heating_schedule.setter - def heating_schedule(self, values): - """ - heating schedules - :param values: dict{DataFrame(int)} - """ - self._heating_schedule = values - - @property - def cooling_schedule(self) -> dict: - """ - Get cooling schedules: list of 0, 1 that define whether the cooling system should be OFF or ON - :return: dict{DataFrame(int)} - """ - return self._cooling_schedule - - @cooling_schedule.setter - def cooling_schedule(self, values): - """ - cooling schedules - :param values: dict{DataFrame(int)} - """ - self._cooling_schedule = values - - @property - def ventilation_schedule(self) -> dict: - """ - Get ventilation schedules: list of 0, 1 that define whether the ventilation system should be OFF or ON - :return: dict{DataFrame(int)} - """ - return self._ventilation_schedule - - @ventilation_schedule.setter - def ventilation_schedule(self, values): - """ - ventilation_schedule schedules - :param values: dict{DataFrame(int)} - """ - self._ventilation_schedule = values - - @property - def schedules(self) -> dict: - """ - Get schedules of diverse issues in a dictionary - :return: dict() - """ - return self._schedules - - @schedules.setter - def schedules(self, values): - """ - Set schedules of diverse issues in a dictionary - :param values: dict() - """ - self._schedules = values - - @property - def occupancy_density(self): - """ - Get schedules density in persons per m2 - :return: float - """ - return self._occupancy_density - - @occupancy_density.setter - def occupancy_density(self, values): - """ - schedules density in persons per m2 - :param values: float - """ - self._occupancy_density = values - - @property - def dhw_average_volume_pers_day(self): - """ - Get average DHW consumption in m3 per person per day - :return: float - """ - return self._dhw_average_volume_pers_day - - @dhw_average_volume_pers_day.setter - def dhw_average_volume_pers_day(self, values): - """ - average DHW consumption in m3 per person per day - :param values: float - """ - self._dhw_average_volume_pers_day = values - - @property - def dhw_preparation_temperature(self): - """ - Get preparation temperature of the DHW in degree Celsius - :return: float - """ - return self._dhw_preparation_temperature - - @dhw_preparation_temperature.setter - def dhw_preparation_temperature(self, values): - """ - preparation temperature of the DHW in degree Celsius - :param values: float - """ - self._dhw_preparation_temperature = values - - @property - def electrical_app_average_consumption_sqm_year(self): - """ - Get average consumption of electrical appliances in Joules hour per m2 and year (J/m2yr) - :return: float - """ - return self._electrical_app_average_consumption_sqm_year - - @electrical_app_average_consumption_sqm_year.setter - def electrical_app_average_consumption_sqm_year(self, values): - """ - average consumption of electrical appliances in Joules per m2 and year (J/m2yr) - :param values: float - """ - self._electrical_app_average_consumption_sqm_year = values - - @property - def volume_geometry(self) -> Polyhedron: - """ - Get the polyhedron defined by the usage zone - :return: Polyhedron - """ - return self._volume_geometry - - @property - def volume(self): - """ - Get the volume in m3 - :return: float - """ - return self._volume - - @volume.setter - def volume(self, value): - """ - Volume in m3 setter - :param value: float - """ - self._volume = value - - @property - def is_heated(self): - """ - Get thermal zone heated flag - :return: Boolean - """ - return self._is_heated - - @is_heated.setter - def is_heated(self, value): - """ - Set thermal zone heated flag - :param value: Boolean - """ - self._is_heated = value - - @property - def is_cooled(self): - """ - Get thermal zone cooled flag - :return: Boolean - """ - return self._is_cooled - - @is_cooled.setter - def is_cooled(self, value): - """ - Set thermal zone cooled flag - :param value: Boolean - """ - self._is_cooled = value diff --git a/city_model_structure/city_model_structure/buildings_cluster.py b/city_model_structure/city_model_structure/buildings_cluster.py deleted file mode 100644 index 5ba7f74e..00000000 --- a/city_model_structure/city_model_structure/buildings_cluster.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -BuildingsCluster module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from typing import List, TypeVar - -from city_model_structure.city_objects_cluster import CityObjectsCluster - -CityObject = TypeVar('CityObject') - - -class BuildingsCluster(CityObjectsCluster): - """ - BuildingsCluster(CityObjectsCluster) class - """ - def __init__(self, name, city_objects): - self._cluster_type = 'buildings' - super().__init__(name, self._cluster_type, city_objects) - self._name = name - self._city_objects = city_objects - - @property - def type(self): - """ - Cluster type - :return: str - """ - return self._cluster_type - - @property - def city_objects(self) -> List[CityObject]: - """ - List of city objects conforming the cluster - :return: [CityObject] - """ - return self._city_objects diff --git a/city_model_structure/city_model_structure/city.py b/city_model_structure/city_model_structure/city.py deleted file mode 100644 index 326a0c89..00000000 --- a/city_model_structure/city_model_structure/city.py +++ /dev/null @@ -1,366 +0,0 @@ -""" -City module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" -from __future__ import annotations -import sys -import pickle -import math -from typing import List, Union, TypeVar -import pyproj -from pyproj import Transformer - - -from city_model_structure.building import Building -from city_model_structure.city_object import CityObject -from city_model_structure.city_objects_cluster import CityObjectsCluster -from city_model_structure.buildings_cluster import BuildingsCluster -from city_model_structure.parts_consisting_building import PartsConsistingBuilding -from helpers.geometry_helper import GeometryHelper -from helpers.location import Location - - -Path = TypeVar('Path') - - -class City: - """ - City class - """ - - def __init__(self, lower_corner, upper_corner, srs_name): - self._name = None - self._lower_corner = lower_corner - self._upper_corner = upper_corner - self._buildings = None - self._srs_name = srs_name - self._geometry = GeometryHelper() - # todo: right now extracted at city level, in the future should be extracted also at building level if exist - self._location = None - self._country_code = None - self._climate_reference_city = None - self._climate_file = None - self._latitude = None - self._longitude = None - self._time_zone = None - self._buildings_clusters = None - self._parts_consisting_buildings = None - self._city_objects_clusters = None - self._city_objects = None - - def _get_location(self) -> Location: - if self._location is None: - gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth - try: - input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data - except pyproj.exceptions.CRSError: - sys.stderr.write('Invalid projection reference system, please check the input data. ' - '(e.g. in CityGML files: srs_name)\n') - sys.exit() - transformer = Transformer.from_crs(input_reference, gps) - coordinates = transformer.transform(self.lower_corner[0], self.lower_corner[1]) - self._location = GeometryHelper.get_location(coordinates[0], coordinates[1]) - return self._location - - @property - def country_code(self): - """ - City country code - :return: str - """ - return self._get_location().country - - @property - def name(self): - """ - City name - :return: str - """ - return self._get_location().city - - @property - def climate_reference_city(self): - """ - Name of the city of reference for climatic information - :return: str - """ - return self._climate_reference_city - - @climate_reference_city.setter - def climate_reference_city(self, value): - """ - Name of the city of reference for climatic information - :param value: str - """ - self._climate_reference_city = value - - @property - def climate_file(self) -> Path: - """ - Full path of climate file - :return: Path - """ - return self._climate_file - - @climate_file.setter - def climate_file(self, value): - """ - Full path of climate file - :param value: Path - """ - self._climate_file = value - - @property - def city_objects(self) -> Union[List[CityObject], None]: - """ - City objects belonging to the city - :return: None or [CityObject] - """ - if self._city_objects is None: - if self.city_objects_clusters is None: - self._city_objects = [] - else: - self._city_objects = self.city_objects_clusters - if self.buildings is not None: - for building in self.buildings: - self._city_objects.append(building) - return self._city_objects - - @property - def buildings(self) -> Union[List[Building], None]: - """ - Buildings belonging to the city - :return: None or [Building] - """ - return self._buildings - - @property - def trees(self) -> NotImplementedError: - """ - Trees belonging to the city - :return: NotImplementedError - """ - raise NotImplementedError - - @property - def bixi_features(self) -> NotImplementedError: - """ - Bixi features belonging to the city - :return: NotImplementedError - """ - raise NotImplementedError - - @property - def composting_plants(self) -> NotImplementedError: - """ - Composting plants belonging to the city - :return: NotImplementedError - """ - raise NotImplementedError - - @property - def lower_corner(self): - """ - City lower corner - :return: [x,y,z] - """ - return self._lower_corner - - @property - def upper_corner(self): - """ - City upper corner - :return: [x,y,z] - """ - return self._upper_corner - - def city_object(self, name) -> Union[CityObject, None]: - """ - Retrieve the city CityObject with the given name - :param name:str - :return: None or CityObject - """ - for city_object in self.buildings: - if city_object.name == name: - return city_object - return None - - def add_city_object(self, new_city_object): - """ - Add a CityObject to the city - :param new_city_object:CityObject - :return: None or not implemented error - """ - if new_city_object.type == 'building': - if self._buildings is None: - self._buildings = [] - self._buildings.append(new_city_object) - else: - raise NotImplementedError(new_city_object.type) - - def remove_city_object(self, city_object): - """ - Remove a CityObject from the city - :param city_object:CityObject - :return: None - """ - if city_object.type != 'building': - raise NotImplementedError(city_object.type) - if self._buildings is None or self._buildings == []: - sys.stderr.write('Warning: impossible to remove city_object, the city is empty\n') - else: - if city_object in self._buildings: - self._buildings.remove(city_object) - - @property - def srs_name(self): - """ - srs name - :return: str - """ - return self._srs_name - - @name.setter - def name(self, value): - """ - Set the city name - :param value:str - :return: None - """ - self._name = value - - @staticmethod - def load(city_filename) -> City: - """ - Load a city saved with city.save(city_filename) - :param city_filename: city filename - :return: City - """ - with open(city_filename, 'rb') as file: - return pickle.load(file) - - def save(self, city_filename): - """ - Save a city into the given filename - :param city_filename: destination city filename - :return: - """ - with open(city_filename, 'wb') as file: - pickle.dump(self, file) - - def region(self, center, radius) -> City: - """ - Save a city into the given filename - :param center: specific point in space [x, y, z] - :param radius: distance to center of the sphere selected in meters - :return: selected_region_city - """ - selected_region_lower_corner = [center[0] - radius, center[1] - radius, center[2] - radius] - selected_region_upper_corner = [center[0] + radius, center[1] + radius, center[2] + radius] - selected_region_city = City(selected_region_lower_corner, selected_region_upper_corner, srs_name=self.srs_name) - selected_region_city.climate_file = self.climate_file -# selected_region_city.climate_reference_city = self.climate_reference_city - for city_object in self.city_objects: - location = city_object.centroid - if location is not None: - distance = math.sqrt(math.pow(location[0]-center[0], 2) + math.pow(location[1]-center[1], 2) - + math.pow(location[2]-center[2], 2)) - if distance < radius: - selected_region_city.add_city_object(city_object) - return selected_region_city - - @property - def latitude(self): - """ - city latitude in degrees - :return: float - """ - return self._latitude - - @latitude.setter - def latitude(self, value): - """ - city latitude in degrees - :parameter value: float - """ - self._latitude = value - - @property - def longitude(self): - """ - city longitude in degrees - :return: float - """ - return self._longitude - - @longitude.setter - def longitude(self, value): - """ - city longitude in degrees - :parameter value: float - """ - self._longitude = value - - @property - def time_zone(self): - """ - city time_zone - :return: float - """ - return self._time_zone - - @time_zone.setter - def time_zone(self, value): - """ - city time_zone - :parameter value: float - """ - self._time_zone = value - - @property - def buildings_clusters(self) -> Union[List[BuildingsCluster], None]: - """ - buildings clusters belonging to the city - :return: None or [BuildingsCluster] - """ - return self._buildings_clusters - - @property - def parts_consisting_buildings(self) -> Union[List[PartsConsistingBuilding], None]: - """ - Parts consisting buildings belonging to the city - :return: None or [PartsConsistingBuilding] - """ - return self._parts_consisting_buildings - - @property - def city_objects_clusters(self) -> Union[List[CityObjectsCluster], None]: - """ - City objects clusters belonging to the city - :return: None or [CityObjectsCluster] - """ - if self.buildings_clusters is None: - self._city_objects_clusters = [] - else: - self._city_objects_clusters = self.buildings_clusters - if self.parts_consisting_buildings is not None: - self._city_objects_clusters.append(self.parts_consisting_buildings) - return self._city_objects_clusters - - def add_city_objects_cluster(self, new_city_objects_cluster): - """ - Add a CityObject to the city - :param new_city_objects_cluster:CityObjectsCluster - :return: None or NotImplementedError - """ - if new_city_objects_cluster.type == 'buildings': - if self._buildings_clusters is None: - self._buildings_clusters = [] - self._buildings_clusters.append(new_city_objects_cluster) - elif new_city_objects_cluster.type == 'building_parts': - if self._parts_consisting_buildings is None: - self._parts_consisting_buildings = [] - self._parts_consisting_buildings.append(new_city_objects_cluster) - else: - raise NotImplementedError diff --git a/city_model_structure/city_model_structure/city_object.py b/city_model_structure/city_model_structure/city_object.py deleted file mode 100644 index f42a1c77..00000000 --- a/city_model_structure/city_model_structure/city_object.py +++ /dev/null @@ -1,229 +0,0 @@ -""" -CityObject module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - -import math -from typing import List, Union - - -from city_model_structure.iot.sensor import Sensor -from city_model_structure.building_demand.surface import Surface -from city_model_structure.attributes.polyhedron import Polyhedron -from helpers.configuration_helper import ConfigurationHelper - - -class CityObject: - """ - class CityObject - """ - def __init__(self, name, lod, surfaces, city_lower_corner): - self._name = name - self._lod = lod - self._surfaces = surfaces - self._city_lower_corner = city_lower_corner - self._type = None - self._city_object_lower_corner = None - self._detailed_polyhedron = None - self._simplified_polyhedron = None - self._min_x = ConfigurationHelper().max_coordinate - self._min_y = ConfigurationHelper().max_coordinate - self._min_z = ConfigurationHelper().max_coordinate - self._centroid = None - self._external_temperature = dict() - self._global_horizontal = dict() - self._diffuse = dict() - self._beam = dict() - self._sensors = [] - - @property - def lod(self): - """ - City object level of detail 1, 2, 3 or 4 - :return: int - """ - lod = math.log(self._lod, 2) + 1 - return lod - - @property - def type(self): - """ - city object type - :return: str - """ - return self._type - - @property - def volume(self): - """ - City object volume in cubic meters - :return: float - """ - return self.simplified_polyhedron.volume - - @property - def detailed_polyhedron(self) -> Polyhedron: - """ - City object polyhedron including details such as holes - :return: Polyhedron - """ - if self._detailed_polyhedron is None: - polygons = [] - for surface in self.surfaces: - polygons.append(surface.solid_polygon) - if surface.holes_polygons is not None: - for hole_polygon in surface.holes_polygons: - polygons.append(hole_polygon) - self._detailed_polyhedron = Polyhedron(polygons) - return self._detailed_polyhedron - - @property - def simplified_polyhedron(self) -> Polyhedron: - """ - City object polyhedron, just the simple lod2 representation - :return: Polyhedron - """ - if self._simplified_polyhedron is None: - polygons = [] - for surface in self.surfaces: - polygons.append(surface.perimeter_polygon) - self._simplified_polyhedron = Polyhedron(polygons) - return self._simplified_polyhedron - - @property - def surfaces(self) -> List[Surface]: - """ - City object surfaces - :return: [Surface] - """ - return self._surfaces - - def surface(self, name) -> Union[Surface, None]: - """ - Get the city object surface with a given name - :param name: str - :return: None or Surface - """ - for s in self.surfaces: - if s.name == name: - return s - return None - - def surface_by_id(self, identification_number) -> Union[Surface, None]: - """ - Get the city object surface with a given name - :param identification_number: str - :return: None or Surface - """ - for s in self.surfaces: - if str(s.id) == str(identification_number): - return s - return None - - @property - def centroid(self): - """ - City object centroid - :return: [x,y,z] - """ - if self._centroid is None: - self._centroid = self.simplified_polyhedron.centroid - return self._centroid - - @property - def max_height(self): - """ - City object maximal height in meters - :return: float - """ - return self.simplified_polyhedron.max_z - - @property - def external_temperature(self) -> dict: - """ - external temperature surrounding the city object in grads Celsius - :return: dict{DataFrame(float)} - """ - return self._external_temperature - - @external_temperature.setter - def external_temperature(self, value): - """ - external temperature surrounding the city object in grads Celsius - :param value: dict{DataFrame(float)} - """ - self._external_temperature = value - - @property - def global_horizontal(self) -> dict: - """ - global horizontal radiation surrounding the city object in W/m2 - :return: dict{DataFrame(float)} - """ - return self._global_horizontal - - @global_horizontal.setter - def global_horizontal(self, value): - """ - global horizontal radiation surrounding the city object in W/m2 - :param value: dict{DataFrame(float)} - """ - self._global_horizontal = value - - @property - def diffuse(self) -> dict: - """ - diffuse radiation surrounding the city object in W/m2 - :return: dict{DataFrame(float)} - """ - return self._diffuse - - @diffuse.setter - def diffuse(self, value): - """ - diffuse radiation surrounding the city object in W/m2 - :param value: dict{DataFrame(float)} - """ - self._diffuse = value - - @property - def beam(self) -> dict: - """ - beam radiation surrounding the city object in W/m2 - :return: dict{DataFrame(float)} - """ - return self._beam - - @beam.setter - def beam(self, value): - """ - beam radiation surrounding the city object in W/m2 - :param value: dict{DataFrame(float)} - """ - self._beam = value - - @property - def lower_corner(self): - """ - City object lower corner coordinates [x, y, z] - """ - if self._city_object_lower_corner is None: - self._city_object_lower_corner = [self._min_x, self._min_y, self._min_z] - return self._city_object_lower_corner - - @property - def sensors(self) -> List[Sensor]: - """ - Sensor list belonging to the city object - :return: [Sensor] - """ - return self._sensors - - @sensors.setter - def sensors(self, value): - """ - Sensor list belonging to the city object - :param value: [Sensor] - """ - self._sensors = value diff --git a/city_model_structure/city_model_structure/city_objects_cluster.py b/city_model_structure/city_model_structure/city_objects_cluster.py deleted file mode 100644 index 780574a1..00000000 --- a/city_model_structure/city_model_structure/city_objects_cluster.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -CityObjectsCluster module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from abc import ABC -from typing import List -from city_model_structure.iot.sensor import Sensor -from city_model_structure.city_object import CityObject - - -class CityObjectsCluster(ABC, CityObject): - """ - CityObjectsCluster(ABC) class - """ - def __init__(self, name, cluster_type, city_objects): - self._name = name - self._cluster_type = cluster_type - self._city_objects = city_objects - self._sensors = [] - self._lod = '' - super().__init__(name, self._lod, None, None) - - @property - def name(self): - """ - Cluster name - :return: str - """ - return self._name - - @property - def type(self): - """ - City object cluster type raises NotImplemented error - """ - raise NotImplementedError - - @property - def city_objects(self): - """ - City objects raises NotImplemented error - """ - raise NotImplementedError - - def add_city_object(self, city_object) -> List[CityObject]: - """ - add new object to the cluster - :return: [CityObjects] - """ - if self._city_objects is None: - self._city_objects = [city_object] - else: - self._city_objects.append(city_object) - return self._city_objects - - @property - def sensors(self) -> List[Sensor]: - """ - Sensor list belonging to the city objects cluster - :return: [Sensor] - """ - return self._sensors - - @sensors.setter - def sensors(self, value): - """ - Sensor list belonging to the city objects cluster - :param value: [Sensor] - """ - self._sensors = value diff --git a/city_model_structure/city_model_structure/composting_plant.py b/city_model_structure/city_model_structure/composting_plant.py deleted file mode 100644 index 0030b4d0..00000000 --- a/city_model_structure/city_model_structure/composting_plant.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Composting plant module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from city_model_structure.city_object import CityObject - - -class CompostingPlant(CityObject): - """ - CompostingPlant(CityObject) class - """ - def __init__(self, lod, surfaces, name, waste_type, capacity): - super().__init__(lod, surfaces, name, []) - self._waste_type = waste_type - self._capacity = capacity - self._type = 'composting_plant' - - @property - def waste_type(self): - """ - Get waste_type treated in composting plant - :return: waste_type - """ - return self._waste_type - - @property - def capacity(self): - """ - Get capacity of composting plant in kg - :return: capacity - """ - return self._capacity diff --git a/city_model_structure/city_model_structure/energy_systems/heat_pump.py b/city_model_structure/city_model_structure/energy_systems/heat_pump.py deleted file mode 100644 index c6b059bc..00000000 --- a/city_model_structure/city_model_structure/energy_systems/heat_pump.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -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 -""" - - -class HeatPump: - """ - HeatPump class - """ - def __init__(self): - self._seasonal_mean_cop = None - self._seasonal_mean_coverage_factor = None - - @property - def seasonal_mean_cop(self): - """ - Get seasonal mean COP (-) - :return: real - """ - return self._seasonal_mean_cop - - @seasonal_mean_cop.setter - def seasonal_mean_cop(self, value): - """ - Get seasonal mean COP (-) - :param value: real - """ - self._seasonal_mean_cop = value - - @property - def seasonal_mean_coverage_factor(self): - """ - Get percentage of demand covered by the hp (-) - :return: real - """ - return self._seasonal_mean_coverage_factor - - @seasonal_mean_coverage_factor.setter - def seasonal_mean_coverage_factor(self, value): - """ - Set percentage of demand covered by the hp (-) - :return: real - """ - self._seasonal_mean_coverage_factor = value diff --git a/city_model_structure/city_model_structure/energy_systems/pv_system.py b/city_model_structure/city_model_structure/energy_systems/pv_system.py deleted file mode 100644 index e0facb47..00000000 --- a/city_model_structure/city_model_structure/energy_systems/pv_system.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -pv_system defines a pv system including all components: PV panels, transformer... -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - - -class PvSystem: - """ - PvSystem class - """ - def __init__(self): - self._modules_mean_seasonal_efficiency = None - self._total_area = None - self._module_area = None - self._number_of_modules = None - self._overall_system_performance_ratio = None - self._electricity_generation = None - - @property - def modules_mean_seasonal_efficiency(self): - """ - Get mean modules efficiency (-) - :return: float - """ - return self._modules_mean_seasonal_efficiency - - @modules_mean_seasonal_efficiency.setter - def modules_mean_seasonal_efficiency(self, value): - """ - Set mean modules efficiency (-) - :param value: float - """ - self._modules_mean_seasonal_efficiency = value - - @property - def total_area(self): - """ - Get total modules area (m2) - :return: float - """ - return self._total_area - - @total_area.setter - def total_area(self, value): - """ - Set total modules area (m2) - :param value: float - """ - self._total_area = value - - @property - def module_area(self): - """ - Get module area (m2) - :return: float - """ - return self._module_area - - @module_area.setter - def module_area(self, value): - """ - Set module area (m2) - :param value: float - """ - self._module_area = value - - @property - def number_of_modules(self): - """ - Get number of modules - :return: int - """ - return self._number_of_modules - - @number_of_modules.setter - def number_of_modules(self, value): - """ - Set number of modules - :param value: int - """ - self._number_of_modules = value - - @property - def overall_system_performance_ratio(self): - """ - Get overall system performance ratio (-) - :return: float - """ - return self._overall_system_performance_ratio - - @overall_system_performance_ratio.setter - def overall_system_performance_ratio(self, value): - """ - Set overall system performance ratio (-) - :param value: float - """ - self._overall_system_performance_ratio = value - - @property - def electricity_generation(self): - """ - Get electricity generation (J) - :return: float - """ - return self._electricity_generation - - @electricity_generation.setter - def electricity_generation(self, value): - """ - Set electricity generation (J) - :param value: float - """ - self._electricity_generation = value diff --git a/city_model_structure/city_model_structure/iot/concordia_energy_sensor.py b/city_model_structure/city_model_structure/iot/concordia_energy_sensor.py deleted file mode 100644 index 88a88e51..00000000 --- a/city_model_structure/city_model_structure/iot/concordia_energy_sensor.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Energy Sensor module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - -import pandas as pd -from city_model_structure.iot.sensor import Sensor - - -class ConcordiaEnergySensor(Sensor): - """ - Concordia energy sensor. - """ - - def __init__(self, name): - super().__init__() - self._name = name - self._interval = 5 - self._interval_units = 'minutes' - self._type = 'ConcordiaEnergySensor' - self._units = 'kW' - self._measures = pd.DataFrame(columns=["Date time", "Energy consumption"]) - - @property - def measures(self) -> pd.DataFrame: - """ - Sensor measures [yyyy-mm-dd, hh:mm:ss kW] - :return: DataFrame["Date time", "Energy consumption"] - """ - return self._measures - - @measures.deleter - def measures(self): - self._measures.drop = None - - def add_period(self, measures): - """ - Add or update a period measures to the dataframe - """ - measures = self._measures.append(measures, ignore_index=True) - self._measures = measures.drop_duplicates('Date time', keep='last') diff --git a/city_model_structure/city_model_structure/iot/concordia_gas_flow_sensor.py b/city_model_structure/city_model_structure/iot/concordia_gas_flow_sensor.py deleted file mode 100644 index 3dd7a7c0..00000000 --- a/city_model_structure/city_model_structure/iot/concordia_gas_flow_sensor.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Gas Flow Sensor module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -import pandas as pd -from city_model_structure.iot.sensor import Sensor - - -class ConcordiaGasFlowSensor(Sensor): - """ - Concordia gas flow sensor. - """ - - def __init__(self, name): - super().__init__() - self._name = name - self._interval = 5 - self._interval_units = 'minutes' - self._type = 'ConcordiaGasFlowSensor' - self._units = 'm3' - self._measures = pd.DataFrame(columns=["Date time", "Gas Flow Cumulative Monthly"]) - - @property - def measures(self) -> pd.DataFrame: - """ - Sensor measures [yyyy-mm-dd, hh:mm:ss m3] - :return: DataFrame["Date time", "Gas Flow Cumulative Monthly"] - """ - return self._measures - - @measures.deleter - def measures(self): - self._measures.drop = None - - def add_period(self, measures): - """ - Add or update a period measures to the dataframe - """ - measures = self._measures.append(measures, ignore_index=True) - self._measures = measures.drop_duplicates('Date time', keep='last') diff --git a/city_model_structure/city_model_structure/iot/concordia_temperature_sensor.py b/city_model_structure/city_model_structure/iot/concordia_temperature_sensor.py deleted file mode 100644 index ae1b1129..00000000 --- a/city_model_structure/city_model_structure/iot/concordia_temperature_sensor.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Temperature Sensor module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -import pandas as pd -from city_model_structure.iot.sensor import Sensor - - -class ConcordiaTemperatureSensor(Sensor): - """ - Concordia temperature sensor. - """ - - def __init__(self, name): - super().__init__() - self._name = name - self._interval = 5 - self._interval_units = 'minutes' - self._type = 'ConcordiaTemperatureSensor' - self._units = 'Celsius' - self._measures = pd.DataFrame(columns=["Date time", "Temperature"]) - - @property - def measures(self) -> pd.DataFrame: - """ - Sensor measures [yyyy-mm-dd, hh:mm:ss Celsius] - :return: DataFrame["Date time", "Temperature"] - """ - return self._measures - - @measures.deleter - def measures(self): - self._measures.drop = None - - def add_period(self, measures): - """ - Add or update a period measures to the dataframe - """ - measures = self._measures.append(measures, ignore_index=True) - self._measures = measures.drop_duplicates('Date time', keep='last') diff --git a/city_model_structure/city_model_structure/iot/sensor.py b/city_model_structure/city_model_structure/iot/sensor.py deleted file mode 100644 index 6dfad778..00000000 --- a/city_model_structure/city_model_structure/iot/sensor.py +++ /dev/null @@ -1,73 +0,0 @@ -""" -Sensor module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - -from helpers.location import Location - - -class Sensor: - """ - Sensor abstract class - """ - def __init__(self): - self._name = None - self._type = None - self._units = None - self._location = None - - @property - def name(self): - """ - Get sensor name - :return: str - """ - return self._name - - @name.setter - def name(self, value): - """ - Set sensor name - :param value: str - """ - self._name = value - - @property - def type(self): - """ - Get sensor type - :return: str - """ - return self._type - - @property - def units(self): - """ - Get sensor units - :return: str - """ - return self._units - - @property - def location(self) -> Location: - """ - Get sensor location - :return: Location - """ - return self._location - - @location.setter - def location(self, value): - """ - Set sensor location - :param value: Location - """ - self._location = value - - @property - def measures(self): - """ - Sensor measures - """ - raise NotImplementedError diff --git a/city_model_structure/city_model_structure/network.py b/city_model_structure/city_model_structure/network.py deleted file mode 100644 index 67759f54..00000000 --- a/city_model_structure/city_model_structure/network.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Network module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -""" -import uuid -from typing import List - -from city_model_structure.city_object import CityObject -from city_model_structure.attributes.edge import Edge -from city_model_structure.attributes.node import Node - - -class Network(CityObject): - """ - Generic network class to be used as base for the network models - """ - def __init__(self, name, edges=None, nodes=None): - super().__init__(name, 0, [], None) - if nodes is None: - nodes = [] - if edges is None: - edges = [] - self._id = None - self._edges = edges - self._nodes = nodes - - @property - def id(self): - """ - Network id, an universally unique identifier randomly generated - :return: str - """ - if self._id is None: - self._id = uuid.uuid4() - return self._id - - @property - def edges(self) -> List[Edge]: - """ - Network edges - """ - return self._edges - - @property - def nodes(self) -> List[Node]: - """ - Network nodes - """ - return self._nodes diff --git a/city_model_structure/city_model_structure/parts_consisting_building.py b/city_model_structure/city_model_structure/parts_consisting_building.py deleted file mode 100644 index bb342321..00000000 --- a/city_model_structure/city_model_structure/parts_consisting_building.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -PartsConsistingBuilding module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" - -from typing import List, TypeVar -from city_model_structure.city_objects_cluster import CityObjectsCluster -CityObject = TypeVar('CityObject') - - -class PartsConsistingBuilding(CityObjectsCluster): - """ - PartsConsistingBuilding(CityObjectsCluster) class - """ - def __init__(self, name, city_objects): - self._cluster_type = 'building_parts' - super().__init__(name, self._cluster_type, city_objects) - self._name = name - self._city_objects = city_objects - - @property - def type(self): - """ - type of cluster - :return: str - """ - return self._cluster_type - - @property - def city_objects(self) -> List[CityObject]: - """ - city objects that compose the cluster - :return: [CityObject] - """ - return self._city_objects diff --git a/city_model_structure/city_model_structure/subway_entrance.py b/city_model_structure/city_model_structure/subway_entrance.py deleted file mode 100644 index b42dd880..00000000 --- a/city_model_structure/city_model_structure/subway_entrance.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Subway entrance module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from city_model_structure.city_object import CityObject - - -class SubwayEntrance(CityObject): - """ - SubwayEntrance(CityObject) class - """ - def __init__(self, name, latitude, longitude): - super().__init__(0, [], name, []) - self._name = name - self._latitude = latitude - self._longitude = longitude - self._type = 'subway_entrance' - - @property - def latitude(self): - # todo: to be defined the spacial point and the units - """ - Get latitude - :return: float - """ - return self._latitude - - @property - def longitude(self): - # todo: to be defined the spacial point and the units - """ - Get longitude - :return: float - """ - return self._longitude - - @property - def name(self): - """ - Get name - :return: string - """ - return self._name diff --git a/city_model_structure/city_model_structure/transport/connection.py b/city_model_structure/city_model_structure/transport/connection.py deleted file mode 100644 index 9265a5df..00000000 --- a/city_model_structure/city_model_structure/transport/connection.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -Connection module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" -from city_model_structure.attributes.edge import Edge -from city_model_structure.transport.lane import Lane - - -class Connection: - """ - Connection class - """ - - def __init__(self): - self._from_edge = None - self._to_edge = None - self._from_lane = None - self._to_lane = None - self._pass = None - self._keep_clear = None - - @property - def from_edge(self) -> Edge: - """ - Edge the vehicle leaves - :return: Edge - """ - return self._from_edge - - @from_edge.setter - def from_edge(self, value): - """ - Edge the vehicle leaves setter - :param value: Edge - """ - self._from_edge = value - - @property - def to_edge(self) -> Edge: - """ - Edge the vehicle reaches - :return: Edge - """ - return self._to_edge - - @to_edge.setter - def to_edge(self, value): - """ - Edge the vehicle reaches setter - :param value: Edge - """ - self._to_edge = value - - @property - def from_lane(self) -> Lane: - """ - Incoming lane - :return: Lane - """ - return self._to_lane - - @from_lane.setter - def from_lane(self, value): - """ - Incoming lane setter - :param value: Lane - """ - self._from_lane = value - - @property - def to_lane(self) -> Lane: - """ - Outgoing lane - :return: Lane - """ - return self._to_lane - - @to_lane.setter - def to_lane(self, value): - """ - Outgoing lane setter - :param value: Lane - """ - self._to_lane = value - - @property - def pass_not_wait(self): - """ - if set, vehicles which pass this (lane-2-lane) connection will not wait - :return: bool - """ - return self._pass - - @pass_not_wait.setter - def pass_not_wait(self, value): - """ - pass_not_wait setter - :param value: bool - """ - self._pass = value - - @property - def keep_clear(self): - """ - if set to false, vehicles which pass this (lane-2-lane) connection will not worry about blocking the intersection - :return: bool - """ - return self._keep_clear - - @keep_clear.setter - def keep_clear(self, value): - """ - keep_clear setter - :param value: bool - """ - self._keep_clear = value diff --git a/city_model_structure/city_model_structure/transport/crossing.py b/city_model_structure/city_model_structure/transport/crossing.py deleted file mode 100644 index 5a2db9e2..00000000 --- a/city_model_structure/city_model_structure/transport/crossing.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Crossing module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" - -from typing import List -from city_model_structure.transport.traffic_node import TrafficNode - - -class Crossing(TrafficNode): - """ - Crossing class - """ - - def __init__(self, name, coordinates, priority, width, shape=None, edges=None): - super().__init__(name, coordinates, edges=edges, node_type='Crossing') - self._priority = priority - self._width = width - self._shape = shape - - @property - def priority(self): - """ - Whether the pedestrians have priority over the vehicles (automatically set to true at tls-controlled intersections). - :return: bool - """ - return self._priority - - @priority.setter - def priority(self, value): - """ - Priority setter - :param value: bool - """ - self._priority = value - - @property - def width(self): - """ - Width in m - :return: float - """ - return self._width - - @width.setter - def width(self, value): - """ - Width in m setter - :param value: float - """ - self._width = value - - @property - def shape(self) -> List[List[float]]: - """ - List of positions (positions in m) - :return: [[x, y, (z)]] - """ - return self._shape - - @shape.setter - def shape(self, value): - """ - List of positions setter - :param value: [[x, y, (z)]] - """ - self._shape = value diff --git a/city_model_structure/city_model_structure/transport/join.py b/city_model_structure/city_model_structure/transport/join.py deleted file mode 100644 index a7f609b8..00000000 --- a/city_model_structure/city_model_structure/transport/join.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Join module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" - -from city_model_structure.transport.traffic_node import TrafficNode - - -class Join(TrafficNode): - """ - Join class - """ - - def __init__(self, name, coordinates, nodes): - self._nodes = nodes - edges = [] - prohibitions = [] - connections = [] - for node in self._nodes: - edges = edges + node.edges - prohibitions = prohibitions + node.prohibitions - connections = connections + node.connections - super().__init__(name, coordinates, edges=edges, prohibitions=prohibitions, connections=connections, - node_type='Join') diff --git a/city_model_structure/city_model_structure/transport/lane.py b/city_model_structure/city_model_structure/transport/lane.py deleted file mode 100644 index d89481d8..00000000 --- a/city_model_structure/city_model_structure/transport/lane.py +++ /dev/null @@ -1,136 +0,0 @@ -""" -Lane module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -""" - -from typing import List - - -class Lane: - """ - Lane class - """ - - def __init__(self): - self._index = None - self._allow = None - self._disallow = None - self._change_left = None - self._change_right = None - self._speed = None - self._width = None - - @property - def index(self): - """ - Lane index - The enumeration index of the lane (0 is the rightmost lane, -1 is the leftmost one) - :return: int - """ - return self._index - - @index.setter - def index(self, value): - """ - Index setter - :param value: int - """ - self._index = value - - @property - def allow(self) -> List[str]: - """ - List of allowed vehicle classes - :return: [str] - """ - return self._allow - - @allow.setter - def allow(self, value): - """ - List of allowed vehicle classes setter - :param value: [str] - """ - self._allow = value - - @property - def disallow(self) -> List[str]: - """ - List of not allowed vehicle classes - :return: [str] - """ - return self._disallow - - @disallow.setter - def disallow(self, value): - """ - List of not allowed vehicle classes setter - :param value: [str] - """ - self._disallow = value - - @property - def change_left(self) -> List[str]: - """ - List of vehicle classes that may change left from this lane - :return: [str] - """ - return self._change_left - - @change_left.setter - def change_left(self, value): - """ - change_left setter - :param value: [str] - """ - self._change_left = value - - @property - def change_right(self) -> List[str]: - """ - List of vehicle classes that may change right from this lane - :return: [str] - """ - return self._change_right - - @change_right.setter - def change_right(self, value): - """ - change_right setter - :param value: [str] - """ - self._change_right = value - - @property - def speed(self): - """ - Speed in m/s - :return: float - """ - return self._speed - - @speed.setter - def speed(self, value): - """ - Speed in m/s setter - :param value: float - """ - self._speed = value - - @property - def width(self): - """ - Width in m - :return: float - """ - return self._width - - @width.setter - def width(self, value): - """ - Width in m setter - :param value: float - """ - self._width = value diff --git a/city_model_structure/city_model_structure/transport/phase.py b/city_model_structure/city_model_structure/transport/phase.py deleted file mode 100644 index cc3f7a83..00000000 --- a/city_model_structure/city_model_structure/transport/phase.py +++ /dev/null @@ -1,125 +0,0 @@ -""" -Phase module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -""" - -from typing import List - - -class Phase: - """ - Phase class - """ - - def __init__(self): - self._duration = None - self._state = None - self._min_duration = None - self._max_duration = None - self._name = None - self._next = None - - @property - def duration(self): - """ - Duration in seconds - :return: int - """ - return self._duration - - @duration.setter - def duration(self, value): - """ - Duration setter - :param value: int - """ - self._duration = value - - @property - def state(self): - """ - List of signal states - :return: [] - """ - return self._state - - @state.setter - def state(self, value): - """ - List of signal states setter - :param value: [] - """ - self._state = value - - @property - def min_duration(self): - """ - Minimum duration in seconds - :return: int - """ - if self._min_duration is None: - self._min_duration = self._duration - return self._min_duration - - @min_duration.setter - def min_duration(self, value): - """ - Minimum duration setter - :param value: int - """ - self._min_duration = value - - @property - def max_duration(self): - """ - Maximum duration in seconds - :return: int - """ - if self._max_duration is None: - self._max_duration = self._duration - return self._max_duration - - @max_duration.setter - def max_duration(self, value): - """ - Maximum duration setter - :param value: int - """ - self._max_duration = value - - @property - def name(self): - """ - Phase name - :return: str - """ - return self._name - - @name.setter - def name(self, value): - """ - Phase name setter - :param value: str - """ - self._name = value - - @property - def next(self) -> List[int]: - """ - The next phase in the cycle after the current. - This is useful when adding extra transition phases to a traffic light plan which are not part of every cycle. - Traffic lights of type 'actuated' can make use of a list of indices for selecting among alternative - successor phases. - :return: [int] - """ - return self._next - - @next.setter - def next(self, value): - """ - Next setter - :param value: [int] - """ - self._next = value diff --git a/city_model_structure/city_model_structure/transport/traffic_edge.py b/city_model_structure/city_model_structure/transport/traffic_edge.py deleted file mode 100644 index 6bfa3d39..00000000 --- a/city_model_structure/city_model_structure/transport/traffic_edge.py +++ /dev/null @@ -1,135 +0,0 @@ -""" -Edge module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" - -from typing import List -from city_model_structure.attributes.edge import Edge -from city_model_structure.transport.lane import Lane - - -class TrafficEdge(Edge): - """ - Edge class - Each edge is unidirectional and starts at the "from" node and ends at the "to" node - """ - - def __init__(self, name, nodes, priority, speed, lanes, length, allows=None, disallows=None, sidewalk_width=None, - edge_type='TrafficEdge'): - super().__init__(name, nodes) - self._edge_type = edge_type - self._lanes = lanes - self._priority = priority - self._speed = speed - self._length = length - self._allows = allows - self._disallows = disallows - self._sidewalk_width = sidewalk_width - - @property - def edge_type(self): - """ - The name of a edge type - :return: str - """ - return self._edge_type - - @property - def lanes(self) -> List[Lane]: - """ - List of lanes on an edge - :return: List[Lane] - """ - return self._lanes - - @lanes.setter - def lanes(self, value): - """ - List of lanes on an edge setter - :param value: List[Lane] - """ - self._lanes = value - - @property - def priority(self): - """ - A number, which determines the priority between different road types. - It starts with one; higher numbers represent more important roads. - :return: int - """ - return self._priority - - @priority.setter - def priority(self, value): - """ - Priority setter - :param value: int - """ - self._priority = value - - @property - def speed(self): - """ - The speed limit in m/s - :return: float - """ - return self._speed - - @speed.setter - def speed(self, value): - """ - The speed limit in m/s setter - :param value: float - """ - self._speed = value - - @property - def length(self): - """ - Length in m - :return: float - """ - return self._length - - @length.setter - def length(self, value): - """ - Length in m setter - :param value: float - """ - self._length = value - - @property - def allows(self) -> List[str]: - """ - List of allowed vehicle classes - :return: [str] - """ - return self._allows - - @allows.setter - def allows(self, value): - """ - List of allowed vehicle classes setter - :param value: [str] - """ - self._allows = value - - @property - def disallows(self) -> List[str]: - """ - List of not allowed vehicle classes - :return: [str] - """ - return self._disallows - - @disallows.setter - def disallows(self, value): - """ - List of not allowed vehicle classes setter - :param value: [str] - """ - self._disallows = value diff --git a/city_model_structure/city_model_structure/transport/traffic_light.py b/city_model_structure/city_model_structure/transport/traffic_light.py deleted file mode 100644 index a5244eaa..00000000 --- a/city_model_structure/city_model_structure/transport/traffic_light.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Traffic light module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" - -from typing import List -from city_model_structure.transport.phase import Phase -from city_model_structure.transport.traffic_node import TrafficNode - - -class TrafficLight(TrafficNode): - """ - Traffic light class - """ - def __init__(self, name, coordinates, offset, phases=None, edges=None, right_on_red=False): - super().__init__(name, coordinates, edges=edges, node_type='TrafficLight') - if phases is None: - phases = [] - self._right_on_red = right_on_red - self._offset = offset - self._phases = phases - - @property - def right_on_red(self): - """ - Return if is possible to turn right if the traffic light is red - """ - return self._right_on_red - - @right_on_red.setter - def right_on_red(self, value): - """ - Set if is possible to turn right if the traffic light is red - """ - self._right_on_red = value - - @property - def offset(self): - """ - The initial time offset of the program - :return: int - """ - return self._offset - - @offset.setter - def offset(self, value): - """ - The initial time offset of the program setter - :param value: int - """ - self._offset = value - - @property - def phases(self) -> List[Phase]: - """ - Phases of the traffic light logic - :return: [Phase] - """ - return self._phases - - @phases.setter - def phases(self, value): - """ - Phases setter - :param value: [Phase] - """ - self._phases = value diff --git a/city_model_structure/city_model_structure/transport/traffic_network.py b/city_model_structure/city_model_structure/transport/traffic_network.py deleted file mode 100644 index 6bd46a52..00000000 --- a/city_model_structure/city_model_structure/transport/traffic_network.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Traffic network module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" - -from city_model_structure.network import Network - - -class TrafficNetwork(Network): - """ - TrafficNetwork(CityObject) class - """ - def __init__(self, name, edges=None, nodes=None): - super().__init__(name, edges, nodes) - self._type = "TrafficNetwork" - - @property - def type(self): - """ - Network type - """ - return self._type diff --git a/city_model_structure/city_model_structure/transport/traffic_node.py b/city_model_structure/city_model_structure/transport/traffic_node.py deleted file mode 100644 index 1ff63de7..00000000 --- a/city_model_structure/city_model_structure/transport/traffic_node.py +++ /dev/null @@ -1,84 +0,0 @@ -""" -Node module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" -from typing import List - -from city_model_structure.attributes.edge import Edge -from city_model_structure.attributes.node import Node -from city_model_structure.attributes.point import Point - - -from city_model_structure.transport.connection import Connection - - -class TrafficNode(Node): - """ - Node class - """ - - def __init__(self, name, coordinates, node_type='TrafficNode', edges=None, prohibitions=None, connections=None): - super().__init__(name, edges) - if connections is None: - connections = [] - if prohibitions is None: - prohibitions = [] - self._coordinates = coordinates - self._prohibitions = prohibitions - self._connections = connections - self._node_type = node_type - - @property - def node_type(self): - """ - The name of a node type - :return: str - """ - return self._node_type - - @property - def coordinates(self) -> Point: - """ - The x,y,z - Node coordinates - :return: Point - """ - return self._coordinates - - @coordinates.setter - def coordinates(self, value): - """ - The x,y,z - Node coordinates setter - :param value: Point - """ - self._coordinates = value - - @property - def prohibitions(self) -> List[(Edge, Edge)]: - """ - return a list of forbidden edges tuples meaning you can not move from the first edge to the second - """ - return self._prohibitions - - @prohibitions.setter - def prohibitions(self, value): - """ - Set the prohibitions tuples for this node - """ - self._prohibitions = value - - @property - def connections(self) -> List[Connection]: - """ - Return a list of connections for the node - """ - return self._connections - - @connections.setter - def connections(self, value): - """ - Set the connections for this node - """ - self._connections = value diff --git a/city_model_structure/city_model_structure/transport/walkway_node.py b/city_model_structure/city_model_structure/transport/walkway_node.py deleted file mode 100644 index cde5f821..00000000 --- a/city_model_structure/city_model_structure/transport/walkway_node.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Walkway node module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -Contributor Milad milad.aghamohamadnia@concordia.ca -Contributor Guille guille.gutierrezmorote@concordia.ca -""" - -from typing import List -from city_model_structure.transport.traffic_node import TrafficNode - - -class WalkwayNode(TrafficNode): - """ - WalkwayNode class - """ - - def __init__(self, name, coordinates, edges=None, shape=None): - super().__init__(name, coordinates, edges=edges, node_type='WalkwayNode') - self._shape = shape - - @property - def shape(self) -> List[List[float]]: - """ - List of positions (positions in m) - :return: [[x, y, (z)]] - """ - return self._shape - - @shape.setter - def shape(self, value): - """ - List of positions setter - :param value: [[x, y, (z)]] - """ - self._shape = value diff --git a/city_model_structure/city_model_structure/tree.py b/city_model_structure/city_model_structure/tree.py deleted file mode 100644 index f1e0caff..00000000 --- a/city_model_structure/city_model_structure/tree.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Tree module -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca -""" -from city_model_structure.city_object import CityObject - - -class Tree(CityObject): - """ - Tree(CityObject) class - """ - def __init__(self, lod, surfaces, name, height, canopy): - super().__init__(lod, surfaces, name, []) - self._height = height - self._canopy = canopy - self._type = 'tree' - - @property - def height(self): - """ - Get height of tree in meters - :return: height - """ - return self._height - - @property - def canopy(self): - """ - Get canopy of tree - :return: canopy - """ - return self._canopy diff --git a/exports/exports/exports_factory.py b/exports/exports/exports_factory.py deleted file mode 100644 index 06d90099..00000000 --- a/exports/exports/exports_factory.py +++ /dev/null @@ -1,84 +0,0 @@ -""" -ExportsFactory export a city into several formats -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - -from pathlib import Path -from exports.formats.energy_ade import EnergyAde -from exports.formats.idf import Idf -from exports.formats.obj import Obj -from exports.formats.simplified_radiosity_algorithm import SimplifiedRadiosityAlgorithm -from exports.formats.stl import Stl - - -class ExportsFactory: - """ - Exports factory class - """ - def __init__(self, export_type, city, path): - self._city = city - self._export_type = '_' + export_type.lower() - self._path = path - - @property - def _citygml(self): - """ - Export to citygml_classes with application domain extensions - :return: None - """ - raise NotImplementedError - - @property - def _energy_ade(self): - """ - Export to citygml_classes with application domain extensions - :return: None - """ - return EnergyAde(self._city, self._path) - - @property - def _stl(self): - """ - Export the city geometry to stl - :return: None - """ - return Stl(self._city, self._path) - - @property - def _obj(self): - """ - Export the city geometry to obj - :return: None - """ - return Obj(self._city, self._path) - - @property - def _grounded_obj(self): - """ - Export the city geometry to obj - :return: None - """ - return Obj(self._city, self._path).to_ground_points() - - @property - def _idf(self): - """ - Export the city to Energy+ idf format - :return: - """ - idf_data_path = (Path(__file__).parent / './formats/idf_files/').resolve() - # todo: create a get epw file function based on the city - weather_path = (Path(__file__).parent / '../data/weather/epw/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw').resolve() - return Idf(self._city, self._path, (idf_data_path / 'Minimal.idf'), (idf_data_path / 'Energy+.idd'), weather_path) - - @property - def _sra(self): - return SimplifiedRadiosityAlgorithm(self._city, (self._path / f'{self._city.name}_sra.xml')) - - def export(self): - """ - Export the city model structure to the given export type - :return: None - """ - return getattr(self, self._export_type, lambda: None) diff --git a/exports/exports/formats/energy_ade.py b/exports/exports/formats/energy_ade.py deleted file mode 100644 index 60c10af2..00000000 --- a/exports/exports/formats/energy_ade.py +++ /dev/null @@ -1,378 +0,0 @@ -""" -ExportsFactory export a city into several formats -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -""" - -import uuid -import datetime -from pathlib import Path -import xmltodict -import helpers.constants as cte - - -class EnergyAde: - """ - Export the city to citygml + energy ade - """ - def __init__(self, city, path): - self._city = city - self._path = path - self._surface_members = None - self._export() - - def _export(self): - energy_ade = { - 'core:CityModel': { - '@xmlns:brid': 'http://www.opengis.net/citygml/bridge/2.0', - '@xmlns:tran': 'http://www.opengis.net/citygml/transportation/2.0', - '@xmlns:frn': 'http://www.opengis.net/citygml/cityfurniture/2.0', - '@xmlns:wtr': 'http://www.opengis.net/citygml/waterbody/2.0', - '@xmlns:sch': 'http://www.ascc.net/xml/schematron', - '@xmlns:veg': 'http://www.opengis.net/citygml/vegetation/2.0', - '@xmlns:xlink': 'http://www.w3.org/1999/xlink', - '@xmlns:tun': 'http://www.opengis.net/citygml/tunnel/2.0', - '@xmlns:tex': 'http://www.opengis.net/citygml/texturedsurface/2.0', - '@xmlns:gml': 'http://www.opengis.net/gml', - '@xmlns:genobj': 'http://www.opengis.net/citygml/generics/2.0', - '@xmlns:dem': 'http://www.opengis.net/citygml/relief/2.0', - '@xmlns:app': 'http://www.opengis.net/citygml/appearance/2.0', - '@xmlns:luse': 'http://www.opengis.net/citygml/landuse/2.0', - '@xmlns:xAL': 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0', - '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', - '@xmlns:smil20lang': 'http://www.w3.org/2001/SMIL20/Language', - '@xmlns:pbase': 'http://www.opengis.net/citygml/profiles/base/2.0', - '@xmlns:smil20': 'http://www.w3.org/2001/SMIL20/', - '@xmlns:bldg': 'http://www.opengis.net/citygml/building/2.0', - '@xmlns:energy': "http://www.sig3d.org/citygml/2.0/energy/1.0", - '@xmlns:core': 'http://www.opengis.net/citygml/2.0', - '@xmlns:grp': 'http://www.opengis.net/citygml/cityobjectgroup/2.0', - 'gml:boundedBy': { - 'gml:Envelope': { - '@srsName': self._city.srs_name, - '@srsDimension': 3, - 'gml:lowerCorner': ' '.join([str(e) for e in self._city.lower_corner]), - 'gml:upperCorner': ' '.join([str(e) for e in self._city.upper_corner]) - } - } - } - } - buildings = [] - for building in self._city.buildings: - building_dic = { - 'bldg:Building': { - '@gml:id': building.name, - 'gml:description': f'Building {building.name} at {self._city.name}', - 'gml:name': f'{building.name}', - 'core:creationDate': datetime.datetime.now().strftime('%Y-%m-%d') - } - } - building_dic = EnergyAde._measures(building, building_dic) - building_dic = self._building_geometry(building, building_dic, self._city) - building_dic['bldg:Building']['energy:volume'] = { - 'energy:VolumeType': { - 'energy:type': 'grossVolume', - 'energy:value': { - '@uom': 'm3', - 'energy:value': building.volume - } - } - } - building_dic['bldg:Building']['energy:referencePoint'] = { - 'gml:Point': { - '@srsName': self._city.srs_name, - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:Pos': f'{" ".join(map(str, building.centroid))}' - } - } - building_dic['bldg:Building']['energy:thermalZone'] = self._thermal_zones(building, self._city) - buildings.append(building_dic) - - energy_ade['core:CityModel']['core:cityObjectMember'] = buildings - - file_name = self._city.name + '_ade.gml' - file_path = Path(self._path / file_name).resolve() - with open(file_path, 'w') as file: - file.write(xmltodict.unparse(energy_ade, pretty=True, short_empty_elements=True)) - - @staticmethod - def _measures(building, building_dic): - # todo: this method is only for year and insel need to be generalized - measures = [] - measure = EnergyAde._measure(building.heating, cte.YEAR, 'Energy demand heating', 'INSEL') - if measure is not None: - measures.append(measure) - measure = EnergyAde._measure(building.cooling, cte.YEAR, 'Energy demand cooling', 'INSEL') - if measure is not None: - measures.append(measure) - if len(measures) != 0: - building_dic['bldg:Building']['genobj:measureAttribute'] = measures - - demands = [] - for key in building.heating: - if key != cte.YEAR: - demand = EnergyAde._demand(building.heating, key, 'Heating energy', 'INSEL') - demands.append(demand) - - for key in building.cooling: - if key != cte.YEAR: - demand = EnergyAde._demand(building.cooling, key, 'Cooling energy', 'INSEL') - demands.append(demand) - if len(demands) != 0: - building_dic['bldg:Building']['energy:demands'] = demands - - return building_dic - - @staticmethod - def _measure(measure_dict, key_value, name, source): - measure = None - if key_value in measure_dict: - measure = { - '@name': name, - 'genobj:value': { - '@uom': 'kWh', - '#text': ' '.join([str(e / 1000) for e in measure_dict[key_value][source]]) - } - } - return measure - - @staticmethod - def _demand(measure_dict, key_value, description, source): - demand = { - 'energy:EnergyDemand': { - '@gml:id': f'GML_{uuid.uuid4()}', - 'energy:energyAmount': { - 'energy:RegularTimeSeries': { - 'energy:variableProperties': { - 'energy:TimeValuesProperties': { - 'energy:acquisitionMethod': 'simulation', - 'energy:source': source, - 'energy:thematicDescription': description, - }, - 'energy:timeInterval': { - '@unit': key_value, - '#text': '1', - }, - 'energy:values': { - '@uom': 'kWh', - '#text': ' '.join([str(float(e) / 1000) for e in measure_dict[key_value][source]]) - } - } - } - }, - 'energy:endUse': 'spaceHeating' - } - } - return demand - - def _building_geometry(self, building, building_dic, city): - - building_dic['bldg:Building']['bldg:function'] = building.function - building_dic['bldg:Building']['bldg:usage'] = ', '.join([u.usage for u in building.usage_zones]) - building_dic['bldg:Building']['bldg:yearOfConstruction'] = building.year_of_construction - building_dic['bldg:Building']['bldg:roofType'] = building.roof_type - building_dic['bldg:Building']['bldg:measuredHeight'] = { - '@uom': 'm', - '#text': f'{building.max_height}' - } - building_dic['bldg:Building']['bldg:storeysAboveGround'] = building.storeys_above_ground - - if building.lod == 1: - building_dic = self._lod1(building, building_dic, city) - elif building.lod == 2: - building_dic = self._lod2(building, building_dic, city) - else: - raise NotImplementedError('Only lod 1 and 2 can be exported') - return building_dic - - def _lod1(self, building, building_dic, city): - raise NotImplementedError('Only lod 1 and 2 can be exported') - - def _lod2(self, building, building_dic, city): - self._surface_members = [] - boundaries = [{ - 'gml:Envelope': { - '@srsName': city.srs_name, - '@srsDimension': 3, - 'gml:lowerCorner': ' '.join([str(e) for e in city.lower_corner]), - 'gml:upperCorner': ' '.join([str(e) for e in city.upper_corner]) - }}] - for surface in building.surfaces: - surface_member = {'@xlink:href': f'#PolyId{surface.name}'} - self._surface_members.append(surface_member) - if surface.type == 'Wall': - surface_type = 'bldg:WallSurface' - elif surface.type == 'Ground': - surface_type = 'bldg:GroundSurface' - else: - surface_type = 'bldg:RoofSurface' - surface_dic = { - surface_type: { - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:name': f'{surface.name} ({surface.type})', - 'gml:boundedBy': { - 'gml:Envelope': { - '@srsName': city.srs_name, - 'gml:lowerCorner': f'{surface.lower_corner[0]} {surface.lower_corner[1]}' - f' {surface.lower_corner[2]}', - 'gml:upperCorner': f'{surface.upper_corner[0]} {surface.upper_corner[1]}' - f' {surface.upper_corner[2]}' - } - }, - 'bldg:lod2MultiSurface': { - 'gml:MultiSurface': { - '@srsName': city.srs_name, - '@gml:id': f'GML_{uuid.uuid4()}', - 'surfaceMember': { - 'gml:Polygon': { - '@srsName': city.srs_name, - '@gml:id': f'PolyId{surface.name}', - 'gml:exterior': { - 'gml:LinearRing': { - '@gml:id': f'PolyId{surface.name}_0', - 'gml:posList': { - '@srsDimension': '3', - '@count': len(surface.solid_polygon.coordinates) + 1, - '#text': f'{" ".join(map(str, surface.solid_polygon.points_list))} ' - f'{" ".join(map(str, surface.solid_polygon.coordinates[0]))}' - } - } - } - } - } - } - } - } - } - boundaries.append(surface_dic) - building_dic['bldg:Building']['bldg:lod2Solid'] = { - 'gml:Solid': { - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:exterior': { - 'gml:CompositeSurface': { - '@srsName': city.srs_name, - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:surfaceMember': self._surface_members - } - } - } - } - - building_dic['bldg:Building']['gml:boundedBy'] = boundaries - return building_dic - - def _thermal_zones(self, building, city): - thermal_zones = [] - for index, thermal_zone in enumerate(building.thermal_zones): - usage_zones = [] - for usage_zone in thermal_zone.usage_zones: - usage_zones.append({'@xlink:href': f'#GML_{usage_zone.id}'}) - thermal_zone_dic = { - 'energy:ThermalZone': { - '@gml:id': f'GML_{thermal_zone.id}', - 'gml:name': f'Thermal zone {index} in {building.name} building', - 'energy:contains': [], - 'energy:floorArea': { - 'energy:FloorArea': { - 'energy:type': 'grossFloorArea', - 'energy:value': { - '@uom': 'm2', - '#text': f'{thermal_zone.floor_area}' - } - } - }, - 'energy:volume': { - 'energy:VolumeType': { - 'energy:type': 'grossVolume', - 'energy:value': { - '@uom': 'm3', - # todo: for now we have just one thermal zone, therefore is the building volume, this need to be changed - '#text': f'{building.volume}' - } - } - }, - 'energy:isCooled': f'{thermal_zone.is_cooled}', - 'energy:isHeated': f'{thermal_zone.is_heated}', - 'energy:volumeGeometry': { - 'gml:Solid': { - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:exterior': { - 'gml:CompositeSurface': { - '@srsName': f'{city.srs_name}', - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:surfaceMember': self._surface_members - } - } - } - }, - 'energy:boundedBy': self._thermal_boundaries(city, thermal_zone) - } - } - thermal_zone_dic['energy:ThermalZone']['energy:contains'] = usage_zones - thermal_zones.append(thermal_zone_dic) - return thermal_zones - - def _thermal_boundaries(self, city, thermal_zone): - thermal_boundaries = [] - for thermal_boundary in thermal_zone.thermal_boundaries: - thermal_boundary_dic = { - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:name': f'{thermal_boundary.construction_name}', - 'energy:thermalBoundaryType': thermal_boundary.type, - 'energy:azumuth': { - '@uom': 'rad', - '#text': f'{thermal_boundary.azimuth}' - }, - 'energy:inclination': { - '@uom': 'rad', - '#text': f'{thermal_boundary.inclination}' - }, - 'energy:area': { - '@uom': 'm2', - '#text': f'{thermal_boundary.area}' - }, - 'energy:surfaceGeometry': { - 'gml:MultiSurface': { - '@srsName': city.srs_name, - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:surfaceMember': { - 'gml:Polygon': { - '@srsName': city.srs_name, - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:exterior': { - 'gml:LinearRing': { - '@gml:id': f'GML_{uuid.uuid4()}', - 'gml:posList': { - '@srsDimension': '3', - '@count': len(thermal_boundary.surface.solid_polygon.coordinates) + 1, - '#text': f'{" ".join(map(str, thermal_boundary.surface.solid_polygon.points_list))} ' - f'{" ".join(map(str, thermal_boundary.surface.solid_polygon.coordinates[0]))}' - } - } - } - } - } - } - } - } - construction = [] - opening_construction = [] - if thermal_boundary.layers is not None: - construction.append(uuid.uuid4()) - thermal_boundary_dic['energy:construction'] = { - '@xlink:href': f'#GML_{construction[0]}' - } - if thermal_boundary.thermal_openings is not None: - for opening in thermal_boundary.thermal_openings: - opening_construction.append(uuid.uuid4()) - thermal_boundary_dic['energy:contains'] = { - 'energy:ThermalOpening': { - '@gml:id': f'GML_{uuid.uuid4()}', - 'energy:construction': f'#GML_{opening_construction}', - 'energy:surfaceGeometry': { - - } - } - } - thermal_boundaries.append(thermal_boundary_dic) - return thermal_boundaries diff --git a/exports/exports/formats/idf.py b/exports/exports/formats/idf.py deleted file mode 100644 index b956367e..00000000 --- a/exports/exports/formats/idf.py +++ /dev/null @@ -1,278 +0,0 @@ -""" -TestOccupancyFactory test and validate the city model structure schedules parameters -SPDX - License - Identifier: LGPL - 3.0 - or -later -Copyright © 2020 Project Author Soroush Samareh Abolhassani - soroush.samarehabolhassani@mail.concordia.ca -""" -from geomeppy import IDF - - -class Idf: - """ - Export city to IDF - """ - _THERMOSTAT = 'HVACTEMPLATE:THERMOSTAT' - _IDEAL_LOAD_AIR_SYSTEM = 'HVACTEMPLATE:ZONE:IDEALLOADSAIRSYSTEM' - _SURFACE = 'BUILDINGSURFACE:DETAILED' - _CONSTRUCTION = 'CONSTRUCTION' - _MATERIAL = 'MATERIAL' - _MATERIAL_NOMASS = 'MATERIAL:NOMASS' - _ROUGHNESS = 'MediumRough' - _HOURLY_SCHEDULE = 'SCHEDULE:DAY:HOURLY' - _ZONE = 'ZONE' - _LIGHTS = 'LIGHTS' - _PEOPLE = 'PEOPLE' - _ELECTRIC_EQUIPMENT = 'ELECTRICEQUIPMENT' - _INFILTRATION = 'ZONEINFILTRATION:DESIGNFLOWRATE' - _BUILDING_SURFACE = 'BuildingSurfaceDetailed' - _SCHEDULE_LIMIT = 'SCHEDULETYPELIMITS' - _ON_OFF = 'On/Off' - _FRACTION = 'Fraction' - _ANY_NUMBER = 'Any Number' - _CONTINUOUS = 'CONTINUOUS' - _DISCRETE = 'DISCRETE' - - idf_surfaces = { - # todo: make an enum for all the surface types - 'Wall': 'wall', - 'Ground': 'floor', - 'Roof': 'roof' - } - idf_usage = { - # todo: make an enum for all the usage types - 'residential': 'residential_building' - } - - def __init__(self, city, output_path, idf_file_path, idd_file_path, epw_file_path, export_type="Surfaces"): - self._city = city - self._output_path = str((output_path / f'{city.name}.idf').resolve()) - self._export_type = export_type - self._idd_file_path = str(idd_file_path) - self._idf_file_path = str(idf_file_path) - self._epw_file_path = str(epw_file_path) - IDF.setiddname(self._idd_file_path) - self._idf = IDF(self._idf_file_path, self._epw_file_path) - self._idf.newidfobject(self._SCHEDULE_LIMIT, Name=self._ANY_NUMBER) - self._idf.newidfobject(self._SCHEDULE_LIMIT, Name=self._FRACTION, Lower_Limit_Value=0.0, Upper_Limit_Value=1.0, - Numeric_Type=self._CONTINUOUS) - self._idf.newidfobject(self._SCHEDULE_LIMIT, Name=self._ON_OFF, Lower_Limit_Value=0, Upper_Limit_Value=1, - Numeric_Type=self._DISCRETE) - self._export() - - @staticmethod - def _matrix_to_list(points): - points_list = [] - for point in points: - point_tuple = (point[0], point[1], point[2]) - points_list.append(point_tuple) - return points_list - - @staticmethod - def _matrix_to_2d_list(points): - points_list = [] - for point in points: - point_tuple = (point[0], point[1]) - points_list.append(point_tuple) - return points_list - - def _add_material(self, layer): - for material in self._idf.idfobjects[self._MATERIAL]: - if material.Name == layer.material.name: - return - for material in self._idf.idfobjects[self._MATERIAL_NOMASS]: - if material.Name == layer.material.name: - return - if layer.material.no_mass: - self._idf.newidfobject(self._MATERIAL_NOMASS, - Name=layer.material.name, - Roughness=self._ROUGHNESS, - Thermal_Resistance=layer.material.thermal_resistance, - Thermal_Absorptance=layer.material.thermal_absorptance, - Solar_Absorptance=layer.material.solar_absorptance, - Visible_Absorptance=layer.material.visible_absorptance - ) - else: - self._idf.newidfobject(self._MATERIAL, - Name=layer.material.name, - Roughness=self._ROUGHNESS, - Thickness=layer.thickness, - Conductivity=layer.material.conductivity, - Density=layer.material.density, - Specific_Heat=layer.material.specific_heat, - Thermal_Absorptance=layer.material.thermal_absorptance, - Solar_Absorptance=layer.material.solar_absorptance, - Visible_Absorptance=layer.material.visible_absorptance - ) - - def _add_schedule(self, usage_zone, schedule_type, limit_name='Any Number'): - for schedule in self._idf.idfobjects[self._HOURLY_SCHEDULE]: - if schedule.Name == f'{schedule_type} schedules {usage_zone.usage}': - return - if usage_zone.schedules is None or schedule_type not in usage_zone.schedules: - # there are no schedule for this type - return - schedule = self._idf.newidfobject(self._HOURLY_SCHEDULE, Name=f'{schedule_type} schedules {usage_zone.usage}') - schedule.Schedule_Type_Limits_Name = limit_name - - schedule.Hour_1 = usage_zone.schedules[schedule_type]["WD"][0] - schedule.Hour_2 = usage_zone.schedules[schedule_type]["WD"][1] - schedule.Hour_3 = usage_zone.schedules[schedule_type]["WD"][2] - schedule.Hour_4 = usage_zone.schedules[schedule_type]["WD"][3] - schedule.Hour_5 = usage_zone.schedules[schedule_type]["WD"][4] - schedule.Hour_6 = usage_zone.schedules[schedule_type]["WD"][5] - schedule.Hour_7 = usage_zone.schedules[schedule_type]["WD"][6] - schedule.Hour_8 = usage_zone.schedules[schedule_type]["WD"][7] - schedule.Hour_9 = usage_zone.schedules[schedule_type]["WD"][8] - schedule.Hour_10 = usage_zone.schedules[schedule_type]["WD"][9] - schedule.Hour_11 = usage_zone.schedules[schedule_type]["WD"][10] - schedule.Hour_12 = usage_zone.schedules[schedule_type]["WD"][11] - schedule.Hour_13 = usage_zone.schedules[schedule_type]["WD"][12] - schedule.Hour_14 = usage_zone.schedules[schedule_type]["WD"][13] - schedule.Hour_15 = usage_zone.schedules[schedule_type]["WD"][14] - schedule.Hour_16 = usage_zone.schedules[schedule_type]["WD"][15] - schedule.Hour_17 = usage_zone.schedules[schedule_type]["WD"][16] - schedule.Hour_18 = usage_zone.schedules[schedule_type]["WD"][17] - schedule.Hour_19 = usage_zone.schedules[schedule_type]["WD"][18] - schedule.Hour_20 = usage_zone.schedules[schedule_type]["WD"][19] - schedule.Hour_21 = usage_zone.schedules[schedule_type]["WD"][20] - schedule.Hour_22 = usage_zone.schedules[schedule_type]["WD"][21] - schedule.Hour_23 = usage_zone.schedules[schedule_type]["WD"][22] - schedule.Hour_24 = usage_zone.schedules[schedule_type]["WD"][23] - - def _add_construction(self, thermal_boundary): - for construction in self._idf.idfobjects[self._CONSTRUCTION]: - if construction.Name == thermal_boundary.construction_name: - return - - if thermal_boundary.layers is None: - for material in self._idf.idfobjects[self._MATERIAL]: - if material.Name == "DefaultMaterial": - return - self._idf.set_default_constructions() - return - for layer in thermal_boundary.layers: - self._add_material(layer) - layers = thermal_boundary.layers - # The constructions should have at least one layer - _kwargs = {"Name": thermal_boundary.construction_name, "Outside_Layer": layers[0].material.name} - for i in range(1, len(layers) - 1): - _kwargs[f'Layer_{i + 1}'] = layers[1].material.name - self._idf.newidfobject(self._CONSTRUCTION, **_kwargs) - - def _add_zone(self, usage_zone): - for zone in self._idf.idfobjects['ZONE']: - if zone.Name == usage_zone.id: - return - # todo: what does we need to define a zone in energy plus? - self._idf.newidfobject(self._ZONE, Name=usage_zone.id, Volume=usage_zone.volume) - self._add_heating_system(usage_zone) - - def _add_thermostat(self, usage_zone): - thermostat_name = f'Thermostat {usage_zone.usage}' - for thermostat in self._idf.idfobjects[self._THERMOSTAT]: - if thermostat.Name == thermostat_name: - return thermostat - return self._idf.newidfobject(self._THERMOSTAT, - Name=thermostat_name, - Constant_Heating_Setpoint=usage_zone.heating_setpoint, - Constant_Cooling_Setpoint=usage_zone.cooling_setpoint) - - def _add_heating_system(self, usage_zone): - for air_system in self._idf.idfobjects[self._IDEAL_LOAD_AIR_SYSTEM]: - if air_system.Zone_Name == usage_zone.id: - return - thermostat = self._add_thermostat(usage_zone) - self._idf.newidfobject(self._IDEAL_LOAD_AIR_SYSTEM, - Zone_Name=usage_zone.id, - Cooling_Availability_Schedule_Name=f'Refrigeration schedules {usage_zone.usage}', - Template_Thermostat_Name=thermostat.Name) - - def _add_occupancy(self, usage_zone): - self._idf.newidfobject(self._PEOPLE, - Name=f'{usage_zone.id}_occupancy', - Zone_or_ZoneList_Name=usage_zone.id, - Number_of_People_Schedule_Name=f'Occupancy schedules {usage_zone.usage}', - Number_of_People_Calculation_Method="People", - Number_of_People=500, # todo: get people from where? - Fraction_Radiant=0.3, # todo: howto get this from InternalGains - Activity_Level_Schedule_Name='occupant schedules' - ) - - def _add_equipment(self, usage_zone): - self._idf.newidfobject(self._ELECTRIC_EQUIPMENT, - Name=f'{usage_zone.id}_electricload', - Zone_or_ZoneList_Name=usage_zone.id, - Schedule_Name=f'Electrical schedules {usage_zone.usage}', # todo: add electrical schedules - Design_Level_Calculation_Method='EquipmentLevel', - Design_Level=566000 # todo: change it from usage catalog - ) - - def _add_infiltration(self, usage_zone): - for zone in self._idf.idfobjects["ZONE"]: - if zone.Name == f'{usage_zone.id}_infiltration': - return - self._idf.newidfobject(self._INFILTRATION, - Name=f'{usage_zone.id}_infiltration', - Zone_or_ZoneList_Name=usage_zone.id, - Schedule_Name=f'Infiltration schedules {usage_zone.usage}', - Design_Flow_Rate_Calculation_Method='AirChanges/Hour', - Air_Changes_per_Hour=0.35, # todo: change it from usage catalog - Constant_Term_Coefficient=0.606, # todo: change it from usage catalog - Temperature_Term_Coefficient=3.6359996E-02, # todo: change it from usage catalog - Velocity_Term_Coefficient=0.1177165, # todo: change it from usage catalog - Velocity_Squared_Term_Coefficient=0.0000000E+00 # todo: change it from usage catalog - ) - - def _export(self): - """ - Export the idf file into the given path - export type = "Surfaces|Block" - """ - for building in self._city.buildings: - for usage_zone in building.usage_zones: - self._add_schedule(usage_zone, "Infiltration") - self._add_schedule(usage_zone, "Lights") - self._add_schedule(usage_zone, "Occupancy") - self._add_schedule(usage_zone, "Refrigeration", self._ON_OFF) - - self._add_zone(usage_zone) - self._add_heating_system(usage_zone) - # self._add_infiltration(usage_zone) - # self._add_occupancy(usage_zone) - for thermal_zone in building.thermal_zones: - for thermal_boundary in thermal_zone.thermal_boundaries: - self._add_construction(thermal_boundary) - - if self._export_type == "Surfaces": - self._add_surfaces(building) - else: - self._add_block(building) - self._idf.match() - self._idf.saveas(str(self._output_path)) - - def _add_block(self, building): - _points = self._matrix_to_2d_list(building.foot_print.coordinates) - self._idf.add_block(name=building.name, coordinates=_points, height=building.max_height, - num_stories=int(building.storeys_above_ground)) - - for surface in self._idf.idfobjects[self._SURFACE]: - for thermal_zone in building.thermal_zones: - for boundary in thermal_zone.thermal_boundaries: - if surface.Type == self.idf_surfaces[boundary.surface.type]: - surface.Construction_Name = boundary.construction_name - break - for usage_zone in thermal_zone.usage_zones: - surface.Zone_Name = usage_zone.id - break - break - self._idf.intersect_match() - - def _add_surfaces(self, building): - for thermal_zone in building.thermal_zones: - for boundary in thermal_zone.thermal_boundaries: - idf_surface_type = self.idf_surfaces[boundary.surface.type] - for usage_zone in thermal_zone.usage_zones: - surface = self._idf.newidfobject(self._SURFACE, Name=f'{boundary.surface.name}', - Surface_Type=idf_surface_type, Zone_Name=usage_zone.id, - Construction_Name=boundary.construction_name) - coordinates = self._matrix_to_list(boundary.surface.solid_polygon.coordinates) - surface.setcoords(coordinates) diff --git a/exports/exports/formats/idf_files/Energy+.idd b/exports/exports/formats/idf_files/Energy+.idd deleted file mode 100644 index 12d2d762..00000000 --- a/exports/exports/formats/idf_files/Energy+.idd +++ /dev/null @@ -1,103532 +0,0 @@ -!IDD_Version 9.5.0 -!IDD_BUILD de239b2e5f -! ************************************************************************** -! This file is the Input Data Dictionary (IDD) for EnergyPlus. -! The IDD defines the syntax and data model for each type of input "Object." -! Lines in EnergyPlus input files (and IDD) are limited to 500 characters. -! -! Object Description -! ------------------ -! To define an object (a record with data), develop a key word that is unique -! Each data item to the object can be A (Alphanumeric string) or N (numeric) -! Number each A and N. This will show how the data items will be put into the -! arrays that are passed to the Input Processor "Get" (GetObjectItem) routines. -! All alpha fields are limited to 100 characters. Numeric fields should be -! valid numerics (can include such as 1.0E+05) and are placed into double -! precision variables. -! -! NOTE: Even though a field may be optional, a comma representing that field -! must be included (unless it is the last field in the object). Since the -! entire input is "field-oriented" and not "keyword-oriented", the EnergyPlus -! Input Processor must have some representation (even if blank) for each -! field. -! -! Object Documentation -! -------------------- -! In addition, the following special comments appear one per line and -! most are followed by a value. Comments may apply to a field or the object -! or a group of objects. -! -! Field-level comments: -! -! \field Name of field -! (should be succinct and readable, blanks are encouraged) -! -! \note Note describing the field and its valid values. If multiple lines, -! start each line with \note. Limit line length to 100 characters. -! -! \required-field To flag fields which must have a value. If the idf input is blank and -! there is a \default, then the default will be used. However, as of v8.6.0 -! the use of \required-field and \default on the same field is discouraged -! and instances with both have been changed. -! (this comment has no "value") -! -! \begin-extensible Marks the first field at which the object accepts an extensible -! field set. A fixed number of fields from this marker define the -! extensible field set, see the object code \extensible for -! more information. -! -! \units Units (must be from EnergyPlus standard units list) -! EnergyPlus units are standard SI units -! -! \ip-units IP-Units (for use by input processors with IP units) -! This is only used if the default conversion is not -! appropriate. -! -! \unitsBasedOnField For fields that may have multiple possible units, indicates -! the field in the object that can be used to determine -! the units. The field reference is in the A2 form. -! -! \minimum Minimum that includes the following value -! -! \minimum> Minimum that must be > than the following value -! -! \maximum Maximum that includes the following value -! -! \maximum< Maximum that must be < than the following value -! -! \default Default for the field (if N/A then omit entire line). If a default is -! added to an existing field, then \required-field should be removed if present. -! Defaults are filled in only if the field is within \min-fields, or the actual -! object is longer than this field. -! -! \deprecated This field is not really used and will be deleted from the object. -! The required information is gotten internally or -! not needed by the program. -! -! \autosizable Flag to indicate that this field can be used with the Auto -! Sizing routines to produce calculated results for the -! field. If a value follows this, then that will be used -! when the "Autosize" feature is flagged. To trigger -! autosizing for a field, enter Autosize as the field's -! value. Only applicable to numeric fields. -! -! \autocalculatable Flag to indicate that this field can be automatically -! calculated. To trigger auto calculation for a field, enter -! Autocalculate as the field's value. Only applicable to -! numeric fields. -! -! \type Type of data for the field - -! integer -! real -! alpha (arbitrary string), -! choice (alpha with specific list of choices, see -! \key) -! object-list (link to a list of objects defined elsewhere, -! see \object-list and \reference) -! external-list (uses a special list from an external source, -! see \external-list) -! node (name used in connecting HVAC components) -! -! \retaincase Retains the alphabetic case for alpha type fields -! -! \key Possible value for "\type choice" (blanks are significant) -! use multiple \key lines to indicate all valid choices -! -! \object-list Name of a list of user-provided object names that are valid -! entries for this field (used with "\reference") -! see Zone and BuildingSurface:Detailed objects below for -! examples. -! ** Note that a field may have multiple \object-list commands. -! -! \external-list The values for this field should be selected from a special -! list generated outside of the IDD file. The choices for the -! special lists are: -! autoRDDvariable -! autoRDDmeter -! autoRDDvariableMeter -! When one of these are selected the options for the field -! are taken from the RDD or MDD file or both. -! -! \reference Name of a list of names to which this object belongs -! used with "\type object-list" and with "\object-list" -! see Zone and BuildingSurface:Detailed objects below for -! examples: -! -! Zone, -! A1 , \field Name -! \type alpha -! \reference ZoneNames -! -! BuildingSurface:Detailed, -! A4 , \field Zone Name -! \note Zone the surface is a part of -! \type object-list -! \object-list ZoneNames -! -! For each zone, the field "Name" may be referenced -! by other objects, such as BuildingSurface:Detailed, so it is -! commented with "\reference ZoneNames" -! Fields that reference a zone name, such as BuildingSurface:Detailed's -! "Zone Name", are commented as -! "\type object-list" and "\object-list ZoneNames" -! ** Note that a field may have multiple \reference commands. -! ** This is useful if the object belongs to a small specific -! object-list as well as a larger more general object-list. -! -! Object-level comments: -! -! \memo Memo describing the object. If multiple lines, start each line -! with \memo. -! Limit line length to 100 characters. -! -! \unique-object To flag objects which should appear only once in an idf -! (this comment has no "value") -! -! \required-object To flag objects which are required in every idf -! (this comment has no "value") -! -! \min-fields Minimum number of fields that should be included in the -! object. If appropriate, the Input Processor will fill -! any missing fields with defaults (for numeric fields). -! It will also supply that number of fields to the "get" -! routines using blanks for alpha fields (note -- blanks -! may not be allowable for some alpha fields). -! -! \obsolete This object has been replaced though is kept (and is read) -! in the current version. Please refer to documentation as -! to the dispersal of the object. If this object is -! encountered in an IDF, the InputProcessor will post an -! appropriate message to the error file. -! usage: \obsolete New=>[New object name] -! -! \extensible:<#> This object is dynamically extensible -- meaning, if you -! change the IDD appropriately (if the object has a simple list -! structure -- just add items to the list arguments (i.e. BRANCH -! LIST). These will be automatically redimensioned and used during -! the simulation. <#> should be entered by the developer to signify -! how many of the last fields are needed to be extended (and EnergyPlus -! will attempt to auto-extend the object). The first field of the first -! instance of the extensible field set is marked with \begin-extensible. -! -! \begin-extensible See previous item, marks beginning of extensible fields in -! an object. -! -! \format The object should have a special format when saved in -! the IDF Editor with the special format option enabled. -! The options include SingleLine, Vertices, CompactSchedule, -! FluidProperties, ViewFactors, and Spectral. -! The SingleLine option puts all the fields for the object -! on a single line. The Vertices option is used in objects -! that use X, Y and Z fields to format those three fields -! on a single line. -! The CompactSchedule formats that specific object. -! The FluidProperty option formats long lists of fluid -! properties to ten values per line. -! The ViewFactor option formats three fields related to -! view factors per line. -! The Spectral option formats the four fields related to -! window glass spectral data per line. -! -! \reference-class-name Adds the name of the class to the reference list -! similar to \reference. -! -! Group-level comments: -! -! \group Name for a group of related objects -! -! -! Notes on comments -! ----------------- -! -! 1. If a particular comment is not applicable (such as units, or default) -! then simply omit the comment rather than indicating N/A. -! -! 2. Memos and notes should be brief (recommend 5 lines or less per block). -! More extensive explanations are expected to be in the user documentation -! -! Default IP conversions (no \ip-units necessary) -! $/(m3/s) => $/(ft3/min) 0.000472000059660808 -! $/(W/K) => $/(Btu/h-F) 0.52667614683731 -! $/kW => $/(kBtuh/h) 0.293083235638921 -! $/m2 => $/ft2 0.0928939733269818 -! $/m3 => $/ft3 0.0283127014102352 -! (kg/s)/W => (lbm/sec)/(Btu/hr) 0.646078115385742 -! 1/K => 1/F 0.555555555555556 -! 1/m => 1/ft 0.3048 -! A/K => A/F 0.555555555555556 -! C => F 1.8 (plus 32) -! cm => in 0.3937 -! cm2 => inch2 0.15500031000062 -! deltaC => deltaF 1.8 -! deltaC/hr => deltaF/hr 1.8 -! deltaJ/kg => deltaBtu/lb 0.0004299 -! g/GJ => lb/MWh 0.00793664091373665 -! g/kg => grains/lb 7 -! g/MJ => lb/MWh 7.93664091373665 -! g/mol => lb/mol 0.0022046 -! g/m-s => lb/ft-s 0.000671968949659 -! g/m-s-K => lb/ft-s-F 0.000373574867724868 -! GJ => ton-hrs 78.9889415481832 -! J => Wh 0.000277777777777778 -! J/K => Btu/F 526.565 -! J/kg => Btu/lb 0.00042986 (plus 7.686) -! J/kg-K => Btu/lb-F 0.000239005736137667 -! J/kg-K2 => Btu/lb-F2 0.000132889924714692 -! J/kg-K3 => Btu/lb-F3 7.38277359526066E-05 -! J/m2-K => Btu/ft2-F 4.89224766847393E-05 -! J/m3 => Btu/ft3 2.68096514745308E-05 -! J/m3-K => Btu/ft3-F 1.49237004739337E-05 -! K => R 1.8 -! K/m => F/ft 0.54861322767449 -! kg => lb 2.2046 -! kg/J => lb/Btu 2325.83774250441 -! kg/kg-K => lb/lb-F 0.555555555555556 -! kg/m => lb/ft 0.67196893069637 -! kg/m2 => lb/ft2 0.204794053596664 -! kg/m3 => lb/ft3 0.062428 -! kg/m-s => lb/ft-s 0.67196893069637 -! kg/m-s-K => lb/ft-s-F 0.373316072609094 -! kg/m-s-K2 => lb/ft-s-F2 0.207397818116164 -! kg/Pa-s-m2 => lb/psi-s-ft2 1412.00523459398 -! kg/s => lb/s 2.20462247603796 -! kg/s2 => lb/s2 2.2046 -! kg/s-m => lb/s-ft 0.67196893069637 -! kJ/kg => Btu/lb 0.429925 -! kPa => psi 0.145038 -! L/day => pint/day 2.11337629827348 -! L/GJ => gal/kWh 0.000951022349025202 -! L/kWh => pint/kWh 2.11337629827348 -! L/MJ => gal/kWh 0.951022349025202 -! lux => foot-candles 0.092902267 -! m => ft 3.28083989501312 -! m/hr => ft/hr 3.28083989501312 -! m/s => ft/min 196.850393700787 -! m/s => miles/hr 2.2369362920544 -! m/yr => inch/yr 39.3700787401575 -! m2 => ft2 10.7639104167097 -! m2/m => ft2/ft 3.28083989501312 -! m2/person => ft2/person 10.764961 -! m2/s => ft2/s 10.7639104167097 -! m2-K/W => ft2-F-hr/Btu 5.678263 -! m3 => ft3 35.3146667214886 -! m3 => gal 264.172037284185 -! m3/GJ => ft3/MWh 127.13292 -! m3/hr => ft3/hr 35.3146667214886 -! m3/hr-m2 => ft3/hr-ft2 3.28083989501312 -! m3/hr-person => ft3/hr-person 35.3146667214886 -! m3/kg => ft3/lb 16.018 -! m3/m2 => ft3/ft2 3.28083989501312 -! m3/MJ => ft3/kWh 127.13292 -! m3/person => ft3/person 35.3146667214886 -! m3/s => ft3/min 2118.88000328931 -! m3/s-m => ft3/min-ft 645.89 -! m3/s-m2 => ft3/min-ft2 196.85 -! m3/s-person => ft3/min-person 2118.6438 -! m3/s-W => (ft3/min)/(Btu/h) 621.099127332943 -! N-m => lbf-in 8.85074900525547 -! N-s/m2 => lbf-s/ft2 0.0208857913669065 -! Pa => psi 0.000145037743897283 -! percent/K => percent/F 0.555555555555556 -! person/m2 => person/ft2 0.0928939733269818 -! s/m => s/ft 0.3048 -! V/K => V/F 0.555555555555556 -! W => Btu/h 3.4121412858518 -! W/((m3/s)-Pa) => W/((gal/min)-ftH20) 0.188582274697355 -! W/((m3/s)-Pa) => W/((ft3/min)-inH2O) 0.117556910599482 -! W/(m3/s) => W/(ft3/min) 0.0004719475 -! W/K => Btu/h-F 1.89563404769544 -! W/m => Btu/h-ft 1.04072 -! W/m2 => Btu/h-ft2 0.316957210776545 -! W/m2 => W/ft2 0.09290304 -! W/m2-K => Btu/h-ft2-F 0.176110194261872 -! W/m2-K2 => Btu/h-ft2-F2 0.097826 -! W/m-K => Btu-in/h-ft2-F 6.93481276005548 -! W/m-K2 => Btu/h-F2-ft 0.321418310071648 -! W/m-K3 => Btu/h-F3-ft 0.178565727817582 -! W/person => Btu/h-person 3.4121412858518 -! -! Other conversions supported (needs the \ip-units code) -! -! kPa => inHg 0.29523 -! m => in 39.3700787401575 -! m3/hr => gal/hr 264.172037284185 -! m3/hr-m2 => gal/hr-ft2 24.5423853466941 -! m3/hr-person => gal/hr-person 264.172037284185 -! m3/m2 => gal/ft2 24.5423853466941 -! m3/person => gal/person 264.172037284185 -! m3/s => gal/min 15850.3222370511 -! m3/s-m => gal/min-ft 4831.17821785317 -! m3/s-W => (gal/min)/(Btu/h) 4645.27137336702 -! Pa => ftH2O 0.00033455 -! Pa => inH2O 0.00401463 -! Pa => inHg 0.00029613 -! Pa => Pa 1 -! W => W 1 -! W/(m3/s) => W/(gal/min) 0.0000630902 -! W/m2 => W/m2 1 -! W/m-K => Btu/h-ft-F 0.577796066000163 -! W/person => W/person 1 -! -! Units fields that are not translated -! $ -! 1/hr -! A -! A/V -! Ah -! Availability -! Control -! cycles/hr -! days -! deg -! dimensionless -! eV -! hh:mm -! hr -! J/J -! kg/kg -! kgWater/kgDryAir -! kmol -! kmol/s -! m3/m3 -! micron -! minutes -! Mode -! ms -! ohms -! percent -! ppm -! rev/min -! s -! V -! VA -! W/m2 or deg C -! W/m2, W or deg C -! W/s -! W/W -! years -! ************************************************************************** - -\group Simulation Parameters - -Version, - \memo Specifies the EnergyPlus version of the IDF file. - \unique-object - \format singleLine - A1 ; \field Version Identifier - \default 9.5 - -SimulationControl, - \unique-object - \memo Note that the following 3 fields are related to the Sizing:Zone, Sizing:System, - \memo and Sizing:Plant objects. Having these fields set to Yes but no corresponding - \memo Sizing object will not cause the sizing to be done. However, having any of these - \memo fields set to No, the corresponding Sizing object is ignored. - \memo Note also, if you want to do system sizing, you must also do zone sizing in the same - \memo run or an error will result. - \min-fields 7 - A1, \field Do Zone Sizing Calculation - \note If Yes, Zone sizing is accomplished from corresponding Sizing:Zone objects - \note and autosize fields. - \type choice - \key Yes - \key No - \default No - A2, \field Do System Sizing Calculation - \note If Yes, System sizing is accomplished from corresponding Sizing:System objects - \note and autosize fields. - \note If Yes, Zone sizing (previous field) must also be Yes. - \type choice - \key Yes - \key No - \default No - A3, \field Do Plant Sizing Calculation - \note If Yes, Plant sizing is accomplished from corresponding Sizing:Plant objects - \note and autosize fields. - \type choice - \key Yes - \key No - \default No - A4, \field Run Simulation for Sizing Periods - \note If Yes, SizingPeriod:* objects are executed and results from those may be displayed.. - \type choice - \key Yes - \key No - \default Yes - A5, \field Run Simulation for Weather File Run Periods - \note If Yes, RunPeriod:* objects are executed and results from those may be displayed.. - \type choice - \key Yes - \key No - \default Yes - A6, \field Do HVAC Sizing Simulation for Sizing Periods - \note If Yes, SizingPeriod:* objects are exectuted additional times for advanced sizing. - \note Currently limited to use with coincident plant sizing, see Sizing:Plant object - \type choice - \key Yes - \key No - \default No - N1; \field Maximum Number of HVAC Sizing Simulation Passes - \note the entire set of SizingPeriod:* objects may be repeated to fine tune size results - \note this input sets a limit on the number of passes that the sizing algorithms can repeate the set - \type integer - \minimum 1 - \default 1 - -PerformancePrecisionTradeoffs, - \unique-object - \memo This object enables users to choose certain options that speed up EnergyPlus simulation, - \memo but may lead to small decreases in accuracy of results. - A1, \field Use Coil Direct Solutions - \note If Yes, an analytical or empirical solution will be used to replace iterations in - \note the coil performance calculations. - \type choice - \key Yes - \key No - \default No - A2, \field Zone Radiant Exchange Algorithm - \note Determines which algorithm will be used to solve long wave radiant exchange among surfaces within a zone. - \type choice - \key ScriptF - \key CarrollMRT - \default ScriptF - A3, \field Override Mode - \note The increasing mode number roughly correspond with increased speed. A description of each mode - \note are shown in the documentation. When Advanced is selected the N1 field value is used. - \type choice - \key Normal - \key Mode01 - \key Mode02 - \key Mode03 - \key Mode04 - \key Mode05 - \key Mode06 - \key Mode07 - \key Advanced - \default Normal - N1, \field MaxZoneTempDiff - \note Maximum zone temperature change before HVAC timestep is shortened. - \note Only used when Override Mode is set to Advanced - \type real - \minimum 0.1 - \maximum 3.0 - \default 0.3 - N2; \field MaxAllowedDelTemp - \note Maximum surface temperature change before HVAC timestep is shortened. - \note Only used when Override Mode is set to Advanced - \type real - \minimum 0.002 - \maximum 0.1 - \default 0.002 - -Building, - \memo Describes parameters that are used during the simulation - \memo of the building. There are necessary correlations between the entries for - \memo this object and some entries in the Site:WeatherStation and - \memo Site:HeightVariation objects, specifically the Terrain field. - \unique-object - \required-object - \min-fields 8 - A1 , \field Name - \retaincase - \default NONE - N1 , \field North Axis - \note degrees from true North - \units deg - \type real - \default 0.0 - A2 , \field Terrain - \note Country=FlatOpenCountry | Suburbs=CountryTownsSuburbs | City=CityCenter | Ocean=body of water (5km) | Urban=Urban-Industrial-Forest - \type choice - \key Country - \key Suburbs - \key City - \key Ocean - \key Urban - \default Suburbs - N2 , \field Loads Convergence Tolerance Value - \note Loads Convergence Tolerance Value is a change in load from one warmup day to the next - \type real - \minimum> 0.0 - \maximum .5 - \default .04 - \units W - N3 , \field Temperature Convergence Tolerance Value - \units deltaC - \type real - \minimum> 0.0 - \maximum .5 - \default .4 - A3 , \field Solar Distribution - \note MinimalShadowing | FullExterior | FullInteriorAndExterior | FullExteriorWithReflections | FullInteriorAndExteriorWithReflections - \type choice - \key MinimalShadowing - \key FullExterior - \key FullInteriorAndExterior - \key FullExteriorWithReflections - \key FullInteriorAndExteriorWithReflections - \default FullExterior - N4 , \field Maximum Number of Warmup Days - \note EnergyPlus will only use as many warmup days as needed to reach convergence tolerance. - \note This field's value should NOT be set less than 25. - \type integer - \minimum> 0 - \default 25 - N5 ; \field Minimum Number of Warmup Days - \note The minimum number of warmup days that produce enough temperature and flux history - \note to start EnergyPlus simulation for all reference buildings was suggested to be 6. - \note However this can lead to excessive run times as warmup days can be repeated needlessly. - \note For faster execution rely on the convergence criteria to detect when warmup is complete. - \note When this field is greater than the maximum warmup days defined previous field - \note the maximum number of warmup days will be reset to the minimum value entered here. - \note Warmup days will be set to be the value you entered. The default is 1. - \type integer - \minimum> 0 - \default 1 - -ShadowCalculation, - \unique-object - \memo This object is used to control details of the solar, shading, and daylighting models - \extensible:1 - A1 , \field Shading Calculation Method - \note Select between CPU-based polygon clipping method, the GPU-based pixel counting method, - \note or importing from external shading data. - \note If PixelCounting is selected and GPU hardware (or GPU emulation) is not available, a warning will be - \note displayed and EnergyPlus will revert to PolygonClipping. - \note If Scheduled is chosen, the External Shading Fraction Schedule Name is required - \note in SurfaceProperty:LocalEnvironment. - \note If Imported is chosen, the Schedule:File:Shading object is required. - \type choice - \key PolygonClipping - \key PixelCounting - \key Scheduled - \key Imported - \default PolygonClipping - A2 , \field Shading Calculation Update Frequency Method - \note choose calculation frequency method. note that Timestep is only needed for certain cases - \note and can increase execution time significantly. - \type choice - \key Periodic - \key Timestep - \default Periodic - N1 , \field Shading Calculation Update Frequency - \type integer - \minimum 1 - \default 20 - \note enter number of days - \note this field is only used if the previous field is set to Periodic - \note warning issued if >31 - N2 , \field Maximum Figures in Shadow Overlap Calculations - \note Number of allowable figures in shadow overlap in PolygonClipping calculations - \type integer - \minimum 200 - \default 15000 - A3 , \field Polygon Clipping Algorithm - \note Advanced Feature. Internal default is SutherlandHodgman - \note Refer to InputOutput Reference and Engineering Reference for more information - \type choice - \key ConvexWeilerAtherton - \key SutherlandHodgman - \key SlaterBarskyandSutherlandHodgman - \default SutherlandHodgman - N3 , \field Pixel Counting Resolution - \note Number of pixels in both dimensions of the surface rendering - \type integer - \default 512 - A4 , \field Sky Diffuse Modeling Algorithm - \note Advanced Feature. Internal default is SimpleSkyDiffuseModeling - \note If you have shading elements that change transmittance over the - \note year, you may wish to choose the detailed method. - \note Refer to InputOutput Reference and Engineering Reference for more information - \type choice - \key SimpleSkyDiffuseModeling - \key DetailedSkyDiffuseModeling - \default SimpleSkyDiffuseModeling - A5 , \field Output External Shading Calculation Results - \type choice - \key Yes - \key No - \default No - \note If Yes is chosen, the calculated external shading fraction results will be saved to an external CSV file with surface names as the column headers. - A6 , \field Disable Self-Shading Within Shading Zone Groups - \note If Yes, self-shading will be disabled from all exterior surfaces in a given Shading Zone Group to surfaces within - \note the same Shading Zone Group. - \note If both Disable Self-Shading Within Shading Zone Groups and Disable Self-Shading From Shading Zone Groups to Other Zones = Yes, - \note then all self-shading from exterior surfaces will be disabled. - \note If only one of these fields = Yes, then at least one Shading Zone Group must be specified, or this field will be ignored. - \note Shading from Shading:* surfaces, overhangs, fins, and reveals will not be disabled. - \type choice - \key Yes - \key No - \default No - A7 , \field Disable Self-Shading From Shading Zone Groups to Other Zones - \note If Yes, self-shading will be disabled from all exterior surfaces in a given Shading Zone Group to all other zones in the model. - \note If both Disable Self-Shading Within Shading Zone Groups and Disable Self-Shading From Shading Zone Groups to Other Zones = Yes, - \note then all self-shading from exterior surfaces will be disabled. - \note If only one of these fields = Yes, then at least one Shading Zone Group must be specified, or this field will be ignored. - \note Shading from Shading:* surfaces, overhangs, fins, and reveals will not be disabled. - \type choice - \key Yes - \key No - \default No - A8 , \field Shading Zone Group 1 ZoneList Name - \note Specifies a group of zones which are controlled by the Disable Self-Shading fields. - \type object-list - \object-list ZoneListNames - \begin-extensible - A9 , \field Shading Zone Group 2 ZoneList Name - \type object-list - \object-list ZoneListNames - A10, \field Shading Zone Group 3 ZoneList Name - \type object-list - \object-list ZoneListNames - A11, \field Shading Zone Group 4 ZoneList Name - \type object-list - \object-list ZoneListNames - A12, \field Shading Zone Group 5 ZoneList Name - \type object-list - \object-list ZoneListNames - A13; \field Shading Zone Group 6 ZoneList Name - \type object-list - \object-list ZoneListNames - -SurfaceConvectionAlgorithm:Inside, - \memo Default indoor surface heat transfer convection algorithm to be used for all zones - \unique-object - \format singleLine - A1 ; \field Algorithm - \type choice - \key Simple - \key TARP - \key CeilingDiffuser - \key AdaptiveConvectionAlgorithm - \key ASTMC1340 - \default TARP - \note Simple = constant value natural convection (ASHRAE) - \note TARP = variable natural convection based on temperature difference (ASHRAE, Walton) - \note CeilingDiffuser = ACH-based forced and mixed convection correlations - \note for ceiling diffuser configuration with simple natural convection limit - \note AdaptiveConvectionAlgorithm = dynamic selection of convection models based on conditions - \note ASTMC1340 = mixed convection correlations based on heat flow direction, - \note surface tilt angle, surface characteristic length, and air speed past the surface. - -SurfaceConvectionAlgorithm:Outside, - \memo Default outside surface heat transfer convection algorithm to be used for all zones - \unique-object - \format singleLine - A1 ; \field Algorithm - \type choice - \key SimpleCombined - \key TARP - \key MoWiTT - \key DOE-2 - \key AdaptiveConvectionAlgorithm - \default DOE-2 - \note SimpleCombined = Combined radiation and convection coefficient using simple ASHRAE model - \note TARP = correlation from models developed by ASHRAE, Walton, and Sparrow et. al. - \note MoWiTT = correlation from measurements by Klems and Yazdanian for smooth surfaces - \note DOE-2 = correlation from measurements by Klems and Yazdanian for rough surfaces - \note AdaptiveConvectionAlgorithm = dynamic selection of correlations based on conditions - -HeatBalanceAlgorithm, - \memo Determines which Heat Balance Algorithm will be used ie. - \memo CTF (Conduction Transfer Functions), - \memo EMPD (Effective Moisture Penetration Depth with Conduction Transfer Functions). - \memo Advanced/Research Usage: CondFD (Conduction Finite Difference) - \memo Advanced/Research Usage: ConductionFiniteDifferenceSimplified - \memo Advanced/Research Usage: HAMT (Combined Heat And Moisture Finite Element) - \unique-object - \format singleLine - A1 , \field Algorithm - \type choice - \key ConductionTransferFunction - \key MoisturePenetrationDepthConductionTransferFunction - \key ConductionFiniteDifference - \key CombinedHeatAndMoistureFiniteElement - \default ConductionTransferFunction - N1 , \field Surface Temperature Upper Limit - \type real - \minimum 200 - \default 200 - \units C - N2 , \field Minimum Surface Convection Heat Transfer Coefficient Value - \units W/m2-K - \default 0.1 - \minimum> 0.0 - N3 ; \field Maximum Surface Convection Heat Transfer Coefficient Value - \units W/m2-K - \default 1000 - \minimum 1.0 - -HeatBalanceSettings:ConductionFiniteDifference, - \memo Determines settings for the Conduction Finite Difference - \memo algorithm for surface heat transfer modeling. - \unique-object - A1 , \field Difference Scheme - \type choice - \key CrankNicholsonSecondOrder - \key FullyImplicitFirstOrder - \default FullyImplicitFirstOrder - N1 , \field Space Discretization Constant - \note increase or decrease number of nodes - \type real - \default 3 - N2 , \field Relaxation Factor - \type real - \default 1.0 - \minimum 0.01 - \maximum 1.0 - N3 ; \field Inside Face Surface Temperature Convergence Criteria - \type real - \default 0.002 - \minimum 1.0E-7 - \maximum 0.01 - -ZoneAirHeatBalanceAlgorithm, - \memo Determines which algorithm will be used to solve the zone air heat balance. - \unique-object - \format singleLine - \min-fields 1 - A1 ; \field Algorithm - \type choice - \key ThirdOrderBackwardDifference - \key AnalyticalSolution - \key EulerMethod - \default ThirdOrderBackwardDifference - -ZoneAirContaminantBalance, - \memo Determines which contaminant concentration will be simulates. - \unique-object - \format singleLine - A1 , \field Carbon Dioxide Concentration - \note If Yes, CO2 simulation will be performed. - \type choice - \key Yes - \key No - \default No - A2 , \field Outdoor Carbon Dioxide Schedule Name - \note Schedule values should be in parts per million (ppm) - \type object-list - \object-list ScheduleNames - A3 , \field Generic Contaminant Concentration - \note If Yes, generic contaminant simulation will be performed. - \type choice - \key Yes - \key No - \default No - A4 ; \field Outdoor Generic Contaminant Schedule Name - \note Schedule values should be generic contaminant concentration in parts per - \note million (ppm) - \type object-list - \object-list ScheduleNames - -ZoneAirMassFlowConservation, - \memo Enforces the zone air mass flow balance by either adjusting zone mixing object flow only, - \memo adjusting zone total return flow only, zone mixing and the zone total return flows, - \memo or adjusting the zone total return and zone mixing object flows. Zone infiltration flow air - \memo flow is increased or decreased depending user selection in the infiltration treatment method. - \memo If either of zone mixing or zone return flow adjusting methods or infiltration is active, - \memo then the zone air mass flow balance calculation will attempt to enforce conservation of - \memo mass for each zone. If flow balancing method is "None" and infiltration is "None", then the - \memo zone air mass flow calculation defaults to assume self-balanced simple flow mixing and - \memo infiltration objects. - \unique-object - \min-fields 3 - A1, \field Adjust Zone Mixing and Return For Air Mass Flow Balance - \note If "AdjustMixingOnly", zone mixing object flow rates are adjusted to balance the zone air mass - \note flow and zone infiltration air flow may be increased or decreased if required in order to balance - \note the zone air mass flow. If "AdjustReturnOnly", zone total return flow rate is adjusted to balance - \note the zone air mass flow and zone infiltration air flow may be increased or decreased if required - \note in order to balance the zone air mass flow. If "AdjustMixingThenReturn", first the zone mixing - \note objects flow rates are adjusted to balance the zone air flow, second zone total return flow rate - \note is adjusted and zone infiltration air flow may be increased or decreased if required in order to - \note balance the zone air mass flow. If "AdjustReturnThenMixing", first zone total return flow rate is - \note adjusted to balance the zone air flow, second the zone mixing object flow rates are adjusted and - \note infiltration air flow may be increased or decreased if required in order to balance the zone - \note air mass flow. - \type choice - \key AdjustMixingOnly - \key AdjustReturnOnly - \key AdjustMixingThenReturn - \key AdjustReturnThenMixing - \key None - \default None - A2, \field Infiltration Balancing Method - \note This input field allows user to choose how zone infiltration flow is treated during - \note the zone air mass flow balance calculation. - \type choice - \key AddInfiltrationFlow - \key AdjustInfiltrationFlow - \key None - \default AddInfiltrationFlow - \note AddInfiltrationFlow may add infiltration to the base flow specified in the - \note infiltration object to balance the zone air mass flow. The additional infiltration - \note air mass flow is not self-balanced. The base flow is assumed to be self-balanced. - \note AdjustInfiltrationFlow may adjust the base flow calculated using - \note the base flow specified in the infiltration object to balance the zone air mass flow. If it - \note If no adjustment is required, then the base infiltration is assumed to be self-balanced. - \note None will make no changes to the base infiltration flow. - A3; \field Infiltration Balancing Zones - \note This input field allows user to choose which zones are included in infiltration balancing. - \note MixingSourceZonesOnly allows infiltration balancing only in zones which as source zones for mixing - \note which also have an infiltration object defined. - \note AllZones allows infiltration balancing in any zone which has an infiltration object defined. - \type choice - \key MixingSourceZonesOnly - \key AllZones - \default MixingSourceZonesOnly - -ZoneCapacitanceMultiplier:ResearchSpecial, - \format singleLine - \memo Multiplier altering the relative capacitance of the air compared to an empty zone - \min-fields 6 - A1 , \field Name - \required-field - \type alpha - A2 , \field Zone or ZoneList Name - \type object-list - \object-list ZoneAndZoneListNames - \note If this field is left blank, the multipliers are applied to all the zones not specified - N1 , \field Temperature Capacity Multiplier - \type real - \default 1.0 - \minimum> 0.0 - \note Used to alter the capacitance of zone air with respect to heat or temperature - N2 , \field Humidity Capacity Multiplier - \type real - \default 1.0 - \minimum> 0.0 - \note Used to alter the capacitance of zone air with respect to moisture or humidity ratio - N3 , \field Carbon Dioxide Capacity Multiplier - \type real - \default 1.0 - \minimum> 0.0 - \note Used to alter the capacitance of zone air with respect to zone air carbon dioxide concentration - N4 ; \field Generic Contaminant Capacity Multiplier - \type real - \default 1.0 - \minimum> 0.0 - \note Used to alter the capacitance of zone air with respect to zone air generic contaminant concentration - -Timestep, - \memo Specifies the "basic" timestep for the simulation. The - \memo value entered here is also known as the Zone Timestep. This is used in - \memo the Zone Heat Balance Model calculation as the driving timestep for heat - \memo transfer and load calculations. - \unique-object - \format singleLine - N1 ; \field Number of Timesteps per Hour - \note Number in hour: normal validity 4 to 60: 6 suggested - \note Must be evenly divisible into 60 - \note Allowable values include 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, and 60 - \note Normal 6 is minimum as lower values may cause inaccuracies - \note A minimum value of 20 is suggested for both ConductionFiniteDifference - \note and CombinedHeatAndMoistureFiniteElement surface heat balance algorithms - \note A minimum of 12 is suggested for simulations involving a Vegetated Roof (Material:RoofVegetation). - \default 6 - \type integer - \minimum 1 - \maximum 60 - -ConvergenceLimits, - \memo Specifies limits on HVAC system simulation timesteps and iterations. - \memo This item is an advanced feature that should be used only with caution. - \unique-object - N1 , \field Minimum System Timestep - \units minutes - \type integer - \note 0 sets the minimum to the zone timestep (ref: Timestep) - \note 1 is normal (ratchet down to 1 minute) - \note setting greater than zone timestep (in minutes) will effectively set to zone timestep - \minimum 0 - \maximum 60 - N2 , \field Maximum HVAC Iterations - \type integer - \default 20 - \minimum 1 - N3 , \field Minimum Plant Iterations - \note Controls the minimum number of plant system solver iterations within a single HVAC iteration - \note Larger values will increase runtime but might improve solution accuracy for complicated plant systems - \note Complex plants include: several interconnected loops, heat recovery, thermal load following generators, etc. - \type integer - \default 2 - \minimum 1 - N4 ; \field Maximum Plant Iterations - \note Controls the maximum number of plant system solver iterations within a single HVAC iteration - \note Smaller values might decrease runtime but could decrease solution accuracy for complicated plant systems - \type integer - \default 8 - \minimum 2 - -HVACSystemRootFindingAlgorithm, - \memo Specifies a HVAC system solver algorithm to find a root - \unique-object - A1 , \field Algorithm - \type choice - \key RegulaFalsi - \key Bisection - \key BisectionThenRegulaFalsi - \key RegulaFalsiThenBisection - \key Alternation - \default RegulaFalsi - N1 ; \field Number of Iterations Before Algorithm Switch - \note This field is used when RegulaFalsiThenBisection or BisectionThenRegulaFalsi is - \note entered. When iteration number is greater than the value, algorithm switches. - \type integer - \default 5 - -\group Compliance Objects - -Compliance:Building, - \memo Building level inputs related to compliance to building standards, building codes, and beyond energy code programs. - \unique-object - \min-fields 1 - N1; \field Building Rotation for Appendix G - \note Additional degrees of rotation to be used with the requirement in ASHRAE Standard 90.1 Appendix G - \note that states that the baseline building should be rotated in four directions. - \units deg - \type real - \default 0.0 - -\group Location and Climate - -Site:Location, - \memo Specifies the building's location. Only one location is allowed. - \memo Weather data file location, if it exists, will override this object. - \unique-object - \min-fields 5 - A1 , \field Name - \required-field - \type alpha - N1 , \field Latitude - \units deg - \minimum -90.0 - \maximum +90.0 - \default 0.0 - \note + is North, - is South, degree minutes represented in decimal (i.e. 30 minutes is .5) - \type real - N2 , \field Longitude - \units deg - \minimum -180.0 - \maximum +180.0 - \default 0.0 - \note - is West, + is East, degree minutes represented in decimal (i.e. 30 minutes is .5) - \type real - N3 , \field Time Zone - \note basic these limits on the WorldTimeZone Map (2003) - \units hr - \minimum -12.0 - \maximum +14.0 - \default 0.0 - \note Time relative to GMT. Decimal hours. - \type real - N4 ; \field Elevation - \units m - \minimum -300.0 - \maximum< 8900.0 - \default 0.0 - \type real - -Site:VariableLocation, - \memo Captures the scheduling of a moving/reorienting building, or more likely a vessel - \unique-object - \min-fields 1 - A1 , \field Name - \required-field - \type alpha - A2 , \field Building Location Latitude Schedule - \note The name of a schedule that defines the latitude of the building at any time. - \note If not entered, the latitude defined in the Site:Location, or the default - \note latitude, will be used for the entirety of the simulation - \type object-list - \object-list ScheduleNames - A3 , \field Building Location Longitude Schedule - \note The name of a schedule that defines the longitude of the building at any time. - \note If not entered, the longitude defined in the Site:Location, or the default - \note longitude, will be used for the entirety of the simulation - \type object-list - \object-list ScheduleNames - A4 ; \field Building Location Orientation Schedule - \note The name of a schedule that defines the orientation of the building at any time. - \note This orientation is based on a change from the original orientation. -- NEED TO REFINE THIS - \note If not entered, the original orientation will be used for the entirety of the simulation - \type object-list - \object-list ScheduleNames - -SizingPeriod:DesignDay, - \memo The design day object creates the parameters for the program to create - \memo the 24 hour weather profile that can be used for sizing as well as - \memo running to test the other simulation parameters. Parameters in this - \memo include a date (month and day), a day type (which uses the appropriate - \memo schedules for either sizing or simple tests), min/max temperatures, - \memo wind speeds, and solar radiation values. - A1, \field Name - \type alpha - \required-field - \reference RunPeriodsAndDesignDays - N1, \field Month - \required-field - \minimum 1 - \maximum 12 - \type integer - N2, \field Day of Month - \required-field - \minimum 1 - \maximum 31 - \type integer - \note must be valid for Month field - A2, \field Day Type - \required-field - \note Day Type selects the schedules appropriate for this design day - \type choice - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - N3, \field Maximum Dry-Bulb Temperature - \note This field is required when field "Dry-Bulb Temperature Range Modifier Type" - \note is not "TemperatureProfileSchedule". - \units C - \minimum -90 - \maximum 70 - \type real - N4, \field Daily Dry-Bulb Temperature Range - \note Must still produce appropriate maximum dry-bulb (within range) - \note This field is not needed if Dry-Bulb Temperature Range Modifier Type - \note is "delta". - \units deltaC - \minimum 0 - \default 0 - \type real - A3, \field Dry-Bulb Temperature Range Modifier Type - \note Type of modifier to the dry-bulb temperature calculated for the timestep - \type choice - \key MultiplierSchedule - \key DifferenceSchedule - \key TemperatureProfileSchedule - \key DefaultMultipliers - \default DefaultMultipliers - A4, \field Dry-Bulb Temperature Range Modifier Day Schedule Name - \type object-list - \object-list DayScheduleNames - \note Only used when previous field is "MultiplierSchedule", "DifferenceSchedule" or - \note "TemperatureProfileSchedule". - \note For type "MultiplierSchedule" the hour/time interval values should specify - \note the fraction (0-1) of the dry-bulb temperature range to be subtracted - \note from the maximum dry-bulb temperature for each timestep in the day - \note For type "DifferenceSchedule" the values should specify a number to be subtracted - \note from the maximum dry-bulb temperature for each timestep in the day. - \note Note that numbers in the difference schedule cannot be negative as that - \note would result in a higher maximum than the maximum previously specified. - \note For type "TemperatureProfileSchedule" the values should specify the actual dry-bulb - \note temperature for each timestep in the day. - A5, \field Humidity Condition Type - \note values/schedules indicated here and in subsequent fields create the humidity - \note values in the 24 hour design day conditions profile. - \type choice - \key WetBulb - \key DewPoint - \key HumidityRatio - \key Enthalpy - \key RelativeHumiditySchedule - \key WetBulbProfileMultiplierSchedule - \key WetBulbProfileDifferenceSchedule - \key WetBulbProfileDefaultMultipliers - \default WetBulb - N5, \field Wetbulb or DewPoint at Maximum Dry-Bulb - \note Wetbulb or dewpoint temperature coincident with the maximum temperature. - \note Required only if field Humidity Condition Type is "Wetbulb", "Dewpoint", - \note "WetBulbProfileMultiplierSchedule", "WetBulbProfileDifferenceSchedule", - \note or "WetBulbProfileDefaultMultipliers" - \type real - \units C - A6, \field Humidity Condition Day Schedule Name - \type object-list - \object-list DayScheduleNames - \note Only used when Humidity Condition Type is "RelativeHumiditySchedule", - \note "WetBulbProfileMultiplierSchedule", or "WetBulbProfileDifferenceSchedule" - \note For type "RelativeHumiditySchedule", the hour/time interval values should specify - \note relative humidity (percent) from 0.0 to 100.0. - \note For type "WetBulbProfileMultiplierSchedule" the hour/time interval values should specify - \note the fraction (0-1) of the wet-bulb temperature range to be subtracted from the - \note maximum wet-bulb temperature for each timestep in the day (units = Fraction) - \note For type "WetBulbProfileDifferenceSchedule" the values should specify a number to be subtracted - \note from the maximum wet-bulb temperature for each timestep in the day. (units = deltaC) - N6, \field Humidity Ratio at Maximum Dry-Bulb - \note Humidity ratio coincident with the maximum temperature (constant humidity ratio throughout day). - \note Required only if field Humidity Condition Type is "HumidityRatio". - \type real - \units kgWater/kgDryAir - N7, \field Enthalpy at Maximum Dry-Bulb - \note Enthalpy coincident with the maximum temperature. - \note Required only if field Humidity Condition Type is "Enthalpy". - \type real - \units J/kg - N8, \field Daily Wet-Bulb Temperature Range - \units deltaC - \note Required only if Humidity Condition Type = "WetbulbProfileMultiplierSchedule" or - \note "WetBulbProfileDefaultMultipliers" - N9, \field Barometric Pressure - \note This field's value is also checked against the calculated "standard barometric pressure" - \note for the location. If out of range (>10%) or blank, then is replaced by standard value. - \units Pa - \minimum 31000 - \maximum 120000 - \type real - \ip-units inHg - N10, \field Wind Speed - \required-field - \units m/s - \minimum 0 - \maximum 40 - \ip-units miles/hr - \type real - N11, \field Wind Direction - \required-field - \units deg - \minimum 0 - \maximum 360 - \note North=0.0 East=90.0 - \note 0 and 360 are the same direction. - \type real - A7, \field Rain Indicator - \note Yes is raining (all day), No is not raining - \type choice - \key Yes - \key No - \default No - A8, \field Snow Indicator - \type choice - \key Yes - \key No - \default No - \note Yes is Snow on Ground, No is no Snow on Ground - A9, \field Daylight Saving Time Indicator - \note Yes -- use schedules modified for Daylight Saving Time Schedules. - \note No - do not use schedules modified for Daylight Saving Time Schedules - \type choice - \key Yes - \key No - \default No - A10, \field Solar Model Indicator - \type choice - \key ASHRAEClearSky - \key ZhangHuang - \key Schedule - \key ASHRAETau - \key ASHRAETau2017 - \default ASHRAEClearSky - A11, \field Beam Solar Day Schedule Name - \note if Solar Model Indicator = Schedule, then beam schedule name (for day) - \type object-list - \object-list DayScheduleNames - A12, \field Diffuse Solar Day Schedule Name - \note if Solar Model Indicator = Schedule, then diffuse schedule name (for day) - \type object-list - \object-list DayScheduleNames - N12, \field ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) - \units dimensionless - \note Required if Solar Model Indicator = ASHRAETau or ASHRAETau2017 - \note ASHRAETau2017 solar model can be used with 2013 and 2017 HOF matching taub - \minimum 0 - \maximum 1.2 - \default 0 - N13, \field ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) - \units dimensionless - \note Required if Solar Model Indicator = ASHRAETau or ASHRAETau2017 - \note ASHRAETau2017 solar model can be used with 2013 and 2017 HOF matching taud - \minimum 0 - \maximum 3 - \default 0 - N14, \field Sky Clearness - \note Used if Sky Model Indicator = ASHRAEClearSky or ZhangHuang - \minimum 0.0 - \maximum 1.2 - \default 0.0 - \note 0.0 is totally unclear, 1.0 is totally clear - \type real - N15, \field Maximum Number Warmup Days - \note If used this design day will be run with a custom limit on the maximum number of days that are repeated for warmup. - \note Limiting the number of warmup days can improve run time. - \type integer - A13; \field Begin Environment Reset Mode - \note If used this can control if you want the thermal history to be reset at the beginning of the design day. - \note When using a series of similiar design days, this field can be used to retain warmup state from the previous design day. - \type choice - \key FullResetAtBeginEnvironment - \key SuppressAllBeginEnvironmentResets - \default FullResetAtBeginEnvironment - -SizingPeriod:WeatherFileDays, - \memo Use a weather file period for design sizing calculations. - A1 , \field Name - \reference RunPeriodsAndDesignDays - \required-field - \note user supplied name for reporting - N1 , \field Begin Month - \required-field - \minimum 1 - \maximum 12 - \type integer - N2 , \field Begin Day of Month - \required-field - \minimum 1 - \maximum 31 - \type integer - N3 , \field End Month - \required-field - \minimum 1 - \maximum 12 - \type integer - N4 , \field End Day of Month - \required-field - \minimum 1 - \maximum 31 - \type integer - A2 , \field Day of Week for Start Day - \note =[|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|SummerDesignDay|WinterDesignDay| - \note |CustomDay1|CustomDay2]; - \note if you use SummerDesignDay or WinterDesignDay or the CustomDays then this will apply - \note to the whole period; other days (i.e., Monday) will signify a start day and - \note normal sequence of subsequent days - \default Monday - \type choice - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A3, \field Use Weather File Daylight Saving Period - \note If yes or blank, use daylight saving period as specified on Weatherfile. - \note If no, do not use the daylight saving period as specified on the Weatherfile. - \type choice - \default Yes - \key Yes - \key No - A4; \field Use Weather File Rain and Snow Indicators - \type choice - \key Yes - \key No - \default Yes - -SizingPeriod:WeatherFileConditionType, - \memo Use a weather file period for design sizing calculations. - \memo EPW weather files are created with typical and extreme periods - \memo created heuristically from the weather file data. For more - \memo details on these periods, see AuxiliaryPrograms document. - A1 , \field Name - \required-field - \reference RunPeriodsAndDesignDays - \note user supplied name for reporting - A2 , \field Period Selection - \required-field - \retaincase - \note Following is a list of all possible types of Extreme and Typical periods that - \note might be identified in the Weather File. Not all possible types are available - \note for all weather files. - \type choice - \key SummerExtreme - \key SummerTypical - \key WinterExtreme - \key WinterTypical - \key AutumnTypical - \key SpringTypical - \key WetSeason - \key DrySeason - \key NoDrySeason - \key NoWetSeason - \key TropicalHot - \key TropicalCold - \key NoDrySeasonMax - \key NoDrySeasonMin - \key NoWetSeasonMax - \key NoWetSeasonMin - A3 , \field Day of Week for Start Day - \note =[|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|SummerDesignDay|WinterDesignDay| - \note |CustomDay1|CustomDay2]; - \note if you use SummerDesignDay or WinterDesignDay or the CustomDays then this will apply - \note to the whole period; other days (i.e., Monday) will signify a start day and - \note normal sequence of subsequent days - \default Monday - \type choice - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A4, \field Use Weather File Daylight Saving Period - \note If yes or blank, use daylight saving period as specified on Weatherfile. - \note If no, do not use the daylight saving period as specified on the Weatherfile. - \type choice - \default Yes - \key Yes - \key No - A5; \field Use Weather File Rain and Snow Indicators - \type choice - \key Yes - \key No - \default Yes - -RunPeriod, - \memo Specify a range of dates and other parameters for a simulation. - \memo Multiple run periods may be input, but they may not overlap. - \min-fields 7 - A1 , \field Name - \required-field - \reference RunPeriodsAndDesignDays - \note descriptive name (used in reporting mainly) - \note Cannot be not blank and must be unique - N1 , \field Begin Month - \required-field - \minimum 1 - \maximum 12 - \type integer - N2 , \field Begin Day of Month - \required-field - \minimum 1 - \maximum 31 - \type integer - N3, \field Begin Year - \note Start year of the simulation, if this field is specified it must agree with the Day of Week for Start Day - \note If this field is blank, the year will be selected to match the weekday, which is Sunday if not specified - N4 , \field End Month - \required-field - \minimum 1 - \maximum 12 - \type integer - N5 , \field End Day of Month - \required-field - \minimum 1 - \maximum 31 - \type integer - N6, \field End Year - \note end year of simulation, if specified - A2 , \field Day of Week for Start Day - \note =[Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday]; - \note If no year is input, this field will default to Sunday - \note If a year is input and this field is blank, the correct weekday is determined - \type choice - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - A3, \field Use Weather File Holidays and Special Days - \note If yes or blank, use holidays as specified on Weatherfile. - \note If no, do not use the holidays specified on the Weatherfile. - \note Note: You can still specify holidays/special days using the RunPeriodControl:SpecialDays object(s). - \type choice - \default Yes - \key Yes - \key No - A4, \field Use Weather File Daylight Saving Period - \note If yes or blank, use daylight saving period as specified on Weatherfile. - \note If no, do not use the daylight saving period as specified on the Weatherfile. - \type choice - \default Yes - \key Yes - \key No - A5, \field Apply Weekend Holiday Rule - \note if yes and single day holiday falls on weekend, "holiday" occurs on following Monday - \type choice - \key Yes - \key No - \default No - A6, \field Use Weather File Rain Indicators - \type choice - \key Yes - \key No - \default Yes - A7, \field Use Weather File Snow Indicators - \type choice - \key Yes - \key No - \default Yes - A8; \field Treat Weather as Actual - \type choice - \key Yes - \key No - \default No - -RunPeriodControl:SpecialDays, - \min-fields 4 - \memo This object sets up holidays/special days to be used during weather file - \memo run periods. (These are not used with SizingPeriod:* objects.) - \memo Depending on the value in the run period, days on the weather file may also - \memo be used. However, the weather file specification will take precedence over - \memo any specification shown here. (No error message on duplicate days or overlapping - \memo days). - A1, \field Name - \required-field - A2, \field Start Date - \required-field - \note Dates can be several formats: - \note / (month/day) - \note - \note - \note in in - \note can be January, February, March, April, May, June, July, August, September, October, November, December - \note Months can be the first 3 letters of the month - \note can be Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday - \note can be 1 or 1st, 2 or 2nd, etc. up to 5(?) - N1, \field Duration - \units days - \minimum 1 - \maximum 366 - \default 1 - A3; \field Special Day Type - \note Special Day Type selects the schedules appropriate for each day so labeled - \type choice - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - \default Holiday - -RunPeriodControl:DaylightSavingTime, - \unique-object - \min-fields 2 - \memo This object sets up the daylight saving time period for any RunPeriod. - \memo Ignores any daylight saving time period on the weather file and uses this definition. - \memo These are not used with SizingPeriod:DesignDay objects. - \memo Use with SizingPeriod:WeatherFileDays object can be controlled in that object. - A1, \field Start Date - \required-field - A2; \field End Date - \required-field - \note Dates can be several formats: - \note / (month/day) - \note - \note - \note in in - \note can be January, February, March, April, May, June, July, August, September, October, November, December - \note Months can be the first 3 letters of the month - \note can be Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday - \note can be 1 or 1st, 2 or 2nd, etc. up to 5(?) - -WeatherProperty:SkyTemperature, - \memo This object is used to override internal sky temperature calculations. - A1, \field Name - \note blank in this field will apply to all run periods (that is, all objects= - \note SizingPeriod:WeatherFileDays, SizingPeriod:WeatherFileConditionType or RunPeriod - \note otherwise, this name must match one of the environment object names. - \type object-list - \object-list RunPeriodsAndDesignDays - A2, \field Calculation Type - \required-field - \note The field indicates that the sky temperature will be imported from external schedules or calculated by alternative methods other than default. - \type choice - \key ClarkAllen - \key Brunt - \key Idso - \key BerdahlMartin - \key ScheduleValue - \key DifferenceScheduleDryBulbValue - \key DifferenceScheduleDewPointValue - \default ClarkAllen - A3, \field Schedule Name - \note if name matches a SizingPeriod:DesignDay, put in a day schedule of this name - \note if name is for a SizingPeriod:WeatherFileDays, SizingPeriod:WeatherFileConditionType or - \note RunPeriod, put in a full year schedule that covers the appropriate days. - \note Required if Calculation Type is ScheduleValue, DifferenceScheduleDryBulbValue or DifferenceScheduleDewPointValue. - \type object-list - \object-list DayScheduleNames - \object-list ScheduleNames - A4; \field Use Weather File Horizontal IR - \note If yes or blank, use Horizontal IR values from weather file when present, otherwise use the specified sky model. - \note If no, always use the specified sky model and ignore the horizontal IR values from the weather file. - \note For Calculation Type = ScheduleValue, DifferenceScheduleDryBulbValue or DifferenceScheduleDewPointValue, this field is ignored and the scheduled values are used. - \type choice - \default Yes - \key Yes - \key No - -Site:WeatherStation, - \unique-object - \memo This object should only be used for non-standard weather data. Standard weather data - \memo such as TMY2, IWEC, and ASHRAE design day data are all measured at the - \memo default conditions and do not require this object. - N1 , \field Wind Sensor Height Above Ground - \type real - \units m - \default 10.0 - \minimum> 0.0 - N2 , \field Wind Speed Profile Exponent - \type real - \default 0.14 - \minimum 0.0 - N3 , \field Wind Speed Profile Boundary Layer Thickness - \type real - \units m - \default 270.0 - \minimum 0.0 - N4 ; \field Air Temperature Sensor Height Above Ground - \type real - \units m - \default 1.5 - \minimum 0.0 - -Site:HeightVariation, - \unique-object - \memo This object is used if the user requires advanced control over height-dependent - \memo variations in wind speed and temperature. When this object is not present, the default model - \memo for temperature dependence on height is used, and the wind speed is modeled according - \memo to the Terrain field of the BUILDING object. - N1 , \field Wind Speed Profile Exponent - \note Set to zero for no wind speed dependence on height. - \type real - \default 0.22 - \minimum 0.0 - N2 , \field Wind Speed Profile Boundary Layer Thickness - \type real - \units m - \default 370.0 - \minimum> 0.0 - N3 ; \field Air Temperature Gradient Coefficient - \note Set to zero for no air temperature dependence on height. - \type real - \units K/m - \default 0.0065 - \minimum 0.0 - -Site:GroundTemperature:BuildingSurface, - \memo These temperatures are specifically for those surfaces that have the outside environment - \memo of "Ground". Documentation about what values these should be is located in the - \memo Auxiliary programs document (Ground Heat Transfer) as well as the InputOutput Reference. - \memo CAUTION - Do not use the "undisturbed" ground temperatures from the weather data. - \memo These values are too extreme for the soil under a conditioned building. - \memo For best results, use the Slab or Basement program to calculate custom monthly - \memo average ground temperatures (see Auxiliary Programs). For typical commercial - \memo buildings in the USA, a reasonable default value is 2C less than the average indoor space temperature. - \unique-object - \min-fields 12 - \format singleLine - N1 , \field January Ground Temperature - \units C - \type real - \default 18 - N2 , \field February Ground Temperature - \units C - \type real - \default 18 - N3 , \field March Ground Temperature - \units C - \type real - \default 18 - N4 , \field April Ground Temperature - \units C - \type real - \default 18 - N5 , \field May Ground Temperature - \units C - \type real - \default 18 - N6 , \field June Ground Temperature - \units C - \type real - \default 18 - N7 , \field July Ground Temperature - \units C - \type real - \default 18 - N8 , \field August Ground Temperature - \units C - \type real - \default 18 - N9 , \field September Ground Temperature - \units C - \type real - \default 18 - N10, \field October Ground Temperature - \units C - \type real - \default 18 - N11, \field November Ground Temperature - \units C - \type real - \default 18 - N12; \field December Ground Temperature - \units C - \type real - \default 18 - -Site:GroundTemperature:FCfactorMethod, - \memo These temperatures are specifically for underground walls and ground floors - \memo defined with the C-factor and F-factor methods, and should be close to the - \memo monthly average outdoor air temperature delayed by 3 months for the location. - \unique-object - \min-fields 12 - \format singleLine - N1 , \field January Ground Temperature - \units C - \type real - \default 13 - N2 , \field February Ground Temperature - \units C - \type real - \default 13 - N3 , \field March Ground Temperature - \units C - \type real - \default 13 - N4 , \field April Ground Temperature - \units C - \type real - \default 13 - N5 , \field May Ground Temperature - \units C - \type real - \default 13 - N6 , \field June Ground Temperature - \units C - \type real - \default 13 - N7 , \field July Ground Temperature - \units C - \type real - \default 13 - N8 , \field August Ground Temperature - \units C - \type real - \default 13 - N9 , \field September Ground Temperature - \units C - \type real - \default 13 - N10, \field October Ground Temperature - \units C - \type real - \default 13 - N11, \field November Ground Temperature - \units C - \type real - \default 13 - N12; \field December Ground Temperature - \units C - \type real - \default 13 - -Site:GroundTemperature:Shallow, - \memo These temperatures are specifically for the Surface Ground Heat Exchanger and - \memo should probably be close to the average outdoor air temperature for the location. - \memo They are not used in other models. - \unique-object - \min-fields 12 - \format singleLine - N1 , \field January Surface Ground Temperature - \units C - \type real - \default 13 - N2 , \field February Surface Ground Temperature - \units C - \type real - \default 13 - N3 , \field March Surface Ground Temperature - \units C - \type real - \default 13 - N4 , \field April Surface Ground Temperature - \units C - \type real - \default 13 - N5 , \field May Surface Ground Temperature - \units C - \type real - \default 13 - N6 , \field June Surface Ground Temperature - \units C - \type real - \default 13 - N7 , \field July Surface Ground Temperature - \units C - \type real - \default 13 - N8 , \field August Surface Ground Temperature - \units C - \type real - \default 13 - N9 , \field September Surface Ground Temperature - \units C - \type real - \default 13 - N10, \field October Surface Ground Temperature - \units C - \type real - \default 13 - N11, \field November Surface Ground Temperature - \units C - \type real - \default 13 - N12; \field December Surface Ground Temperature - \units C - \type real - \default 13 - -Site:GroundTemperature:Deep, - \memo These temperatures are specifically for the ground heat exchangers that would use - \memo "deep" (3-4 m depth) ground temperatures for their heat source. - \memo They are not used in other models. - \unique-object - \min-fields 12 - \format singleLine - N1 , \field January Deep Ground Temperature - \units C - \type real - \default 16 - N2 , \field February Deep Ground Temperature - \units C - \type real - \default 16 - N3 , \field March Deep Ground Temperature - \units C - \type real - \default 16 - N4 , \field April Deep Ground Temperature - \units C - \type real - \default 16 - N5 , \field May Deep Ground Temperature - \units C - \type real - \default 16 - N6 , \field June Deep Ground Temperature - \units C - \type real - \default 16 - N7 , \field July Deep Ground Temperature - \units C - \type real - \default 16 - N8 , \field August Deep Ground Temperature - \units C - \type real - \default 16 - N9 , \field September Deep Ground Temperature - \units C - \type real - \default 16 - N10, \field October Deep Ground Temperature - \units C - \type real - \default 16 - N11, \field November Deep Ground Temperature - \units C - \type real - \default 16 - N12; \field December Deep Ground Temperature - \units C - \type real - \default 16 - -Site:GroundTemperature:Undisturbed:FiniteDifference, - \memo Undisturbed ground temperature object using a - \memo detailed finite difference 1-D model - \min-fields 7 - A1, \field Name - \required-field - \reference UndisturbedGroundTempModels - N1, \field Soil Thermal Conductivity - \required-field - \type real - \units W/m-K - \minimum> 0.0 - N2, \field Soil Density - \required-field - \type real - \units kg/m3 - \minimum> 0.0 - N3, \field Soil Specific Heat - \required-field - \type real - \units J/kg-K - \minimum> 0.0 - N4, \field Soil Moisture Content Volume Fraction - \type real - \units percent - \minimum 0 - \maximum 100 - \default 30 - N5, \field Soil Moisture Content Volume Fraction at Saturation - \type real - \units percent - \minimum 0 - \maximum 100 - \default 50 - N6; \field Evapotranspiration Ground Cover Parameter - \type real - \units dimensionless - \minimum 0 - \maximum 1.5 - \default 0.4 - \note This specifies the ground cover effects during evapotranspiration - \note calculations. The value roughly represents the following cases: - \note = 0 : concrete or other solid, non-permeable ground surface material - \note = 0.5 : short grass, much like a manicured lawn - \note = 1 : standard reference state (12 cm grass) - \note = 1.5 : wild growth - -Site:GroundTemperature:Undisturbed:KusudaAchenbach, - \memo Undisturbed ground temperature object using the - \memo Kusuda-Achenbach 1965 correlation. - \min-fields 7 - A1, \field Name - \required-field - \reference UndisturbedGroundTempModels - N1, \field Soil Thermal Conductivity - \required-field - \type real - \units W/m-K - \minimum> 0.0 - N2, \field Soil Density - \required-field - \type real - \units kg/m3 - \minimum> 0.0 - N3, \field Soil Specific Heat - \required-field - \type real - \units J/kg-K - \minimum> 0.0 - N4, \field Average Soil Surface Temperature - \type real - \units C - \note Annual average surface temperature - \note If left blank the Site:GroundTemperature:Shallow object must be included in the input - \note The soil temperature, amplitude, and phase shift must all be included or omitted together - N5, \field Average Amplitude of Surface Temperature - \type real - \units deltaC - \minimum 0 - \note Annual average surface temperature variation from average. - \note If left blank the Site:GroundTemperature:Shallow object must be included in the input - \note The soil temperature, amplitude, and phase shift must all be included or omitted together - N6; \field Phase Shift of Minimum Surface Temperature - \type real - \units days - \minimum 0 - \maximum< 365 - \note The phase shift of minimum surface temperature, or the day - \note of the year when the minimum surface temperature occurs. - \note If left blank the Site:GroundTemperature:Shallow object must be included in the input - \note The soil temperature, amplitude, and phase shift must all be included or omitted together - -Site:GroundTemperature:Undisturbed:Xing, - \memo Undisturbed ground temperature object using the - \memo Xing 2014 2 harmonic parameter model. - \min-fields 9 - A1, \field Name - \required-field - \reference UndisturbedGroundTempModels - N1, \field Soil Thermal Conductivity - \required-field - \type real - \units W/m-K - \minimum> 0.0 - N2, \field Soil Density - \required-field - \type real - \units kg/m3 - \minimum> 0.0 - N3, \field Soil Specific Heat - \required-field - \type real - \units J/kg-K - \minimum> 0.0 - N4, \field Average Soil Surface Tempeature - \required-field - \type real - \units C - N5, \field Soil Surface Temperature Amplitude 1 - \required-field - \type real - \units deltaC - N6, \field Soil Surface Temperature Amplitude 2 - \required-field - \type real - \units deltaC - N7, \field Phase Shift of Temperature Amplitude 1 - \required-field - \type real - \units days - \maximum< 365 - N8; \field Phase Shift of Temperature Amplitude 2 - \required-field - \type real - \units days - \maximum< 365 - -Site:GroundDomain:Slab, - \memo Ground-coupled slab model for on-grade and - \memo in-grade cases with or without insulation. - A1, \field Name - \required-field - N1, \field Ground Domain Depth - \type real - \default 10 - \units m - \minimum> 0.0 - N2, \field Aspect Ratio - \type real - \default 1 - N3, \field Perimeter Offset - \type real - \default 5 - \units m - \minimum> 0.0 - N4, \field Soil Thermal Conductivity - \type real - \default 1.5 - \units W/m-K - \minimum> 0.0 - N5, \field Soil Density - \type real - \default 2800 - \units kg/m3 - \minimum> 0.0 - N6, \field Soil Specific Heat - \type real - \default 850 - \units J/kg-K - \minimum> 0.0 - N7, \field Soil Moisture Content Volume Fraction - \type real - \units percent - \minimum 0 - \maximum 100 - \default 30 - N8, \field Soil Moisture Content Volume Fraction at Saturation - \type real - \units percent - \minimum 0 - \maximum 100 - \default 50 - A2, \field Undisturbed Ground Temperature Model Type - \required-field - \type choice - \key Site:GroundTemperature:Undisturbed:FiniteDifference - \key Site:GroundTemperature:Undisturbed:KusudaAchenbach - \key Site:GroundTemperature:Undisturbed:Xing - A3, \field Undisturbed Ground Temperature Model Name - \required-field - \type object-list - \object-list UndisturbedGroundTempModels - N9, \field Evapotranspiration Ground Cover Parameter - \type real - \minimum 0 - \maximum 1.5 - \default 0.4 - \note This specifies the ground cover effects during evapotranspiration - \note calculations. The value roughly represents the following cases: - \note = 0 : concrete or other solid, non-permeable ground surface material - \note = 0.5 : short grass, much like a manicured lawn - \note = 1 : standard reference state (12 cm grass) - \note = 1.5 : wild growth - A4, \field Slab Boundary Condition Model Name - \required-field - \type object-list - \object-list OSCMNames - A5, \field Slab Location - \required-field - \type choice - \key InGrade - \key OnGrade - \note This field specifies whether the slab is located "in-grade" or "on-grade" - A6, \field Slab Material Name - \type object-list - \object-list MaterialName - \note Only applicable for the in-grade case - A7, \field Horizontal Insulation - \type choice - \key Yes - \key No - \default No - \note This field specifies the presence of insulation beneath the slab. - \note Only required for in-grade case. - A8, \field Horizontal Insulation Material Name - \type object-list - \object-list MaterialName - \note This field specifies the horizontal insulation material. - A9, \field Horizontal Insulation Extents - \type choice - \key Full - \key Perimeter - \default Full - \note This field specifies whether the horizontal insulation fully insulates - \note the surface or is perimeter only insulation - N10, \field Perimeter Insulation Width - \type real - \units m - \minimum> 0.0 - \note This field specifies the width of the underfloor perimeter insulation - A10, \field Vertical Insulation - \type choice - \key Yes - \key No - \default No - \note This field specifies the presence of vertical insulation at the slab edge. - A11, \field Vertical Insulation Material Name - \type object-list - \object-list MaterialName - \note This field specifies the vertical insulation material. - N11, \field Vertical Insulation Depth - \type real - \units m - \minimum> 0.0 - \note Only used when including vertical insulation - \note This field specifies the depth of the vertical insulation - A12, \field Simulation Timestep - \type choice - \key Timestep - \key Hourly - \default Hourly - \note This field specifies the ground domain simulation timestep. - N12, \field Geometric Mesh Coefficient - \type real - \minimum 1.0 - \maximum 2.0 - \default 1.6 - N13; \field Mesh Density Parameter - \type integer - \minimum 4 - \default 6 - -Site:GroundDomain:Basement, - \memo Ground-coupled basement model for simulating basements - \memo or other underground zones. - A1, \field Name - \required-field - N1, \field Ground Domain Depth - \type real - \default 10 - \units m - \minimum> 0.0 - \note The depth from ground surface to the deep ground boundary of the domain. - N2, \field Aspect Ratio - \type real - \default 1 - \note This defines the height to width ratio of the basement zone. - N3, \field Perimeter Offset - \type real - \default 5 - \units m - \minimum> 0.0 - \note The distance from the basement wall edge to the edge of the ground domain - N4, \field Soil Thermal Conductivity - \type real - \default 1.5 - \units W/m-K - \minimum> 0.0 - N5, \field Soil Density - \type real - \default 2800 - \units kg/m3 - \minimum> 0.0 - N6, \field Soil Specific Heat - \type real - \default 850 - \units J/kg-K - \minimum> 0.0 - N7, \field Soil Moisture Content Volume Fraction - \type real - \units percent - \minimum 0 - \maximum 100 - \default 30 - N8, \field Soil Moisture Content Volume Fraction at Saturation - \type real - \units percent - \minimum 0 - \maximum 100 - \default 50 - A2, \field Undisturbed Ground Temperature Model Type - \required-field - \type choice - \key Site:GroundTemperature:Undisturbed:FiniteDifference - \key Site:GroundTemperature:Undisturbed:KusudaAchenbach - \key Site:GroundTemperature:Undisturbed:Xing - A3, \field Undisturbed Ground Temperature Model Name - \required-field - \type object-list - \object-list UndisturbedGroundTempModels - N9, \field Evapotranspiration Ground Cover Parameter - \type real - \minimum 0 - \maximum 1.5 - \default 0.4 - \note This specifies the ground cover effects during evapotranspiration - \note calculations. The value roughly represents the following cases: - \note = 0 : concrete or other solid, non-permeable ground surface material - \note = 0.5 : short grass, much like a manicured lawn - \note = 1 : standard reference state (12 cm grass) - \note = 1.5 : wild growth - A4, \field Basement Floor Boundary Condition Model Name - \required-field - \type object-list - \object-list OSCMNames - A5, \field Horizontal Insulation - \type choice - \key Yes - \key No - \default No - \note This field specifies the presence of insulation beneath the basement floor. - A6, \field Horizontal Insulation Material Name - \type object-list - \object-list MaterialName - A7, \field Horizontal Insulation Extents - \type choice - \key Perimeter - \key Full - \default Full - \note This field specifies whether the horizontal insulation fully insulates - \note the surface or is perimeter only insulation - N10, \field Perimeter Horizontal Insulation Width - \type real - \units m - \minimum> 0.0 - \note Width of horizontal perimeter insulation measured from - \note foundation wall inside surface. - N11, \field Basement Wall Depth - \type real - \units m - \minimum> 0.0 - \note Depth measured from ground surface. - A8, \field Basement Wall Boundary Condition Model Name - \required-field - \type object-list - \object-list OSCMNames - A9, \field Vertical Insulation - \type choice - \key Yes - \key No - \default No - A10, \field Basement Wall Vertical Insulation Material Name - \type object-list - \object-list MaterialName - N12, \field Vertical Insulation Depth - \type real - \units m - \minimum> 0.0 - \note Depth measured from the ground surface. - A11, \field Simulation Timestep - \type choice - \key Timestep - \key Hourly - \default Hourly - \note This field specifies the basement domain simulation interval. - N13; \field Mesh Density Parameter - \type integer - \default 4 - \minimum 2 - -Site:GroundReflectance, - \memo Specifies the ground reflectance values used to calculate ground reflected solar. - \memo The ground reflectance can be further modified when snow is on the ground - \memo by Site:GroundReflectance:SnowModifier. - \unique-object - \min-fields 12 - \format singleLine - N1 , \field January Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N2 , \field February Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N3 , \field March Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N4 , \field April Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N5 , \field May Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N6 , \field June Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N7 , \field July Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N8 , \field August Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N9 , \field September Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N10 , \field October Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N11 , \field November Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - N12 ; \field December Ground Reflectance - \default 0.2 - \type real - \minimum 0.0 - \maximum 1.0 - \units dimensionless - -Site:GroundReflectance:SnowModifier, - \memo Specifies ground reflectance multipliers when snow resident on the ground. - \memo These multipliers are applied to the "normal" ground reflectances specified - \memo in Site:GroundReflectance. - N1, \field Ground Reflected Solar Modifier - \minimum 0.0 - \default 1.0 - \note Value for modifying the "normal" ground reflectance when Snow is on ground - \note when calculating the "Ground Reflected Solar Radiation Value" - \note a value of 1.0 here uses the "normal" ground reflectance - \note Ground Reflected Solar = (BeamSolar*CosSunZenith + DiffuseSolar)*GroundReflectance - \note This would be further modified by the Snow Ground Reflectance Modifier when Snow was on the ground - \note When Snow on ground, effective GroundReflectance is normal GroundReflectance*"Ground Reflectance Snow Modifier" - \note Ground Reflectance achieved in this manner will be restricted to [0.0,1.0] - N2; \field Daylighting Ground Reflected Solar Modifier - \minimum 0.0 - \default 1.0 - \note Value for modifying the "normal" daylighting ground reflectance when Snow is on ground - \note when calculating the "Ground Reflected Solar Radiation Value" - \note a value of 1.0 here uses the "normal" ground reflectance - \note Ground Reflected Solar = (BeamSolar*CosSunZenith + DiffuseSolar)*GroundReflectance - \note This would be further modified by the Snow Ground Reflectance Modifier when Snow was on the ground - \note When Snow on ground, effective GroundReflectance is normal GroundReflectance*"Daylighting Ground Reflectance Snow Modifier" - \note Ground Reflectance achieved in this manner will be restricted to [0.0,1.0] - -Site:WaterMainsTemperature, - \memo Used to calculate water mains temperatures delivered by underground water main pipes. - \memo Water mains temperatures are a function of outdoor climate conditions - \memo and vary with time of year. - A1 , \field Calculation Method - \required-field - \type choice - \key Schedule - \key Correlation - \key CorrelationFromWeatherFile - \default CorrelationFromWeatherFile - \note If calculation method is CorrelationFromWeatherFile, the two numeric input - \note fields are ignored. Instead, EnergyPlus calculates them from weather file. - A2 , \field Temperature Schedule Name - \type object-list - \object-list ScheduleNames - N1 , \field Annual Average Outdoor Air Temperature - \note If calculation method is CorrelationFromWeatherFile or Schedule, this input - \note field is ignored. - \type real - \units C - N2 ; \field Maximum Difference In Monthly Average Outdoor Air Temperatures - \note If calculation method is CorrelationFromWeatherFile or Schedule, this input - \note field is ignored. - \type real - \units deltaC - \minimum 0 - -Site:Precipitation, - \memo Used to describe the amount of water precipitation at the building site. - \memo Precipitation includes both rain and the equivalent water content of snow. - A1, \field Precipitation Model Type - \type choice - \key ScheduleAndDesignLevel - N1, \field Design Level for Total Annual Precipitation - \note meters of water per year used for design level - \units m/yr - A2, \field Precipitation Rates Schedule Name - \type object-list - \object-list ScheduleNames - \note Schedule values in meters of water per hour - \note values should be non-negative - N2; \field Average Total Annual Precipitation - \note meters of water per year from average weather statistics - \minimum 0 - \units m/yr - -RoofIrrigation, - \memo Used to describe the amount of irrigation on the ecoroof surface over the course - \memo of the simulation runperiod. - A1, \field Irrigation Model Type - \type choice - \key Schedule - \key SmartSchedule - \note SmartSchedule will not allow irrigation when soil is already moist. - \note Current threshold set at 30% of saturation. - A2, \field Irrigation Rate Schedule Name - \type object-list - \object-list ScheduleNames - \note Schedule values in meters of water per hour - \note values should be non-negative - N1; \field Irrigation Maximum Saturation Threshold - \note Used with SmartSchedule to set the saturation level at which no - \note irrigation is allowed. - \units percent - \minimum 0.0 - \maximum 100.0 - \default 40.0 - -Site:SolarAndVisibleSpectrum, - \memo If this object is omitted, the default solar and visible spectrum data will be used. - \unique-object - A1, \field Name - \required-field - \type alpha - A2, \field Spectrum Data Method - \note The method specifies which of the solar and visible spectrum data to use in the calculations. - \note Choices: Default - existing hard-wired spectrum data in EnergyPlus. - \note UserDefined - user specified spectrum data referenced by the next two fields - \type choice - \key Default - \key UserDefined - \default Default - A3, \field Solar Spectrum Data Object Name - \type object-list - \object-list SpectrumDataNames - A4; \field Visible Spectrum Data Object Name - \type object-list - \object-list SpectrumDataNames - -Site:SpectrumData, - \min-fields 8 - \memo Spectrum Data Type is followed by up to 107 sets of normal-incidence measured values of - \memo [wavelength, spectrum] for wavelengths covering the solar (0.25 to 2.5 microns) or visible - \memo spectrum (0.38 to 0.78 microns) - \extensible:2 - A1, \field Name - \required-field - \type alpha - \reference SpectrumDataNames - A2, \field Spectrum Data Type - \required-field - \type choice - \key Solar - \key Visible - N1, \field Wavelength - \type real - \units micron - N2, \field Spectrum - \type real - N3, \field Wavelength - \type real - \units micron - N4, \field Spectrum - \type real - N5, \field Wavelength - \begin-extensible - \type real - \units micron - N6, \field Spectrum - \type real - N7, N8, \note fields as indicated - N9, N10, \note fields as indicated - N11, N12, \note fields as indicated - N13, N14, \note fields as indicated - N15, N16, \note fields as indicated - N17, N18, \note fields as indicated - N19, N20, \note fields as indicated - N21, N22, \note fields as indicated - N23, N24, \note fields as indicated - N25, N26, \note fields as indicated - N27, N28, \note fields as indicated - N29, N30, \note fields as indicated - N31, N32, \note fields as indicated - N33, N34, \note fields as indicated - N35, N36, \note fields as indicated - N37, N38, \note fields as indicated - N39, N40, \note fields as indicated - N41, N42, \note fields as indicated - N43, N44, \note fields as indicated - N45, N46, \note fields as indicated - N47, N48, \note fields as indicated - N49, N50, \note fields as indicated - N51, N52, \note fields as indicated - N53, N54, \note fields as indicated - N55, N56, \note fields as indicated - N57, N58, \note fields as indicated - N59, N60, \note fields as indicated - N61, N62, \note fields as indicated - N63, N64, \note fields as indicated - N65, N66, \note fields as indicated - N67, N68, \note fields as indicated - N69, N70, \note fields as indicated - N71, N72, \note fields as indicated - N73, N74, \note fields as indicated - N75, N76, \note fields as indicated - N77, N78, \note fields as indicated - N79, N80, \note fields as indicated - N81, N82, \note fields as indicated - N83, N84, \note fields as indicated - N85, N86, \note fields as indicated - N87, N88, \note fields as indicated - N89, N90, \note fields as indicated - N91, N92, \note fields as indicated - N93, N94, \note fields as indicated - N95, N96, \note fields as indicated - N97, N98, \note fields as indicated - N99, N100, \note fields as indicated - N101, N102, \note fields as indicated - N103, N104, \note fields as indicated - N105, N106, \note fields as indicated - N107, N108, \note fields as indicated - N109, N110, \note fields as indicated - N111, N112, \note fields as indicated - N113, N114, \note fields as indicated - N115, N116, \note fields as indicated - N117, N118, \note fields as indicated - N119, N120, \note fields as indicated - N121, N122, \note fields as indicated - N123, N124, \note fields as indicated - N125, N126, \note fields as indicated - N127, N128, \note fields as indicated - N129, N130, \note fields as indicated - N131, N132, \note fields as indicated - N133, N134, \note fields as indicated - N135, N136, \note fields as indicated - N137, N138, \note fields as indicated - N139, N140, \note fields as indicated - N141, N142, \note fields as indicated - N143, N144, \note fields as indicated - N145, N146, \note fields as indicated - N147, N148, \note fields as indicated - N149, N150, \note fields as indicated - N151, N152, \note fields as indicated - N153, N154, \note fields as indicated - N155, N156, \note fields as indicated - N157, N158, \note fields as indicated - N159, N160, \note fields as indicated - N161, N162, \note fields as indicated - N163, N164, \note fields as indicated - N165, N166, \note fields as indicated - N167, N168, \note fields as indicated - N169, N170, \note fields as indicated - N171, N172, \note fields as indicated - N173, N174, \note fields as indicated - N175, N176, \note fields as indicated - N177, N178, \note fields as indicated - N179, N180, \note fields as indicated - N181, N182, \note fields as indicated - N183, N184, \note fields as indicated - N185, N186, \note fields as indicated - N187, N188, \note fields as indicated - N189, N190, \note fields as indicated - N191, N192, \note fields as indicated - N193, N194, \note fields as indicated - N195, N196, \note fields as indicated - N197, N198, \note fields as indicated - N199, N200, \note fields as indicated - N201, N202, \note fields as indicated - N203, N204, \note fields as indicated - N205, N206, \note fields as indicated - N207, N208, \note fields as indicated - N209, N210, \note fields as indicated - N211, N212, \note fields as indicated - N213, N214; \note fields as indicated - -\group Schedules - -ScheduleTypeLimits, - \memo ScheduleTypeLimits specifies the data types and limits for the values contained in schedules - A1, \field Name - \required-field - \reference ScheduleTypeLimitsNames - \note used to validate schedule types in various schedule objects - N1, \field Lower Limit Value - \note lower limit (real or integer) for the Schedule Type. e.g. if fraction, this is 0.0 - \unitsBasedOnField A3 - N2, \field Upper Limit Value - \note upper limit (real or integer) for the Schedule Type. e.g. if fraction, this is 1.0 - \unitsBasedOnField A3 - A2, \field Numeric Type - \note Numeric type is either Continuous (all numbers within the min and - \note max are valid or Discrete (only integer numbers between min and - \note max are valid. (Could also allow REAL and INTEGER to mean the - \note same things) - \type choice - \key Continuous - \key Discrete - A3; \field Unit Type - \note Temperature (C or F) - \note DeltaTemperature (C or F) - \note PrecipitationRate (m/hr or ft/hr) - \note Angle (degrees) - \note Convection Coefficient (W/m2-K or Btu/sqft-hr-F) - \note Activity Level (W/person) - \note Velocity (m/s or ft/min) - \note Capacity (W or Btu/h) - \note Power (W) - \type choice - \key Dimensionless - \key Temperature - \key DeltaTemperature - \key PrecipitationRate - \key Angle - \key ConvectionCoefficient - \key ActivityLevel - \key Velocity - \key Capacity - \key Power - \key Availability - \key Percent - \key Control - \key Mode - \default Dimensionless - -Schedule:Day:Hourly, - \min-fields 26 - \memo A Schedule:Day:Hourly contains 24 values for each hour of the day. - A1 , \field Name - \required-field - \type alpha - \reference DayScheduleNames - A2 , \field Schedule Type Limits Name - \type object-list - \object-list ScheduleTypeLimitsNames - N1 , \field Hour 1 - \type real - \default 0 - N2 , \field Hour 2 - \type real - \default 0 - N3 , \field Hour 3 - \type real - \default 0 - N4 , \field Hour 4 - \type real - \default 0 - N5 , \field Hour 5 - \type real - \default 0 - N6 , \field Hour 6 - \type real - \default 0 - N7 , \field Hour 7 - \type real - \default 0 - N8 , \field Hour 8 - \type real - \default 0 - N9 , \field Hour 9 - \type real - \default 0 - N10, \field Hour 10 - \type real - \default 0 - N11, \field Hour 11 - \type real - \default 0 - N12, \field Hour 12 - \type real - \default 0 - N13, \field Hour 13 - \type real - \default 0 - N14, \field Hour 14 - \type real - \default 0 - N15, \field Hour 15 - \type real - \default 0 - N16, \field Hour 16 - \type real - \default 0 - N17, \field Hour 17 - \type real - \default 0 - N18, \field Hour 18 - \type real - \default 0 - N19, \field Hour 19 - \type real - \default 0 - N20, \field Hour 20 - \type real - \default 0 - N21, \field Hour 21 - \type real - \default 0 - N22, \field Hour 22 - \type real - \default 0 - N23, \field Hour 23 - \type real - \default 0 - N24; \field Hour 24 - \type real - \default 0 - -Schedule:Day:Interval, - \extensible:2 - repeat last two fields, remembering to remove ; from "inner" fields. - \memo A Schedule:Day:Interval contains a full day of values with specified end times for each value - \memo Currently, is set up to allow for 10 minute intervals for an entire day. - \min-fields 5 - A1 , \field Name - \required-field - \type alpha - \reference DayScheduleNames - A2 , \field Schedule Type Limits Name - \type object-list - \object-list ScheduleTypeLimitsNames - A3 , \field Interpolate to Timestep - \note when the interval does not match the user specified timestep a Average choice will average between the intervals request (to - \note timestep resolution. A No choice will use the interval value at the simulation timestep without regard to if it matches - \note the boundary or not. A Linear choice will interpolate linearly between successive values. - \type choice - \key Average - \key Linear - \key No - \default No - A4 , \field Time 1 - \begin-extensible - \note "until" includes the time entered. - \units hh:mm - N1 , \field Value Until Time 1 - A5 , \field Time 2 - \note "until" includes the time entered. - \units hh:mm - N2 , \field Value Until Time 2 - A6 , \field Time 3 - \note "until" includes the time entered. - \units hh:mm - N3 , \field Value Until Time 3 - A7 , \field Time 4 - \note "until" includes the time entered. - \units hh:mm - N4 , \field Value Until Time 4 - A8 , \field Time 5 - \note "until" includes the time entered. - \units hh:mm - N5 , \field Value Until Time 5 - A9 , \field Time 6 - \note "until" includes the time entered. - \units hh:mm - N6 , \field Value Until Time 6 - A10 , \field Time 7 - \note "until" includes the time entered. - \units hh:mm - N7 , \field Value Until Time 7 - A11 , \field Time 8 - \note "until" includes the time entered. - \units hh:mm - N8 , \field Value Until Time 8 - A12 , \field Time 9 - \note "until" includes the time entered. - \units hh:mm - N9 , \field Value Until Time 9 - A13 , \field Time 10 - \note "until" includes the time entered. - \units hh:mm - N10 , \field Value Until Time 10 - A14 , \field Time 11 - \note "until" includes the time entered. - \units hh:mm - N11 , \field Value Until Time 11 - A15 , \field Time 12 - \note "until" includes the time entered. - \units hh:mm - N12 , \field Value Until Time 12 - A16 , \field Time 13 - \note "until" includes the time entered. - \units hh:mm - N13 , \field Value Until Time 13 - A17 , \field Time 14 - \note "until" includes the time entered. - \units hh:mm - N14 , \field Value Until Time 14 - A18 , \field Time 15 - \note "until" includes the time entered. - \units hh:mm - N15 , \field Value Until Time 15 - A19 , \field Time 16 - \note "until" includes the time entered. - \units hh:mm - N16 , \field Value Until Time 16 - A20 , \field Time 17 - \note "until" includes the time entered. - \units hh:mm - N17 , \field Value Until Time 17 - A21 , \field Time 18 - \note "until" includes the time entered. - \units hh:mm - N18 , \field Value Until Time 18 - A22 , \field Time 19 - \note "until" includes the time entered. - \units hh:mm - N19 , \field Value Until Time 19 - A23 , \field Time 20 - \note "until" includes the time entered. - \units hh:mm - N20 , \field Value Until Time 20 - A24 , \field Time 21 - \note "until" includes the time entered. - \units hh:mm - N21 , \field Value Until Time 21 - A25 , \field Time 22 - \note "until" includes the time entered. - \units hh:mm - N22 , \field Value Until Time 22 - A26 , \field Time 23 - \note "until" includes the time entered. - \units hh:mm - N23 , \field Value Until Time 23 - A27 , \field Time 24 - \note "until" includes the time entered. - \units hh:mm - N24 , \field Value Until Time 24 - A28 , \field Time 25 - \note "until" includes the time entered. - \units hh:mm - N25 , \field Value Until Time 25 - A29 , \field Time 26 - \note "until" includes the time entered. - \units hh:mm - N26 , \field Value Until Time 26 - A30 , \field Time 27 - \note "until" includes the time entered. - \units hh:mm - N27 , \field Value Until Time 27 - A31 , \field Time 28 - \note "until" includes the time entered. - \units hh:mm - N28 , \field Value Until Time 28 - A32 , \field Time 29 - \note "until" includes the time entered. - \units hh:mm - N29 , \field Value Until Time 29 - A33 , \field Time 30 - \note "until" includes the time entered. - \units hh:mm - N30 , \field Value Until Time 30 - A34 , \field Time 31 - \note "until" includes the time entered. - \units hh:mm - N31 , \field Value Until Time 31 - A35 , \field Time 32 - \note "until" includes the time entered. - \units hh:mm - N32 , \field Value Until Time 32 - A36 , \field Time 33 - \note "until" includes the time entered. - \units hh:mm - N33 , \field Value Until Time 33 - A37 , \field Time 34 - \note "until" includes the time entered. - \units hh:mm - N34 , \field Value Until Time 34 - A38 , \field Time 35 - \note "until" includes the time entered. - \units hh:mm - N35 , \field Value Until Time 35 - A39 , \field Time 36 - \note "until" includes the time entered. - \units hh:mm - N36 , \field Value Until Time 36 - A40 , \field Time 37 - \note "until" includes the time entered. - \units hh:mm - N37 , \field Value Until Time 37 - A41 , \field Time 38 - \note "until" includes the time entered. - \units hh:mm - N38 , \field Value Until Time 38 - A42 , \field Time 39 - \note "until" includes the time entered. - \units hh:mm - N39 , \field Value Until Time 39 - A43 , \field Time 40 - \note "until" includes the time entered. - \units hh:mm - N40 , \field Value Until Time 40 - A44 , \field Time 41 - \note "until" includes the time entered. - \units hh:mm - N41 , \field Value Until Time 41 - A45 , \field Time 42 - \note "until" includes the time entered. - \units hh:mm - N42 , \field Value Until Time 42 - A46 , \field Time 43 - \note "until" includes the time entered. - \units hh:mm - N43 , \field Value Until Time 43 - A47 , \field Time 44 - \note "until" includes the time entered. - \units hh:mm - N44 , \field Value Until Time 44 - A48 , \field Time 45 - \note "until" includes the time entered. - \units hh:mm - N45 , \field Value Until Time 45 - A49 , \field Time 46 - \note "until" includes the time entered. - \units hh:mm - N46 , \field Value Until Time 46 - A50 , \field Time 47 - \note "until" includes the time entered. - \units hh:mm - N47 , \field Value Until Time 47 - A51 , \field Time 48 - \note "until" includes the time entered. - \units hh:mm - N48 , \field Value Until Time 48 - A52 , \field Time 49 - \note "until" includes the time entered. - \units hh:mm - N49 , \field Value Until Time 49 - A53 , \field Time 50 - \note "until" includes the time entered. - \units hh:mm - N50 , \field Value Until Time 50 - A54 , \field Time 51 - \note "until" includes the time entered. - \units hh:mm - N51 , \field Value Until Time 51 - A55 , \field Time 52 - \note "until" includes the time entered. - \units hh:mm - N52 , \field Value Until Time 52 - A56 , \field Time 53 - \note "until" includes the time entered. - \units hh:mm - N53 , \field Value Until Time 53 - A57 , \field Time 54 - \note "until" includes the time entered. - \units hh:mm - N54 , \field Value Until Time 54 - A58 , \field Time 55 - \note "until" includes the time entered. - \units hh:mm - N55 , \field Value Until Time 55 - A59 , \field Time 56 - \note "until" includes the time entered. - \units hh:mm - N56 , \field Value Until Time 56 - A60 , \field Time 57 - \note "until" includes the time entered. - \units hh:mm - N57 , \field Value Until Time 57 - A61 , \field Time 58 - \note "until" includes the time entered. - \units hh:mm - N58 , \field Value Until Time 58 - A62 , \field Time 59 - \note "until" includes the time entered. - \units hh:mm - N59 , \field Value Until Time 59 - A63 , \field Time 60 - \note "until" includes the time entered. - \units hh:mm - N60 , \field Value Until Time 60 - A64 , \field Time 61 - \note "until" includes the time entered. - \units hh:mm - N61 , \field Value Until Time 61 - A65 , \field Time 62 - \note "until" includes the time entered. - \units hh:mm - N62 , \field Value Until Time 62 - A66 , \field Time 63 - \note "until" includes the time entered. - \units hh:mm - N63 , \field Value Until Time 63 - A67 , \field Time 64 - \note "until" includes the time entered. - \units hh:mm - N64 , \field Value Until Time 64 - A68 , \field Time 65 - \note "until" includes the time entered. - \units hh:mm - N65 , \field Value Until Time 65 - A69 , \field Time 66 - \note "until" includes the time entered. - \units hh:mm - N66 , \field Value Until Time 66 - A70 , \field Time 67 - \note "until" includes the time entered. - \units hh:mm - N67 , \field Value Until Time 67 - A71 , \field Time 68 - \note "until" includes the time entered. - \units hh:mm - N68 , \field Value Until Time 68 - A72 , \field Time 69 - \note "until" includes the time entered. - \units hh:mm - N69 , \field Value Until Time 69 - A73 , \field Time 70 - \note "until" includes the time entered. - \units hh:mm - N70 , \field Value Until Time 70 - A74 , \field Time 71 - \note "until" includes the time entered. - \units hh:mm - N71 , \field Value Until Time 71 - A75 , \field Time 72 - \note "until" includes the time entered. - \units hh:mm - N72 , \field Value Until Time 72 - A76 , \field Time 73 - \note "until" includes the time entered. - \units hh:mm - N73 , \field Value Until Time 73 - A77 , \field Time 74 - \note "until" includes the time entered. - \units hh:mm - N74 , \field Value Until Time 74 - A78 , \field Time 75 - \note "until" includes the time entered. - \units hh:mm - N75 , \field Value Until Time 75 - A79 , \field Time 76 - \note "until" includes the time entered. - \units hh:mm - N76 , \field Value Until Time 76 - A80 , \field Time 77 - \note "until" includes the time entered. - \units hh:mm - N77 , \field Value Until Time 77 - A81 , \field Time 78 - \note "until" includes the time entered. - \units hh:mm - N78 , \field Value Until Time 78 - A82 , \field Time 79 - \note "until" includes the time entered. - \units hh:mm - N79 , \field Value Until Time 79 - A83 , \field Time 80 - \note "until" includes the time entered. - \units hh:mm - N80 , \field Value Until Time 80 - A84 , \field Time 81 - \note "until" includes the time entered. - \units hh:mm - N81 , \field Value Until Time 81 - A85 , \field Time 82 - \note "until" includes the time entered. - \units hh:mm - N82 , \field Value Until Time 82 - A86 , \field Time 83 - \note "until" includes the time entered. - \units hh:mm - N83 , \field Value Until Time 83 - A87 , \field Time 84 - \note "until" includes the time entered. - \units hh:mm - N84 , \field Value Until Time 84 - A88 , \field Time 85 - \note "until" includes the time entered. - \units hh:mm - N85 , \field Value Until Time 85 - A89 , \field Time 86 - \note "until" includes the time entered. - \units hh:mm - N86 , \field Value Until Time 86 - A90 , \field Time 87 - \note "until" includes the time entered. - \units hh:mm - N87 , \field Value Until Time 87 - A91 , \field Time 88 - \note "until" includes the time entered. - \units hh:mm - N88 , \field Value Until Time 88 - A92 , \field Time 89 - \note "until" includes the time entered. - \units hh:mm - N89 , \field Value Until Time 89 - A93 , \field Time 90 - \note "until" includes the time entered. - \units hh:mm - N90 , \field Value Until Time 90 - A94 , \field Time 91 - \note "until" includes the time entered. - \units hh:mm - N91 , \field Value Until Time 91 - A95 , \field Time 92 - \note "until" includes the time entered. - \units hh:mm - N92 , \field Value Until Time 92 - A96 , \field Time 93 - \note "until" includes the time entered. - \units hh:mm - N93 , \field Value Until Time 93 - A97 , \field Time 94 - \note "until" includes the time entered. - \units hh:mm - N94 , \field Value Until Time 94 - A98 , \field Time 95 - \note "until" includes the time entered. - \units hh:mm - N95 , \field Value Until Time 95 - A99 , \field Time 96 - \note "until" includes the time entered. - \units hh:mm - N96 , \field Value Until Time 96 - A100, \field Time 97 - \note "until" includes the time entered. - \units hh:mm - N97 , \field Value Until Time 97 - A101, \field Time 98 - \note "until" includes the time entered. - \units hh:mm - N98 , \field Value Until Time 98 - A102, \field Time 99 - \note "until" includes the time entered. - \units hh:mm - N99 , \field Value Until Time 99 - A103, \field Time 100 - \note "until" includes the time entered. - \units hh:mm - N100, \field Value Until Time 100 - A104, \field Time 101 - \note "until" includes the time entered. - \units hh:mm - N101, \field Value Until Time 101 - A105, \field Time 102 - \note "until" includes the time entered. - \units hh:mm - N102, \field Value Until Time 102 - A106, \field Time 103 - \note "until" includes the time entered. - \units hh:mm - N103, \field Value Until Time 103 - A107, \field Time 104 - \note "until" includes the time entered. - \units hh:mm - N104, \field Value Until Time 104 - A108, \field Time 105 - \note "until" includes the time entered. - \units hh:mm - N105, \field Value Until Time 105 - A109, \field Time 106 - \note "until" includes the time entered. - \units hh:mm - N106, \field Value Until Time 106 - A110, \field Time 107 - \note "until" includes the time entered. - \units hh:mm - N107, \field Value Until Time 107 - A111, \field Time 108 - \note "until" includes the time entered. - \units hh:mm - N108, \field Value Until Time 108 - A112, \field Time 109 - \note "until" includes the time entered. - \units hh:mm - N109, \field Value Until Time 109 - A113, \field Time 110 - \note "until" includes the time entered. - \units hh:mm - N110, \field Value Until Time 110 - A114, \field Time 111 - \note "until" includes the time entered. - \units hh:mm - N111, \field Value Until Time 111 - A115, \field Time 112 - \note "until" includes the time entered. - \units hh:mm - N112, \field Value Until Time 112 - A116, \field Time 113 - \note "until" includes the time entered. - \units hh:mm - N113, \field Value Until Time 113 - A117, \field Time 114 - \note "until" includes the time entered. - \units hh:mm - N114, \field Value Until Time 114 - A118, \field Time 115 - \note "until" includes the time entered. - \units hh:mm - N115, \field Value Until Time 115 - A119, \field Time 116 - \note "until" includes the time entered. - \units hh:mm - N116, \field Value Until Time 116 - A120, \field Time 117 - \note "until" includes the time entered. - \units hh:mm - N117, \field Value Until Time 117 - A121, \field Time 118 - \note "until" includes the time entered. - \units hh:mm - N118, \field Value Until Time 118 - A122, \field Time 119 - \note "until" includes the time entered. - \units hh:mm - N119, \field Value Until Time 119 - A123, \field Time 120 - \note "until" includes the time entered. - \units hh:mm - N120, \field Value Until Time 120 - A124, \field Time 121 - \note "until" includes the time entered. - \units hh:mm - N121, \field Value Until Time 121 - A125, \field Time 122 - \note "until" includes the time entered. - \units hh:mm - N122, \field Value Until Time 122 - A126, \field Time 123 - \note "until" includes the time entered. - \units hh:mm - N123, \field Value Until Time 123 - A127, \field Time 124 - \note "until" includes the time entered. - \units hh:mm - N124, \field Value Until Time 124 - A128, \field Time 125 - \note "until" includes the time entered. - \units hh:mm - N125, \field Value Until Time 125 - A129, \field Time 126 - \note "until" includes the time entered. - \units hh:mm - N126, \field Value Until Time 126 - A130, \field Time 127 - \note "until" includes the time entered. - \units hh:mm - N127, \field Value Until Time 127 - A131, \field Time 128 - \note "until" includes the time entered. - \units hh:mm - N128, \field Value Until Time 128 - A132, \field Time 129 - \note "until" includes the time entered. - \units hh:mm - N129, \field Value Until Time 129 - A133, \field Time 130 - \note "until" includes the time entered. - \units hh:mm - N130, \field Value Until Time 130 - A134, \field Time 131 - \note "until" includes the time entered. - \units hh:mm - N131, \field Value Until Time 131 - A135, \field Time 132 - \note "until" includes the time entered. - \units hh:mm - N132, \field Value Until Time 132 - A136, \field Time 133 - \note "until" includes the time entered. - \units hh:mm - N133, \field Value Until Time 133 - A137, \field Time 134 - \note "until" includes the time entered. - \units hh:mm - N134, \field Value Until Time 134 - A138, \field Time 135 - \note "until" includes the time entered. - \units hh:mm - N135, \field Value Until Time 135 - A139, \field Time 136 - \note "until" includes the time entered. - \units hh:mm - N136, \field Value Until Time 136 - A140, \field Time 137 - \note "until" includes the time entered. - \units hh:mm - N137, \field Value Until Time 137 - A141, \field Time 138 - \note "until" includes the time entered. - \units hh:mm - N138, \field Value Until Time 138 - A142, \field Time 139 - \note "until" includes the time entered. - \units hh:mm - N139, \field Value Until Time 139 - A143, \field Time 140 - \note "until" includes the time entered. - \units hh:mm - N140, \field Value Until Time 140 - A144, \field Time 141 - \note "until" includes the time entered. - \units hh:mm - N141, \field Value Until Time 141 - A145, \field Time 142 - \note "until" includes the time entered. - \units hh:mm - N142, \field Value Until Time 142 - A146, \field Time 143 - \note "until" includes the time entered. - \units hh:mm - N143, \field Value Until Time 143 - A147, \field Time 144 - \note "until" includes the time entered. - \units hh:mm - N144; \field Value Until Time 144 - -Schedule:Day:List, - \memo Schedule:Day:List will allow the user to list 24 hours worth of values, which can be sub-hourly in nature. - \min-fields 5 - \extensible:1 - A1 , \field Name - \required-field - \type alpha - \reference DayScheduleNames - A2 , \field Schedule Type Limits Name - \type object-list - \object-list ScheduleTypeLimitsNames - A3 , \field Interpolate to Timestep - \note when the interval does not match the user specified timestep a "Average" choice will average between the intervals request (to - \note timestep resolution. A "No" choice will use the interval value at the simulation timestep without regard to if it matches - \note the boundary or not. A "Linear" choice will interpolate linearly between successive values. - \type choice - \key Average - \key Linear - \key No - \default No - N1 , \field Minutes per Item - \note Must be evenly divisible into 60 - \type integer - \minimum 1 - \maximum 60 - N2, \field Value 1 - \begin-extensible - \default 0.0 - N3,N4, N5,N6,N7,N8, N9,N10,N11,N12, N13,N14,N15,N16, N17,N18,N19,N20, \note fields as indicated - N21,N22,N23,N24, N25,N26,N27,N28, N29,N30,N31,N32, N33,N34,N35,N36, N37,N38,N39,N40, \note fields as indicated - N41,N42,N43,N44, N45,N46,N47,N48, N49,N50,N51,N52, N53,N54,N55,N56, N57,N58,N59,N60, \note fields as indicated - N61,N62,N63,N64, N65,N66,N67,N68, N69,N70,N71,N72, N73,N74,N75,N76, N77,N78,N79,N80, \note fields as indicated - N81,N82,N83,N84, N85,N86,N87,N88, N89,N90,N91,N92, N93,N94,N95,N96, N97,N98,N99,N100, \note fields as indicated - - N101,N102,N103,N104, N105,N106,N107,N108, N109,N110,N111,N112, N113,N114,N115,N116, N117,N118,N119,N120, \note fields as indicated - N121,N122,N123,N124, N125,N126,N127,N128, N129,N130,N131,N132, N133,N134,N135,N136, N137,N138,N139,N140, \note fields as indicated - N141,N142,N143,N144, N145,N146,N147,N148, N149,N150,N151,N152, N153,N154,N155,N156, N157,N158,N159,N160, \note fields as indicated - N161,N162,N163,N164, N165,N166,N167,N168, N169,N170,N171,N172, N173,N174,N175,N176, N177,N178,N179,N180, \note fields as indicated - N181,N182,N183,N184, N185,N186,N187,N188, N189,N190,N191,N192, N193,N194,N195,N196, N197,N198,N199,N200, \note fields as indicated - - N201,N202,N203,N204, N205,N206,N207,N208, N209,N210,N211,N212, N213,N214,N215,N216, N217,N218,N219,N220, \note fields as indicated - N221,N222,N223,N224, N225,N226,N227,N228, N229,N230,N231,N232, N233,N234,N235,N236, N237,N238,N239,N240, \note fields as indicated - N241,N242,N243,N244, N245,N246,N247,N248, N249,N250,N251,N252, N253,N254,N255,N256, N257,N258,N259,N260, \note fields as indicated - N261,N262,N263,N264, N265,N266,N267,N268, N269,N270,N271,N272, N273,N274,N275,N276, N277,N278,N279,N280, \note fields as indicated - N281,N282,N283,N284, N285,N286,N287,N288, N289,N290,N291,N292, N293,N294,N295,N296, N297,N298,N299,N300, \note fields as indicated - - N301,N302,N303,N304, N305,N306,N307,N308, N309,N310,N311,N312, N313,N314,N315,N316, N317,N318,N319,N320, \note fields as indicated - N321,N322,N323,N324, N325,N326,N327,N328, N329,N330,N331,N332, N333,N334,N335,N336, N337,N338,N339,N340, \note fields as indicated - N341,N342,N343,N344, N345,N346,N347,N348, N349,N350,N351,N352, N353,N354,N355,N356, N357,N358,N359,N360, \note fields as indicated - N361,N362,N363,N364, N365,N366,N367,N368, N369,N370,N371,N372, N373,N374,N375,N376, N377,N378,N379,N380, \note fields as indicated - N381,N382,N383,N384, N385,N386,N387,N388, N389,N390,N391,N392, N393,N394,N395,N396, N397,N398,N399,N400, \note fields as indicated - - N401,N402,N403,N404, N405,N406,N407,N408, N409,N410,N411,N412, N413,N414,N415,N416, N417,N418,N419,N420, \note fields as indicated - N421,N422,N423,N424, N425,N426,N427,N428, N429,N430,N431,N432, N433,N434,N435,N436, N437,N438,N439,N440, \note fields as indicated - N441,N442,N443,N444, N445,N446,N447,N448, N449,N450,N451,N452, N453,N454,N455,N456, N457,N458,N459,N460, \note fields as indicated - N461,N462,N463,N464, N465,N466,N467,N468, N469,N470,N471,N472, N473,N474,N475,N476, N477,N478,N479,N480, \note fields as indicated - N481,N482,N483,N484, N485,N486,N487,N488, N489,N490,N491,N492, N493,N494,N495,N496, N497,N498,N499,N500, \note fields as indicated - - N501,N502,N503,N504, N505,N506,N507,N508, N509,N510,N511,N512, N513,N514,N515,N516, N517,N518,N519,N520, \note fields as indicated - N521,N522,N523,N524, N525,N526,N527,N528, N529,N530,N531,N532, N533,N534,N535,N536, N537,N538,N539,N540, \note fields as indicated - N541,N542,N543,N544, N545,N546,N547,N548, N549,N550,N551,N552, N553,N554,N555,N556, N557,N558,N559,N560, \note fields as indicated - N561,N562,N563,N564, N565,N566,N567,N568, N569,N570,N571,N572, N573,N574,N575,N576, N577,N578,N579,N580, \note fields as indicated - N581,N582,N583,N584, N585,N586,N587,N588, N589,N590,N591,N592, N593,N594,N595,N596, N597,N598,N599,N600, \note fields as indicated - - N601,N602,N603,N604, N605,N606,N607,N608, N609,N610,N611,N612, N613,N614,N615,N616, N617,N618,N619,N620, \note fields as indicated - N621,N622,N623,N624, N625,N626,N627,N628, N629,N630,N631,N632, N633,N634,N635,N636, N637,N638,N639,N640, \note fields as indicated - N641,N642,N643,N644, N645,N646,N647,N648, N649,N650,N651,N652, N653,N654,N655,N656, N657,N658,N659,N660, \note fields as indicated - N661,N662,N663,N664, N665,N666,N667,N668, N669,N670,N671,N672, N673,N674,N675,N676, N677,N678,N679,N680, \note fields as indicated - N681,N682,N683,N684, N685,N686,N687,N688, N689,N690,N691,N692, N693,N694,N695,N696, N697,N698,N699,N700, \note fields as indicated - - N701,N702,N703,N704, N705,N706,N707,N708, N709,N710,N711,N712, N713,N714,N715,N716, N717,N718,N719,N720, \note fields as indicated - N721,N722,N723,N724, N725,N726,N727,N728, N729,N730,N731,N732, N733,N734,N735,N736, N737,N738,N739,N740, \note fields as indicated - N741,N742,N743,N744, N745,N746,N747,N748, N749,N750,N751,N752, N753,N754,N755,N756, N757,N758,N759,N760, \note fields as indicated - N761,N762,N763,N764, N765,N766,N767,N768, N769,N770,N771,N772, N773,N774,N775,N776, N777,N778,N779,N780, \note fields as indicated - N781,N782,N783,N784, N785,N786,N787,N788, N789,N790,N791,N792, N793,N794,N795,N796, N797,N798,N799,N800, \note fields as indicated - - N801,N802,N803,N804, N805,N806,N807,N808, N809,N810,N811,N812, N813,N814,N815,N816, N817,N818,N819,N820, \note fields as indicated - N821,N822,N823,N824, N825,N826,N827,N828, N829,N830,N831,N832, N833,N834,N835,N836, N837,N838,N839,N840, \note fields as indicated - N841,N842,N843,N844, N845,N846,N847,N848, N849,N850,N851,N852, N853,N854,N855,N856, N857,N858,N859,N860, \note fields as indicated - N861,N862,N863,N864, N865,N866,N867,N868, N869,N870,N871,N872, N873,N874,N875,N876, N877,N878,N879,N880, \note fields as indicated - N881,N882,N883,N884, N885,N886,N887,N888, N889,N890,N891,N892, N893,N894,N895,N896, N897,N898,N899,N900, \note fields as indicated - - N901,N902,N903,N904, N905,N906,N907,N908, N909,N910,N911,N912, N913,N914,N915,N916, N917,N918,N919,N920, \note fields as indicated - N921,N922,N923,N924, N925,N926,N927,N928, N929,N930,N931,N932, N933,N934,N935,N936, N937,N938,N939,N940, \note fields as indicated - N941,N942,N943,N944, N945,N946,N947,N948, N949,N950,N951,N952, N953,N954,N955,N956, N957,N958,N959,N960, \note fields as indicated - N961,N962,N963,N964, N965,N966,N967,N968, N969,N970,N971,N972, N973,N974,N975,N976, N977,N978,N979,N980, \note fields as indicated - N981,N982,N983,N984, N985,N986,N987,N988, N989,N990,N991,N992, N993,N994,N995,N996, N997,N998,N999,N1000, \note fields as indicated - - N1001,N1002,N1003,N1004, N1005,N1006,N1007,N1008, N1009,N1010,N1011,N1012, N1013,N1014,N1015,N1016, N1017,N1018,N1019,N1020, \note fields as indicated - N1021,N1022,N1023,N1024, N1025,N1026,N1027,N1028, N1029,N1030,N1031,N1032, N1033,N1034,N1035,N1036, N1037,N1038,N1039,N1040, \note fields as indicated - N1041,N1042,N1043,N1044, N1045,N1046,N1047,N1048, N1049,N1050,N1051,N1052, N1053,N1054,N1055,N1056, N1057,N1058,N1059,N1060, \note fields as indicated - N1061,N1062,N1063,N1064, N1065,N1066,N1067,N1068, N1069,N1070,N1071,N1072, N1073,N1074,N1075,N1076, N1077,N1078,N1079,N1080, \note fields as indicated - N1081,N1082,N1083,N1084, N1085,N1086,N1087,N1088, N1089,N1090,N1091,N1092, N1093,N1094,N1095,N1096, N1097,N1098,N1099,N1100, \note fields as indicated - - N1101,N1102,N1103,N1104, N1105,N1106,N1107,N1108, N1109,N1110,N1111,N1112, N1113,N1114,N1115,N1116, N1117,N1118,N1119,N1120, \note fields as indicated - N1121,N1122,N1123,N1124, N1125,N1126,N1127,N1128, N1129,N1130,N1131,N1132, N1133,N1134,N1135,N1136, N1137,N1138,N1139,N1140, \note fields as indicated - N1141,N1142,N1143,N1144, N1145,N1146,N1147,N1148, N1149,N1150,N1151,N1152, N1153,N1154,N1155,N1156, N1157,N1158,N1159,N1160, \note fields as indicated - N1161,N1162,N1163,N1164, N1165,N1166,N1167,N1168, N1169,N1170,N1171,N1172, N1173,N1174,N1175,N1176, N1177,N1178,N1179,N1180, \note fields as indicated - N1181,N1182,N1183,N1184, N1185,N1186,N1187,N1188, N1189,N1190,N1191,N1192, N1193,N1194,N1195,N1196, N1197,N1198,N1199,N1200, \note fields as indicated - - N1201,N1202,N1203,N1204, N1205,N1206,N1207,N1208, N1209,N1210,N1211,N1212, N1213,N1214,N1215,N1216, N1217,N1218,N1219,N1220,\note fields as indicated - N1221,N1222,N1223,N1224, N1225,N1226,N1227,N1228, N1229,N1230,N1231,N1232, N1233,N1234,N1235,N1236, N1237,N1238,N1239,N1240,\note fields as indicated - N1241,N1242,N1243,N1244, N1245,N1246,N1247,N1248, N1249,N1250,N1251,N1252, N1253,N1254,N1255,N1256, N1257,N1258,N1259,N1260,\note fields as indicated - N1261,N1262,N1263,N1264, N1265,N1266,N1267,N1268, N1269,N1270,N1271,N1272, N1273,N1274,N1275,N1276, N1277,N1278,N1279,N1280,\note fields as indicated - N1281,N1282,N1283,N1284, N1285,N1286,N1287,N1288, N1289,N1290,N1291,N1292, N1293,N1294,N1295,N1296, N1297,N1298,N1299,N1300,\note fields as indicated - - N1301,N1302,N1303,N1304, N1305,N1306,N1307,N1308, N1309,N1310,N1311,N1312, N1313,N1314,N1315,N1316, N1317,N1318,N1319,N1320,\note fields as indicated - N1321,N1322,N1323,N1324, N1325,N1326,N1327,N1328, N1329,N1330,N1331,N1332, N1333,N1334,N1335,N1336, N1337,N1338,N1339,N1340,\note fields as indicated - N1341,N1342,N1343,N1344, N1345,N1346,N1347,N1348, N1349,N1350,N1351,N1352, N1353,N1354,N1355,N1356, N1357,N1358,N1359,N1360,\note fields as indicated - N1361,N1362,N1363,N1364, N1365,N1366,N1367,N1368, N1369,N1370,N1371,N1372, N1373,N1374,N1375,N1376, N1377,N1378,N1379,N1380,\note fields as indicated - N1381,N1382,N1383,N1384, N1385,N1386,N1387,N1388, N1389,N1390,N1391,N1392, N1393,N1394,N1395,N1396, N1397,N1398,N1399,N1400,\note fields as indicated - - N1401,N1402,N1403,N1404, N1405,N1406,N1407,N1408, N1409,N1410,N1411,N1412, N1413,N1414,N1415,N1416, N1417,N1418,N1419,N1420,\note fields as indicated - N1421,N1422,N1423,N1424, N1425,N1426,N1427,N1428, N1429,N1430,N1431,N1432, N1433,N1434,N1435,N1436, N1437,N1438,N1439,N1440,\note fields as indicated - N1441;\note fields as indicated - -Schedule:Week:Daily, - \min-fields 13 - \memo A Schedule:Week:Daily contains 12 Schedule:Day:Hourly objects, one for each day type. - A1 , \field Name - \required-field - \reference WeekScheduleNames - \type alpha - A2 , \field Sunday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A3 , \field Monday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A4 , \field Tuesday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A5 , \field Wednesday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A6 , \field Thursday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A7 , \field Friday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A8 , \field Saturday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A9 , \field Holiday Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A10, \field SummerDesignDay Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A11, \field WinterDesignDay Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A12, \field CustomDay1 Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - A13; \field CustomDay2 Schedule:Day Name - \required-field - \type object-list - \object-list DayScheduleNames - -Schedule:Week:Compact, - \extensible:2 - repeat last two fields, remembering to remove ; from "inner" fields. - \memo Compact definition for Schedule:Day:List - \min-fields 3 - A1 , \field Name - \required-field - \reference WeekScheduleNames - \type alpha - A2 , \field DayType List 1 - \begin-extensible - \note "For" is an optional prefix/start of the For fields. Choices can be combined on single line - \note if separated by spaces. i.e. "Holiday Weekends" - \note Should have a space after For, if it is included. i.e. "For Alldays" - \required-field - \type choice - \key AllDays - \key AllOtherDays - \key Weekdays - \key Weekends - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A3 , \field Schedule:Day Name 1 - \required-field - \type object-list - \object-list DayScheduleNames - A4 , \field DayType List 2 - \type choice - \key AllDays - \key AllOtherDays - \key Weekdays - \key Weekends - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A5 , \field Schedule:Day Name 2 - \type object-list - \object-list DayScheduleNames - A6 , \field DayType List 3 - \type choice - \key AllDays - \key AllOtherDays - \key Weekdays - \key Weekends - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A7 , \field Schedule:Day Name 3 - \type object-list - \object-list DayScheduleNames - A8 , \field DayType List 4 - \type choice - \key AllDays - \key AllOtherDays - \key Weekdays - \key Weekends - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A9 , \field Schedule:Day Name 4 - \type object-list - \object-list DayScheduleNames - A10, \field DayType List 5 - \type choice - \key AllDays - \key AllOtherDays - \key Weekdays - \key Weekends - \key Sunday - \key Monday - \key Tuesday - \key Wednesday - \key Thursday - \key Friday - \key Saturday - \key Holiday - \key SummerDesignDay - \key WinterDesignDay - \key CustomDay1 - \key CustomDay2 - A11; \field Schedule:Day Name 5 - \type object-list - \object-list DayScheduleNames - -Schedule:Year, - \min-fields 7 - \extensible:5 - \memo A Schedule:Year contains from 1 to 52 week schedules - A1 , \field Name - \required-field - \type alpha - \reference ScheduleNames - A2 , \field Schedule Type Limits Name - \type object-list - \object-list ScheduleTypeLimitsNames - A3 , \field Schedule:Week Name 1 - \begin-extensible - \required-field - \type object-list - \object-list WeekScheduleNames - N1 , \field Start Month 1 - \required-field - \type integer - \minimum 1 - \maximum 12 - N2 , \field Start Day 1 - \required-field - \type integer - \minimum 1 - \maximum 31 - N3 , \field End Month 1 - \required-field - \type integer - \minimum 1 - \maximum 12 - N4 , \field End Day 1 - \required-field - \type integer - \minimum 1 - \maximum 31 - A4 , \field Schedule:Week Name 2 - \type object-list - \object-list WeekScheduleNames - N5 , \field Start Month 2 - \type integer - \minimum 1 - \maximum 12 - N6 , \field Start Day 2 - \type integer - \minimum 1 - \maximum 31 - N7 , \field End Month 2 - \type integer - \minimum 1 - \maximum 12 - N8 , \field End Day 2 - \type integer - \minimum 1 - \maximum 31 - A5 , \field Schedule:Week Name 3 - \type object-list - \object-list WeekScheduleNames - N9 , \field Start Month 3 - \type integer - \minimum 1 - \maximum 12 - N10, \field Start Day 3 - \type integer - \minimum 1 - \maximum 31 - N11, \field End Month 3 - \type integer - \minimum 1 - \maximum 12 - N12, \field End Day 3 - \type integer - \minimum 1 - \maximum 31 - A6 , \field Schedule:Week Name 4 - \type object-list - \object-list WeekScheduleNames - N13, \field Start Month 4 - \type integer - \minimum 1 - \maximum 12 - N14, \field Start Day 4 - \type integer - \minimum 1 - \maximum 31 - N15, \field End Month 4 - \type integer - \minimum 1 - \maximum 12 - N16, \field End Day 4 - \type integer - \minimum 1 - \maximum 31 - A7 , \field Schedule:Week Name 5 - \type object-list - \object-list WeekScheduleNames - N17, \field Start Month 5 - \type integer - \minimum 1 - \maximum 12 - N18, \field Start Day 5 - \type integer - \minimum 1 - \maximum 31 - N19, \field End Month 5 - \type integer - \minimum 1 - \maximum 12 - N20, \field End Day 5 - \type integer - \minimum 1 - \maximum 31 - A8 , \field Schedule:Week Name 6 - \type object-list - \object-list WeekScheduleNames - N21, \field Start Month 6 - \type integer - \minimum 1 - \maximum 12 - N22, \field Start Day 6 - \type integer - \minimum 1 - \maximum 31 - N23, \field End Month 6 - \type integer - \minimum 1 - \maximum 12 - N24, \field End Day 6 - \type integer - \minimum 1 - \maximum 31 - A9 , \field Schedule:Week Name 7 - \type object-list - \object-list WeekScheduleNames - N25, \field Start Month 7 - \type integer - \minimum 1 - \maximum 12 - N26, \field Start Day 7 - \type integer - \minimum 1 - \maximum 31 - N27, \field End Month 7 - \type integer - \minimum 1 - \maximum 12 - N28, \field End Day 7 - \type integer - \minimum 1 - \maximum 31 - A10, \field Schedule:Week Name 8 - \type object-list - \object-list WeekScheduleNames - N29, \field Start Month 8 - \type integer - \minimum 1 - \maximum 12 - N30, \field Start Day 8 - \type integer - \minimum 1 - \maximum 31 - N31, \field End Month 8 - \type integer - \minimum 1 - \maximum 12 - N32, \field End Day 8 - \type integer - \minimum 1 - \maximum 31 - A11, \field Schedule:Week Name 9 - \type object-list - \object-list WeekScheduleNames - N33, \field Start Month 9 - \type integer - \minimum 1 - \maximum 12 - N34, \field Start Day 9 - \type integer - \minimum 1 - \maximum 31 - N35, \field End Month 9 - \type integer - \minimum 1 - \maximum 12 - N36, \field End Day 9 - \type integer - \minimum 1 - \maximum 31 - A12, \field Schedule:Week Name 10 - \type object-list - \object-list WeekScheduleNames - N37, \field Start Month 10 - \type integer - \minimum 1 - \maximum 12 - N38, \field Start Day 10 - \type integer - \minimum 1 - \maximum 31 - N39, \field End Month 10 - \type integer - \minimum 1 - \maximum 12 - N40, \field End Day 10 - \type integer - \minimum 1 - \maximum 31 - A13, \field Schedule:Week Name 11 - \type object-list - \object-list WeekScheduleNames - N41, \field Start Month 11 - \type integer - \minimum 1 - \maximum 12 - N42, \field Start Day 11 - \type integer - \minimum 1 - \maximum 31 - N43, \field End Month 11 - \type integer - \minimum 1 - \maximum 12 - N44, \field End Day 11 - \type integer - \minimum 1 - \maximum 31 - A14, \field Schedule:Week Name 12 - \type object-list - \object-list WeekScheduleNames - N45, \field Start Month 12 - \type integer - \minimum 1 - \maximum 12 - N46, \field Start Day 12 - \type integer - \minimum 1 - \maximum 31 - N47, \field End Month 12 - \type integer - \minimum 1 - \maximum 12 - N48, \field End Day 12 - \type integer - \minimum 1 - \maximum 31 - A15, \field Schedule:Week Name 13 - \type object-list - \object-list WeekScheduleNames - N49, \field Start Month 13 - \type integer - \minimum 1 - \maximum 12 - N50, \field Start Day 13 - \type integer - \minimum 1 - \maximum 31 - N51, \field End Month 13 - \type integer - \minimum 1 - \maximum 12 - N52, \field End Day 13 - \type integer - \minimum 1 - \maximum 31 - A16, \field Schedule:Week Name 14 - \type object-list - \object-list WeekScheduleNames - N53, \field Start Month 14 - \type integer - \minimum 1 - \maximum 12 - N54, \field Start Day 14 - \type integer - \minimum 1 - \maximum 31 - N55, \field End Month 14 - \type integer - \minimum 1 - \maximum 12 - N56, \field End Day 14 - \type integer - \minimum 1 - \maximum 31 - A17, \field Schedule:Week Name 15 - \type object-list - \object-list WeekScheduleNames - N57, \field Start Month 15 - \type integer - \minimum 1 - \maximum 12 - N58, \field Start Day 15 - \type integer - \minimum 1 - \maximum 31 - N59, \field End Month 15 - \type integer - \minimum 1 - \maximum 12 - N60, \field End Day 15 - \type integer - \minimum 1 - \maximum 31 - A18, \field Schedule:Week Name 16 - \type object-list - \object-list WeekScheduleNames - N61, \field Start Month 16 - \type integer - \minimum 1 - \maximum 12 - N62, \field Start Day 16 - \type integer - \minimum 1 - \maximum 31 - N63, \field End Month 16 - \type integer - \minimum 1 - \maximum 12 - N64, \field End Day 16 - \type integer - \minimum 1 - \maximum 31 - A19, \field Schedule:Week Name 17 - \type object-list - \object-list WeekScheduleNames - N65, \field Start Month 17 - \type integer - \minimum 1 - \maximum 12 - N66, \field Start Day 17 - \type integer - \minimum 1 - \maximum 31 - N67, \field End Month 17 - \type integer - \minimum 1 - \maximum 12 - N68, \field End Day 17 - \type integer - \minimum 1 - \maximum 31 - A20, \field Schedule:Week Name 18 - \type object-list - \object-list WeekScheduleNames - N69, \field Start Month 18 - \type integer - \minimum 1 - \maximum 12 - N70, \field Start Day 18 - \type integer - \minimum 1 - \maximum 31 - N71, \field End Month 18 - \type integer - \minimum 1 - \maximum 12 - N72, \field End Day 18 - \type integer - \minimum 1 - \maximum 31 - A21, \field Schedule:Week Name 19 - \type object-list - \object-list WeekScheduleNames - N73, \field Start Month 19 - \type integer - \minimum 1 - \maximum 12 - N74, \field Start Day 19 - \type integer - \minimum 1 - \maximum 31 - N75, \field End Month 19 - \type integer - \minimum 1 - \maximum 12 - N76, \field End Day 19 - \type integer - \minimum 1 - \maximum 31 - A22, \field Schedule:Week Name 20 - \type object-list - \object-list WeekScheduleNames - N77, \field Start Month 20 - \type integer - \minimum 1 - \maximum 12 - N78, \field Start Day 20 - \type integer - \minimum 1 - \maximum 31 - N79, \field End Month 20 - \type integer - \minimum 1 - \maximum 12 - N80, \field End Day 20 - \type integer - \minimum 1 - \maximum 31 - A23, \field Schedule:Week Name 21 - \type object-list - \object-list WeekScheduleNames - N81, \field Start Month 21 - \type integer - \minimum 1 - \maximum 12 - N82, \field Start Day 21 - \type integer - \minimum 1 - \maximum 31 - N83, \field End Month 21 - \type integer - \minimum 1 - \maximum 12 - N84, \field End Day 21 - \type integer - \minimum 1 - \maximum 31 - A24, \field Schedule:Week Name 22 - \type object-list - \object-list WeekScheduleNames - N85, \field Start Month 22 - \type integer - \minimum 1 - \maximum 12 - N86, \field Start Day 22 - \type integer - \minimum 1 - \maximum 31 - N87, \field End Month 22 - \type integer - \minimum 1 - \maximum 12 - N88, \field End Day 22 - \type integer - \minimum 1 - \maximum 31 - A25, \field Schedule:Week Name 23 - \type object-list - \object-list WeekScheduleNames - N89, \field Start Month 23 - \type integer - \minimum 1 - \maximum 12 - N90, \field Start Day 23 - \type integer - \minimum 1 - \maximum 31 - N91, \field End Month 23 - \type integer - \minimum 1 - \maximum 12 - N92, \field End Day 23 - \type integer - \minimum 1 - \maximum 31 - A26, \field Schedule:Week Name 24 - \type object-list - \object-list WeekScheduleNames - N93, \field Start Month 24 - \type integer - \minimum 1 - \maximum 12 - N94, \field Start Day 24 - \type integer - \minimum 1 - \maximum 31 - N95, \field End Month 24 - \type integer - \minimum 1 - \maximum 12 - N96, \field End Day 24 - \type integer - \minimum 1 - \maximum 31 - A27, \field Schedule:Week Name 25 - \type object-list - \object-list WeekScheduleNames - N97, \field Start Month 25 - \type integer - \minimum 1 - \maximum 12 - N98, \field Start Day 25 - \type integer - \minimum 1 - \maximum 31 - N99, \field End Month 25 - \type integer - \minimum 1 - \maximum 12 - N100, \field End Day 25 - \type integer - \minimum 1 - \maximum 31 - A28, \field Schedule:Week Name 26 - \type object-list - \object-list WeekScheduleNames - N101, \field Start Month 26 - \type integer - \minimum 1 - \maximum 12 - N102, \field Start Day 26 - \type integer - \minimum 1 - \maximum 31 - N103, \field End Month 26 - \type integer - \minimum 1 - \maximum 12 - N104, \field End Day 26 - \type integer - \minimum 1 - \maximum 31 - \note Schedule:Week for Weeks 27-53 are condensed - A29,N105,N106,N107,N108, \note For Week 27 - A30,N109,N110,N111,N112, \note For Week 28 - A31,N113,N114,N115,N116, \note For Week 29 - A32,N117,N118,N119,N120, \note For Week 30 - A33,N121,N122,N123,N124, \note For Week 31 - A34,N125,N126,N127,N128, \note For Week 32 - A35,N129,N130,N131,N132, \note For Week 33 - A36,N133,N134,N135,N136, \note For Week 34 - A37,N137,N138,N139,N140, \note For Week 35 - A38,N141,N142,N143,N144, \note For Week 36 - A39,N145,N146,N147,N148, \note For Week 37 - A40,N149,N150,N151,N152, \note For Week 38 - A41,N153,N154,N155,N156, \note For Week 39 - A42,N157,N158,N159,N160, \note For Week 40 - A43,N161,N162,N163,N164, \note For Week 41 - A44,N165,N166,N167,N168, \note For Week 42 - A45,N169,N170,N171,N172, \note For Week 43 - A46,N173,N174,N175,N176, \note For Week 44 - A47,N177,N178,N179,N180, \note For Week 45 - A48,N181,N182,N183,N184, \note For Week 46 - A49,N185,N186,N187,N188, \note For Week 47 - A50,N189,N190,N191,N192, \note For Week 48 - A51,N193,N194,N195,N196, \note For Week 49 - A52,N197,N198,N199,N200, \note For Week 50 - A53,N201,N202,N203,N204, \note For Week 51 - A54,N205,N206,N207,N208, \note For Week 52 - A55,N209,N210,N211,N212; \note For Week 53 - -Schedule:Compact, - \extensible:1 - repeat last field, remembering to remove ; from "inner" fields. - \min-fields 5 - \memo Irregular object. Does not follow the usual definition for fields. Fields A3... are: - \memo Through: Date - \memo For: Applicable days (ref: Schedule:Week:Compact) - \memo Interpolate: Average/Linear/No (ref: Schedule:Day:Interval) -- optional, if not used will be "No" - \memo Until: