Class: OpenStudio::Workflow::Run
- Inherits:
-
Object
- Object
- OpenStudio::Workflow::Run
- Defined in:
- lib/openstudio/workflow/run.rb
Instance Attribute Summary collapse
-
#current_state ⇒ Object
readonly
Returns the value of attribute current_state.
-
#final_message ⇒ Object
readonly
Returns the value of attribute final_message.
-
#input_adapter ⇒ Object
readonly
Returns the value of attribute input_adapter.
-
#job_results ⇒ Object
readonly
Returns the value of attribute job_results.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#output_adapter ⇒ Object
readonly
Returns the value of attribute output_adapter.
-
#registry ⇒ Object
Returns the value of attribute registry.
Class Method Summary collapse
-
.default_jobs ⇒ Object
Define the default set of jobs.
Instance Method Summary collapse
-
#initialize(osw_path, user_options = {}) ⇒ Run
constructor
Initialize a new run class.
-
#run ⇒ Object
execute the workflow defined in the state object.
-
#run_finished(_, _, _) ⇒ Object
Return the finished state and exit.
-
#step ⇒ Object
Step through the states, if there is an error (e.g. exception) then go to error.
-
#step_error(*args) ⇒ Object
Error handling for when there is an exception running any of the state transitions.
Constructor Details
#initialize(osw_path, user_options = {}) ⇒ Run
Initialize a new run class
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/openstudio/workflow/run.rb', line 100 def initialize(osw_path, = {}) # DLM - what is final_message? = '' @current_state = nil = {} # Registry is a large hash of objects that are populated during the run, the number of objects in the registry should be reduced over time, especially if the functionality can be added to the WorkflowJSON class # - analysis - the current OSA parsed as a Ruby Hash # - datapoint - the current OSD parsed as a Ruby Hash # - log_targets - IO devices that are being logged to # - logger - general logger # - model - the current OpenStudio Model object, updated after each step # - model_idf - the current EnergyPlus Workspace object, updated after each step # - openstudio_2 - true if we are running in OpenStudio 2.X environment # - osw_path - the path the OSW was loaded from as a string # - osw_dir - the directory the OSW was loaded from as a string # - output_attributes - added during simulation time # - results - objective function values # - root_dir - the root directory in the OSW as a string # - run_dir - the run directory for the simulation as a string # - runner - the current OSRunner object # - sql - the path to the current EnergyPlus SQL file as a string # - time_logger - logger for doing profiling - time to run each step will be captured in OSResult, deprecate # - wf - the path to the current weather file as a string, updated after each step # - workflow - the current OSW parsed as a Ruby Hash # - workflow_json - the current WorkflowJSON object @registry = Registry.new openstudio_2 = false begin # OpenStudio 2.X test OpenStudio::WorkflowJSON.new openstudio_2 = true rescue NameError => e end @registry.register(:openstudio_2) { openstudio_2 } # get the input osw @input_adapter = OpenStudio::Workflow::InputAdapter::Local.new(osw_path) # DLM: need to check that we have correct permissions to all these paths @registry.register(:osw_path) { Pathname.new(@input_adapter.osw_path).realpath } @registry.register(:osw_dir) { Pathname.new(@input_adapter.osw_dir).realpath } @registry.register(:run_dir) { Pathname.new(@input_adapter.run_dir).cleanpath } # run dir might not yet exist, calling realpath will throw # get info to set up logging first in case of failures later [:debug] = @input_adapter.debug(, false) [:preserve_run_dir] = @input_adapter.preserve_run_dir(, false) [:skip_expand_objects] = @input_adapter.(, false) [:skip_energyplus_preprocess] = @input_adapter.skip_energyplus_preprocess(, false) [:profile] = @input_adapter.profile(, false) # if running in osw dir, force preserve run dir if @registry[:osw_dir] == @registry[:run_dir] # force preserving the run directory [:preserve_run_dir] = true end # By default blow away the entire run directory every time and recreate it if ![:preserve_run_dir] && File.exist?(@registry[:run_dir]) # logger is not initialized yet (it needs run dir to exist for log) puts "Removing existing run directory #{@registry[:run_dir]}" if [:debug] # DLM: this is dangerous, we are calling rm_rf on a user entered directory, need to check this first # TODO: Echoing Dan's comment FileUtils.rm_rf(@registry[:run_dir]) end FileUtils.mkdir_p(@registry[:run_dir]) # set up logging after cleaning run dir if [:targets] [:targets] = [:targets] else # don't create these files unless we want to use them # DLM: TODO, make sure that run.log will be closed later [:targets] = [$stdout, File.open(File.join(@registry[:run_dir], 'run.log'), 'a')] end @registry.register(:log_targets) { [:targets] } @registry.register(:time_logger) { TimeLogger.new } if [:profile] # Initialize the MultiDelegator logger logger_level = [:debug] ? ::Logger::DEBUG : ::Logger::WARN @logger = ::Logger.new(MultiDelegator.delegate(:write, :close).to(*[:targets])) # * is the splat operator @logger.level = logger_level @registry.register(:logger) { @logger } @logger.info "openstudio_2 = #{@registry[:openstudio_2]}" # get the output adapter default_output_adapter = OpenStudio::Workflow::OutputAdapter::Local.new(output_directory: @input_adapter.run_dir) @output_adapter = @input_adapter.output_adapter(, default_output_adapter, @logger) # get the jobs default_jobs = OpenStudio::Workflow::Run.default_jobs @jobs = @input_adapter.jobs(, default_jobs, @logger) # get other run options out of user_options and into permanent options [:cleanup] = @input_adapter.cleanup(, true) [:energyplus_path] = @input_adapter.energyplus_path(, nil) [:verify_osw] = @input_adapter.verify_osw(, true) [:weather_file] = @input_adapter.weather_file(, nil) [:fast] = @input_adapter.fast(, false) [:skip_zip_results] = @input_adapter.skip_zip_results(, false) [:epjson] = @input_adapter.epjson(, false, @logger) [:ft_options] = @input_adapter.(, {}, @logger) openstudio_dir = 'unknown' begin openstudio_dir = $OpenStudio_Dir if openstudio_dir.nil? openstudio_dir = OpenStudio.getOpenStudioModuleDirectory.to_s end rescue StandardError end @logger.info "openstudio_dir = #{openstudio_dir}" @logger.info "Initializing directory #{@registry[:run_dir]} for simulation with options #{@options}" # Define the state and transitions @current_state = :queued end |
Instance Attribute Details
#current_state ⇒ Object (readonly)
Returns the value of attribute current_state.
51 52 53 |
# File 'lib/openstudio/workflow/run.rb', line 51 def current_state @current_state end |
#final_message ⇒ Object (readonly)
Returns the value of attribute final_message.
51 52 53 |
# File 'lib/openstudio/workflow/run.rb', line 51 def end |
#input_adapter ⇒ Object (readonly)
Returns the value of attribute input_adapter.
51 52 53 |
# File 'lib/openstudio/workflow/run.rb', line 51 def input_adapter @input_adapter end |
#job_results ⇒ Object (readonly)
Returns the value of attribute job_results.
51 52 53 |
# File 'lib/openstudio/workflow/run.rb', line 51 def job_results @job_results end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
51 52 53 |
# File 'lib/openstudio/workflow/run.rb', line 51 def end |
#output_adapter ⇒ Object (readonly)
Returns the value of attribute output_adapter.
51 52 53 |
# File 'lib/openstudio/workflow/run.rb', line 51 def output_adapter @output_adapter end |
#registry ⇒ Object
Returns the value of attribute registry.
49 50 51 |
# File 'lib/openstudio/workflow/run.rb', line 49 def registry @registry end |
Class Method Details
.default_jobs ⇒ Object
Define the default set of jobs. Note that the states of :queued of :finished need to exist for all job arrays.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/openstudio/workflow/run.rb', line 55 def self.default_jobs [ { state: :queued, next_state: :initialization, options: { initial: true } }, { state: :initialization, next_state: :os_measures, job: :RunInitialization, file: 'openstudio/workflow/jobs/run_initialization', options: {} }, { state: :os_measures, next_state: :translator, job: :RunOpenStudioMeasures, file: 'openstudio/workflow/jobs/run_os_measures.rb', options: {} }, { state: :translator, next_state: :ep_measures, job: :RunTranslation, file: 'openstudio/workflow/jobs/run_translation.rb', options: {} }, { state: :ep_measures, next_state: :preprocess, job: :RunEnergyPlusMeasures, file: 'openstudio/workflow/jobs/run_ep_measures.rb', options: {} }, { state: :preprocess, next_state: :simulation, job: :RunPreprocess, file: 'openstudio/workflow/jobs/run_preprocess.rb', options: {} }, { state: :simulation, next_state: :reporting_measures, job: :RunEnergyPlus, file: 'openstudio/workflow/jobs/run_energyplus.rb', options: {} }, { state: :reporting_measures, next_state: :postprocess, job: :RunReportingMeasures, file: 'openstudio/workflow/jobs/run_reporting_measures.rb', options: {} }, { state: :postprocess, next_state: :finished, job: :RunPostprocess, file: 'openstudio/workflow/jobs/run_postprocess.rb', options: {} }, { state: :finished }, { state: :errored } ] end |
Instance Method Details
#run ⇒ Object
add a catch if any job fails
make a block method to provide feedback
execute the workflow defined in the state object
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/openstudio/workflow/run.rb', line 227 def run @logger.info "Starting workflow in #{@registry[:run_dir]}" begin next_state while @current_state != :finished && @current_state != :errored # sleep 2 step end if ![:fast] @logger.info 'Finished workflow - communicating results and zipping files' @output_adapter.communicate_results(@registry[:run_dir], @registry[:results], [:skip_zip_results]) end rescue StandardError => e @logger.info "Error occurred during running with #{e.message}" ensure @logger.info 'Workflow complete' # If we let the :reporting_measures step fail to continue with # postprocess, we still want to report and error if != '' @current_state = :errored end if @current_state == :errored @registry[:workflow_json]&.setCompletedStatus('Fail') else # completed status will already be set if workflow was halted if @registry[:workflow_json].completedStatus.empty? @registry[:workflow_json].setCompletedStatus('Success') else @current_state = :errored if @registry[:workflow_json].completedStatus.get == 'Fail' end end # save all files before calling output adapter @registry[:log_targets].each(&:flush) # save workflow with results if @registry[:workflow_json] && ![:fast] out_path = @registry[:workflow_json].absoluteOutPath @registry[:workflow_json].saveAs(out_path) end # Write out the TimeLogger to the filesystem @registry[:time_logger]&.save(File.join(@registry[:run_dir], 'profile.json')) if @current_state == :errored @output_adapter.communicate_failure else @output_adapter.communicate_complete end end @current_state end |
#run_finished(_, _, _) ⇒ Object
Return the finished state and exit
325 326 327 328 329 |
# File 'lib/openstudio/workflow/run.rb', line 325 def run_finished(_, _, _) logger.info "Running #{__method__}" @current_state end |
#step ⇒ Object
Step through the states, if there is an error (e.g. exception) then go to error
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/openstudio/workflow/run.rb', line 286 def step step_instance = @jobs.find { |h| h[:state] == @current_state } require step_instance[:file] klass = OpenStudio::Workflow.new_class(step_instance[:job], @input_adapter, @output_adapter, @registry, ) @output_adapter.communicate_transition("Starting state #{@current_state}", :state) state_return = klass.perform if state_return @output_adapter.communicate_transition("Returned from state #{@current_state} with message #{state_return}", :state) else @output_adapter.communicate_transition("Returned from state #{@current_state}", :state) end next_state rescue StandardError => e step_error("#{e.message}:#{e.backtrace.join("\n")}") end |
#step_error(*args) ⇒ Object
Error handling for when there is an exception running any of the state transitions
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/openstudio/workflow/run.rb', line 304 def step_error(*args) # Make sure to set the instance variable @error to true in order to stop the :step # event from being fired. # Allow continuing anyways if it fails in reporting measures if @current_state == :reporting_measures = "Found error in state '#{@current_state}' with message #{args}}" @logger.error next_state else = "Found error in state '#{@current_state}' with message #{args}}" @logger.error # transition to an error state @current_state = :errored end end |