openstudio-workflow 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +39 -2
  4. data/Rakefile +12 -1
  5. data/lib/openstudio-workflow.rb +31 -4
  6. data/lib/openstudio/workflow/adapter.rb +8 -9
  7. data/lib/openstudio/workflow/adapters/local.rb +35 -22
  8. data/lib/openstudio/workflow/adapters/mongo.rb +82 -92
  9. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +229 -0
  10. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +7 -10
  11. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +37 -159
  12. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +53 -492
  13. data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +1 -5
  14. data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/README.md +0 -0
  15. data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.rb +81 -87
  16. data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.xml +1 -1
  17. data/lib/openstudio/workflow/jobs/{run_postprocess/packaged_measures/StandardReports/resources/report.html.in → run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb} +0 -0
  18. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +548 -0
  19. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +226 -0
  20. data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +39 -41
  21. data/lib/openstudio/workflow/multi_delegator.rb +6 -6
  22. data/lib/openstudio/workflow/run.rb +95 -39
  23. data/lib/openstudio/workflow/version.rb +1 -1
  24. metadata +9 -6
@@ -21,7 +21,11 @@
21
21
  # TODO: I hear that measures can step on each other if not run in their own directory
22
22
 
23
23
  require 'csv'
24
+ require 'ostruct'
25
+
24
26
  class RunPostprocess
27
+ # Mixin the MeasureApplication module to apply measures
28
+ include OpenStudio::Workflow::ApplyMeasures
25
29
 
26
30
  def initialize(directory, logger, adapter, options = {})
27
31
  defaults = {}
@@ -31,519 +35,76 @@ class RunPostprocess
31
35
  @adapter = adapter
32
36
  @logger = logger
33
37
  @results = {}
34
-
35
- # TODO: we shouldn't have to keep loading this file if we need it. It should be availabe for any job.
36
- # TODO: passing in the options everytime is ridiculuous
37
- @analysis_json = @adapter.get_problem(@directory, @options)
38
+ @output_attributes = {}
38
39
 
39
40
  @logger.info "#{self.class} passed the following options #{@options}"
40
-
41
- @model = load_model @options[:run_openstudio][:osm]
42
- # TODO: should read the name of the sql output file via the :run_openstudio options hash
43
- @sql_filename = "#{@run_directory}/eplusout.sql"
44
- fail "EnergyPlus SQL file did not exist #{@sql_filename}" unless File.exist? @sql_filename
45
-
46
- @objective_functions = {}
47
41
  end
48
42
 
49
43
  def perform
50
44
  @logger.info "Calling #{__method__} in the #{self.class} class"
45
+ @logger.info 'RunPostProcess Retrieving datapoint and problem'
51
46
 
52
- if @options[:use_monthly_reports]
53
- run_monthly_postprocess
54
- else
55
- run_standard_postprocess
47
+ begin
48
+ cleanup
49
+ rescue => e
50
+ log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
51
+ @logger.error log_message
52
+ # raise log_message
56
53
  end
57
54
 
58
- translate_csv_to_json
59
-
60
- run_packaged_measures
61
-
62
- run_extract_inputs_and_outputs
63
-
64
- cleanup
65
-
66
55
  @results
67
56
  end
68
57
 
69
58
  def cleanup
70
- # TODO: use Dir glob instead of pathname
71
- require 'pathname'
72
- require 'fileutils'
59
+ # move any of the reporting file to the 'reports' directory for serverside access
60
+ eplus_search_path = nil
61
+ FileUtils.mkdir_p "#{@directory}/reports"
62
+
63
+ # try to find the energyplus result file
64
+ eplus_html = "#{@run_directory}/eplustbl.htm"
65
+ unless File.exist? eplus_html
66
+ eplus_html = Dir["#{@directory}/*EnergyPlus*/eplustbl.htm"].last || nil
67
+ end
68
+
69
+ if eplus_html
70
+ if File.exist? eplus_html
71
+ # do some encoding on the html if possible
72
+ html = File.read(eplus_html)
73
+ html = html.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
74
+ File.open("#{@directory}/reports/eplustbl.html", 'w') { |f| f << html }
75
+ end
76
+ end
77
+
78
+ # Also, find any "report.html" files
79
+ Dir["#{@run_directory}/*/report*.*"].each do |report|
80
+ # get the parent directory of the file and snake case it
81
+ # do i need to force encoding on this as well?
82
+ measure_class_name = File.basename(File.dirname(report)).snake_case
83
+ file_ext = File.extname(report)
84
+ append_str = File.basename(report, '.*').gsub('report', '')
85
+ new_file_name = "#{@directory}/reports/#{measure_class_name}#{append_str}#{file_ext}"
86
+ FileUtils.copy report, new_file_name
87
+ end
88
+
89
+ # Remove empty directories in run folder
90
+ Dir["#{@run_directory}/*"].select { |d| File.directory? d }.select { |d| (Dir.entries(d) - %w(. ..)).empty? }.each { |d| Dir.rmdir d }
91
+
73
92
  paths_to_rm = []
74
- #paths_to_rm << Pathname.glob("#{@run_directory}/*.osm")
93
+ # paths_to_rm << Pathname.glob("#{@run_directory}/*.osm")
94
+ # paths_to_rm << Pathname.glob("#{@run_directory}/*.idf") # keep the idfs
95
+ # paths_to_rm << Pathname.glob("*.audit")
96
+ # paths_to_rm << Pathname.glob("*.bnd")
75
97
  paths_to_rm << Pathname.glob("#{@run_directory}/*.ini")
76
- paths_to_rm << Pathname.glob("#{@run_directory}/*.idf")
77
- paths_to_rm << Pathname.glob("#{@run_directory}/ExpandObjects")
78
- paths_to_rm << Pathname.glob("#{@run_directory}/EnergyPlus")
98
+ paths_to_rm << Pathname.glob("#{@run_directory}/*.eso")
99
+ paths_to_rm << Pathname.glob("#{@run_directory}/*.mtr")
79
100
  paths_to_rm << Pathname.glob("#{@run_directory}/*.so")
80
101
  paths_to_rm << Pathname.glob("#{@run_directory}/*.epw")
81
102
  paths_to_rm << Pathname.glob("#{@run_directory}/*.idd")
82
- # paths_to_rm << Pathname.glob("*.audit")
83
- # paths_to_rm << Pathname.glob("*.bnd")
84
103
  paths_to_rm << Pathname.glob("#{@run_directory}/*.mtd")
85
104
  paths_to_rm << Pathname.glob("#{@run_directory}/*.rdd")
105
+ paths_to_rm << Pathname.glob("#{@run_directory}/ExpandObjects")
106
+ paths_to_rm << Pathname.glob("#{@run_directory}/EnergyPlus")
86
107
  paths_to_rm << Pathname.glob("#{@run_directory}/packaged_measures")
87
108
  paths_to_rm.each { |p| FileUtils.rm_rf(p) }
88
109
  end
89
-
90
- def run_extract_inputs_and_outputs
91
- # For xml, the measure attributes are in the measure_attributes_xml.json file
92
- if File.exist?("#{@run_directory}/measure_attributes_xml.json")
93
- temp_json = JSON.parse(File.read("#{@run_directory}/measure_attributes_xml.json"), symbolize_names: true)
94
- @results.merge!(temp_json)
95
- end
96
-
97
- # Inputs are in the measure_attributes.json file
98
- if File.exist?("#{@run_directory}/measure_attributes.json")
99
- temp_json = JSON.parse(File.read("#{@run_directory}/measure_attributes.json"), symbolize_names: true)
100
- @results.merge!(temp_json)
101
- end
102
-
103
- if File.exist?("#{@run_directory}/standard_report.json")
104
- @results[:standard_report] = JSON.parse(File.read("#{@run_directory}/standard_report.json"), symbolize_names: true)
105
- end
106
-
107
- # Initialize the objective function variable
108
- @objective_functions = {}
109
- if File.exist?("#{@run_directory}/standard_report_legacy.json")
110
- @results[:standard_report_legacy] = JSON.parse(File.read("#{@run_directory}/standard_report_legacy.json"), symbolize_names: true)
111
- @logger.info "Analysis JSON Output Variables are: #{@analysis_json[:analysis][:output_variables]}"
112
- # Save the objective functions to the object for sending back to the simulation executive
113
- @analysis_json[:analysis][:output_variables].each do |variable|
114
- # determine which ones are the objective functions (code smell: todo: use enumerator)
115
- if variable[:objective_function]
116
- @logger.info "Found objective function for #{variable[:name]}"
117
- if @results[:standard_report_legacy][variable[:name].to_sym]
118
- @objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = @results[:standard_report_legacy][variable[:name].to_sym]
119
- if variable[:objective_function_target]
120
- @logger.info "Found objective function target for #{variable[:name]}"
121
- @objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_target].to_f
122
- end
123
- if variable[:scaling_factor]
124
- @logger.info "Found scaling factor for #{variable[:name]}"
125
- @objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = variable[:scaling_factor].to_f
126
- end
127
- if variable['objective_function_group']
128
- @logger.info "Found objective function group for #{variable[:name]}"
129
- @objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_group].to_f
130
- end
131
- else
132
- # objective_functions[variable['name']] = nil
133
- @objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = Float::MAX
134
- @objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = nil
135
- @objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = nil
136
- @objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = nil
137
- end
138
- end
139
- end
140
- end
141
- end
142
-
143
- private
144
-
145
- # Load in the OpenStudio model. It is required for postprocessing
146
- def load_model(filename)
147
- model = nil
148
- @logger.info 'Loading model'
149
-
150
- # TODO: wrap this in an exception block and fail as appropriate
151
- # assume that the seed model has been placed in the directory
152
- if File.exist? filename
153
- @logger.info "Reading in model #{filename}"
154
- translator = OpenStudio::OSVersion::VersionTranslator.new
155
- model = translator.loadModel(filename)
156
- fail 'OpenStudio model is empty or could not be loaded' if model.empty?
157
- model = model.get
158
- else
159
- fail "Model '#{filename}' did not exist"
160
- end
161
-
162
- model
163
- end
164
-
165
- # TODO: loop of the workflow and run any other reporting measures
166
- # Run the prepackaged measures in the Gem.
167
- def run_packaged_measures
168
- @logger.info "Running packaged reporting measures"
169
-
170
- # HARD CODE the running of the report measure
171
- measure_path = 'packaged_measures'
172
- measure_name = 'StandardReports'
173
-
174
- # when full workflow then do this
175
- # require "#{File.expand_path(File.join(File.dirname(__FILE__), '..', measure_path, measure_name, 'measure'))}"
176
- measure_file_path = File.expand_path(File.join(File.dirname(__FILE__), measure_path, measure_name, 'measure.rb'))
177
- @logger.info "Loading measure in relative path #{measure_path}"
178
- fail "Packaged measure does not exist for #{measure_file_path}" unless File.exist?(measure_file_path)
179
-
180
- #measure_file_path = File.expand_path(
181
- # File.join(@directory, @options[:analysis_root_path], measure_path, 'measure.rb'))
182
- #fail "Measure file does not exist #{measure_name} in #{measure_file_path}" unless File.exist? measure_file_path
183
-
184
- require measure_file_path
185
- measure = Object.const_get(measure_name).new
186
- runner = OpenStudio::Ruleset::OSRunner.new
187
-
188
- @logger.info "Run directory for post process: #{@run_directory}"
189
- runner.setLastOpenStudioModel(@model)
190
- runner.setLastEnergyPlusSqlFilePath(@sql_filename)
191
-
192
- # create a new directory before running
193
- measure_run_dir = "#{@directory}/#{measure_name}"
194
- @logger.info "Running measure in #{measure_run_dir}"
195
- FileUtils.mkdir_p(measure_run_dir)
196
- current_dir = Dir.pwd
197
- begin
198
- Dir.chdir(measure_run_dir)
199
- argument_map = OpenStudio::Ruleset::OSArgumentMap.new
200
- @logger.info "Calling run on measure"
201
- measure.run(runner, argument_map)
202
- measure_result = runner.result
203
- ensure
204
- Dir.chdir(current_dir)
205
- end
206
-
207
- @logger.info measure_result.initialCondition.get.logMessage unless measure_result.initialCondition.empty?
208
- @logger.info measure_result.finalCondition.get.logMessage unless measure_result.finalCondition.empty?
209
-
210
- measure_result.warnings.each { |w| @logger.info w.logMessage }
211
- measure_result.errors.each { |w| @logger.info w.logMessage }
212
- measure_result.info.each { |w| @logger.info w.logMessage }
213
-
214
- report_json = JSON.parse(OpenStudio.toJSON(measure_result.attributes), symbolize_names: true)
215
-
216
- # only grab the attributes
217
- standard_report = report_json[:attributes]
218
- File.open("#{@run_directory}/standard_report.json", 'w') { |f| f << JSON.pretty_generate(standard_report) }
219
-
220
- @logger.info 'Finished OpenStudio Post Processing'
221
- end
222
-
223
- def translate_csv_to_json
224
- if File.exist?("#{@run_directory}/eplustbl.csv")
225
- @logger.info 'Translating EnergyPlus table CSV to JSON file'
226
- results = {}
227
- csv = CSV.read("#{@run_directory}/eplustbl.csv")
228
- csv.transpose.each do |k, v|
229
- longname = k.gsub(/\(.*\)/, '').strip
230
- short_name = longname.downcase.gsub(' ', '_')
231
- units = k.match(/\(.*\)/)[0].gsub('(', '').gsub(')', '')
232
- results[short_name.to_sym] = v.nil? ? nil : v.to_f
233
- results["#{short_name}_units".to_sym] = units
234
- results["#{short_name}_display_name".to_sym] = longname
235
- end
236
-
237
- @logger.info 'Saving results to json'
238
-
239
- # save out results
240
- File.open("#{@run_directory}/standard_report_legacy.json", 'w') { |f| f << JSON.pretty_generate(results) }
241
- end
242
- end
243
-
244
- # TODO: THis is uglier than the one below! sorry.
245
- def run_monthly_postprocess
246
- # sql_query method
247
- def sql_query(sql, report_name, query)
248
- val = nil
249
- result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
250
- if result
251
- begin
252
- val = result.get
253
- rescue Exception => e
254
- @logger.info "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
255
- val = nil
256
- end
257
- end
258
- val
259
- end
260
-
261
- def add_element(hash, var_name, value, xpath = nil)
262
- values_hash = {}
263
- values_hash['name'] = var_name
264
-
265
- # store correct datatype
266
- store_val = nil
267
- if value.nil?
268
- store_val = nil
269
- elsif value == 'true'
270
- store_val = true
271
- elsif value == 'false'
272
- store_val = false
273
- else
274
- test = value.to_s
275
- value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
276
- if value.is_a?(Fixnum) || value.is_a?(Float)
277
- store_val = value.to_f
278
- else
279
- store_val = value.to_s
280
- end
281
- end
282
- values_hash['value'] = store_val
283
- values_hash['xpath'] = xpath unless xpath.nil?
284
-
285
- hash['data']['variables'] << values_hash
286
- end
287
-
288
- # add results from sql method
289
- def add_data(sql, query, hdr, area, val)
290
- row = []
291
- val = sql_query(sql, 'AnnualBuildingUtilityPerformanceSummary', query) if val.nil?
292
- row << hdr
293
- if area.nil?
294
- row << val
295
- else
296
- row << (val * 1000) / area
297
- end
298
- row
299
- end
300
-
301
- # add results from sql method
302
- def add_data2(sql, query, hdr, area, val)
303
- row = []
304
- val = sql_query(sql, 'BUILDING ENERGY PERFORMANCE - ELECTRICITY', query) if val.nil?
305
- row << hdr
306
- if area.nil?
307
- row << val
308
- else
309
- row << (val * 1000) / area
310
- end
311
- row
312
- end
313
-
314
- # add results from sql method
315
- def add_data3(sql, query, hdr, area, val)
316
- row = []
317
- val = sql_query(sql, 'BUILDING ENERGY PERFORMANCE - NATURAL GAS', query) if val.nil?
318
- row << hdr
319
- if area.nil?
320
- row << val
321
- else
322
- row << (val * 1000) / area
323
- end
324
- row
325
- end
326
-
327
- # add results from sql method
328
- def add_data4(sql, query, hdr, area, val)
329
- row = []
330
-
331
- if val.nil?
332
- val = 0
333
-
334
- ["INTERIORLIGHTS:ELECTRICITY", "EXTERIORLIGHTS:ELECTRICITY", "INTERIOREQUIPMENT:ELECTRICITY", "EXTERIOREQUIPMENT:ELECTRICITY",
335
- "FANS:ELECTRICITY", "PUMPS:ELECTRICITY", "HEATING:ELECTRICITY", "COOLING:ELECTRICITY", "HEATREJECTION:ELECTRICITY",
336
- "HUMIDIFIER:ELECTRICITY", "HEATRECOVERY:ELECTRICITY", "WATERSYSTEMS:ELECTRICITY", "COGENERATION:ELECTRICITY", "REFRIGERATION:ELECTRICITY"].each do |end_use|
337
-
338
- tmp_query = query + " AND ColumnName='#{end_use}'"
339
- tmp_val = sql_query(sql, 'BUILDING ENERGY PERFORMANCE - ELECTRICITY', tmp_query)
340
- val += tmp_val if not tmp_val.nil?
341
- end
342
- end
343
-
344
- row << hdr
345
- if area.nil?
346
- row << val
347
- else
348
- row << (val * 1000) / area
349
- end
350
- row
351
- end
352
-
353
- # open sql file
354
- sql_file = OpenStudio::SqlFile.new(@sql_filename)
355
-
356
- # get building area
357
- bldg_area = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
358
- # populate data array
359
-
360
- tbl_data = []
361
- tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Energy (MJ/m2)', nil, nil)
362
- tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Source Energy (MJ/m2)', nil, nil)
363
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Electricity'", 'Total Electricity (MJ/m2)', bldg_area, nil)
364
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Natural Gas'", 'Total Natural Gas (MJ/m2)', bldg_area, nil)
365
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Electricity'", 'Heating Electricity (MJ/m2)', bldg_area, nil)
366
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Natural Gas'", 'Heating Natural Gas (MJ/m2)', bldg_area, nil)
367
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Cooling' AND ColumnName='Electricity'", 'Cooling Electricity (MJ/m2)', bldg_area, nil)
368
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Lighting' AND ColumnName='Electricity'", 'Interior Lighting Electricity (MJ/m2)', bldg_area, nil)
369
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Lighting' AND ColumnName='Electricity'", 'Exterior Lighting Electricity (MJ/m2)', bldg_area, nil)
370
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Electricity'", 'Interior Equipment Electricity (MJ/m2)', bldg_area, nil)
371
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Natural Gas'", 'Interior Equipment Natural Gas (MJ/m2)', bldg_area, nil)
372
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Equipment' AND ColumnName='Electricity'", 'Exterior Equipment Electricity (MJ/m2)', bldg_area, nil)
373
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Fans' AND ColumnName='Electricity'", 'Fans Electricity (MJ/m2)', bldg_area, nil)
374
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Pumps' AND ColumnName='Electricity'", 'Pumps Electricity (MJ/m2)', bldg_area, nil)
375
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heat Rejection' AND ColumnName='Electricity'", 'Heat Rejection Electricity (MJ/m2)', bldg_area, nil)
376
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Humidification' AND ColumnName='Electricity'", 'Humidification Electricity (MJ/m2)', bldg_area, nil)
377
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Electricity'", 'Water Systems Electricity (MJ/m2)', bldg_area, nil)
378
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Natural Gas'", 'Water Systems Natural Gas (MJ/m2)', bldg_area, nil)
379
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Refrigeration' AND ColumnName='Electricity'", 'Refrigeration Electricity (MJ/m2)', bldg_area, nil)
380
- htg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Heating' AND ColumnName='Facility'")
381
- clg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Cooling' AND ColumnName='Facility'")
382
- tot_hrs = clg_hrs && htg_hrs ? htg_hrs + clg_hrs : nil
383
- tbl_data << add_data(sql_file, nil, 'Heating Hours Unmet (hr)', nil, htg_hrs)
384
- tbl_data << add_data(sql_file, nil, 'Cooling Hours Unmet (hr)', nil, clg_hrs)
385
- tbl_data << add_data(sql_file, nil, 'Total Hours Unmet (hr)', nil, tot_hrs)
386
- total_cost = sql_query(sql_file, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
387
- tbl_data << add_data(sql_file, nil, 'Total Life Cycle Cost ($)', nil, total_cost)
388
- # cooling:electricity
389
- tbl_data << add_data2(sql_file, "RowName='January' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Jan (J)', nil, nil)
390
- tbl_data << add_data2(sql_file, "RowName='February' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Feb (J)', nil, nil)
391
- tbl_data << add_data2(sql_file, "RowName='March' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Mar (J)', nil, nil)
392
- tbl_data << add_data2(sql_file, "RowName='April' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Apr (J)', nil, nil)
393
- tbl_data << add_data2(sql_file, "RowName='May' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity May (J)', nil, nil)
394
- tbl_data << add_data2(sql_file, "RowName='June' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Jun (J)', nil, nil)
395
- tbl_data << add_data2(sql_file, "RowName='July' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Jul (J)', nil, nil)
396
- tbl_data << add_data2(sql_file, "RowName='August' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Aug (J)', nil, nil)
397
- tbl_data << add_data2(sql_file, "RowName='September' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Sep (J)', nil, nil)
398
- tbl_data << add_data2(sql_file, "RowName='October' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Oct (J)', nil, nil)
399
- tbl_data << add_data2(sql_file, "RowName='November' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Nov (J)', nil, nil)
400
- tbl_data << add_data2(sql_file, "RowName='December' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Dec (J)', nil, nil)
401
- # heating:gas
402
- tbl_data << add_data3(sql_file, "RowName='January' AND ColumnName='HEATING:GAS'", 'Heating Gas Jan (J)', nil, nil)
403
- tbl_data << add_data3(sql_file, "RowName='February' AND ColumnName='HEATING:GAS'", 'Heating Gas Feb (J)', nil, nil)
404
- tbl_data << add_data3(sql_file, "RowName='March' AND ColumnName='HEATING:GAS'", 'Heating Gas Mar (J)', nil, nil)
405
- tbl_data << add_data3(sql_file, "RowName='April' AND ColumnName='HEATING:GAS'", 'Heating Gas Apr (J)', nil, nil)
406
- tbl_data << add_data3(sql_file, "RowName='May' AND ColumnName='HEATING:GAS'", 'Heating Gas May (J)', nil, nil)
407
- tbl_data << add_data3(sql_file, "RowName='June' AND ColumnName='HEATING:GAS'", 'Heating Gas Jun (J)', nil, nil)
408
- tbl_data << add_data3(sql_file, "RowName='July' AND ColumnName='HEATING:GAS'", 'Heating Gas Jul (J)', nil, nil)
409
- tbl_data << add_data3(sql_file, "RowName='August' AND ColumnName='HEATING:GAS'", 'Heating Gas Aug (J)', nil, nil)
410
- tbl_data << add_data3(sql_file, "RowName='September' AND ColumnName='HEATING:GAS'", 'Heating Gas Sep (J)', nil, nil)
411
- tbl_data << add_data3(sql_file, "RowName='October' AND ColumnName='HEATING:GAS'", 'Heating Gas Oct (J)', nil, nil)
412
- tbl_data << add_data3(sql_file, "RowName='November' AND ColumnName='HEATING:GAS'", 'Heating Gas Nov (J)', nil, nil)
413
- tbl_data << add_data3(sql_file, "RowName='December' AND ColumnName='HEATING:GAS'", 'Heating Gas Dec (J)', nil, nil)
414
- # total Electricity
415
- tbl_data << add_data4(sql_file, "RowName='January'", 'Total Electricity Jan (J)', nil, nil)
416
- tbl_data << add_data4(sql_file, "RowName='February'", 'Total Electricity Feb (J)', nil, nil)
417
- tbl_data << add_data4(sql_file, "RowName='March'", 'Total Electricity Mar (J)', nil, nil)
418
- tbl_data << add_data4(sql_file, "RowName='April'", 'Total Electricity Apr (J)', nil, nil)
419
- tbl_data << add_data4(sql_file, "RowName='May'", 'Total Electricity May (J)', nil, nil)
420
- tbl_data << add_data4(sql_file, "RowName='June'", 'Total Electricity Jun (J)', nil, nil)
421
- tbl_data << add_data4(sql_file, "RowName='July'", 'Total Electricity Jul (J)', nil, nil)
422
- tbl_data << add_data4(sql_file, "RowName='August'", 'Total Electricity Aug (J)', nil, nil)
423
- tbl_data << add_data4(sql_file, "RowName='September'", 'Total Electricity Sep (J)', nil, nil)
424
- tbl_data << add_data4(sql_file, "RowName='October'", 'Total Electricity Oct (J)', nil, nil)
425
- tbl_data << add_data4(sql_file, "RowName='November'", 'Total Electricity Nov (J)', nil, nil)
426
- tbl_data << add_data4(sql_file, "RowName='December'", 'Total Electricity Dec (J)', nil, nil) # close SQL file
427
- sql_file.close
428
- # transpose data
429
- tbl_rows = tbl_data.transpose
430
-
431
- @logger.info tbl_rows
432
- # write electricity data to CSV
433
- CSV.open("#{@run_directory}/eplustbl.csv", 'wb') do |csv|
434
- tbl_rows.each do |row|
435
- csv << row
436
- end
437
- end
438
- end
439
-
440
-
441
- # TODO: This is ugly. Move this out of here entirely and into a reporting measure if we need it at all
442
- def run_standard_postprocess
443
- # sql_query method
444
- def sql_query(sql, report_name, query)
445
- val = nil
446
- result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
447
- if result
448
- begin
449
- val = result.get
450
- rescue Exception => e
451
- @logger.info "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
452
- val = nil
453
- end
454
- end
455
- val
456
- end
457
-
458
- def add_element(hash, var_name, value, xpath = nil)
459
- values_hash = {}
460
- values_hash['name'] = var_name
461
-
462
- # store correct datatype
463
- store_val = nil
464
- if value.nil?
465
- store_val = nil
466
- elsif value == 'true'
467
- store_val = true
468
- elsif value == 'false'
469
- store_val = false
470
- else
471
- test = value.to_s
472
- value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
473
- if value.is_a?(Fixnum) || value.is_a?(Float)
474
- store_val = value.to_f
475
- else
476
- store_val = value.to_s
477
- end
478
- end
479
- values_hash['value'] = store_val
480
- values_hash['xpath'] = xpath unless xpath.nil?
481
-
482
- hash['data']['variables'] << values_hash
483
- end
484
-
485
- # add results from sql method
486
- def add_data(sql, query, hdr, area, val)
487
- row = []
488
- val = sql_query(sql, 'AnnualBuildingUtilityPerformanceSummary', query) if val.nil?
489
- row << hdr
490
- if area.nil?
491
- row << val
492
- else
493
- row << (val * 1000) / area
494
- end
495
- row
496
- end
497
-
498
-
499
- # open sql file
500
- sql_file = OpenStudio::SqlFile.new(@sql_filename)
501
-
502
- # get building area
503
- bldg_area = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
504
- # populate data array
505
-
506
- tbl_data = []
507
- tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Energy (MJ/m2)', nil, nil)
508
- tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Source Energy (MJ/m2)', nil, nil)
509
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Electricity'", 'Total Electricity (MJ/m2)', bldg_area, nil)
510
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Natural Gas'", 'Total Natural Gas (MJ/m2)', bldg_area, nil)
511
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Electricity'", 'Heating Electricity (MJ/m2)', bldg_area, nil)
512
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Natural Gas'", 'Heating Natural Gas (MJ/m2)', bldg_area, nil)
513
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Cooling' AND ColumnName='Electricity'", 'Cooling Electricity (MJ/m2)', bldg_area, nil)
514
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Lighting' AND ColumnName='Electricity'", 'Interior Lighting Electricity (MJ/m2)', bldg_area, nil)
515
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Lighting' AND ColumnName='Electricity'", 'Exterior Lighting Electricity (MJ/m2)', bldg_area, nil)
516
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Electricity'", 'Interior Equipment Electricity (MJ/m2)', bldg_area, nil)
517
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Natural Gas'", 'Interior Equipment Natural Gas (MJ/m2)', bldg_area, nil)
518
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Equipment' AND ColumnName='Electricity'", 'Exterior Equipment Electricity (MJ/m2)', bldg_area, nil)
519
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Fans' AND ColumnName='Electricity'", 'Fans Electricity (MJ/m2)', bldg_area, nil)
520
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Pumps' AND ColumnName='Electricity'", 'Pumps Electricity (MJ/m2)', bldg_area, nil)
521
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heat Rejection' AND ColumnName='Electricity'", 'Heat Rejection Electricity (MJ/m2)', bldg_area, nil)
522
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Humidification' AND ColumnName='Electricity'", 'Humidification Electricity (MJ/m2)', bldg_area, nil)
523
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Electricity'", 'Water Systems Electricity (MJ/m2)', bldg_area, nil)
524
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Natural Gas'", 'Water Systems Natural Gas (MJ/m2)', bldg_area, nil)
525
- tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Refrigeration' AND ColumnName='Electricity'", 'Refrigeration Electricity (MJ/m2)', bldg_area, nil)
526
- htg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Heating' AND ColumnName='Facility'")
527
- clg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Cooling' AND ColumnName='Facility'")
528
- tot_hrs = clg_hrs && htg_hrs ? htg_hrs + clg_hrs : nil
529
- tbl_data << add_data(sql_file, nil, 'Heating Hours Unmet (hr)', nil, htg_hrs)
530
- tbl_data << add_data(sql_file, nil, 'Cooling Hours Unmet (hr)', nil, clg_hrs)
531
- tbl_data << add_data(sql_file, nil, 'Total Hours Unmet (hr)', nil, tot_hrs)
532
- total_cost = sql_query(sql_file, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
533
- tbl_data << add_data(sql_file, nil, 'Total Life Cycle Cost ($)', nil, total_cost)
534
- # close SQL file
535
- sql_file.close
536
- # transpose data
537
- tbl_rows = tbl_data.transpose
538
-
539
- @logger.info tbl_rows
540
- # write electricity data to CSV
541
- CSV.open("#{@run_directory}/eplustbl.csv", 'wb') do |csv|
542
- tbl_rows.each do |row|
543
- csv << row
544
- end
545
- end
546
-
547
- end
548
-
549
110
  end