openstudio-workflow 1.0.0.pat1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +16 -68
  4. data/Rakefile +9 -9
  5. data/bin/openstudio_cli +786 -0
  6. data/lib/openstudio/workflow/adapters/input/local.rb +97 -0
  7. data/lib/openstudio/workflow/adapters/output/local.rb +90 -0
  8. data/lib/openstudio/workflow/adapters/output/socket.rb +70 -0
  9. data/lib/openstudio/workflow/{jobs/run_preflight/run_preflight.rb → adapters/output/web.rb} +37 -19
  10. data/lib/openstudio/workflow/{adapter.rb → adapters/output_adapter.rb} +53 -51
  11. data/lib/openstudio/workflow/job.rb +22 -0
  12. data/lib/openstudio/workflow/jobs/{run_energyplus → resources}/monthly_report.idf +0 -0
  13. data/lib/openstudio/workflow/jobs/run_energyplus.rb +49 -0
  14. data/lib/openstudio/workflow/jobs/run_ep_measures.rb +55 -0
  15. data/lib/openstudio/workflow/jobs/run_initialization.rb +136 -0
  16. data/lib/openstudio/workflow/jobs/run_os_measures.rb +59 -0
  17. data/lib/openstudio/workflow/jobs/run_postprocess.rb +53 -0
  18. data/lib/openstudio/workflow/jobs/run_preprocess.rb +81 -0
  19. data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +86 -0
  20. data/lib/openstudio/workflow/jobs/run_translation.rb +49 -0
  21. data/lib/openstudio/workflow/multi_delegator.rb +1 -3
  22. data/lib/openstudio/workflow/registry.rb +137 -0
  23. data/lib/openstudio/workflow/run.rb +182 -221
  24. data/lib/openstudio/workflow/time_logger.rb +1 -1
  25. data/lib/openstudio/workflow/util/energyplus.rb +564 -0
  26. data/lib/openstudio/workflow/util/io.rb +33 -0
  27. data/lib/openstudio/workflow/util/measure.rb +520 -0
  28. data/lib/openstudio/workflow/util/model.rb +100 -0
  29. data/lib/openstudio/workflow/util/post_process.rb +177 -0
  30. data/lib/openstudio/workflow/util/weather_file.rb +108 -0
  31. data/lib/openstudio/workflow/util.rb +14 -0
  32. data/lib/openstudio/workflow/version.rb +1 -1
  33. data/lib/openstudio/workflow_json.rb +399 -0
  34. data/lib/openstudio/workflow_runner.rb +213 -0
  35. data/lib/openstudio-workflow.rb +13 -118
  36. metadata +45 -85
  37. data/lib/openstudio/extended_runner.rb +0 -105
  38. data/lib/openstudio/workflow/adapters/local.rb +0 -101
  39. data/lib/openstudio/workflow/adapters/mongo.rb +0 -227
  40. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +0 -253
  41. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +0 -314
  42. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +0 -230
  43. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +0 -110
  44. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +0 -471
  45. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +0 -247
  46. data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +0 -279
@@ -1,314 +0,0 @@
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
- ENERGYPLUS_REGEX = /^energyplus\D{0,4}$/i
22
- EXPAND_OBJECTS_REGEX = /^expandobjects\D{0,4}$/i
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, time_logger, adapter, workflow_arguments, past_results, options = {})
28
- @logger = logger
29
-
30
- energyplus_path = find_energyplus
31
- defaults = {
32
- energyplus_path: energyplus_path
33
- }
34
- @options = defaults.merge(options)
35
-
36
- # TODO: use openstudio tool finder for this
37
- @directory = directory
38
- @run_directory = "#{@directory}/run"
39
- @adapter = adapter
40
- @time_logger = time_logger
41
- @workflow_arguments = workflow_arguments
42
- @past_results = past_results
43
- @results = {}
44
-
45
- # container for storing the energyplus files there were copied into the local directory. These will be
46
- # removed at the end of the simulation.
47
- @energyplus_files = []
48
- @energyplus_exe = nil
49
- @expand_objects_exe = nil
50
-
51
- @logger.info "#{self.class} passed the following options #{@options}"
52
- end
53
-
54
- def perform
55
- @logger.info "Calling #{__method__} in the #{self.class} class"
56
- @logger.info "Current directory is #{@directory}"
57
-
58
- # Ensure that the directory is created (but it should already be at this point)
59
- FileUtils.mkdir_p(@run_directory)
60
-
61
- # if the weather file is already in the directory, then just use that weather file
62
- weather_file_name = nil
63
- weather_files = Dir["#{@directory}/*.epw"]
64
- if weather_files.size > 1
65
- @logger.info 'Multiple weather files in the directory. Will rely on the weather file name in the openstudio model'
66
- elsif weather_files.size == 1
67
- weather_file_name = weather_files.first
68
- end
69
-
70
- # verify that the OSM, IDF, and the Weather files are in the run directory as the 'in.*' format
71
- if !weather_file_name &&
72
- @options[:run_openstudio] &&
73
- @options[:run_openstudio][:weather_filename] &&
74
- File.exist?(@options[:run_openstudio][:weather_filename])
75
- weather_file_name = @options[:run_openstudio][:weather_filename]
76
- end
77
-
78
- if weather_file_name
79
- # verify that it is named in.epw
80
- @logger.info "Weather file for EnergyPlus simulation is #{weather_file_name}"
81
- FileUtils.copy(weather_file_name, "#{@run_directory}/in.epw")
82
- else
83
- fail "EPW file not found or not sent to #{self.class}"
84
- end
85
-
86
- # check if the run folder has an IDF. If not then check if the parent folder does.
87
- idf_file_name = nil
88
- if File.exist?("#{@run_directory}/in.idf")
89
- @logger.info 'IDF (in.idf) already exists in the run directory'
90
- else
91
- # glob for idf at the directory level
92
- idfs = Dir["#{@directory}/*.idf"]
93
- if idfs.size > 1
94
- @logger.info 'Multiple IDF files in the directory. Cannot continue'
95
- elsif idfs.size == 1
96
- idf_file_name = idfs.first
97
- end
98
- end
99
-
100
- # Need to check the in.idf and in.osm
101
- # FileUtils.copy(options[:osm], "#{@run_directory}/in.osm")
102
- if idf_file_name
103
- FileUtils.copy(idf_file_name, "#{@run_directory}/in.idf")
104
- end
105
-
106
- # can't create symlinks because the /vagrant mount is actually a windows mount
107
- @time_logger.start('Copying EnergyPlus files')
108
- prepare_energyplus_dir
109
- @time_logger.stop('Copying EnergyPlus files')
110
-
111
- @time_logger.start('Running EnergyPlus Preprocess Script')
112
- energyplus_preprocess("#{@run_directory}/in.idf")
113
- @time_logger.start('Running EnergyPlus Preprocess Script')
114
-
115
- @time_logger.start('Running EnergyPlus')
116
- @results = call_energyplus
117
- @time_logger.stop('Running EnergyPlus')
118
-
119
- @results
120
- end
121
-
122
- private
123
-
124
- def find_energyplus
125
- if ENV['ENERGYPLUSDIR']
126
- return ENV['ENERGYPLUSDIR']
127
- # TODO: check if method exists! first
128
- elsif OpenStudio.respond_to? :getEnergyPlusDirectory
129
- return OpenStudio.getEnergyPlusDirectory.to_s
130
- elsif ENV['RUBYLIB'] =~ /OpenStudio/
131
- warn 'Finding EnergyPlus by RUBYLIB parsing will not be supported in the near future. Use either ENERGYPLUSDIR'\
132
- 'env variable or a newer OpenStudio version that has the getEnergyPlusDirectory method'
133
- path = ENV['RUBYLIB'].split(':')
134
- path = File.dirname(path.find { |p| p =~ /OpenStudio/ })
135
- # Grab the version out of the openstudio path
136
- path += '/sharedresources/EnergyPlus-8-3-0'
137
-
138
- return path
139
- else
140
- if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
141
- return 'C:/EnergyPlus-8-3-0'
142
- else
143
- return '/usr/local/EnergyPlus-8-3-0'
144
- end
145
- end
146
- end
147
-
148
- def clean_directory
149
- @logger.info 'Removing any copied EnergyPlus files'
150
- @energyplus_files.each do |file|
151
- if File.exist? file
152
- FileUtils.rm_f file
153
- end
154
- end
155
-
156
- paths_to_rm = []
157
- paths_to_rm << "#{@run_directory}/packaged_measures"
158
- paths_to_rm << "#{@run_directory}/Energy+.ini"
159
- paths_to_rm.each { |p| FileUtils.rm_rf(p) if File.exist?(p) }
160
- end
161
-
162
- # Prepare the directory to run EnergyPlus. In EnergyPlus < 8.2, we have to copy all the files into the directory.
163
- #
164
- # @return [Boolean] Returns true is there is more than one file copied
165
- def prepare_energyplus_dir
166
- @logger.info "Copying EnergyPlus files to run directory: #{@run_directory}"
167
- Dir["#{@options[:energyplus_path]}/*"].each do |file|
168
- next if File.directory? file
169
- next if File.extname(file).downcase =~ /.pdf|.app|.html|.gif|.txt|.xlsx/
170
-
171
- dest_file = "#{@run_directory}/#{File.basename(file)}"
172
- @energyplus_files << dest_file
173
-
174
- @energyplus_exe = File.basename(dest_file) if File.basename(dest_file) =~ ENERGYPLUS_REGEX
175
- @expand_objects_exe = File.basename(dest_file) if File.basename(dest_file) =~ EXPAND_OBJECTS_REGEX
176
- FileUtils.copy file, dest_file
177
- end
178
-
179
- fail "Could not find EnergyPlus executable in #{@options[:energyplus_path]}" unless @energyplus_exe
180
- fail "Could not find ExpandObjects executable in #{@options[:energyplus_path]}" unless @expand_objects_exe
181
-
182
- @energyplus_files.size > 0
183
- end
184
-
185
- def call_energyplus
186
- begin
187
- current_dir = Dir.pwd
188
- Dir.chdir(@run_directory)
189
- @logger.info "Starting simulation in run directory: #{Dir.pwd}"
190
-
191
- File.open('stdout-expandobject', 'w') do |file|
192
- IO.popen("./#{@expand_objects_exe}") do |io|
193
- while (line = io.gets)
194
- file << line
195
- end
196
- end
197
- end
198
-
199
- # Check if expand objects did anythying
200
- if File.exist? 'expanded.idf'
201
- FileUtils.mv('in.idf', 'pre-expand.idf', force: true) if File.exist?('in.idf')
202
- FileUtils.mv('expanded.idf', 'in.idf', force: true)
203
- end
204
-
205
- # create stdout
206
- File.open('stdout-energyplus', 'w') do |file|
207
- IO.popen("./#{@energyplus_exe} 2>&1") do |io|
208
- while (line = io.gets)
209
- file << line
210
- end
211
- end
212
- end
213
- r = $?
214
-
215
- @logger.info "EnergyPlus returned '#{r}'"
216
- unless r == 0
217
- @logger.warn 'EnergyPlus returned a non-zero exit code. Check the stdout-energyplus log.'
218
- end
219
-
220
- if File.exist? 'eplusout.end'
221
- f = File.read('eplusout.end').force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
222
- warnings_count = f[/(\d*).Warning/, 1]
223
- error_count = f[/(\d*).Severe.Errors/, 1]
224
- @logger.info "EnergyPlus finished with #{warnings_count} warnings and #{error_count} severe errors"
225
- if f =~ /EnergyPlus Terminated--Fatal Error Detected/
226
- fail 'EnergyPlus Terminated with a Fatal Error. Check eplusout.err log.'
227
- end
228
- else
229
- fail 'EnergyPlus failed and did not create an eplusout.end file. Check the stdout-energyplus log.'
230
- end
231
-
232
- if File.exist? 'eplusout.err'
233
- eplus_err = File.read('eplusout.err').force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
234
- if eplus_err =~ /EnergyPlus Terminated--Fatal Error Detected/
235
- fail 'EnergyPlus Terminated with a Fatal Error. Check eplusout.err log.'
236
- end
237
- end
238
- rescue => e
239
- log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
240
- @logger.error log_message
241
- raise log_message
242
- ensure
243
- @logger.info "Ensuring 'clean' directory"
244
- clean_directory
245
-
246
- Dir.chdir(current_dir)
247
- @logger.info 'EnergyPlus Completed'
248
- end
249
-
250
- {}
251
- end
252
-
253
- # Run this code before running energyplus to make sure the reporting variables are setup correctly
254
- def energyplus_preprocess(idf_filename)
255
- @logger.info 'Running EnergyPlus Preprocess'
256
-
257
- fail "Could not find IDF file in run directory (#{idf_filename})" unless File.exist? idf_filename
258
-
259
- new_objects = []
260
- needs_monthlyoutput = false
261
-
262
- idf = OpenStudio::IdfFile.load(idf_filename).get
263
- # save the pre-preprocess file
264
- File.open("#{File.dirname(idf_filename)}/pre-preprocess.idf", 'w') { |f| f << idf.to_s }
265
-
266
- needs_sqlobj = idf.getObjectsByType('Output:SQLite'.to_IddObjectType).empty?
267
-
268
- needs_monthlyoutput = idf.getObjectsByName('Building Energy Performance - Natural Gas').empty? ||
269
- idf.getObjectsByName('Building Energy Performance - Electricity').empty? ||
270
- idf.getObjectsByName('Building Energy Performance - District Heating').empty? ||
271
- idf.getObjectsByName('Building Energy Performance - District Cooling').empty?
272
-
273
- # this is a workaround for issue #1699 -- remove when 1699 is closed.
274
- new_objects << 'Output:Variable,*,Zone Air Temperature,Hourly;'
275
- new_objects << 'Output:Variable,*,Zone Air Relative Humidity,Daily;'
276
- new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Monthly;'
277
- new_objects << 'Output:Variable,*,Site Outdoor Air Wetbulb Temperature,Timestep;'
278
-
279
- if needs_sqlobj
280
- @logger.info 'Adding SQL Output to IDF'
281
- new_objects << '
282
- Output:SQLite,
283
- SimpleAndTabular; ! Option Type
284
- '
285
- end
286
-
287
- if needs_monthlyoutput
288
- monthly_report_idf = File.join(File.dirname(__FILE__), 'monthly_report.idf')
289
- idf_file = OpenStudio::IdfFile.load(File.read(monthly_report_idf), 'EnergyPlus'.to_IddFileType).get
290
- idf.addObjects(idf_file.objects)
291
- end
292
-
293
- # These are supposedly needed for the calibration report
294
- new_objects << 'Output:Meter:MeterFileOnly,Gas:Facility,Daily;'
295
- new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Timestep;'
296
- new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Daily;'
297
-
298
- # Always add in the timestep facility meters
299
- new_objects << 'Output:Meter,Electricity:Facility,Timestep;'
300
- new_objects << 'Output:Meter,Gas:Facility,Timestep;'
301
- new_objects << 'Output:Meter,DistrictCooling:Facility,Timestep;'
302
- new_objects << 'Output:Meter,DistrictHeating:Facility,Timestep;'
303
-
304
- new_objects.each do |obj|
305
- object = OpenStudio::IdfObject.load(obj).get
306
- idf.addObject(object)
307
- end
308
-
309
- # save the file
310
- File.open(idf_filename, 'w') { |f| f << idf.to_s }
311
-
312
- @logger.info 'Finished EnergyPlus Preprocess'
313
- end
314
- end
@@ -1,230 +0,0 @@
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 RunOpenstudio
21
- # Mixin the MeasureApplication module to apply measures
22
- include OpenStudio::Workflow::ApplyMeasures
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, time_logger, adapter, workflow_arguments, past_results, options = {})
28
- defaults = { format: 'hash', analysis_root_path: '.' }
29
- warn 'Option of use_monthly_reports is deprecated. Monthly reports are always generated.' if options[:use_monthly_reports]
30
-
31
- @options = defaults.merge(options)
32
- @directory = directory
33
- # TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
34
- @run_directory = "#{@directory}/run"
35
- @adapter = adapter
36
- @results = {}
37
- @logger = logger
38
- @time_logger = time_logger
39
- @workflow_arguments = workflow_arguments
40
- @past_results = past_results
41
- @logger.info "#{self.class} passed the following options #{@options}"
42
-
43
- # initialize instance variables that are needed in the perform section
44
- @model = nil
45
- @model_idf = nil
46
- @initial_weather_file = nil
47
- @weather_file_path = nil
48
- @analysis_json = nil
49
- # TODO: rename datapoint_json to just datapoint
50
- @datapoint_json = nil
51
- @output_attributes = {}
52
- @report_measures = []
53
- end
54
-
55
- def perform
56
- @logger.info "Calling #{__method__} in the #{self.class} class"
57
- @logger.info "Current directory is #{@directory}"
58
-
59
- @logger.info 'Retrieving datapoint and problem'
60
- @datapoint_json = @adapter.get_datapoint(@directory, @options)
61
- @analysis_json = @adapter.get_problem(@directory, @options)
62
-
63
- if @analysis_json && @analysis_json[:analysis]
64
- @model = load_seed_model
65
-
66
- load_weather_file
67
-
68
- apply_measures(:openstudio_measure)
69
- @logger.info('Finished applying OpenStudio measures.')
70
-
71
- @time_logger.start('Translating to EnergyPlus')
72
- translate_to_energyplus
73
- @time_logger.stop('Translating to EnergyPlus')
74
-
75
- apply_measures(:energyplus_measure)
76
- @logger.info('Finished applying EnergyPlus measures.')
77
-
78
- # check if the weather file has changed. This is cheesy for now. Should have a default measure that
79
- # always sets the weather file so that it can be better controlled
80
- updated_weather_file = get_weather_file_from_model
81
- unless updated_weather_file == @initial_weather_file
82
- # reset the result hash so the future processes know which weather file to run
83
- @logger.info "Updating the weather file to be '#{updated_weather_file}'"
84
- if (Pathname.new updated_weather_file).absolute? && (Pathname.new updated_weather_file).exist?
85
- @results[:weather_filename] = updated_weather_file
86
- else
87
- @results[:weather_filename] = "#{@weather_file_path}/#{updated_weather_file}"
88
- end
89
- end
90
-
91
- @logger.info 'Saving measure output attributes JSON'
92
- File.open("#{@run_directory}/measure_attributes.json", 'w') do |f|
93
- f << JSON.pretty_generate(@output_attributes)
94
- end
95
- end
96
-
97
- @time_logger.start('Saving OSM and IDF')
98
- save_osm_and_idf
99
- @time_logger.stop('Saving OSM and IDF')
100
-
101
- @results
102
- end
103
-
104
- private
105
-
106
- def save_osm_and_idf
107
- # save the data
108
- osm_filename = "#{@run_directory}/in.osm"
109
- File.open(osm_filename, 'w') { |f| f << @model.to_s }
110
-
111
- idf_filename = "#{@run_directory}/in.idf"
112
- File.open(idf_filename, 'w') { |f| f << @model_idf.to_s }
113
-
114
- @results[:osm] = File.expand_path(osm_filename)
115
- @results[:idf] = File.expand_path(idf_filename)
116
- end
117
-
118
- def load_seed_model
119
- model = nil
120
- @logger.info 'Loading seed model'
121
-
122
- baseline_model_path = nil
123
- # Unique case to use the previous generated OSM as the seed
124
- if @options[:run_xml] && @options[:run_xml][:osm_filename]
125
- if File.exist? @options[:run_xml][:osm_filename]
126
- baseline_model_path = @options[:run_xml][:osm_filename]
127
- end
128
- elsif @analysis_json[:analysis][:seed]
129
- @logger.info "Seed model is #{@analysis_json[:analysis][:seed]}"
130
- if @analysis_json[:analysis][:seed][:path]
131
-
132
- # assume that the seed model has been placed in the directory
133
- baseline_model_path = File.expand_path(
134
- File.join(@options[:analysis_root_path], @analysis_json[:analysis][:seed][:path]))
135
- else
136
- fail 'No seed model path in JSON defined'
137
- end
138
- else
139
- # TODO: create a blank model and return
140
- fail 'No seed model block'
141
- end
142
-
143
- if baseline_model_path
144
- if File.exist? baseline_model_path
145
- @logger.info "Reading in baseline model #{baseline_model_path}"
146
- translator = OpenStudio::OSVersion::VersionTranslator.new
147
- model = translator.loadModel(baseline_model_path)
148
- fail 'OpenStudio model is empty or could not be loaded' if model.empty?
149
- model = model.get
150
- else
151
- fail "Seed model '#{baseline_model_path}' did not exist"
152
- end
153
- else
154
- fail 'No baseline/seed model found'
155
- end
156
-
157
- model
158
- end
159
-
160
- # Save the weather file to the instance variable
161
- def load_weather_file
162
- @initial_weather_file = get_weather_file_from_model
163
-
164
- weather_filename = nil
165
- if @options[:run_xml] && @options[:run_xml][:weather_filename]
166
- if File.exist? @options[:run_xml][:weather_filename]
167
- weather_filename = @options[:run_xml][:weather_filename]
168
- end
169
- elsif @analysis_json[:analysis][:weather_file]
170
- if @analysis_json[:analysis][:weather_file][:path]
171
- weather_filename = File.expand_path(
172
- File.join(@options[:analysis_root_path], @analysis_json[:analysis][:weather_file][:path])
173
- )
174
- @weather_file_path = File.dirname(weather_filename)
175
- else
176
- fail 'No weather file path defined'
177
- end
178
- else
179
- fail 'No weather file block defined'
180
- end
181
-
182
- unless File.exist?(weather_filename)
183
- fail "Could not find weather file for simulation #{weather_filename}"
184
- end
185
-
186
- @results[:weather_filename] = weather_filename
187
-
188
- weather_filename
189
- end
190
-
191
- # return the weather file from the model. If the weather file is defined in the model, then
192
- # it checks the file paths to check if the model exists. This allows for a user to upload a
193
- # weather file in a measure and then have the measure's path be used for the weather file.
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
- p = @model.weatherFile.get.path.get.to_s.gsub('file://', '')
201
- if File.exist? p
202
- # use this entire path
203
- @logger.info "Full path to weather file exists #{p}"
204
- wf = p
205
- else
206
- # this is the weather file from the OSM model
207
- wf = File.basename(@model.weatherFile.get.path.get.to_s)
208
- end
209
-
210
- # @logger.info "Initial model weather file is #{wf}" # unless model.weatherFile.empty?
211
- end
212
-
213
- wf
214
- end
215
-
216
- # Forward translate to energyplus
217
- def translate_to_energyplus
218
- if @model_idf.nil?
219
- @logger.info 'Translate object to EnergyPlus IDF in Prep for EnergyPlus Measure'
220
- a = Time.now
221
- # ensure objects exist for reporting purposes
222
- @model.getFacility
223
- @model.getBuilding
224
- forward_translator = OpenStudio::EnergyPlus::ForwardTranslator.new
225
- @model_idf = forward_translator.translateModel(@model)
226
- b = Time.now
227
- @logger.info "Translate object to EnergyPlus IDF took #{b.to_f - a.to_f}"
228
- end
229
- end
230
- end
@@ -1,110 +0,0 @@
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
- # Run precanned post processing to extract object functions
21
- # TODO: I hear that measures can step on each other if not run in their own directory
22
-
23
- require 'csv'
24
- require 'ostruct'
25
-
26
- class RunPostprocess
27
- # Mixin the MeasureApplication module to apply measures
28
- include OpenStudio::Workflow::ApplyMeasures
29
-
30
- def initialize(directory, logger, time_logger, adapter, workflow_arguments, past_results, options = {})
31
- defaults = {}
32
- @options = defaults.merge(options)
33
- @directory = directory
34
- @run_directory = "#{@directory}/run"
35
- @adapter = adapter
36
- @logger = logger
37
- @time_logger = time_logger
38
- @workflow_arguments = workflow_arguments
39
- @past_results = past_results
40
- @results = {}
41
- @output_attributes = {}
42
-
43
- @logger.info "#{self.class} passed the following options #{@options}"
44
- end
45
-
46
- def perform
47
- @logger.info "Calling #{__method__} in the #{self.class} class"
48
- @logger.info 'RunPostProcess Retrieving datapoint and problem'
49
-
50
- begin
51
- cleanup
52
- rescue => e
53
- log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
54
- @logger.error log_message
55
- # raise log_message
56
- end
57
-
58
- @results
59
- end
60
-
61
- def cleanup
62
- # move any of the reporting file to the 'reports' directory for serverside access
63
- eplus_search_path = nil
64
- FileUtils.mkdir_p "#{@directory}/reports"
65
-
66
- # try to find the energyplus result file
67
- eplus_html = "#{@run_directory}/eplustbl.htm"
68
- unless File.exist? eplus_html
69
- eplus_html = Dir["#{@directory}/*EnergyPlus*/eplustbl.htm"].last || nil
70
- end
71
-
72
- if eplus_html
73
- if File.exist? eplus_html
74
- # do some encoding on the html if possible
75
- html = File.read(eplus_html)
76
- html = html.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
77
- File.open("#{@directory}/reports/eplustbl.html", 'w') { |f| f << html }
78
- end
79
- end
80
-
81
- # Also, find any "report*.*" files
82
- Dir["#{@run_directory}/*/report*.*"].each do |report|
83
- # get the parent directory of the file and snake case it
84
- # do i need to force encoding on this as well?
85
- measure_class_name = File.basename(File.dirname(report)).to_underscore
86
- file_ext = File.extname(report)
87
- append_str = File.basename(report, '.*')
88
- new_file_name = "#{@directory}/reports/#{measure_class_name}_#{append_str}#{file_ext}"
89
- FileUtils.copy report, new_file_name
90
- end
91
-
92
- # Remove empty directories in run folder
93
- Dir["#{@run_directory}/*"].select { |d| File.directory? d }.select { |d| (Dir.entries(d) - %w(. ..)).empty? }.each do |d|
94
- @logger.info "Removing empty directory #{d}"
95
- Dir.rmdir d
96
- end
97
-
98
- paths_to_rm = []
99
- # paths_to_rm << Pathname.glob("#{@run_directory}/*.osm")
100
- # paths_to_rm << Pathname.glob("#{@run_directory}/*.idf") # keep the idfs
101
- # paths_to_rm << Pathname.glob("*.audit")
102
- # paths_to_rm << Pathname.glob("*.bnd")
103
- # paths_to_rm << Pathname.glob("#{@run_directory}/*.eso")
104
- paths_to_rm << Pathname.glob("#{@run_directory}/*.mtr")
105
- paths_to_rm << Pathname.glob("#{@run_directory}/*.epw")
106
- paths_to_rm << Pathname.glob("#{@run_directory}/*.mtd")
107
- paths_to_rm << Pathname.glob("#{@run_directory}/*.rdd")
108
- paths_to_rm.each { |p| FileUtils.rm_rf(p) }
109
- end
110
- end