urbanopt-reporting 0.2.0 → 0.3.3

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +19 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
  4. data/.github/pull_request_template.md +13 -0
  5. data/.rdoc_options +36 -0
  6. data/CHANGELOG.md +43 -1
  7. data/LICENSE.md +1 -1
  8. data/RDOC_MAIN.md +10 -0
  9. data/deploy_docs.sh +5 -0
  10. data/doc_templates/LICENSE.md +1 -1
  11. data/doc_templates/copyright_erb.txt +1 -1
  12. data/doc_templates/copyright_js.txt +1 -1
  13. data/doc_templates/copyright_ruby.txt +1 -1
  14. data/docs/.gitignore +3 -0
  15. data/docs/.vuepress/components/InnerJsonSchema.vue +76 -0
  16. data/docs/.vuepress/components/JsonSchema.vue +12 -0
  17. data/docs/.vuepress/components/ScenarioSchema.vue +12 -0
  18. data/docs/.vuepress/components/StaticLink.vue +8 -0
  19. data/docs/.vuepress/config.js +25 -0
  20. data/docs/.vuepress/highlight.js +8 -0
  21. data/docs/.vuepress/json-schema-deref-loader.js +22 -0
  22. data/docs/.vuepress/public/custom_rdoc_styles.css +78 -0
  23. data/docs/.vuepress/styles/palette.styl +1 -0
  24. data/docs/.vuepress/utils.js +17 -0
  25. data/docs/README.md +9 -0
  26. data/docs/package-lock.json +10018 -0
  27. data/docs/package.json +30 -0
  28. data/docs/schemas/scenario-schema.md +3 -0
  29. data/lib/measures/default_feature_reports/LICENSE.md +1 -1
  30. data/lib/measures/default_feature_reports/measure.rb +231 -87
  31. data/lib/measures/default_feature_reports/measure.xml +11 -11
  32. data/lib/measures/export_modelica_loads/LICENSE.md +27 -0
  33. data/lib/measures/export_modelica_loads/README.md +26 -0
  34. data/lib/measures/export_modelica_loads/README.md.erb +42 -0
  35. data/lib/measures/export_modelica_loads/docs/.gitkeep +0 -0
  36. data/lib/measures/export_modelica_loads/measure.rb +367 -0
  37. data/lib/measures/export_modelica_loads/measure.xml +92 -0
  38. data/lib/measures/export_modelica_loads/resources/report.html.in +13 -0
  39. data/lib/measures/export_time_series_modelica/LICENSE.md +1 -0
  40. data/lib/measures/export_time_series_modelica/README.md +59 -0
  41. data/lib/measures/export_time_series_modelica/README.md.erb +42 -0
  42. data/lib/measures/export_time_series_modelica/docs/.gitkeep +0 -0
  43. data/lib/measures/export_time_series_modelica/measure.rb +433 -0
  44. data/lib/measures/export_time_series_modelica/measure.xml +147 -0
  45. data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +399 -0
  46. data/lib/measures/export_time_series_modelica/resources/report.html.in +13 -0
  47. data/lib/urbanopt/reporting/default_reports/end_uses.rb +52 -38
  48. data/lib/urbanopt/reporting/default_reports/feature_report.rb +79 -8
  49. data/lib/urbanopt/reporting/default_reports/location.rb +11 -11
  50. data/lib/urbanopt/reporting/default_reports/program.rb +86 -86
  51. data/lib/urbanopt/reporting/default_reports/reporting_period.rb +98 -78
  52. data/lib/urbanopt/reporting/default_reports/scenario_report.rb +7 -4
  53. data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +15 -0
  54. data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +108 -80
  55. data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +10 -10
  56. data/lib/urbanopt/reporting/version.rb +1 -1
  57. data/urbanopt-reporting-gem.gemspec +4 -4
  58. metadata +50 -13
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.0</schema_version>
4
4
  <name>default_feature_reports</name>
5
5
  <uid>9ee3135a-8070-4408-bfa1-b75fecf9dd4f</uid>
6
- <version_id>1f4eb28d-d586-4c10-8d23-f3495054ce1e</version_id>
7
- <version_modified>20200921T204602Z</version_modified>
6
+ <version_id>d4f5b2e2-f93d-4ce2-9c68-ed29714fdc0c</version_id>
7
+ <version_modified>20201208T230102Z</version_modified>
8
8
  <xml_checksum>FB304155</xml_checksum>
9
9
  <class_name>DefaultFeatureReports</class_name>
10
10
  <display_name>DefaultFeatureReports</display_name>
@@ -126,17 +126,23 @@
126
126
  <usage_type>test</usage_type>
127
127
  <checksum>CC4BFFAF</checksum>
128
128
  </file>
129
+ <file>
130
+ <filename>README.md</filename>
131
+ <filetype>md</filetype>
132
+ <usage_type>readme</usage_type>
133
+ <checksum>0B68E96D</checksum>
134
+ </file>
129
135
  <file>
130
136
  <filename>LICENSE.md</filename>
131
137
  <filetype>md</filetype>
132
138
  <usage_type>license</usage_type>
133
- <checksum>D8541540</checksum>
139
+ <checksum>BBD19F47</checksum>
134
140
  </file>
135
141
  <file>
136
142
  <filename>default_feature_reports_test.rb</filename>
137
143
  <filetype>rb</filetype>
138
144
  <usage_type>test</usage_type>
139
- <checksum>A5706600</checksum>
145
+ <checksum>19681175</checksum>
140
146
  </file>
141
147
  <file>
142
148
  <version>
@@ -147,13 +153,7 @@
147
153
  <filename>measure.rb</filename>
148
154
  <filetype>rb</filetype>
149
155
  <usage_type>script</usage_type>
150
- <checksum>3C7B646E</checksum>
151
- </file>
152
- <file>
153
- <filename>README.md</filename>
154
- <filetype>md</filetype>
155
- <usage_type>readme</usage_type>
156
- <checksum>0B68E96D</checksum>
156
+ <checksum>48AEB753</checksum>
157
157
  </file>
158
158
  </files>
159
159
  </measure>
@@ -0,0 +1,27 @@
1
+ OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted
4
+ provided that the following conditions are met:
5
+
6
+ (1) Redistributions of source code must retain the above copyright notice, this list of conditions
7
+ and the following disclaimer.
8
+
9
+ (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10
+ and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+
12
+ (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
13
+ or promote products derived from this software without specific prior written permission from the
14
+ respective party.
15
+
16
+ (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
17
+ derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
18
+ designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
21
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
23
+ OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,26 @@
1
+
2
+
3
+ ###### (Automatically generated documentation)
4
+
5
+ # Export Modelica Loads
6
+
7
+ ## Description
8
+ Use the results from the EnergyPlus simulation to generate a load file for use in Modelica. This will create a MOS and a CSV file of the heating, cooling, and hot water loads.
9
+
10
+ ## Modeler Description
11
+
12
+
13
+ ## Measure Type
14
+ ReportingMeasure
15
+
16
+ ## Taxonomy
17
+
18
+
19
+ ## Arguments
20
+
21
+
22
+
23
+
24
+ This measure does not have any user arguments
25
+
26
+
@@ -0,0 +1,42 @@
1
+ <%#= README.md.erb is used to auto-generate README.md. %>
2
+ <%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
3
+ ###### (Automatically generated documentation)
4
+
5
+ # <%= name %>
6
+
7
+ ## Description
8
+ <%= description %>
9
+
10
+ ## Modeler Description
11
+ <%= modelerDescription %>
12
+
13
+ ## Measure Type
14
+ <%= measureType %>
15
+
16
+ ## Taxonomy
17
+ <%= taxonomy %>
18
+
19
+ ## Arguments
20
+
21
+ <% arguments.each do |argument| %>
22
+ ### <%= argument[:display_name] %>
23
+ <%= argument[:description] %>
24
+ **Name:** <%= argument[:name] %>,
25
+ **Type:** <%= argument[:type] %>,
26
+ **Units:** <%= argument[:units] %>,
27
+ **Required:** <%= argument[:required] %>,
28
+ **Model Dependent:** <%= argument[:model_dependent] %>
29
+ <% end %>
30
+
31
+ <% if arguments.size == 0 %>
32
+ <%= "This measure does not have any user arguments" %>
33
+ <% end %>
34
+
35
+ <% if outputs.size > 0 %>
36
+ ## Outputs
37
+ <% output_names = [] %>
38
+ <% outputs.each do |output| %>
39
+ <% output_names << output[:display_name] %>
40
+ <% end %>
41
+ <%= output_names.join(", ") %>
42
+ <% end %>
@@ -0,0 +1,367 @@
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 HOLDER(S) AND ANY CONTRIBUTORS
24
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
27
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
28
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ # *******************************************************************************
35
+
36
+ require 'erb'
37
+
38
+ # start the measure
39
+ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
40
+ # human readable name
41
+ def name
42
+ # Measure name should be the title case of the class name.
43
+ return 'Export Modelica Loads'
44
+ end
45
+
46
+ def description
47
+ return 'Use the results from the EnergyPlus simulation to generate a load file for use in Modelica. This will create a MOS and a CSV file of the heating, cooling, and hot water loads.'
48
+ end
49
+
50
+ def modeler_description
51
+ return ''
52
+ end
53
+
54
+ def log(str)
55
+ puts "#{Time.now}: #{str}"
56
+ end
57
+
58
+ def arguments(_model)
59
+ args = OpenStudio::Measure::OSArgumentVector.new
60
+
61
+ # this measure does not require any user arguments, return an empty list
62
+ return args
63
+ end
64
+
65
+ # return a vector of IdfObject's to request EnergyPlus objects needed by the run method
66
+ def energyPlusOutputRequests(runner, user_arguments)
67
+ super(runner, user_arguments)
68
+
69
+ result = OpenStudio::IdfObjectVector.new
70
+
71
+ # To use the built-in error checking we need the model...
72
+ # get the last model and sql file
73
+ model = runner.lastOpenStudioModel
74
+ if model.empty?
75
+ runner.registerError('Cannot find last model.')
76
+ return false
77
+ end
78
+ model = model.get
79
+
80
+ # use the built-in error checking
81
+ if !runner.validateUserArguments(arguments(model), user_arguments)
82
+ return false
83
+ end
84
+
85
+ result << OpenStudio::IdfObject.load('Output:Variable,,Site Mains Water Temperature,hourly;').get
86
+ result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,hourly;').get
87
+ result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,hourly;').get
88
+ result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,hourly;').get
89
+ result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,hourly;').get
90
+ result << OpenStudio::IdfObject.load('Output:Meter,Heating:Gas,hourly;').get
91
+ result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,hourly;').get
92
+ result << OpenStudio::IdfObject.load('Output:Meter,Fans:Electricity,hourly;').get
93
+ result << OpenStudio::IdfObject.load('Output:Meter,InteriorEquipment:Electricity,hourly;').get # Joules
94
+ result << OpenStudio::IdfObject.load('Output:Meter,ExteriorLighting:Electricity,hourly;').get # Joules
95
+ result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,hourly;').get # Joules
96
+ result << OpenStudio::IdfObject.load('Output:Meter,Gas:Facility,hourly;').get # Joules
97
+ result << OpenStudio::IdfObject.load('Output:Meter,Heating:EnergyTransfer,hourly;').get # Joules
98
+ result << OpenStudio::IdfObject.load('Output:Meter,WaterSystems:EnergyTransfer,hourly;').get # Joules
99
+ # these variables are used for the modelica export.
100
+ result << OpenStudio::IdfObject.load('Output:Variable,*,Zone Predicted Sensible Load to Setpoint Heat Transfer Rate,hourly;').get # watts according to e+
101
+ result << OpenStudio::IdfObject.load('Output:Variable,*,Water Heater Total Demand Heat Transfer Rate,hourly;').get # Watts
102
+
103
+ return result
104
+ end
105
+
106
+ def extract_timeseries_into_matrix(sqlfile, data, variable_name, key_value = nil, default_if_empty=0)
107
+ log "Executing query for #{variable_name}"
108
+ column_name = variable_name
109
+ if key_value
110
+ ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name, key_value)
111
+ # ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
112
+ column_name += "_#{key_value}"
113
+ else
114
+ ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
115
+ # ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
116
+ end
117
+ log 'Iterating over timeseries'
118
+ column = [column_name.delete(':').delete(' ')] # Set the header of the data to the variable name, removing : and spaces
119
+
120
+ if ts.empty?
121
+ log "No time series for #{variable_name}:#{key_value}... defaulting to #{default_if_empty}"
122
+ # needs to be data.size-1 since the column name is already stored above (+=)
123
+ column += [default_if_empty] * (data.size-1)
124
+ else
125
+ ts = ts.get if ts.respond_to?(:get)
126
+ ts = ts.first if ts.respond_to?(:first)
127
+
128
+ start = Time.now
129
+ # Iterating in OpenStudio can take up to 60 seconds with 10min data. The quick_proc takes 0.03 seconds.
130
+ # for i in 0..ts.values.size - 1
131
+ # log "... at #{i}" if i % 10000 == 0
132
+ # column << ts.values[i]
133
+ # end
134
+
135
+ quick_proc = ts.values.to_s.split(',')
136
+
137
+ # the first and last have some cleanup items because of the Vector method
138
+ quick_proc[0] = quick_proc[0].gsub(/^.*\(/, '')
139
+ quick_proc[-1] = quick_proc[-1].delete(')')
140
+ column += quick_proc
141
+
142
+ log "Took #{Time.now - start} to iterate"
143
+ end
144
+
145
+ log 'Appending column to data'
146
+
147
+ # append the data to the end of the rows
148
+ if column.size == data.size
149
+ data.each_index do |index|
150
+ data[index] << column[index]
151
+ end
152
+ end
153
+
154
+ log "Finished extracting #{variable_name}"
155
+ end
156
+
157
+ def create_new_variable_sum(data, new_var_name, include_str, options=nil)
158
+ var_info = {
159
+ name: new_var_name,
160
+ var_indexes: []
161
+ }
162
+ data.each_with_index do |row, index|
163
+ if index.zero?
164
+ # Get the index of the columns to add
165
+ row.each do |c|
166
+ if c.include? include_str
167
+ var_info[:var_indexes] << row.index(c)
168
+ end
169
+ end
170
+
171
+ # add the new var to the header row
172
+ data[0] << var_info[:name]
173
+ else
174
+ # sum the values
175
+ sum = 0
176
+ var_info[:var_indexes].each do |var|
177
+ temp_v = row[var].to_f
178
+ if options.nil?
179
+ sum += temp_v
180
+ elsif options[:positive_only] && temp_v > 0
181
+ sum += temp_v
182
+ elsif options[:negative_only] && temp_v < 0
183
+ sum += temp_v
184
+ end
185
+ end
186
+
187
+ # Also round the data here, because we don't need 10 decimals
188
+ data[index] << sum.round(1)
189
+ end
190
+ end
191
+ end
192
+
193
+ def run(runner, user_arguments)
194
+ super(runner, user_arguments)
195
+
196
+ # get the last model and sql file
197
+ model = runner.lastOpenStudioModel
198
+ if model.empty?
199
+ runner.registerError('Cannot find last model.')
200
+ return false
201
+ end
202
+ model = model.get
203
+
204
+ # use the built-in error checking
205
+ return false unless runner.validateUserArguments(arguments(model), user_arguments)
206
+
207
+ # get the last model and sql file
208
+ model = runner.lastOpenStudioModel
209
+ if model.empty?
210
+ runner.registerError('Cannot find last model.')
211
+ return false
212
+ end
213
+ model = model.get
214
+
215
+ sqlFile = runner.lastEnergyPlusSqlFile
216
+ if sqlFile.empty?
217
+ runner.registerError('Cannot find last sql file.')
218
+ return false
219
+ end
220
+ sqlFile = sqlFile.get
221
+ model.setSqlFile(sqlFile)
222
+
223
+ # create a new csv with the values and save to the reports directory.
224
+ # assumptions:
225
+ # - all the variables exist
226
+ # - data are the same length
227
+
228
+ # initialize the rows with the header
229
+ log 'Starting to process Timeseries data'
230
+ # Initial header row
231
+ rows = [
232
+ ['Date Time', 'Month', 'Day', 'Day of Week', 'Hour', 'Minute', 'SecondsFromStart']
233
+ ]
234
+
235
+ # just grab one of the variables to get the date/time stamps
236
+ # ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', 'Cooling:Electricity')
237
+ ts = sqlFile.timeSeries('RUN PERIOD 1', 'Hourly', 'Cooling:Electricity')
238
+ unless ts.empty?
239
+ ts = ts.first
240
+ dt_base = nil
241
+ # Save off the date time values
242
+ ts.dateTimes.each_with_index do |dt, index|
243
+ runner.registerInfo("My index is #{index}")
244
+ dt_base = DateTime.parse(dt.to_s) if dt_base.nil?
245
+ dt_current = DateTime.parse(dt.to_s)
246
+ rows << [
247
+ DateTime.parse(dt.to_s).strftime('%m/%d/%Y %H:%M'),
248
+ dt.date.monthOfYear.value,
249
+ dt.date.dayOfMonth,
250
+ dt.date.dayOfWeek.value,
251
+ dt.time.hours,
252
+ dt.time.minutes,
253
+ dt_current.to_time.to_i - dt_base.to_time.to_i
254
+ ]
255
+ end
256
+ end
257
+
258
+ # add in the other variables by columns -- should really pull this from the report variables defined above
259
+ extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Drybulb Temperature', 'Environment', 0)
260
+ extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Relative Humidity', 'Environment', 0)
261
+ extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Electricity', nil, 0)
262
+ extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Gas', nil, 0)
263
+ extract_timeseries_into_matrix(sqlFile, rows, 'Cooling:Electricity', nil, 0)
264
+ extract_timeseries_into_matrix(sqlFile, rows, 'Electricity:Facility', nil, 0)
265
+ extract_timeseries_into_matrix(sqlFile, rows, 'Gas:Facility', nil, 0)
266
+ extract_timeseries_into_matrix(sqlFile, rows, 'Heating:EnergyTransfer', nil, 0)
267
+ extract_timeseries_into_matrix(sqlFile, rows, 'WaterSystems:EnergyTransfer', nil, 0)
268
+
269
+ # get all zones and save the names for later use in aggregation.
270
+ tz_names = []
271
+ model.getThermalZones.each do |tz|
272
+ tz_names << tz.name.get if tz.name.is_initialized
273
+ extract_timeseries_into_matrix(sqlFile, rows, 'Zone Predicted Sensible Load to Setpoint Heat Transfer Rate', tz_names.last, 0)
274
+ extract_timeseries_into_matrix(sqlFile, rows, 'Water Heater Heating Rate', tz_names.last, 0)
275
+ end
276
+
277
+ # sum up a couple of the columns and create a new columns
278
+ create_new_variable_sum(rows, 'TotalSensibleLoad', 'ZonePredictedSensibleLoadtoSetpointHeatTransferRate')
279
+ create_new_variable_sum(rows, 'TotalCoolingSensibleLoad', 'ZonePredictedSensibleLoadtoSetpointHeatTransferRate', negative_only: true)
280
+ create_new_variable_sum(rows, 'TotalHeatingSensibleLoad', 'ZonePredictedSensibleLoadtoSetpointHeatTransferRate', positive_only: true)
281
+ create_new_variable_sum(rows, 'TotalWaterHeating', 'WaterHeaterHeatingRate')
282
+
283
+ # convert this to CSV object
284
+ File.open('./building_loads.csv', 'w') do |f|
285
+ rows.each do |row|
286
+ f << row.join(',') << "\n"
287
+ end
288
+ end
289
+
290
+ # covert the row data into the format needed by modelica
291
+ modelica_data = [['seconds', 'cooling', 'heating', 'waterheating']]
292
+ seconds_index = nil
293
+ total_water_heating_index = nil
294
+ total_cooling_sensible_index = nil
295
+ total_heating_sensible_index = nil
296
+ peak_cooling = 0
297
+ peak_heating = 0
298
+ peak_water_heating = 0
299
+ rows.each_with_index do |row, index|
300
+ if index.zero?
301
+ seconds_index = row.index('SecondsFromStart')
302
+ total_cooling_sensible_index = row.index('TotalCoolingSensibleLoad')
303
+ total_heating_sensible_index = row.index('TotalHeatingSensibleLoad')
304
+ total_water_heating_index = row.index('TotalWaterHeating')
305
+ else
306
+ new_data = [
307
+ row[seconds_index],
308
+ row[total_cooling_sensible_index],
309
+ row[total_heating_sensible_index],
310
+ row[total_water_heating_index]
311
+ ]
312
+
313
+ modelica_data << new_data
314
+
315
+ # store the peaks
316
+ peak_cooling = row[total_cooling_sensible_index] if row[total_cooling_sensible_index] < peak_cooling
317
+ peak_heating = row[total_heating_sensible_index] if row[total_heating_sensible_index] > peak_heating
318
+ peak_water_heating = row[total_water_heating_index] if row[total_water_heating_index] > peak_water_heating
319
+ end
320
+ end
321
+
322
+ File.open('./modelica.mos', 'w') do |f|
323
+ f << "#1\n"
324
+ f << "#Heating and Cooling Model loads from OpenStudio Prototype Buildings\n"
325
+ f << "# Building Type: {{BUILDINGTYPE}}\n"
326
+ f << "# Climate Zone: {{CLIMATEZONE}}\n"
327
+ f << "# Vintage: {{VINTAGE}}\n"
328
+ f << "# Simulation ID (for debugging): {{SIMID}}\n"
329
+ f << "# URL: https://github.com/urbanopt/openstudio-prototype-loads\n"
330
+ f << "\n"
331
+ f << "#First column: Seconds in the year (loads are hourly)\n"
332
+ f << "#Second column: cooling loads in Watts (as negative numbers).\n"
333
+ f << "#Third column: space heating loads in Watts\n"
334
+ f << "#Fourth column: water heating in Watts\n"
335
+ f << "\n"
336
+ f << "#Peak space cooling load = #{peak_cooling} Watts\n"
337
+ f << "#Peak space heating load = #{peak_heating} Watts\n"
338
+ f << "#Peak water heating load = #{peak_water_heating} Watts\n"
339
+ f << "double tab1(8760,4)\n"
340
+ modelica_data.each_with_index do |row, index|
341
+ next if index.zero?
342
+ f << row.join(';') << "\n"
343
+ end
344
+ end
345
+
346
+ # Find the total runtime for energyplus and save it into a registerValue
347
+ total_time = -999
348
+ location_of_file = ['../eplusout.end', './run/eplusout.end']
349
+ first_index = location_of_file.map {|f| File.exist?(f)}.index(true)
350
+ if first_index
351
+ match = File.read(location_of_file[first_index]).to_s.match(/Elapsed.Time=(.*)hr(.*)min(.*)sec/)
352
+ total_time = match[1].to_i * 3600 + match[2].to_i * 60 + match[3].to_f
353
+ end
354
+
355
+ runner.registerValue('energyplus_runtime', total_time, 'sec')
356
+ runner.registerValue('peak_cooling_load', peak_cooling, 'W')
357
+ runner.registerValue('peak_heating_load', peak_heating, 'W')
358
+ runner.registerValue('peak_water_heating', peak_water_heating, 'W')
359
+
360
+ return true
361
+ ensure
362
+ sqlFile.close if sqlFile
363
+ end
364
+ end
365
+
366
+ # register the measure to be used by the application
367
+ ExportModelicaLoads.new.registerWithApplication