openstudio-workflow 1.3.3 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -72
  3. data/README.md +93 -93
  4. data/Rakefile +36 -36
  5. data/lib/openstudio-workflow.rb +65 -49
  6. data/lib/openstudio/workflow/adapters/input/local.rb +324 -301
  7. data/lib/openstudio/workflow/adapters/output/local.rb +161 -97
  8. data/lib/openstudio/workflow/adapters/output/socket.rb +107 -91
  9. data/lib/openstudio/workflow/adapters/output/web.rb +82 -66
  10. data/lib/openstudio/workflow/adapters/output_adapter.rb +163 -147
  11. data/lib/openstudio/workflow/job.rb +57 -22
  12. data/lib/openstudio/workflow/jobs/resources/monthly_report.idf +222 -222
  13. data/lib/openstudio/workflow/jobs/run_energyplus.rb +70 -54
  14. data/lib/openstudio/workflow/jobs/run_ep_measures.rb +73 -57
  15. data/lib/openstudio/workflow/jobs/run_initialization.rb +203 -171
  16. data/lib/openstudio/workflow/jobs/run_os_measures.rb +89 -73
  17. data/lib/openstudio/workflow/jobs/run_postprocess.rb +73 -57
  18. data/lib/openstudio/workflow/jobs/run_preprocess.rb +104 -80
  19. data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +118 -102
  20. data/lib/openstudio/workflow/jobs/run_translation.rb +84 -68
  21. data/lib/openstudio/workflow/multi_delegator.rb +62 -46
  22. data/lib/openstudio/workflow/registry.rb +172 -137
  23. data/lib/openstudio/workflow/run.rb +328 -312
  24. data/lib/openstudio/workflow/time_logger.rb +96 -53
  25. data/lib/openstudio/workflow/util.rb +49 -14
  26. data/lib/openstudio/workflow/util/energyplus.rb +605 -570
  27. data/lib/openstudio/workflow/util/io.rb +68 -33
  28. data/lib/openstudio/workflow/util/measure.rb +650 -615
  29. data/lib/openstudio/workflow/util/model.rb +151 -100
  30. data/lib/openstudio/workflow/util/post_process.rb +238 -187
  31. data/lib/openstudio/workflow/util/weather_file.rb +143 -108
  32. data/lib/openstudio/workflow/version.rb +40 -24
  33. data/lib/openstudio/workflow_json.rb +476 -443
  34. data/lib/openstudio/workflow_runner.rb +268 -252
  35. metadata +23 -23
@@ -1,301 +1,324 @@
1
- ######################################################################
2
- # Copyright (c) 2008-2014, Alliance for Sustainable Energy.
3
- # All rights reserved.
4
- #
5
- # This library is free software; you can redistribute it and/or
6
- # modify it under the terms of the GNU Lesser General Public
7
- # License as published by the Free Software Foundation; either
8
- # version 2.1 of the License, or (at your option) any later version.
9
- #
10
- # This library is distributed in the hope that it will be useful,
11
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- # Lesser General Public License for more details.
14
- #
15
- # You should have received a copy of the GNU Lesser General Public
16
- # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
- ######################################################################
19
-
20
- require 'openstudio/workflow_json'
21
-
22
- # Local file based workflow
23
- module OpenStudio
24
- module Workflow
25
- module InputAdapter
26
- class Local
27
- def initialize(osw_path = './workflow.osw')
28
- @osw_abs_path = File.absolute_path(osw_path, Dir.pwd)
29
-
30
- @workflow = nil
31
- if File.exist? @osw_abs_path
32
- @workflow = ::JSON.parse(File.read(@osw_abs_path), symbolize_names: true)
33
- end
34
-
35
- @workflow_json = nil
36
- @run_options = nil
37
- if @workflow
38
- begin
39
- # Create a temporary WorkflowJSON, will not be same one used in registry during simulation
40
- @workflow_json = OpenStudio::WorkflowJSON.new(JSON.fast_generate(workflow))
41
- @workflow_json.setOswDir(osw_dir)
42
- rescue NameError => e
43
- @workflow_json = WorkflowJSON_Shim.new(workflow, osw_dir)
44
- end
45
-
46
- begin
47
- @run_options = @workflow_json.runOptions
48
- rescue
49
- end
50
- end
51
- end
52
-
53
- # Get the OSW file from the local filesystem
54
- #
55
- def workflow
56
- raise "Could not read workflow from #{@osw_abs_path}" if @workflow.nil?
57
- @workflow
58
- end
59
-
60
- # Get the OSW path
61
- #
62
- def osw_path
63
- @osw_abs_path
64
- end
65
-
66
- # Get the OSW dir
67
- #
68
- def osw_dir
69
- File.dirname(@osw_abs_path)
70
- end
71
-
72
- # Get the run dir
73
- #
74
- def run_dir
75
- result = File.join(osw_dir, 'run')
76
- if @workflow_json
77
- begin
78
- result = @workflow_json.absoluteRunDir.to_s
79
- rescue
80
- end
81
- end
82
- result
83
- end
84
-
85
- def output_adapter(user_options, default, logger)
86
-
87
- # user option trumps all others
88
- return user_options[:output_adapter] if user_options[:output_adapter]
89
-
90
- # try to read from OSW
91
- if @run_options && !@run_options.empty?
92
- custom_adapter = @run_options.get.customOutputAdapter
93
- if !custom_adapter.empty?
94
- begin
95
- custom_file_name = custom_adapter.get.customFileName
96
- class_name = custom_adapter.get.className
97
- options = ::JSON.parse(custom_adapter.get.options, :symbolize_names => true)
98
-
99
- # merge with user options, user options will replace options loaded from OSW
100
- options.merge!(user_options)
101
-
102
- # stick output_directory in options
103
- options[:output_directory] = run_dir
104
-
105
- p = @workflow_json.findFile(custom_file_name)
106
- if !p.empty?
107
- load(p.get.to_s)
108
- output_adapter = eval("#{class_name}.new(options)")
109
- return output_adapter
110
- else
111
- log_message = "Failed to load custom adapter file '#{custom_file_name}'"
112
- logger.error log_message
113
- raise log_message
114
- end
115
- rescue
116
- log_message = "Failed to load custom adapter '#{class_name}' from file '#{custom_file_name}'"
117
- logger.error log_message
118
- raise log_message
119
- end
120
- end
121
- end
122
-
123
- return default
124
- end
125
-
126
- def jobs(user_options, default, logger)
127
-
128
- # user option trumps all others
129
- return user_options[:jobs] if user_options[:jobs]
130
-
131
- # try to read from OSW
132
- begin
133
- #log_message = "Reading custom job states from OSW is not currently supported'"
134
- #logger.info log_message
135
- rescue
136
- end
137
-
138
- return default
139
- end
140
-
141
- def debug(user_options, default)
142
-
143
- # user option trumps all others
144
- return user_options[:debug] if user_options[:debug]
145
-
146
- # try to read from OSW
147
- if @run_options && !@run_options.empty?
148
- return @run_options.get.debug
149
- end
150
-
151
- return default
152
- end
153
-
154
- def fast(user_options, default)
155
-
156
- # user option trumps all others
157
- return user_options[:fast] if user_options[:fast]
158
-
159
- # try to read from OSW
160
- if @run_options && !@run_options.empty?
161
- if @run_options.get.respond_to?(:fast)
162
- return @run_options.get.fast
163
- else
164
- if @workflow[:run_options]
165
- return @workflow[:run_options][:fast]
166
- end
167
- end
168
- end
169
-
170
- return default
171
- end
172
-
173
- def preserve_run_dir(user_options, default)
174
-
175
- # user option trumps all others
176
- return user_options[:preserve_run_dir] if user_options[:preserve_run_dir]
177
-
178
- # try to read from OSW
179
- if @run_options && !@run_options.empty?
180
- return @run_options.get.preserveRunDir
181
- end
182
-
183
- return default
184
- end
185
-
186
- def skip_expand_objects(user_options, default)
187
-
188
- # user option trumps all others
189
- return user_options[:skip_expand_objects] if user_options[:skip_expand_objects]
190
-
191
- # try to read from OSW
192
- if @run_options && !@run_options.empty?
193
- if @run_options.get.respond_to?(:skipExpandObjects)
194
- return @run_options.get.skipExpandObjects
195
- else
196
- if @workflow[:run_options]
197
- return @workflow[:run_options][:skip_expand_objects]
198
- end
199
- end
200
- end
201
-
202
- return default
203
- end
204
-
205
- def skip_energyplus_preprocess(user_options, default)
206
-
207
- # user option trumps all others
208
- return user_options[:skip_energyplus_preprocess] if user_options[:skip_energyplus_preprocess]
209
-
210
- # try to read from OSW
211
- if @run_options && !@run_options.empty?
212
- if @run_options.get.respond_to?(:skipEnergyPlusPreprocess)
213
- return @run_options.get.skipEnergyPlusPreprocess
214
- else
215
- if @workflow[:run_options]
216
- return @workflow[:run_options][:skip_energyplus_preprocess]
217
- end
218
- end
219
- end
220
-
221
- return default
222
- end
223
-
224
- def cleanup(user_options, default)
225
-
226
- # user option trumps all others
227
- return user_options[:cleanup] if user_options[:cleanup]
228
-
229
- # try to read from OSW
230
- if @run_options && !@run_options.empty?
231
- return @run_options.get.cleanup
232
- end
233
-
234
- return default
235
- end
236
-
237
- def energyplus_path(user_options, default)
238
-
239
- # user option trumps all others
240
- return user_options[:energyplus_path] if user_options[:energyplus_path]
241
-
242
- return default
243
- end
244
-
245
- def profile(user_options, default)
246
-
247
- # user option trumps all others
248
- return user_options[:profile] if user_options[:profile]
249
-
250
- return default
251
- end
252
-
253
- def verify_osw(user_options, default)
254
-
255
- # user option trumps all others
256
- return user_options[:verify_osw] if user_options[:verify_osw]
257
-
258
- return default
259
- end
260
-
261
- def weather_file(user_options, default)
262
-
263
- # user option trumps all others
264
- return user_options[:weather_file] if user_options[:weather_file]
265
-
266
- # try to read from OSW
267
- if !@workflow_json.weatherFile.empty?
268
- return @workflow_json.weatherFile.get.to_s
269
- end
270
-
271
- return default
272
- end
273
-
274
- # Get the associated OSD (datapoint) file from the local filesystem
275
- #
276
- def datapoint
277
- # DLM: should this come from the OSW? the osd id and checksum are specified there.
278
- osd_abs_path = File.join(osw_dir, 'datapoint.osd')
279
- result = nil
280
- if File.exist? osd_abs_path
281
- result = ::JSON.parse(File.read(osd_abs_path), symbolize_names: true)
282
- end
283
- return result
284
- end
285
-
286
- # Get the associated OSA (analysis) definition from the local filesystem
287
- #
288
- def analysis
289
- # DLM: should this come from the OSW? the osd id and checksum are specified there.
290
- osa_abs_path = File.join(osw_dir, '../analysis.json')
291
- result = nil
292
- if File.exist? osa_abs_path
293
- result = ::JSON.parse(File.read(osa_abs_path), symbolize_names: true)
294
- end
295
- return result
296
- end
297
-
298
- end
299
- end
300
- end
301
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2018, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
+ # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
36
+ require 'openstudio/workflow_json'
37
+
38
+ # Local file based workflow
39
+ module OpenStudio
40
+ module Workflow
41
+ module InputAdapter
42
+ class Local
43
+ def initialize(osw_path = './workflow.osw')
44
+ @osw_abs_path = File.absolute_path(osw_path, Dir.pwd)
45
+
46
+ @workflow = nil
47
+ if File.exist? @osw_abs_path
48
+ @workflow = ::JSON.parse(File.read(@osw_abs_path), symbolize_names: true)
49
+ end
50
+
51
+ begin
52
+ # configure the OSW with paths for loaded extension gems
53
+ # Bundler.require is called in the CLI to load extension gems
54
+ @workflow = OpenStudio::Extension::configure_osw(@workflow)
55
+ rescue NameError => e
56
+ end
57
+
58
+ @workflow_json = nil
59
+ @run_options = nil
60
+ if @workflow
61
+ begin
62
+ # Create a temporary WorkflowJSON, will not be same one used in registry during simulation
63
+ @workflow_json = OpenStudio::WorkflowJSON.new(JSON.fast_generate(workflow))
64
+ @workflow_json.setOswDir(osw_dir)
65
+ rescue NameError => e
66
+ @workflow_json = WorkflowJSON_Shim.new(workflow, osw_dir)
67
+ end
68
+
69
+ begin
70
+ @run_options = @workflow_json.runOptions
71
+ rescue
72
+ end
73
+ end
74
+ end
75
+
76
+ # Get the OSW file from the local filesystem
77
+ #
78
+ def workflow
79
+ raise "Could not read workflow from #{@osw_abs_path}" if @workflow.nil?
80
+ @workflow
81
+ end
82
+
83
+ # Get the OSW path
84
+ #
85
+ def osw_path
86
+ @osw_abs_path
87
+ end
88
+
89
+ # Get the OSW dir
90
+ #
91
+ def osw_dir
92
+ File.dirname(@osw_abs_path)
93
+ end
94
+
95
+ # Get the run dir
96
+ #
97
+ def run_dir
98
+ result = File.join(osw_dir, 'run')
99
+ if @workflow_json
100
+ begin
101
+ result = @workflow_json.absoluteRunDir.to_s
102
+ rescue
103
+ end
104
+ end
105
+ result
106
+ end
107
+
108
+ def output_adapter(user_options, default, logger)
109
+
110
+ # user option trumps all others
111
+ return user_options[:output_adapter] if user_options[:output_adapter]
112
+
113
+ # try to read from OSW
114
+ if @run_options && !@run_options.empty?
115
+ custom_adapter = @run_options.get.customOutputAdapter
116
+ if !custom_adapter.empty?
117
+ begin
118
+ custom_file_name = custom_adapter.get.customFileName
119
+ class_name = custom_adapter.get.className
120
+ options = ::JSON.parse(custom_adapter.get.options, :symbolize_names => true)
121
+
122
+ # merge with user options, user options will replace options loaded from OSW
123
+ options.merge!(user_options)
124
+
125
+ # stick output_directory in options
126
+ options[:output_directory] = run_dir
127
+
128
+ p = @workflow_json.findFile(custom_file_name)
129
+ if !p.empty?
130
+ load(p.get.to_s)
131
+ output_adapter = eval("#{class_name}.new(options)")
132
+ return output_adapter
133
+ else
134
+ log_message = "Failed to load custom adapter file '#{custom_file_name}'"
135
+ logger.error log_message
136
+ raise log_message
137
+ end
138
+ rescue
139
+ log_message = "Failed to load custom adapter '#{class_name}' from file '#{custom_file_name}'"
140
+ logger.error log_message
141
+ raise log_message
142
+ end
143
+ end
144
+ end
145
+
146
+ return default
147
+ end
148
+
149
+ def jobs(user_options, default, logger)
150
+
151
+ # user option trumps all others
152
+ return user_options[:jobs] if user_options[:jobs]
153
+
154
+ # try to read from OSW
155
+ begin
156
+ #log_message = "Reading custom job states from OSW is not currently supported'"
157
+ #logger.info log_message
158
+ rescue
159
+ end
160
+
161
+ return default
162
+ end
163
+
164
+ def debug(user_options, default)
165
+
166
+ # user option trumps all others
167
+ return user_options[:debug] if user_options[:debug]
168
+
169
+ # try to read from OSW
170
+ if @run_options && !@run_options.empty?
171
+ return @run_options.get.debug
172
+ end
173
+
174
+ return default
175
+ end
176
+
177
+ def fast(user_options, default)
178
+
179
+ # user option trumps all others
180
+ return user_options[:fast] if user_options[:fast]
181
+
182
+ # try to read from OSW
183
+ if @run_options && !@run_options.empty?
184
+ if @run_options.get.respond_to?(:fast)
185
+ return @run_options.get.fast
186
+ else
187
+ if @workflow[:run_options]
188
+ return @workflow[:run_options][:fast]
189
+ end
190
+ end
191
+ end
192
+
193
+ return default
194
+ end
195
+
196
+ def preserve_run_dir(user_options, default)
197
+
198
+ # user option trumps all others
199
+ return user_options[:preserve_run_dir] if user_options[:preserve_run_dir]
200
+
201
+ # try to read from OSW
202
+ if @run_options && !@run_options.empty?
203
+ return @run_options.get.preserveRunDir
204
+ end
205
+
206
+ return default
207
+ end
208
+
209
+ def skip_expand_objects(user_options, default)
210
+
211
+ # user option trumps all others
212
+ return user_options[:skip_expand_objects] if user_options[:skip_expand_objects]
213
+
214
+ # try to read from OSW
215
+ if @run_options && !@run_options.empty?
216
+ if @run_options.get.respond_to?(:skipExpandObjects)
217
+ return @run_options.get.skipExpandObjects
218
+ else
219
+ if @workflow[:run_options]
220
+ return @workflow[:run_options][:skip_expand_objects]
221
+ end
222
+ end
223
+ end
224
+
225
+ return default
226
+ end
227
+
228
+ def skip_energyplus_preprocess(user_options, default)
229
+
230
+ # user option trumps all others
231
+ return user_options[:skip_energyplus_preprocess] if user_options[:skip_energyplus_preprocess]
232
+
233
+ # try to read from OSW
234
+ if @run_options && !@run_options.empty?
235
+ if @run_options.get.respond_to?(:skipEnergyPlusPreprocess)
236
+ return @run_options.get.skipEnergyPlusPreprocess
237
+ else
238
+ if @workflow[:run_options]
239
+ return @workflow[:run_options][:skip_energyplus_preprocess]
240
+ end
241
+ end
242
+ end
243
+
244
+ return default
245
+ end
246
+
247
+ def cleanup(user_options, default)
248
+
249
+ # user option trumps all others
250
+ return user_options[:cleanup] if user_options[:cleanup]
251
+
252
+ # try to read from OSW
253
+ if @run_options && !@run_options.empty?
254
+ return @run_options.get.cleanup
255
+ end
256
+
257
+ return default
258
+ end
259
+
260
+ def energyplus_path(user_options, default)
261
+
262
+ # user option trumps all others
263
+ return user_options[:energyplus_path] if user_options[:energyplus_path]
264
+
265
+ return default
266
+ end
267
+
268
+ def profile(user_options, default)
269
+
270
+ # user option trumps all others
271
+ return user_options[:profile] if user_options[:profile]
272
+
273
+ return default
274
+ end
275
+
276
+ def verify_osw(user_options, default)
277
+
278
+ # user option trumps all others
279
+ return user_options[:verify_osw] if user_options[:verify_osw]
280
+
281
+ return default
282
+ end
283
+
284
+ def weather_file(user_options, default)
285
+
286
+ # user option trumps all others
287
+ return user_options[:weather_file] if user_options[:weather_file]
288
+
289
+ # try to read from OSW
290
+ if !@workflow_json.weatherFile.empty?
291
+ return @workflow_json.weatherFile.get.to_s
292
+ end
293
+
294
+ return default
295
+ end
296
+
297
+ # Get the associated OSD (datapoint) file from the local filesystem
298
+ #
299
+ def datapoint
300
+ # DLM: should this come from the OSW? the osd id and checksum are specified there.
301
+ osd_abs_path = File.join(osw_dir, 'datapoint.osd')
302
+ result = nil
303
+ if File.exist? osd_abs_path
304
+ result = ::JSON.parse(File.read(osd_abs_path), symbolize_names: true)
305
+ end
306
+ return result
307
+ end
308
+
309
+ # Get the associated OSA (analysis) definition from the local filesystem
310
+ #
311
+ def analysis
312
+ # DLM: should this come from the OSW? the osd id and checksum are specified there.
313
+ osa_abs_path = File.join(osw_dir, '../analysis.json')
314
+ result = nil
315
+ if File.exist? osa_abs_path
316
+ result = ::JSON.parse(File.read(osa_abs_path), symbolize_names: true)
317
+ end
318
+ return result
319
+ end
320
+
321
+ end
322
+ end
323
+ end
324
+ end