or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

energyplus.mdindex.mdmeasure.mdmodel.mdradiance.mdutilities.mdworkflow.md

measure.mddocs/

0

# Measure Framework

1

2

Parametric analysis framework for automated model modifications and simulation workflows. The measure framework enables systematic exploration of design alternatives through scripted model modifications, making it ideal for sensitivity analysis, optimization, and automated design studies.

3

4

## Capabilities

5

6

### Base Measure Classes

7

8

Core measure framework providing the foundation for all measure types.

9

10

```cpp { .api }

11

/**

12

* Base class for all OpenStudio measures

13

* Defines the interface for parametric model modifications

14

*/

15

class OSMeasure {

16

public:

17

// Virtual destructor

18

virtual ~OSMeasure() = default;

19

20

// Core measure interface

21

virtual std::string name() const = 0;

22

virtual std::string description() const = 0;

23

virtual std::string modeler_description() const = 0;

24

25

// Argument definition - defines measure parameters

26

virtual OSArgumentVector arguments() = 0;

27

28

// Main execution method - implemented by derived classes

29

virtual bool run(OSRunner& runner, const OSArgumentMap& user_arguments) = 0;

30

31

// Measure metadata

32

virtual std::vector<std::string> tags() const;

33

virtual std::vector<std::string> outcomes() const;

34

35

// File and resource handling

36

virtual std::vector<FileReferenceType> fileReferenceTypes() const;

37

virtual std::vector<OSAttribute> outputAttributes() const;

38

};

39

40

/**

41

* Model-based measure - operates on OpenStudio models

42

*/

43

class ModelMeasure : public OSMeasure {

44

public:

45

// Constructor

46

ModelMeasure() = default;

47

48

// Model-specific run method

49

virtual bool run(Model& model,

50

OSRunner& runner,

51

const OSArgumentMap& user_arguments) = 0;

52

53

// Final run implementation calls model-specific version

54

virtual bool run(OSRunner& runner, const OSArgumentMap& user_arguments) override final;

55

};

56

57

/**

58

* EnergyPlus-based measure - operates on IDF workspaces

59

*/

60

class EnergyPlusMeasure : public OSMeasure {

61

public:

62

// Constructor

63

EnergyPlusMeasure() = default;

64

65

// Workspace-specific run method

66

virtual bool run(Workspace& workspace,

67

OSRunner& runner,

68

const OSArgumentMap& user_arguments) = 0;

69

70

// Final run implementation calls workspace-specific version

71

virtual bool run(OSRunner& runner, const OSArgumentMap& user_arguments) override final;

72

};

73

74

/**

75

* Reporting measure - processes simulation results

76

*/

77

class ReportingMeasure : public OSMeasure {

78

public:

79

// Constructor

80

ReportingMeasure() = default;

81

82

// Reporting-specific run method

83

virtual bool run(OSRunner& runner,

84

const OSArgumentMap& user_arguments) = 0;

85

};

86

```

87

88

### Measure Arguments

89

90

Type-safe parameter system for measure configuration and user input.

91

92

```cpp { .api }

93

/**

94

* Measure argument definition and validation

95

*/

96

class OSArgument {

97

public:

98

// Argument types

99

enum class Type {

100

Boolean,

101

Double,

102

Integer,

103

String,

104

Choice,

105

Path

106

};

107

108

// Static factory methods for different argument types

109

static OSArgument makeBoolArgument(const std::string& name,

110

bool required = true);

111

112

static OSArgument makeDoubleArgument(const std::string& name,

113

bool required = true);

114

115

static OSArgument makeIntegerArgument(const std::string& name,

116

bool required = true);

117

118

static OSArgument makeStringArgument(const std::string& name,

119

bool required = true);

120

121

static OSArgument makeChoiceArgument(const std::string& name,

122

const std::vector<std::string>& choices,

123

bool required = true);

124

125

static OSArgument makePathArgument(const std::string& name,

126

bool isRead = true,

127

const std::string& extension = std::string(),

128

bool required = true);

129

130

// Argument properties

131

std::string name() const;

132

Type type() const;

133

bool required() const;

134

135

// Display properties

136

std::string displayName() const;

137

void setDisplayName(const std::string& displayName);

138

139

std::string description() const;

140

void setDescription(const std::string& description);

141

142

std::string units() const;

143

void setUnits(const std::string& units);

144

145

// Default values

146

bool hasDefaultValue() const;

147

boost::optional<bool> defaultValueAsBool() const;

148

boost::optional<double> defaultValueAsDouble() const;

149

boost::optional<int> defaultValueAsInteger() const;

150

boost::optional<std::string> defaultValueAsString() const;

151

152

void setDefaultValue(bool value);

153

void setDefaultValue(double value);

154

void setDefaultValue(int value);

155

void setDefaultValue(const std::string& value);

156

157

// Value constraints

158

bool hasDomainType() const;

159

void setMinValue(double minValue);

160

void setMaxValue(double maxValue);

161

boost::optional<double> minValue() const;

162

boost::optional<double> maxValue() const;

163

164

// Choice-specific methods

165

std::vector<std::string> choiceValues() const;

166

std::vector<std::string> choiceDisplayNames() const;

167

void setChoiceDisplayName(const std::string& choice, const std::string& displayName);

168

};

169

170

/**

171

* Collection of arguments with type-safe value access

172

*/

173

using OSArgumentVector = std::vector<OSArgument>;

174

175

class OSArgumentMap {

176

public:

177

// Constructor

178

OSArgumentMap();

179

OSArgumentMap(const OSArgumentVector& arguments);

180

181

// Argument management

182

void insert(const std::string& name, const OSArgument& argument);

183

bool hasArgument(const std::string& name) const;

184

OSArgument getArgument(const std::string& name) const;

185

186

// Value access with type safety

187

boost::optional<bool> getArgumentValue(const std::string& name) const;

188

bool getArgumentValueAsBool(const std::string& name, bool defaultValue = false) const;

189

double getArgumentValueAsDouble(const std::string& name, double defaultValue = 0.0) const;

190

int getArgumentValueAsInteger(const std::string& name, int defaultValue = 0) const;

191

std::string getArgumentValueAsString(const std::string& name,

192

const std::string& defaultValue = std::string()) const;

193

Path getArgumentValueAsPath(const std::string& name) const;

194

195

// Validation

196

bool isValid(const OSArgumentVector& argumentVector) const;

197

std::vector<std::string> validate(const OSArgumentVector& argumentVector) const;

198

};

199

```

200

201

### Measure Execution Environment

202

203

Runtime environment for measure execution with logging and progress tracking.

204

205

```cpp { .api }

206

/**

207

* Measure execution environment and logging

208

*/

209

class OSRunner {

210

public:

211

// Constructor

212

OSRunner();

213

OSRunner(const WorkflowJSON& workflow);

214

215

// Logging methods

216

void registerInfo(const std::string& message);

217

void registerWarning(const std::string& message);

218

void registerError(const std::string& message);

219

void registerAsNotApplicable(const std::string& message);

220

void registerFinalCondition(const std::string& message);

221

222

// Progress tracking

223

void registerInitialCondition(const std::string& message);

224

void registerProgress(double percentComplete, const std::string& message = std::string());

225

226

// Value registration for reporting

227

void registerValue(const std::string& name, double value, const std::string& units = std::string());

228

void registerValue(const std::string& name, int value, const std::string& units = std::string());

229

void registerValue(const std::string& name, const std::string& value);

230

231

// File handling

232

bool registerFileForUpload(const Path& path, const std::string& filename = std::string());

233

Path workflow() const;

234

235

// Result queries

236

bool result() const;

237

std::vector<LogMessage> errors() const;

238

std::vector<LogMessage> warnings() const;

239

std::vector<LogMessage> info() const;

240

241

// Halt execution

242

void haltWorkflow(const std::string& completedStatus = std::string());

243

244

// Workflow step information

245

boost::optional<WorkflowStep> currentStep() const;

246

void setCurrentStep(const WorkflowStep& step);

247

248

// Model and workspace access during workflow

249

boost::optional<Model> lastOpenStudioModel() const;

250

void setLastOpenStudioModel(const Model& model);

251

252

boost::optional<Workspace> lastEnergyPlusWorkspace() const;

253

void setLastEnergyPlusWorkspace(const Workspace& workspace);

254

255

boost::optional<SqlFile> lastEnergyPlusSqlFile() const;

256

void setLastEnergyPlusSqlFile(const SqlFile& sqlFile);

257

};

258

```

259

260

### Building Component Library Integration

261

262

Integration with online measure and component libraries.

263

264

```cpp { .api }

265

/**

266

* Building Component Library measure access

267

*/

268

class BCLMeasure {

269

public:

270

// Constructor from local directory

271

BCLMeasure(const Path& directory);

272

273

// Metadata access

274

std::string uid() const;

275

std::string name() const;

276

std::string displayName() const;

277

std::string className() const;

278

std::string description() const;

279

std::string modelerDescription() const;

280

281

// Version and provenance

282

VersionString version() const;

283

std::string xmlChecksum() const;

284

285

// Taxonomy and tagging

286

std::vector<std::string> tags() const;

287

std::vector<BCLMeasureArgument> arguments() const;

288

std::vector<BCLMeasureOutput> outputs() const;

289

290

// File access

291

Path directory() const;

292

std::vector<BCLFileReference> files() const;

293

294

// Measure type

295

MeasureType measureType() const;

296

297

// Validation

298

bool isValid() const;

299

std::vector<std::string> errors() const;

300

301

// Updates from BCL

302

bool checkForUpdates();

303

bool update();

304

};

305

306

/**

307

* BCL measure argument metadata

308

*/

309

class BCLMeasureArgument {

310

public:

311

// Properties

312

std::string name() const;

313

std::string displayName() const;

314

std::string description() const;

315

std::string type() const;

316

std::string units() const;

317

bool required() const;

318

319

// Default value

320

boost::optional<std::string> defaultValue() const;

321

322

// Choice values for choice arguments

323

std::vector<std::string> choiceValues() const;

324

std::vector<std::string> choiceDisplayNames() const;

325

326

// Numeric constraints

327

boost::optional<double> minValue() const;

328

boost::optional<double> maxValue() const;

329

};

330

331

/**

332

* BCL measure output metadata

333

*/

334

class BCLMeasureOutput {

335

public:

336

std::string name() const;

337

std::string displayName() const;

338

std::string shortName() const;

339

std::string description() const;

340

std::string type() const;

341

std::string units() const;

342

std::string modelDependent() const;

343

};

344

345

// Measure type enumeration

346

enum class MeasureType {

347

ModelMeasure,

348

EnergyPlusMeasure,

349

ReportingMeasure

350

};

351

```

352

353

### Measure Utilities

354

355

Helper classes and utilities for common measure operations.

356

357

```cpp { .api }

358

/**

359

* Utilities for common measure operations

360

*/

361

namespace MeasureUtils {

362

363

// Model object utilities

364

template<typename T>

365

std::vector<T> getObjectsByType(const Model& model);

366

367

template<typename T>

368

boost::optional<T> getObjectByName(const Model& model, const std::string& name);

369

370

// Space and zone utilities

371

std::vector<Space> getSpacesByType(const Model& model,

372

const boost::optional<SpaceType>& spaceType = boost::none);

373

std::vector<ThermalZone> getZonesByName(const Model& model, const std::string& namePattern);

374

375

// Schedule utilities

376

boost::optional<Schedule> getScheduleByName(const Model& model, const std::string& name);

377

Schedule createConstantSchedule(Model& model, const std::string& name, double value);

378

379

// Construction and material utilities

380

std::vector<Construction> getConstructionsByType(const Model& model, const std::string& type);

381

boost::optional<Construction> cloneConstruction(Model& model,

382

const Construction& originalConstruction,

383

const std::string& newName);

384

385

// Load utilities

386

double getTotalFloorArea(const Model& model);

387

double getTotalConditionedFloorArea(const Model& model);

388

std::map<SpaceType, double> getFloorAreaBySpaceType(const Model& model);

389

390

// Cost utilities

391

double getTotalCost(const std::vector<LifeCycleCost>& costs);

392

boost::optional<LifeCycleCost> addCostToObject(ModelObject& object,

393

const std::string& name,

394

const std::string& category,

395

double cost);

396

397

// Validation utilities

398

bool validateModel(const Model& model, OSRunner& runner);

399

std::vector<std::string> getModelWarnings(const Model& model);

400

std::vector<std::string> getModelErrors(const Model& model);

401

}

402

```

403

404

## Common Usage Patterns

405

406

### Creating a Model Measure

407

408

```cpp

409

#include <openstudio/measure/ModelMeasure.hpp>

410

#include <openstudio/model/Model.hpp>

411

#include <openstudio/model/Space.hpp>

412

413

using namespace openstudio;

414

using namespace openstudio::model;

415

416

/**

417

* Example measure that adds daylighting controls to spaces

418

*/

419

class AddDaylightingControls : public ModelMeasure {

420

public:

421

// Measure metadata

422

virtual std::string name() const override {

423

return "Add Daylighting Controls";

424

}

425

426

virtual std::string description() const override {

427

return "This measure adds daylighting controls to specified space types.";

428

}

429

430

virtual std::string modeler_description() const override {

431

return "Adds DaylightingControl objects to spaces with the specified space type.";

432

}

433

434

// Define measure arguments

435

virtual OSArgumentVector arguments() override {

436

OSArgumentVector args;

437

438

// Space type selection

439

OSArgument spaceTypeName = OSArgument::makeStringArgument("space_type_name", true);

440

spaceTypeName.setDisplayName("Space Type Name");

441

spaceTypeName.setDescription("Name of space type to add daylighting controls to");

442

args.push_back(spaceTypeName);

443

444

// Control illuminance setpoint

445

OSArgument illuminanceSetpoint = OSArgument::makeDoubleArgument("illuminance_setpoint", true);

446

illuminanceSetpoint.setDisplayName("Illuminance Setpoint");

447

illuminanceSetpoint.setDescription("Illuminance setpoint for daylighting control");

448

illuminanceSetpoint.setUnits("lux");

449

illuminanceSetpoint.setDefaultValue(300.0);

450

illuminanceSetpoint.setMinValue(100.0);

451

illuminanceSetpoint.setMaxValue(1000.0);

452

args.push_back(illuminanceSetpoint);

453

454

return args;

455

}

456

457

// Implement measure logic

458

virtual bool run(Model& model, OSRunner& runner, const OSArgumentMap& user_arguments) override {

459

460

// Get arguments

461

std::string spaceTypeName = user_arguments.getArgumentValueAsString("space_type_name");

462

double illuminanceSetpoint = user_arguments.getArgumentValueAsDouble("illuminance_setpoint", 300.0);

463

464

runner.registerInitialCondition("Starting daylighting controls addition");

465

466

// Find space type

467

boost::optional<SpaceType> spaceType;

468

for (const auto& st : model.getConcreteModelObjects<SpaceType>()) {

469

if (st.name() && *st.name() == spaceTypeName) {

470

spaceType = st;

471

break;

472

}

473

}

474

475

if (!spaceType) {

476

runner.registerError("Space type '" + spaceTypeName + "' not found in model");

477

return false;

478

}

479

480

// Add daylighting controls to spaces with this space type

481

int controlsAdded = 0;

482

std::vector<Space> spaces = model.getConcreteModelObjects<Space>();

483

484

for (auto& space : spaces) {

485

if (space.spaceType() && space.spaceType().get() == spaceType.get()) {

486

487

// Create daylighting control

488

DaylightingControl daylightingControl(model);

489

daylightingControl.setSpace(space);

490

daylightingControl.setIlluminanceSetpoint(illuminanceSetpoint);

491

492

// Position at space centroid

493

boost::optional<Point3d> centroid = space.transformation() * space.floorPrint().centroid();

494

if (centroid) {

495

daylightingControl.setPositionXCoordinate(centroid->x());

496

daylightingControl.setPositionYCoordinate(centroid->y());

497

daylightingControl.setPositionZCoordinate(centroid->z() + 0.8); // 0.8m above floor

498

}

499

500

controlsAdded++;

501

runner.registerInfo("Added daylighting control to space: " + space.name().get_value_or("Unnamed"));

502

}

503

}

504

505

if (controlsAdded == 0) {

506

runner.registerAsNotApplicable("No spaces found with space type '" + spaceTypeName + "'");

507

return true;

508

}

509

510

runner.registerFinalCondition("Added " + std::to_string(controlsAdded) + " daylighting controls");

511

runner.registerValue("daylighting_controls_added", controlsAdded);

512

513

return true;

514

}

515

};

516

```

517

518

### Creating an EnergyPlus Measure

519

520

```cpp

521

#include <openstudio/measure/EnergyPlusMeasure.hpp>

522

#include <openstudio/utilities/idf/Workspace.hpp>

523

524

using namespace openstudio;

525

526

/**

527

* Example measure that modifies EnergyPlus simulation parameters

528

*/

529

class ModifySimulationParameters : public EnergyPlusMeasure {

530

public:

531

virtual std::string name() const override {

532

return "Modify Simulation Parameters";

533

}

534

535

virtual std::string description() const override {

536

return "This measure modifies EnergyPlus simulation control parameters.";

537

}

538

539

virtual OSArgumentVector arguments() override {

540

OSArgumentVector args;

541

542

// Timestep selection

543

std::vector<std::string> timestepChoices{"1", "2", "4", "6", "10", "15", "20", "30", "60"};

544

OSArgument timesteps = OSArgument::makeChoiceArgument("timesteps_per_hour", timestepChoices, true);

545

timesteps.setDisplayName("Timesteps per Hour");

546

timesteps.setDefaultValue("6");

547

args.push_back(timesteps);

548

549

// Solar distribution

550

std::vector<std::string> solarChoices{"MinimalShadowing", "FullExterior", "FullInteriorAndExterior"};

551

OSArgument solarDistribution = OSArgument::makeChoiceArgument("solar_distribution", solarChoices, true);

552

solarDistribution.setDisplayName("Solar Distribution Algorithm");

553

solarDistribution.setDefaultValue("FullExterior");

554

args.push_back(solarDistribution);

555

556

return args;

557

}

558

559

virtual bool run(Workspace& workspace, OSRunner& runner, const OSArgumentMap& user_arguments) override {

560

561

int timestepsPerHour = user_arguments.getArgumentValueAsInteger("timesteps_per_hour", 6);

562

std::string solarDistribution = user_arguments.getArgumentValueAsString("solar_distribution", "FullExterior");

563

564

runner.registerInitialCondition("Modifying EnergyPlus simulation parameters");

565

566

// Modify timestep

567

std::vector<WorkspaceObject> timestepObjects = workspace.getObjectsByType(IddObjectType::Timestep);

568

if (!timestepObjects.empty()) {

569

WorkspaceObject& timestepObj = timestepObjects[0];

570

timestepObj.setInt(0, timestepsPerHour);

571

runner.registerInfo("Set timesteps per hour to: " + std::to_string(timestepsPerHour));

572

} else {

573

// Create new timestep object

574

IdfObject newTimestep(IddObjectType::Timestep);

575

newTimestep.setInt(0, timestepsPerHour);

576

workspace.addObject(newTimestep);

577

runner.registerInfo("Created new timestep object with " + std::to_string(timestepsPerHour) + " timesteps per hour");

578

}

579

580

// Modify building object for solar distribution

581

std::vector<WorkspaceObject> buildingObjects = workspace.getObjectsByType(IddObjectType::Building);

582

if (!buildingObjects.empty()) {

583

WorkspaceObject& building = buildingObjects[0];

584

building.setString(2, solarDistribution); // Solar Distribution field

585

runner.registerInfo("Set solar distribution to: " + solarDistribution);

586

}

587

588

runner.registerFinalCondition("Successfully modified simulation parameters");

589

return true;

590

}

591

};

592

```

593

594

### Using Measures in Applications

595

596

```cpp

597

#include <openstudio/measure/OSRunner.hpp>

598

#include <openstudio/utilities/bcl/BCLMeasure.hpp>

599

600

using namespace openstudio;

601

602

// Function to run a measure on a model

603

bool runMeasureOnModel(Model& model, const BCLMeasure& measure, const OSArgumentMap& arguments) {

604

605

// Create runner

606

OSRunner runner;

607

608

// Load measure class (this would typically involve dynamic loading)

609

// For this example, assume we have the measure instance

610

std::unique_ptr<ModelMeasure> measureInstance = loadMeasureFromBCL(measure);

611

612

if (!measureInstance) {

613

std::cout << "Failed to load measure: " << measure.name() << std::endl;

614

return false;

615

}

616

617

// Run the measure

618

bool success = measureInstance->run(model, runner, arguments);

619

620

// Handle results

621

std::vector<LogMessage> errors = runner.errors();

622

std::vector<LogMessage> warnings = runner.warnings();

623

std::vector<LogMessage> info = runner.info();

624

625

// Log all messages

626

for (const auto& msg : errors) {

627

std::cout << "ERROR: " << msg.logMessage() << std::endl;

628

}

629

630

for (const auto& msg : warnings) {

631

std::cout << "WARNING: " << msg.logMessage() << std::endl;

632

}

633

634

for (const auto& msg : info) {

635

std::cout << "INFO: " << msg.logMessage() << std::endl;

636

}

637

638

return success && errors.empty();

639

}

640

641

// Function to apply multiple measures in sequence

642

bool runMeasureSequence(Model& model, const std::vector<std::pair<BCLMeasure, OSArgumentMap>>& measures) {

643

644

for (const auto& measurePair : measures) {

645

const BCLMeasure& measure = measurePair.first;

646

const OSArgumentMap& arguments = measurePair.second;

647

648

std::cout << "Running measure: " << measure.displayName() << std::endl;

649

650

bool success = runMeasureOnModel(model, measure, arguments);

651

if (!success) {

652

std::cout << "Measure failed: " << measure.displayName() << std::endl;

653

return false;

654

}

655

}

656

657

return true;

658

}

659

```

660

661

### Argument Validation and Error Handling

662

663

```cpp

664

#include <openstudio/measure/OSArgument.hpp>

665

666

using namespace openstudio;

667

668

// Function to create and validate measure arguments

669

OSArgumentMap createValidatedArguments(const OSArgumentVector& argumentDefinitions) {

670

OSArgumentMap argumentMap;

671

672

for (const auto& argDef : argumentDefinitions) {

673

OSArgument arg = argDef; // Copy the definition

674

675

// Set values based on argument type and validation rules

676

if (argDef.type() == OSArgument::Type::Double) {

677

double value = 25.0; // Example value

678

679

// Check constraints

680

if (argDef.minValue() && value < *argDef.minValue()) {

681

value = *argDef.minValue();

682

std::cout << "Adjusted " << argDef.name() << " to minimum value: " << value << std::endl;

683

}

684

685

if (argDef.maxValue() && value > *argDef.maxValue()) {

686

value = *argDef.maxValue();

687

std::cout << "Adjusted " << argDef.name() << " to maximum value: " << value << std::endl;

688

}

689

690

arg.setDefaultValue(value);

691

}

692

693

else if (argDef.type() == OSArgument::Type::Choice) {

694

std::vector<std::string> choices = argDef.choiceValues();

695

if (!choices.empty()) {

696

arg.setDefaultValue(choices[0]); // Use first choice as default

697

}

698

}

699

700

argumentMap.insert(argDef.name(), arg);

701

}

702

703

// Validate the complete argument map

704

std::vector<std::string> validationErrors = argumentMap.validate(argumentDefinitions);

705

if (!validationErrors.empty()) {

706

std::cout << "Validation errors:" << std::endl;

707

for (const auto& error : validationErrors) {

708

std::cout << " " << error << std::endl;

709

}

710

}

711

712

return argumentMap;

713

}

714

```