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
```