Class: OpenStudio::Workflow::Run

Inherits:
Object
  • Object
show all
Includes:
AASM
Defined in:
lib/openstudio/workflow/run.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(adapter, directory, options = {}) ⇒ Run

initialize a new run class

Parameters:

  • adapter

    an instance of the adapter class

  • directory

    location of the datapoint directory to run. This is needed independent of the adapter that is being used. Note that the simulation will actually run in ‘run’



96
97
98
99
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
# File 'lib/openstudio/workflow/run.rb', line 96

def initialize(adapter, directory, options = {})
  @adapter = adapter
  @directory = directory
  # TODO: run directory is a convention right now. Move to a configuration item
  @run_directory = "#{@directory}/run"

  defaults = nil
  if options[:is_pat]
    defaults = {
      transitions: OpenStudio::Workflow::Run.pat_transition,
      states: OpenStudio::Workflow::Run.pat_states,
      jobs: {}
    }
  else
    defaults = {
      transitions: OpenStudio::Workflow::Run.default_transition,
      states: OpenStudio::Workflow::Run.default_states,
      jobs: {}
    }
  end
  @options = defaults.merge(options)

  @error = false

  @job_results = {}

  # By default blow away the entire run directory every time and recreate it
  FileUtils.rm_rf(@run_directory) if File.exist?(@run_directory)
  FileUtils.mkdir_p(@run_directory)

  # There is a namespace conflict when OpenStudio is loaded: be careful!
  log_file = File.open("#{@run_directory}/run.log", 'a')

  l = @adapter.get_logger @directory, @options
  if l
    @logger = ::Logger.new MultiDelegator.delegate(:write, :close).to(STDOUT, log_file, l)
  else
    @logger = ::Logger.new MultiDelegator.delegate(:write, :close).to(STDOUT, log_file)
  end

  @logger.info "Initializing directory #{@directory} for simulation with options #{@options}"
  @logger.info "OpenStudio loaded: '#{$openstudio_gem}'"

  super()

  # load the state machine
  machine
end

Instance Attribute Details

#adapterObject (readonly)

Returns the value of attribute adapter.



29
30
31
# File 'lib/openstudio/workflow/run.rb', line 29

def adapter
  @adapter
end

#directoryObject (readonly)

Returns the value of attribute directory.



30
31
32
# File 'lib/openstudio/workflow/run.rb', line 30

def directory
  @directory
end

#final_stateObject (readonly)

Returns the value of attribute final_state.



32
33
34
# File 'lib/openstudio/workflow/run.rb', line 32

def final_state
  @final_state
end

#job_resultsObject (readonly)

Returns the value of attribute job_results.



33
34
35
# File 'lib/openstudio/workflow/run.rb', line 33

def job_results
  @job_results
end

#loggerObject

Returns the value of attribute logger.



26
27
28
# File 'lib/openstudio/workflow/run.rb', line 26

def logger
  @logger
end

#optionsObject (readonly)

Returns the value of attribute options.



28
29
30
# File 'lib/openstudio/workflow/run.rb', line 28

def options
  @options
end

#run_directoryObject (readonly)

Returns the value of attribute run_directory.



31
32
33
# File 'lib/openstudio/workflow/run.rb', line 31

def run_directory
  @run_directory
end

Class Method Details

.default_statesObject

The default states for the workflow. Note that the states of :queued of :finished need to exist for all cases.



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/openstudio/workflow/run.rb', line 53

def self.default_states
  # TODO: replace this with some sort of dynamic store
  [
    { state: :queued, options: { initial: true } },
    { state: :preflight, options: { after_enter: :run_preflight } },
    { state: :openstudio, options: { after_enter: :run_openstudio } }, # TODO: this should be run_openstudio_measures and run_energyplus_measures
    { state: :energyplus, options: { after_enter: :run_energyplus } },
    { state: :reporting_measures, options: { after_enter: :run_reporting_measures } },
    { state: :postprocess, options: { after_enter: :run_postprocess } },
    { state: :finished },
    { state: :errored }
  ]
end

.default_transitionObject

load the transitions



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/openstudio/workflow/run.rb', line 39

def self.default_transition
  # TODO: replace these with dynamic states from a config file of some sort
  [
    { from: :queued, to: :preflight },
    { from: :preflight, to: :openstudio },
    { from: :openstudio, to: :energyplus },
    { from: :energyplus, to: :reporting_measures },
    { from: :reporting_measures, to: :postprocess },
    { from: :postprocess, to: :finished }
  ]
end

.pat_statesObject

states for pat job



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/openstudio/workflow/run.rb', line 79

def self.pat_states
  # TODO: replace this with some sort of dynamic store
  [
    { state: :queued, options: { initial: true } },
    { state: :preflight, options: { after_enter: :run_preflight } },
    { state: :runmanager, options: { after_enter: :run_runmanager } },
    { state: :postprocess, options: { after_enter: :run_postprocess } },
    { state: :finished },
    { state: :errored }
  ]
end

.pat_transitionObject

transitions for pat job



68
69
70
71
72
73
74
75
76
# File 'lib/openstudio/workflow/run.rb', line 68

def self.pat_transition
  # TODO: replace these with dynamic states from a config file of some sort
  [
    { from: :queued, to: :preflight },
    { from: :preflight, to: :runmanager },
    { from: :runmanager, to: :postprocess },
    { from: :postprocess, to: :finished }
  ]
end

Instance Method Details

#runObject

run the simulations. TODO: add a catch if any job fails; TODO: make a block method to provide feedback



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
# File 'lib/openstudio/workflow/run.rb', line 147

def run
  @logger.info "Starting workflow in #{@directory}"
  begin
    while state.current_state != :finished && !@error
      step
    end

    @logger.info 'Finished workflow - communicating results and zipping files'

    # TODO: this should be a job that handles the use case with a :guard on if @job_results[:run_postprocess]
    # or @job_results[:run_reporting_measures]
    # these are the results that need to be sent back to adapter
    if @job_results[:run_runmanager]
      @logger.info 'Sending the run_runmananger results back to the adapter'
      @adapter.communicate_results @directory, @job_results[:run_runmanager]
    elsif @job_results[:run_reporting_measures]
      @logger.info 'Sending the reporting measuers results back to the adapter'
      @adapter.communicate_results @directory, @job_results[:run_reporting_measures]
    end
  ensure
    if @error
      @adapter.communicate_failure @directory
    else
      @adapter.communicate_complete @directory
    end

    @logger.info 'Workflow complete'

    # TODO: define the outputs and figure out how to show it correctory
    obj_function_array ||= ['NA']

    # Print the objective functions to the screen even though the file is being used right now
    # Note as well that we can't guarantee that the csv format will be in the right order
    puts obj_function_array.join(',')
  end

  state.current_state
end

#run_energyplusObject

TODO: these methods needs to be dynamic or inherited run energplus



199
200
201
202
203
204
# File 'lib/openstudio/workflow/run.rb', line 199

def run_energyplus
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  @job_results[__method__.to_sym] = klass.perform
end

#run_openstudioObject

run openstudio to create the model and apply the measures



207
208
209
210
211
212
213
# File 'lib/openstudio/workflow/run.rb', line 207

def run_openstudio
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  # TODO: save the resulting filenames to an array
  @job_results[__method__.to_sym] = klass.perform
end

#run_postprocessObject



233
234
235
236
237
238
# File 'lib/openstudio/workflow/run.rb', line 233

def run_postprocess
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  @job_results[__method__.to_sym] = klass.perform
end

#run_preflightObject

preconfigured run method for preflight. This configures the input directories and sets everything up for running the simulations.



242
243
244
245
246
247
# File 'lib/openstudio/workflow/run.rb', line 242

def run_preflight
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  @job_results[__method__.to_sym] = klass.perform
end

#run_reporting_measuresObject

run reporting measures



225
226
227
228
229
230
231
# File 'lib/openstudio/workflow/run.rb', line 225

def run_reporting_measures
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  # TODO: save the resulting filenames to an array
  @job_results[__method__.to_sym] = klass.perform
end

#run_runmanagerObject

run a pat file using runmanager



216
217
218
219
220
221
222
# File 'lib/openstudio/workflow/run.rb', line 216

def run_runmanager
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  # TODO: save the resulting filenames to an array
  @job_results[__method__.to_sym] = klass.perform
end

#run_xmlObject



249
250
251
252
253
254
255
# File 'lib/openstudio/workflow/run.rb', line 249

def run_xml
  @logger.info "Running #{__method__}"
  klass = get_run_class(__method__)

  @job_results[__method__.to_sym] = klass.perform
  @logger.info @job_results
end

#step_error(*args) ⇒ Object

call back for when there is an exception running any of the state transitions



187
188
189
190
191
192
193
194
195
# File 'lib/openstudio/workflow/run.rb', line 187

def step_error(*args)
  # Make sure to set the instance variable @error to true in order to stop the :step
  # event from being fired.
  @error = true
  @logger.error "Found error in state '#{aasm.current_state}' with message #{args}}"

  # Call the error_out event to transition to the :errored state
  error_out
end