openstudio-workflow 1.3.4 → 1.3.5

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +89 -77
  3. data/README.md +67 -93
  4. data/Rakefile +36 -36
  5. data/lib/openstudio-workflow.rb +65 -65
  6. data/lib/openstudio/workflow/adapters/input/local.rb +311 -324
  7. data/lib/openstudio/workflow/adapters/output/local.rb +158 -161
  8. data/lib/openstudio/workflow/adapters/output/socket.rb +106 -107
  9. data/lib/openstudio/workflow/adapters/output/web.rb +82 -82
  10. data/lib/openstudio/workflow/adapters/output_adapter.rb +163 -163
  11. data/lib/openstudio/workflow/job.rb +57 -57
  12. data/lib/openstudio/workflow/jobs/resources/monthly_report.idf +222 -222
  13. data/lib/openstudio/workflow/jobs/run_energyplus.rb +70 -70
  14. data/lib/openstudio/workflow/jobs/run_ep_measures.rb +73 -73
  15. data/lib/openstudio/workflow/jobs/run_initialization.rb +203 -203
  16. data/lib/openstudio/workflow/jobs/run_os_measures.rb +89 -89
  17. data/lib/openstudio/workflow/jobs/run_postprocess.rb +73 -73
  18. data/lib/openstudio/workflow/jobs/run_preprocess.rb +104 -104
  19. data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +118 -118
  20. data/lib/openstudio/workflow/jobs/run_translation.rb +84 -84
  21. data/lib/openstudio/workflow/multi_delegator.rb +62 -62
  22. data/lib/openstudio/workflow/registry.rb +172 -172
  23. data/lib/openstudio/workflow/run.rb +342 -328
  24. data/lib/openstudio/workflow/time_logger.rb +96 -96
  25. data/lib/openstudio/workflow/util.rb +49 -49
  26. data/lib/openstudio/workflow/util/energyplus.rb +575 -605
  27. data/lib/openstudio/workflow/util/io.rb +68 -68
  28. data/lib/openstudio/workflow/util/measure.rb +658 -650
  29. data/lib/openstudio/workflow/util/model.rb +151 -151
  30. data/lib/openstudio/workflow/util/post_process.rb +235 -238
  31. data/lib/openstudio/workflow/util/weather_file.rb +143 -143
  32. data/lib/openstudio/workflow/version.rb +40 -40
  33. data/lib/openstudio/workflow_json.rb +475 -476
  34. data/lib/openstudio/workflow_runner.rb +263 -268
  35. metadata +24 -24
@@ -1,96 +1,96 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2018, Alliance for Sustainable Energy, LLC.
3
- # All rights reserved.
4
- # Redistribution and use in source and binary forms, with or without
5
- # modification, are permitted provided that the following conditions are met:
6
- #
7
- # (1) Redistributions of source code must retain the above copyright notice,
8
- # this list of conditions and the following disclaimer.
9
- #
10
- # (2) Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- #
14
- # (3) Neither the name of the copyright holder nor the names of any contributors
15
- # may be used to endorse or promote products derived from this software without
16
- # specific prior written permission from the respective party.
17
- #
18
- # (4) Other than as required in clauses (1) and (2), distributions in any form
19
- # of modifications or other derivative works may not use the "OpenStudio"
20
- # trademark, "OS", "os", or any other confusingly similar designation without
21
- # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
- #
23
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
- # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
- # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
- # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- # *******************************************************************************
35
-
36
- # Class to store run times in a useful structure. Data are stored in a hash based on a the channel name
37
- # There is no concept of multi-levels. The onus is on the user to make sure that they don't add a value to the
38
- # logger that may be a level.
39
- class TimeLogger
40
- attr_reader :channels
41
-
42
- def initialize
43
- @logger = []
44
- @channels = {}
45
- end
46
-
47
- # name of the moniker that you are tracking. If the name is already in use, then it restarts the timer.
48
- def start(channel)
49
- # warning -- "will reset timer for #{moniker}" if @monikers.key? moniker
50
- s = ::Time.now
51
- @channels[channel] = { start_time_str: s.to_s, start_time: s.to_f }
52
- end
53
-
54
- def stop(channel)
55
- end_time = ::Time.now.to_f
56
- @logger << {
57
- channel: channel,
58
- start_time: @channels[channel][:start_time],
59
- start_time_str: @channels[channel][:start_time_str],
60
- end_time: end_time,
61
- delta: end_time - @channels[channel][:start_time]
62
- }
63
-
64
- # remove the channel
65
- @channels.delete(channel) if @channels.key? channel
66
- end
67
-
68
- def stop_all
69
- @channels.each_key do |channel|
70
- stop(channel)
71
- end
72
- end
73
-
74
- # return the entire report
75
- def report
76
- @logger
77
- end
78
-
79
- # this will report all the values for all the channels with this name.
80
- def delta(channel)
81
- @logger.map { |k| { channel.to_s => k[:delta] } if k[:channel] == channel }.compact
82
- end
83
-
84
- # save the data to a file. This will overwrite the file if it already exists
85
- def save(filename)
86
- File.open(filename, 'w') do |f|
87
- f << JSON.pretty_generate(@logger)
88
- # make sure data is written to the disk one way or the other
89
- begin
90
- f.fsync
91
- rescue
92
- f.flush
93
- end
94
- end
95
- end
96
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
+ # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
36
+ # Class to store run times in a useful structure. Data are stored in a hash based on a the channel name
37
+ # There is no concept of multi-levels. The onus is on the user to make sure that they don't add a value to the
38
+ # logger that may be a level.
39
+ class TimeLogger
40
+ attr_reader :channels
41
+
42
+ def initialize
43
+ @logger = []
44
+ @channels = {}
45
+ end
46
+
47
+ # name of the moniker that you are tracking. If the name is already in use, then it restarts the timer.
48
+ def start(channel)
49
+ # warning -- "will reset timer for #{moniker}" if @monikers.key? moniker
50
+ s = ::Time.now
51
+ @channels[channel] = { start_time_str: s.to_s, start_time: s.to_f }
52
+ end
53
+
54
+ def stop(channel)
55
+ end_time = ::Time.now.to_f
56
+ @logger << {
57
+ channel: channel,
58
+ start_time: @channels[channel][:start_time],
59
+ start_time_str: @channels[channel][:start_time_str],
60
+ end_time: end_time,
61
+ delta: end_time - @channels[channel][:start_time]
62
+ }
63
+
64
+ # remove the channel
65
+ @channels.delete(channel) if @channels.key? channel
66
+ end
67
+
68
+ def stop_all
69
+ @channels.each_key do |channel|
70
+ stop(channel)
71
+ end
72
+ end
73
+
74
+ # return the entire report
75
+ def report
76
+ @logger
77
+ end
78
+
79
+ # this will report all the values for all the channels with this name.
80
+ def delta(channel)
81
+ @logger.map { |k| { channel.to_s => k[:delta] } if k[:channel] == channel }.compact
82
+ end
83
+
84
+ # save the data to a file. This will overwrite the file if it already exists
85
+ def save(filename)
86
+ File.open(filename, 'w') do |f|
87
+ f << JSON.pretty_generate(@logger)
88
+ # make sure data is written to the disk one way or the other
89
+ begin
90
+ f.fsync
91
+ rescue StandardError
92
+ f.flush
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,49 +1,49 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2018, Alliance for Sustainable Energy, LLC.
3
- # All rights reserved.
4
- # Redistribution and use in source and binary forms, with or without
5
- # modification, are permitted provided that the following conditions are met:
6
- #
7
- # (1) Redistributions of source code must retain the above copyright notice,
8
- # this list of conditions and the following disclaimer.
9
- #
10
- # (2) Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- #
14
- # (3) Neither the name of the copyright holder nor the names of any contributors
15
- # may be used to endorse or promote products derived from this software without
16
- # specific prior written permission from the respective party.
17
- #
18
- # (4) Other than as required in clauses (1) and (2), distributions in any form
19
- # of modifications or other derivative works may not use the "OpenStudio"
20
- # trademark, "OS", "os", or any other confusingly similar designation without
21
- # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
- #
23
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
- # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
- # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
- # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- # *******************************************************************************
35
-
36
- module OpenStudio
37
- module Workflow
38
- # Hard load utils for the moment
39
- #
40
- module Util
41
- require 'openstudio/workflow/util/io'
42
- require 'openstudio/workflow/util/measure'
43
- require 'openstudio/workflow/util/weather_file'
44
- require 'openstudio/workflow/util/model'
45
- require 'openstudio/workflow/util/energyplus'
46
- require 'openstudio/workflow/util/post_process'
47
- end
48
- end
49
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
+ # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
36
+ module OpenStudio
37
+ module Workflow
38
+ # Hard load utils for the moment
39
+ #
40
+ module Util
41
+ require 'openstudio/workflow/util/io'
42
+ require 'openstudio/workflow/util/measure'
43
+ require 'openstudio/workflow/util/weather_file'
44
+ require 'openstudio/workflow/util/model'
45
+ require 'openstudio/workflow/util/energyplus'
46
+ require 'openstudio/workflow/util/post_process'
47
+ end
48
+ end
49
+ end
@@ -1,605 +1,575 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) 2008-2018, Alliance for Sustainable Energy, LLC.
3
- # All rights reserved.
4
- # Redistribution and use in source and binary forms, with or without
5
- # modification, are permitted provided that the following conditions are met:
6
- #
7
- # (1) Redistributions of source code must retain the above copyright notice,
8
- # this list of conditions and the following disclaimer.
9
- #
10
- # (2) Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- #
14
- # (3) Neither the name of the copyright holder nor the names of any contributors
15
- # may be used to endorse or promote products derived from this software without
16
- # specific prior written permission from the respective party.
17
- #
18
- # (4) Other than as required in clauses (1) and (2), distributions in any form
19
- # of modifications or other derivative works may not use the "OpenStudio"
20
- # trademark, "OS", "os", or any other confusingly similar designation without
21
- # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
- #
23
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
- # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
- # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
- # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- # *******************************************************************************
35
-
36
- module OpenStudio
37
- module Workflow
38
- module Util
39
- # The methods needed to run simulations using EnergyPlus are stored here. See the run_simulation class for
40
- # implementation details.
41
- module EnergyPlus
42
- require 'openstudio/workflow/util/io'
43
- include OpenStudio::Workflow::Util::IO
44
- ENERGYPLUS_REGEX = /^energyplus\D{0,4}$/i
45
- EXPAND_OBJECTS_REGEX = /^expandobjects\D{0,4}$/i
46
-
47
- # Find the installation directory of EnergyPlus linked to the OpenStudio version being used
48
- #
49
- # @return [String] Returns the path to EnergyPlus
50
- #
51
- def find_energyplus
52
- path = OpenStudio.getEnergyPlusDirectory.to_s
53
- raise 'Unable to find the EnergyPlus executable' unless File.exist? path
54
- path
55
- end
56
-
57
- # Does something
58
- #
59
- # @param [String] run_directory Directory to run the EnergyPlus simulation in
60
- # @param [Array] energyplus_files Array of files containing the EnergyPlus and ExpandObjects EXEs
61
- # @return [Void]
62
- #
63
- def clean_directory(run_directory, energyplus_files, logger)
64
- logger.info 'Removing any copied EnergyPlus files'
65
- energyplus_files.each do |file|
66
- if File.exist? file
67
- FileUtils.rm_f file
68
- end
69
- end
70
-
71
- paths_to_rm = []
72
- paths_to_rm << "#{run_directory}/packaged_measures"
73
- paths_to_rm << "#{run_directory}/Energy+.ini"
74
- paths_to_rm.each { |p| FileUtils.rm_rf(p) if File.exist?(p) }
75
- end
76
-
77
- # Prepare the directory to run EnergyPlus
78
- #
79
- # @param [String] run_directory Directory to copy the required EnergyPlus files to
80
- # @param [Object] logger Logger object
81
- # @param [String] energyplus_path Path to the EnergyPlus EXE
82
- # @return [Array, file, file] Returns an array of strings of EnergyPlus files copied to the run_directory, the
83
- # ExpandObjects EXE file, and EnergyPlus EXE file
84
- #
85
- def prepare_energyplus_dir(run_directory, logger, energyplus_path = nil)
86
- logger.info "Copying EnergyPlus files to run directory: #{run_directory}"
87
- energyplus_path ||= find_energyplus
88
- logger.info "EnergyPlus path is #{energyplus_path}"
89
- energyplus_files = []
90
- energyplus_exe, expand_objects_exe = nil
91
- Dir["#{energyplus_path}/*"].each do |file|
92
- next if File.directory? file
93
-
94
- # copy idd and ini files
95
- if File.extname(file).downcase =~ /.idd|.ini/
96
- dest_file = "#{run_directory}/#{File.basename(file)}"
97
- energyplus_files << dest_file
98
- FileUtils.copy file, dest_file
99
- end
100
-
101
- energyplus_exe = file if File.basename(file) =~ ENERGYPLUS_REGEX
102
- expand_objects_exe = file if File.basename(file) =~ EXPAND_OBJECTS_REGEX
103
-
104
- end
105
-
106
- raise "Could not find EnergyPlus executable in #{energyplus_path}" unless energyplus_exe
107
- raise "Could not find ExpandObjects executable in #{energyplus_path}" unless expand_objects_exe
108
-
109
- logger.info "EnergyPlus executable path is #{energyplus_exe}"
110
- logger.info "ExpandObjects executable path is #{expand_objects_exe}"
111
-
112
- return energyplus_files, energyplus_exe, expand_objects_exe
113
- end
114
-
115
- # Configures and executes the EnergyPlus simulation and checks to see if the simulation was successful
116
- #
117
- # @param [String] run_directory Directory to execute the EnergyPlus simulation in. It is assumed that this
118
- # directory already has the IDF and weather file in it
119
- # @param [String] energyplus_path (nil) Optional path to override the default path associated with the
120
- # OpenStudio package being used
121
- # @param [Object] output_adapter (nil) Optional output adapter to update
122
- # @param [Object] logger (nil) Optional logger, will log to STDOUT if none provided
123
- # @return [Void]
124
- #
125
- def call_energyplus(run_directory, energyplus_path = nil, output_adapter = nil, logger = nil, workflow_json = nil)
126
- logger ||= ::Logger.new(STDOUT) unless logger
127
-
128
- current_dir = Dir.pwd
129
- energyplus_path ||= find_energyplus
130
- logger.info "EnergyPlus path is #{energyplus_path}"
131
- energyplus_files, energyplus_exe, expand_objects_exe = prepare_energyplus_dir(run_directory, logger, energyplus_path)
132
- Dir.chdir(run_directory)
133
- logger.info "Starting simulation in run directory: #{Dir.pwd}"
134
-
135
- if !@options[:skip_expand_objects]
136
- command = popen_command("\"#{expand_objects_exe}\"")
137
- logger.info "Running command '#{command}'"
138
- File.open('stdout-expandobject', 'w') do |file|
139
- ::IO.popen(command) do |io|
140
- while (line = io.gets)
141
- file << line
142
- end
143
- end
144
- end
145
-
146
- # Check if expand objects did anything
147
- if File.exist? 'expanded.idf'
148
- FileUtils.mv('in.idf', 'pre-expand.idf', force: true) if File.exist?('in.idf')
149
- FileUtils.mv('expanded.idf', 'in.idf', force: true)
150
- end
151
- end
152
-
153
- # create stdout
154
- command = popen_command("\"#{energyplus_exe}\" 2>&1")
155
- logger.info "Running command '#{command}'"
156
- File.open('stdout-energyplus', 'w') do |file|
157
- ::IO.popen(command) do |io|
158
- while (line = io.gets)
159
- file << line
160
- output_adapter.communicate_energyplus_stdout(line) if output_adapter
161
- end
162
- end
163
- end
164
- r = $?
165
-
166
- logger.info "EnergyPlus returned '#{r}'"
167
- unless r.to_i.zero?
168
- logger.warn 'EnergyPlus returned a non-zero exit code. Check the stdout-energyplus log.'
169
- end
170
-
171
- if File.exist? 'eplusout.err'
172
- eplus_err = File.read('eplusout.err').force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
173
-
174
- if workflow_json
175
- begin
176
- if !@options[:fast]
177
- workflow_json.setEplusoutErr(eplus_err)
178
- end
179
- rescue => e
180
- # older versions of OpenStudio did not have the setEplusoutErr method
181
- end
182
- end
183
-
184
- if eplus_err =~ /EnergyPlus Terminated--Fatal Error Detected/
185
- raise 'EnergyPlus Terminated with a Fatal Error. Check eplusout.err log.'
186
- end
187
- end
188
-
189
- if File.exist? 'eplusout.end'
190
- f = File.read('eplusout.end').force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
191
- warnings_count = f[/(\d*).Warning/, 1]
192
- error_count = f[/(\d*).Severe.Errors/, 1]
193
- logger.info "EnergyPlus finished with #{warnings_count} warnings and #{error_count} severe errors"
194
- if f =~ /EnergyPlus Terminated--Fatal Error Detected/
195
- raise 'EnergyPlus Terminated with a Fatal Error. Check eplusout.err log.'
196
- end
197
- else
198
- raise 'EnergyPlus failed and did not create an eplusout.end file. Check the stdout-energyplus log.'
199
- end
200
-
201
- rescue => e
202
- log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
203
- logger.error log_message
204
- raise log_message
205
- ensure
206
- logger.info "Ensuring 'clean' directory"
207
- clean_directory(run_directory, energyplus_files, logger)
208
-
209
- Dir.chdir(current_dir)
210
- logger.info 'EnergyPlus Completed'
211
- end
212
-
213
- # Run this code before running EnergyPlus to make sure the reporting variables are setup correctly
214
- #
215
- # @param [Object] idf The IDF Workspace to be simulated
216
- # @return [Void]
217
- #
218
- def energyplus_preprocess(idf, logger)
219
- logger.info 'Running EnergyPlus Preprocess'
220
-
221
- new_objects = []
222
-
223
- needs_sqlobj = idf.getObjectsByType('Output:SQLite'.to_IddObjectType).empty?
224
-
225
- if needs_sqlobj
226
- # just add this, we don't allow this type in add_energyplus_output_request
227
- logger.info 'Adding SQL Output to IDF'
228
- object = OpenStudio::IdfObject.load('Output:SQLite,SimpleAndTabular;').get
229
- idf.addObjects(object)
230
- end
231
-
232
- # merge in monthly reports
233
- EnergyPlus.monthly_report_idf_text.split(/^[\s]*$/).each do |object|
234
- object = object.strip
235
- next if object.empty?
236
-
237
- new_objects << object
238
- end
239
-
240
- # These are needed for the calibration report
241
- new_objects << 'Output:Meter:MeterFileOnly,Gas:Facility,Daily;'
242
- new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Timestep;'
243
- new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Daily;'
244
-
245
- # Always add in the timestep facility meters
246
- new_objects << 'Output:Meter,Electricity:Facility,Timestep;'
247
- new_objects << 'Output:Meter,Gas:Facility,Timestep;'
248
- new_objects << 'Output:Meter,DistrictCooling:Facility,Timestep;'
249
- new_objects << 'Output:Meter,DistrictHeating:Facility,Timestep;'
250
-
251
- new_objects.each do |obj|
252
- object = OpenStudio::IdfObject.load(obj).get
253
- OpenStudio::Workflow::Util::EnergyPlus.add_energyplus_output_request(idf, object)
254
- end
255
-
256
- # this is a workaround for issue #1699 -- remove when 1699 is closed.
257
- needs_hourly = true
258
- needs_timestep = true
259
- needs_daily = true
260
- needs_monthy = true
261
- idf.getObjectsByType('Output:Variable'.to_IddObjectType).each do |object|
262
- timestep = object.getString(2, true).get
263
- if /Hourly/i =~ timestep
264
- needs_hourly = false
265
- elsif /Timestep/i =~ timestep
266
- needs_timestep = false
267
- elsif /Daily/i =~ timestep
268
- needs_daily = false
269
- elsif /Monthly/i =~ timestep
270
- needs_monthy = false
271
- end
272
- end
273
-
274
- new_objects = []
275
- new_objects << 'Output:Variable,*,Zone Air Temperature,Hourly;' if needs_hourly
276
- new_objects << 'Output:Variable,*,Site Outdoor Air Wetbulb Temperature,Timestep;' if needs_timestep
277
- new_objects << 'Output:Variable,*,Zone Air Relative Humidity,Daily;' if needs_daily
278
- new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Monthly;' if needs_monthy
279
-
280
- new_objects.each do |obj|
281
- object = OpenStudio::IdfObject.load(obj).get
282
- OpenStudio::Workflow::Util::EnergyPlus.add_energyplus_output_request(idf, object)
283
- end
284
-
285
- logger.info 'Finished EnergyPlus Preprocess'
286
- end
287
-
288
- # examines object and determines whether or not to add it to the workspace
289
- def self.add_energyplus_output_request(workspace, idf_object)
290
- num_added = 0
291
- idd_object = idf_object.iddObject
292
-
293
- allowed_objects = []
294
- allowed_objects << 'Output:Surfaces:List'
295
- allowed_objects << 'Output:Surfaces:Drawing'
296
- allowed_objects << 'Output:Schedules'
297
- allowed_objects << 'Output:Constructions'
298
- allowed_objects << 'Output:Table:TimeBins'
299
- allowed_objects << 'Output:Table:Monthly'
300
- allowed_objects << 'Output:Variable'
301
- allowed_objects << 'Output:Meter'
302
- allowed_objects << 'Output:Meter:MeterFileOnly'
303
- allowed_objects << 'Output:Meter:Cumulative'
304
- allowed_objects << 'Output:Meter:Cumulative:MeterFileOnly'
305
- allowed_objects << 'Meter:Custom'
306
- allowed_objects << 'Meter:CustomDecrement'
307
-
308
- if allowed_objects.include?(idd_object.name)
309
- unless check_for_object(workspace, idf_object, idd_object.type)
310
- workspace.addObject(idf_object)
311
- num_added += 1
312
- end
313
- end
314
-
315
- allowed_unique_objects = []
316
- # allowed_unique_objects << "Output:EnergyManagementSystem" # TODO: have to merge
317
- # allowed_unique_objects << "OutputControl:SurfaceColorScheme" # TODO: have to merge
318
- allowed_unique_objects << 'Output:Table:SummaryReports' # TODO: have to merge
319
- # OutputControl:Table:Style # not allowed
320
- # OutputControl:ReportingTolerances # not allowed
321
- # Output:SQLite # not allowed
322
-
323
- if allowed_unique_objects.include?(idf_object.iddObject.name)
324
- if idf_object.iddObject.name == 'Output:Table:SummaryReports'
325
- summary_reports = workspace.getObjectsByType(idf_object.iddObject.type)
326
- if summary_reports.empty?
327
- workspace.addObject(idf_object)
328
- num_added += 1
329
- else
330
- merge_output_table_summary_reports(summary_reports[0], idf_object)
331
- end
332
- end
333
- end
334
-
335
- return num_added
336
- end
337
-
338
- # check to see if we have an exact match for this object already
339
- def self.check_for_object(workspace, idf_object, idd_object_type)
340
- workspace.getObjectsByType(idd_object_type).each do |object|
341
- # all of these objects fields are data fields
342
- if idf_object.dataFieldsEqual(object)
343
- return true
344
- end
345
- end
346
- return false
347
- end
348
-
349
- # merge all summary reports that are not in the current workspace
350
- def self.merge_output_table_summary_reports(current_object, new_object)
351
- current_fields = []
352
- current_object.extensibleGroups.each do |current_extensible_group|
353
- current_fields << current_extensible_group.getString(0).to_s
354
- end
355
-
356
- fields_to_add = []
357
- new_object.extensibleGroups.each do |new_extensible_group|
358
- field = new_extensible_group.getString(0).to_s
359
- unless current_fields.include?(field)
360
- current_fields << field
361
- fields_to_add << field
362
- end
363
- end
364
-
365
- unless fields_to_add.empty?
366
- fields_to_add.each do |field|
367
- values = OpenStudio::StringVector.new
368
- values << field
369
- current_object.pushExtensibleGroup(values)
370
- end
371
- return true
372
- end
373
-
374
- return false
375
- end
376
-
377
- def self.monthly_report_idf_text
378
- <<-HEREDOC
379
- Output:Table:Monthly,
380
- Building Energy Performance - Electricity, !- Name
381
- 2, !- Digits After Decimal
382
- InteriorLights:Electricity, !- Variable or Meter 1 Name
383
- SumOrAverage, !- Aggregation Type for Variable or Meter 1
384
- ExteriorLights:Electricity, !- Variable or Meter 2 Name
385
- SumOrAverage, !- Aggregation Type for Variable or Meter 2
386
- InteriorEquipment:Electricity, !- Variable or Meter 3 Name
387
- SumOrAverage, !- Aggregation Type for Variable or Meter 3
388
- ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
389
- SumOrAverage, !- Aggregation Type for Variable or Meter 4
390
- Fans:Electricity, !- Variable or Meter 5 Name
391
- SumOrAverage, !- Aggregation Type for Variable or Meter 5
392
- Pumps:Electricity, !- Variable or Meter 6 Name
393
- SumOrAverage, !- Aggregation Type for Variable or Meter 6
394
- Heating:Electricity, !- Variable or Meter 7 Name
395
- SumOrAverage, !- Aggregation Type for Variable or Meter 7
396
- Cooling:Electricity, !- Variable or Meter 8 Name
397
- SumOrAverage, !- Aggregation Type for Variable or Meter 8
398
- HeatRejection:Electricity, !- Variable or Meter 9 Name
399
- SumOrAverage, !- Aggregation Type for Variable or Meter 9
400
- Humidifier:Electricity, !- Variable or Meter 10 Name
401
- SumOrAverage, !- Aggregation Type for Variable or Meter 10
402
- HeatRecovery:Electricity,!- Variable or Meter 11 Name
403
- SumOrAverage, !- Aggregation Type for Variable or Meter 11
404
- WaterSystems:Electricity,!- Variable or Meter 12 Name
405
- SumOrAverage, !- Aggregation Type for Variable or Meter 12
406
- Cogeneration:Electricity,!- Variable or Meter 13 Name
407
- SumOrAverage, !- Aggregation Type for Variable or Meter 13
408
- Refrigeration:Electricity,!- Variable or Meter 14 Name
409
- SumOrAverage; !- Aggregation Type for Variable or Meter 14
410
-
411
- Output:Table:Monthly,
412
- Building Energy Performance - Natural Gas, !- Name
413
- 2, !- Digits After Decimal
414
- InteriorEquipment:Gas, !- Variable or Meter 1 Name
415
- SumOrAverage, !- Aggregation Type for Variable or Meter 1
416
- ExteriorEquipment:Gas, !- Variable or Meter 2 Name
417
- SumOrAverage, !- Aggregation Type for Variable or Meter 2
418
- Heating:Gas, !- Variable or Meter 3 Name
419
- SumOrAverage, !- Aggregation Type for Variable or Meter 3
420
- Cooling:Gas, !- Variable or Meter 4 Name
421
- SumOrAverage, !- Aggregation Type for Variable or Meter 4
422
- WaterSystems:Gas, !- Variable or Meter 5 Name
423
- SumOrAverage, !- Aggregation Type for Variable or Meter 5
424
- Cogeneration:Gas, !- Variable or Meter 6 Name
425
- SumOrAverage; !- Aggregation Type for Variable or Meter 6
426
-
427
- Output:Table:Monthly,
428
- Building Energy Performance - District Heating, !- Name
429
- 2, !- Digits After Decimal
430
- InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
431
- SumOrAverage, !- Aggregation Type for Variable or Meter 1
432
- ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
433
- SumOrAverage, !- Aggregation Type for Variable or Meter 2
434
- InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
435
- SumOrAverage, !- Aggregation Type for Variable or Meter 3
436
- ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
437
- SumOrAverage, !- Aggregation Type for Variable or Meter 4
438
- Fans:DistrictHeating, !- Variable or Meter 5 Name
439
- SumOrAverage, !- Aggregation Type for Variable or Meter 5
440
- Pumps:DistrictHeating, !- Variable or Meter 6 Name
441
- SumOrAverage, !- Aggregation Type for Variable or Meter 6
442
- Heating:DistrictHeating, !- Variable or Meter 7 Name
443
- SumOrAverage, !- Aggregation Type for Variable or Meter 7
444
- Cooling:DistrictHeating, !- Variable or Meter 8 Name
445
- SumOrAverage, !- Aggregation Type for Variable or Meter 8
446
- HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
447
- SumOrAverage, !- Aggregation Type for Variable or Meter 9
448
- Humidifier:DistrictHeating, !- Variable or Meter 10 Name
449
- SumOrAverage, !- Aggregation Type for Variable or Meter 10
450
- HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
451
- SumOrAverage, !- Aggregation Type for Variable or Meter 11
452
- WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
453
- SumOrAverage, !- Aggregation Type for Variable or Meter 12
454
- Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
455
- SumOrAverage; !- Aggregation Type for Variable or Meter 13
456
-
457
- Output:Table:Monthly,
458
- Building Energy Performance - District Cooling, !- Name
459
- 2, !- Digits After Decimal
460
- InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
461
- SumOrAverage, !- Aggregation Type for Variable or Meter 1
462
- ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
463
- SumOrAverage, !- Aggregation Type for Variable or Meter 2
464
- InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
465
- SumOrAverage, !- Aggregation Type for Variable or Meter 3
466
- ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
467
- SumOrAverage, !- Aggregation Type for Variable or Meter 4
468
- Fans:DistrictCooling, !- Variable or Meter 5 Name
469
- SumOrAverage, !- Aggregation Type for Variable or Meter 5
470
- Pumps:DistrictCooling, !- Variable or Meter 6 Name
471
- SumOrAverage, !- Aggregation Type for Variable or Meter 6
472
- Heating:DistrictCooling, !- Variable or Meter 7 Name
473
- SumOrAverage, !- Aggregation Type for Variable or Meter 7
474
- Cooling:DistrictCooling, !- Variable or Meter 8 Name
475
- SumOrAverage, !- Aggregation Type for Variable or Meter 8
476
- HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
477
- SumOrAverage, !- Aggregation Type for Variable or Meter 9
478
- Humidifier:DistrictCooling, !- Variable or Meter 10 Name
479
- SumOrAverage, !- Aggregation Type for Variable or Meter 10
480
- HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
481
- SumOrAverage, !- Aggregation Type for Variable or Meter 11
482
- WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
483
- SumOrAverage, !- Aggregation Type for Variable or Meter 12
484
- Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
485
- SumOrAverage; !- Aggregation Type for Variable or Meter 13
486
-
487
- Output:Table:Monthly,
488
- Building Energy Performance - Electricity Peak Demand, !- Name
489
- 2, !- Digits After Decimal
490
- Electricity:Facility, !- Variable or Meter 1 Name
491
- Maximum, !- Aggregation Type for Variable or Meter 1
492
- InteriorLights:Electricity, !- Variable or Meter 1 Name
493
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
494
- ExteriorLights:Electricity, !- Variable or Meter 2 Name
495
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
496
- InteriorEquipment:Electricity, !- Variable or Meter 3 Name
497
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
498
- ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
499
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
500
- Fans:Electricity, !- Variable or Meter 5 Name
501
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
502
- Pumps:Electricity, !- Variable or Meter 6 Name
503
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
504
- Heating:Electricity, !- Variable or Meter 7 Name
505
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
506
- Cooling:Electricity, !- Variable or Meter 8 Name
507
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
508
- HeatRejection:Electricity, !- Variable or Meter 9 Name
509
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
510
- Humidifier:Electricity, !- Variable or Meter 10 Name
511
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
512
- HeatRecovery:Electricity,!- Variable or Meter 11 Name
513
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
514
- WaterSystems:Electricity,!- Variable or Meter 12 Name
515
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
516
- Cogeneration:Electricity,!- Variable or Meter 13 Name
517
- ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
518
-
519
- Output:Table:Monthly,
520
- Building Energy Performance - Natural Gas Peak Demand, !- Name
521
- 2, !- Digits After Decimal
522
- Gas:Facility, !- Variable or Meter 1 Name
523
- Maximum, !- Aggregation Type for Variable or Meter 1
524
- InteriorEquipment:Gas, !- Variable or Meter 1 Name
525
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
526
- ExteriorEquipment:Gas, !- Variable or Meter 2 Name
527
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
528
- Heating:Gas, !- Variable or Meter 3 Name
529
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
530
- Cooling:Gas, !- Variable or Meter 4 Name
531
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
532
- WaterSystems:Gas, !- Variable or Meter 5 Name
533
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
534
- Cogeneration:Gas, !- Variable or Meter 6 Name
535
- ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 6
536
-
537
- Output:Table:Monthly,
538
- Building Energy Performance - District Heating Peak Demand, !- Name
539
- 2, !- Digits After Decimal
540
- DistrictHeating:Facility, !- Variable or Meter 1 Name
541
- Maximum, !- Aggregation Type for Variable or Meter 1
542
- InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
543
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
544
- ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
545
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
546
- InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
547
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
548
- ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
549
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
550
- Fans:DistrictHeating, !- Variable or Meter 5 Name
551
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
552
- Pumps:DistrictHeating, !- Variable or Meter 6 Name
553
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
554
- Heating:DistrictHeating, !- Variable or Meter 7 Name
555
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
556
- Cooling:DistrictHeating, !- Variable or Meter 8 Name
557
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
558
- HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
559
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
560
- Humidifier:DistrictHeating, !- Variable or Meter 10 Name
561
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
562
- HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
563
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
564
- WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
565
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
566
- Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
567
- ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
568
-
569
- Output:Table:Monthly,
570
- Building Energy Performance - District Cooling Peak Demand, !- Name
571
- 2, !- Digits After Decimal
572
- DistrictCooling:Facility, !- Variable or Meter 1 Name
573
- Maximum, !- Aggregation Type for Variable or Meter 1
574
- InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
575
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
576
- ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
577
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
578
- InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
579
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
580
- ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
581
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
582
- Fans:DistrictCooling, !- Variable or Meter 5 Name
583
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
584
- Pumps:DistrictCooling, !- Variable or Meter 6 Name
585
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
586
- Heating:DistrictCooling, !- Variable or Meter 7 Name
587
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
588
- Cooling:DistrictCooling, !- Variable or Meter 8 Name
589
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
590
- HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
591
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
592
- Humidifier:DistrictCooling, !- Variable or Meter 10 Name
593
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
594
- HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
595
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
596
- WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
597
- ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
598
- Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
599
- ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
600
- HEREDOC
601
- end
602
- end
603
- end
604
- end
605
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
3
+ # All rights reserved.
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # (1) Redistributions of source code must retain the above copyright notice,
8
+ # this list of conditions and the following disclaimer.
9
+ #
10
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # (3) Neither the name of the copyright holder nor the names of any contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission from the respective party.
17
+ #
18
+ # (4) Other than as required in clauses (1) and (2), distributions in any form
19
+ # of modifications or other derivative works may not use the "OpenStudio"
20
+ # trademark, "OS", "os", or any other confusingly similar designation without
21
+ # specific prior written permission from Alliance for Sustainable Energy, LLC.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
27
+ # GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
36
+ module OpenStudio
37
+ module Workflow
38
+ module Util
39
+ # The methods needed to run simulations using EnergyPlus are stored here. See the run_simulation class for
40
+ # implementation details.
41
+ module EnergyPlus
42
+ require 'openstudio/workflow/util/io'
43
+ include OpenStudio::Workflow::Util::IO
44
+ ENERGYPLUS_REGEX = /^energyplus\D{0,4}$/i
45
+ EXPAND_OBJECTS_REGEX = /^expandobjects\D{0,4}$/i
46
+
47
+ # Find the installation directory of EnergyPlus linked to the OpenStudio version being used
48
+ #
49
+ # @return [String] Returns the path to EnergyPlus
50
+ #
51
+ def find_energyplus
52
+ path = OpenStudio.getEnergyPlusDirectory.to_s
53
+ raise 'Unable to find the EnergyPlus executable' unless File.exist? path
54
+ path
55
+ end
56
+
57
+ # Does something
58
+ #
59
+ # @param [String] run_directory Directory to run the EnergyPlus simulation in
60
+ # @param [Array] energyplus_files Array of files containing the EnergyPlus and ExpandObjects EXEs
61
+ # @return [Void]
62
+ #
63
+ def clean_directory(run_directory, energyplus_files, logger)
64
+ logger.info 'Removing any copied EnergyPlus files'
65
+ energyplus_files.each do |file|
66
+ if File.exist? file
67
+ FileUtils.rm_f file
68
+ end
69
+ end
70
+
71
+ paths_to_rm = []
72
+ paths_to_rm << "#{run_directory}/packaged_measures"
73
+ paths_to_rm << "#{run_directory}/Energy+.ini"
74
+ paths_to_rm.each { |p| FileUtils.rm_rf(p) if File.exist?(p) }
75
+ end
76
+
77
+ # Prepare the directory to run EnergyPlus
78
+ #
79
+ # @param [String] run_directory Directory to copy the required EnergyPlus files to
80
+ # @param [Object] logger Logger object
81
+ # @param [String] energyplus_path Path to the EnergyPlus EXE
82
+ # @return [Array, file, file] Returns an array of strings of EnergyPlus files copied to the run_directory, the
83
+ # ExpandObjects EXE file, and EnergyPlus EXE file
84
+ #
85
+ def prepare_energyplus_dir(run_directory, logger, energyplus_path = nil)
86
+ logger.info "Copying EnergyPlus files to run directory: #{run_directory}"
87
+ energyplus_path ||= find_energyplus
88
+ logger.info "EnergyPlus path is #{energyplus_path}"
89
+ energyplus_files = []
90
+ energyplus_exe, expand_objects_exe = nil
91
+ Dir["#{energyplus_path}/*"].each do |file|
92
+ next if File.directory? file
93
+
94
+ # copy idd and ini files
95
+ if File.extname(file).downcase =~ /.idd|.ini/
96
+ dest_file = "#{run_directory}/#{File.basename(file)}"
97
+ energyplus_files << dest_file
98
+ FileUtils.copy file, dest_file
99
+ end
100
+
101
+ energyplus_exe = file if File.basename(file) =~ ENERGYPLUS_REGEX
102
+ expand_objects_exe = file if File.basename(file) =~ EXPAND_OBJECTS_REGEX
103
+ end
104
+
105
+ raise "Could not find EnergyPlus executable in #{energyplus_path}" unless energyplus_exe
106
+ raise "Could not find ExpandObjects executable in #{energyplus_path}" unless expand_objects_exe
107
+
108
+ logger.info "EnergyPlus executable path is #{energyplus_exe}"
109
+ logger.info "ExpandObjects executable path is #{expand_objects_exe}"
110
+
111
+ return energyplus_files, energyplus_exe, expand_objects_exe
112
+ end
113
+
114
+ # Configures and executes the EnergyPlus simulation and checks to see if the simulation was successful
115
+ #
116
+ # @param [String] run_directory Directory to execute the EnergyPlus simulation in. It is assumed that this
117
+ # directory already has the IDF and weather file in it
118
+ # @param [String] energyplus_path (nil) Optional path to override the default path associated with the
119
+ # OpenStudio package being used
120
+ # @param [Object] output_adapter (nil) Optional output adapter to update
121
+ # @param [Object] logger (nil) Optional logger, will log to STDOUT if none provided
122
+ # @return [Void]
123
+ #
124
+ def call_energyplus(run_directory, energyplus_path = nil, output_adapter = nil, logger = nil, workflow_json = nil)
125
+ logger ||= ::Logger.new(STDOUT) unless logger
126
+
127
+ current_dir = Dir.pwd
128
+ energyplus_path ||= find_energyplus
129
+ logger.info "EnergyPlus path is #{energyplus_path}"
130
+ energyplus_files, energyplus_exe, expand_objects_exe = prepare_energyplus_dir(run_directory, logger, energyplus_path)
131
+ Dir.chdir(run_directory)
132
+ logger.info "Starting simulation in run directory: #{Dir.pwd}"
133
+
134
+ if !@options[:skip_expand_objects]
135
+ command = popen_command("\"#{expand_objects_exe}\"")
136
+ logger.info "Running command '#{command}'"
137
+ File.open('stdout-expandobject', 'w') do |file|
138
+ ::IO.popen(command) do |io|
139
+ while (line = io.gets)
140
+ file << line
141
+ end
142
+ end
143
+ end
144
+
145
+ # Check if expand objects did anything
146
+ if File.exist? 'expanded.idf'
147
+ FileUtils.mv('in.idf', 'pre-expand.idf', force: true) if File.exist?('in.idf')
148
+ FileUtils.mv('expanded.idf', 'in.idf', force: true)
149
+ end
150
+ end
151
+
152
+ # create stdout
153
+ command = popen_command("\"#{energyplus_exe}\" 2>&1")
154
+ logger.info "Running command '#{command}'"
155
+ File.open('stdout-energyplus', 'w') do |file|
156
+ ::IO.popen(command) do |io|
157
+ while (line = io.gets)
158
+ file << line
159
+ output_adapter.communicate_energyplus_stdout(line) if output_adapter
160
+ end
161
+ end
162
+ end
163
+ r = $?
164
+
165
+ logger.info "EnergyPlus returned '#{r}'"
166
+ unless r.to_i.zero?
167
+ logger.warn 'EnergyPlus returned a non-zero exit code. Check the stdout-energyplus log.'
168
+ end
169
+
170
+ if File.exist? 'eplusout.err'
171
+ eplus_err = File.read('eplusout.err').force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
172
+
173
+ if workflow_json
174
+ begin
175
+ if !@options[:fast]
176
+ workflow_json.setEplusoutErr(eplus_err)
177
+ end
178
+ rescue StandardError => e
179
+ # older versions of OpenStudio did not have the setEplusoutErr method
180
+ end
181
+ end
182
+
183
+ if eplus_err =~ /EnergyPlus Terminated--Fatal Error Detected/
184
+ raise 'EnergyPlus Terminated with a Fatal Error. Check eplusout.err log.'
185
+ end
186
+ end
187
+
188
+ if File.exist? 'eplusout.end'
189
+ f = File.read('eplusout.end').force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
190
+ warnings_count = f[/(\d*).Warning/, 1]
191
+ error_count = f[/(\d*).Severe.Errors/, 1]
192
+ logger.info "EnergyPlus finished with #{warnings_count} warnings and #{error_count} severe errors"
193
+ if f =~ /EnergyPlus Terminated--Fatal Error Detected/
194
+ raise 'EnergyPlus Terminated with a Fatal Error. Check eplusout.err log.'
195
+ end
196
+ else
197
+ raise 'EnergyPlus failed and did not create an eplusout.end file. Check the stdout-energyplus log.'
198
+ end
199
+ rescue StandardError => e
200
+ log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
201
+ logger.error log_message
202
+ raise log_message
203
+ ensure
204
+ logger.info "Ensuring 'clean' directory"
205
+ clean_directory(run_directory, energyplus_files, logger)
206
+
207
+ Dir.chdir(current_dir)
208
+ logger.info 'EnergyPlus Completed'
209
+ end
210
+
211
+ # Run this code before running EnergyPlus to make sure the reporting variables are setup correctly
212
+ #
213
+ # @param [Object] idf The IDF Workspace to be simulated
214
+ # @return [Void]
215
+ #
216
+ def energyplus_preprocess(idf, logger)
217
+ logger.info 'Running EnergyPlus Preprocess'
218
+
219
+ new_objects = []
220
+
221
+ needs_sqlobj = idf.getObjectsByType('Output:SQLite'.to_IddObjectType).empty?
222
+
223
+ if needs_sqlobj
224
+ # just add this, we don't allow this type in add_energyplus_output_request
225
+ logger.info 'Adding SQL Output to IDF'
226
+ object = OpenStudio::IdfObject.load('Output:SQLite,SimpleAndTabular;').get
227
+ idf.addObjects(object)
228
+ end
229
+
230
+ # merge in monthly reports
231
+ EnergyPlus.monthly_report_idf_text.split(/^[\s]*$/).each do |object|
232
+ object = object.strip
233
+ next if object.empty?
234
+
235
+ new_objects << object
236
+ end
237
+
238
+ # These are needed for the calibration report
239
+ new_objects << 'Output:Meter:MeterFileOnly,Gas:Facility,Daily;'
240
+ new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Timestep;'
241
+ new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Daily;'
242
+
243
+ # Always add in the timestep facility meters
244
+ new_objects << 'Output:Meter,Electricity:Facility,Timestep;'
245
+ new_objects << 'Output:Meter,Gas:Facility,Timestep;'
246
+ new_objects << 'Output:Meter,DistrictCooling:Facility,Timestep;'
247
+ new_objects << 'Output:Meter,DistrictHeating:Facility,Timestep;'
248
+
249
+ new_objects.each do |obj|
250
+ object = OpenStudio::IdfObject.load(obj).get
251
+ OpenStudio::Workflow::Util::EnergyPlus.add_energyplus_output_request(idf, object)
252
+ end
253
+
254
+ logger.info 'Finished EnergyPlus Preprocess'
255
+ end
256
+
257
+ # examines object and determines whether or not to add it to the workspace
258
+ def self.add_energyplus_output_request(workspace, idf_object)
259
+ num_added = 0
260
+ idd_object = idf_object.iddObject
261
+
262
+ allowed_objects = []
263
+ allowed_objects << 'Output:Surfaces:List'
264
+ allowed_objects << 'Output:Surfaces:Drawing'
265
+ allowed_objects << 'Output:Schedules'
266
+ allowed_objects << 'Output:Constructions'
267
+ allowed_objects << 'Output:Table:TimeBins'
268
+ allowed_objects << 'Output:Table:Monthly'
269
+ allowed_objects << 'Output:Variable'
270
+ allowed_objects << 'Output:Meter'
271
+ allowed_objects << 'Output:Meter:MeterFileOnly'
272
+ allowed_objects << 'Output:Meter:Cumulative'
273
+ allowed_objects << 'Output:Meter:Cumulative:MeterFileOnly'
274
+ allowed_objects << 'Meter:Custom'
275
+ allowed_objects << 'Meter:CustomDecrement'
276
+ allowed_objects << 'EnergyManagementSystem:OutputVariable'
277
+
278
+ if allowed_objects.include?(idd_object.name)
279
+ unless check_for_object(workspace, idf_object, idd_object.type)
280
+ workspace.addObject(idf_object)
281
+ num_added += 1
282
+ end
283
+ end
284
+
285
+ allowed_unique_objects = []
286
+ # allowed_unique_objects << "Output:EnergyManagementSystem" # TODO: have to merge
287
+ # allowed_unique_objects << "OutputControl:SurfaceColorScheme" # TODO: have to merge
288
+ allowed_unique_objects << 'Output:Table:SummaryReports' # TODO: have to merge
289
+ # OutputControl:Table:Style # not allowed
290
+ # OutputControl:ReportingTolerances # not allowed
291
+ # Output:SQLite # not allowed
292
+
293
+ if allowed_unique_objects.include?(idf_object.iddObject.name)
294
+ if idf_object.iddObject.name == 'Output:Table:SummaryReports'
295
+ summary_reports = workspace.getObjectsByType(idf_object.iddObject.type)
296
+ if summary_reports.empty?
297
+ workspace.addObject(idf_object)
298
+ num_added += 1
299
+ else
300
+ merge_output_table_summary_reports(summary_reports[0], idf_object)
301
+ end
302
+ end
303
+ end
304
+
305
+ return num_added
306
+ end
307
+
308
+ # check to see if we have an exact match for this object already
309
+ def self.check_for_object(workspace, idf_object, idd_object_type)
310
+ workspace.getObjectsByType(idd_object_type).each do |object|
311
+ # all of these objects fields are data fields
312
+ if idf_object.dataFieldsEqual(object)
313
+ return true
314
+ end
315
+ end
316
+ return false
317
+ end
318
+
319
+ # merge all summary reports that are not in the current workspace
320
+ def self.merge_output_table_summary_reports(current_object, new_object)
321
+ current_fields = []
322
+ current_object.extensibleGroups.each do |current_extensible_group|
323
+ current_fields << current_extensible_group.getString(0).to_s
324
+ end
325
+
326
+ fields_to_add = []
327
+ new_object.extensibleGroups.each do |new_extensible_group|
328
+ field = new_extensible_group.getString(0).to_s
329
+ unless current_fields.include?(field)
330
+ current_fields << field
331
+ fields_to_add << field
332
+ end
333
+ end
334
+
335
+ unless fields_to_add.empty?
336
+ fields_to_add.each do |field|
337
+ values = OpenStudio::StringVector.new
338
+ values << field
339
+ current_object.pushExtensibleGroup(values)
340
+ end
341
+ return true
342
+ end
343
+
344
+ return false
345
+ end
346
+
347
+ def self.monthly_report_idf_text
348
+ <<-HEREDOC
349
+ Output:Table:Monthly,
350
+ Building Energy Performance - Electricity, !- Name
351
+ 2, !- Digits After Decimal
352
+ InteriorLights:Electricity, !- Variable or Meter 1 Name
353
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
354
+ ExteriorLights:Electricity, !- Variable or Meter 2 Name
355
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
356
+ InteriorEquipment:Electricity, !- Variable or Meter 3 Name
357
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
358
+ ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
359
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
360
+ Fans:Electricity, !- Variable or Meter 5 Name
361
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
362
+ Pumps:Electricity, !- Variable or Meter 6 Name
363
+ SumOrAverage, !- Aggregation Type for Variable or Meter 6
364
+ Heating:Electricity, !- Variable or Meter 7 Name
365
+ SumOrAverage, !- Aggregation Type for Variable or Meter 7
366
+ Cooling:Electricity, !- Variable or Meter 8 Name
367
+ SumOrAverage, !- Aggregation Type for Variable or Meter 8
368
+ HeatRejection:Electricity, !- Variable or Meter 9 Name
369
+ SumOrAverage, !- Aggregation Type for Variable or Meter 9
370
+ Humidifier:Electricity, !- Variable or Meter 10 Name
371
+ SumOrAverage, !- Aggregation Type for Variable or Meter 10
372
+ HeatRecovery:Electricity,!- Variable or Meter 11 Name
373
+ SumOrAverage, !- Aggregation Type for Variable or Meter 11
374
+ WaterSystems:Electricity,!- Variable or Meter 12 Name
375
+ SumOrAverage, !- Aggregation Type for Variable or Meter 12
376
+ Cogeneration:Electricity,!- Variable or Meter 13 Name
377
+ SumOrAverage, !- Aggregation Type for Variable or Meter 13
378
+ Refrigeration:Electricity,!- Variable or Meter 14 Name
379
+ SumOrAverage; !- Aggregation Type for Variable or Meter 14
380
+
381
+ Output:Table:Monthly,
382
+ Building Energy Performance - Natural Gas, !- Name
383
+ 2, !- Digits After Decimal
384
+ InteriorEquipment:Gas, !- Variable or Meter 1 Name
385
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
386
+ ExteriorEquipment:Gas, !- Variable or Meter 2 Name
387
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
388
+ Heating:Gas, !- Variable or Meter 3 Name
389
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
390
+ Cooling:Gas, !- Variable or Meter 4 Name
391
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
392
+ WaterSystems:Gas, !- Variable or Meter 5 Name
393
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
394
+ Cogeneration:Gas, !- Variable or Meter 6 Name
395
+ SumOrAverage; !- Aggregation Type for Variable or Meter 6
396
+
397
+ Output:Table:Monthly,
398
+ Building Energy Performance - District Heating, !- Name
399
+ 2, !- Digits After Decimal
400
+ InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
401
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
402
+ ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
403
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
404
+ InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
405
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
406
+ ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
407
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
408
+ Fans:DistrictHeating, !- Variable or Meter 5 Name
409
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
410
+ Pumps:DistrictHeating, !- Variable or Meter 6 Name
411
+ SumOrAverage, !- Aggregation Type for Variable or Meter 6
412
+ Heating:DistrictHeating, !- Variable or Meter 7 Name
413
+ SumOrAverage, !- Aggregation Type for Variable or Meter 7
414
+ Cooling:DistrictHeating, !- Variable or Meter 8 Name
415
+ SumOrAverage, !- Aggregation Type for Variable or Meter 8
416
+ HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
417
+ SumOrAverage, !- Aggregation Type for Variable or Meter 9
418
+ Humidifier:DistrictHeating, !- Variable or Meter 10 Name
419
+ SumOrAverage, !- Aggregation Type for Variable or Meter 10
420
+ HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
421
+ SumOrAverage, !- Aggregation Type for Variable or Meter 11
422
+ WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
423
+ SumOrAverage, !- Aggregation Type for Variable or Meter 12
424
+ Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
425
+ SumOrAverage; !- Aggregation Type for Variable or Meter 13
426
+
427
+ Output:Table:Monthly,
428
+ Building Energy Performance - District Cooling, !- Name
429
+ 2, !- Digits After Decimal
430
+ InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
431
+ SumOrAverage, !- Aggregation Type for Variable or Meter 1
432
+ ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
433
+ SumOrAverage, !- Aggregation Type for Variable or Meter 2
434
+ InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
435
+ SumOrAverage, !- Aggregation Type for Variable or Meter 3
436
+ ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
437
+ SumOrAverage, !- Aggregation Type for Variable or Meter 4
438
+ Fans:DistrictCooling, !- Variable or Meter 5 Name
439
+ SumOrAverage, !- Aggregation Type for Variable or Meter 5
440
+ Pumps:DistrictCooling, !- Variable or Meter 6 Name
441
+ SumOrAverage, !- Aggregation Type for Variable or Meter 6
442
+ Heating:DistrictCooling, !- Variable or Meter 7 Name
443
+ SumOrAverage, !- Aggregation Type for Variable or Meter 7
444
+ Cooling:DistrictCooling, !- Variable or Meter 8 Name
445
+ SumOrAverage, !- Aggregation Type for Variable or Meter 8
446
+ HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
447
+ SumOrAverage, !- Aggregation Type for Variable or Meter 9
448
+ Humidifier:DistrictCooling, !- Variable or Meter 10 Name
449
+ SumOrAverage, !- Aggregation Type for Variable or Meter 10
450
+ HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
451
+ SumOrAverage, !- Aggregation Type for Variable or Meter 11
452
+ WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
453
+ SumOrAverage, !- Aggregation Type for Variable or Meter 12
454
+ Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
455
+ SumOrAverage; !- Aggregation Type for Variable or Meter 13
456
+
457
+ Output:Table:Monthly,
458
+ Building Energy Performance - Electricity Peak Demand, !- Name
459
+ 2, !- Digits After Decimal
460
+ Electricity:Facility, !- Variable or Meter 1 Name
461
+ Maximum, !- Aggregation Type for Variable or Meter 1
462
+ InteriorLights:Electricity, !- Variable or Meter 1 Name
463
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
464
+ ExteriorLights:Electricity, !- Variable or Meter 2 Name
465
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
466
+ InteriorEquipment:Electricity, !- Variable or Meter 3 Name
467
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
468
+ ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
469
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
470
+ Fans:Electricity, !- Variable or Meter 5 Name
471
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
472
+ Pumps:Electricity, !- Variable or Meter 6 Name
473
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
474
+ Heating:Electricity, !- Variable or Meter 7 Name
475
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
476
+ Cooling:Electricity, !- Variable or Meter 8 Name
477
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
478
+ HeatRejection:Electricity, !- Variable or Meter 9 Name
479
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
480
+ Humidifier:Electricity, !- Variable or Meter 10 Name
481
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
482
+ HeatRecovery:Electricity,!- Variable or Meter 11 Name
483
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
484
+ WaterSystems:Electricity,!- Variable or Meter 12 Name
485
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
486
+ Cogeneration:Electricity,!- Variable or Meter 13 Name
487
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
488
+
489
+ Output:Table:Monthly,
490
+ Building Energy Performance - Natural Gas Peak Demand, !- Name
491
+ 2, !- Digits After Decimal
492
+ Gas:Facility, !- Variable or Meter 1 Name
493
+ Maximum, !- Aggregation Type for Variable or Meter 1
494
+ InteriorEquipment:Gas, !- Variable or Meter 1 Name
495
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
496
+ ExteriorEquipment:Gas, !- Variable or Meter 2 Name
497
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
498
+ Heating:Gas, !- Variable or Meter 3 Name
499
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
500
+ Cooling:Gas, !- Variable or Meter 4 Name
501
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
502
+ WaterSystems:Gas, !- Variable or Meter 5 Name
503
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
504
+ Cogeneration:Gas, !- Variable or Meter 6 Name
505
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 6
506
+
507
+ Output:Table:Monthly,
508
+ Building Energy Performance - District Heating Peak Demand, !- Name
509
+ 2, !- Digits After Decimal
510
+ DistrictHeating:Facility, !- Variable or Meter 1 Name
511
+ Maximum, !- Aggregation Type for Variable or Meter 1
512
+ InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
513
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
514
+ ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
515
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
516
+ InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
517
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
518
+ ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
519
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
520
+ Fans:DistrictHeating, !- Variable or Meter 5 Name
521
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
522
+ Pumps:DistrictHeating, !- Variable or Meter 6 Name
523
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
524
+ Heating:DistrictHeating, !- Variable or Meter 7 Name
525
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
526
+ Cooling:DistrictHeating, !- Variable or Meter 8 Name
527
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
528
+ HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
529
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
530
+ Humidifier:DistrictHeating, !- Variable or Meter 10 Name
531
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
532
+ HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
533
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
534
+ WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
535
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
536
+ Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
537
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
538
+
539
+ Output:Table:Monthly,
540
+ Building Energy Performance - District Cooling Peak Demand, !- Name
541
+ 2, !- Digits After Decimal
542
+ DistrictCooling:Facility, !- Variable or Meter 1 Name
543
+ Maximum, !- Aggregation Type for Variable or Meter 1
544
+ InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
545
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
546
+ ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
547
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
548
+ InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
549
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
550
+ ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
551
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
552
+ Fans:DistrictCooling, !- Variable or Meter 5 Name
553
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
554
+ Pumps:DistrictCooling, !- Variable or Meter 6 Name
555
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
556
+ Heating:DistrictCooling, !- Variable or Meter 7 Name
557
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
558
+ Cooling:DistrictCooling, !- Variable or Meter 8 Name
559
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
560
+ HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
561
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
562
+ Humidifier:DistrictCooling, !- Variable or Meter 10 Name
563
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
564
+ HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
565
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
566
+ WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
567
+ ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
568
+ Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
569
+ ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
570
+ HEREDOC
571
+ end
572
+ end
573
+ end
574
+ end
575
+ end