openstudio-workflow 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +10 -0
- data/README.md +97 -0
- data/Rakefile +20 -0
- data/lib/openstudio/workflow/adapter.rb +68 -0
- data/lib/openstudio/workflow/adapters/local.rb +110 -0
- data/lib/openstudio/workflow/adapters/mongo.rb +259 -0
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +128 -0
- data/lib/openstudio/workflow/jobs/run_openstudio/monthly_report.idf +218 -0
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +344 -0
- data/lib/openstudio/workflow/jobs/run_postprocess/packaged_measures/README.md +5 -0
- data/lib/openstudio/workflow/jobs/run_postprocess/packaged_measures/StandardReports/measure.rb +212 -0
- data/lib/openstudio/workflow/jobs/run_postprocess/packaged_measures/StandardReports/measure.xml +53 -0
- data/lib/openstudio/workflow/jobs/run_postprocess/packaged_measures/StandardReports/resources/report.html.in +298 -0
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +549 -0
- data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +45 -0
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +279 -0
- data/lib/openstudio/workflow/multi_delegator.rb +48 -0
- data/lib/openstudio/workflow/run.rb +258 -0
- data/lib/openstudio/workflow/version.rb +24 -0
- data/lib/openstudio-workflow.rb +69 -0
- metadata +134 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
######################################################################
|
2
|
+
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
######################################################################
|
19
|
+
|
20
|
+
class RunEnergyplus
|
21
|
+
|
22
|
+
# Initialize
|
23
|
+
# param directory: base directory where the simulation files are prepared
|
24
|
+
# param logger: logger object in which to write log messages
|
25
|
+
def initialize(directory, logger, adapter, options = {})
|
26
|
+
|
27
|
+
energyplus_path = nil
|
28
|
+
if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
29
|
+
energyplus_path = 'C:/EnergyPlus-8-1-0'
|
30
|
+
else
|
31
|
+
energyplus_path ='/usr/local/EnergyPlus-8-1-0'
|
32
|
+
end
|
33
|
+
|
34
|
+
defaults = {
|
35
|
+
energyplus_path: energyplus_path
|
36
|
+
}
|
37
|
+
@options = defaults.merge(options)
|
38
|
+
|
39
|
+
# TODO: use openstudio tool finder for this
|
40
|
+
@directory = directory
|
41
|
+
@run_directory = "#{@directory}/run"
|
42
|
+
@adapter = adapter
|
43
|
+
@logger = logger
|
44
|
+
@results = {}
|
45
|
+
|
46
|
+
@logger.info "#{self.class} passed the following options #{@options}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def perform
|
50
|
+
@logger.info "Calling #{__method__} in the #{self.class} class"
|
51
|
+
@logger.info "Current directory is #{@directory}"
|
52
|
+
|
53
|
+
# Ensure that the directory is created (but it should already be at this point)
|
54
|
+
FileUtils.mkdir_p(@run_directory)
|
55
|
+
|
56
|
+
# verify that the OSM, IDF, and the Weather files are in the run directory as the 'in.*' format
|
57
|
+
if @options[:run_openstudio][:weather_filename] && File.exist?(@options[:run_openstudio][:weather_filename])
|
58
|
+
# verify that it is named in.epw
|
59
|
+
unless File.basename(@options[:run_openstudio][:weather_filename]).downcase == 'in.idf'
|
60
|
+
FileUtils.copy(@options[:run_openstudio][:weather_filename], "#{@run_directory}/in.epw")
|
61
|
+
end
|
62
|
+
else
|
63
|
+
fail "EPW file not found or not sent to #{self.class}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Need to check the in.idf and in.osm
|
67
|
+
#FileUtils.copy(options[:osm], "#{@run_directory}/in.osm")
|
68
|
+
#FileUtils.copy(options[:idf], "#{@run_directory}/in.idf")
|
69
|
+
|
70
|
+
# can't create symlinks because the /vagrant mount is actually a windows mount
|
71
|
+
@logger.info "Copying EnergyPlus files to run directory: #{@run_directory}"
|
72
|
+
FileUtils.copy("#{@options[:energyplus_path]}/libbcvtb.so", "#{@run_directory}/libbcvtb.so")
|
73
|
+
FileUtils.copy("#{@options[:energyplus_path]}/libepexpat.so", "#{@run_directory}/libepexpat.so")
|
74
|
+
FileUtils.copy("#{@options[:energyplus_path]}/libepfmiimport.so", "#{@run_directory}/libepfmiimport.so")
|
75
|
+
FileUtils.copy("#{@options[:energyplus_path]}/libDElight.so", "#{@run_directory}/libDElight.so")
|
76
|
+
FileUtils.copy("#{@options[:energyplus_path]}/libDElight.so", "#{@run_directory}/libDElight.so")
|
77
|
+
FileUtils.copy("#{@options[:energyplus_path]}/ExpandObjects", "#{@run_directory}/ExpandObjects")
|
78
|
+
FileUtils.copy("#{@options[:energyplus_path]}/EnergyPlus", "#{@run_directory}/EnergyPlus")
|
79
|
+
FileUtils.copy("#{@options[:energyplus_path]}/Energy+.idd", "#{@run_directory}/Energy+.idd")
|
80
|
+
|
81
|
+
@results = call_energyplus
|
82
|
+
|
83
|
+
@results
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def call_energyplus
|
89
|
+
begin
|
90
|
+
current_dir = Dir.pwd
|
91
|
+
Dir.chdir(@run_directory)
|
92
|
+
@logger.info "Starting simulation in run directory: #{Dir.pwd}"
|
93
|
+
|
94
|
+
File.open('stdout-expandobject', 'w') do |file|
|
95
|
+
IO.popen('ExpandObjects') do |io|
|
96
|
+
while (line = io.gets)
|
97
|
+
file << line
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Check if expand objects did anythying
|
103
|
+
if File.exist? 'expanded.idf'
|
104
|
+
FileUtils.mv('in.idf', 'pre-expand.idf', force: true) if File.exist?('in.idf')
|
105
|
+
FileUtils.mv('expanded.idf', 'in.idf', force: true)
|
106
|
+
end
|
107
|
+
|
108
|
+
# create stdout
|
109
|
+
File.open('stdout-energyplus', 'w') do |file|
|
110
|
+
IO.popen('EnergyPlus') do |io|
|
111
|
+
while (line = io.gets)
|
112
|
+
file << line
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
rescue Exception => e
|
118
|
+
log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
119
|
+
@logger.error log_message
|
120
|
+
ensure
|
121
|
+
Dir.chdir(current_dir)
|
122
|
+
@logger.info 'EnergyPlus Completed'
|
123
|
+
end
|
124
|
+
|
125
|
+
# TODO: get list of all the files that are generated and return
|
126
|
+
{}
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
Output:Table:Monthly,
|
2
|
+
Building Energy Performance - Electricity, !- Name
|
3
|
+
2, !- Digits After Decimal
|
4
|
+
InteriorLights:Electricity, !- Variable or Meter 1 Name
|
5
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 1
|
6
|
+
ExteriorLights:Electricity, !- Variable or Meter 2 Name
|
7
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 2
|
8
|
+
InteriorEquipment:Electricity, !- Variable or Meter 3 Name
|
9
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 3
|
10
|
+
ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
|
11
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 4
|
12
|
+
Fans:Electricity, !- Variable or Meter 5 Name
|
13
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 5
|
14
|
+
Pumps:Electricity, !- Variable or Meter 6 Name
|
15
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 6
|
16
|
+
Heating:Electricity, !- Variable or Meter 7 Name
|
17
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 7
|
18
|
+
Cooling:Electricity, !- Variable or Meter 8 Name
|
19
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 8
|
20
|
+
HeatRejection:Electricity, !- Variable or Meter 9 Name
|
21
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 9
|
22
|
+
Humidifier:Electricity, !- Variable or Meter 10 Name
|
23
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 10
|
24
|
+
HeatRecovery:Electricity,!- Variable or Meter 11 Name
|
25
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 11
|
26
|
+
WaterSystems:Electricity,!- Variable or Meter 12 Name
|
27
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 12
|
28
|
+
Cogeneration:Electricity,!- Variable or Meter 13 Name
|
29
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 13
|
30
|
+
Refrigeration:Electricity,!- Variable or Meter 14 Name
|
31
|
+
SumOrAverage; !- Aggregation Type for Variable or Meter 14
|
32
|
+
Output:Table:Monthly,
|
33
|
+
Building Energy Performance - Natural Gas, !- Name
|
34
|
+
2, !- Digits After Decimal
|
35
|
+
InteriorEquipment:Gas, !- Variable or Meter 1 Name
|
36
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 1
|
37
|
+
ExteriorEquipment:Gas, !- Variable or Meter 2 Name
|
38
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 2
|
39
|
+
Heating:Gas, !- Variable or Meter 3 Name
|
40
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 3
|
41
|
+
Cooling:Gas, !- Variable or Meter 4 Name
|
42
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 4
|
43
|
+
WaterSystems:Gas, !- Variable or Meter 5 Name
|
44
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 5
|
45
|
+
Cogeneration:Gas, !- Variable or Meter 6 Name
|
46
|
+
SumOrAverage; !- Aggregation Type for Variable or Meter 6
|
47
|
+
Output:Table:Monthly,
|
48
|
+
Building Energy Performance - District Heating, !- Name
|
49
|
+
2, !- Digits After Decimal
|
50
|
+
InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
|
51
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 1
|
52
|
+
ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
|
53
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 2
|
54
|
+
InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
|
55
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 3
|
56
|
+
ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
|
57
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 4
|
58
|
+
Fans:DistrictHeating, !- Variable or Meter 5 Name
|
59
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 5
|
60
|
+
Pumps:DistrictHeating, !- Variable or Meter 6 Name
|
61
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 6
|
62
|
+
Heating:DistrictHeating, !- Variable or Meter 7 Name
|
63
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 7
|
64
|
+
Cooling:DistrictHeating, !- Variable or Meter 8 Name
|
65
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 8
|
66
|
+
HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
|
67
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 9
|
68
|
+
Humidifier:DistrictHeating, !- Variable or Meter 10 Name
|
69
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 10
|
70
|
+
HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
|
71
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 11
|
72
|
+
WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
|
73
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 12
|
74
|
+
Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
|
75
|
+
SumOrAverage; !- Aggregation Type for Variable or Meter 13
|
76
|
+
Output:Table:Monthly,
|
77
|
+
Building Energy Performance - District Cooling, !- Name
|
78
|
+
2, !- Digits After Decimal
|
79
|
+
InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
|
80
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 1
|
81
|
+
ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
|
82
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 2
|
83
|
+
InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
|
84
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 3
|
85
|
+
ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
|
86
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 4
|
87
|
+
Fans:DistrictCooling, !- Variable or Meter 5 Name
|
88
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 5
|
89
|
+
Pumps:DistrictCooling, !- Variable or Meter 6 Name
|
90
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 6
|
91
|
+
Heating:DistrictCooling, !- Variable or Meter 7 Name
|
92
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 7
|
93
|
+
Cooling:DistrictCooling, !- Variable or Meter 8 Name
|
94
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 8
|
95
|
+
HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
|
96
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 9
|
97
|
+
Humidifier:DistrictCooling, !- Variable or Meter 10 Name
|
98
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 10
|
99
|
+
HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
|
100
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 11
|
101
|
+
WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
|
102
|
+
SumOrAverage, !- Aggregation Type for Variable or Meter 12
|
103
|
+
Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
|
104
|
+
SumOrAverage; !- Aggregation Type for Variable or Meter 13
|
105
|
+
Output:Table:Monthly,
|
106
|
+
Building Energy Performance - Electricity Peak Demand, !- Name
|
107
|
+
2, !- Digits After Decimal
|
108
|
+
Electricity:Facility, !- Variable or Meter 1 Name
|
109
|
+
Maximum, !- Aggregation Type for Variable or Meter 1
|
110
|
+
InteriorLights:Electricity, !- Variable or Meter 1 Name
|
111
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
|
112
|
+
ExteriorLights:Electricity, !- Variable or Meter 2 Name
|
113
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
|
114
|
+
InteriorEquipment:Electricity, !- Variable or Meter 3 Name
|
115
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
|
116
|
+
ExteriorEquipment:Electricity, !- Variable or Meter 4 Name
|
117
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
|
118
|
+
Fans:Electricity, !- Variable or Meter 5 Name
|
119
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
|
120
|
+
Pumps:Electricity, !- Variable or Meter 6 Name
|
121
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
|
122
|
+
Heating:Electricity, !- Variable or Meter 7 Name
|
123
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
|
124
|
+
Cooling:Electricity, !- Variable or Meter 8 Name
|
125
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
|
126
|
+
HeatRejection:Electricity, !- Variable or Meter 9 Name
|
127
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
|
128
|
+
Humidifier:Electricity, !- Variable or Meter 10 Name
|
129
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
|
130
|
+
HeatRecovery:Electricity,!- Variable or Meter 11 Name
|
131
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
|
132
|
+
WaterSystems:Electricity,!- Variable or Meter 12 Name
|
133
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
|
134
|
+
Cogeneration:Electricity,!- Variable or Meter 13 Name
|
135
|
+
ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
|
136
|
+
Output:Table:Monthly,
|
137
|
+
Building Energy Performance - Natural Gas Peak Demand, !- Name
|
138
|
+
2, !- Digits After Decimal
|
139
|
+
Gas:Facility, !- Variable or Meter 1 Name
|
140
|
+
Maximum, !- Aggregation Type for Variable or Meter 1
|
141
|
+
InteriorEquipment:Gas, !- Variable or Meter 1 Name
|
142
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
|
143
|
+
ExteriorEquipment:Gas, !- Variable or Meter 2 Name
|
144
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
|
145
|
+
Heating:Gas, !- Variable or Meter 3 Name
|
146
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
|
147
|
+
Cooling:Gas, !- Variable or Meter 4 Name
|
148
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
|
149
|
+
WaterSystems:Gas, !- Variable or Meter 5 Name
|
150
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
|
151
|
+
Cogeneration:Gas, !- Variable or Meter 6 Name
|
152
|
+
ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 6
|
153
|
+
Output:Table:Monthly,
|
154
|
+
Building Energy Performance - District Heating Peak Demand, !- Name
|
155
|
+
2, !- Digits After Decimal
|
156
|
+
DistrictHeating:Facility, !- Variable or Meter 1 Name
|
157
|
+
Maximum, !- Aggregation Type for Variable or Meter 1
|
158
|
+
InteriorLights:DistrictHeating, !- Variable or Meter 1 Name
|
159
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
|
160
|
+
ExteriorLights:DistrictHeating, !- Variable or Meter 2 Name
|
161
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
|
162
|
+
InteriorEquipment:DistrictHeating, !- Variable or Meter 3 Name
|
163
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
|
164
|
+
ExteriorEquipment:DistrictHeating, !- Variable or Meter 4 Name
|
165
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
|
166
|
+
Fans:DistrictHeating, !- Variable or Meter 5 Name
|
167
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
|
168
|
+
Pumps:DistrictHeating, !- Variable or Meter 6 Name
|
169
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
|
170
|
+
Heating:DistrictHeating, !- Variable or Meter 7 Name
|
171
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
|
172
|
+
Cooling:DistrictHeating, !- Variable or Meter 8 Name
|
173
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
|
174
|
+
HeatRejection:DistrictHeating, !- Variable or Meter 9 Name
|
175
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
|
176
|
+
Humidifier:DistrictHeating, !- Variable or Meter 10 Name
|
177
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
|
178
|
+
HeatRecovery:DistrictHeating,!- Variable or Meter 11 Name
|
179
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
|
180
|
+
WaterSystems:DistrictHeating,!- Variable or Meter 12 Name
|
181
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
|
182
|
+
Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
|
183
|
+
ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
|
184
|
+
Output:Table:Monthly,
|
185
|
+
Building Energy Performance - District Cooling Peak Demand, !- Name
|
186
|
+
2, !- Digits After Decimal
|
187
|
+
DistrictCooling:Facility, !- Variable or Meter 1 Name
|
188
|
+
Maximum, !- Aggregation Type for Variable or Meter 1
|
189
|
+
InteriorLights:DistrictCooling, !- Variable or Meter 1 Name
|
190
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 1
|
191
|
+
ExteriorLights:DistrictCooling, !- Variable or Meter 2 Name
|
192
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 2
|
193
|
+
InteriorEquipment:DistrictCooling, !- Variable or Meter 3 Name
|
194
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 3
|
195
|
+
ExteriorEquipment:DistrictCooling, !- Variable or Meter 4 Name
|
196
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 4
|
197
|
+
Fans:DistrictCooling, !- Variable or Meter 5 Name
|
198
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
|
199
|
+
Pumps:DistrictCooling, !- Variable or Meter 6 Name
|
200
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 6
|
201
|
+
Heating:DistrictCooling, !- Variable or Meter 7 Name
|
202
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 7
|
203
|
+
Cooling:DistrictCooling, !- Variable or Meter 8 Name
|
204
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 8
|
205
|
+
HeatRejection:DistrictCooling, !- Variable or Meter 9 Name
|
206
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 9
|
207
|
+
Humidifier:DistrictCooling, !- Variable or Meter 10 Name
|
208
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 10
|
209
|
+
HeatRecovery:DistrictCooling,!- Variable or Meter 11 Name
|
210
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 11
|
211
|
+
WaterSystems:DistrictCooling,!- Variable or Meter 12 Name
|
212
|
+
ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
|
213
|
+
Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
|
214
|
+
ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
|
215
|
+
Output:Meter,Electricity:Facility,Timestep; !- [J]
|
216
|
+
Output:Meter,Gas:Facility,Timestep; !- [J]
|
217
|
+
Output:Meter,DistrictCooling:Facility,Timestep; !- [J]
|
218
|
+
Output:Meter,DistrictHeating:Facility,Timestep; !- [J]
|
@@ -0,0 +1,344 @@
|
|
1
|
+
######################################################################
|
2
|
+
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
######################################################################
|
19
|
+
|
20
|
+
# TODO: I hear that measures can step on each other if not run in their own directory
|
21
|
+
class RunOpenstudio
|
22
|
+
CRASH_ON_NO_WORKFLOW_VARIABLE = false
|
23
|
+
|
24
|
+
# Initialize
|
25
|
+
# param directory: base directory where the simulation files are prepared
|
26
|
+
# param logger: logger object in which to write log messages
|
27
|
+
def initialize(directory, logger, adapter, options = {})
|
28
|
+
defaults = {format: 'hash', use_monthly_reports: false, analysis_root_path: '.'}
|
29
|
+
@options = defaults.merge(options)
|
30
|
+
@directory = directory
|
31
|
+
# TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
|
32
|
+
@run_directory = "#{@directory}/run"
|
33
|
+
@adapter = adapter
|
34
|
+
@results = {}
|
35
|
+
@logger = logger
|
36
|
+
@logger.info "#{self.class} passed the following options #{@options}"
|
37
|
+
|
38
|
+
# initialize instance variables that are needed in the perform section
|
39
|
+
@model = nil
|
40
|
+
@model_idf = nil
|
41
|
+
@analysis_json = nil
|
42
|
+
# TODO: rename datapoint_json to just datapoint
|
43
|
+
@datapoint_json = nil
|
44
|
+
@output_attributes = {}
|
45
|
+
@report_measures = []
|
46
|
+
@measure_type_lookup = {
|
47
|
+
:openstudio_measure => 'RubyMeasure',
|
48
|
+
:energyplus_measure => 'EnergyPlusMeasure',
|
49
|
+
:reporting_measure => 'ReportingMeasure'
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def perform
|
54
|
+
@logger.info "Calling #{__method__} in the #{self.class} class"
|
55
|
+
@logger.info "Current directory is #{@directory}"
|
56
|
+
|
57
|
+
@logger.info "Retrieving datapoint and problem"
|
58
|
+
@datapoint_json = @adapter.get_datapoint(@directory, @options)
|
59
|
+
@analysis_json = @adapter.get_problem(@directory, @options)
|
60
|
+
|
61
|
+
if @analysis_json && @analysis_json[:analysis]
|
62
|
+
@model = load_seed_model
|
63
|
+
load_weather_file
|
64
|
+
|
65
|
+
apply_measures(:openstudio_measure)
|
66
|
+
|
67
|
+
translate_to_energyplus
|
68
|
+
|
69
|
+
apply_measures(:energyplus_measure)
|
70
|
+
|
71
|
+
@logger.info "Measure output attributes JSON is #{@output_attributes}"
|
72
|
+
File.open("#{@run_directory}/measure_attributes.json", 'w') {
|
73
|
+
|f| f << JSON.pretty_generate(@output_attributes)
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
save_osm_and_idf
|
78
|
+
|
79
|
+
@results
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def save_osm_and_idf
|
85
|
+
# save the data
|
86
|
+
a = Time.now
|
87
|
+
osm_filename = "#{@run_directory}/out_raw.osm"
|
88
|
+
File.open(osm_filename, 'w') { |f| f << @model.to_s }
|
89
|
+
b = Time.now
|
90
|
+
@logger.info "Ruby write took #{b.to_f - a.to_f}"
|
91
|
+
|
92
|
+
a = Time.now
|
93
|
+
osm_filename = "#{@run_directory}/in.osm"
|
94
|
+
@model.save(OpenStudio::Path.new(osm_filename), true)
|
95
|
+
b = Time.now
|
96
|
+
@logger.info "OpenStudio write took #{b.to_f - a.to_f}"
|
97
|
+
|
98
|
+
# Run EnergyPlus using run energyplus script
|
99
|
+
idf_filename = "#{@run_directory}/in.idf"
|
100
|
+
File.open(idf_filename, 'w') { |f| f << @model_idf.to_s }
|
101
|
+
|
102
|
+
# TODO: convert this to an OpenStudio method instead of substituting the data as text
|
103
|
+
if @options[:use_monthly_reports]
|
104
|
+
@logger.info 'Adding monthly reports to EnergyPlus IDF'
|
105
|
+
to_append = File.read(File.join(File.dirname(__FILE__), 'monthly_report.idf'))
|
106
|
+
File.open(idf_filename, 'a') do |handle|
|
107
|
+
handle.puts to_append
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
@results[:osm] = File.expand_path(osm_filename)
|
112
|
+
@results[:idf] = File.expand_path(idf_filename)
|
113
|
+
end
|
114
|
+
|
115
|
+
def load_seed_model
|
116
|
+
model = nil
|
117
|
+
@logger.info 'Loading seed model'
|
118
|
+
|
119
|
+
baseline_model_path = nil
|
120
|
+
# Unique case to use the previous generated OSM as the seed
|
121
|
+
if @options[:run_xml] && @options[:run_xml][:osm_filename]
|
122
|
+
if File.exist? @options[:run_xml][:osm_filename]
|
123
|
+
baseline_model_path = @options[:run_xml][:osm_filename]
|
124
|
+
end
|
125
|
+
elsif @analysis_json[:analysis][:seed]
|
126
|
+
@logger.info "Seed model is #{@analysis_json[:analysis][:seed]}"
|
127
|
+
if @analysis_json[:analysis][:seed][:path]
|
128
|
+
|
129
|
+
# assume that the seed model has been placed in the directory
|
130
|
+
baseline_model_path = File.expand_path(
|
131
|
+
File.join(@options[:analysis_root_path], @analysis_json[:analysis][:seed][:path]))
|
132
|
+
else
|
133
|
+
fail 'No seed model path in JSON defined'
|
134
|
+
end
|
135
|
+
else
|
136
|
+
fail 'No seed model block'
|
137
|
+
end
|
138
|
+
|
139
|
+
if baseline_model_path
|
140
|
+
if File.exist? baseline_model_path
|
141
|
+
@logger.info "Reading in baseline model #{baseline_model_path}"
|
142
|
+
translator = OpenStudio::OSVersion::VersionTranslator.new
|
143
|
+
model = translator.loadModel(baseline_model_path)
|
144
|
+
fail 'OpenStudio model is empty or could not be loaded' if model.empty?
|
145
|
+
model = model.get
|
146
|
+
else
|
147
|
+
fail "Seed model '#{baseline_model_path}' did not exist"
|
148
|
+
end
|
149
|
+
else
|
150
|
+
fail "No baseline/seed model found"
|
151
|
+
end
|
152
|
+
|
153
|
+
model
|
154
|
+
end
|
155
|
+
|
156
|
+
# Save the weather file to the instance variable
|
157
|
+
def load_weather_file
|
158
|
+
weather_filename = nil
|
159
|
+
if @options[:run_xml] && @options[:run_xml][:weather_filename]
|
160
|
+
if File.exist? @options[:run_xml][:weather_filename]
|
161
|
+
weather_filename = @options[:run_xml][:weather_filename]
|
162
|
+
end
|
163
|
+
elsif @analysis_json[:analysis][:weather_file]
|
164
|
+
if @analysis_json[:analysis][:weather_file][:path]
|
165
|
+
weather_filename = File.expand_path(
|
166
|
+
File.join(@options[:analysis_root_path], @analysis_json[:analysis][:weather_file][:path]))
|
167
|
+
else
|
168
|
+
fail 'No weather file path defined'
|
169
|
+
end
|
170
|
+
else
|
171
|
+
fail 'No weather file block defined'
|
172
|
+
end
|
173
|
+
|
174
|
+
unless File.exist?(weather_filename)
|
175
|
+
fail "Could not find weather file for simulation #{weather_filename}"
|
176
|
+
end
|
177
|
+
|
178
|
+
@results[:weather_filename] = weather_filename
|
179
|
+
|
180
|
+
weather_filename
|
181
|
+
end
|
182
|
+
|
183
|
+
# Forward translate to energyplus
|
184
|
+
def translate_to_energyplus
|
185
|
+
if @model_idf.nil?
|
186
|
+
@logger.info 'Translate object to EnergyPlus IDF in Prep for EnergyPlus Measure'
|
187
|
+
a = Time.now
|
188
|
+
# ensure objects exist for reporting purposes
|
189
|
+
@model.getFacility
|
190
|
+
@model.getBuilding
|
191
|
+
forward_translator = OpenStudio::EnergyPlus::ForwardTranslator.new
|
192
|
+
@model_idf = forward_translator.translateModel(@model)
|
193
|
+
b = Time.now
|
194
|
+
@logger.info "Translate object to energyplus IDF took #{b.to_f - a.to_f}"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def apply_arguments(argument_map, argument)
|
199
|
+
success = true
|
200
|
+
|
201
|
+
if argument[:value]
|
202
|
+
@logger.info "Setting argument value #{argument[:name]} to #{argument[:value]}"
|
203
|
+
|
204
|
+
v = argument_map[argument[:name]]
|
205
|
+
fail 'Could not find argument map in measure' unless v
|
206
|
+
value_set = v.setValue(argument[:value])
|
207
|
+
fail "Could not set argument #{argument[:name]} of value #{argument[:value]} on model" unless value_set
|
208
|
+
argument_map[argument[:name]] = v.clone
|
209
|
+
else
|
210
|
+
fail "Value for argument '#{argument[:name]}' not set in argument list" if CRASH_ON_NO_WORKFLOW_VARIABLE
|
211
|
+
@logger.warn "Value for argument '#{argument[:name]}' not set in argument list therefore will use default"
|
212
|
+
#success = false
|
213
|
+
|
214
|
+
# TODO: what is the fail case (success = false?)
|
215
|
+
end
|
216
|
+
|
217
|
+
success
|
218
|
+
end
|
219
|
+
|
220
|
+
# Apply the variable values to the measure argument map object
|
221
|
+
def apply_variables(argument_map, variable)
|
222
|
+
success = true
|
223
|
+
|
224
|
+
# save the uuid of the variable
|
225
|
+
variable_uuid = variable[:uuid].to_sym
|
226
|
+
if variable[:argument]
|
227
|
+
variable_name = variable[:argument][:name]
|
228
|
+
|
229
|
+
# Get the value from the data point json that was set via R / Problem Formulation
|
230
|
+
if @datapoint_json[:data_point]
|
231
|
+
if @datapoint_json[:data_point][:set_variable_values]
|
232
|
+
if @datapoint_json[:data_point][:set_variable_values][variable_uuid]
|
233
|
+
@logger.info "Setting variable '#{variable_name}' to #{@datapoint_json[:data_point][:set_variable_values][variable_uuid]}"
|
234
|
+
v = argument_map[variable_name]
|
235
|
+
fail 'Could not find argument map in measure' unless v
|
236
|
+
variable_value = @datapoint_json[:data_point][:set_variable_values][variable_uuid]
|
237
|
+
value_set = v.setValue(variable_value)
|
238
|
+
fail "Could not set variable '#{variable_name}' of value #{variable_value} on model" unless value_set
|
239
|
+
argument_map[variable_name] = v.clone
|
240
|
+
else
|
241
|
+
fail "[ERROR] Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object" if CRASH_ON_NO_WORKFLOW_VARIABLE
|
242
|
+
@logger.warn "Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
|
243
|
+
# success = false
|
244
|
+
end
|
245
|
+
else
|
246
|
+
fail 'No block for set_variable_values in data point record'
|
247
|
+
end
|
248
|
+
else
|
249
|
+
fail 'No block for data_point in data_point record'
|
250
|
+
end
|
251
|
+
else
|
252
|
+
fail "Variable '#{variable_name}' is defined but no argument is present"
|
253
|
+
end
|
254
|
+
|
255
|
+
success
|
256
|
+
end
|
257
|
+
|
258
|
+
def apply_measure(workflow_item)
|
259
|
+
measure_path = workflow_item[:measure_definition_directory]
|
260
|
+
measure_name = workflow_item[:measure_definition_class_name]
|
261
|
+
|
262
|
+
@logger.info "Loading measure in relative path #{measure_path}"
|
263
|
+
measure_file_path = File.expand_path(
|
264
|
+
File.join(@options[:analysis_root_path], measure_path, 'measure.rb'))
|
265
|
+
fail "Measure file does not exist #{measure_name} in #{measure_file_path}" unless File.exist? measure_file_path
|
266
|
+
|
267
|
+
require measure_file_path
|
268
|
+
measure = Object.const_get(measure_name).new
|
269
|
+
runner = OpenStudio::Ruleset::OSRunner.new
|
270
|
+
result = nil
|
271
|
+
|
272
|
+
arguments = measure.arguments(@model)
|
273
|
+
|
274
|
+
# Create argument map and initialize all the arguments
|
275
|
+
argument_map = OpenStudio::Ruleset::OSArgumentMap.new
|
276
|
+
arguments.each do |v|
|
277
|
+
argument_map[v.name] = v.clone
|
278
|
+
end
|
279
|
+
|
280
|
+
@logger.info "Iterating over arguments for workflow item '#{workflow_item[:name]}'"
|
281
|
+
if workflow_item[:arguments]
|
282
|
+
workflow_item[:arguments].each do |argument|
|
283
|
+
success = apply_arguments(argument_map, argument)
|
284
|
+
fail "could not set arguments" unless success
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
@logger.info "Iterating over variables for workflow item '#{workflow_item[:name]}'"
|
289
|
+
if workflow_item[:variables]
|
290
|
+
workflow_item[:variables].each do |variable|
|
291
|
+
success = apply_variables(argument_map, variable)
|
292
|
+
fail "could not set variables" unless success
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
begin
|
297
|
+
if workflow_item[:measure_type] == 'RubyMeasure'
|
298
|
+
@logger.info "Running runner for '#{workflow_item[:name]}'"
|
299
|
+
measure.run(@model, runner, argument_map)
|
300
|
+
@logger.info "Finished runner for '#{workflow_item[:name]}'"
|
301
|
+
elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
|
302
|
+
measure.run(@model_idf, runner, argument_map)
|
303
|
+
elsif workflow_item[:measure_type] == 'ReportingMeasure'
|
304
|
+
report_measures << measure
|
305
|
+
end
|
306
|
+
rescue Exception => e
|
307
|
+
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
308
|
+
fail log_message
|
309
|
+
end
|
310
|
+
|
311
|
+
begin
|
312
|
+
result = runner.result
|
313
|
+
|
314
|
+
@logger.info result.initialCondition.get.logMessage unless result.initialCondition.empty?
|
315
|
+
@logger.info result.finalCondition.get.logMessage unless result.finalCondition.empty?
|
316
|
+
|
317
|
+
result.warnings.each { |w| @logger.info w.logMessage }
|
318
|
+
result.errors.each { |w| @logger.info w.logMessage }
|
319
|
+
result.info.each { |w| @logger.info w.logMessage }
|
320
|
+
rescue Exception => e
|
321
|
+
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
322
|
+
fail log_message
|
323
|
+
end
|
324
|
+
|
325
|
+
begin
|
326
|
+
measure_attributes = JSON.parse(OpenStudio::toJSON(result.attributes), symbolize_names: true)
|
327
|
+
@output_attributes[workflow_item[:name].to_sym] = measure_attributes[:attributes]
|
328
|
+
rescue Exception => e
|
329
|
+
log_message = "TODO: #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
330
|
+
@logger.warn log_message
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def apply_measures(measure_type)
|
335
|
+
if @analysis_json[:analysis][:problem] && @analysis_json[:analysis][:problem][:workflow]
|
336
|
+
@logger.info "Applying measures for #{@measure_type_lookup[measure_type]}"
|
337
|
+
@analysis_json[:analysis][:problem][:workflow].each do |wf|
|
338
|
+
next unless wf[:measure_type] == @measure_type_lookup[measure_type]
|
339
|
+
|
340
|
+
apply_measure(wf)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|