openstudio-workflow 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|