openstudio-workflow 0.1.1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +24 -63
- data/lib/openstudio/extended_runner.rb +94 -0
- data/lib/openstudio/workflow/adapter.rb +10 -0
- data/lib/openstudio/workflow/adapters/mongo.rb +1 -1
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +12 -17
- data/lib/openstudio/workflow/jobs/{run_openstudio → run_energyplus}/monthly_report.idf +8 -4
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +132 -21
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +6 -11
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +7 -6
- data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +2 -1
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +27 -148
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +31 -10
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +4 -3
- data/lib/openstudio/workflow/run.rb +4 -5
- data/lib/openstudio/workflow/version.rb +1 -1
- data/lib/openstudio-workflow.rb +6 -10
- metadata +9 -12
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/README.md +0 -5
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.rb +0 -206
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.xml +0 -53
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb +0 -298
@@ -17,7 +17,6 @@
|
|
17
17
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
######################################################################
|
19
19
|
|
20
|
-
# TODO: I hear that measures can step on each other if not run in their own directory
|
21
20
|
class RunOpenstudio
|
22
21
|
# Mixin the MeasureApplication module to apply measures
|
23
22
|
include OpenStudio::Workflow::ApplyMeasures
|
@@ -25,8 +24,10 @@ class RunOpenstudio
|
|
25
24
|
# Initialize
|
26
25
|
# param directory: base directory where the simulation files are prepared
|
27
26
|
# param logger: logger object in which to write log messages
|
28
|
-
def initialize(directory, logger, time_logger, adapter, options = {})
|
27
|
+
def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
|
29
28
|
defaults = { format: 'hash', use_monthly_reports: false, analysis_root_path: '.' }
|
29
|
+
warn 'Option of use_monthly_reports is deprecated. Monthly reports are always generated.' if options[:use_monthly_reports]
|
30
|
+
|
30
31
|
@options = defaults.merge(options)
|
31
32
|
@directory = directory
|
32
33
|
# TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
|
@@ -35,6 +36,7 @@ class RunOpenstudio
|
|
35
36
|
@results = {}
|
36
37
|
@logger = logger
|
37
38
|
@time_logger = time_logger
|
39
|
+
@workflow_arguments = workflow_arguments
|
38
40
|
@logger.info "#{self.class} passed the following options #{@options}"
|
39
41
|
|
40
42
|
# initialize instance variables that are needed in the perform section
|
@@ -63,12 +65,14 @@ class RunOpenstudio
|
|
63
65
|
load_weather_file
|
64
66
|
|
65
67
|
apply_measures(:openstudio_measure)
|
68
|
+
@logger.info('Finished applying OpenStudio measures.')
|
66
69
|
|
67
70
|
@time_logger.start('Translating to EnergyPlus')
|
68
71
|
translate_to_energyplus
|
69
72
|
@time_logger.stop('Translating to EnergyPlus')
|
70
73
|
|
71
74
|
apply_measures(:energyplus_measure)
|
75
|
+
@logger.info('Finished applying EnergyPlus measures.')
|
72
76
|
|
73
77
|
# check if the weather file has changed. This is cheesy for now. Should have a default measure that
|
74
78
|
# always sets the weather file so that it can be better controlled
|
@@ -106,15 +110,6 @@ class RunOpenstudio
|
|
106
110
|
idf_filename = "#{@run_directory}/in.idf"
|
107
111
|
File.open(idf_filename, 'w') { |f| f << @model_idf.to_s }
|
108
112
|
|
109
|
-
# TODO: convert this to an OpenStudio method instead of substituting the data as text
|
110
|
-
if @options[:use_monthly_reports]
|
111
|
-
@logger.info 'Adding monthly reports to EnergyPlus IDF'
|
112
|
-
to_append = File.read(File.join(File.dirname(__FILE__), 'monthly_report.idf'))
|
113
|
-
File.open(idf_filename, 'a') do |handle|
|
114
|
-
handle.puts to_append
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
113
|
@results[:osm] = File.expand_path(osm_filename)
|
119
114
|
@results[:idf] = File.expand_path(idf_filename)
|
120
115
|
end
|
@@ -27,7 +27,7 @@ class RunPostprocess
|
|
27
27
|
# Mixin the MeasureApplication module to apply measures
|
28
28
|
include OpenStudio::Workflow::ApplyMeasures
|
29
29
|
|
30
|
-
def initialize(directory, logger, time_logger, adapter, options = {})
|
30
|
+
def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
|
31
31
|
defaults = {}
|
32
32
|
@options = defaults.merge(options)
|
33
33
|
@directory = directory
|
@@ -35,6 +35,7 @@ class RunPostprocess
|
|
35
35
|
@adapter = adapter
|
36
36
|
@logger = logger
|
37
37
|
@time_logger = time_logger
|
38
|
+
@workflow_arguments = workflow_arguments
|
38
39
|
@results = {}
|
39
40
|
@output_attributes = {}
|
40
41
|
|
@@ -76,14 +77,14 @@ class RunPostprocess
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
|
-
# Also, find any "report
|
80
|
+
# Also, find any "report*.*" files
|
80
81
|
Dir["#{@run_directory}/*/report*.*"].each do |report|
|
81
82
|
# get the parent directory of the file and snake case it
|
82
83
|
# do i need to force encoding on this as well?
|
83
|
-
measure_class_name = File.basename(File.dirname(report)).
|
84
|
+
measure_class_name = File.basename(File.dirname(report)).to_underscore
|
84
85
|
file_ext = File.extname(report)
|
85
|
-
append_str = File.basename(report, '.*')
|
86
|
-
new_file_name = "#{@directory}/reports/#{measure_class_name}#{append_str}#{file_ext}"
|
86
|
+
append_str = File.basename(report, '.*')
|
87
|
+
new_file_name = "#{@directory}/reports/#{measure_class_name}_#{append_str}#{file_ext}"
|
87
88
|
FileUtils.copy report, new_file_name
|
88
89
|
end
|
89
90
|
|
@@ -98,7 +99,7 @@ class RunPostprocess
|
|
98
99
|
# paths_to_rm << Pathname.glob("#{@run_directory}/*.idf") # keep the idfs
|
99
100
|
# paths_to_rm << Pathname.glob("*.audit")
|
100
101
|
# paths_to_rm << Pathname.glob("*.bnd")
|
101
|
-
paths_to_rm << Pathname.glob("#{@run_directory}/*.eso")
|
102
|
+
# paths_to_rm << Pathname.glob("#{@run_directory}/*.eso")
|
102
103
|
paths_to_rm << Pathname.glob("#{@run_directory}/*.mtr")
|
103
104
|
paths_to_rm << Pathname.glob("#{@run_directory}/*.epw")
|
104
105
|
paths_to_rm << Pathname.glob("#{@run_directory}/*.mtd")
|
@@ -19,13 +19,14 @@
|
|
19
19
|
|
20
20
|
# Run Prelight job to prepare the directory for simulations.
|
21
21
|
class RunPreflight
|
22
|
-
def initialize(directory, logger, time_logger, adapter, options = {})
|
22
|
+
def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
|
23
23
|
defaults = {}
|
24
24
|
@options = defaults.merge(options)
|
25
25
|
@directory = directory
|
26
26
|
@adapter = adapter
|
27
27
|
@logger = logger
|
28
28
|
@time_logger = time_logger
|
29
|
+
@workflow_arguments = workflow_arguments
|
29
30
|
@results = {}
|
30
31
|
end
|
31
32
|
|
@@ -25,7 +25,7 @@ class RunReportingMeasures
|
|
25
25
|
# Mixin the MeasureApplication module to apply measures
|
26
26
|
include OpenStudio::Workflow::ApplyMeasures
|
27
27
|
|
28
|
-
def initialize(directory, logger, time_logger, adapter, options = {})
|
28
|
+
def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
|
29
29
|
defaults = {}
|
30
30
|
@options = defaults.merge(options)
|
31
31
|
@directory = directory
|
@@ -33,6 +33,7 @@ class RunReportingMeasures
|
|
33
33
|
@adapter = adapter
|
34
34
|
@logger = logger
|
35
35
|
@time_logger = time_logger
|
36
|
+
@workflow_arguments = workflow_arguments
|
36
37
|
@results = {}
|
37
38
|
@output_attributes = {}
|
38
39
|
|
@@ -43,6 +44,7 @@ class RunReportingMeasures
|
|
43
44
|
@logger.info "#{self.class} passed the following options #{@options}"
|
44
45
|
|
45
46
|
@model = load_model @options[:run_openstudio][:osm]
|
47
|
+
@model_idf = load_idf @options[:run_openstudio][:idf]
|
46
48
|
|
47
49
|
# TODO: should read the name of the sql output file via the :run_openstudio options hash
|
48
50
|
# I want to reiterate that this is cheezy!
|
@@ -61,11 +63,7 @@ class RunReportingMeasures
|
|
61
63
|
@analysis_json = @adapter.get_problem(@directory, @options)
|
62
64
|
|
63
65
|
@time_logger.start('Running standard post process')
|
64
|
-
|
65
|
-
run_monthly_postprocess
|
66
|
-
else
|
67
|
-
run_standard_postprocess
|
68
|
-
end
|
66
|
+
run_monthly_postprocess
|
69
67
|
@time_logger.stop('Running standard post process')
|
70
68
|
|
71
69
|
translate_csv_to_json
|
@@ -193,7 +191,7 @@ class RunReportingMeasures
|
|
193
191
|
|
194
192
|
private
|
195
193
|
|
196
|
-
# Load in the OpenStudio model. It is required for
|
194
|
+
# Load in the OpenStudio model. It is required for post processing
|
197
195
|
def load_model(filename)
|
198
196
|
model = nil
|
199
197
|
@logger.info 'Loading model'
|
@@ -213,18 +211,34 @@ class RunReportingMeasures
|
|
213
211
|
model
|
214
212
|
end
|
215
213
|
|
216
|
-
#
|
214
|
+
# Load in the IDF model. It is required for post processing
|
215
|
+
def load_idf(filename)
|
216
|
+
fail "IDF file does not exist: #{filename}" unless File.exist? filename
|
217
|
+
OpenStudio::Workspace.load(filename, 'EnergyPlus'.to_IddFileType).get
|
218
|
+
end
|
219
|
+
|
220
|
+
# Run the prepackaged measures in OpenStudio. Currently this runs the standard reports and the calibration measure
|
221
|
+
# TODO: add a flag on which packaged reporting measures to run
|
217
222
|
def run_packaged_measures
|
218
223
|
# configure the workflow item json to pass
|
219
224
|
workflow_item = {
|
220
225
|
display_name: 'Standard Reports',
|
221
|
-
measure_definition_directory: File.expand_path(File.join(
|
222
|
-
measure_definition_class_name: '
|
226
|
+
measure_definition_directory: File.expand_path(File.join(OpenStudio::BCLMeasure.standardReportMeasure.directory.to_s, 'measure.rb')),
|
227
|
+
measure_definition_class_name: 'OpenStudioResults',
|
223
228
|
measure_type: 'ReportingMeasure',
|
224
229
|
name: 'standard_reports'
|
225
230
|
}
|
226
|
-
@logger.info 'Running packaged
|
231
|
+
@logger.info 'Running packaged Standard Reports measures'
|
232
|
+
apply_measure(workflow_item)
|
227
233
|
|
234
|
+
workflow_item = {
|
235
|
+
display_name: 'Calibration Reports',
|
236
|
+
measure_definition_directory: File.expand_path(File.join(OpenStudio::BCLMeasure.calibrationReportMeasure.directory.to_s, 'measure.rb')),
|
237
|
+
measure_definition_class_name: 'CalibrationReports',
|
238
|
+
measure_type: 'CalibrationReports',
|
239
|
+
name: 'calibration_reports'
|
240
|
+
}
|
241
|
+
@logger.info 'Running packaged Calibration Reports measures'
|
228
242
|
apply_measure(workflow_item)
|
229
243
|
|
230
244
|
@logger.info 'Finished Running Packaged Measures'
|
@@ -237,8 +251,8 @@ class RunReportingMeasures
|
|
237
251
|
csv = CSV.read("#{@run_directory}/eplustbl.csv")
|
238
252
|
csv.transpose.each do |k, v|
|
239
253
|
longname = k.gsub(/\(.*\)/, '').strip
|
240
|
-
short_name = longname.downcase.
|
241
|
-
units = k.match(/\(.*\)/)[0].
|
254
|
+
short_name = longname.downcase.tr(' ', '_')
|
255
|
+
units = k.match(/\(.*\)/)[0].delete('(').delete(')')
|
242
256
|
results[short_name.to_sym] = v.nil? ? nil : v.to_f
|
243
257
|
results["#{short_name}_units".to_sym] = units
|
244
258
|
results["#{short_name}_display_name".to_sym] = longname
|
@@ -294,33 +308,6 @@ class RunReportingMeasures
|
|
294
308
|
val
|
295
309
|
end
|
296
310
|
|
297
|
-
def add_element(hash, var_name, value, xpath = nil)
|
298
|
-
values_hash = {}
|
299
|
-
values_hash['name'] = var_name
|
300
|
-
|
301
|
-
# store correct datatype
|
302
|
-
store_val = nil
|
303
|
-
if value.nil?
|
304
|
-
store_val = nil
|
305
|
-
elsif value == 'true'
|
306
|
-
store_val = true
|
307
|
-
elsif value == 'false'
|
308
|
-
store_val = false
|
309
|
-
else
|
310
|
-
test = value.to_s
|
311
|
-
value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
|
312
|
-
if value.is_a?(Fixnum) || value.is_a?(Float)
|
313
|
-
store_val = value.to_f
|
314
|
-
else
|
315
|
-
store_val = value.to_s
|
316
|
-
end
|
317
|
-
end
|
318
|
-
values_hash['value'] = store_val
|
319
|
-
values_hash['xpath'] = xpath unless xpath.nil?
|
320
|
-
|
321
|
-
hash['data']['variables'] << values_hash
|
322
|
-
end
|
323
|
-
|
324
311
|
# add results from sql method
|
325
312
|
def add_data(sql, query, hdr, area, val)
|
326
313
|
row = []
|
@@ -471,112 +458,4 @@ class RunReportingMeasures
|
|
471
458
|
end
|
472
459
|
end
|
473
460
|
end
|
474
|
-
|
475
|
-
# TODO: This is ugly. Move this out of here entirely and into a reporting measure if we need it at all
|
476
|
-
def run_standard_postprocess
|
477
|
-
def sql_query(sql, report_name, query)
|
478
|
-
val = nil
|
479
|
-
result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
|
480
|
-
if result.empty?
|
481
|
-
@logger.warn "Query for run_standard_postprocess failed for #{query}"
|
482
|
-
else
|
483
|
-
begin
|
484
|
-
val = result.get
|
485
|
-
rescue => e
|
486
|
-
@logger.info "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
487
|
-
val = nil
|
488
|
-
end
|
489
|
-
end
|
490
|
-
|
491
|
-
val
|
492
|
-
end
|
493
|
-
|
494
|
-
def add_element(hash, var_name, value, xpath = nil)
|
495
|
-
values_hash = {}
|
496
|
-
values_hash['name'] = var_name
|
497
|
-
|
498
|
-
# store correct datatype
|
499
|
-
store_val = nil
|
500
|
-
if value.nil?
|
501
|
-
store_val = nil
|
502
|
-
elsif value == 'true'
|
503
|
-
store_val = true
|
504
|
-
elsif value == 'false'
|
505
|
-
store_val = false
|
506
|
-
else
|
507
|
-
test = value.to_s
|
508
|
-
value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
|
509
|
-
if value.is_a?(Fixnum) || value.is_a?(Float)
|
510
|
-
store_val = value.to_f
|
511
|
-
else
|
512
|
-
store_val = value.to_s
|
513
|
-
end
|
514
|
-
end
|
515
|
-
values_hash['value'] = store_val
|
516
|
-
values_hash['xpath'] = xpath unless xpath.nil?
|
517
|
-
|
518
|
-
hash['data']['variables'] << values_hash
|
519
|
-
end
|
520
|
-
|
521
|
-
# add results from sql method
|
522
|
-
def add_data(sql, query, hdr, area, val)
|
523
|
-
row = []
|
524
|
-
val = sql_query(sql, 'AnnualBuildingUtilityPerformanceSummary', query) if val.nil?
|
525
|
-
row << hdr
|
526
|
-
if area.nil?
|
527
|
-
row << val
|
528
|
-
else
|
529
|
-
row << (val * 1000) / area
|
530
|
-
end
|
531
|
-
row
|
532
|
-
end
|
533
|
-
|
534
|
-
# open sql file
|
535
|
-
sql_file = OpenStudio::SqlFile.new(@sql_filename)
|
536
|
-
|
537
|
-
# get building area
|
538
|
-
bldg_area = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
|
539
|
-
# populate data array
|
540
|
-
|
541
|
-
tbl_data = []
|
542
|
-
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)
|
543
|
-
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)
|
544
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Electricity'", 'Total Electricity (MJ/m2)', bldg_area, nil)
|
545
|
-
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)
|
546
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Electricity'", 'Heating Electricity (MJ/m2)', bldg_area, nil)
|
547
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Natural Gas'", 'Heating Natural Gas (MJ/m2)', bldg_area, nil)
|
548
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Cooling' AND ColumnName='Electricity'", 'Cooling Electricity (MJ/m2)', bldg_area, nil)
|
549
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Lighting' AND ColumnName='Electricity'", 'Interior Lighting Electricity (MJ/m2)', bldg_area, nil)
|
550
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Lighting' AND ColumnName='Electricity'", 'Exterior Lighting Electricity (MJ/m2)', bldg_area, nil)
|
551
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Electricity'", 'Interior Equipment Electricity (MJ/m2)', bldg_area, nil)
|
552
|
-
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)
|
553
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Equipment' AND ColumnName='Electricity'", 'Exterior Equipment Electricity (MJ/m2)', bldg_area, nil)
|
554
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Fans' AND ColumnName='Electricity'", 'Fans Electricity (MJ/m2)', bldg_area, nil)
|
555
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Pumps' AND ColumnName='Electricity'", 'Pumps Electricity (MJ/m2)', bldg_area, nil)
|
556
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heat Rejection' AND ColumnName='Electricity'", 'Heat Rejection Electricity (MJ/m2)', bldg_area, nil)
|
557
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Humidification' AND ColumnName='Electricity'", 'Humidification Electricity (MJ/m2)', bldg_area, nil)
|
558
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Electricity'", 'Water Systems Electricity (MJ/m2)', bldg_area, nil)
|
559
|
-
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)
|
560
|
-
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Refrigeration' AND ColumnName='Electricity'", 'Refrigeration Electricity (MJ/m2)', bldg_area, nil)
|
561
|
-
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'")
|
562
|
-
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'")
|
563
|
-
tot_hrs = clg_hrs && htg_hrs ? htg_hrs + clg_hrs : nil
|
564
|
-
tbl_data << add_data(sql_file, nil, 'Heating Hours Unmet (hr)', nil, htg_hrs)
|
565
|
-
tbl_data << add_data(sql_file, nil, 'Cooling Hours Unmet (hr)', nil, clg_hrs)
|
566
|
-
tbl_data << add_data(sql_file, nil, 'Total Hours Unmet (hr)', nil, tot_hrs)
|
567
|
-
total_cost = sql_query(sql_file, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
|
568
|
-
tbl_data << add_data(sql_file, nil, 'Total Life Cycle Cost ($)', nil, total_cost)
|
569
|
-
# close SQL file
|
570
|
-
sql_file.close
|
571
|
-
# transpose data
|
572
|
-
tbl_rows = tbl_data.transpose
|
573
|
-
|
574
|
-
@logger.info tbl_rows
|
575
|
-
# write electricity data to CSV
|
576
|
-
CSV.open("#{@run_directory}/eplustbl.csv", 'wb') do |csv|
|
577
|
-
tbl_rows.each do |row|
|
578
|
-
csv << row
|
579
|
-
end
|
580
|
-
end
|
581
|
-
end
|
582
461
|
end
|
@@ -27,14 +27,10 @@ class RunRunmanager
|
|
27
27
|
# Initialize
|
28
28
|
# param directory: base directory where the simulation files are prepared
|
29
29
|
# param logger: logger object in which to write log messages
|
30
|
-
def initialize(directory, logger, time_logger, adapter, options = {})
|
31
|
-
|
32
|
-
if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
33
|
-
energyplus_path = 'C:/EnergyPlus-8-2-0'
|
34
|
-
else
|
35
|
-
energyplus_path = '/usr/local/EnergyPlus-8-2-0'
|
36
|
-
end
|
30
|
+
def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
|
31
|
+
@logger = logger
|
37
32
|
|
33
|
+
energyplus_path = find_energyplus
|
38
34
|
defaults = {
|
39
35
|
analysis_root_path: '.',
|
40
36
|
energyplus_path: energyplus_path
|
@@ -47,9 +43,9 @@ class RunRunmanager
|
|
47
43
|
@run_directory = @directory / OpenStudio::Path.new('run')
|
48
44
|
@adapter = adapter
|
49
45
|
@results = {}
|
50
|
-
@logger = logger
|
51
46
|
@logger.info "#{self.class} passed the following options #{@options}"
|
52
47
|
@time_logger = time_logger
|
48
|
+
@workflow_arguments = workflow_arguments
|
53
49
|
|
54
50
|
# initialize instance variables that are needed in the perform section
|
55
51
|
@model = nil
|
@@ -200,8 +196,6 @@ class RunRunmanager
|
|
200
196
|
@logger.info 'Updating OpenStudio DataPoint object'
|
201
197
|
analysis.problem.updateDataPoint(data_point, job)
|
202
198
|
|
203
|
-
@logger.info data_point
|
204
|
-
|
205
199
|
@results = { pat_data_point: ::MultiJson.load(data_point.toJSON, symbolize_names: true) }
|
206
200
|
|
207
201
|
# Savet this to the directory for debugging purposes
|
@@ -222,4 +216,31 @@ class RunRunmanager
|
|
222
216
|
|
223
217
|
@results
|
224
218
|
end
|
219
|
+
|
220
|
+
private
|
221
|
+
|
222
|
+
# Look for the location of EnergyPlus
|
223
|
+
def find_energyplus
|
224
|
+
if ENV['ENERGYPLUSDIR']
|
225
|
+
return ENV['ENERGYPLUSDIR']
|
226
|
+
# TODO: check if method exists! first
|
227
|
+
elsif OpenStudio.respond_to? :getEnergyPlusDirectory
|
228
|
+
return OpenStudio.getEnergyPlusDirectory.to_s
|
229
|
+
elsif ENV['RUBYLIB'] =~ /OpenStudio/
|
230
|
+
warn 'Finding EnergyPlus by RUBYLIB parsing will not be supported in the near future. Use either ENERGYPLUSDIR'\
|
231
|
+
'env variable or a newer OpenStudio version that has the getEnergyPlusDirectory method'
|
232
|
+
path = ENV['RUBYLIB'].split(':')
|
233
|
+
path = File.dirname(path.find { |p| p =~ /OpenStudio/ })
|
234
|
+
# Grab the version out of the openstudio path
|
235
|
+
path += '/sharedresources/EnergyPlus-8-3-0'
|
236
|
+
|
237
|
+
return path
|
238
|
+
else
|
239
|
+
if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
240
|
+
return 'C:/EnergyPlus-8-3-0'
|
241
|
+
else
|
242
|
+
return '/usr/local/EnergyPlus-8-3-0'
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
225
246
|
end
|
@@ -22,8 +22,8 @@ require 'libxml'
|
|
22
22
|
# This actually belongs as another class that gets added as a state dynamically
|
23
23
|
class RunXml
|
24
24
|
# RunXml
|
25
|
-
def initialize(directory, logger, time_logger, adapter, options = {})
|
26
|
-
defaults = {
|
25
|
+
def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
|
26
|
+
defaults = { analysis_root_path: '.', xml_library_file: 'xml_runner.rb' }
|
27
27
|
@options = defaults.merge(options)
|
28
28
|
@directory = directory
|
29
29
|
# TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
|
@@ -32,6 +32,7 @@ class RunXml
|
|
32
32
|
@results = {}
|
33
33
|
@logger = logger
|
34
34
|
@time_logger = time_logger
|
35
|
+
@workflow_arguments = workflow_arguments
|
35
36
|
@logger.info "#{self.class} passed the following options #{@options}"
|
36
37
|
|
37
38
|
# initialize instance variables that are needed in the perform section
|
@@ -239,7 +240,7 @@ class RunXml
|
|
239
240
|
@logger.info "Setting variable '#{variable_name}' to '#{@datapoint_json[:data_point][:set_variable_values][variable_uuid]}'"
|
240
241
|
|
241
242
|
args[wf_var[:argument][:name].to_sym] = @datapoint_json[:data_point][:set_variable_values][variable_uuid]
|
242
|
-
args["#{wf_var[:argument][:name]}_machine_name".to_sym] = wf_var[:argument][:display_name].
|
243
|
+
args["#{wf_var[:argument][:name]}_machine_name".to_sym] = wf_var[:argument][:display_name].to_underscore
|
243
244
|
args["#{wf_var[:argument][:name]}_type".to_sym] = wf_var[:value_type] if wf_var[:value_type]
|
244
245
|
@logger.info "Setting the machine name for argument '#{wf_var[:argument][:name]}' to '#{args["#{wf_var[:argument][:name]}_machine_name".to_sym]}'"
|
245
246
|
|
@@ -22,6 +22,7 @@ module OpenStudio
|
|
22
22
|
module Workflow
|
23
23
|
class Run
|
24
24
|
attr_accessor :logger
|
25
|
+
attr_accessor :workflow_arguments
|
25
26
|
|
26
27
|
attr_reader :options
|
27
28
|
attr_reader :adapter
|
@@ -46,7 +47,6 @@ module OpenStudio
|
|
46
47
|
# The default states for the workflow. Note that the states of :queued of :finished need
|
47
48
|
# to exist for all cases.
|
48
49
|
def self.default_states
|
49
|
-
warn "[Deprecation Warning] explicitly specifying states will no longer be required in 0.3.0. Method #{__method__}"
|
50
50
|
[
|
51
51
|
{ state: :queued, options: { initial: true } },
|
52
52
|
{ state: :preflight, options: { after_enter: :run_preflight } },
|
@@ -71,7 +71,6 @@ module OpenStudio
|
|
71
71
|
|
72
72
|
# states for pat job
|
73
73
|
def self.pat_states
|
74
|
-
warn "[Deprecation Warning] explicitly specifying states will no longer be required in 0.3.0. Method #{__method__}"
|
75
74
|
[
|
76
75
|
{ state: :queued, options: { initial: true } },
|
77
76
|
{ state: :preflight, options: { after_enter: :run_preflight } },
|
@@ -95,6 +94,7 @@ module OpenStudio
|
|
95
94
|
@transitions = {}
|
96
95
|
@directory = directory
|
97
96
|
@time_logger = TimeLogger.new
|
97
|
+
@workflow_arguments = {}
|
98
98
|
# TODO: run directory is a convention right now. Move to a configuration item
|
99
99
|
@run_directory = "#{@directory}/run"
|
100
100
|
|
@@ -131,7 +131,6 @@ module OpenStudio
|
|
131
131
|
end
|
132
132
|
|
133
133
|
@logger.info "Initializing directory #{@directory} for simulation with options #{@options}"
|
134
|
-
@logger.info "OpenStudio loaded: '#{$openstudio_gem}'"
|
135
134
|
|
136
135
|
# load the state machine
|
137
136
|
machine
|
@@ -156,7 +155,7 @@ module OpenStudio
|
|
156
155
|
@logger.info 'Sending the run_runmananger results back to the adapter'
|
157
156
|
@adapter.communicate_results @directory, @job_results[:run_runmanager]
|
158
157
|
elsif @job_results[:run_reporting_measures]
|
159
|
-
@logger.info 'Sending the reporting
|
158
|
+
@logger.info 'Sending the reporting measures results back to the adapter'
|
160
159
|
@time_logger.save(File.join(@directory, 'profile.json'))
|
161
160
|
@adapter.communicate_results @directory, @job_results[:run_reporting_measures]
|
162
161
|
end
|
@@ -311,7 +310,7 @@ module OpenStudio
|
|
311
310
|
require_relative "jobs/#{from_method}/#{from_method}"
|
312
311
|
klass_name = from_method.to_s.split('_').map(&:capitalize) * ''
|
313
312
|
@logger.info "Getting method for state transition '#{from_method}'"
|
314
|
-
klass = Object.const_get(klass_name).new(@directory, @logger, @time_logger, @adapter, get_job_options)
|
313
|
+
klass = Object.const_get(klass_name).new(@directory, @logger, @time_logger, @adapter, @workflow_arguments, get_job_options)
|
315
314
|
klass
|
316
315
|
end
|
317
316
|
end
|
data/lib/openstudio-workflow.rb
CHANGED
@@ -25,7 +25,6 @@ require 'fileutils'
|
|
25
25
|
require 'securerandom' # uuids
|
26
26
|
require 'json' # needed for a single pretty generate call
|
27
27
|
require 'pathname'
|
28
|
-
require 'mkmf' # for finding files
|
29
28
|
|
30
29
|
begin
|
31
30
|
require 'facter'
|
@@ -39,21 +38,18 @@ require 'openstudio/workflow/run'
|
|
39
38
|
require 'openstudio/workflow/jobs/lib/apply_measures'
|
40
39
|
require 'openstudio/workflow/time_logger'
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
$openstudio_gem = false
|
47
|
-
puts 'OpenStudio did not load, but most functionality is still available. Will try to continue...'.red
|
48
|
-
end
|
41
|
+
require 'openstudio'
|
42
|
+
require 'openstudio/extended_runner'
|
43
|
+
|
44
|
+
ENV['OPENSTUDIO_WORKFLOW'] = 'true'
|
49
45
|
|
50
46
|
# some core extensions
|
51
47
|
class String
|
52
|
-
def
|
48
|
+
def to_underscore
|
53
49
|
gsub(/::/, '/')
|
54
50
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
55
51
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
56
|
-
.tr('
|
52
|
+
.tr('-', '_')
|
57
53
|
.downcase
|
58
54
|
end
|
59
55
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstudio-workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Long
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -115,23 +115,16 @@ executables: []
|
|
115
115
|
extensions: []
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
|
-
-
|
119
|
-
- README.md
|
120
|
-
- Rakefile
|
121
|
-
- lib/openstudio-workflow.rb
|
118
|
+
- lib/openstudio/extended_runner.rb
|
122
119
|
- lib/openstudio/workflow/adapter.rb
|
123
120
|
- lib/openstudio/workflow/adapters/local.rb
|
124
121
|
- lib/openstudio/workflow/adapters/mongo.rb
|
125
122
|
- lib/openstudio/workflow/jobs/lib/apply_measures.rb
|
123
|
+
- lib/openstudio/workflow/jobs/run_energyplus/monthly_report.idf
|
126
124
|
- lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb
|
127
|
-
- lib/openstudio/workflow/jobs/run_openstudio/monthly_report.idf
|
128
125
|
- lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb
|
129
126
|
- lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb
|
130
127
|
- lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb
|
131
|
-
- lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/README.md
|
132
|
-
- lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.rb
|
133
|
-
- lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.xml
|
134
|
-
- lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb
|
135
128
|
- lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb
|
136
129
|
- lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb
|
137
130
|
- lib/openstudio/workflow/jobs/run_xml/run_xml.rb
|
@@ -139,6 +132,10 @@ files:
|
|
139
132
|
- lib/openstudio/workflow/run.rb
|
140
133
|
- lib/openstudio/workflow/time_logger.rb
|
141
134
|
- lib/openstudio/workflow/version.rb
|
135
|
+
- lib/openstudio-workflow.rb
|
136
|
+
- README.md
|
137
|
+
- CHANGELOG.md
|
138
|
+
- Rakefile
|
142
139
|
homepage: https://github.com/NREL/OpenStudio-workflow-gem
|
143
140
|
licenses:
|
144
141
|
- LGPL
|
@@ -159,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
156
|
version: '0'
|
160
157
|
requirements: []
|
161
158
|
rubyforge_project:
|
162
|
-
rubygems_version: 2.
|
159
|
+
rubygems_version: 2.0.14.1
|
163
160
|
signing_key:
|
164
161
|
specification_version: 4
|
165
162
|
summary: Workflow Manager
|
@@ -1,5 +0,0 @@
|
|
1
|
-
# Packaged Measure Folder
|
2
|
-
|
3
|
-
This folder is used to ship packaged measures with the AMIs.
|
4
|
-
|
5
|
-
Current the only packaged measure is the StandardReports because it is run every simulation. This folder will be copied into each data_point folder for now, but will eventually be part of the standard upload of the project and live in the scripts
|