or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

workflow.mddocs/

0

# Workflow Management

1

2

Orchestration of complete building simulation workflows from initial model through results processing. The workflow system manages the complete analysis pipeline including model measures, EnergyPlus simulation, and reporting measures with comprehensive error handling and progress tracking.

3

4

## Capabilities

5

6

### Workflow Orchestration

7

8

Main workflow coordination class managing the complete simulation pipeline.

9

10

```cpp { .api }

11

/**

12

* Main workflow orchestrator for complete building simulation workflows

13

*/

14

class OSWorkflow {

15

public:

16

// Constructors

17

OSWorkflow();

18

explicit OSWorkflow(const Path& oswPath);

19

explicit OSWorkflow(const WorkflowJSON& workflowJSON);

20

21

// Workflow execution

22

bool run();

23

bool run(const Path& oswPath);

24

25

// Workflow configuration

26

WorkflowJSON workflowJSON() const;

27

void setWorkflowJSON(const WorkflowJSON& workflowJSON);

28

29

// Model and simulation access

30

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

31

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

32

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

33

34

// Results and logging

35

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

36

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

37

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

38

39

// Workflow state

40

bool completed() const;

41

std::string completedStatus() const;

42

43

// Progress tracking

44

void setProgressCallback(std::function<void(int)> callback);

45

46

// Step-by-step execution

47

bool runInitialization();

48

bool runOpenStudioMeasures();

49

bool runTranslator();

50

bool runEnergyPlus();

51

bool runReportingMeasures();

52

bool runCleanup();

53

54

// Working directory management

55

Path rootDirectory() const;

56

Path runDirectory() const;

57

void setRunDirectory(const Path& runDirectory);

58

59

// Simulation files

60

Path osmPath() const;

61

Path idfPath() const;

62

boost::optional<Path> sqlPath() const;

63

boost::optional<Path> epwPath() const;

64

};

65

```

66

67

**Usage Examples:**

68

69

```cpp

70

#include <openstudio/workflow/OSWorkflow.hpp>

71

#include <openstudio/utilities/filetypes/WorkflowJSON.hpp>

72

73

using namespace openstudio;

74

75

// Simple workflow execution

76

OSWorkflow workflow;

77

78

// Load workflow configuration

79

WorkflowJSON workflowJSON = WorkflowJSON::load(Path("simulation_workflow.osw")).get();

80

workflow.setWorkflowJSON(workflowJSON);

81

82

// Run complete workflow

83

bool success = workflow.run();

84

85

if (success) {

86

// Access results

87

boost::optional<Model> finalModel = workflow.model();

88

boost::optional<SqlFile> results = workflow.sqlFile();

89

90

if (results) {

91

std::cout << "Simulation completed successfully" << std::endl;

92

}

93

} else {

94

// Handle errors

95

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

96

for (const auto& error : errors) {

97

std::cout << "Workflow Error: " << error.logMessage() << std::endl;

98

}

99

}

100

```

101

102

### Workflow JSON Configuration

103

104

JSON-based workflow configuration and serialization.

105

106

```cpp { .api }

107

/**

108

* JSON-based workflow configuration

109

*/

110

class WorkflowJSON {

111

public:

112

// Constructors

113

WorkflowJSON();

114

WorkflowJSON(const Path& seedFile, const Path& weatherFile);

115

116

// File I/O

117

static boost::optional<WorkflowJSON> load(const Path& path);

118

bool save(const Path& path) const;

119

bool saveAs(const Path& path);

120

121

// Seed file (starting model)

122

boost::optional<Path> seedFile() const;

123

bool setSeedFile(const Path& seedFile);

124

void resetSeedFile();

125

126

// Weather file

127

boost::optional<Path> weatherFile() const;

128

bool setWeatherFile(const Path& weatherFile);

129

void resetWeatherFile();

130

131

// Measure steps

132

std::vector<MeasureStep> measures() const;

133

bool addMeasure(const MeasureStep& measureStep);

134

bool insertMeasure(int index, const MeasureStep& measureStep);

135

bool removeMeasure(int index);

136

void clearMeasures();

137

138

// File paths

139

std::vector<Path> filePaths() const;

140

bool addFilePath(const Path& filePath);

141

142

// Run options

143

boost::optional<RunOptions> runOptions() const;

144

void setRunOptions(const RunOptions& runOptions);

145

146

// Root directory

147

boost::optional<Path> rootDirectory() const;

148

void setRootDirectory(const Path& rootDirectory);

149

150

// JSON access

151

std::string string() const;

152

Json::Value toJSON() const;

153

154

// Validation

155

bool isValid() const;

156

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

157

};

158

159

/**

160

* Individual measure step configuration

161

*/

162

class MeasureStep {

163

public:

164

// Constructors

165

MeasureStep();

166

MeasureStep(const std::string& measureDirName);

167

MeasureStep(const BCLMeasure& bclMeasure);

168

169

// Measure identification

170

std::string measureDirName() const;

171

void setMeasureDirName(const std::string& measureDirName);

172

173

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

174

void setName(const std::string& name);

175

176

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

177

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

178

179

// Measure arguments

180

std::map<std::string, OSArgument> arguments() const;

181

bool setArgument(const OSArgument& argument);

182

bool setArgument(const std::string& name, const std::string& value);

183

bool setArgument(const std::string& name, double value);

184

bool setArgument(const std::string& name, int value);

185

bool setArgument(const std::string& name, bool value);

186

187

// Step properties

188

boost::optional<MeasureType> measureType() const;

189

void setMeasureType(MeasureType measureType);

190

191

// Results

192

boost::optional<StepResult> result() const;

193

void setResult(const StepResult& result);

194

void resetResult();

195

};

196

197

/**

198

* Workflow run options and simulation settings

199

*/

200

class RunOptions {

201

public:

202

// Constructors

203

RunOptions();

204

205

// EnergyPlus options

206

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

207

void setDebug(bool debug);

208

209

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

210

void setFastExecution(bool fastExecution);

211

212

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

213

void setPreserveRunDir(bool preserveRunDir);

214

215

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

216

void setCleanup(bool cleanup);

217

218

// Simulation options

219

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

220

void setMaxDatapoints(int maxDatapoints);

221

222

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

223

void setNumParallel(int numParallel);

224

225

// Custom options

226

std::map<std::string, std::string> customOptions() const;

227

void setCustomOption(const std::string& key, const std::string& value);

228

};

229

```

230

231

### Workflow Steps

232

233

Individual workflow step implementations for different phases of simulation.

234

235

```cpp { .api }

236

/**

237

* Base class for workflow steps

238

*/

239

class WorkflowStep {

240

public:

241

// Step identification

242

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

243

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

244

245

// Execution

246

virtual StepResult run(OSWorkflow& workflow) = 0;

247

248

// Step type

249

virtual WorkflowStepType stepType() const = 0;

250

};

251

252

/**

253

* Initialization step - validates inputs and sets up workflow

254

*/

255

class RunInitialization : public WorkflowStep {

256

public:

257

RunInitialization();

258

259

virtual std::string stepName() const override { return "Initialization"; }

260

virtual std::string stepDescription() const override {

261

return "Initialize workflow and validate inputs";

262

}

263

264

virtual StepResult run(OSWorkflow& workflow) override;

265

virtual WorkflowStepType stepType() const override { return WorkflowStepType::Initialization; }

266

};

267

268

/**

269

* OpenStudio measures step - applies model measures

270

*/

271

class RunOpenStudioMeasures : public WorkflowStep {

272

public:

273

RunOpenStudioMeasures();

274

275

virtual std::string stepName() const override { return "OpenStudio Measures"; }

276

virtual std::string stepDescription() const override {

277

return "Apply OpenStudio model measures";

278

}

279

280

virtual StepResult run(OSWorkflow& workflow) override;

281

virtual WorkflowStepType stepType() const override { return WorkflowStepType::ModelMeasures; }

282

283

// Measure filtering

284

void setMeasureFilter(std::function<bool(const MeasureStep&)> filter);

285

};

286

287

/**

288

* Translation step - converts OpenStudio model to EnergyPlus IDF

289

*/

290

class RunTranslator : public WorkflowStep {

291

public:

292

RunTranslator();

293

294

virtual std::string stepName() const override { return "Forward Translator"; }

295

virtual std::string stepDescription() const override {

296

return "Translate OpenStudio model to EnergyPlus IDF";

297

}

298

299

virtual StepResult run(OSWorkflow& workflow) override;

300

virtual WorkflowStepType stepType() const override { return WorkflowStepType::Translation; }

301

302

// Translation options

303

void setTranslationOptions(const ForwardTranslatorOptions& options);

304

};

305

306

/**

307

* EnergyPlus simulation step

308

*/

309

class RunEnergyPlus : public WorkflowStep {

310

public:

311

RunEnergyPlus();

312

313

virtual std::string stepName() const override { return "EnergyPlus"; }

314

virtual std::string stepDescription() const override {

315

return "Run EnergyPlus simulation";

316

}

317

318

virtual StepResult run(OSWorkflow& workflow) override;

319

virtual WorkflowStepType stepType() const override { return WorkflowStepType::Simulation; }

320

321

// Simulation options

322

void setEnergyPlusPath(const Path& energyPlusPath);

323

void setNumThreads(int numThreads);

324

};

325

326

/**

327

* Reporting measures step - processes simulation results

328

*/

329

class RunReportingMeasures : public WorkflowStep {

330

public:

331

RunReportingMeasures();

332

333

virtual std::string stepName() const override { return "Reporting Measures"; }

334

virtual std::string stepDescription() const override {

335

return "Apply reporting measures to process results";

336

}

337

338

virtual StepResult run(OSWorkflow& workflow) override;

339

virtual WorkflowStepType stepType() const override { return WorkflowStepType::ReportingMeasures; }

340

};

341

342

// Workflow step type enumeration

343

enum class WorkflowStepType {

344

Initialization,

345

ModelMeasures,

346

EnergyPlusMeasures,

347

Translation,

348

Simulation,

349

ReportingMeasures,

350

Cleanup

351

};

352

```

353

354

### Results and Status Tracking

355

356

Comprehensive result tracking and status management for workflow execution.

357

358

```cpp { .api }

359

/**

360

* Step execution result

361

*/

362

class StepResult {

363

public:

364

// Result status

365

enum class Status {

366

NotStarted,

367

Running,

368

Success,

369

Fail,

370

Skip,

371

NA // Not Applicable

372

};

373

374

// Constructors

375

StepResult();

376

StepResult(Status initialStatus);

377

378

// Status management

379

Status status() const;

380

void setStatus(Status status);

381

382

std::string statusDescription() const;

383

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

384

385

// Execution details

386

boost::optional<DateTime> startTime() const;

387

void setStartTime(const DateTime& startTime);

388

389

boost::optional<DateTime> endTime() const;

390

void setEndTime(const DateTime& endTime);

391

392

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

393

394

// Error and warning messages

395

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

396

void addError(const LogMessage& error);

397

398

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

399

void addWarning(const LogMessage& warning);

400

401

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

402

void addInfo(const LogMessage& info);

403

404

// Step outputs

405

std::vector<StepFile> stepFiles() const;

406

void addStepFile(const StepFile& stepFile);

407

408

std::vector<OSAttribute> stepValues() const;

409

void addStepValue(const OSAttribute& stepValue);

410

411

// Initial and final conditions

412

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

413

void setInitialCondition(const std::string& condition);

414

415

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

416

void setFinalCondition(const std::string& condition);

417

};

418

419

/**

420

* File output from workflow steps

421

*/

422

class StepFile {

423

public:

424

// Constructors

425

StepFile();

426

StepFile(const Path& path);

427

428

// File properties

429

Path path() const;

430

void setPath(const Path& path);

431

432

std::string displayName() const;

433

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

434

435

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

436

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

437

438

// File type

439

std::string fileType() const;

440

void setFileType(const std::string& fileType);

441

442

// Usage type (input, output, resource)

443

std::string usageType() const;

444

void setUsageType(const std::string& usageType);

445

};

446

447

/**

448

* Workflow progress tracking

449

*/

450

class WorkflowProgress {

451

public:

452

WorkflowProgress();

453

454

// Overall progress

455

double overallProgress() const;

456

void setOverallProgress(double progress);

457

458

// Current step

459

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

460

void setCurrentStep(WorkflowStepType step);

461

462

double stepProgress() const;

463

void setStepProgress(double progress);

464

465

std::string currentActivity() const;

466

void setCurrentActivity(const std::string& activity);

467

468

// Step results

469

std::vector<StepResult> stepResults() const;

470

void addStepResult(const StepResult& result);

471

472

// Callback registration

473

void setProgressCallback(std::function<void(double)> callback);

474

void setStepCallback(std::function<void(WorkflowStepType, double, const std::string&)> callback);

475

};

476

```

477

478

### Parallel Workflow Execution

479

480

Support for parallel workflow execution and datapoint management.

481

482

```cpp { .api }

483

/**

484

* Parallel workflow execution for multiple datapoints

485

*/

486

class ParallelWorkflow {

487

public:

488

// Constructor

489

ParallelWorkflow();

490

ParallelWorkflow(int numParallel);

491

492

// Datapoint management

493

void addDatapoint(const WorkflowJSON& datapoint);

494

void addDatapoints(const std::vector<WorkflowJSON>& datapoints);

495

496

std::vector<WorkflowJSON> datapoints() const;

497

int numDatapoints() const;

498

499

// Execution settings

500

int numParallel() const;

501

void setNumParallel(int numParallel);

502

503

// Execute all datapoints

504

bool run();

505

bool run(const Path& outputDirectory);

506

507

// Results access

508

std::vector<StepResult> results() const;

509

StepResult result(int datapointIndex) const;

510

511

bool allSucceeded() const;

512

int numSucceeded() const;

513

int numFailed() const;

514

515

// Progress tracking

516

void setProgressCallback(std::function<void(int, int)> callback);

517

518

// Cancel execution

519

void cancel();

520

bool cancelled() const;

521

};

522

523

/**

524

* Distributed workflow execution

525

*/

526

class DistributedWorkflow {

527

public:

528

DistributedWorkflow();

529

530

// Cluster configuration

531

void setServerConfig(const std::string& serverUrl, int port);

532

void setAuthToken(const std::string& token);

533

534

// Job submission

535

std::string submitJob(const WorkflowJSON& workflow);

536

std::vector<std::string> submitJobs(const std::vector<WorkflowJSON>& workflows);

537

538

// Job monitoring

539

enum class JobStatus { Queued, Running, Completed, Failed, Cancelled };

540

541

JobStatus getJobStatus(const std::string& jobId);

542

std::map<std::string, JobStatus> getJobStatuses(const std::vector<std::string>& jobIds);

543

544

// Results retrieval

545

boost::optional<StepResult> getJobResult(const std::string& jobId);

546

std::vector<Path> getJobOutputFiles(const std::string& jobId);

547

548

// Job management

549

bool cancelJob(const std::string& jobId);

550

bool deleteJob(const std::string& jobId);

551

};

552

```

553

554

## Common Usage Patterns

555

556

### Basic Workflow Execution

557

558

```cpp

559

#include <openstudio/workflow/OSWorkflow.hpp>

560

#include <openstudio/utilities/filetypes/WorkflowJSON.hpp>

561

562

using namespace openstudio;

563

564

// Create workflow configuration

565

WorkflowJSON workflowJSON;

566

567

// Set seed model and weather file

568

workflowJSON.setSeedFile(Path("baseline_model.osm"));

569

workflowJSON.setWeatherFile(Path("weather.epw"));

570

571

// Add model measures

572

MeasureStep improveLighting;

573

improveLighting.setMeasureDirName("improve_lighting_efficiency");

574

improveLighting.setArgument("lighting_power_density_reduction", 0.3);

575

workflowJSON.addMeasure(improveLighting);

576

577

MeasureStep improveHVAC;

578

improveHVAC.setMeasureDirName("improve_hvac_efficiency");

579

improveHVAC.setArgument("cop_improvement", 0.15);

580

workflowJSON.addMeasure(improveHVAC);

581

582

// Add reporting measure

583

MeasureStep energyReport;

584

energyReport.setMeasureDirName("energy_use_summary_report");

585

workflowJSON.addMeasure(energyReport);

586

587

// Set run options

588

RunOptions runOptions;

589

runOptions.setPreserveRunDir(true);

590

runOptions.setDebug(false);

591

workflowJSON.setRunOptions(runOptions);

592

593

// Execute workflow

594

OSWorkflow workflow;

595

workflow.setWorkflowJSON(workflowJSON);

596

597

std::cout << "Starting workflow execution..." << std::endl;

598

bool success = workflow.run();

599

600

if (success) {

601

std::cout << "Workflow completed successfully!" << std::endl;

602

603

// Access final results

604

boost::optional<SqlFile> sqlFile = workflow.sqlFile();

605

if (sqlFile) {

606

// Process simulation results

607

boost::optional<double> totalEnergy = sqlFile->totalSiteEnergy();

608

if (totalEnergy) {

609

std::cout << "Total site energy: " << *totalEnergy << " GJ" << std::endl;

610

}

611

}

612

613

} else {

614

std::cout << "Workflow failed!" << std::endl;

615

616

// Print errors

617

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

618

for (const auto& error : errors) {

619

std::cout << "Error: " << error.logMessage() << std::endl;

620

}

621

}

622

```

623

624

### Step-by-Step Workflow Execution

625

626

```cpp

627

#include <openstudio/workflow/OSWorkflow.hpp>

628

629

using namespace openstudio;

630

631

OSWorkflow workflow(Path("detailed_workflow.osw"));

632

633

// Execute workflow step by step with detailed monitoring

634

std::cout << "Step 1: Initialization..." << std::endl;

635

if (!workflow.runInitialization()) {

636

std::cout << "Initialization failed!" << std::endl;

637

return false;

638

}

639

640

std::cout << "Step 2: Applying model measures..." << std::endl;

641

if (!workflow.runOpenStudioMeasures()) {

642

std::cout << "Model measures failed!" << std::endl;

643

return false;

644

}

645

646

// Check intermediate model

647

boost::optional<Model> model = workflow.model();

648

if (model) {

649

std::vector<ThermalZone> zones = model->getConcreteModelObjects<ThermalZone>();

650

std::cout << "Model now has " << zones.size() << " thermal zones" << std::endl;

651

}

652

653

std::cout << "Step 3: Translating to EnergyPlus..." << std::endl;

654

if (!workflow.runTranslator()) {

655

std::cout << "Translation failed!" << std::endl;

656

return false;

657

}

658

659

std::cout << "Step 4: Running EnergyPlus simulation..." << std::endl;

660

if (!workflow.runEnergyPlus()) {

661

std::cout << "EnergyPlus simulation failed!" << std::endl;

662

return false;

663

}

664

665

std::cout << "Step 5: Processing results..." << std::endl;

666

if (!workflow.runReportingMeasures()) {

667

std::cout << "Reporting measures failed!" << std::endl;

668

return false;

669

}

670

671

std::cout << "Step 6: Cleanup..." << std::endl;

672

if (!workflow.runCleanup()) {

673

std::cout << "Cleanup failed!" << std::endl;

674

return false;

675

}

676

677

std::cout << "All workflow steps completed successfully!" << std::endl;

678

```

679

680

### Parallel Datapoint Execution

681

682

```cpp

683

#include <openstudio/workflow/ParallelWorkflow.hpp>

684

685

using namespace openstudio;

686

687

// Create base workflow

688

WorkflowJSON baseWorkflow;

689

baseWorkflow.setSeedFile(Path("base_model.osm"));

690

baseWorkflow.setWeatherFile(Path("weather.epw"));

691

692

// Create parametric study

693

ParallelWorkflow parallelWorkflow(4); // Use 4 parallel processes

694

695

std::vector<double> wwrValues = {0.2, 0.3, 0.4, 0.5}; // Window-to-wall ratios

696

std::vector<double> insulationValues = {0.1, 0.15, 0.2, 0.25}; // Insulation R-values

697

698

for (double wwr : wwrValues) {

699

for (double insulation : insulationValues) {

700

701

// Create datapoint workflow

702

WorkflowJSON datapoint = baseWorkflow;

703

704

// Add parametric measures

705

MeasureStep wwrMeasure;

706

wwrMeasure.setMeasureDirName("set_window_to_wall_ratio");

707

wwrMeasure.setArgument("wwr", wwr);

708

datapoint.addMeasure(wwrMeasure);

709

710

MeasureStep insulationMeasure;

711

insulationMeasure.setMeasureDirName("set_wall_insulation");

712

insulationMeasure.setArgument("r_value", insulation);

713

datapoint.addMeasure(insulationMeasure);

714

715

// Add to parallel execution

716

parallelWorkflow.addDatapoint(datapoint);

717

}

718

}

719

720

// Set progress callback

721

parallelWorkflow.setProgressCallback([](int completed, int total) {

722

double progress = (double)completed / total * 100.0;

723

std::cout << "Progress: " << completed << "/" << total

724

<< " (" << std::fixed << std::setprecision(1) << progress << "%)" << std::endl;

725

});

726

727

// Execute all datapoints

728

std::cout << "Starting parametric study with " << parallelWorkflow.numDatapoints() << " datapoints..." << std::endl;

729

bool success = parallelWorkflow.run(Path("parametric_results"));

730

731

if (success) {

732

std::cout << "Parametric study completed!" << std::endl;

733

std::cout << "Successful runs: " << parallelWorkflow.numSucceeded()

734

<< "/" << parallelWorkflow.numDatapoints() << std::endl;

735

736

// Process results from all datapoints

737

std::vector<StepResult> results = parallelWorkflow.results();

738

for (size_t i = 0; i < results.size(); ++i) {

739

if (results[i].status() == StepResult::Status::Success) {

740

std::cout << "Datapoint " << i << " completed successfully" << std::endl;

741

} else {

742

std::cout << "Datapoint " << i << " failed: " << results[i].statusDescription() << std::endl;

743

}

744

}

745

746

} else {

747

std::cout << "Parametric study failed!" << std::endl;

748

}

749

```

750

751

### Custom Workflow Steps

752

753

```cpp

754

#include <openstudio/workflow/WorkflowStep.hpp>

755

756

using namespace openstudio;

757

758

/**

759

* Custom workflow step for model validation

760

*/

761

class ModelValidationStep : public WorkflowStep {

762

public:

763

virtual std::string stepName() const override {

764

return "Model Validation";

765

}

766

767

virtual std::string stepDescription() const override {

768

return "Validate model geometry and HVAC systems";

769

}

770

771

virtual StepResult run(OSWorkflow& workflow) override {

772

StepResult result(StepResult::Status::Running);

773

774

boost::optional<Model> model = workflow.model();

775

if (!model) {

776

result.setStatus(StepResult::Status::Fail);

777

result.addError(LogMessage(LogLevel::Error, "No model available for validation"));

778

return result;

779

}

780

781

std::vector<std::string> validationIssues;

782

783

// Check for spaces without thermal zones

784

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

785

for (const auto& space : spaces) {

786

if (!space.thermalZone()) {

787

validationIssues.push_back("Space '" + space.name().get_value_or("Unnamed") +

788

"' is not assigned to a thermal zone");

789

}

790

}

791

792

// Check for surfaces without constructions

793

std::vector<Surface> surfaces = model->getConcreteModelObjects<Surface>();

794

for (const auto& surface : surfaces) {

795

if (!surface.construction()) {

796

validationIssues.push_back("Surface '" + surface.name().get_value_or("Unnamed") +

797

"' has no construction assigned");

798

}

799

}

800

801

// Report validation results

802

if (validationIssues.empty()) {

803

result.setStatus(StepResult::Status::Success);

804

result.setFinalCondition("Model validation passed with no issues");

805

} else {

806

result.setStatus(StepResult::Status::Success); // Warnings, not errors

807

for (const auto& issue : validationIssues) {

808

result.addWarning(LogMessage(LogLevel::Warn, issue));

809

}

810

result.setFinalCondition("Model validation completed with " +

811

std::to_string(validationIssues.size()) + " warnings");

812

}

813

814

return result;

815

}

816

817

virtual WorkflowStepType stepType() const override {

818

return WorkflowStepType::ModelMeasures; // Custom type could be added

819

}

820

};

821

822

// Usage in custom workflow

823

void runCustomWorkflow() {

824

OSWorkflow workflow(Path("model.osm"));

825

826

// Add custom validation step

827

ModelValidationStep validationStep;

828

StepResult validationResult = validationStep.run(workflow);

829

830

if (validationResult.status() != StepResult::Status::Success) {

831

std::cout << "Validation failed, aborting workflow" << std::endl;

832

return;

833

}

834

835

// Continue with standard workflow steps

836

workflow.runTranslator();

837

workflow.runEnergyPlus();

838

workflow.runReportingMeasures();

839

}

840

```