openstudio-workflow 0.0.1 → 0.0.2
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 +9 -0
- data/README.md +39 -2
- data/Rakefile +12 -1
- data/lib/openstudio-workflow.rb +31 -4
- data/lib/openstudio/workflow/adapter.rb +8 -9
- data/lib/openstudio/workflow/adapters/local.rb +35 -22
- data/lib/openstudio/workflow/adapters/mongo.rb +82 -92
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +229 -0
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +7 -10
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +37 -159
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +53 -492
- data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +1 -5
- data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/README.md +0 -0
- data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.rb +81 -87
- data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.xml +1 -1
- 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
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +548 -0
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +226 -0
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +39 -41
- data/lib/openstudio/workflow/multi_delegator.rb +6 -6
- data/lib/openstudio/workflow/run.rb +95 -39
- data/lib/openstudio/workflow/version.rb +1 -1
- metadata +9 -6
@@ -0,0 +1,229 @@
|
|
1
|
+
######################################################################
|
2
|
+
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
######################################################################
|
19
|
+
|
20
|
+
# module containing the methods to apply measures to a model
|
21
|
+
# must define the following
|
22
|
+
# @logger : where to log information
|
23
|
+
# @model : the OpenStudio model on which to apply measures
|
24
|
+
# @datapoint_json : the datapoint JSON
|
25
|
+
# @anlaysis_json : the analysis JSON
|
26
|
+
# @output_attributes : hash to store any output attributes
|
27
|
+
# @sql_filename : needed for reporting measures
|
28
|
+
|
29
|
+
module OpenStudio
|
30
|
+
module Workflow
|
31
|
+
module ApplyMeasures
|
32
|
+
MEASURE_TYPES = {
|
33
|
+
openstudio_measure: 'RubyMeasure',
|
34
|
+
energyplus_measure: 'EnergyPlusMeasure',
|
35
|
+
reporting_measure: 'ReportingMeasure'
|
36
|
+
}
|
37
|
+
|
38
|
+
def apply_arguments(argument_map, argument)
|
39
|
+
success = true
|
40
|
+
|
41
|
+
unless argument[:value].nil?
|
42
|
+
@logger.info "Setting argument value #{argument[:name]} to #{argument[:value]}"
|
43
|
+
|
44
|
+
v = argument_map[argument[:name]]
|
45
|
+
fail "Could not find argument map in measure for '#{argument[:name]}' with value '#{argument[:value]}'" unless v
|
46
|
+
value_set = v.setValue(argument[:value])
|
47
|
+
fail "Could not set argument #{argument[:name]} of value #{argument[:value]} on model" unless value_set
|
48
|
+
argument_map[argument[:name]] = v.clone
|
49
|
+
else
|
50
|
+
@logger.warn "Value for argument '#{argument[:name]}' not set in argument list therefore will use default"
|
51
|
+
# success = false
|
52
|
+
|
53
|
+
# TODO: what is the fail case (success = false?)
|
54
|
+
end
|
55
|
+
|
56
|
+
success
|
57
|
+
end
|
58
|
+
|
59
|
+
# Apply the variable values to the measure argument map object
|
60
|
+
def apply_variables(argument_map, variable)
|
61
|
+
success = true
|
62
|
+
|
63
|
+
# save the uuid of the variable
|
64
|
+
variable_uuid = variable[:uuid].to_sym
|
65
|
+
if variable[:argument]
|
66
|
+
variable_name = variable[:argument][:name]
|
67
|
+
|
68
|
+
# Get the value from the data point json that was set via R / Problem Formulation
|
69
|
+
if @datapoint_json[:data_point]
|
70
|
+
if @datapoint_json[:data_point][:set_variable_values]
|
71
|
+
unless @datapoint_json[:data_point][:set_variable_values][variable_uuid].nil?
|
72
|
+
@logger.info "Setting variable '#{variable_name}' to #{@datapoint_json[:data_point][:set_variable_values][variable_uuid]}"
|
73
|
+
v = argument_map[variable_name]
|
74
|
+
fail 'Could not find argument map in measure' unless v
|
75
|
+
variable_value = @datapoint_json[:data_point][:set_variable_values][variable_uuid]
|
76
|
+
value_set = v.setValue(variable_value)
|
77
|
+
fail "Could not set variable '#{variable_name}' of value #{variable_value} on model" unless value_set
|
78
|
+
argument_map[variable_name] = v.clone
|
79
|
+
else
|
80
|
+
fail "[ERROR] Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
|
81
|
+
# @logger.error "Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
|
82
|
+
# success = false
|
83
|
+
end
|
84
|
+
else
|
85
|
+
fail 'No block for set_variable_values in data point record'
|
86
|
+
end
|
87
|
+
else
|
88
|
+
fail 'No block for data_point in data_point record'
|
89
|
+
end
|
90
|
+
else
|
91
|
+
fail "Variable '#{variable_name}' is defined but no argument is present"
|
92
|
+
end
|
93
|
+
|
94
|
+
success
|
95
|
+
end
|
96
|
+
|
97
|
+
def apply_measure(workflow_item)
|
98
|
+
@logger.info "Starting #{__method__} for #{workflow_item[:name]}"
|
99
|
+
start_time = ::Time.now
|
100
|
+
current_dir = Dir.pwd
|
101
|
+
begin
|
102
|
+
|
103
|
+
measure_working_directory = "#{@run_directory}/#{workflow_item[:measure_definition_class_name]}"
|
104
|
+
|
105
|
+
@logger.info "Creating run directory to #{measure_working_directory}"
|
106
|
+
FileUtils.mkdir_p measure_working_directory
|
107
|
+
Dir.chdir measure_working_directory
|
108
|
+
|
109
|
+
measure_path = workflow_item[:measure_definition_directory]
|
110
|
+
measure_name = workflow_item[:measure_definition_class_name]
|
111
|
+
@logger.info "Apply measure running in #{Dir.pwd}"
|
112
|
+
|
113
|
+
measure_file_path = nil
|
114
|
+
if (Pathname.new measure_path).absolute?
|
115
|
+
measure_file_path = measure_path
|
116
|
+
else
|
117
|
+
measure_file_path = File.expand_path(File.join(@options[:analysis_root_path], measure_path, 'measure.rb'))
|
118
|
+
end
|
119
|
+
|
120
|
+
@logger.info "Loading Measure from #{measure_file_path}"
|
121
|
+
fail "Measure file does not exist #{measure_name} in #{measure_file_path}" unless File.exist? measure_file_path
|
122
|
+
|
123
|
+
require measure_file_path
|
124
|
+
measure = Object.const_get(measure_name).new
|
125
|
+
runner = OpenStudio::Ruleset::OSRunner.new
|
126
|
+
result = nil
|
127
|
+
|
128
|
+
arguments = nil
|
129
|
+
if workflow_item[:measure_type] == 'RubyMeasure'
|
130
|
+
arguments = measure.arguments(@model)
|
131
|
+
elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
|
132
|
+
arguments = measure.arguments(@model)
|
133
|
+
elsif workflow_item[:measure_type] == 'ReportingMeasure'
|
134
|
+
arguments = measure.arguments
|
135
|
+
end
|
136
|
+
|
137
|
+
# Create argument map and initialize all the arguments
|
138
|
+
argument_map = OpenStudio::Ruleset::OSArgumentMap.new
|
139
|
+
arguments.each do |v|
|
140
|
+
argument_map[v.name] = v.clone
|
141
|
+
end
|
142
|
+
# @logger.info "Argument map for measure is #{argument_map}"
|
143
|
+
|
144
|
+
@logger.info "Iterating over arguments for workflow item '#{workflow_item[:name]}'"
|
145
|
+
if workflow_item[:arguments]
|
146
|
+
workflow_item[:arguments].each do |argument|
|
147
|
+
success = apply_arguments(argument_map, argument)
|
148
|
+
fail 'Could not set arguments' unless success
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
@logger.info "Iterating over variables for workflow item '#{workflow_item[:name]}'"
|
153
|
+
if workflow_item[:variables]
|
154
|
+
workflow_item[:variables].each do |variable|
|
155
|
+
success = apply_variables(argument_map, variable)
|
156
|
+
fail 'Could not set variables' unless success
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
begin
|
161
|
+
@logger.info "Calling measure.run for '#{workflow_item[:name]}'"
|
162
|
+
if workflow_item[:measure_type] == 'RubyMeasure'
|
163
|
+
measure.run(@model, runner, argument_map)
|
164
|
+
elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
|
165
|
+
measure.run(@model_idf, runner, argument_map)
|
166
|
+
elsif workflow_item[:measure_type] == 'ReportingMeasure'
|
167
|
+
# This is silly, set the last model and last sqlfile instead of passing it into the measure.run method
|
168
|
+
runner.setLastOpenStudioModel(@model)
|
169
|
+
runner.setLastEnergyPlusSqlFilePath(@sql_filename)
|
170
|
+
|
171
|
+
measure.run(runner, argument_map)
|
172
|
+
end
|
173
|
+
@logger.info "Finished measure.run for '#{workflow_item[:name]}'"
|
174
|
+
rescue => e
|
175
|
+
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
176
|
+
raise log_message
|
177
|
+
end
|
178
|
+
|
179
|
+
begin
|
180
|
+
result = runner.result
|
181
|
+
@logger.info "Running of measure '#{workflow_item[:name]}' completed. Post-processing measure output"
|
182
|
+
|
183
|
+
@logger.info result.initialCondition.get.logMessage unless result.initialCondition.empty?
|
184
|
+
@logger.info result.finalCondition.get.logMessage unless result.finalCondition.empty?
|
185
|
+
|
186
|
+
result.warnings.each { |w| @logger.warn w.logMessage }
|
187
|
+
an_error = false
|
188
|
+
result.errors.each do |w|
|
189
|
+
@logger.error w.logMessage
|
190
|
+
an_error = true
|
191
|
+
end
|
192
|
+
fail "Measure #{measure_name} reported an error, check log" if an_error
|
193
|
+
result.info.each { |w| @logger.info w.logMessage }
|
194
|
+
rescue => e
|
195
|
+
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
196
|
+
raise log_message
|
197
|
+
end
|
198
|
+
|
199
|
+
begin
|
200
|
+
measure_attributes = JSON.parse(OpenStudio.toJSON(result.attributes), symbolize_names: true)
|
201
|
+
@output_attributes[workflow_item[:name].to_sym] = measure_attributes[:attributes]
|
202
|
+
rescue => e
|
203
|
+
log_message = "TODO: #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
204
|
+
@logger.warn log_message
|
205
|
+
end
|
206
|
+
ensure
|
207
|
+
Dir.chdir current_dir
|
208
|
+
@logger.info "Finished #{__method__} for #{workflow_item[:name]} in #{::Time.now - start_time} s"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def apply_measures(measure_type)
|
213
|
+
if @analysis_json[:analysis][:problem] && @analysis_json[:analysis][:problem][:workflow]
|
214
|
+
current_dir = Dir.pwd
|
215
|
+
begin
|
216
|
+
@logger.info "Applying measures for #{MEASURE_TYPES[measure_type]}"
|
217
|
+
@analysis_json[:analysis][:problem][:workflow].each do |wf|
|
218
|
+
next unless wf[:measure_type] == MEASURE_TYPES[measure_type]
|
219
|
+
|
220
|
+
apply_measure(wf)
|
221
|
+
end
|
222
|
+
ensure
|
223
|
+
Dir.chdir current_dir
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -18,19 +18,17 @@
|
|
18
18
|
######################################################################
|
19
19
|
|
20
20
|
class RunEnergyplus
|
21
|
-
|
22
21
|
# Initialize
|
23
22
|
# param directory: base directory where the simulation files are prepared
|
24
23
|
# param logger: logger object in which to write log messages
|
25
24
|
def initialize(directory, logger, adapter, options = {})
|
26
|
-
|
27
25
|
energyplus_path = nil
|
28
26
|
if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
29
27
|
energyplus_path = 'C:/EnergyPlus-8-1-0'
|
30
28
|
else
|
31
|
-
energyplus_path ='/usr/local/EnergyPlus-8-1-0'
|
29
|
+
energyplus_path = '/usr/local/EnergyPlus-8-1-0'
|
32
30
|
end
|
33
|
-
|
31
|
+
|
34
32
|
defaults = {
|
35
33
|
energyplus_path: energyplus_path
|
36
34
|
}
|
@@ -64,8 +62,8 @@ class RunEnergyplus
|
|
64
62
|
end
|
65
63
|
|
66
64
|
# Need to check the in.idf and in.osm
|
67
|
-
#FileUtils.copy(options[:osm], "#{@run_directory}/in.osm")
|
68
|
-
#FileUtils.copy(options[:idf], "#{@run_directory}/in.idf")
|
65
|
+
# FileUtils.copy(options[:osm], "#{@run_directory}/in.osm")
|
66
|
+
# FileUtils.copy(options[:idf], "#{@run_directory}/in.idf")
|
69
67
|
|
70
68
|
# can't create symlinks because the /vagrant mount is actually a windows mount
|
71
69
|
@logger.info "Copying EnergyPlus files to run directory: #{@run_directory}"
|
@@ -92,7 +90,7 @@ class RunEnergyplus
|
|
92
90
|
@logger.info "Starting simulation in run directory: #{Dir.pwd}"
|
93
91
|
|
94
92
|
File.open('stdout-expandobject', 'w') do |file|
|
95
|
-
IO.popen('ExpandObjects') do |io|
|
93
|
+
IO.popen('./ExpandObjects') do |io|
|
96
94
|
while (line = io.gets)
|
97
95
|
file << line
|
98
96
|
end
|
@@ -107,14 +105,13 @@ class RunEnergyplus
|
|
107
105
|
|
108
106
|
# create stdout
|
109
107
|
File.open('stdout-energyplus', 'w') do |file|
|
110
|
-
IO.popen('EnergyPlus') do |io|
|
108
|
+
IO.popen('./EnergyPlus') do |io|
|
111
109
|
while (line = io.gets)
|
112
110
|
file << line
|
113
111
|
end
|
114
112
|
end
|
115
113
|
end
|
116
|
-
|
117
|
-
rescue Exception => e
|
114
|
+
rescue => e
|
118
115
|
log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
119
116
|
@logger.error log_message
|
120
117
|
ensure
|
@@ -19,13 +19,14 @@
|
|
19
19
|
|
20
20
|
# TODO: I hear that measures can step on each other if not run in their own directory
|
21
21
|
class RunOpenstudio
|
22
|
-
|
22
|
+
# Mixin the MeasureApplication module to apply measures
|
23
|
+
include OpenStudio::Workflow::ApplyMeasures
|
23
24
|
|
24
25
|
# Initialize
|
25
26
|
# param directory: base directory where the simulation files are prepared
|
26
27
|
# param logger: logger object in which to write log messages
|
27
28
|
def initialize(directory, logger, adapter, options = {})
|
28
|
-
defaults = {format: 'hash', use_monthly_reports: false, analysis_root_path: '.'}
|
29
|
+
defaults = { format: 'hash', use_monthly_reports: false, analysis_root_path: '.' }
|
29
30
|
@options = defaults.merge(options)
|
30
31
|
@directory = directory
|
31
32
|
# TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
|
@@ -38,28 +39,26 @@ class RunOpenstudio
|
|
38
39
|
# initialize instance variables that are needed in the perform section
|
39
40
|
@model = nil
|
40
41
|
@model_idf = nil
|
42
|
+
@initial_weather_file = nil
|
43
|
+
@weather_file_path = nil
|
41
44
|
@analysis_json = nil
|
42
45
|
# TODO: rename datapoint_json to just datapoint
|
43
46
|
@datapoint_json = nil
|
44
47
|
@output_attributes = {}
|
45
48
|
@report_measures = []
|
46
|
-
@measure_type_lookup = {
|
47
|
-
:openstudio_measure => 'RubyMeasure',
|
48
|
-
:energyplus_measure => 'EnergyPlusMeasure',
|
49
|
-
:reporting_measure => 'ReportingMeasure'
|
50
|
-
}
|
51
49
|
end
|
52
50
|
|
53
51
|
def perform
|
54
52
|
@logger.info "Calling #{__method__} in the #{self.class} class"
|
55
53
|
@logger.info "Current directory is #{@directory}"
|
56
54
|
|
57
|
-
@logger.info
|
55
|
+
@logger.info 'Retrieving datapoint and problem'
|
58
56
|
@datapoint_json = @adapter.get_datapoint(@directory, @options)
|
59
57
|
@analysis_json = @adapter.get_problem(@directory, @options)
|
60
58
|
|
61
59
|
if @analysis_json && @analysis_json[:analysis]
|
62
60
|
@model = load_seed_model
|
61
|
+
|
63
62
|
load_weather_file
|
64
63
|
|
65
64
|
apply_measures(:openstudio_measure)
|
@@ -68,10 +67,19 @@ class RunOpenstudio
|
|
68
67
|
|
69
68
|
apply_measures(:energyplus_measure)
|
70
69
|
|
71
|
-
|
72
|
-
|
70
|
+
# check if the weather file has changed. This is cheesy for now. Should have a default measure that
|
71
|
+
# always sets the weather file so that it can be better controlled
|
72
|
+
updated_weather_file = get_weather_file_from_model
|
73
|
+
unless updated_weather_file == @initial_weather_file
|
74
|
+
# reset the result hash so the future processes know which weather file to run
|
75
|
+
@logger.info "Updating the weather file result to be #{updated_weather_file }"
|
76
|
+
@results[:weather_filename] = "#{@weather_file_path}/#{updated_weather_file}"
|
77
|
+
end
|
78
|
+
|
79
|
+
@logger.info 'Saving measure output attributes JSON'
|
80
|
+
File.open("#{@run_directory}/measure_attributes.json", 'w') do
|
73
81
|
|f| f << JSON.pretty_generate(@output_attributes)
|
74
|
-
|
82
|
+
end
|
75
83
|
end
|
76
84
|
|
77
85
|
save_osm_and_idf
|
@@ -147,7 +155,7 @@ class RunOpenstudio
|
|
147
155
|
fail "Seed model '#{baseline_model_path}' did not exist"
|
148
156
|
end
|
149
157
|
else
|
150
|
-
fail
|
158
|
+
fail 'No baseline/seed model found'
|
151
159
|
end
|
152
160
|
|
153
161
|
model
|
@@ -155,6 +163,8 @@ class RunOpenstudio
|
|
155
163
|
|
156
164
|
# Save the weather file to the instance variable
|
157
165
|
def load_weather_file
|
166
|
+
@initial_weather_file = get_weather_file_from_model
|
167
|
+
|
158
168
|
weather_filename = nil
|
159
169
|
if @options[:run_xml] && @options[:run_xml][:weather_filename]
|
160
170
|
if File.exist? @options[:run_xml][:weather_filename]
|
@@ -164,6 +174,7 @@ class RunOpenstudio
|
|
164
174
|
if @analysis_json[:analysis][:weather_file][:path]
|
165
175
|
weather_filename = File.expand_path(
|
166
176
|
File.join(@options[:analysis_root_path], @analysis_json[:analysis][:weather_file][:path]))
|
177
|
+
@weather_file_path = File.dirname(weather_filename)
|
167
178
|
else
|
168
179
|
fail 'No weather file path defined'
|
169
180
|
end
|
@@ -180,6 +191,20 @@ class RunOpenstudio
|
|
180
191
|
weather_filename
|
181
192
|
end
|
182
193
|
|
194
|
+
def get_weather_file_from_model
|
195
|
+
wf = nil
|
196
|
+
# grab the weather file out of the OSM if it exists
|
197
|
+
if @model.weatherFile.empty?
|
198
|
+
@logger.info 'No weather file in model'
|
199
|
+
else
|
200
|
+
# this is the weather file from the OSM model
|
201
|
+
wf = File.basename(@model.weatherFile.get.path.get.to_s)
|
202
|
+
@logger.info "Model weather file is #{wf}" # unless model.weatherFile.empty?
|
203
|
+
end
|
204
|
+
|
205
|
+
wf
|
206
|
+
end
|
207
|
+
|
183
208
|
# Forward translate to energyplus
|
184
209
|
def translate_to_energyplus
|
185
210
|
if @model_idf.nil?
|
@@ -194,151 +219,4 @@ class RunOpenstudio
|
|
194
219
|
@logger.info "Translate object to energyplus IDF took #{b.to_f - a.to_f}"
|
195
220
|
end
|
196
221
|
end
|
197
|
-
|
198
|
-
def apply_arguments(argument_map, argument)
|
199
|
-
success = true
|
200
|
-
|
201
|
-
if argument[:value]
|
202
|
-
@logger.info "Setting argument value #{argument[:name]} to #{argument[:value]}"
|
203
|
-
|
204
|
-
v = argument_map[argument[:name]]
|
205
|
-
fail 'Could not find argument map in measure' unless v
|
206
|
-
value_set = v.setValue(argument[:value])
|
207
|
-
fail "Could not set argument #{argument[:name]} of value #{argument[:value]} on model" unless value_set
|
208
|
-
argument_map[argument[:name]] = v.clone
|
209
|
-
else
|
210
|
-
fail "Value for argument '#{argument[:name]}' not set in argument list" if CRASH_ON_NO_WORKFLOW_VARIABLE
|
211
|
-
@logger.warn "Value for argument '#{argument[:name]}' not set in argument list therefore will use default"
|
212
|
-
#success = false
|
213
|
-
|
214
|
-
# TODO: what is the fail case (success = false?)
|
215
|
-
end
|
216
|
-
|
217
|
-
success
|
218
|
-
end
|
219
|
-
|
220
|
-
# Apply the variable values to the measure argument map object
|
221
|
-
def apply_variables(argument_map, variable)
|
222
|
-
success = true
|
223
|
-
|
224
|
-
# save the uuid of the variable
|
225
|
-
variable_uuid = variable[:uuid].to_sym
|
226
|
-
if variable[:argument]
|
227
|
-
variable_name = variable[:argument][:name]
|
228
|
-
|
229
|
-
# Get the value from the data point json that was set via R / Problem Formulation
|
230
|
-
if @datapoint_json[:data_point]
|
231
|
-
if @datapoint_json[:data_point][:set_variable_values]
|
232
|
-
if @datapoint_json[:data_point][:set_variable_values][variable_uuid]
|
233
|
-
@logger.info "Setting variable '#{variable_name}' to #{@datapoint_json[:data_point][:set_variable_values][variable_uuid]}"
|
234
|
-
v = argument_map[variable_name]
|
235
|
-
fail 'Could not find argument map in measure' unless v
|
236
|
-
variable_value = @datapoint_json[:data_point][:set_variable_values][variable_uuid]
|
237
|
-
value_set = v.setValue(variable_value)
|
238
|
-
fail "Could not set variable '#{variable_name}' of value #{variable_value} on model" unless value_set
|
239
|
-
argument_map[variable_name] = v.clone
|
240
|
-
else
|
241
|
-
fail "[ERROR] Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object" if CRASH_ON_NO_WORKFLOW_VARIABLE
|
242
|
-
@logger.warn "Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
|
243
|
-
# success = false
|
244
|
-
end
|
245
|
-
else
|
246
|
-
fail 'No block for set_variable_values in data point record'
|
247
|
-
end
|
248
|
-
else
|
249
|
-
fail 'No block for data_point in data_point record'
|
250
|
-
end
|
251
|
-
else
|
252
|
-
fail "Variable '#{variable_name}' is defined but no argument is present"
|
253
|
-
end
|
254
|
-
|
255
|
-
success
|
256
|
-
end
|
257
|
-
|
258
|
-
def apply_measure(workflow_item)
|
259
|
-
measure_path = workflow_item[:measure_definition_directory]
|
260
|
-
measure_name = workflow_item[:measure_definition_class_name]
|
261
|
-
|
262
|
-
@logger.info "Loading measure in relative path #{measure_path}"
|
263
|
-
measure_file_path = File.expand_path(
|
264
|
-
File.join(@options[:analysis_root_path], measure_path, 'measure.rb'))
|
265
|
-
fail "Measure file does not exist #{measure_name} in #{measure_file_path}" unless File.exist? measure_file_path
|
266
|
-
|
267
|
-
require measure_file_path
|
268
|
-
measure = Object.const_get(measure_name).new
|
269
|
-
runner = OpenStudio::Ruleset::OSRunner.new
|
270
|
-
result = nil
|
271
|
-
|
272
|
-
arguments = measure.arguments(@model)
|
273
|
-
|
274
|
-
# Create argument map and initialize all the arguments
|
275
|
-
argument_map = OpenStudio::Ruleset::OSArgumentMap.new
|
276
|
-
arguments.each do |v|
|
277
|
-
argument_map[v.name] = v.clone
|
278
|
-
end
|
279
|
-
|
280
|
-
@logger.info "Iterating over arguments for workflow item '#{workflow_item[:name]}'"
|
281
|
-
if workflow_item[:arguments]
|
282
|
-
workflow_item[:arguments].each do |argument|
|
283
|
-
success = apply_arguments(argument_map, argument)
|
284
|
-
fail "could not set arguments" unless success
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
@logger.info "Iterating over variables for workflow item '#{workflow_item[:name]}'"
|
289
|
-
if workflow_item[:variables]
|
290
|
-
workflow_item[:variables].each do |variable|
|
291
|
-
success = apply_variables(argument_map, variable)
|
292
|
-
fail "could not set variables" unless success
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
begin
|
297
|
-
if workflow_item[:measure_type] == 'RubyMeasure'
|
298
|
-
@logger.info "Running runner for '#{workflow_item[:name]}'"
|
299
|
-
measure.run(@model, runner, argument_map)
|
300
|
-
@logger.info "Finished runner for '#{workflow_item[:name]}'"
|
301
|
-
elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
|
302
|
-
measure.run(@model_idf, runner, argument_map)
|
303
|
-
elsif workflow_item[:measure_type] == 'ReportingMeasure'
|
304
|
-
report_measures << measure
|
305
|
-
end
|
306
|
-
rescue Exception => e
|
307
|
-
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
308
|
-
fail log_message
|
309
|
-
end
|
310
|
-
|
311
|
-
begin
|
312
|
-
result = runner.result
|
313
|
-
|
314
|
-
@logger.info result.initialCondition.get.logMessage unless result.initialCondition.empty?
|
315
|
-
@logger.info result.finalCondition.get.logMessage unless result.finalCondition.empty?
|
316
|
-
|
317
|
-
result.warnings.each { |w| @logger.info w.logMessage }
|
318
|
-
result.errors.each { |w| @logger.info w.logMessage }
|
319
|
-
result.info.each { |w| @logger.info w.logMessage }
|
320
|
-
rescue Exception => e
|
321
|
-
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
322
|
-
fail log_message
|
323
|
-
end
|
324
|
-
|
325
|
-
begin
|
326
|
-
measure_attributes = JSON.parse(OpenStudio::toJSON(result.attributes), symbolize_names: true)
|
327
|
-
@output_attributes[workflow_item[:name].to_sym] = measure_attributes[:attributes]
|
328
|
-
rescue Exception => e
|
329
|
-
log_message = "TODO: #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
330
|
-
@logger.warn log_message
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
def apply_measures(measure_type)
|
335
|
-
if @analysis_json[:analysis][:problem] && @analysis_json[:analysis][:problem][:workflow]
|
336
|
-
@logger.info "Applying measures for #{@measure_type_lookup[measure_type]}"
|
337
|
-
@analysis_json[:analysis][:problem][:workflow].each do |wf|
|
338
|
-
next unless wf[:measure_type] == @measure_type_lookup[measure_type]
|
339
|
-
|
340
|
-
apply_measure(wf)
|
341
|
-
end
|
342
|
-
end
|
343
|
-
end
|
344
222
|
end
|