openstudio-calibration 0.1.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +5 -0
  4. data/CHANGELOG.md +23 -8
  5. data/Gemfile +0 -3
  6. data/Jenkinsfile +6 -2
  7. data/README.md +2 -2
  8. data/Rakefile +5 -5
  9. data/lib/measures/TimeseriesObjectiveFunction/README.md +5 -171
  10. data/lib/measures/TimeseriesObjectiveFunction/measure.rb +2 -6
  11. data/lib/measures/TimeseriesObjectiveFunction/measure.xml +89 -13
  12. data/lib/measures/TimeseriesObjectiveFunction/resources/report.html.erb +2 -0
  13. data/lib/measures/TimeseriesPlot/README.md +5 -35
  14. data/lib/measures/TimeseriesPlot/measure.xml +27 -11
  15. data/lib/measures/TimeseriesPlot/resources/report.html.erb +2 -0
  16. data/lib/measures/zone_report/README.md +2 -2
  17. data/lib/measures/zone_report/measure.rb +1 -1
  18. data/lib/measures/zone_report/measure.xml +14 -12
  19. data/lib/{openstudio-calibration-measures.rb → openstudio-calibration.rb} +1 -1
  20. data/lib/openstudio/{calibration_measures.rb → calibration.rb} +2 -2
  21. data/lib/openstudio/{calibration_measures → calibration}/extension.rb +1 -1
  22. data/lib/openstudio/{calibration_measures → calibration}/version.rb +2 -2
  23. data/openstudio-calibration.gemspec +38 -0
  24. metadata +37 -54
  25. data/lib/measures/AddMonthlyUtilityData/tests/AddMonthlyUtilityData_Test.rb +0 -88
  26. data/lib/measures/AddMonthlyUtilityData/tests/electric_billed_usages.json +0 -198
  27. data/lib/measures/AddMonthlyUtilityData/tests/gas_billed_usages.json +0 -198
  28. data/lib/measures/CalibrationReports/tests/CalibrationReports_Test.rb +0 -523
  29. data/lib/measures/CalibrationReports/tests/ExampleModel.osm +0 -10497
  30. data/lib/measures/CalibrationReports/tests/ExampleModelNoDemandInput.osm +0 -10560
  31. data/lib/measures/CalibrationReports/tests/ExampleModelNoGasInput.osm +0 -10456
  32. data/lib/measures/CalibrationReports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +0 -8768
  33. data/lib/measures/CalibrationReportsEnhanced/tests/CalibrationReportsEnhanced_Test.rb +0 -734
  34. data/lib/measures/CalibrationReportsEnhanced/tests/ExampleModel.osm +0 -10497
  35. data/lib/measures/CalibrationReportsEnhanced/tests/ExampleModel_FuelOil.osm +0 -12740
  36. data/lib/measures/CalibrationReportsEnhanced/tests/USA_CO_Golden-NREL.724666_TMY3.epw +0 -8768
  37. data/lib/measures/CalibrationReportsEnhanced21/LICENSE.md +0 -27
  38. data/lib/measures/CalibrationReportsEnhanced21/README.md +0 -109
  39. data/lib/measures/CalibrationReportsEnhanced21/README.md.erb +0 -42
  40. data/lib/measures/CalibrationReportsEnhanced21/measure.rb +0 -690
  41. data/lib/measures/CalibrationReportsEnhanced21/measure.xml +0 -269
  42. data/lib/measures/CalibrationReportsEnhanced21/resources/report.html.in +0 -380
  43. data/lib/measures/MaalkaMonthlyJSONUtilityData/LICENSE.md +0 -27
  44. data/lib/measures/MaalkaMonthlyJSONUtilityData/README.md +0 -104
  45. data/lib/measures/MaalkaMonthlyJSONUtilityData/README.md.erb +0 -42
  46. data/lib/measures/MaalkaMonthlyJSONUtilityData/measure.rb +0 -304
  47. data/lib/measures/MaalkaMonthlyJSONUtilityData/measure.xml +0 -216
  48. data/openstudio-calibration-measures.gemspec +0 -30
@@ -1,27 +0,0 @@
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.
@@ -1,109 +0,0 @@
1
-
2
-
3
- ###### (Automatically generated documentation)
4
-
5
- # Calibration Reports Enhanced
6
-
7
- ## Description
8
- This measure is intended for calibibration of modeled results against user entered utility bill.
9
-
10
- ## Modeler Description
11
- Measure looks at consumption for electricity and natural gas, and demand for electricity. It is inteneded to be used with no more than one gas an electric bills. Each bill can have multiple billing periods. Make sure ot use an AMY matching the utility data time frame.
12
-
13
- ## Measure Type
14
- ReportingMeasure
15
-
16
- ## Taxonomy
17
-
18
-
19
- ## Arguments
20
-
21
-
22
- ### Electric NMBE limit (%)
23
-
24
- **Name:** electric_nmbe_limit,
25
- **Type:** Double,
26
- **Units:** ,
27
- **Required:** true,
28
- **Model Dependent:** false
29
-
30
- ### Electric CVRMSE limit (%)
31
-
32
- **Name:** electric_cvrmse_limit,
33
- **Type:** Double,
34
- **Units:** ,
35
- **Required:** true,
36
- **Model Dependent:** false
37
-
38
- ### Gas NMBE limit (%)
39
-
40
- **Name:** gas_nmbe_limit,
41
- **Type:** Double,
42
- **Units:** ,
43
- **Required:** true,
44
- **Model Dependent:** false
45
-
46
- ### Gas CVRMSE limit (%)
47
-
48
- **Name:** gas_cvrmse_limit,
49
- **Type:** Double,
50
- **Units:** ,
51
- **Required:** true,
52
- **Model Dependent:** false
53
-
54
-
55
-
56
-
57
-
58
- ## Outputs
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
- electricity_consumption_actual, electricity_consumption_modeled, electricity_consumption_cvrmse, electricity_consumption_nmbe, electricity_sum_of_squares, electricity_dof, electricity_rmse, electricity_peak_demand_nmbe, electricity_peak_demand_actual, electricity_peak_demand_modeled, natural_gas_consumption_actual, natural_gas_consumption_modeled, natural_gas_consumption_cvrmse, natural_gas_consumption_nmbe, natural_gas_sum_of_squares, natural_gas_dof, natural_gas_rmse, total_sum_of_squares, total_dof, total_rmse, electricity_cvrmse_within_limit, electricity_nmbe_within_limit, natural_gas_cvrmse_within_limit, natural_gas_nmbe_within_limit
@@ -1,42 +0,0 @@
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 %>
@@ -1,690 +0,0 @@
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
- require 'json'
38
-
39
- # start the measure
40
- class CalibrationReportsEnhanced21 < OpenStudio::Measure::ReportingMeasure
41
- # define the name that a user will see, this method may be deprecated as
42
- # the display name in PAT comes from the name field in measure.xml
43
- def name
44
- 'Calibration Reports Enhanced'
45
- end
46
-
47
- # human readable description
48
- def description
49
- 'This measure is intended for calibibration of modeled results against user entered utility bill.'
50
- end
51
-
52
- # human readable description of modeling approach
53
- def modeler_description
54
- 'Measure looks at consumption for electricity and natural gas, and demand for electricity. It is inteneded to be used with no more than one gas an electric bills. Each bill can have multiple billing periods. Make sure ot use an AMY matching the utility data time frame.'
55
- end
56
-
57
- # define the arguments that the user will input
58
- def arguments
59
- args = OpenStudio::Measure::OSArgumentVector.new
60
-
61
- # Electric NMBE limit
62
- electric_nmbe_limit = OpenStudio::Measure::OSArgument.makeDoubleArgument('electric_nmbe_limit', true)
63
- electric_nmbe_limit.setDisplayName('Electric NMBE limit (%)')
64
- electric_nmbe_limit.setDefaultValue(5.0)
65
- args << electric_nmbe_limit
66
-
67
- # Electric CVRMSE limit
68
- electric_cvrmse_limit = OpenStudio::Measure::OSArgument.makeDoubleArgument('electric_cvrmse_limit', true)
69
- electric_cvrmse_limit.setDisplayName('Electric CVRMSE limit (%)')
70
- electric_cvrmse_limit.setDefaultValue(15.0)
71
- args << electric_cvrmse_limit
72
-
73
- # Gas NMBE limit
74
- gas_nmbe_limit = OpenStudio::Measure::OSArgument.makeDoubleArgument('gas_nmbe_limit', true)
75
- gas_nmbe_limit.setDisplayName('Gas NMBE limit (%)')
76
- gas_nmbe_limit.setDefaultValue(5.0)
77
- args << gas_nmbe_limit
78
-
79
- # Gas CVRMSE limit
80
- gas_cvrmse_limit = OpenStudio::Measure::OSArgument.makeDoubleArgument('gas_cvrmse_limit', true)
81
- gas_cvrmse_limit.setDisplayName('Gas CVRMSE limit (%)')
82
- gas_cvrmse_limit.setDefaultValue(15.0)
83
- args << gas_cvrmse_limit
84
-
85
- args
86
- end # end the arguments method
87
-
88
- def outputs
89
- result = OpenStudio::Measure::OSOutputVector.new
90
-
91
- # electric consumption values
92
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_consumption_actual') # kWh
93
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_consumption_modeled') # kWh
94
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_consumption_cvrmse') # %
95
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_consumption_nmbe') # %
96
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_sum_of_squares') # kWh
97
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_dof') # na
98
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_rmse') # kWh^0.5
99
-
100
- # electric peak values
101
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_peak_demand_nmbe') # %
102
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_peak_demand_actual') # kW
103
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_peak_demand_modeled') # kW
104
-
105
- # gas consumption values
106
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_consumption_actual') # therms
107
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_consumption_modeled') # therms
108
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_consumption_cvrmse') # %
109
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_consumption_nmbe') # %
110
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_sum_of_squares') # therms
111
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_dof') # na
112
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_rmse') # therms^0.5
113
-
114
- # total fuel values (gas plus electric only? not district?)
115
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('total_sum_of_squares') # kBtu
116
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('total_dof') # na
117
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('total_rmse') # kBtu^0.5
118
-
119
- # within limit check values
120
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_cvrmse_within_limit') # na
121
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('electricity_nmbe_within_limit') # na
122
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_cvrmse_within_limit') # na
123
- result << OpenStudio::Measure::OSOutput.makeDoubleOutput('natural_gas_nmbe_within_limit') # na
124
-
125
- result
126
- end
127
-
128
- # define what happens when the measure is run
129
- def run(runner, user_arguments)
130
- super(runner, user_arguments)
131
-
132
- # use the built-in error checking
133
- return false unless runner.validateUserArguments(arguments, user_arguments)
134
-
135
- electric_nmbe_limit = runner.getDoubleArgumentValue('electric_nmbe_limit', user_arguments)
136
- electric_cvrmse_limit = runner.getDoubleArgumentValue('electric_cvrmse_limit', user_arguments)
137
- gas_nmbe_limit = runner.getDoubleArgumentValue('gas_nmbe_limit', user_arguments)
138
- gas_cvrmse_limit = runner.getDoubleArgumentValue('gas_cvrmse_limit', user_arguments)
139
-
140
- os_version = OpenStudio::VersionString.new(OpenStudio.openStudioVersion)
141
- min_version_feature1 = OpenStudio::VersionString.new('1.2.2')
142
-
143
- # get the last model and sql file
144
-
145
- model = runner.lastOpenStudioModel
146
- if model.empty?
147
- runner.registerError('Cannot find last model.')
148
- return false
149
- end
150
- model = model.get
151
-
152
- sqlFile = runner.lastEnergyPlusSqlFile
153
- if sqlFile.empty?
154
- runner.registerError('Cannot find last sql file.')
155
- return false
156
- end
157
- sqlFile = sqlFile.get
158
- model.setSqlFile(sqlFile)
159
-
160
- # put data into variables, these are available in the local scope binding
161
- # building_name = model.getBuilding.name.get
162
-
163
- web_asset_path = OpenStudio.getSharedResourcesPath / OpenStudio::Path.new('web_assets')
164
-
165
- energy = ''
166
-
167
- calibrationGuidelines = OpenStudio::Model::UtilityBill.calibrationGuidelines
168
- energy << 'var calibrationGuidelines = ['
169
- calibrationGuidelines.each do |calibrationGuideline|
170
- energy << '"' << calibrationGuideline << '",'
171
- end
172
- energy = energy[0..-2]
173
- energy << "];\n"
174
-
175
- maxNMBE = OpenStudio::Model::UtilityBill.maxNMBE(calibrationGuidelines[0])
176
- energy << 'var ashraeMaxNMBE = '
177
- energy << if !maxNMBE.empty?
178
- maxNMBE.get.to_s
179
- else
180
- 'N/A'
181
- end
182
- energy << ";\n"
183
- if os_version >= min_version_feature1
184
- runner.registerValue('ashrae_max_nmbe', maxNMBE.get, '%')
185
- end
186
-
187
- maxCVRMSE = OpenStudio::Model::UtilityBill.maxCVRMSE(calibrationGuidelines[0])
188
- energy << 'var ashraeMaxCVRMSE = '
189
- energy << if !maxCVRMSE.empty?
190
- maxCVRMSE.get.to_s
191
- else
192
- 'N/A'
193
- end
194
- energy << ";\n"
195
- if os_version >= min_version_feature1
196
- runner.registerValue('ashrae_max_cvrmse', maxCVRMSE.get, '%')
197
- end
198
-
199
- maxNMBE = OpenStudio::Model::UtilityBill.maxNMBE(calibrationGuidelines[1])
200
- energy << 'var fempMaxNMBE = '
201
- energy << if !maxNMBE.empty?
202
- maxNMBE.get.to_s
203
- else
204
- 'N/A'
205
- end
206
- energy << ";\n"
207
- if os_version >= min_version_feature1
208
- runner.registerValue('femp_max_nmbe', maxNMBE.get, '%')
209
- end
210
-
211
- maxCVRMSE = OpenStudio::Model::UtilityBill.maxCVRMSE(calibrationGuidelines[1])
212
- energy << 'var fempMaxCVRMSE = '
213
- energy << if !maxCVRMSE.empty?
214
- maxCVRMSE.get.to_s
215
- else
216
- 'N/A'
217
- end
218
- energy << ";\n"
219
- if os_version >= min_version_feature1
220
- runner.registerValue('femp_max_cvrmse', maxCVRMSE.get, '%')
221
- end
222
-
223
- energyElec = "\t\"Electricity Consumption\":{\n\t\t\"units\":\"kWh\",\n"
224
- energyDemand = "\t\"Electricity Demand\":{\n\t\t\"units\":\"kW\",\n"
225
- energyGas = "\t\"Natural Gas Consumption\":{\n\t\t\"units\":\"therms\",\n"
226
- tempStartDate = ''
227
- tempEndDate = ''
228
- elecStartDate = "\t\t\t\t\"Start\":["
229
- elecEndDate = "\t\t\t\t\"End\":["
230
- gasStartDate = "\t\t\t\t\"Start\":["
231
- gasEndDate = "\t\t\t\t\"End\":["
232
- elecActualConsumption = "\t\t\t\t\"Actual\":["
233
- elecModelConsumption = "\t\t\t\t\"Model\":["
234
- actualPeakDemand = "\t\t\t\t\"Actual\":["
235
- modelPeakDemand = "\t\t\t\t\"Model\":["
236
- gasActualConsumption = "\t\t\t\t\"Actual\":["
237
- gasModelConsumption = "\t\t\t\t\"Model\":["
238
- elecNMBE = "\t\t\t\t\"NMBE\":["
239
- demandNMBE = "\t\t\t\t\"NMBE\":["
240
- gasNMBE = "\t\t\t\t\"NMBE\":["
241
- peakDemandUnitConversionFactor = 1.0
242
- consumptionUnitConversionFactor = 1.0
243
- hasElec = false
244
- hasDemand = false
245
- hasGas = false
246
-
247
- missingData = false
248
- # must have a runPeriod
249
- runPeriod = model.runPeriod
250
- if runPeriod.empty?
251
- missingData = true
252
- runner.registerWarning('Model has no run period and cannot generate all data.')
253
- end
254
-
255
- # must have a calendarYear to generate model data
256
- yearDescription = model.yearDescription
257
- if yearDescription.empty?
258
- missingData = true
259
- runner.registerWarning('Model has no year description and cannot generate all data.')
260
- end
261
- calendarYear = yearDescription.get.calendarYear
262
- if calendarYear.empty?
263
- missingData = true
264
- runner.registerWarning('Model has no calendar year and cannot generate all data.')
265
- end
266
-
267
- all_actual_consumption_values = []
268
- all_modeled_consumption_values = []
269
-
270
- # sort bills by fuel type and name
271
- utilityBills = model.getUtilityBills.sort { |x, y| (x.fuelType.valueDescription + x.name.get) <=> (y.fuelType.valueDescription + y.name.get) }
272
- registered_fuel_types = []
273
-
274
- utilityBills.each do |utilityBill|
275
- utility_bill_name = OpenStudio.toUnderscoreCase(utilityBill.name.get)
276
- utility_bill_fuel_type = OpenStudio.toUnderscoreCase(utilityBill.fuelType.valueDescription)
277
- if registered_fuel_types.include?(utility_bill_fuel_type)
278
- runner.registerWarning("More than one utility bill of fuel type #{utility_bill_fuel_type} is in the model. Skipping #{utility_bill_name}.")
279
- next
280
- else
281
- registered_fuel_types << utility_bill_fuel_type
282
- end
283
-
284
- cvrsme = 0.0
285
- unless utilityBill.CVRMSE.empty?
286
- cvrsme = utilityBill.CVRMSE.get
287
- if os_version >= min_version_feature1
288
- runner.registerValue("#{utility_bill_fuel_type}_consumption_cvrmse", cvrsme, '%')
289
- end
290
- cvrsme = format '%.2f', cvrsme
291
- end
292
-
293
- nmbe = 0.0
294
- unless utilityBill.NMBE.empty?
295
- nmbe = utilityBill.NMBE.get
296
- if os_version >= min_version_feature1
297
- runner.registerValue("#{utility_bill_fuel_type}_consumption_nmbe", nmbe, '%')
298
- end
299
- nmbe = format '%.2f', nmbe
300
- end
301
-
302
- string = ''
303
- string << "\t\t\"cvrsme\":\"" << cvrsme.to_s << "\",\n\t\t\"nmbe\":\"" << nmbe.to_s << "\",\n\t\t\t\"data\":{\n"
304
-
305
- hasDemandValues = false
306
- if !utilityBill.peakDemandUnitConversionFactor.empty?
307
- hasDemandValues = true
308
- energyElec << string
309
- energyDemand << string
310
- peakDemandUnitConversionFactor = utilityBill.peakDemandUnitConversionFactor.get
311
- else
312
- hasDemandValues = false
313
- energyGas << string
314
- end
315
-
316
- consumptionUnitConversionFactor = utilityBill.consumptionUnitConversionFactor
317
-
318
- period_index = 1
319
- actual_consumption = 0.0
320
- modeled_consumption = 0.0
321
- actual_consumption_values = []
322
- modeled_consumption_values = []
323
- actual_demand = 0.0
324
- modeled_demand = 0.0
325
-
326
- utilityBill.billingPeriods.each do |billingPeriod|
327
- tempStartDate = '"' << billingPeriod.startDate.monthOfYear.value.to_s
328
- tempStartDate << '/'
329
- tempStartDate << billingPeriod.startDate.dayOfMonth.to_s << '"'
330
- tempEndDate = '"' << billingPeriod.endDate.monthOfYear.value.to_s
331
- tempEndDate << '/'
332
- tempEndDate << billingPeriod.endDate.dayOfMonth.to_s << '"'
333
- if os_version >= min_version_feature1
334
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_start_date", billingPeriod.startDate.to_s)
335
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_end_date", billingPeriod.endDate.to_s)
336
- end
337
-
338
- if hasDemandValues
339
- elecStartDate << tempStartDate << ','
340
- elecEndDate << tempEndDate << ','
341
-
342
- consumption = billingPeriod.consumption
343
- if !consumption.empty?
344
- hasElec = true
345
- elecActualConsumption << consumption.get.to_s
346
- actual_consumption += consumption.get
347
- actual_consumption_values << consumption.get
348
- all_actual_consumption_values << consumption.get * utilityBill.consumptionUnitConversionFactor
349
- if os_version >= min_version_feature1
350
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_consumption_actual",
351
- consumption.get,
352
- utilityBill.consumptionUnit)
353
- end
354
- else
355
- elecActualConsumption << '0'
356
- end
357
- elecActualConsumption << ','
358
-
359
- consumption = billingPeriod.modelConsumption
360
- if !consumption.empty?
361
- hasElec = true
362
- temp = consumption.get / consumptionUnitConversionFactor
363
- elecModelConsumption << temp.round(2).to_s
364
- modeled_consumption += temp
365
- modeled_consumption_values << temp
366
- all_modeled_consumption_values << consumption.get
367
- if os_version >= min_version_feature1
368
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_consumption_modeled",
369
- temp,
370
- utilityBill.consumptionUnit)
371
- end
372
- else
373
- elecModelConsumption << '0'
374
- end
375
- elecModelConsumption << ','
376
-
377
- peakDemand = billingPeriod.peakDemand
378
- if !peakDemand.empty?
379
- hasDemand = true
380
- actualPeakDemand << peakDemand.get.to_s
381
- actual_demand = peakDemand.get if peakDemand.get > actual_demand
382
- if os_version >= min_version_feature1
383
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_peak_demand_actual",
384
- peakDemand.get,
385
- utilityBill.peakDemandUnit.get)
386
- end
387
- else
388
- actualPeakDemand << '0'
389
- end
390
- actualPeakDemand << ','
391
-
392
- peakDemand = billingPeriod.modelPeakDemand
393
- if !peakDemand.empty?
394
- hasDemand = true
395
- temp = peakDemand.get / 1000
396
- temp_str = format '%.1f', temp
397
- modelPeakDemand << temp_str.to_s
398
- modeled_demand = temp if temp > modeled_demand
399
- if os_version >= min_version_feature1
400
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_peak_demand_modeled",
401
- temp,
402
- utilityBill.peakDemandUnit.get)
403
- end
404
- else
405
- modelPeakDemand << '0'
406
- end
407
- modelPeakDemand << ','
408
-
409
- if !billingPeriod.peakDemand.empty? && !billingPeriod.modelPeakDemand.empty? && (billingPeriod.consumption.get != 0)
410
- percent = 100 * ((billingPeriod.modelPeakDemand.get / 1000) - billingPeriod.peakDemand.get) / billingPeriod.peakDemand.get
411
- percent_str = format '%.2f', percent
412
- demandNMBE << percent_str.to_s
413
- if os_version >= min_version_feature1
414
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_peak_demand_nmbe",
415
- percent,
416
- '%')
417
- end
418
- else
419
- demandNMBE << '0'
420
- end
421
- demandNMBE << ','
422
-
423
- if !billingPeriod.consumption.empty? && !billingPeriod.modelConsumption.empty? && (billingPeriod.consumption.get != 0)
424
- percent = 100 * ((billingPeriod.modelConsumption.get / consumptionUnitConversionFactor) - billingPeriod.consumption.get) / billingPeriod.consumption.get
425
- percent_str = format '%.2f', percent
426
- elecNMBE << percent_str.to_s
427
- if os_version >= min_version_feature1
428
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_consumption_nmbe",
429
- percent,
430
- '%')
431
- end
432
- else
433
- elecNMBE << '0'
434
- end
435
- elecNMBE << ','
436
-
437
- else
438
- gasStartDate << tempStartDate << ','
439
- gasEndDate << tempEndDate << ','
440
-
441
- consumption = billingPeriod.consumption
442
- if !consumption.empty?
443
- hasGas = true
444
- gasActualConsumption << consumption.get.to_s
445
- actual_consumption += consumption.get
446
- actual_consumption_values << consumption.get
447
- all_actual_consumption_values << consumption.get * utilityBill.consumptionUnitConversionFactor
448
- if os_version >= min_version_feature1
449
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_consumption_actual",
450
- consumption.get,
451
- utilityBill.consumptionUnit)
452
- end
453
- else
454
- gasActualConsumption << '0'
455
- end
456
- gasActualConsumption << ','
457
-
458
- consumption = billingPeriod.modelConsumption
459
- if !consumption.empty?
460
- hasGas = true
461
- temp = consumption.get / consumptionUnitConversionFactor
462
- gasModelConsumption << temp.round(2).to_s
463
- modeled_consumption += temp
464
- modeled_consumption_values << temp
465
- all_modeled_consumption_values << consumption.get
466
- if os_version >= min_version_feature1
467
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_consumption_modeled",
468
- temp,
469
- utilityBill.consumptionUnit)
470
- end
471
- else
472
- gasModelConsumption << '0'
473
- end
474
- gasModelConsumption << ','
475
-
476
- if !billingPeriod.consumption.empty? && !billingPeriod.modelConsumption.empty? && (billingPeriod.consumption.get != 0)
477
- percent = 100 * ((billingPeriod.modelConsumption.get / consumptionUnitConversionFactor) - billingPeriod.consumption.get) / billingPeriod.consumption.get
478
- percent_str = format '%.2f', percent
479
- gasNMBE << percent_str.to_s
480
- if os_version >= min_version_feature1
481
- runner.registerValue("#{utility_bill_fuel_type}_period_#{period_index}_consumption_nmbe",
482
- percent,
483
- '%')
484
- end
485
- else
486
- gasNMBE << '0'
487
- end
488
- gasNMBE << ','
489
-
490
- end
491
- period_index += 1
492
- end
493
-
494
- next unless os_version >= min_version_feature1
495
- if actual_consumption > 0.0
496
- runner.registerValue("#{utility_bill_fuel_type}_consumption_actual",
497
- actual_consumption,
498
- utilityBill.consumptionUnit)
499
- runner.registerValue("#{utility_bill_fuel_type}_consumption_modeled",
500
- modeled_consumption,
501
- utilityBill.consumptionUnit)
502
- end
503
- if actual_demand > 0.0
504
- runner.registerValue("#{utility_bill_fuel_type}_peak_demand_actual",
505
- actual_demand,
506
- utilityBill.peakDemandUnit.get)
507
- runner.registerValue("#{utility_bill_fuel_type}_peak_demand_modeled",
508
- modeled_demand,
509
- utilityBill.peakDemandUnit.get)
510
- runner.registerValue("#{utility_bill_fuel_type}_peak_demand_nmbe",
511
- 100.0 * (modeled_demand - actual_demand) / actual_demand,
512
- '%')
513
- end
514
- next unless !actual_consumption_values.empty? && (actual_consumption_values.size == modeled_consumption_values.size)
515
- sum_squares = 0.0
516
- actual_consumption_values.each_index do |i|
517
- sum_squares += (actual_consumption_values[i] - modeled_consumption_values[i])**2
518
- end
519
- rmse = Math.sqrt(sum_squares / actual_consumption_values.size)
520
- runner.registerValue("#{utility_bill_fuel_type}_sum_of_squares",
521
- sum_squares,
522
- utilityBill.consumptionUnit)
523
- runner.registerValue("#{utility_bill_fuel_type}_dof",
524
- actual_consumption_values.size)
525
- runner.registerValue("#{utility_bill_fuel_type}_rmse",
526
- rmse,
527
- utilityBill.consumptionUnit + '^0.5')
528
- end
529
-
530
- if os_version >= min_version_feature1
531
- if !all_actual_consumption_values.empty? && (all_actual_consumption_values.size == all_modeled_consumption_values.size)
532
- sum_squares = 0.0
533
- all_actual_consumption_values.each_index do |i|
534
- sum_squares += (all_actual_consumption_values[i] - all_modeled_consumption_values[i])**2
535
- end
536
- rmse = Math.sqrt(sum_squares / all_actual_consumption_values.size)
537
- runner.registerValue('total_sum_of_squares',
538
- sum_squares,
539
- 'kBtu')
540
- runner.registerValue('total_dof',
541
- all_actual_consumption_values.size)
542
- runner.registerValue('total_rmse',
543
- rmse,
544
- 'kBtu^0.5')
545
- end
546
-
547
- end
548
-
549
- elecStartDate = elecStartDate[0..-2]
550
- elecStartDate << "],\n"
551
- elecEndDate = elecEndDate[0..-2]
552
- elecEndDate << "],\n"
553
- elecActualConsumption = elecActualConsumption[0..-2]
554
- elecActualConsumption << "],\n"
555
- elecModelConsumption = elecModelConsumption[0..-2]
556
- elecModelConsumption << "],\n"
557
- actualPeakDemand = actualPeakDemand[0..-2]
558
- actualPeakDemand << "],\n"
559
- modelPeakDemand = modelPeakDemand[0..-2]
560
- modelPeakDemand << "],\n"
561
- elecNMBE = elecNMBE[0..-2]
562
- elecNMBE << "]\n"
563
- demandNMBE = demandNMBE[0..-2]
564
- demandNMBE << "]\n"
565
- energyElec << elecStartDate << elecEndDate << elecActualConsumption << elecModelConsumption << elecNMBE
566
- energyElec << "\t\t}\n" << "\t},\n"
567
-
568
- energyDemand << elecStartDate << elecEndDate << actualPeakDemand << modelPeakDemand << demandNMBE
569
- energyDemand << "\t\t}\n" << "\t},\n"
570
-
571
- gasStartDate = gasStartDate[0..-2]
572
- gasStartDate << "],\n"
573
- gasEndDate = gasEndDate[0..-2]
574
- gasEndDate << "],\n"
575
- gasActualConsumption = gasActualConsumption[0..-2]
576
- gasActualConsumption << "],\n"
577
- gasModelConsumption = gasModelConsumption[0..-2]
578
- gasModelConsumption << "],\n"
579
- gasNMBE = gasNMBE[0..-2]
580
- gasNMBE << "]\n"
581
- energyGas << gasStartDate << gasEndDate << gasActualConsumption << gasModelConsumption << gasNMBE
582
- energyGas << "\t\t}\n" << "\t},\n"
583
-
584
- energy << "var consumption = {\n"
585
-
586
- energy << energyElec if hasElec
587
-
588
- energy << energyDemand if hasDemand
589
-
590
- energy << energyGas if hasGas
591
-
592
- energy << '};'
593
-
594
- # echo out our values
595
- # runner.registerInfo("This building is named #{building_name}.")
596
-
597
- # read in template
598
- html_in_path = "#{File.dirname(__FILE__)}/resources/report.html.in"
599
- html_in_path = if File.exist?(html_in_path)
600
- html_in_path
601
- else
602
- "#{File.dirname(__FILE__)}/report.html.in"
603
- end
604
- html_in = ''
605
- File.open(html_in_path, 'r') do |file|
606
- html_in = file.read
607
- end
608
-
609
- # configure template with variable values
610
- renderer = ERB.new(html_in)
611
- html_out = renderer.result(binding)
612
-
613
- # write html file
614
- html_out_path = './report.html'
615
- File.open(html_out_path, 'w') do |file|
616
- file << html_out
617
- # make sure data is written to the disk one way or the other
618
- begin
619
- file.fsync
620
- rescue StandardError
621
- file.flush
622
- end
623
- end
624
-
625
- # closing the sql file
626
- sqlFile.close
627
-
628
- # reporting final condition
629
- if missingData == true
630
- runner.registerFinalCondition('Calibration Report was not generated successfully.')
631
- else
632
- runner.registerFinalCondition('Calibration Report generated successfully.')
633
- end
634
-
635
- # write json specific file format, everything can be derived from reported attributes
636
- result_hash = {}
637
- runner.result.attributes.each do |attribute|
638
- # skip individual period metrics
639
- next if /period_\d+_consumption/.match(attribute.name)
640
-
641
- if match_data = /(.*)_consumption_cvrmse/.match(attribute.name)
642
- cvrmse = attribute.valueAsDouble
643
-
644
- # this is a hack
645
- is_electric = /electric/i.match(match_data[1])
646
-
647
- within_limit = false
648
- within_limit = if is_electric
649
- (cvrmse <= electric_cvrmse_limit)
650
- else
651
- (cvrmse <= gas_cvrmse_limit)
652
- end
653
- result_hash[match_data[1] + '_cvrmse_within_limit'] = within_limit
654
- within_limit_i = if within_limit
655
- 1
656
- else
657
- 0
658
- end
659
- runner.registerValue("#{match_data[1]}_cvrmse_within_limit", within_limit_i)
660
- elsif match_data = /(.*)_consumption_nmbe/i.match(attribute.name)
661
- nmbe = attribute.valueAsDouble
662
-
663
- # this is a hack
664
- is_electric = /electric/i.match(match_data[1])
665
-
666
- within_limit = false
667
- within_limit = if is_electric
668
- (nmbe.abs <= electric_nmbe_limit)
669
- else
670
- (nmbe.abs <= gas_nmbe_limit)
671
- end
672
- result_hash[match_data[1] + '_nmbe_within_limit'] = within_limit
673
- within_limit_i = if within_limit
674
- 1
675
- else
676
- 0
677
- end
678
- runner.registerValue("#{match_data[1]}_nmbe_within_limit", within_limit_i)
679
- end
680
- end
681
- File.open('./report_guideline.json', 'w') do |f|
682
- f.write(result_hash.to_json)
683
- end
684
-
685
- true
686
- end # end the run method
687
- end # end the measure
688
-
689
- # this allows the measure to be use by the application
690
- CalibrationReportsEnhanced21.new.registerWithApplication