Cross-platform collection of software tools to support whole building energy modeling using EnergyPlus and advanced daylight analysis using Radiance
—
Integration with Radiance for advanced daylight and lighting analysis capabilities. The Radiance module provides comprehensive daylight simulation tools including illuminance mapping, glare analysis, and annual daylight metrics, enabling detailed lighting design and energy-efficient daylighting strategies.
Conversion of OpenStudio models to Radiance format for daylight simulation.
/**
* Converts OpenStudio models to Radiance simulation format
*/
namespace radiance {
class ForwardTranslator {
public:
// Constructor
ForwardTranslator();
// Model translation
std::vector<Path> translateModel(const Path& outPath, const Model& model);
std::vector<Path> translateModel(const Path& outPath,
const Model& model,
const std::vector<Space>& spaces);
// Space-specific translation
std::vector<Path> translateSpace(const Path& outPath, const Space& space);
std::vector<Path> translateSpaces(const Path& outPath,
const std::vector<Space>& spaces);
// Surface translation
std::vector<Path> translateSurface(const Path& outPath, const Surface& surface);
std::vector<Path> translateSubSurface(const Path& outPath, const SubSurface& subSurface);
// Material translation
std::vector<Path> translateMaterials(const Path& outPath, const Model& model);
Path translateMaterial(const Path& outPath, const Material& material);
// Translation options
RadianceParameters radianceParameters() const;
void setRadianceParameters(const RadianceParameters& radianceParameters);
// Error and warning handling
std::vector<LogMessage> errors() const;
std::vector<LogMessage> warnings() const;
// Generated files
std::vector<Path> radianceFiles() const;
std::vector<Path> octreeFiles() const;
};
/**
* Radiance simulation parameters and settings
*/
class RadianceParameters {
public:
// Constructor
RadianceParameters();
// Ambient bounces
boost::optional<int> ambientBounces() const;
bool setAmbientBounces(int ambientBounces);
void resetAmbientBounces();
// Ambient divisions
boost::optional<int> ambientDivisions() const;
bool setAmbientDivisions(int ambientDivisions);
void resetAmbientDivisions();
// Ambient super-samples
boost::optional<int> ambientSupersamples() const;
bool setAmbientSupersamples(int ambientSupersamples);
void resetAmbientSupersamples();
// Limit reflection
boost::optional<int> limitReflection() const;
bool setLimitReflection(int limitReflection);
void resetLimitReflection();
// Limit weight
boost::optional<double> limitWeight() const;
bool setLimitWeight(double limitWeight);
void resetLimitWeight();
// Grid resolution
boost::optional<double> gridResolution() const;
bool setGridResolution(double gridResolution);
void resetGridResolution();
// Sensor height
boost::optional<double> sensorHeight() const;
bool setSensorHeight(double sensorHeight);
void resetSensorHeight();
};
}Usage Examples:
#include <openstudio/radiance/ForwardTranslator.hpp>
#include <openstudio/model/Model.hpp>
using namespace openstudio;
using namespace openstudio::model;
using namespace openstudio::radiance;
// Load OpenStudio model
boost::optional<Model> model = Model::load(Path("office_building.osm"));
if (model) {
// Set up Radiance translator
ForwardTranslator ft;
// Configure simulation parameters
RadianceParameters params;
params.setAmbientBounces(3);
params.setAmbientDivisions(1000);
params.setGridResolution(0.5); // 0.5m grid spacing
ft.setRadianceParameters(params);
// Translate model to Radiance
Path radianceDir("radiance_simulation");
std::vector<Path> radianceFiles = ft.translateModel(radianceDir, *model);
// Check translation results
std::vector<LogMessage> errors = ft.errors();
if (errors.empty()) {
std::cout << "Radiance translation successful!" << std::endl;
std::cout << "Generated " << radianceFiles.size() << " Radiance files" << std::endl;
} else {
for (const auto& error : errors) {
std::cout << "Translation error: " << error.logMessage() << std::endl;
}
}
}Tools for calculating and analyzing illuminance levels and daylight distribution.
/**
* Annual illuminance map generation and analysis
*/
class AnnualIlluminanceMap {
public:
// Constructors
AnnualIlluminanceMap();
AnnualIlluminanceMap(const Path& path);
// File I/O
static boost::optional<AnnualIlluminanceMap> load(const Path& path);
bool save(const Path& path) const;
// Illuminance data access
boost::optional<Matrix> illuminanceMap() const;
std::vector<double> illuminanceValues() const;
std::vector<DateTime> dateTimes() const;
// Grid properties
unsigned xPoints() const;
unsigned yPoints() const;
double xSpacing() const;
double ySpacing() const;
// Statistical analysis
boost::optional<double> minimumIlluminance() const;
boost::optional<double> maximumIlluminance() const;
boost::optional<double> averageIlluminance() const;
boost::optional<double> medianIlluminance() const;
// Daylight metrics
boost::optional<double> spatialDaylightAutonomy(double threshold = 300.0) const;
boost::optional<double> continuousDaylightAutonomy(double threshold = 300.0) const;
boost::optional<double> annualSunlightExposure(double threshold = 1000.0) const;
// Time-based analysis
std::vector<double> illuminanceAtTime(const DateTime& dateTime) const;
std::vector<double> illuminanceAtPoint(unsigned x, unsigned y) const;
// Zone-based metrics
boost::optional<double> zoneAverageIlluminance() const;
boost::optional<double> uniformityRatio() const;
};
/**
* Point-in-time illuminance calculations
*/
class IlluminanceMap {
public:
// Constructor
IlluminanceMap();
IlluminanceMap(const Space& space);
// Grid definition
void setXSpacing(double xSpacing);
void setYSpacing(double ySpacing);
void setOriginXCoordinate(double originX);
void setOriginYCoordinate(double originY);
void setOriginZCoordinate(double originZ);
double xSpacing() const;
double ySpacing() const;
double originXCoordinate() const;
double originYCoordinate() const;
double originZCoordinate() const;
// Grid points
std::vector<Point3d> referencePoints() const;
unsigned numberofXGridPoints() const;
unsigned numberofYGridPoints() const;
// Space association
boost::optional<Space> space() const;
bool setSpace(const Space& space);
// Illuminance calculation
std::vector<double> calculateIlluminance(const std::vector<double>& skyValues) const;
Matrix calculateIlluminanceMatrix(const Matrix& skyMatrix) const;
};
/**
* Daylighting control and sensor modeling
*/
class DaylightingControl : public SpaceLoadInstance {
public:
// Constructor
DaylightingControl(const Model& model);
// Position
double positionXCoordinate() const;
bool setPositionXCoordinate(double positionXCoordinate);
double positionYCoordinate() const;
bool setPositionYCoordinate(double positionYCoordinate);
double positionZCoordinate() const;
bool setPositionZCoordinate(double positionZCoordinate);
// Sensor orientation
double psiRotationAroundXAxis() const;
bool setPsiRotationAroundXAxis(double psiRotation);
double thetaRotationAroundYAxis() const;
bool setThetaRotationAroundYAxis(double thetaRotation);
double phiRotationAroundZAxis() const;
bool setPhiRotationAroundZAxis(double phiRotation);
// Control parameters
double illuminanceSetpoint() const;
bool setIlluminanceSetpoint(double illuminanceSetpoint);
boost::optional<double> lightingControlSteps() const;
bool setLightingControlSteps(double lightingControlSteps);
void resetLightingControlSteps();
double lightingControlProbability() const;
bool setLightingControlProbability(double lightingControlProbability);
// Glare control
boost::optional<double> glareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis() const;
bool setGlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis(double angle);
boost::optional<double> maximumAllowableDiscomfortGlareIndex() const;
bool setMaximumAllowableDiscomfortGlareIndex(double index);
};Advanced window modeling and daylight analysis for complex fenestration systems.
/**
* Window group for coordinated daylighting analysis
*/
class WindowGroup {
public:
// Constructor
WindowGroup();
WindowGroup(const std::vector<SubSurface>& subSurfaces);
// Window management
std::vector<SubSurface> subSurfaces() const;
bool addSubSurface(const SubSurface& subSurface);
bool removeSubSurface(const SubSurface& subSurface);
void clearSubSurfaces();
// Group properties
boost::optional<std::string> name() const;
void setName(const std::string& name);
boost::optional<double> windowGroupRendering() const;
void setWindowGroupRendering(double windowGroupRendering);
// Window group control
boost::optional<Construction> windowGroupConstruction() const;
void setWindowGroupConstruction(const Construction& construction);
boost::optional<ShadingControl> windowGroupShadingControl() const;
void setWindowGroupShadingControl(const ShadingControl& shadingControl);
// Daylight matrix generation
std::vector<Path> generateDaylightMatrix(const Path& outputDir,
const RadianceParameters& parameters) const;
// View matrix calculation
Matrix calculateViewMatrix(const std::vector<Point3d>& sensorPoints,
const RadianceParameters& parameters) const;
};
/**
* Three-phase method daylight calculation
*/
class ThreePhaseMethod {
public:
// Constructor
ThreePhaseMethod();
// Matrix components
void setViewMatrix(const Matrix& viewMatrix);
void setDaylightMatrix(const Matrix& daylightMatrix);
void setSkyMatrix(const Matrix& skyMatrix);
Matrix viewMatrix() const;
Matrix daylightMatrix() const;
Matrix skyMatrix() const;
// Calculation
Matrix calculateIlluminance() const;
std::vector<double> calculateAnnualIlluminance(const std::vector<DateTime>& dateTimes) const;
// Sky conditions
void setClearSky();
void setOvercastSky();
void setIntermediateSky();
void setCustomSky(const Matrix& skyRadiance);
// Window state management
void setWindowState(const WindowGroup& windowGroup, const std::string& state);
std::map<WindowGroup, std::string> windowStates() const;
};Helper classes for Radiance file management and simulation control.
/**
* Radiance file header information
*/
class HeaderInfo {
public:
// Constructor
HeaderInfo();
// Header fields
std::string creator() const;
void setCreator(const std::string& creator);
DateTime creationDate() const;
void setCreationDate(const DateTime& date);
std::string description() const;
void setDescription(const std::string& description);
std::string format() const;
void setFormat(const std::string& format);
// View information
boost::optional<std::string> view() const;
void setView(const std::string& view);
void resetView();
// Resolution
boost::optional<int> xResolution() const;
boost::optional<int> yResolution() const;
void setResolution(int x, int y);
// File generation
std::string generateHeader() const;
};
/**
* Radiance utility functions
*/
namespace Utils {
// File path utilities
Path radianceDirectory();
Path radianceBinDirectory();
Path radianceLibDirectory();
// Executable paths
Path rpictPath();
Path rtracePath();
Path rviewPath();
Path oconvPath();
Path genDayMtxPath();
// Sky generation
Path generateClearSky(const Path& outputDir,
const DateTime& dateTime,
double latitude,
double longitude,
double timeZone);
Path generateOvercastSky(const Path& outputDir);
Path generateIntermediateSky(const Path& outputDir,
const DateTime& dateTime,
double latitude,
double longitude,
double timeZone,
double cloudCover);
// Weather file processing
std::vector<Matrix> generateAnnualSkyMatrix(const Path& weatherFile,
const Path& outputDir);
Matrix generateSkyMatrix(const std::vector<DateTime>& dateTimes,
const std::vector<double>& directNormalIrradiance,
const std::vector<double>& diffuseHorizontalIrradiance);
// Simulation execution
bool runRadianceSimulation(const Path& octreeFile,
const Path& viewFile,
const Path& outputFile,
const RadianceParameters& parameters);
bool runRtrace(const Path& octreeFile,
const std::vector<Point3d>& points,
const std::vector<Vector3d>& directions,
const Path& outputFile);
// Result processing
std::vector<double> parseIlluminanceResults(const Path& resultsFile);
Matrix parseMatrixResults(const Path& matrixFile);
// File validation
bool validateRadianceFile(const Path& radianceFile);
bool validateOctreeFile(const Path& octreeFile);
}Comprehensive daylight performance metrics and analysis tools.
/**
* Annual daylight performance metrics calculation
*/
class AnnualDaylightMetrics {
public:
// Constructor from illuminance map
AnnualDaylightMetrics(const AnnualIlluminanceMap& illuminanceMap);
// Daylight Autonomy (DA)
double daylightAutonomy(double threshold = 300.0) const;
Matrix daylightAutonomyMap(double threshold = 300.0) const;
// Continuous Daylight Autonomy (cDA)
double continuousDaylightAutonomy(double threshold = 300.0) const;
Matrix continuousDaylightAutonomyMap(double threshold = 300.0) const;
// Spatial Daylight Autonomy (sDA)
double spatialDaylightAutonomy(double threshold = 300.0, double areaThreshold = 0.50) const;
// Annual Sunlight Exposure (ASE)
double annualSunlightExposure(double threshold = 1000.0, double areaThreshold = 0.10) const;
Matrix annualSunlightExposureMap(double threshold = 1000.0) const;
// Useful Daylight Illuminance (UDI)
struct UDIBins {
double fell_short; // < 100 lux
double supplementary; // 100-300 lux
double autonomous; // 300-3000 lux
double exceeded; // > 3000 lux
};
UDIBins usefulDaylightIlluminance() const;
std::map<std::string, Matrix> usefulDaylightIlluminanceMaps() const;
// Daylight Glare Probability (DGP) - requires view analysis
boost::optional<double> daylightGlareProbability() const;
void setDaylightGlareProbability(double dgp);
// Climate-based daylight modeling
double climaticAvailability() const;
std::vector<double> monthlyDaylightAvailability() const;
// Summary statistics
struct DaylightSummary {
double mean_illuminance;
double median_illuminance;
double min_illuminance;
double max_illuminance;
double uniformity_ratio;
double daylight_autonomy;
double spatial_daylight_autonomy;
double annual_sunlight_exposure;
};
DaylightSummary generateSummary() const;
};#include <openstudio/radiance/ForwardTranslator.hpp>
#include <openstudio/radiance/Utils.hpp>
using namespace openstudio;
using namespace openstudio::model;
using namespace openstudio::radiance;
// Load model and set up translation
boost::optional<Model> model = Model::load(Path("daylit_office.osm"));
if (model) {
// Configure Radiance parameters for high accuracy
RadianceParameters params;
params.setAmbientBounces(5);
params.setAmbientDivisions(1500);
params.setAmbientSupersamples(100);
params.setLimitWeight(0.0002);
// Set up translator
ForwardTranslator ft;
ft.setRadianceParameters(params);
// Translate specific spaces (e.g., only occupied spaces)
std::vector<Space> spaces;
for (const auto& space : model->getConcreteModelObjects<Space>()) {
// Only translate spaces with people
if (!space.people().empty()) {
spaces.push_back(space);
}
}
// Translate to Radiance
Path radianceDir("daylight_analysis");
std::vector<Path> radianceFiles = ft.translateModel(radianceDir, *model, spaces);
// Generate octree for simulation
Path octreeFile = radianceDir / "scene.oct";
// Note: In practice, you would call oconv to generate the octree
// Set up illuminance mapping
for (const auto& space : spaces) {
IlluminanceMap illumMap(space);
illumMap.setXSpacing(0.5); // 0.5m grid
illumMap.setYSpacing(0.5);
illumMap.setOriginZCoordinate(0.8); // Desktop height
// Calculate reference points
std::vector<Point3d> points = illumMap.referencePoints();
std::cout << "Space '" << space.name().get_value_or("Unnamed")
<< "' has " << points.size() << " analysis points" << std::endl;
}
}#include <openstudio/radiance/AnnualIlluminanceMap.hpp>
#include <openstudio/radiance/AnnualDaylightMetrics.hpp>
using namespace openstudio;
using namespace openstudio::radiance;
// Load annual illuminance results (typically generated by external Radiance tools)
boost::optional<AnnualIlluminanceMap> annualMap =
AnnualIlluminanceMap::load(Path("annual_illuminance.ill"));
if (annualMap) {
// Calculate comprehensive daylight metrics
AnnualDaylightMetrics metrics(*annualMap);
// Generate summary report
AnnualDaylightMetrics::DaylightSummary summary = metrics.generateSummary();
std::cout << "Daylight Performance Summary:" << std::endl;
std::cout << " Mean Illuminance: " << summary.mean_illuminance << " lux" << std::endl;
std::cout << " Daylight Autonomy (300 lux): " << summary.daylight_autonomy * 100 << "%" << std::endl;
std::cout << " Spatial DA (sDA300/50%): " << summary.spatial_daylight_autonomy * 100 << "%" << std::endl;
std::cout << " Annual Sunlight Exposure (ASE1000/10%): " << summary.annual_sunlight_exposure * 100 << "%" << std::endl;
// Check LEED v4 compliance
bool leedCompliant = (summary.spatial_daylight_autonomy >= 0.50) &&
(summary.annual_sunlight_exposure <= 0.10);
if (leedCompliant) {
std::cout << "✓ LEED v4 daylight requirements met" << std::endl;
} else {
std::cout << "✗ LEED v4 daylight requirements not met" << std::endl;
}
// Useful Daylight Illuminance analysis
AnnualDaylightMetrics::UDIBins udi = metrics.usefulDaylightIlluminance();
std::cout << "\nUseful Daylight Illuminance:" << std::endl;
std::cout << " Fell Short (<100 lux): " << udi.fell_short * 100 << "%" << std::endl;
std::cout << " Supplementary (100-300 lux): " << udi.supplementary * 100 << "%" << std::endl;
std::cout << " Autonomous (300-3000 lux): " << udi.autonomous * 100 << "%" << std::endl;
std::cout << " Exceeded (>3000 lux): " << udi.exceeded * 100 << "%" << std::endl;
}#include <openstudio/radiance/ThreePhaseMethod.hpp>
#include <openstudio/radiance/WindowGroup.hpp>
using namespace openstudio;
using namespace openstudio::radiance;
// Set up three-phase daylight calculation for dynamic shading analysis
Model model;
// ... create model with windows and shading systems ...
// Create window groups for coordinated analysis
std::vector<SubSurface> southWindows;
for (const auto& surface : model.getConcreteModelObjects<Surface>()) {
if (surface.azimuth() && std::abs(*surface.azimuth() - 180.0) < 45.0) { // South-facing
for (const auto& subSurface : surface.subSurfaces()) {
if (subSurface.subSurfaceType() == "FixedWindow" ||
subSurface.subSurfaceType() == "OperableWindow") {
southWindows.push_back(subSurface);
}
}
}
}
WindowGroup southWindowGroup(southWindows);
southWindowGroup.setName("South Windows");
// Set up three-phase calculation
ThreePhaseMethod threePhase;
// Generate daylight matrices for different shading states
RadianceParameters params;
params.setAmbientBounces(3);
params.setAmbientDivisions(1000);
// Calculate for clear glazing state
southWindowGroup.setWindowGroupConstruction(/* clear glazing construction */);
std::vector<Path> clearMatrixFiles = southWindowGroup.generateDaylightMatrix(
Path("matrices/clear"), params);
// Calculate for shaded state
southWindowGroup.setWindowGroupConstruction(/* shaded glazing construction */);
std::vector<Path> shadedMatrixFiles = southWindowGroup.generateDaylightMatrix(
Path("matrices/shaded"), params);
// Load matrices (in practice, these would be read from generated files)
Matrix viewMatrix; // View matrix from sensors to window
Matrix daylightMatrixClear; // Daylight matrix for clear state
Matrix daylightMatrixShaded; // Daylight matrix for shaded state
Matrix skyMatrix; // Annual sky matrix
// Calculate annual illuminance for both states
threePhase.setViewMatrix(viewMatrix);
threePhase.setSkyMatrix(skyMatrix);
// Clear state analysis
threePhase.setDaylightMatrix(daylightMatrixClear);
Matrix clearIlluminance = threePhase.calculateIlluminance();
// Shaded state analysis
threePhase.setDaylightMatrix(daylightMatrixShaded);
Matrix shadedIlluminance = threePhase.calculateIlluminance();
// Compare results and optimize shading control
std::cout << "Clear state annual illuminance calculated" << std::endl;
std::cout << "Shaded state annual illuminance calculated" << std::endl;#include <openstudio/model/DaylightingControl.hpp>
#include <openstudio/model/Space.hpp>
using namespace openstudio;
using namespace openstudio::model;
Model model;
// ... create model with spaces ...
// Add daylighting controls to each space
for (auto& space : model.getConcreteModelObjects<Space>()) {
// Only add controls to spaces with significant window area
double windowArea = 0.0;
for (const auto& surface : space.surfaces()) {
for (const auto& subSurface : surface.subSurfaces()) {
windowArea += subSurface.grossArea();
}
}
if (windowArea > 5.0) { // More than 5 m² of windows
// Create daylighting control
DaylightingControl daylightingControl(model);
daylightingControl.setSpace(space);
// Position at space centroid
boost::optional<Point3d> centroid = space.transformation() * space.floorPrint().centroid();
if (centroid) {
daylightingControl.setPositionXCoordinate(centroid->x());
daylightingControl.setPositionYCoordinate(centroid->y());
daylightingControl.setPositionZCoordinate(centroid->z() + 0.8); // Desktop height
}
// Configure control parameters
daylightingControl.setIlluminanceSetpoint(500.0); // 500 lux target
daylightingControl.setLightingControlSteps(3.0); // 3-step dimming
daylightingControl.setLightingControlProbability(1.0); // Always respond
// Set up glare control if space has view to exterior
bool hasExteriorView = false;
for (const auto& surface : space.surfaces()) {
if (surface.outsideBoundaryCondition() == "Outdoors") {
for (const auto& subSurface : surface.subSurfaces()) {
hasExteriorView = true;
break;
}
}
}
if (hasExteriorView) {
daylightingControl.setMaximumAllowableDiscomfortGlareIndex(0.4); // Imperceptible glare
daylightingControl.setGlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis(0.0);
}
std::cout << "Added daylighting control to space: "
<< space.name().get_value_or("Unnamed") << std::endl;
}
}
// Verify all daylighting controls
std::vector<DaylightingControl> controls = model.getConcreteModelObjects<DaylightingControl>();
std::cout << "Total daylighting controls: " << controls.size() << std::endl;Install with Tessl CLI
npx tessl i tessl/pypi-openstudio