Cross-platform collection of software tools to support whole building energy modeling using EnergyPlus and advanced daylight analysis using Radiance
npx @tessl/cli install tessl/pypi-openstudio@3.10.0OpenStudio is a cross-platform collection of software tools to support whole building energy modeling using EnergyPlus and advanced daylight analysis using Radiance. It provides a comprehensive C++ SDK with language bindings for Python, Ruby, C#, and JavaScript, enabling developers to create, modify, and simulate building energy models programmatically. The Python bindings provide the most commonly used interface for building energy modeling workflows.
pip install openstudioPython (Primary):
import openstudio
from openstudio import model
from openstudio import energyplus
from openstudio import measureFor specific modules:
from openstudio.model import Model, Building, Zone, Space
from openstudio.energyplus import ForwardTranslatorC++ (Advanced):
#include <openstudio/model/Model.hpp>
#include <openstudio/model/Building.hpp>
#include <openstudio/model/Zone.hpp>
#include <openstudio/model/Space.hpp>
#include <openstudio/energyplus/ForwardTranslator.hpp>
#include <openstudio/utilities/core/Path.hpp>Python (Recommended):
import openstudio
from openstudio import model
from openstudio import energyplus
# Create a new building model
model_obj = model.Model()
# Get or create the building object
building = model_obj.getUniqueModelObject(model.Building)
building.setName("Sample Building")
# Create a thermal zone
zone = model.Zone(model_obj)
zone.setName("Main Zone")
# Translate to EnergyPlus
forward_translator = energyplus.ForwardTranslator()
workspace = forward_translator.translateModel(model_obj)
# Save to IDF file
path = openstudio.Path("building.idf")
workspace.save(path, True)C++ (Advanced):
#include <openstudio/model/Model.hpp>
#include <openstudio/model/Building.hpp>
#include <openstudio/model/Zone.hpp>
#include <openstudio/energyplus/ForwardTranslator.hpp>
using namespace openstudio;
using namespace openstudio::model;
// Create a new building model
Model model;
// Get or create the building object
Building building = model.getUniqueModelObject<Building>();
building.setName("Sample Building");
// Create a thermal zone
Zone zone(model);
zone.setName("Main Zone");
// Translate to EnergyPlus
energyplus::ForwardTranslator ft;
Workspace workspace = ft.translateModel(model);
// Save to IDF file
workspace.save(Path("building.idf"), true);OpenStudio is built around several key components:
Core classes for creating and managing building energy models with hierarchical object relationships and template-based type safety.
# Python API
class Model:
def __init__(self)
# Object access methods
def getModelObject(self, handle): # Returns optional object
def getConcreteModelObjects(self, object_type): # Returns list
def getUniqueModelObject(self, object_type): # Returns single object
# Model operations
def sqlFile(self): # Returns optional SqlFile
def setSqlFile(self, sql_file): # Returns bool
def insertComponent(self, component): # Returns ComponentData
# HVAC operations
def connect(self, source_object, source_port, target_object, target_port): # Returns bool
class ModelObject:
def clone(self, model): # Returns ModelObject
def createComponent(self): # Returns Component
def model(self): # Returns Model
def resources(self): # Returns list of ResourceObject
def outputVariables(self): # Returns list of OutputVariable
def lifeCycleCosts(self): # Returns list of LifeCycleCost// C++ API
class Model : public openstudio::Workspace {
public:
// Template-based object access
template<typename T>
boost::optional<T> getModelObject(const Handle& handle) const;
template<typename T>
std::vector<T> getConcreteModelObjects() const;
template<typename T>
T getUniqueModelObject();
// Model operations
boost::optional<SqlFile> sqlFile() const;
bool setSqlFile(const SqlFile& sqlFile);
ComponentData insertComponent(const Component& component);
// HVAC operations
bool connect(ModelObject sourceObject,
unsigned sourcePort,
ModelObject targetObject,
unsigned targetPort);
};
class ModelObject : public openstudio::WorkspaceObject {
public:
ModelObject clone(Model model) const;
Component createComponent() const;
Model model() const;
std::vector<ResourceObject> resources() const;
std::vector<OutputVariable> outputVariables() const;
std::vector<LifeCycleCost> lifeCycleCosts() const;
};Comprehensive utility classes for geometry, units, file I/O, and data structures that form the foundation of the OpenStudio SDK.
# Python API
class Path:
def __init__(self)
def __init__(self, path_string)
def string(self): # Returns str
def filename(self): # Returns str
def stem(self): # Returns str
def extension(self): # Returns str
def exists(self): # Returns bool
def is_complete(self): # Returns bool
def empty(self): # Returns bool
class Point3d:
def __init__(self)
def __init__(self, x, y, z)
def x(self): # Returns float
def y(self): # Returns float
def z(self): # Returns float
def __sub__(self, other): # Returns Vector3d
def __add__(self, vec): # Returns Point3d
class Quantity:
def __init__(self)
def __init__(self, value, units)
def value(self): # Returns float
def units(self): # Returns Unit
def convert(self, target_units): # Returns optional Quantity// C++ API
class Path {
public:
Path();
Path(const std::string& p);
std::string string() const;
std::string filename() const;
std::string stem() const;
std::string extension() const;
bool exists() const;
bool is_complete() const;
bool empty() const;
};
class Point3d {
public:
Point3d();
Point3d(double x, double y, double z);
double x() const;
double y() const;
double z() const;
Vector3d operator-(const Point3d& other) const;
Point3d operator+(const Vector3d& vec) const;
};
class Quantity {
public:
Quantity();
Quantity(double value, const Unit& units);
double value() const;
Unit units() const;
boost::optional<Quantity> convert(const Unit& targetUnits) const;
};Translation between OpenStudio models and EnergyPlus IDF format for building energy simulation.
# Python API
class ForwardTranslator:
def __init__(self)
def translateModel(self, model): # Returns Workspace
def warnings(self): # Returns list of LogMessage
def errors(self): # Returns list of LogMessage
class ReverseTranslator:
def __init__(self)
def translateWorkspace(self, workspace): # Returns optional Model
def warnings(self): # Returns list of LogMessage
def errors(self): # Returns list of LogMessage// C++ API
class ForwardTranslator {
public:
ForwardTranslator();
Workspace translateModel(const Model& model);
std::vector<LogMessage> warnings() const;
std::vector<LogMessage> errors() const;
};
class ReverseTranslator {
public:
ReverseTranslator();
boost::optional<Model> translateWorkspace(const Workspace& workspace);
std::vector<LogMessage> warnings() const;
std::vector<LogMessage> errors() const;
};Parametric analysis framework for automated model modifications and simulation workflows.
# Python API
class OSMeasure:
def arguments(self): # Returns list of OSArgument
def run(self, model, runner, user_arguments): # Returns bool
class ModelMeasure(OSMeasure):
def run(self, model, runner, user_arguments): # Returns bool
class OSArgument:
@staticmethod
def makeBoolArgument(name): # Returns OSArgument
@staticmethod
def makeDoubleArgument(name): # Returns OSArgument
@staticmethod
def makeStringArgument(name): # Returns OSArgument
@staticmethod
def makeChoiceArgument(name, choices): # Returns OSArgument// C++ API
class OSMeasure {
public:
virtual ~OSMeasure() = default;
virtual OSArgumentVector arguments() = 0;
virtual bool run(Model& model,
OSRunner& runner,
const OSArgumentMap& user_arguments) = 0;
};
class ModelMeasure : public OSMeasure {
public:
virtual bool run(Model& model,
OSRunner& runner,
const OSArgumentMap& user_arguments) override = 0;
};
class OSArgument {
public:
static OSArgument makeBoolArgument(const std::string& name);
static OSArgument makeDoubleArgument(const std::string& name);
static OSArgument makeStringArgument(const std::string& name);
static OSArgument makeChoiceArgument(const std::string& name,
const StringVector& choices);
};Orchestration of complete building simulation workflows from initial model through results processing.
# Python API
class OSWorkflow:
def __init__(self)
def __init__(self, osw_path)
def run(self): # Returns bool
def model(self): # Returns optional Model
def workspace(self): # Returns optional Workspace
def sqlFile(self): # Returns optional SqlFile
def errors(self): # Returns list of LogMessage
def warnings(self): # Returns list of LogMessage
class WorkflowStepType:
ModelMeasure = "ModelMeasure"
EnergyPlusMeasure = "EnergyPlusMeasure"
ReportingMeasure = "ReportingMeasure"
class WorkflowStep:
def type(self): # Returns WorkflowStepType
def measure(self): # Returns optional BCLMeasure
def arguments(self): # Returns dict// C++ API
class OSWorkflow {
public:
OSWorkflow();
explicit OSWorkflow(const Path& oswPath);
bool run();
boost::optional<Model> model() const;
boost::optional<Workspace> workspace() const;
boost::optional<SqlFile> sqlFile() const;
std::vector<LogMessage> errors() const;
std::vector<LogMessage> warnings() const;
};
enum class WorkflowStepType {
ModelMeasure,
EnergyPlusMeasure,
ReportingMeasure
};
class WorkflowStep {
public:
WorkflowStepType type() const;
boost::optional<BCLMeasure> measure() const;
OSArgumentMap arguments() const;
};Integration with Radiance for advanced daylight and lighting analysis capabilities.
# Python API - openstudio.radiance module
class ForwardTranslator:
def __init__(self)
def translateModel(self, out_path, model): # Returns list of Path
def translateSpace(self, out_path, space): # Returns bool
class AnnualIlluminanceMap:
def __init__(self, path)
def illuminanceMap(self): # Returns optional Matrix
def dateTimes(self): # Returns list of DateTime
def values(self): # Returns list of float// C++ API
namespace radiance {
class ForwardTranslator {
public:
ForwardTranslator();
std::vector<Path> translateModel(const Path& outPath,
const Model& model);
bool translateSpace(const Path& outPath,
const Space& space);
};
class AnnualIlluminanceMap {
public:
AnnualIlluminanceMap(const Path& path);
boost::optional<Matrix> illuminanceMap() const;
std::vector<DateTime> dateTimes() const;
std::vector<double> values() const;
};
}Python (Pythonic API):
# Get specific object types
zones = model.getConcreteModelObjects(model.Zone)
building = model.getOptionalUniqueModelObject(model.Building)
# Access by handle
zone_handle = zones[0].handle()
zone = model.getModelObject(zone_handle)C++ (Template-Based Access):
// Get specific object types
std::vector<Zone> zones = model.getConcreteModelObjects<Zone>();
boost::optional<Building> building = model.getOptionalUniqueModelObject<Building>();
// Safe casting with handle
Handle zoneHandle = zones[0].handle();
boost::optional<Zone> zone = model.getModelObject<Zone>(zoneHandle);Building objects maintain parent-child and usage relationships:
Python:
# Parent-child hierarchy
space = surface.space()
if space:
surfaces = space.surfaces()
zone = space.thermalZone()
# Resource usage
construction = model.Construction(model)
users = construction.getModelObjectSources()
resources = surface.resources()C++:
// Parent-child hierarchy
boost::optional<Space> space = surface.space();
if (space) {
std::vector<Surface> surfaces = space->surfaces();
boost::optional<ThermalZone> zone = space->thermalZone();
}
// Resource usage
Construction construction(model);
std::vector<ModelObject> users = construction.getModelObjectSources<>();
std::vector<ResourceObject> resources = surface.resources();Python (Automatic Garbage Collection):
# Python handles memory management automatically
model = model.Model()
zone = model.Zone(model)
# Objects are garbage collected when no longer referenced
# No explicit cleanup neededC++ (RAII Principles):
{
Model model; // Automatic cleanup when scope ends
Zone zone(model); // Objects manage their own lifecycle
// No explicit cleanup needed
} // All objects automatically cleaned up here