Utilities#
smart_control.simulator.constants
#
Defines constants for use in simulation code suite.
smart_control.simulator.building_utils
#
Utils for computing the physical and thermal characteristics of buildings.
RoomIndicesDict
module-attribute
#
Note: The following four types all describe various aspects of the same
floorplan; i.e. all four types have the same dimensionality and encode similar variations of the same information. Here I will describe the differences between the types: (1) FileInputFloorPlan: the floorplan format as entered into the program. This specifically notes exterior space as 2's, walls as 1's, and inside space as 0's. This file type may have various "glitches" that the program will correct, such as walls that abut directly the frame of the image. (2) ConnectionReadyFloorPlan: the floorplan format as processed and ready for the opencv function connectedComponents . This format requires a very specific input type, namely 1's where there is open space and 0's everywhere else. Therefore, prior to this step, various pieces of information must be removed from the floor plan, such as the location of exterior space, and stored in other datatypes. (3) Connections: the floorplan format after opencv's connectedComponents is run on it. The Connections floorplan has each connected component, defined as the contiguous space within each component of interest (room, zone, etc.) labelled with an increasing integer indexing the component. It is an np.ndarray where 0's are walls and connected contiguous space are increasing integers. (4) ExteriorSpace: the floorplan format serves an auxiliary store of information so that the original floorplan can be stripped of a specific designation for exterior space in order to be prepared for ingestion into connectedComponents. It is an np.ndarray where 0's are walls or interior space and exterior space is marked with -1. (5) ExteriorWalls: a floorplan format that notes where exterior walls are with 1's and everywhere else with 0's. (6) InteriorWalls: a floorplan format that notes where interior walls are with -3 and everywhere else with 0's.
construct_building_data_types
#
construct_building_data_types(
floor_plan: FileInputFloorPlan,
zone_map: FileInputFloorPlan,
save_debugging_image: bool = False,
) -> Tuple[RoomIndicesDict, ExteriorWalls, InteriorWalls, ExteriorSpace]
Sequentially calls all preprocessing functions in building_utils.py.
This function links together the necessary helper functions in building_utils.py so that it is clear and straightforward what they do when put in sequence. Given a FileInputFloorPlan, this function breaks out the necessary pieces of information for further processing.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
floor_plan
|
FileInputFloorPlan
|
an FileInputFloorPlan with outside air marked as constants.EXTERIOR_SPACE_VALUE_IN_FILE_INPUT, inside walls marked as constants.INTERIOR_WALL_VALUE_IN_FILE_INPUT, and inside space marked as constants.INTERIOR_SPACE_VALUE_IN_FILE_INPUT. |
required |
zone_map
|
FileInputFloorPlan
|
a FileInputFloorPlan that has, using the same int markings as the floor_plan, the VAV zones noted instead of the physical rooms. |
required |
save_debugging_image
|
bool
|
bool for whether we should save some debugging images to CNS. |
False
|
Returns:
Type | Description |
---|---|
Tuple[RoomIndicesDict, ExteriorWalls, InteriorWalls, ExteriorSpace]
|
connections output with exterior space set negative. |
enlarge_component
#
enlarge_component(
array_with_component_nonzero: ndarray, distance_to_augment: float
) -> np.ndarray
Enlarges the component in question by CVs within a certain distance.
Note: this function is a general purpose function intended to enlarge any component by measure of "distance_to_augment".
Parameters:
Name | Type | Description | Default |
---|---|---|---|
array_with_component_nonzero
|
ndarray
|
array where the object to enlarge is nonzero |
required |
distance_to_augment
|
float
|
return a new object with CVs within this distance selected. |
required |
Returns:
Type | Description |
---|---|
ndarray
|
An array with 1 being a CV to include and 0 being a CV to exclude. |
guarantee_air_padding_in_frame
#
Adds a row or column of air if a building is abuts its frame edge.
Future computation relies on buildings being surrounded by at least one layer of air CVs between them and the edge of the floor plan frame. However, due to human variation in preparing floor plans for transformation into arrays, we may have the case where a floor plan is passed in that has wall CVs at the edge of the frame. Thus, this function should check that that is the case and will add a layer of exterior space CVs if building lies against the array's edge.
If walls are touching more than
one edge of the floor plan, the function should be able to compute this -- but if it adds rows of CVs and then does not update the shape of the floor plan, it will fail. Thus, we package the dimension tracking and rows to concatenate in a convenient helper function so it can be called multiple times without repetitive code.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
floor_plan
|
FileInputFloorPlan
|
a FileInputFloorPlan |
required |
Returns:
Type | Description |
---|---|
FileInputFloorPlan
|
an FileInputFloorPlan that has 2's padded along whichever array edge was missing them. |
process_and_run_connected_components
#
Public function that takes in floor plan and outputs a Components.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
floor_plan
|
FileInputFloorPlan
|
FileInputFloorPlan |
required |
Returns:
Type | Description |
---|---|
Connections
|
connections output with exterior space set negative. |
read_floor_plan_from_filepath
#
read_floor_plan_from_filepath(
filepath: str, save_debugging_image: bool = False
) -> FileInputFloorPlan
Reads a file from a disk (including CNS) and returns it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
filepath
|
str
|
name of the location on CNS. CSV and NPY files are supported, and they are both determined by the semantic naming of the path, i.e. the file type suffix. |
required |
save_debugging_image
|
bool
|
boolean for whether we should save the debugging image to cns. |
False
|
Returns:
Type | Description |
---|---|
FileInputFloorPlan
|
a FileInputFloorPlan |
save_images_to_cns_for_debugging
#
save_images_to_cns_for_debugging(
floor_plan: Union[
FileInputFloorPlan,
Connections,
ExteriorWalls,
InteriorWalls,
ndarray,
ConnectionReadyFloorPlan,
],
path_ending: str,
path_to_simulator_cns: str = "/cns/oi-d/home/smart_buildings/control/configs/simulation/",
) -> None
Saves a .png of a floorplan array to CNS for visual debugging.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
floor_plan
|
Union[FileInputFloorPlan, Connections, ExteriorWalls, InteriorWalls, ndarray, ConnectionReadyFloorPlan]
|
one of the floor_plan types |
required |
path_ending
|
str
|
a path suffix to end saved files |
required |
path_to_simulator_cns
|
str
|
base path to save the files on CNS. |
'/cns/oi-d/home/smart_buildings/control/configs/simulation/'
|
smart_control.simulator.building_radiation_utils
#
Building Radiation Utility Functions
For computing the physical and thermal characteristics of buildings.
calculate_A_tilde_inv
#
Calculates the A-tilde matrix used in radiative heat transfer calculations.
The A-tilde matrix relates the radiosity to the blackbody emissive power in a radiative heat transfer system. It accounts for both emission and reflection.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
epsilon
|
ndarray
|
Array of surface emissivity values (between 0 and 1) |
required |
F
|
ndarray
|
View factor matrix |
required |
Returns:
Type | Description |
---|---|
ndarray
|
The A-tilde matrix relating radiosity to blackbody emissive power |
Raises:
Type | Description |
---|---|
AssertionError
|
If emissivity vector size doesn't match view factor matrix or if emissivity values are outside [0,1] |
calculate_IFAinv
#
Calculates the \(IFA_{inv}\) matrix.
See net_radiative_heatflux_function_of_T
for more details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
F
|
ndarray
|
The view factor matrix. |
required |
A_inv
|
ndarray
|
The A inverse matrix. |
required |
Returns:
Name | Type | Description |
---|---|---|
IFA_inv |
ndarray
|
The IFA inverse matrix. |
net_radiative_heatflux_function_of_T
#
Calculates the net radiative heat flux and radiosity for all surfaces given surface temperatures.
Equations:#
The net radiative heat flux leaving surface \(i\) is:
where: - \(J_i\) is the radiosity (total outgoing radiative flux) from surface \(i\), - \(G_i\) is the irradiation (total incoming radiative flux) onto surface \(i\).
The radiosity is given by:
where \(\epsilon_i\) is the emissivity, \(\rho_i = 1 - \epsilon_i\) is the reflectivity (for opaque surfaces), and \(E_{b,i}\) is the blackbody emission from \(i\) surface.
The irradiation for the \(i\) surface is:
where \(F_{ji}\) is the view factor from surface \(j\) to \(i\).
Combining these, the radiosity equation for all surfaces can be written in vector-matrix form as:
where \(\tilde{A}_{ij} = \delta_{ij} - \frac{(1-\epsilon_i) F_{ij}}{\epsilon_i}\).
Solving for \(\mathbf{J}\):
The net heat flux vector for all surfaces is:
where \(\tilde{\mathbf{F}}\) is the matrix of view factors, \(F_{ij}\) and\(\mathbf{E}_b\) is \(\sigma \mathbf{T}^4\).
Nomenclature and Units:#
- \(q_i\) : Net radiative heat flux from surface \(i\) [\(\mathrm{W/m^2}\)]
- \(\mathbf{q}\) : Vector of \(q_i\) for all \(i=1..n\) [\(\mathrm{W/m^2}\)]
- \(J_i\) : Radiosity of surface \(i\) [\(\mathrm{W/m^2}\)]
- \(\mathbf{J}\) : Vector of \(J_i\) for all \(i=1..n\) [\(\mathrm{W/m^2}\)]
- \(G_i\) : Irradiation on surface \(i\) [\(\mathrm{W/m^2}\)]
- \(E_{b,i}\) : Blackbody emissive power of surface \(i\) [\(\mathrm{W/m^2}\)]$
- \(\mathbf{E}_b\): Vector of \(E_{b,i}\) for all \(i=1..n\) [\(\mathrm{W/m^2}\)]
- \(\epsilon_i\) : Emissivity of surface \(i\) [dimensionless]
- \(\rho_i\) : Reflectivity of surface \(i\) [dimensionless], (\(\rho_i=1-\epsilon_i\))
- \(A_i\) : Area of surface \(i\) [\(\mathrm{m^2}\)]
- \(F_{ij}\) : View factor from surface \(i\) to \(j\) [dimensionless]
- \(\tilde{\mathbf{A}}\): Matrix with elements (\(\tilde{A}_{ij} = \delta_{ij} - \frac{(1-\epsilon_i) F_{ij}}{\epsilon_i}\))
- \(\mathbf{I}\) : \(n \times n\) identity matrix
- \(\tilde{\mathbf{F}}\): Matrix of \(F_{ij}\) (view factors)
- \(\delta_{ij}\): Kronecker delta (\(=1\) if \(i=j\), \(=0\) otherwise)
- \(\sigma\): Stefan-Boltzmann constant [\(\mathrm{W/m^2K^4}\)]
- \(\mathbf{T}\): Vector of surface temperatures [K]
References:#
- Incropera, F.P., DeWitt, D.P., "Fundamentals of Heat and Mass Transfer"
Parameters:
Name | Type | Description | Default |
---|---|---|---|
T
|
ndarray
|
Surface temperatures in Kelvin. |
required |
IFAinv
|
ndarray
|
(I - F) @ A_inv. |
required |
Returns:
Name | Type | Description |
---|---|---|
q |
array
|
Net radiative heat flux [W/m^2] |
mark_air_connected_interior_walls
#
mark_air_connected_interior_walls(
indexed_floor_plan: ndarray,
start_pos: Tuple[int, int],
interior_wall_value: int = constants.INTERIOR_WALL_VALUE_IN_FUNCTION,
marked_value: int = TEMPORARY_MARKED_VALUE,
air_value: int = constants.INTERIOR_SPACE_VALUE_IN_FUNCTION,
) -> Tuple[Optional[np.ndarray], Optional[np.ndarray]]
Mark all interior wall nodes that are connected to the same air space as the starting interior wall. Uses 4-directional connectivity to check wall-air adjacency. All connected walls including the starting position are marked.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
indexed_floor_plan
|
ndarray
|
2D numpy array representing the floor plan where different values represent different types of cells (walls, air, etc.). |
required |
start_pos
|
Tuple[int, int]
|
Starting position (row, col) of the interior wall to begin marking from. |
required |
interior_wall_value
|
int
|
Value used to represent interior walls in the floor plan. Defaults to -3 (from constants.py). |
INTERIOR_WALL_VALUE_IN_FUNCTION
|
marked_value
|
int
|
Value used to mark connected interior walls. Only used internally. Defaults to -33. |
TEMPORARY_MARKED_VALUE
|
air_value
|
int
|
Value used to represent air spaces in the floor plan. Defaults to 0 (from constants.py). |
INTERIOR_SPACE_VALUE_IN_FUNCTION
|
Returns:
Type | Description |
---|---|
Tuple[Optional[ndarray], Optional[ndarray]]
|
A tuple containing:
|
Raises:
Type | Description |
---|---|
ValueError
|
If the starting position is out of bounds of the floor plan. |
Note
This function is used as the first step in radiative heat transfer calculations to identify all interior wall nodes that are connected to the same air space. The marked_value (-33) indicates walls that can potentially participate in radiative heat transfer with each other.
fix_view_factors
#
Fix approximate view factors and enforce reciprocity and completeness.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
F
|
ndarray
|
Approximate direct view factor matrix (N x N) |
required |
A
|
ndarray
|
Area vector (N elements). Defaults to None. |
None
|
Returns:
Type | Description |
---|---|
ndarray
|
Fixed view factor matrix |
References
See FixViewFactors
function in EnergyPlus
get_VF
#
get_VF(
indexed_floor_plan: ndarray,
interior_wall_mask: ndarray,
view_factor_method: str = "ScriptF",
marked_value: int = TEMPORARY_MARKED_VALUE,
) -> np.ndarray
Calculate view factors between interior walls in the floor plan.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
indexed_floor_plan
|
ndarray
|
2D array representing the floor plan with indexed values. |
required |
view_factor_method
|
str
|
Method to use for view factors. Defaults to 'ScriptF'. Either "ScriptF" or "CarrollMRT". |
'ScriptF'
|
marked_value
|
int
|
Value used to mark connected interior walls. Only used internally. Defaults to -33. |
TEMPORARY_MARKED_VALUE
|
Returns:
Type | Description |
---|---|
ndarray
|
View factor matrix where |
mark_interior_wall_adjacent_to_air
#
mark_interior_wall_adjacent_to_air(
arr: ndarray,
interior_wall_value: int = constants.INTERIOR_WALL_VALUE_IN_FUNCTION,
air_value: int = constants.INTERIOR_SPACE_VALUE_IN_FUNCTION,
) -> np.ndarray
Marks interior walls that are adjacent to air spaces.
Creates a boolean mask identifying interior walls that share an edge with an air space (value of 0) in the floor plan. Checks for adjacency in four directions: up, down, left, and right.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
arr
|
ndarray
|
2D array representing the floor plan with interior walls marked as interior_wall_value and air spaces as 0. |
required |
interior_wall_value
|
int
|
Value used to represent interior walls in the floor plan. Defaults to -3 (constants.INTERIOR_WALL_VALUE_IN_FUNCTION). |
INTERIOR_WALL_VALUE_IN_FUNCTION
|
Returns:
Type | Description |
---|---|
ndarray
|
Boolean mask array where True indicates an interior wall that is adjacent to |
ndarray
|
at least one air space. |
get_line_points
#
get_line_points(
start: Tuple[float, float], end: Tuple[float, float]
) -> list[Tuple[float, float]]
Generate points where the line crosses integer grid lines.
This function calculates all intersection points between a line segment and the integer grid lines. It handles vertical, horizontal, and diagonal lines by finding intersections with both vertical (x = integer) and horizontal (y = integer) grid lines.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
start
|
Tuple[float, float]
|
Starting point of the line segment as (x, y) coordinates. |
required |
end
|
Tuple[float, float]
|
Ending point of the line segment as (x, y) coordinates. |
required |
Returns:
Type | Description |
---|---|
list[Tuple[float, float]]
|
List of intersection points sorted by distance from the start point. Each point is a tuple of (x, y) coordinates as floats. |
is_line_blocked
#
is_line_blocked(
floor_plan: ndarray,
start: Tuple[float, float],
end: Tuple[float, float],
interior_wall_value: int = constants.INTERIOR_WALL_VALUE_IN_FUNCTION,
marked_value: int = TEMPORARY_MARKED_VALUE,
blocked_value: int = TEMPORARY_BLOCKED_VALUE,
) -> bool
Check if the line between start and end is blocked by walls.
This function determines if a line of sight between two points is blocked by walls in the floor plan. It checks all grid intersections along the line and determines if the line is blocked by examining the 4 surrounding grid cells at each intersection point.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
floor_plan
|
ndarray
|
2D numpy array representing the floor plan where different values represent different types of cells (walls, air, etc.). |
required |
start
|
Tuple[float, float]
|
Starting point of the line as (x, y) coordinates. |
required |
end
|
Tuple[float, float]
|
Ending point of the line as (x, y) coordinates. |
required |
interior_wall_value
|
int
|
Value used to represent interior walls in the floor plan. Defaults to -3 (from constants.py). |
INTERIOR_WALL_VALUE_IN_FUNCTION
|
marked_value
|
int
|
Value used to represent marked wall nodes. Only used internally. Defaults: -33. Only used internally. |
TEMPORARY_MARKED_VALUE
|
blocked_value
|
int
|
Value used to represent blocked wall nodes. Only used internally. Default: -34. Only used internally. |
TEMPORARY_BLOCKED_VALUE
|
Returns:
Type | Description |
---|---|
bool
|
True if the line is blocked by walls, False if the line of sight is clear. |
Note
The function considers a line blocked if all 4 grid cells surrounding an intersection point are walls (values -3, -33, or -34).
are_neighbors
#
Check if two positions are physically neighboring (adjacent).
This function determines if two grid positions are adjacent to each other using 4-connectivity. Two positions are considered neighbors if they are within 1 unit distance in both x and y directions, but not the same position.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
pos1
|
Tuple[int, int]
|
First position as (row, col) coordinates. |
required |
pos2
|
Tuple[int, int]
|
Second position as (row, col) coordinates. |
required |
Returns:
Type | Description |
---|---|
bool
|
True if the positions are neighbors, False otherwise. |
mark_directly_seeing_nodes
#
mark_directly_seeing_nodes(
floor_plan: ndarray,
base_node: Tuple[int, int],
interior_wall_value: int = constants.INTERIOR_WALL_VALUE_IN_FUNCTION,
marked_value: int = TEMPORARY_MARKED_VALUE,
blocked_value: int = TEMPORARY_BLOCKED_VALUE,
) -> np.ndarray
Mark nodes that are directly seeing the base node as blocked_value.
This function identifies and marks wall nodes that have a direct line of sight to the base node. It processes all connected wall nodes (marked with marked_value) and determines which ones can directly see the base node without being blocked by other walls.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
floor_plan
|
ndarray
|
2D numpy array representing the floor plan where different values represent different types of cells (walls, air, etc.). |
required |
base_node
|
Tuple[int, int]
|
Position of the base node as (row, col) coordinates. |
required |
interior_wall_value
|
int
|
Value used to represent interior walls in the floor plan. Defaults to -3 (from constants.py). |
INTERIOR_WALL_VALUE_IN_FUNCTION
|
marked_value
|
int
|
Value used to represent connected wall nodes that should be checked for line of sight. Only used internally. Defaults to -33. |
TEMPORARY_MARKED_VALUE
|
blocked_value
|
int
|
Value used to mark nodes that cannot directly see the base node. Only used internally. Defaults to -34. |
TEMPORARY_BLOCKED_VALUE
|
Returns:
Type | Description |
---|---|
ndarray
|
Copy of the floor plan with nodes marked according to their visibility to the base node. Nodes that cannot see the base node are marked with blocked_value, and the base node itself is marked with blocked_value + marked_value. |
Note
- Neighboring nodes are automatically marked as blocked (no line of sight calculation needed).
- For non-neighboring nodes, the function checks if the line of sight is blocked by walls using is_line_blocked().
- The base node itself is marked with a special value to distinguish it.
- Value meanings for radiative heat transfer:
- marked_value (-33): Interior wall nodes connected to the same air space (can participate in radiative transfer)
- blocked_value (-34): Interior wall nodes that cannot see the base node (blocked from radiative transfer)
- blocked_value + marked_value (-67): The starting node itself
smart_control.simulator.thermal_diffuser_utils
#
Code for generating thermal diffusers in a building.
These helper functions are separated these out into their own file for extensibility: we can easily put in another function loading these from data and process this using similar function format.
diffuser_allocation_switch
#
diffuser_allocation_switch(
room_cv_indices: Collection[Coordinates2D],
spacing: int = 10,
interior_walls: Optional[InteriorWalls] = None,
buffer_from_walls: int = 2,
) -> Collection[Coordinates2D]
Switches between random and even assignment of thermal diffusers.
A more in-depth explanation: here we provide a method for allocating thermal diffusers that is general for many types of rooms. At a high level, if a room is rectangular enough, we allocate diffusers evenly according to a grid determined by the input "spacing", and then only select the points that are inside the original set of room indices to ensure we don't place a diffuser outside. If a room is too insanely shaped (i.e. imagine a long snaking hallway or an entryway to a few private alcoves) we instead try to ensure that the appropriate number of diffusers are still placed, but for simplicity we place them randomly. This option is almost never taken, as most rooms are deemed rectangular enough according to our measure:
Here, from the number of CVs that define a room, extract the total number of CVs (num_CVs), the maximum and minimum x coordinates (x_max, x_min), and the maximum and minimum y coordinates (y_max, y_min), and set a threshold. If num_CVs / ((x_max - x_min) * (y_max - y_min)) > threshold, it is rectangular enough.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
room_cv_indices
|
Collection[Coordinates2D]
|
a list of indices making up a room. |
required |
spacing
|
int
|
how many control volumes to put between each diffuser |
10
|
interior_walls
|
Optional[InteriorWalls]
|
an InteriorWalls for determining whether thermal diffusers are allocated in walls. This measure is intended for cases in which one needs to provide a interior_walls and zone_map to the Building class, and they may not line up correctly on account of being from different photo sources. |
None
|
buffer_from_walls
|
int
|
how far to place a thermal diffuser away from a wall. |
2
|
Returns:
Type | Description |
---|---|
Collection[Coordinates2D]
|
a list of inds to place diffusers. |