openstudio-workflow 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,128 @@
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
+ class RunEnergyplus
21
+
22
+ # Initialize
23
+ # param directory: base directory where the simulation files are prepared
24
+ # param logger: logger object in which to write log messages
25
+ def initialize(directory, logger, adapter, options = {})
26
+
27
+ energyplus_path = nil
28
+ if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
29
+ energyplus_path = 'C:/EnergyPlus-8-1-0'
30
+ else
31
+ energyplus_path ='/usr/local/EnergyPlus-8-1-0'
32
+ end
33
+
34
+ defaults = {
35
+ energyplus_path: energyplus_path
36
+ }
37
+ @options = defaults.merge(options)
38
+
39
+ # TODO: use openstudio tool finder for this
40
+ @directory = directory
41
+ @run_directory = "#{@directory}/run"
42
+ @adapter = adapter
43
+ @logger = logger
44
+ @results = {}
45
+
46
+ @logger.info "#{self.class} passed the following options #{@options}"
47
+ end
48
+
49
+ def perform
50
+ @logger.info "Calling #{__method__} in the #{self.class} class"
51
+ @logger.info "Current directory is #{@directory}"
52
+
53
+ # Ensure that the directory is created (but it should already be at this point)
54
+ FileUtils.mkdir_p(@run_directory)
55
+
56
+ # verify that the OSM, IDF, and the Weather files are in the run directory as the 'in.*' format
57
+ if @options[:run_openstudio][:weather_filename] && File.exist?(@options[:run_openstudio][:weather_filename])
58
+ # verify that it is named in.epw
59
+ unless File.basename(@options[:run_openstudio][:weather_filename]).downcase == 'in.idf'
60
+ FileUtils.copy(@options[:run_openstudio][:weather_filename], "#{@run_directory}/in.epw")
61
+ end
62
+ else
63
+ fail "EPW file not found or not sent to #{self.class}"
64
+ end
65
+
66
+ # 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")
69
+
70
+ # can't create symlinks because the /vagrant mount is actually a windows mount
71
+ @logger.info "Copying EnergyPlus files to run directory: #{@run_directory}"
72
+ FileUtils.copy("#{@options[:energyplus_path]}/libbcvtb.so", "#{@run_directory}/libbcvtb.so")
73
+ FileUtils.copy("#{@options[:energyplus_path]}/libepexpat.so", "#{@run_directory}/libepexpat.so")
74
+ FileUtils.copy("#{@options[:energyplus_path]}/libepfmiimport.so", "#{@run_directory}/libepfmiimport.so")
75
+ FileUtils.copy("#{@options[:energyplus_path]}/libDElight.so", "#{@run_directory}/libDElight.so")
76
+ FileUtils.copy("#{@options[:energyplus_path]}/libDElight.so", "#{@run_directory}/libDElight.so")
77
+ FileUtils.copy("#{@options[:energyplus_path]}/ExpandObjects", "#{@run_directory}/ExpandObjects")
78
+ FileUtils.copy("#{@options[:energyplus_path]}/EnergyPlus", "#{@run_directory}/EnergyPlus")
79
+ FileUtils.copy("#{@options[:energyplus_path]}/Energy+.idd", "#{@run_directory}/Energy+.idd")
80
+
81
+ @results = call_energyplus
82
+
83
+ @results
84
+ end
85
+
86
+ private
87
+
88
+ def call_energyplus
89
+ begin
90
+ current_dir = Dir.pwd
91
+ Dir.chdir(@run_directory)
92
+ @logger.info "Starting simulation in run directory: #{Dir.pwd}"
93
+
94
+ File.open('stdout-expandobject', 'w') do |file|
95
+ IO.popen('ExpandObjects') do |io|
96
+ while (line = io.gets)
97
+ file << line
98
+ end
99
+ end
100
+ end
101
+
102
+ # Check if expand objects did anythying
103
+ if File.exist? 'expanded.idf'
104
+ FileUtils.mv('in.idf', 'pre-expand.idf', force: true) if File.exist?('in.idf')
105
+ FileUtils.mv('expanded.idf', 'in.idf', force: true)
106
+ end
107
+
108
+ # create stdout
109
+ File.open('stdout-energyplus', 'w') do |file|
110
+ IO.popen('EnergyPlus') do |io|
111
+ while (line = io.gets)
112
+ file << line
113
+ end
114
+ end
115
+ end
116
+
117
+ rescue Exception => e
118
+ log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
119
+ @logger.error log_message
120
+ ensure
121
+ Dir.chdir(current_dir)
122
+ @logger.info 'EnergyPlus Completed'
123
+ end
124
+
125
+ # TODO: get list of all the files that are generated and return
126
+ {}
127
+ end
128
+ end
@@ -0,0 +1,218 @@
1
+ Output:Table:Monthly,
2
+ Building Energy Performance - Electricity, !- Name
3
+ 2, !- Digits After Decimal
4
+ InteriorLights:Electricity, !- Variable or Meter 1 Name
5
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
6
+ ExteriorLights:Electricity, !- Variable or Meter 2 Name
7
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
8
+ InteriorEquipment:Electricity, !- Variable or Meter 3 Name
9
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
10
+ ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
11
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
12
+ Fans:Electricity, !- Variable or Meter 5 Name
13
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
14
+ Pumps:Electricity, !- Variable or Meter 6 Name
15
+ SumOrAverage, !- Aggregation Type for Variable or Meter 6
16
+ Heating:Electricity, !- Variable or Meter 7 Name
17
+ SumOrAverage, !- Aggregation Type for Variable or Meter 7
18
+ Cooling:Electricity, !- Variable or Meter 8 Name
19
+ SumOrAverage, !- Aggregation Type for Variable or Meter 8
20
+ HeatRejection:Electricity, !- Variable or Meter 9 Name
21
+ SumOrAverage, !- Aggregation Type for Variable or Meter 9
22
+ Humidifier:Electricity, !- Variable or Meter 10 Name
23
+ SumOrAverage, !- Aggregation Type for Variable or Meter 10
24
+ HeatRecovery:Electricity,!- Variable or Meter 11 Name
25
+ SumOrAverage, !- Aggregation Type for Variable or Meter 11
26
+ WaterSystems:Electricity,!- Variable or Meter 12 Name
27
+ SumOrAverage, !- Aggregation Type for Variable or Meter 12
28
+ Cogeneration:Electricity,!- Variable or Meter 13 Name
29
+ SumOrAverage, !- Aggregation Type for Variable or Meter 13
30
+ Refrigeration:Electricity,!- Variable or Meter 14 Name
31
+ SumOrAverage; !- Aggregation Type for Variable or Meter 14
32
+ Output:Table:Monthly,
33
+ Building Energy Performance - Natural Gas, !- Name
34
+ 2, !- Digits After Decimal
35
+ InteriorEquipment:Gas, !- Variable or Meter 1 Name
36
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
37
+ ExteriorEquipment:Gas, !- Variable or Meter 2 Name
38
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
39
+ Heating:Gas, !- Variable or Meter 3 Name
40
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
41
+ Cooling:Gas, !- Variable or Meter 4 Name
42
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
43
+ WaterSystems:Gas, !- Variable or Meter 5 Name
44
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
45
+ Cogeneration:Gas, !- Variable or Meter 6 Name
46
+ SumOrAverage; !- Aggregation Type for Variable or Meter 6
47
+ Output:Table:Monthly,
48
+ Building Energy Performance - District Heating, !- Name
49
+ 2, !- Digits After Decimal
50
+ InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
51
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
52
+ ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
53
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
54
+ InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
55
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
56
+ ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
57
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
58
+ Fans:DistrictHeating, !- Variable or Meter 5 Name
59
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
60
+ Pumps:DistrictHeating, !- Variable or Meter 6 Name
61
+ SumOrAverage, !- Aggregation Type for Variable or Meter 6
62
+ Heating:DistrictHeating, !- Variable or Meter 7 Name
63
+ SumOrAverage, !- Aggregation Type for Variable or Meter 7
64
+ Cooling:DistrictHeating, !- Variable or Meter 8 Name
65
+ SumOrAverage, !- Aggregation Type for Variable or Meter 8
66
+ HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
67
+ SumOrAverage, !- Aggregation Type for Variable or Meter 9
68
+ Humidifier:DistrictHeating, !- Variable or Meter 10 Name
69
+ SumOrAverage, !- Aggregation Type for Variable or Meter 10
70
+ HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
71
+ SumOrAverage, !- Aggregation Type for Variable or Meter 11
72
+ WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
73
+ SumOrAverage, !- Aggregation Type for Variable or Meter 12
74
+ Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
75
+ SumOrAverage; !- Aggregation Type for Variable or Meter 13
76
+ Output:Table:Monthly,
77
+ Building Energy Performance - District Cooling, !- Name
78
+ 2, !- Digits After Decimal
79
+ InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
80
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
81
+ ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
82
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
83
+ InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
84
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
85
+ ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
86
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
87
+ Fans:DistrictCooling, !- Variable or Meter 5 Name
88
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
89
+ Pumps:DistrictCooling, !- Variable or Meter 6 Name
90
+ SumOrAverage, !- Aggregation Type for Variable or Meter 6
91
+ Heating:DistrictCooling, !- Variable or Meter 7 Name
92
+ SumOrAverage, !- Aggregation Type for Variable or Meter 7
93
+ Cooling:DistrictCooling, !- Variable or Meter 8 Name
94
+ SumOrAverage, !- Aggregation Type for Variable or Meter 8
95
+ HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
96
+ SumOrAverage, !- Aggregation Type for Variable or Meter 9
97
+ Humidifier:DistrictCooling, !- Variable or Meter 10 Name
98
+ SumOrAverage, !- Aggregation Type for Variable or Meter 10
99
+ HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
100
+ SumOrAverage, !- Aggregation Type for Variable or Meter 11
101
+ WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
102
+ SumOrAverage, !- Aggregation Type for Variable or Meter 12
103
+ Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
104
+ SumOrAverage; !- Aggregation Type for Variable or Meter 13
105
+ Output:Table:Monthly,
106
+ Building Energy Performance - Electricity Peak Demand, !- Name
107
+ 2, !- Digits After Decimal
108
+ Electricity:Facility, !- Variable or Meter 1 Name
109
+ Maximum, !- Aggregation Type for Variable or Meter 1
110
+ InteriorLights:Electricity, !- Variable or Meter 1 Name
111
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
112
+ ExteriorLights:Electricity, !- Variable or Meter 2 Name
113
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
114
+ InteriorEquipment:Electricity, !- Variable or Meter 3 Name
115
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
116
+ ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
117
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
118
+ Fans:Electricity, !- Variable or Meter 5 Name
119
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
120
+ Pumps:Electricity, !- Variable or Meter 6 Name
121
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
122
+ Heating:Electricity, !- Variable or Meter 7 Name
123
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
124
+ Cooling:Electricity, !- Variable or Meter 8 Name
125
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
126
+ HeatRejection:Electricity, !- Variable or Meter 9 Name
127
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
128
+ Humidifier:Electricity, !- Variable or Meter 10 Name
129
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
130
+ HeatRecovery:Electricity,!- Variable or Meter 11 Name
131
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
132
+ WaterSystems:Electricity,!- Variable or Meter 12 Name
133
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
134
+ Cogeneration:Electricity,!- Variable or Meter 13 Name
135
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
136
+ Output:Table:Monthly,
137
+ Building Energy Performance - Natural Gas Peak Demand, !- Name
138
+ 2, !- Digits After Decimal
139
+ Gas:Facility, !- Variable or Meter 1 Name
140
+ Maximum, !- Aggregation Type for Variable or Meter 1
141
+ InteriorEquipment:Gas, !- Variable or Meter 1 Name
142
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
143
+ ExteriorEquipment:Gas, !- Variable or Meter 2 Name
144
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
145
+ Heating:Gas, !- Variable or Meter 3 Name
146
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
147
+ Cooling:Gas, !- Variable or Meter 4 Name
148
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
149
+ WaterSystems:Gas, !- Variable or Meter 5 Name
150
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
151
+ Cogeneration:Gas, !- Variable or Meter 6 Name
152
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 6
153
+ Output:Table:Monthly,
154
+ Building Energy Performance - District Heating Peak Demand, !- Name
155
+ 2, !- Digits After Decimal
156
+ DistrictHeating:Facility, !- Variable or Meter 1 Name
157
+ Maximum, !- Aggregation Type for Variable or Meter 1
158
+ InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
159
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
160
+ ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
161
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
162
+ InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
163
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
164
+ ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
165
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
166
+ Fans:DistrictHeating, !- Variable or Meter 5 Name
167
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
168
+ Pumps:DistrictHeating, !- Variable or Meter 6 Name
169
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
170
+ Heating:DistrictHeating, !- Variable or Meter 7 Name
171
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
172
+ Cooling:DistrictHeating, !- Variable or Meter 8 Name
173
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
174
+ HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
175
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
176
+ Humidifier:DistrictHeating, !- Variable or Meter 10 Name
177
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
178
+ HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
179
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
180
+ WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
181
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
182
+ Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
183
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
184
+ Output:Table:Monthly,
185
+ Building Energy Performance - District Cooling Peak Demand, !- Name
186
+ 2, !- Digits After Decimal
187
+ DistrictCooling:Facility, !- Variable or Meter 1 Name
188
+ Maximum, !- Aggregation Type for Variable or Meter 1
189
+ InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
190
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
191
+ ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
192
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
193
+ InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
194
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
195
+ ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
196
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
197
+ Fans:DistrictCooling, !- Variable or Meter 5 Name
198
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
199
+ Pumps:DistrictCooling, !- Variable or Meter 6 Name
200
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
201
+ Heating:DistrictCooling, !- Variable or Meter 7 Name
202
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
203
+ Cooling:DistrictCooling, !- Variable or Meter 8 Name
204
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
205
+ HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
206
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
207
+ Humidifier:DistrictCooling, !- Variable or Meter 10 Name
208
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
209
+ HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
210
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
211
+ WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
212
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
213
+ Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
214
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
215
+ Output:Meter,Electricity:Facility,Timestep; !- [J]
216
+ Output:Meter,Gas:Facility,Timestep; !- [J]
217
+ Output:Meter,DistrictCooling:Facility,Timestep; !- [J]
218
+ Output:Meter,DistrictHeating:Facility,Timestep; !- [J]
@@ -0,0 +1,344 @@
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
+ # TODO: I hear that measures can step on each other if not run in their own directory
21
+ class RunOpenstudio
22
+ CRASH_ON_NO_WORKFLOW_VARIABLE = false
23
+
24
+ # Initialize
25
+ # param directory: base directory where the simulation files are prepared
26
+ # param logger: logger object in which to write log messages
27
+ def initialize(directory, logger, adapter, options = {})
28
+ defaults = {format: 'hash', use_monthly_reports: false, analysis_root_path: '.'}
29
+ @options = defaults.merge(options)
30
+ @directory = directory
31
+ # TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
32
+ @run_directory = "#{@directory}/run"
33
+ @adapter = adapter
34
+ @results = {}
35
+ @logger = logger
36
+ @logger.info "#{self.class} passed the following options #{@options}"
37
+
38
+ # initialize instance variables that are needed in the perform section
39
+ @model = nil
40
+ @model_idf = nil
41
+ @analysis_json = nil
42
+ # TODO: rename datapoint_json to just datapoint
43
+ @datapoint_json = nil
44
+ @output_attributes = {}
45
+ @report_measures = []
46
+ @measure_type_lookup = {
47
+ :openstudio_measure => 'RubyMeasure',
48
+ :energyplus_measure => 'EnergyPlusMeasure',
49
+ :reporting_measure => 'ReportingMeasure'
50
+ }
51
+ end
52
+
53
+ def perform
54
+ @logger.info "Calling #{__method__} in the #{self.class} class"
55
+ @logger.info "Current directory is #{@directory}"
56
+
57
+ @logger.info "Retrieving datapoint and problem"
58
+ @datapoint_json = @adapter.get_datapoint(@directory, @options)
59
+ @analysis_json = @adapter.get_problem(@directory, @options)
60
+
61
+ if @analysis_json && @analysis_json[:analysis]
62
+ @model = load_seed_model
63
+ load_weather_file
64
+
65
+ apply_measures(:openstudio_measure)
66
+
67
+ translate_to_energyplus
68
+
69
+ apply_measures(:energyplus_measure)
70
+
71
+ @logger.info "Measure output attributes JSON is #{@output_attributes}"
72
+ File.open("#{@run_directory}/measure_attributes.json", 'w') {
73
+ |f| f << JSON.pretty_generate(@output_attributes)
74
+ }
75
+ end
76
+
77
+ save_osm_and_idf
78
+
79
+ @results
80
+ end
81
+
82
+ private
83
+
84
+ def save_osm_and_idf
85
+ # save the data
86
+ a = Time.now
87
+ osm_filename = "#{@run_directory}/out_raw.osm"
88
+ File.open(osm_filename, 'w') { |f| f << @model.to_s }
89
+ b = Time.now
90
+ @logger.info "Ruby write took #{b.to_f - a.to_f}"
91
+
92
+ a = Time.now
93
+ osm_filename = "#{@run_directory}/in.osm"
94
+ @model.save(OpenStudio::Path.new(osm_filename), true)
95
+ b = Time.now
96
+ @logger.info "OpenStudio write took #{b.to_f - a.to_f}"
97
+
98
+ # Run EnergyPlus using run energyplus script
99
+ idf_filename = "#{@run_directory}/in.idf"
100
+ File.open(idf_filename, 'w') { |f| f << @model_idf.to_s }
101
+
102
+ # TODO: convert this to an OpenStudio method instead of substituting the data as text
103
+ if @options[:use_monthly_reports]
104
+ @logger.info 'Adding monthly reports to EnergyPlus IDF'
105
+ to_append = File.read(File.join(File.dirname(__FILE__), 'monthly_report.idf'))
106
+ File.open(idf_filename, 'a') do |handle|
107
+ handle.puts to_append
108
+ end
109
+ end
110
+
111
+ @results[:osm] = File.expand_path(osm_filename)
112
+ @results[:idf] = File.expand_path(idf_filename)
113
+ end
114
+
115
+ def load_seed_model
116
+ model = nil
117
+ @logger.info 'Loading seed model'
118
+
119
+ baseline_model_path = nil
120
+ # Unique case to use the previous generated OSM as the seed
121
+ if @options[:run_xml] && @options[:run_xml][:osm_filename]
122
+ if File.exist? @options[:run_xml][:osm_filename]
123
+ baseline_model_path = @options[:run_xml][:osm_filename]
124
+ end
125
+ elsif @analysis_json[:analysis][:seed]
126
+ @logger.info "Seed model is #{@analysis_json[:analysis][:seed]}"
127
+ if @analysis_json[:analysis][:seed][:path]
128
+
129
+ # assume that the seed model has been placed in the directory
130
+ baseline_model_path = File.expand_path(
131
+ File.join(@options[:analysis_root_path], @analysis_json[:analysis][:seed][:path]))
132
+ else
133
+ fail 'No seed model path in JSON defined'
134
+ end
135
+ else
136
+ fail 'No seed model block'
137
+ end
138
+
139
+ if baseline_model_path
140
+ if File.exist? baseline_model_path
141
+ @logger.info "Reading in baseline model #{baseline_model_path}"
142
+ translator = OpenStudio::OSVersion::VersionTranslator.new
143
+ model = translator.loadModel(baseline_model_path)
144
+ fail 'OpenStudio model is empty or could not be loaded' if model.empty?
145
+ model = model.get
146
+ else
147
+ fail "Seed model '#{baseline_model_path}' did not exist"
148
+ end
149
+ else
150
+ fail "No baseline/seed model found"
151
+ end
152
+
153
+ model
154
+ end
155
+
156
+ # Save the weather file to the instance variable
157
+ def load_weather_file
158
+ weather_filename = nil
159
+ if @options[:run_xml] && @options[:run_xml][:weather_filename]
160
+ if File.exist? @options[:run_xml][:weather_filename]
161
+ weather_filename = @options[:run_xml][:weather_filename]
162
+ end
163
+ elsif @analysis_json[:analysis][:weather_file]
164
+ if @analysis_json[:analysis][:weather_file][:path]
165
+ weather_filename = File.expand_path(
166
+ File.join(@options[:analysis_root_path], @analysis_json[:analysis][:weather_file][:path]))
167
+ else
168
+ fail 'No weather file path defined'
169
+ end
170
+ else
171
+ fail 'No weather file block defined'
172
+ end
173
+
174
+ unless File.exist?(weather_filename)
175
+ fail "Could not find weather file for simulation #{weather_filename}"
176
+ end
177
+
178
+ @results[:weather_filename] = weather_filename
179
+
180
+ weather_filename
181
+ end
182
+
183
+ # Forward translate to energyplus
184
+ def translate_to_energyplus
185
+ if @model_idf.nil?
186
+ @logger.info 'Translate object to EnergyPlus IDF in Prep for EnergyPlus Measure'
187
+ a = Time.now
188
+ # ensure objects exist for reporting purposes
189
+ @model.getFacility
190
+ @model.getBuilding
191
+ forward_translator = OpenStudio::EnergyPlus::ForwardTranslator.new
192
+ @model_idf = forward_translator.translateModel(@model)
193
+ b = Time.now
194
+ @logger.info "Translate object to energyplus IDF took #{b.to_f - a.to_f}"
195
+ end
196
+ 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
+ end