Energy Model with Openstudio

Import the needed classes

# Import the needed classes
from topologicpy.Vertex import Vertex
from topologicpy.Face import Face
from topologicpy.Cell import Cell
from topologicpy.CellComplex import CellComplex
from topologicpy.Cluster import Cluster
from topologicpy.Topology import Topology
from topologicpy.Dictionary import Dictionary
from topologicpy.Color import Color
from topologicpy.Plotly import Plotly
from topologicpy.EnergyModel import EnergyModel
from topologicpy.Helper import Helper
print("\nDONE")

DONE
import openstudio
result = getattr(openstudio, "openStudioVersion", None)
result()
'3.11.0'

Check software versions

import sys
print("This workflow was designed and verified to work with python 3.11, TopologicPy 0.8.54 and OpenStudio SDK 3.10.0.\n")
py_version = sys.version.split()[0]
print("Python version:", py_version)

print("TopologicPy Version:", Helper.Version(check=False))
print("OpenStudio SDK Version:", EnergyModel.Version(check=False))
print(" ")
print("TopologicPy Version:", Helper.Version(check=True))
print("OpenStudio SDK Version:", EnergyModel.Version(check=True))
print("\nDONE")
This workflow was designed and verified to work with python 3.11, TopologicPy 0.8.54 and OpenStudio SDK 3.10.0.

Python version: 3.13.12
TopologicPy Version: 0.9.5
OpenStudio SDK Version: 3.11.0
 
TopologicPy Version: The version that you are using (0.9.5) is EQUAL TO the latest version available on PyPI.
OpenStudio SDK Version: The version that you are using (3.11.0) is EQUAL TO the latest version available on PyPI.

DONE

Set the input variables for path names and load geometries

import pathlib
fdir = pathlib.Path("..")
weatherFilePath = fdir / "assets" / "EnergyModel"/ "GBR_London.Gatwick.037760_IWEC.epw"
designDayFilePath = fdir / "assets" / "EnergyModel" / "GBR_London.Gatwick.037760_IWEC.ddy"
# osBinaryPath = r"C:" / "openstudio-3.10.0" / "bin" / "openstudio.exe"

buildingPath = fdir / "assets" / "EnergyModel" / "TopologicBuilding.brep"
shadingPath = fdir / "assets" / "EnergyModel" / "TopologicShadingSurfaces.brep"
osModelPath = fdir / "assets" / "EnergyModel" / "OSMTemplate-OfficeBuilding-3.10.0.osm"
outputFolder = fdir / "EnergyModels"
outputFolder.mkdir(exist_ok=True)

assert buildingPath.is_file()
weatherFilePath, designDayFilePath, buildingPath, shadingPath, osModelPath, outputFolder = [str(x.resolve()) for x in [weatherFilePath, designDayFilePath, buildingPath, shadingPath, osModelPath, outputFolder]]
osModelPath
'/home/runner/work/topologicpy/topologicpy/assets/EnergyModel/OSMTemplate-OfficeBuilding-3.10.0.osm'

Load and set the building geometry, apertures (External Windows), and shading surfaces

# BUILDING
building = Topology.ByBREPPath(buildingPath)

# APERTURES
# Decompose the building
d = CellComplex.Decompose(building)
# Specify a glazing (window to wall) ratio:
import math
gr = 0.25
# Create apertures (windows) by scaling the external vertical walls
# Get the external vertical faces
walls = d['externalVerticalFaces']
apertures = []
for wall in walls:
    centroid = Topology.Centroid(wall)
    aperture = Topology.Scale(wall, centroid, math.sqrt(gr), math.sqrt(gr), math.sqrt(gr))
    apertures.append(aperture)
building = Topology.AddApertures(building, apertures, subTopologyType="face")

# SHADING SURFACES
shadingSurfaces = Topology.ByBREPPath(shadingPath)

# DISPLAY RESULT
Topology.Show(building, shadingSurfaces, apertures)
print("\nDONE")

DONE

Create an Energy Model

model = EnergyModel.ByTopology(building=building,
                               shadingSurfaces = shadingSurfaces,
                               osModelPath=osModelPath,
                               weatherFilePath=weatherFilePath,
                               designDayFilePath=designDayFilePath,
                               glazingRatio=0.25)

print("THIS IS A SNIPPET OF THE OSM MODEL TO VERIFY THAT IT WORKED.")
print(str(model)[:900])
print("\nDONE")
THIS IS A SNIPPET OF THE OSM MODEL TO VERIFY THAT IT WORKED.

OS:Version,
  {bb7ded13-bc75-4cad-b53b-60c55dfb4d86}, !- Handle
  3.11.0;                                 !- Version Identifier

OS:Building,
  {08678ddd-175a-469b-9626-2f02c40b6916}, ! Handle
  TopologicBuilding,                      ! Name
  ,                                       ! Building Type
  0,                                      ! North Axis
  3.00000016666667,                       ! Nominal Floor to Floor Height
  {23783b22-e086-4ec3-9e58-7b592355f93c}, ! Space Type Name
  {8d276ca2-ac82-489c-8e07-395b89456514}, ! Default Construction Set Name
  {14c603bd-dcaa-469b-be33-8c0fd5024bd4}, ! Default Schedule Set Name
  6,                                      !- Standards Number of Stories
  ,                                       !- Standards Number of Above Ground Stories
  ,                                       !- Standards Template
  Commercial;                             !

DONE

Create an HBJSON Model

from topologicpy.Honeybee import Honeybee

hb_model = Honeybee.ModelByTopology(building, shadingSurfaces)

print("THIS IS A SNIPPET OF THE OSM MODEL TO VERIFY THAT IT WORKED.")
print(str(hb_model)[:900])
print("\nDONE")
THIS IS A SNIPPET OF THE OSM MODEL TO VERIFY THAT IT WORKED.
Model: Generic_Building

DONE
/home/runner/work/topologicpy/topologicpy/.pixi/envs/dev/lib/python3.13/site-packages/honeybee_radiance_command/_command_util.py:120: SyntaxWarning:

invalid escape sequence '\c'

/home/runner/work/topologicpy/topologicpy/.pixi/envs/dev/lib/python3.13/site-packages/honeybee_radiance_command/_command_util.py:123: SyntaxWarning:

invalid escape sequence '\8'

/home/runner/work/topologicpy/topologicpy/.pixi/envs/dev/lib/python3.13/site-packages/honeybee_radiance_command/_command_util.py:123: SyntaxWarning:

invalid escape sequence '\9'

(Optional) Export the model to OSM, GBXML, or HBJSON

# Uncomment these files and change output path if you wish to export the model
#status01 = EnergyModel.ExportToOSM(model, outputFolder+"/EnergyModel.osm", overwrite=True)
#status02 = EnergyModel.ExportToGbXML(model, outputFolder+"/EnergyModel.xml", overwrite=True)
#status03 = Honeybee.ExportToHBJSON(hb_model, outputFolder+"/EnergyModel.hbjson", overwrite=True)
print("\DONE")
\DONE
<>:5: SyntaxWarning:

invalid escape sequence '\D'

<>:5: SyntaxWarning:

invalid escape sequence '\D'

/tmp/ipykernel_3455/4170888431.py:5: SyntaxWarning:

invalid escape sequence '\D'

Run the Simulation

# Run the simulation
import ipywidgets as w
osBinaryPath = "openstudio" # this works if it is on the PATH
out = w.Output()
with out:
    model = EnergyModel.Run(model, weatherFilePath=weatherFilePath,
                            osBinaryPath=osBinaryPath, outputFolder=outputFolder)
print("\nDONE")

DONE

Get the space names used in the energy model

# Get the topologies from the energy model. These have the correct dictionaries with space names etc.
topologies = EnergyModel.Topologies(model)
cells = topologies['cells']

# Get the required row names for the SQL query
names = []
for cell in cells:
    d = Topology.Dictionary(cell)
    name = Dictionary.ValueAtKey(d, 'TOPOLOGIC_name')
    name = name.upper()+"_THERMAL_ZONE"
    names.append(name)
print("\nDONE")

DONE
names
['SPACE_0024_THERMAL_ZONE',
 'SPACE_0023_THERMAL_ZONE',
 'SPACE_0022_THERMAL_ZONE',
 'SPACE_0021_THERMAL_ZONE',
 'SPACE_0019_THERMAL_ZONE',
 'SPACE_0017_THERMAL_ZONE',
 'SPACE_0016_THERMAL_ZONE',
 'SPACE_0018_THERMAL_ZONE',
 'SPACE_0015_THERMAL_ZONE',
 'SPACE_0014_THERMAL_ZONE',
 'SPACE_0013_THERMAL_ZONE',
 'SPACE_0006_THERMAL_ZONE',
 'SPACE_0012_THERMAL_ZONE',
 'SPACE_0002_THERMAL_ZONE',
 'SPACE_0010_THERMAL_ZONE',
 'SPACE_0000_THERMAL_ZONE',
 'SPACE_0001_THERMAL_ZONE',
 'SPACE_0011_THERMAL_ZONE',
 'SPACE_0020_THERMAL_ZONE',
 'SPACE_0004_THERMAL_ZONE',
 'SPACE_0009_THERMAL_ZONE',
 'SPACE_0003_THERMAL_ZONE',
 'SPACE_0005_THERMAL_ZONE',
 'SPACE_0007_THERMAL_ZONE',
 'SPACE_0008_THERMAL_ZONE']

Set the report, table, and column names to retrieve from the SQL data

# Set the report, table, and column names to retrieve from the SQL data

# Here we specify three possible reports. We get them by index for convenience.
reports = ["HVACSizingSummary", "HVACSizingSummary", "SystemSummary"]
forStrings = ["Entire Facility", "Entire Facility", "Entire Facility"]
tableNames = ["Zone Sensible Cooling", "Zone Sensible Heating", "Time Not Comfortable Based on Simple ASHRAE 55-2004"]
columnNames = ["User Design Load", "User Design Load", "Summer or Winter Clothes"]
unitsList = ["W", "W", "hr"]

# Choose report 0, 1, or 2
index = 0 

reportName = reports[index]
reportForString = forStrings[index]
tableName = tableNames[index]
columnName = columnNames[index]
units = unitsList[index]

# Get the values from the SQL data
values = EnergyModel.Query(model,
                          reportName = reportName,
                          reportForString = reportForString,
                          tableName = tableName,
                          columnName = columnName,
                          rowNames = names,
                          units = units)
print("\nDONE")

DONE

Apply the values to the bottom face(s) of each space/cell.

# This section is to apply the values only to the bottom face of each cell.
faces = []
selectors = []
for i, cell in enumerate(cells):
    d = Cell.Decompose(cell)
    bottomFaces = d['bottomHorizontalFaces']
    for bottomFace in bottomFaces:
        d = Dictionary.ByKeysValues(["value", "label"], [values[i], str(round(values[i], 2))])
        faces.append(bottomFace)
        s = Face.InternalVertex(bottomFace)
        s = Topology.SetDictionary(s, d)
        selectors.append(s)
faceCluster = Cluster.ByTopologies(faces)
faceCluster = Topology.TransferDictionariesBySelectors(faceCluster, selectors, tranFaces=True, tolerance=0.0001)
print("\nDONE")

DONE

Create a Plotly figure and draw it.

# Create a Plotly figure and draw it.
# Create a cluster to represent the building envelope (translucent). This is just for visualisation.
envelopeCluster = Cluster.ByTopologies(cells+apertures+Topology.Faces(shadingSurfaces))
plotlyData = Plotly.DataByTopology(envelopeCluster, faceOpacity=0.1)

# Add the color-coded faces
colorScale = "thermal"
plotlyData += Plotly.DataByTopology(faceCluster, faceOpacity=1, faceGroupKey="value",
                              faceLabelKey="label", faceGroups=values,
                              colorScale=colorScale)
# Create a Plotly Figure
figure = Plotly.FigureByData(plotlyData, width=800, height=600, backgroundColor="White")

# Add a colorbar
figure = Plotly.AddColorBar(figure, values=values, width=30, outlineWidth=1,
                            nTicks=len(values), title=tableName, subTitle=columnName,
                            units=units, colorScale=colorScale, mantissa=2)
# Show plotly figure
Plotly.Show(figure)
print("\nDONE")

DONE