urbanopt-reporting 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/nightly_build.yml +41 -0
- data/CHANGELOG.md +17 -2
- data/Gemfile +5 -5
- data/README.md +4 -2
- data/lib/measures/default_feature_reports/measure.rb +111 -24
- data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +5 -1
- data/lib/urbanopt/reporting/default_reports/logger.rb +2 -0
- data/lib/urbanopt/reporting/default_reports/qaqc_flags.rb +182 -0
- data/lib/urbanopt/reporting/default_reports/reporting_period.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/scenario_power_distribution_cost.rb +212 -0
- data/lib/urbanopt/reporting/default_reports/scenario_report.rb +34 -15
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +372 -31
- data/lib/urbanopt/reporting/version.rb +1 -1
- data/urbanopt-reporting-gem.gemspec +4 -1
- metadata +35 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 186e2233b38a2f167fadd907eb6d768a589ca55dfc0a11e238b363bbc9574c27
|
4
|
+
data.tar.gz: 5cdb0f89a17ea078ef7ed61ed5710892ae956620a5370fe140fd4c8107ab73e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bce9e36d7098ceb88b559d01b4e2eeeb5a30b78c0cacfd476a9501592df3b65b2d9807c45203fb3b2bccb53b3e8334e35acd362f5c848ac089635ce3f9ff932
|
7
|
+
data.tar.gz: 218468f4c8beb0b2dc4c4afa7ef4b7e05410d42bf7898236e58de93048f32c1b3be290a47260bd7d457811821562223e3fbd49845cb77334c5a7e3a9a256bdea
|
@@ -0,0 +1,41 @@
|
|
1
|
+
name: nightly_build
|
2
|
+
|
3
|
+
on:
|
4
|
+
# push:
|
5
|
+
schedule:
|
6
|
+
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule
|
7
|
+
# 5 am UTC (11pm MDT the day before) every weekday night in MDT
|
8
|
+
- cron: '22 5 * * 2-6'
|
9
|
+
|
10
|
+
# Cancels an existing job (of the same workflow) if it is still running
|
11
|
+
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-only-cancel-in-progress-jobs-or-runs-for-the-current-workflow
|
12
|
+
# concurrency:
|
13
|
+
# group: ${{ github.workflow }}-${{ github.ref }}
|
14
|
+
# cancel-in-progress: true
|
15
|
+
|
16
|
+
env:
|
17
|
+
# This env var should enforce develop branch of all dependencies
|
18
|
+
# FAVOR_LOCAL_GEMS: true
|
19
|
+
GEM_DEVELOPER_KEY: ${{ secrets.GEM_DEVELOPER_KEY }}
|
20
|
+
|
21
|
+
jobs:
|
22
|
+
weeknight-tests:
|
23
|
+
# Pinned to `ubuntu-20.04`. When ubuntu-latest adopts 22.04 it would break for us since 22 only supports Ruby 3.1
|
24
|
+
# https://github.com/ruby/setup-ruby#supported-platforms
|
25
|
+
runs-on: ubuntu-20.04
|
26
|
+
container:
|
27
|
+
image: docker://nrel/openstudio:3.4.0
|
28
|
+
steps:
|
29
|
+
- name: Checkout code
|
30
|
+
uses: actions/checkout@v3
|
31
|
+
- name: Update gems
|
32
|
+
run: |
|
33
|
+
bundle update
|
34
|
+
- name: Run Rspec
|
35
|
+
run: bundle exec rspec
|
36
|
+
# coveralls action docs: https://github.com/marketplace/actions/coveralls-github-action
|
37
|
+
- name: Coveralls
|
38
|
+
uses: coverallsapp/github-action@master
|
39
|
+
with:
|
40
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
41
|
+
path-to-lcov: "./coverage/lcov/urbanopt-reporting-gem.lcov"
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,27 @@
|
|
1
1
|
# URBANopt Reporting Gem
|
2
2
|
|
3
|
+
## Version 0.7.0
|
4
|
+
Date Range: 08/18/22 - 12/12/22
|
5
|
+
|
6
|
+
- Update Dependencies for OpenStudio 3.5.0
|
7
|
+
- Fixed [#106]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/106 ), Update UO reporting schema to include DISCO outputs
|
8
|
+
- Fixed [#107]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/107 ), QAQC reporting rollup in feature report and scenario report
|
9
|
+
- Fixed [#127]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/127 ), Clean up log output to stdout
|
10
|
+
|
11
|
+
|
12
|
+
## Version 0.6.2
|
13
|
+
Date Range: 06/28/22 - 08/17/22
|
14
|
+
|
15
|
+
- Fixed [#118]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/118 ), set up actions with coveralls
|
16
|
+
- Fixed [#119]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/119 ), emissions bug fix
|
17
|
+
|
3
18
|
## Version 0.6.1
|
4
|
-
Date Range: 05/10-22 - 06/27/22
|
19
|
+
Date Range: 05/10-22 - 06/27/22
|
5
20
|
|
6
21
|
- Fixed [#114]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/114 ), added natural gas, propane and fuel oil emissions reporting
|
7
22
|
|
8
23
|
## Version 0.6.0
|
9
|
-
Date Range: 11/22/21 - 05/09/22
|
24
|
+
Date Range: 11/22/21 - 05/09/22
|
10
25
|
|
11
26
|
- Fixed [#95]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/95 ), adding additional PV fields to UO output reports
|
12
27
|
- Fixed [#98]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/98 ), add RNM results fields to schema
|
data/Gemfile
CHANGED
@@ -11,8 +11,8 @@ gemspec
|
|
11
11
|
# checkout the latest version (develop) from github.
|
12
12
|
allow_local = ENV['FAVOR_LOCAL_GEMS']
|
13
13
|
|
14
|
-
if allow_local && File.exist?('../openstudio-extension-gem')
|
15
|
-
|
16
|
-
elsif allow_local
|
17
|
-
|
18
|
-
end
|
14
|
+
# if allow_local && File.exist?('../openstudio-extension-gem')
|
15
|
+
# gem 'openstudio-extension', path: '../openstudio-extension-gem'
|
16
|
+
# elsif allow_local
|
17
|
+
# gem 'openstudio-extension', github: 'NREL/openstudio-extension-gem', branch: 'develop'
|
18
|
+
# end
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# URBANopt Reporting Gem
|
2
2
|
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/github/urbanopt/urbanopt-reporting-gem/badge.svg?branch=develop)](https://coveralls.io/github/urbanopt/urbanopt-reporting-gem?branch=develop)
|
4
|
+
|
3
5
|
The URBANopt<sup>™</sup> Reporting Gem defines the URABNopt reports (Scenario and Feature reports). It also includes the default reporting measure which query results from the energyplus sql database and reports it in the Feature reports.
|
4
6
|
|
5
7
|
|
@@ -27,9 +29,9 @@ Or install it yourself as:
|
|
27
29
|
Check out the repository and then execute:
|
28
30
|
|
29
31
|
$ bundle install
|
30
|
-
$ bundle update
|
32
|
+
$ bundle update
|
31
33
|
$ bundle exec rake
|
32
|
-
|
34
|
+
|
33
35
|
## Releasing
|
34
36
|
|
35
37
|
* Update CHANGELOG.md
|
@@ -41,12 +41,12 @@
|
|
41
41
|
require 'urbanopt/reporting/default_reports'
|
42
42
|
require 'csv'
|
43
43
|
require 'benchmark'
|
44
|
+
require 'json'
|
44
45
|
require 'logger'
|
45
46
|
|
46
|
-
@@logger = Logger.new($stdout)
|
47
|
-
|
48
47
|
# start the measure
|
49
48
|
class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
49
|
+
@@logger = Logger.new($stdout)
|
50
50
|
# human readable name
|
51
51
|
def name
|
52
52
|
return 'DefaultFeatureReports'
|
@@ -233,7 +233,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
233
233
|
# result << OpenStudio::IdfObject.load("Output:Variable,*,Exterior Equipment:Electric Vehicles,#{reporting_frequency};").get
|
234
234
|
|
235
235
|
## add environmental factor outputs
|
236
|
-
#result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Output:EnvironmentalImpactFactors,#{reporting_frequency};").get
|
236
|
+
# result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Output:EnvironmentalImpactFactors,#{reporting_frequency};").get
|
237
237
|
# result << OpenStudio::IdfObject.load("Output:Variable,*,Environmental Impact Total N2O Emissions Carbon Equivalent Mass,#{reporting_frequency}; !- HVAC Sum [kg];").get
|
238
238
|
# result << OpenStudio::IdfObject.load("Output:Variable,*,Environmental Impact Total CH4 Emissions Carbon Equivalent Mass,#{reporting_frequency}; !- HVAC Sum [kg];").get
|
239
239
|
# result << OpenStudio::IdfObject.load("Output:Variable,*,Environmental Impact Total CO2 Emissions Carbon Equivalent Mass,#{reporting_frequency}; !- HVAC Sum [kg];").get
|
@@ -252,11 +252,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
252
252
|
ev_timeseries_data = ['Exterior Equipment:Electric Vehicles']
|
253
253
|
|
254
254
|
emissions_timeseries_data = ['Future_Annual_Electricity_Emissions', 'Future_Hourly_Electricity_Emissions',
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
255
|
+
'Historical_Annual_Electricity_Emissions', 'Historical_Hourly_Electricity_Emissions',
|
256
|
+
'Future_Annual_Electricity_Emissions_Intensity', 'Future_Hourly_Electricity_Emissions_Intensity',
|
257
|
+
'Historical_Annual_Electricity_Emissions_Intensity', 'Historical_Hourly_Electricity_Emissions_Intensity']
|
260
258
|
|
261
259
|
timeseries_data += tes_timeseries_data
|
262
260
|
timeseries_data += emissions_timeseries_data
|
@@ -291,6 +289,85 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
291
289
|
return val
|
292
290
|
end
|
293
291
|
|
292
|
+
def feature_qaqc_flags(runner)
|
293
|
+
# QAQC flags by category
|
294
|
+
qaqc_flags_hash = {} # Make a hash for count of flags of each category
|
295
|
+
|
296
|
+
runner.workflow.workflowSteps.each do |step| # Go through all the steps
|
297
|
+
|
298
|
+
if step.to_MeasureStep.is_initialized
|
299
|
+
measure_step = step.to_MeasureStep.get
|
300
|
+
|
301
|
+
measure_name = measure_step.measureDirName
|
302
|
+
|
303
|
+
if measure_step.name.is_initialized
|
304
|
+
measure_name = measure_step.name.get
|
305
|
+
end
|
306
|
+
|
307
|
+
if measure_name.include? 'qaqc'
|
308
|
+
puts "measure_name = #{measure_name}"
|
309
|
+
if measure_step.result.is_initialized
|
310
|
+
result = measure_step.result.get
|
311
|
+
puts " result = #{result}"
|
312
|
+
|
313
|
+
## Adding quaqc_flags_list to check the step value name since units key is missing from the result
|
314
|
+
## It does show in the out.osw but not in the runner.workflow.workflowSteps object
|
315
|
+
# use this list to define the flags you want to report
|
316
|
+
qaqc_flags_list = ['eui_reasonableness' , 'end_use_by_category',
|
317
|
+
'mechanical_system_part_load_efficiency', 'simultaneous_heating_and_cooling',
|
318
|
+
'internal_loads', 'schedules', 'envelope_r_value', 'domestic_hot_water',
|
319
|
+
'mechanical_system_efficiency', 'supply_and_zone_air_temperature', 'total_qaqc_flags' ]
|
320
|
+
|
321
|
+
result.stepValues.each do |step_value|
|
322
|
+
|
323
|
+
#get name
|
324
|
+
name = step_value.name
|
325
|
+
|
326
|
+
if qaqc_flags_list.include? name
|
327
|
+
|
328
|
+
# get value
|
329
|
+
# check if value, double, int, or bool
|
330
|
+
value_type = step_value.variantType.valueDescription
|
331
|
+
if value_type == "Double"
|
332
|
+
value = step_value.valueAsDouble
|
333
|
+
elsif value_type == "Integer"
|
334
|
+
value = step_value.valueAsInteger
|
335
|
+
elsif value_type == "Boolean"
|
336
|
+
value = step_value.valueAsBoolean
|
337
|
+
elsif value_type == "String"
|
338
|
+
value = step_value.valueAsString
|
339
|
+
else
|
340
|
+
# catchall for unexpected value types
|
341
|
+
value = step_value.valueAsVariant.to_s
|
342
|
+
end
|
343
|
+
|
344
|
+
if qaqc_flags_hash[name]
|
345
|
+
qaqc_flags_hash[name] += value
|
346
|
+
else
|
347
|
+
qaqc_flags_hash[name] = value
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|
353
|
+
|
354
|
+
puts "qaqc_flags_hash = #{qaqc_flags_hash}"
|
355
|
+
|
356
|
+
# Hack to put 'total_qaqc_flags' at the end of the hash
|
357
|
+
temp_hash_for_ordering = { 'total_qaqc_flags' => qaqc_flags_hash['total_qaqc_flags'] }
|
358
|
+
qaqc_flags_hash.delete('total_qaqc_flags')
|
359
|
+
qaqc_flags_hash['total_qaqc_flags'] = temp_hash_for_ordering['total_qaqc_flags']
|
360
|
+
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|
368
|
+
return qaqc_flags_hash
|
369
|
+
end
|
370
|
+
|
294
371
|
# unit conversion method
|
295
372
|
def convert_units(value, from_units, to_units)
|
296
373
|
if value.nil?
|
@@ -836,7 +913,6 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
836
913
|
|
837
914
|
# electricity emissions
|
838
915
|
begin
|
839
|
-
|
840
916
|
# future_annual_emissions
|
841
917
|
future_annual_emissions_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Future_Annual_Electricity_Emissions', 'EMS')
|
842
918
|
feature_report.reporting_periods[0].emissions[:future_annual_electricity_emissions_mt] = future_annual_emissions_ts.get.values.sum
|
@@ -868,11 +944,24 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
868
944
|
# historical_hourly_emissions_intensity
|
869
945
|
historical_hourly_emissions_intensity_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Historical_Hourly_Electricity_Emissions_Intensity', 'EMS')
|
870
946
|
feature_report.reporting_periods[0].emissions[:historical_hourly_electricity_emissions_intensity_kg_per_ft2] = historical_hourly_emissions_intensity_ts.get.values.sum
|
871
|
-
|
872
947
|
rescue StandardError
|
873
948
|
@@logger.info('Emissions are not reported for this feature')
|
874
949
|
end
|
875
950
|
|
951
|
+
# add qaqc results to feature report
|
952
|
+
qaqc_flags_hash = feature_qaqc_flags(runner)
|
953
|
+
feature_report.qaqc_flags.eui_reasonableness = qaqc_flags_hash['eui_reasonableness']
|
954
|
+
feature_report.qaqc_flags.end_use_by_category = qaqc_flags_hash['end_use_by_category']
|
955
|
+
feature_report.qaqc_flags.mechanical_system_part_load_efficiency = qaqc_flags_hash['mechanical_system_part_load_efficiency']
|
956
|
+
feature_report.qaqc_flags.simultaneous_heating_and_cooling = qaqc_flags_hash['simultaneous_heating_and_cooling']
|
957
|
+
feature_report.qaqc_flags.internal_loads = qaqc_flags_hash['internal_loads']
|
958
|
+
feature_report.qaqc_flags.schedules = qaqc_flags_hash['schedules']
|
959
|
+
feature_report.qaqc_flags.envelope_r_value = qaqc_flags_hash['envelope_r_value']
|
960
|
+
feature_report.qaqc_flags.domestic_hot_water = qaqc_flags_hash['domestic_hot_water']
|
961
|
+
feature_report.qaqc_flags.mechanical_system_efficiency = qaqc_flags_hash['mechanical_system_efficiency']
|
962
|
+
feature_report.qaqc_flags.supply_and_zone_air_temperature = qaqc_flags_hash['supply_and_zone_air_temperature']
|
963
|
+
feature_report.qaqc_flags.total_qaqc_flags = qaqc_flags_hash['total_qaqc_flags']
|
964
|
+
|
876
965
|
##########################################################################################################################
|
877
966
|
# set conversion variables
|
878
967
|
conv_J_mwh = 1000000 * 60 * 60 # J to MWh (1000000J/MJ * 60hr/min * 60 min/sec)
|
@@ -888,7 +977,6 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
888
977
|
fo1_val = 294.962046
|
889
978
|
fo2_val = 294.962046
|
890
979
|
|
891
|
-
|
892
980
|
##########################################################################################################################
|
893
981
|
######################################## Reporting TImeseries Results FOR CSV File #######################################
|
894
982
|
|
@@ -948,7 +1036,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
948
1036
|
'Historical_Hourly_Electricity_Emissions_Intensity',
|
949
1037
|
'Natural_Gas_Emissions',
|
950
1038
|
'Natural_Gas_Emissions_Intensity',
|
951
|
-
'Propane_Emissions',
|
1039
|
+
'Propane_Emissions',
|
952
1040
|
'Propane_Emissions_Intensity',
|
953
1041
|
'FuelOilNo2_Emissions',
|
954
1042
|
'FuelOilNo2_Emissions_Intensity',
|
@@ -980,7 +1068,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
980
1068
|
runner.registerInfo("All timeseries: #{requested_timeseries_names}")
|
981
1069
|
|
982
1070
|
# timeseries variables to keep to calculate power
|
983
|
-
tsToKeep = ['Electricity:Facility', 'ElectricityProduced:Facility','Propane:Facility', 'NaturalGas:Facility', 'FuelOilNo2:Facility', 'FuelOilNo1:Facility']
|
1071
|
+
tsToKeep = ['Electricity:Facility', 'ElectricityProduced:Facility', 'Propane:Facility', 'NaturalGas:Facility', 'FuelOilNo2:Facility', 'FuelOilNo1:Facility']
|
984
1072
|
tsToKeepIndexes = {}
|
985
1073
|
|
986
1074
|
### powerFactor ###
|
@@ -1145,7 +1233,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1145
1233
|
if timeseries_name == 'Natural_Gas_Emissions'
|
1146
1234
|
newVals = Array.new(n, 0)
|
1147
1235
|
(0..n - 1).each do |j|
|
1148
|
-
newVals[j] = (nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f
|
1236
|
+
newVals[j] = (nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f
|
1149
1237
|
j += 1
|
1150
1238
|
end
|
1151
1239
|
new_unit = 'MT'
|
@@ -1158,7 +1246,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1158
1246
|
if timeseries_name == 'Propane_Emissions'
|
1159
1247
|
newVals = Array.new(n, 0)
|
1160
1248
|
(0..n - 1).each do |j|
|
1161
|
-
newVals[j] = (lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f
|
1249
|
+
newVals[j] = (lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f
|
1162
1250
|
j += 1
|
1163
1251
|
end
|
1164
1252
|
new_unit = 'MT'
|
@@ -1171,7 +1259,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1171
1259
|
if timeseries_name == 'FuelOilNo2_Emissions'
|
1172
1260
|
newVals = Array.new(n, 0)
|
1173
1261
|
(0..n - 1).each do |j|
|
1174
|
-
newVals[j] = (fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f
|
1262
|
+
newVals[j] = (fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f
|
1175
1263
|
j += 1
|
1176
1264
|
end
|
1177
1265
|
new_unit = 'MT'
|
@@ -1183,12 +1271,12 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1183
1271
|
|
1184
1272
|
### calculate emissions intensity metric
|
1185
1273
|
# get flr_area
|
1186
|
-
flr_area = building.floorArea * 10.764 #change from m2 to ft2
|
1274
|
+
flr_area = building.floorArea * 10.764 # change from m2 to ft2
|
1187
1275
|
|
1188
1276
|
if timeseries_name == 'Natural_Gas_Emissions_Intensity'
|
1189
1277
|
newVals = Array.new(n, 0)
|
1190
1278
|
(0..n - 1).each do |j|
|
1191
|
-
newVals[j] = (((nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f
|
1279
|
+
newVals[j] = (((nat_gas_val * (values[tsToKeepIndexes['NaturalGas:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
|
1192
1280
|
j += 1
|
1193
1281
|
end
|
1194
1282
|
new_unit = 'KG/FT2'
|
@@ -1201,7 +1289,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1201
1289
|
if timeseries_name == 'Propane_Emissions_Intensity'
|
1202
1290
|
newVals = Array.new(n, 0)
|
1203
1291
|
(0..n - 1).each do |j|
|
1204
|
-
newVals[j] = (((lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f
|
1292
|
+
newVals[j] = (((lpg_val * (values[tsToKeepIndexes['Propane:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
|
1205
1293
|
j += 1
|
1206
1294
|
end
|
1207
1295
|
new_unit = 'KG/FT2'
|
@@ -1214,7 +1302,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1214
1302
|
if timeseries_name == 'FuelOilNo2_Emissions_Intensity'
|
1215
1303
|
newVals = Array.new(n, 0)
|
1216
1304
|
(0..n - 1).each do |j|
|
1217
|
-
newVals[j] = (((fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f
|
1305
|
+
newVals[j] = (((fo2_val * (values[tsToKeepIndexes['FuelOilNo2:Facility']][j].to_f * conv_kbtu_J.to_f) / conv_J_mwh.to_f) * conv_kg_mt.to_f) * 1000 / flr_area) # unit: kg/ft2 - changed mt to kg
|
1218
1306
|
j += 1
|
1219
1307
|
end
|
1220
1308
|
new_unit = 'KG/FT2'
|
@@ -1280,8 +1368,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1280
1368
|
end
|
1281
1369
|
end
|
1282
1370
|
end
|
1283
|
-
end
|
1284
|
-
|
1371
|
+
end
|
1285
1372
|
|
1286
1373
|
# append units to headers
|
1287
1374
|
new_timeseries_name += "(#{new_unit})"
|
@@ -1414,7 +1501,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1414
1501
|
end
|
1415
1502
|
end
|
1416
1503
|
|
1417
|
-
puts "values = #{values}"
|
1504
|
+
#puts "values = #{values}"
|
1418
1505
|
|
1419
1506
|
# closing the sql file
|
1420
1507
|
sql_file.close
|
@@ -1425,8 +1512,8 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
1425
1512
|
feature_report.timeseries_csv.first_report_datetime = '0'
|
1426
1513
|
feature_report.timeseries_csv.column_names = final_timeseries_names
|
1427
1514
|
|
1428
|
-
##### Save the 'default_feature_reports.json' file
|
1429
1515
|
|
1516
|
+
##### Save the 'default_feature_reports.json' file
|
1430
1517
|
feature_report_hash = feature_report.to_hash
|
1431
1518
|
|
1432
1519
|
File.open('default_feature_reports.json', 'w') do |f|
|
@@ -210,7 +210,7 @@ module URBANopt
|
|
210
210
|
##
|
211
211
|
# [parameters:]
|
212
212
|
#
|
213
|
-
# * +hash+ - _Hash_ - A hash
|
213
|
+
# * +hash+ - _Hash_ - A hash containing key/value pairs for the distributed generation system attributes listed above.
|
214
214
|
#
|
215
215
|
def initialize(hash = {})
|
216
216
|
hash.delete_if { |k, v| v.nil? }
|
@@ -63,7 +63,7 @@ module URBANopt
|
|
63
63
|
# The DefaultPostProcessor reads these feature reports and aggregates them to create a ScenarioReport.
|
64
64
|
##
|
65
65
|
class FeatureReport
|
66
|
-
attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
|
66
|
+
attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status, :qaqc_flags,
|
67
67
|
:timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution, :thermal_storage # :nodoc:
|
68
68
|
|
69
69
|
##
|
@@ -82,6 +82,7 @@ module URBANopt
|
|
82
82
|
@feature_type = hash[:feature_type]
|
83
83
|
@timesteps_per_hour = hash[:timesteps_per_hour]
|
84
84
|
@simulation_status = hash[:simulation_status]
|
85
|
+
@qaqc_flags = QAQC.new(hash[:qaqc_flags])
|
85
86
|
@timeseries_csv = TimeseriesCSV.new(hash[:timeseries_csv])
|
86
87
|
@timeseries_csv.run_dir_name(@directory_name)
|
87
88
|
@location = Location.new(hash[:location])
|
@@ -124,6 +125,7 @@ module URBANopt
|
|
124
125
|
hash[:distributed_generation] = {}
|
125
126
|
hash[:power_distribution] = {}
|
126
127
|
hash[:thermal_storage] = {}
|
128
|
+
hash[:qaqc_flags] = {}
|
127
129
|
return hash
|
128
130
|
end
|
129
131
|
|
@@ -227,6 +229,8 @@ module URBANopt
|
|
227
229
|
|
228
230
|
result[:thermal_storage] = @thermal_storage.to_hash if @thermal_storage
|
229
231
|
|
232
|
+
result[:qaqc_flags] = @qaqc_flags.to_hash if @qaqc_flags
|
233
|
+
|
230
234
|
# validate feature_report properties against schema
|
231
235
|
if @@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result).any?
|
232
236
|
raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result)}"
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
+
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
30
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
31
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
32
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
33
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
34
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
35
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
36
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
37
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
38
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
# *********************************************************************************
|
40
|
+
|
41
|
+
require 'json'
|
42
|
+
require 'json-schema'
|
43
|
+
|
44
|
+
module URBANopt
|
45
|
+
module Reporting
|
46
|
+
module DefaultReports
|
47
|
+
##
|
48
|
+
# QAQC flags for each feature
|
49
|
+
##
|
50
|
+
class QAQC
|
51
|
+
##
|
52
|
+
# _Hash_ - Hash of flags raised by QAQC measure for this feature during this reporting period
|
53
|
+
#
|
54
|
+
attr_accessor :eui_reasonableness,:end_use_by_category,:mechanical_system_part_load_efficiency,
|
55
|
+
:simultaneous_heating_and_cooling , :internal_loads , :schedules, :envelope_r_value,
|
56
|
+
:domestic_hot_water , :mechanical_system_efficiency , :supply_and_zone_air_temperature,
|
57
|
+
:total_qaqc_flags
|
58
|
+
|
59
|
+
##
|
60
|
+
# QAQC class initialize quaqc attributes: +:eui_reasonableness,+:end_use_by_category,+:mechanical_system_part_load_efficiency,
|
61
|
+
# +:simultaneous_heating_and_cooling , +:internal_loads , +:schedules, +:envelope_r_value,
|
62
|
+
# +:domestic_hot_water , +:mechanical_system_efficiency , +:supply_and_zone_air_temperature, +:total_qaqc_flags
|
63
|
+
##
|
64
|
+
# [parameters:]
|
65
|
+
#
|
66
|
+
# * +hash+ - _Hash_ - A hash containing qaqc attributes listed above.
|
67
|
+
#
|
68
|
+
def initialize(hash = {})
|
69
|
+
hash.delete_if { |k, v| v.nil? }
|
70
|
+
hash = defaults.merge(hash)
|
71
|
+
|
72
|
+
@eui_reasonableness = hash[:eui_reasonableness]
|
73
|
+
@end_use_by_category = hash[:end_use_by_category]
|
74
|
+
@mechanical_system_part_load_efficiency = hash[:mechanical_system_part_load_efficiency]
|
75
|
+
@simultaneous_heating_and_cooling = hash[:simultaneous_heating_and_cooling]
|
76
|
+
@supply_and_zone_air_temperature = hash[:supply_and_zone_air_temperature]
|
77
|
+
@internal_loads = hash[:internal_loads]
|
78
|
+
@schedules = hash[:schedules]
|
79
|
+
@envelope_r_value = hash[:envelope_r_value]
|
80
|
+
@domestic_hot_water = hash[:domestic_hot_water]
|
81
|
+
@mechanical_system_efficiency = hash[:mechanical_system_efficiency]
|
82
|
+
@total_qaqc_flags = hash[:total_qaqc_flags]
|
83
|
+
|
84
|
+
|
85
|
+
# initialize class variables @@validator and @@schema
|
86
|
+
@@validator ||= Validator.new
|
87
|
+
@@schema ||= @@validator.schema
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
##
|
93
|
+
# Assigns default values if values do not exist.
|
94
|
+
##
|
95
|
+
def defaults
|
96
|
+
hash = {}
|
97
|
+
|
98
|
+
hash[:eui_reasonableness] = nil
|
99
|
+
hash[:end_use_by_category] = nil
|
100
|
+
hash[:mechanical_system_part_load_efficiency] = nil
|
101
|
+
hash[:simultaneous_heating_and_cooling] = nil
|
102
|
+
hash[:supply_and_zone_air_temperature] = nil
|
103
|
+
hash[:internal_loads] = nil
|
104
|
+
hash[:schedules] = nil
|
105
|
+
hash[:envelope_r_value] = nil
|
106
|
+
hash[:domestic_hot_water] = nil
|
107
|
+
hash[:mechanical_system_efficiency] = nil
|
108
|
+
hash[:total_qaqc_flags] = nil
|
109
|
+
|
110
|
+
|
111
|
+
return hash
|
112
|
+
end
|
113
|
+
##
|
114
|
+
# Convert to a Hash equivalent for JSON serialization
|
115
|
+
##
|
116
|
+
def to_hash
|
117
|
+
result = {}
|
118
|
+
|
119
|
+
result[:eui_reasonableness] = @eui_reasonableness
|
120
|
+
result[:end_use_by_category] = @end_use_by_category
|
121
|
+
result[:mechanical_system_part_load_efficiency] = @mechanical_system_part_load_efficiency
|
122
|
+
result[:simultaneous_heating_and_cooling] = @simultaneous_heating_and_cooling
|
123
|
+
result[:supply_and_zone_air_temperature] = @supply_and_zone_air_temperature
|
124
|
+
result[:internal_loads] = @internal_loads
|
125
|
+
result[:schedules] = @schedules
|
126
|
+
result[:envelope_r_value] = @envelope_r_value
|
127
|
+
result[:domestic_hot_water] = @domestic_hot_water
|
128
|
+
result[:mechanical_system_efficiency] = @mechanical_system_efficiency
|
129
|
+
result[:total_qaqc_flags] = @total_qaqc_flags
|
130
|
+
|
131
|
+
# validate program properties against schema
|
132
|
+
if @@validator.validate(@@schema[:definitions][:qaqc_flags][:properties], result).any?
|
133
|
+
raise "qaqc properties does not match schema: #{@@validator.validate(@@schema[:definitions][:qaqc_flags][:properties], result)}"
|
134
|
+
end
|
135
|
+
|
136
|
+
return result
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Adds up +existing_value+ and +new_values+ if not nill.
|
142
|
+
##
|
143
|
+
# [parameters:]
|
144
|
+
# +existing_value+ - _Float_ - A value corresponding to a qaqc_flags attribute.
|
145
|
+
##
|
146
|
+
# +new_value+ - _Float_ - A value corresponding to a qaqc_flags attribute.
|
147
|
+
##
|
148
|
+
def add_values(existing_value, new_value) #:nodoc:
|
149
|
+
if existing_value && new_value
|
150
|
+
existing_value += new_value
|
151
|
+
elsif new_value
|
152
|
+
existing_value = new_value
|
153
|
+
end
|
154
|
+
return existing_value
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Merges qaqc_flags objects to each other by summing up values.
|
159
|
+
##
|
160
|
+
# [parameters:]
|
161
|
+
# +other+ - _QAQC_ - An object of Program class.
|
162
|
+
##
|
163
|
+
def add_qaqc_flags(other)
|
164
|
+
|
165
|
+
@eui_reasonableness = add_values(@eui_reasonableness, other.eui_reasonableness)
|
166
|
+
@end_use_by_category = add_values(@end_use_by_category, other.end_use_by_category)
|
167
|
+
@mechanical_system_part_load_efficiency = add_values(@mechanical_system_part_load_efficiency, other.mechanical_system_part_load_efficiency)
|
168
|
+
@simultaneous_heating_and_cooling = add_values(@simultaneous_heating_and_cooling, other.simultaneous_heating_and_cooling)
|
169
|
+
@supply_and_zone_air_temperature = add_values(@supply_and_zone_air_temperature, other.supply_and_zone_air_temperature)
|
170
|
+
@internal_loads = add_values(@internal_loads, other.internal_loads)
|
171
|
+
@schedules = add_values(@schedules, other.schedules)
|
172
|
+
@envelope_r_value = add_values(@envelope_r_value, other.envelope_r_value)
|
173
|
+
@domestic_hot_water = add_values(@domestic_hot_water, other.domestic_hot_water)
|
174
|
+
@mechanical_system_efficiency = add_values(@mechanical_system_efficiency, other.mechanical_system_efficiency)
|
175
|
+
@total_qaqc_flags = add_values(@total_qaqc_flags, other.total_qaqc_flags)
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -222,7 +222,7 @@ module URBANopt
|
|
222
222
|
result[:comfort_result] = comfort_result_hash if @comfort_result
|
223
223
|
|
224
224
|
emissions_hash = @emissions if @emissions
|
225
|
-
|
225
|
+
emissions_hash.delete_if { |k, v| v.nil? }
|
226
226
|
result[:emissions] = emissions_hash if @emissions
|
227
227
|
|
228
228
|
# validates +reporting_period+ properties against schema for reporting period.
|