urbanopt-reporting 0.1.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) 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 +39 -0
  7. data/CONTRIBUTING.md +1 -1
  8. data/LICENSE.md +1 -1
  9. data/RDOC_MAIN.md +10 -0
  10. data/README.md +1 -1
  11. data/Rakefile +1 -1
  12. data/deploy_docs.sh +5 -0
  13. data/doc_templates/LICENSE.md +1 -1
  14. data/doc_templates/copyright_erb.txt +1 -1
  15. data/doc_templates/copyright_js.txt +1 -1
  16. data/doc_templates/copyright_ruby.txt +1 -1
  17. data/docs/.gitignore +3 -0
  18. data/docs/.vuepress/components/InnerJsonSchema.vue +76 -0
  19. data/docs/.vuepress/components/JsonSchema.vue +12 -0
  20. data/docs/.vuepress/components/ScenarioSchema.vue +12 -0
  21. data/docs/.vuepress/components/StaticLink.vue +8 -0
  22. data/docs/.vuepress/config.js +25 -0
  23. data/docs/.vuepress/highlight.js +8 -0
  24. data/docs/.vuepress/json-schema-deref-loader.js +22 -0
  25. data/docs/.vuepress/public/custom_rdoc_styles.css +78 -0
  26. data/docs/.vuepress/styles/palette.styl +1 -0
  27. data/docs/.vuepress/utils.js +17 -0
  28. data/docs/README.md +9 -0
  29. data/docs/package-lock.json +10018 -0
  30. data/docs/package.json +30 -0
  31. data/docs/schemas/scenario-schema.md +3 -0
  32. data/lib/measures/default_feature_reports/LICENSE.md +1 -1
  33. data/lib/measures/default_feature_reports/measure.rb +261 -88
  34. data/lib/measures/default_feature_reports/measure.xml +11 -11
  35. data/lib/urbanopt/reporting.rb +1 -1
  36. data/lib/urbanopt/reporting/default_reports.rb +1 -1
  37. data/lib/urbanopt/reporting/default_reports/construction_cost.rb +1 -1
  38. data/lib/urbanopt/reporting/default_reports/date.rb +1 -1
  39. data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +119 -6
  40. data/lib/urbanopt/reporting/default_reports/end_use.rb +1 -1
  41. data/lib/urbanopt/reporting/default_reports/end_uses.rb +53 -39
  42. data/lib/urbanopt/reporting/default_reports/extension.rb +30 -0
  43. data/lib/urbanopt/reporting/default_reports/feature_report.rb +52 -21
  44. data/lib/urbanopt/reporting/default_reports/generator.rb +2 -2
  45. data/lib/urbanopt/reporting/default_reports/location.rb +12 -12
  46. data/lib/urbanopt/reporting/default_reports/logger.rb +1 -1
  47. data/lib/urbanopt/reporting/default_reports/power_distribution.rb +1 -1
  48. data/lib/urbanopt/reporting/default_reports/program.rb +87 -87
  49. data/lib/urbanopt/reporting/default_reports/reporting_period.rb +87 -79
  50. data/lib/urbanopt/reporting/default_reports/scenario_report.rb +1 -1
  51. data/lib/urbanopt/reporting/default_reports/schema/README.md +1 -1
  52. data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +18 -1
  53. data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +117 -82
  54. data/lib/urbanopt/reporting/default_reports/solar_pv.rb +2 -2
  55. data/lib/urbanopt/reporting/default_reports/storage.rb +2 -2
  56. data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +111 -0
  57. data/lib/urbanopt/reporting/default_reports/timeseries_csv.rb +1 -1
  58. data/lib/urbanopt/reporting/default_reports/validator.rb +1 -1
  59. data/lib/urbanopt/reporting/default_reports/wind.rb +2 -2
  60. data/lib/urbanopt/reporting/derived_extension.rb +1 -1
  61. data/lib/urbanopt/reporting/version.rb +2 -2
  62. data/urbanopt-reporting-gem.gemspec +4 -4
  63. metadata +37 -15
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "urbanopt-reporting-gem-docs",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "dev": "vuepress dev",
8
+ "build": "vuepress build",
9
+ "deploy": "gh-pages -d .vuepress/dist"
10
+ },
11
+ "author": "NREL",
12
+ "dependencies": {
13
+ "highlight.js": "^10.3.1",
14
+ "json-schema-ref-parser": "^9.0.6",
15
+ "json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
16
+ "vuepress": "^1.7.1",
17
+ "webpack-dev-middleware": "^3.6.0"
18
+ },
19
+ "devDependencies": {
20
+ "braces": "^3.0.2",
21
+ "dot-prop": "^5.3.0",
22
+ "gh-pages": "^3.1.0",
23
+ "js-yaml": "^3.14.0",
24
+ "minimist": ">=1.2.3",
25
+ "node-forge": ">=0.10.0",
26
+ "serialize-javascript": "^5.0.1",
27
+ "set-value": "^3.0.2",
28
+ "yargs-parser": "^20.2.3"
29
+ }
30
+ }
@@ -0,0 +1,3 @@
1
+ # Scenario Schema
2
+
3
+ <ScenarioSchema />
@@ -1,4 +1,4 @@
1
- URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
1
+ URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
2
  contributors. All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -71,6 +71,11 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
71
71
  feature_type.setDefaultValue('Building')
72
72
  args << feature_type
73
73
 
74
+ feature_location = OpenStudio::Measure::OSArgument.makeStringArgument('feature_location', false)
75
+ feature_location.setDisplayName('URBANopt Feature Location')
76
+ feature_location.setDefaultValue('0')
77
+ args << feature_location
78
+
74
79
  # make an argument for the frequency
75
80
  reporting_frequency_chs = OpenStudio::StringVector.new
76
81
  reporting_frequency_chs << 'Detailed'
@@ -94,37 +99,39 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
94
99
 
95
100
  # define fuel types
96
101
  def fuel_types
97
- fuel_types = [
98
- 'Electricity',
99
- 'Gas',
100
- 'AdditionalFuel',
101
- 'DistrictCooling',
102
- 'DistrictHeating',
103
- 'Water'
104
- ]
102
+ fuel_types = {
103
+ 'Electricity' => 'Electricity',
104
+ 'Gas' => 'Natural Gas',
105
+ 'FuelOil#2' => 'Fuel Oil #2',
106
+ 'Propane' => 'Propane',
107
+ 'AdditionalFuel' => 'Additional Fuel',
108
+ 'DistrictCooling' => 'District Cooling',
109
+ 'DistrictHeating' => 'District Heating',
110
+ 'Water' => 'Water'
111
+ }
105
112
 
106
113
  return fuel_types
107
114
  end
108
115
 
109
116
  # define enduses
110
117
  def end_uses
111
- end_uses = [
112
- 'Heating',
113
- 'Cooling',
114
- 'InteriorLights',
115
- 'ExteriorLights',
116
- 'InteriorEquipment',
117
- 'ExteriorEquipment',
118
- 'Fans',
119
- 'Pumps',
120
- 'HeatRejection',
121
- 'Humidifier',
122
- 'HeatRecovery',
123
- 'WaterSystems',
124
- 'Refrigeration',
125
- 'Generators',
126
- 'Facility'
127
- ]
118
+ end_uses = {
119
+ 'Heating' => 'Heating',
120
+ 'Cooling' => 'Cooling',
121
+ 'InteriorLights' => 'Interior Lighting',
122
+ 'ExteriorLights' => 'Exterior Lighting',
123
+ 'InteriorEquipment' => 'Interior Equipment',
124
+ 'ExteriorEquipment' => 'Exterior Equipment',
125
+ 'Fans' => 'Fans',
126
+ 'Pumps' => 'Pumps',
127
+ 'HeatRejection' => 'Heat Rejection',
128
+ 'Humidifier' => 'Humidification',
129
+ 'HeatRecovery' => 'Heat Recovery',
130
+ 'WaterSystems' => 'Water Systems',
131
+ 'Refrigeration' => 'Refrigeration',
132
+ 'Generators' => 'Generators',
133
+ 'Facility' => 'Facility'
134
+ }
128
135
 
129
136
  return end_uses
130
137
  end
@@ -158,7 +165,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
158
165
 
159
166
  # Request the output for each end use/fuel type combination
160
167
  end_uses.each do |end_use|
168
+ end_use, _ = end_use
161
169
  fuel_types.each do |fuel_type|
170
+ fuel_type, _ = fuel_type
162
171
  variable_name = if end_use == 'Facility'
163
172
  "#{fuel_type}:#{end_use}"
164
173
  else
@@ -168,6 +177,24 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
168
177
  end
169
178
  end
170
179
 
180
+ # OtherFuels
181
+ other_fuels = ["FuelOil#1", "Diesel", "Gasoline", "Coal", "Steam"]
182
+ other_fuel_uses = ["HeatRejection", "Heating", "WaterSystems", "InteriorEquipment"]
183
+ custom_meter_facility = "Meter:Custom,OtherFuels:Facility,OtherFuel1"
184
+ other_fuel_uses.each do |end_use|
185
+ custom_meter = "Meter:Custom,#{end_use}:OtherFuels,OtherFuel1"
186
+ other_fuels.each do |other_fuel|
187
+ result << OpenStudio::IdfObject.load("Output:Meter,#{end_use}:#{other_fuel},#{reporting_frequency};").get
188
+ custom_meter_facility += ",,#{end_use}:#{other_fuel}"
189
+ custom_meter += ",,#{end_use}:#{other_fuel}"
190
+ end
191
+ custom_meter += ";"
192
+ result << OpenStudio::IdfObject.load(custom_meter).get
193
+ result << OpenStudio::IdfObject.load("Output:Meter,#{end_use}:OtherFuels,#{reporting_frequency};").get
194
+ end
195
+ result << OpenStudio::IdfObject.load("#{custom_meter_facility};").get
196
+ result << OpenStudio::IdfObject.load("Output:Meter,OtherFuels:Facility,#{reporting_frequency};").get
197
+
171
198
  # Request the output for each end use/fuel type combination
172
199
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Electricity:Facility,#{reporting_frequency};").get
173
200
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,ElectricityProduced:Facility,#{reporting_frequency};").get
@@ -193,6 +220,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
193
220
  'District Heating Inlet Temperature', 'District Heating Outlet Temperature', 'Cooling Coil Total Cooling Rate',
194
221
  'Heating Coil Heating Rate']
195
222
 
223
+ tes_timeseries_data = ['Ice Thermal Storage End Fraction', 'Cooling coil Ice Thermal Storage End Fraction']
224
+ timeseries_data += tes_timeseries_data
225
+
196
226
  timeseries_data.each do |ts|
197
227
  result << OpenStudio::IdfObject.load("Output:Variable,*,#{ts},#{reporting_frequency};").get
198
228
  end
@@ -220,11 +250,14 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
220
250
  end
221
251
  end
222
252
 
223
- val
253
+ return val
224
254
  end
225
255
 
226
256
  # unit conversion method
227
257
  def convert_units(value, from_units, to_units)
258
+ if value.nil?
259
+ return nil
260
+ end
228
261
  # apply unit conversion
229
262
  value_converted = OpenStudio.convert(value, from_units, to_units)
230
263
  if value_converted.is_initialized
@@ -254,6 +287,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
254
287
  feature_id = runner.getStringArgumentValue('feature_id', user_arguments)
255
288
  feature_name = runner.getStringArgumentValue('feature_name', user_arguments)
256
289
  feature_type = runner.getStringArgumentValue('feature_type', user_arguments)
290
+ feature_location = runner.getStringArgumentValue('feature_location', user_arguments)
257
291
 
258
292
  # Assign the user inputs to variables
259
293
  reporting_frequency = runner.getStringArgumentValue('reporting_frequency', user_arguments)
@@ -318,37 +352,41 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
318
352
  # Get Location information and store in the feature_report
319
353
  ##
320
354
 
321
- # latitude
322
- latitude = epw_file.latitude
323
- feature_report.location.latitude = latitude
324
-
325
- # longitude
326
- longitude = epw_file.longitude
327
- feature_report.location.longitude = longitude
355
+ if feature_location.include? '['
356
+ # get latitude from feature_location
357
+ latitude = (feature_location.split(',')[0].delete! '[]').to_f
358
+ # get longitude from feature_location
359
+ longitude = (feature_location.split(',')[1].delete! '[]').to_f
360
+ # latitude
361
+ feature_report.location.latitude_deg = latitude
362
+ # longitude
363
+ feature_report.location.longitude_deg = longitude
364
+ end
328
365
 
329
366
  # surface_elevation
330
367
  elev = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='General' AND RowName='Elevation' AND ColumnName='Value'")
331
- feature_report.location.surface_elevation = elev
368
+ feature_report.location.surface_elevation_ft = elev
332
369
 
333
370
  ##########################################################################
334
371
  ##
372
+
335
373
  # Get program information and store in the feature_report
336
374
  ##
337
375
 
338
376
  # floor_area
339
377
  floor_area = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Total Building Area' AND ColumnName='Area'")
340
- feature_report.program.floor_area = convert_units(floor_area, 'm^2', 'ft^2')
378
+ feature_report.program.floor_area_sqft = convert_units(floor_area, 'm^2', 'ft^2')
341
379
 
342
380
  # conditioned_area
343
381
  conditioned_area = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
344
- feature_report.program.conditioned_area = convert_units(conditioned_area, 'm^2', 'ft^2')
382
+ feature_report.program.conditioned_area_sqft = convert_units(conditioned_area, 'm^2', 'ft^2')
345
383
 
346
384
  # unconditioned_area
347
385
  unconditioned_area = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Unconditioned Building Area' AND ColumnName='Area'")
348
- feature_report.program.unconditioned_area = convert_units(unconditioned_area, 'm^2', 'ft^2')
386
+ feature_report.program.unconditioned_area_sqft = convert_units(unconditioned_area, 'm^2', 'ft^2')
349
387
 
350
388
  # footprint_area
351
- feature_report.program.footprint_area = convert_units(floor_area, 'm^2', 'ft^2')
389
+ feature_report.program.footprint_area_sqft = convert_units(floor_area, 'm^2', 'ft^2')
352
390
 
353
391
  # maximum_number_of_stories
354
392
  number_of_stories = building.standardsNumberOfStories.get if building.standardsNumberOfStories.is_initialized
@@ -358,7 +396,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
358
396
  # maximum_roof_height
359
397
  floor_to_floor_height = building.nominalFloortoFloorHeight.to_f
360
398
  maximum_roof_height = number_of_stories * floor_to_floor_height
361
- feature_report.program.maximum_roof_height = maximum_roof_height
399
+ feature_report.program.maximum_roof_height_ft = maximum_roof_height
362
400
 
363
401
  # maximum_number_of_stories_above_ground
364
402
  number_of_stories_above_ground = building.standardsNumberOfAboveGroundStories.get if building.standardsNumberOfAboveGroundStories.is_initialized
@@ -419,36 +457,36 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
419
457
  ## window_area
420
458
  # north_window_area
421
459
  north_window_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Window Opening Area' AND ColumnName='North (315 to 45 deg)'").to_f
422
- feature_report.program.window_area[:north_window_area] = convert_units(north_window_area, 'm^2', 'ft^2')
460
+ feature_report.program.window_area_sqft[:north_window_area_sqft] = convert_units(north_window_area, 'm^2', 'ft^2')
423
461
  # south_window_area
424
462
  south_window_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Window Opening Area' AND ColumnName='South (135 to 225 deg)'").to_f
425
- feature_report.program.window_area[:south_window_area] = convert_units(south_window_area, 'm^2', 'ft^2')
463
+ feature_report.program.window_area_sqft[:south_window_area_sqft] = convert_units(south_window_area, 'm^2', 'ft^2')
426
464
  # east_window_area
427
465
  east_window_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Window Opening Area' AND ColumnName='East (45 to 135 deg)'").to_f
428
- feature_report.program.window_area[:east_window_area] = convert_units(east_window_area, 'm^2', 'ft^2')
466
+ feature_report.program.window_area_sqft[:east_window_area_sqft] = convert_units(east_window_area, 'm^2', 'ft^2')
429
467
  # west_window_area
430
468
  west_window_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Window Opening Area' AND ColumnName='West (225 to 315 deg)'").to_f
431
- feature_report.program.window_area[:west_window_area] = convert_units(west_window_area, 'm^2', 'ft^2')
469
+ feature_report.program.window_area_sqft[:west_window_area_sqft] = convert_units(west_window_area, 'm^2', 'ft^2')
432
470
  # total_window_area
433
471
  total_window_area = north_window_area + south_window_area + east_window_area + west_window_area
434
- feature_report.program.window_area[:total_window_area] = convert_units(total_window_area, 'm^2', 'ft^2')
472
+ feature_report.program.window_area_sqft[:total_window_area_sqft] = convert_units(total_window_area, 'm^2', 'ft^2')
435
473
 
436
474
  ## wall_area
437
475
  # north_wall_area
438
476
  north_wall_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Gross Wall Area' AND ColumnName='North (315 to 45 deg)'").to_f
439
- feature_report.program.wall_area[:north_wall_area] = convert_units(north_wall_area, 'm^2', 'ft^2')
477
+ feature_report.program.wall_area_sqft[:north_wall_area_sqft] = convert_units(north_wall_area, 'm^2', 'ft^2')
440
478
  # south_wall_area
441
479
  south_wall_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Gross Wall Area' AND ColumnName='South (135 to 225 deg)'").to_f
442
- feature_report.program.wall_area[:south_wall_area] = convert_units(south_wall_area, 'm^2', 'ft^2')
480
+ feature_report.program.wall_area_sqft[:south_wall_area_sqft] = convert_units(south_wall_area, 'm^2', 'ft^2')
443
481
  # east_wall_area
444
482
  east_wall_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Gross Wall Area' AND ColumnName='East (45 to 135 deg)'").to_f
445
- feature_report.program.wall_area[:east_wall_area] = convert_units(east_wall_area, 'm^2', 'ft^2')
483
+ feature_report.program.wall_area_sqft[:east_wall_area_sqft] = convert_units(east_wall_area, 'm^2', 'ft^2')
446
484
  # west_wall_area
447
485
  west_wall_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Gross Wall Area' AND ColumnName='West (225 to 315 deg)'").to_f
448
- feature_report.program.wall_area[:west_wall_area] = convert_units(west_wall_area, 'm^2', 'ft^2')
486
+ feature_report.program.wall_area_sqft[:west_wall_area_sqft] = convert_units(west_wall_area, 'm^2', 'ft^2')
449
487
  # total_wall_area
450
488
  total_wall_area = north_wall_area + south_wall_area + east_wall_area + west_wall_area
451
- feature_report.program.wall_area[:total_wall_area] = convert_units(total_wall_area, 'm^2', 'ft^2')
489
+ feature_report.program.wall_area_sqft[:total_wall_area_sqft] = convert_units(total_wall_area, 'm^2', 'ft^2')
452
490
 
453
491
  # total_roof_area
454
492
  total_roof_area = 0.0
@@ -457,12 +495,12 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
457
495
  total_roof_area += surface.netArea
458
496
  end
459
497
  end
460
- feature_report.program.roof_area[:total_roof_area] = convert_units(total_roof_area, 'm^2', 'ft^2')
498
+ feature_report.program.roof_area_sqft[:total_roof_area_sqft] = convert_units(total_roof_area, 'm^2', 'ft^2')
461
499
 
462
500
  # orientation
463
501
  # RK: a more robust method should be implemented to find orientation(finding main axis of the building using aspect ratio)
464
502
  building_rotation = model.getBuilding.northAxis
465
- feature_report.program.orientation = building_rotation
503
+ feature_report.program.orientation_deg = building_rotation
466
504
 
467
505
  # aspect_ratio
468
506
  north_wall_area = sql_query(runner, sql_file, 'InputVerificationandResultsSummary', "TableName='Window-Wall Ratio' AND RowName='Gross Wall Area' AND ColumnName='North (315 to 45 deg)'")
@@ -473,7 +511,40 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
473
511
 
474
512
  # total_construction_cost
475
513
  total_construction_cost = sql_query(runner, sql_file, 'Life-Cycle Cost Report', "TableName='Present Value for Recurring, Nonrecurring and Energy Costs (Before Tax)' AND RowName='LCC_MAT - BUILDING - LIFE CYCLE COSTS' AND ColumnName='Cost'")
476
- feature_report.program.total_construction_cost = total_construction_cost
514
+ feature_report.program.total_construction_cost_dollar = total_construction_cost
515
+
516
+ # packaged thermal storage capacities by cooling coil
517
+ ptes_keys = sql_file.availableKeyValues('RUN Period 1', 'Zone Timestep', 'Cooling Coil Ice Thermal Storage End Fraction')
518
+ if ptes_keys.empty?
519
+ ptes_size = nil
520
+ runner.registerWarning('Query failed for Packaged Ice Thermal Storage Capacity')
521
+ else
522
+ begin
523
+ ptes_size = 0
524
+ ptes_keys.each do |pk|
525
+ ptes_size += sql_query(runner, sql_file, 'ComponentSizingSummary', "TableName='Coil:Cooling:DX:SingleSpeed:ThermalStorage' AND RowName='#{pk}' AND ColumnName='Ice Storage Capacity'").to_f
526
+ end
527
+ ptes_size = convert_units(ptes_size, 'GJ', 'kWh')
528
+ rescue StandardError
529
+ runner.registerWarning('Query ptes_size.get failed')
530
+ end
531
+ end
532
+ feature_report.thermal_storage.ptes_size_kwh = ptes_size
533
+
534
+ # get the central tank thermal storage capacity
535
+ its_size = nil
536
+ its_size_index = sql_file.execAndReturnFirstDouble("SELECT ReportVariableDataDictionaryIndex FROM ReportVariableDataDictionary WHERE VariableName='Ice Thermal Storage Capacity'")
537
+ if its_size_index.empty?
538
+ runner.registerWarning('Query failed for Ice Thermal Storage Capacity')
539
+ else
540
+ begin
541
+ its_size = sql_file.execAndReturnFirstDouble("SELECT VariableValue FROM ReportVariableData WHERE ReportVariableDataDictionaryIndex=#{its_size_index}").get
542
+ its_size = convert_units(its_size.to_f, 'GJ', 'kWh')
543
+ rescue StandardError
544
+ runner.registerWarning('Query its_size.get failed')
545
+ end
546
+ end
547
+ feature_report.thermal_storage.its_size_kwh = its_size
477
548
 
478
549
  ############################################################################
479
550
  ##
@@ -504,78 +575,132 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
504
575
 
505
576
  # total_site_energy
506
577
  total_site_energy = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Total Energy'")
507
- feature_report.reporting_periods[0].total_site_energy = convert_units(total_site_energy, 'GJ', 'kBtu')
578
+ feature_report.reporting_periods[0].total_site_energy_kwh = convert_units(total_site_energy, 'GJ', 'kWh')
508
579
 
509
580
  # total_source_energy
510
581
  total_source_energy = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Total Energy'")
511
- feature_report.reporting_periods[0].total_source_energy = convert_units(total_source_energy, 'GJ', 'kBtu')
582
+ feature_report.reporting_periods[0].total_source_energy_kwh = convert_units(total_source_energy, 'GJ', 'kWh')
512
583
 
513
584
  # net_site_energy
514
585
  net_site_energy = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Net Site Energy' AND ColumnName='Total Energy'")
515
- feature_report.reporting_periods[0].net_site_energy = convert_units(net_site_energy, 'GJ', 'kBtu')
586
+ feature_report.reporting_periods[0].net_site_energy_kwh = convert_units(net_site_energy, 'GJ', 'kWh')
516
587
 
517
588
  # net_source_energy
518
589
  net_source_energy = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Net Source Energy' AND ColumnName='Total Energy'")
519
- feature_report.reporting_periods[0].net_source_energy = convert_units(net_source_energy, 'GJ', 'kBtu')
590
+ feature_report.reporting_periods[0].net_source_energy_kwh = convert_units(net_source_energy, 'GJ', 'kWh')
520
591
 
521
592
  # electricity
522
593
  electricity = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Electricity'")
523
- feature_report.reporting_periods[0].electricity = convert_units(electricity, 'GJ', 'kBtu')
594
+ feature_report.reporting_periods[0].electricity_kwh = convert_units(electricity, 'GJ', 'kWh')
524
595
 
525
596
  # natural_gas
526
597
  natural_gas = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Natural Gas'")
527
- feature_report.reporting_periods[0].natural_gas = convert_units(natural_gas, 'GJ', 'kBtu')
598
+ feature_report.reporting_periods[0].natural_gas_kwh = convert_units(natural_gas, 'GJ', 'kWh')
599
+
600
+ # propane
601
+ propane = sql_query(runner, sql_file, 'EnergyMeters', "TableName='Annual and Peak Values - Other' AND RowName='Propane:Facility' AND ColumnName='Annual Value'")
602
+ feature_report.reporting_periods[0].propane_kwh = 0.0
603
+ feature_report.reporting_periods[0].propane_kwh = convert_units(propane, 'GJ', 'kWh') unless propane.nil?
604
+
605
+ # fuel_oil
606
+ fuel_oil = sql_query(runner, sql_file, 'EnergyMeters', "TableName='Annual and Peak Values - Other' AND RowName='FuelOil#2:Facility' AND ColumnName='Annual Value'")
607
+ feature_report.reporting_periods[0].fuel_oil_kwh = 0.0
608
+ feature_report.reporting_periods[0].fuel_oil_kwh = convert_units(fuel_oil, 'GJ', 'kWh') unless fuel_oil.nil?
528
609
 
529
- # additional_fuel
610
+ # other_fuels
530
611
  additional_fuel = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Additional Fuel'")
531
- feature_report.reporting_periods[0].additional_fuel = convert_units(additional_fuel, 'GJ', 'kBtu')
612
+ # ensure additional fuel is not nil
613
+ feature_report.reporting_periods[0].other_fuels_kwh = 0.0
614
+ feature_report.reporting_periods[0].other_fuels_kwh = convert_units(additional_fuel, 'GJ', 'kWh') unless additional_fuel.nil?
615
+ feature_report.reporting_periods[0].other_fuels_kwh -= feature_report.reporting_periods[0].propane_kwh
616
+ feature_report.reporting_periods[0].other_fuels_kwh -= feature_report.reporting_periods[0].fuel_oil_kwh
532
617
 
533
618
  # district_cooling
534
619
  district_cooling = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='District Cooling'")
535
- feature_report.reporting_periods[0].district_cooling = convert_units(district_cooling, 'GJ', 'kBtu')
620
+ feature_report.reporting_periods[0].district_cooling_kwh = convert_units(district_cooling, 'GJ', 'kWh')
621
+ building_types.each do |i|
622
+ feature_report.reporting_periods[0].district_cooling_kwh = 0.0 if i[:building_type].include?('Single-Family Detached')
623
+ end
536
624
 
537
625
  # district_heating
538
626
  district_heating = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='District Heating'")
539
- feature_report.reporting_periods[0].district_heating = convert_units(district_heating, 'GJ', 'kBtu')
627
+ feature_report.reporting_periods[0].district_heating_kwh = convert_units(district_heating, 'GJ', 'kWh')
628
+ building_types.each do |i|
629
+ feature_report.reporting_periods[0].district_heating_kwh = 0.0 if i[:building_type].include?('Single-Family Detached')
630
+ end
540
631
 
541
632
  # water
542
633
  water = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Water'")
543
634
  # feature_report.reporting_periods[0].water = convert_units(water, 'm3', 'ft3')
544
- feature_report.reporting_periods[0].water = water
635
+ feature_report.reporting_periods[0].water_qbft = water
545
636
 
546
637
  # electricity_produced
547
638
  electricity_produced = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Electric Loads Satisfied' AND RowName='Total On-Site and Utility Electric Sources' AND ColumnName='Electricity'")
548
- feature_report.reporting_periods[0].electricity_produced = convert_units(electricity_produced, 'GJ', 'kBtu')
639
+ feature_report.reporting_periods[0].electricity_produced_kwh = convert_units(electricity_produced, 'GJ', 'kWh')
549
640
 
550
641
  ## end_uses
551
642
 
552
643
  # get fuel type as listed in the sql file
553
- fuel_type = ['Electricity', 'Natural Gas', 'Additional Fuel', 'District Cooling', 'District Heating', 'Water']
644
+ fueltypes = fuel_types.values
645
+ fueltypes.delete('Propane')
646
+ fueltypes.delete('Fuel Oil #2')
554
647
 
555
648
  # get enduses as listed in the sql file
556
- enduses = ['Heating', 'Cooling', 'Interior Lighting', 'Exterior Lighting', 'Interior Equipment', 'Exterior Equipment', 'Fans', 'Pumps',
557
- 'Heat Rejection', 'Humidification', 'Heat Recovery', 'Water Systems', 'Refrigeration', 'Generators']
649
+ enduses = end_uses.values
650
+ enduses.delete('Facility')
651
+
652
+ # propane / fuel_oil
653
+ ['Propane', 'Fuel Oil #2'].each do |ft|
654
+ end_uses.keys.each do |eu|
655
+ next if eu == 'Facility'
656
+
657
+ sql_r = sql_query(runner, sql_file, 'EnergyMeters', "TableName='Annual and Peak Values - Other' AND RowName='#{eu}:#{ft.tr(' ', '')}' AND ColumnName='Annual Value'")
658
+
659
+ # report each query in its corresponding feature report obeject
660
+ x = ft.tr(' ', '_').downcase
661
+ x = x.gsub('_#2', '')
662
+ x_u = x + '_kwh'
663
+ m = feature_report.reporting_periods[0].end_uses.send(x_u)
664
+
665
+ y = end_uses[eu].tr(' ', '_').downcase
666
+ if sql_r.nil?
667
+ sql_r = 0.0
668
+ end
669
+ m.send("#{y}=", convert_units(sql_r, 'GJ', 'kWh'))
670
+ end
671
+ end
558
672
 
559
673
  # loop through fuel types and enduses to fill in sql_query method
560
- fuel_type.each do |ft|
674
+ fueltypes.each do |ft|
561
675
  enduses.each do |eu|
562
676
  sql_r = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='#{eu}' AND ColumnName='#{ft}'")
563
677
 
564
678
  # report each query in its corresponding feature report obeject
565
- if ft.include? ' '
566
- x = ft.tr(' ', '_').downcase
567
- m = feature_report.reporting_periods[0].end_uses.send(x)
679
+ x = ft.tr(' ', '_').downcase
680
+ if x.include? 'water'
681
+ x_u = x + '_qbft'
568
682
  else
569
- m = feature_report.reporting_periods[0].end_uses.send(ft.downcase)
570
-
683
+ x_u = x + '_kwh'
684
+ end
685
+ if x_u == 'additional_fuel_kwh'
686
+ x_u = 'other_fuels_kwh'
571
687
  end
688
+ m = feature_report.reporting_periods[0].end_uses.send(x_u)
572
689
 
573
- if eu.include? ' '
574
- y = eu.tr(' ', '_').downcase
575
- m.send("#{y}=", convert_units(sql_r, 'GJ', 'kBtu'))
576
- else
577
- m.send("#{eu.downcase}=", convert_units(sql_r, 'GJ', 'kBtu'))
690
+ y = eu.tr(' ', '_').downcase
691
+ # ensure not nil so the equations below don't error out
692
+ if sql_r.nil?
693
+ sql_r = 0.0
694
+ end
695
+ sql_r = convert_units(sql_r, 'GJ', 'kWh')
696
+ if x_u == 'other_fuels_kwh'
697
+ sql_r -= feature_report.reporting_periods[0].end_uses.propane_kwh.send(y)
698
+ sql_r -= feature_report.reporting_periods[0].end_uses.fuel_oil_kwh.send(y)
578
699
  end
700
+ building_types.each do |i|
701
+ sql_r = 0.0 if (i[:building_type].include?('Single-Family Detached') && x_u.include?('district'))
702
+ end
703
+ m.send("#{y}=", sql_r)
579
704
  end
580
705
  end
581
706
 
@@ -583,20 +708,20 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
583
708
  ## electricity_produced
584
709
  # photovoltaic
585
710
  photovoltaic_power = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Electric Loads Satisfied' AND RowName='Photovoltaic Power' AND ColumnName='Electricity'")
586
- feature_report.reporting_periods[0].energy_production[:electricity_produced][:photovoltaic] = convert_units(photovoltaic_power, 'GJ', 'kBtu')
711
+ feature_report.reporting_periods[0].energy_production_kwh[:electricity_produced][:photovoltaic] = convert_units(photovoltaic_power, 'GJ', 'kWh')
587
712
 
588
713
  ## Total utility cost
589
714
  total_utility_cost = sql_query(runner, sql_file, 'Economics Results Summary Report', "TableName='Annual Cost' AND RowName='Cost' AND ColumnName='Total'")
590
- feature_report.reporting_periods[0].total_utility_cost = total_utility_cost
715
+ feature_report.reporting_periods[0].total_utility_cost_dollar = total_utility_cost
591
716
 
592
717
  ## Utility Costs
593
718
  # electricity utility cost
594
719
  elec_utility_cost = sql_query(runner, sql_file, 'Economics Results Summary Report', "TableName='Annual Cost' AND RowName='Cost' AND ColumnName='Electric'")
595
- feature_report.reporting_periods[0].utility_costs[0][:fuel_type] = 'Electricity'
596
- feature_report.reporting_periods[0].utility_costs[0][:total_cost] = elec_utility_cost
720
+ feature_report.reporting_periods[0].utility_costs_dollar[0][:fuel_type] = 'Electricity'
721
+ feature_report.reporting_periods[0].utility_costs_dollar[0][:total_cost] = elec_utility_cost
597
722
  # gas utility cost
598
723
  gas_utility_cost = sql_query(runner, sql_file, 'Economics Results Summary Report', "TableName='Annual Cost' AND RowName='Cost' AND ColumnName='Gas'")
599
- feature_report.reporting_periods[0].utility_costs << { fuel_type: 'Natural Gas', total_cost: gas_utility_cost }
724
+ feature_report.reporting_periods[0].utility_costs_dollar << { fuel_type: 'Natural Gas', total_cost: gas_utility_cost }
600
725
 
601
726
  ## comfort_result
602
727
  # time_setpoint_not_met_during_occupied_cooling
@@ -634,6 +759,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
634
759
  'Electricity:Facility',
635
760
  'ElectricityProduced:Facility',
636
761
  'Gas:Facility',
762
+ 'Propane:Facility',
763
+ 'FuelOil#2:Facility',
764
+ 'OtherFuels:Facility',
637
765
  'Cooling:Electricity',
638
766
  'Heating:Electricity',
639
767
  'InteriorLights:Electricity',
@@ -647,6 +775,18 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
647
775
  'Heating:Gas',
648
776
  'WaterSystems:Gas',
649
777
  'InteriorEquipment:Gas',
778
+ 'HeatRejection:Propane',
779
+ 'Heating:Propane',
780
+ 'WaterSystems:Propane',
781
+ 'InteriorEquipment:Propane',
782
+ 'HeatRejection:FuelOil#2',
783
+ 'Heating:FuelOil#2',
784
+ 'WaterSystems:FuelOil#2',
785
+ 'InteriorEquipment:FuelOil#2',
786
+ 'HeatRejection:OtherFuels',
787
+ 'Heating:OtherFuels',
788
+ 'WaterSystems:OtherFuels',
789
+ 'InteriorEquipment:OtherFuels',
650
790
  'DistrictCooling:Facility',
651
791
  'DistrictHeating:Facility',
652
792
  'District Cooling Chilled Water Rate',
@@ -669,6 +809,10 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
669
809
  powerTimeseries = ['Net Electric Energy', 'Electricity:Facility Power', 'ElectricityProduced:Facility Power', 'Electricity:Facility Apparent Power', 'ElectricityProduced:Facility Apparent Power', 'Net Power', 'Net Apparent Power']
670
810
  requested_timeseries_names += powerTimeseries
671
811
 
812
+ # add additional thermal storage timeseries
813
+ tesTimeseries = ['Ice Thermal Storage End Fraction', 'Cooling Coil Ice Thermal Storage End Fraction']
814
+ requested_timeseries_names += tesTimeseries
815
+
672
816
  # register info all timeseries
673
817
  runner.registerInfo("All timeseries: #{requested_timeseries_names}")
674
818
 
@@ -706,8 +850,12 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
706
850
  puts " *********timeseries_name = #{timeseries_name}******************"
707
851
  runner.registerInfo("TIMESERIES: #{timeseries_name}")
708
852
 
709
- # get all the key values that this timeseries can be reported for (e.g. if PMV is requested for each zone)
710
- key_values = sql_file.availableKeyValues('RUN PERIOD 1', 'Zone Timestep', timeseries_name)
853
+ # get all the key values that this timeseries can be reported for (e.g. if PMV is requested for each zone)
854
+ if timeseries_name.include?('OtherFuels')
855
+ key_values = sql_file.availableKeyValues('RUN PERIOD 1', 'Zone Timestep', timeseries_name.upcase)
856
+ else
857
+ key_values = sql_file.availableKeyValues('RUN PERIOD 1', 'Zone Timestep', timeseries_name)
858
+ end
711
859
  runner.registerInfo("KEY VALUES: #{key_values}")
712
860
  if key_values.empty?
713
861
  key_values = ['']
@@ -751,7 +899,11 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
751
899
  # final_timeseries_names << new_timeseries_name
752
900
 
753
901
  # get the actual timeseries
754
- ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, timeseries_name, key_value)
902
+ if timeseries_name.include?('OtherFuels')
903
+ ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, timeseries_name.upcase, key_value)
904
+ else
905
+ ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, timeseries_name, key_value)
906
+ end
755
907
 
756
908
  if n.nil?
757
909
  # first timeseries should always be set
@@ -766,10 +918,15 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
766
918
  values[key_cnt] = Array.new(n, 0)
767
919
  end
768
920
 
921
+ # residential considerations
922
+ building_types.each do |i|
923
+ values[key_cnt] = Array.new(n, 0) if ['DistrictCooling:Facility', 'DistrictHeating:Facility'].include?(timeseries_name) && i[:building_type].include?('Single-Family Detached')
924
+ end
925
+
769
926
  # unit conversion
770
927
  old_unit = ts.get.units if ts.is_initialized
771
928
 
772
- if timeseries_name.include? 'Gas'
929
+ if timeseries_name.include?('Gas') || timeseries_name.include?('Propane') || timeseries_name.include?('FuelOil#2') || timeseries_name.include?('OtherFuels')
773
930
  new_unit = 'kBtu'
774
931
  else
775
932
  new_unit = case old_unit.to_s
@@ -870,6 +1027,22 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
870
1027
  # puts "units = #{new_unit}"
871
1028
  # end
872
1029
 
1030
+ # thermal storage ice end fractions have multiple timeseries, aggregate into a single series with consistent name and use the average value at each timestep
1031
+ if tesTimeseries.include? timeseries_name
1032
+
1033
+ # set up array if 1st key_value
1034
+ if key_i == 0
1035
+ runner.registerInfo("SETTING UP NEW ARRAY FOR: #{timeseries_name}")
1036
+ tmpArray = Array.new(n, 1)
1037
+ end
1038
+
1039
+ # add to array (keep min value at each timestep)
1040
+ (0..(n - 1)).each do |ind|
1041
+ tVal = values[key_cnt][ind].to_f
1042
+ tmpArray[ind] = [tVal, tmpArray[ind]].min
1043
+ end
1044
+ end
1045
+
873
1046
  # comfort results usually have multiple timeseries (per zone), aggregate into a single series with consistent name and use worst value at each timestep
874
1047
  if comfortTimeseries.include? timeseries_name
875
1048