urbanopt-scenario 0.1.1 → 0.2.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -8
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +2 -10
  4. data/.github/pull_request_template.md +5 -15
  5. data/{.github/CONTRIBUTING.md → CONTRIBUTING.md} +0 -0
  6. data/Gemfile +4 -2
  7. data/Jenkinsfile +2 -2
  8. data/Rakefile +1 -1
  9. data/docs/package-lock.json +4607 -6451
  10. data/docs/package.json +1 -1
  11. data/lib/measures/default_feature_reports/LICENSE.md +1 -1
  12. data/lib/measures/default_feature_reports/README.md +1 -1
  13. data/lib/measures/default_feature_reports/measure.rb +256 -41
  14. data/lib/measures/default_feature_reports/measure.xml +19 -15
  15. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +204 -17
  16. data/lib/urbanopt/scenario/default_reports/feature_report.rb +47 -0
  17. data/lib/urbanopt/scenario/default_reports/program.rb +6 -1
  18. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +5 -2
  19. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +17 -6
  20. data/lib/urbanopt/scenario/default_reports/schema/README.md +11 -12
  21. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +14 -6
  22. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +27 -18
  23. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +1 -0
  24. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +29 -3
  25. data/lib/urbanopt/scenario/scenario_runner_osw.rb +21 -5
  26. data/lib/urbanopt/scenario/version.rb +1 -1
  27. data/urbanopt-scenario-gem.gemspec +7 -5
  28. metadata +39 -25
  29. data/.travis.yml +0 -23
@@ -13,7 +13,7 @@
13
13
  "highlight.js": "^9.15.6",
14
14
  "json-schema-ref-parser": "^6.1.0",
15
15
  "json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
16
- "vuepress": "^0.14.10",
16
+ "vuepress": "^1.2.0",
17
17
  "webpack-dev-middleware": "^3.6.0"
18
18
  },
19
19
  "devDependencies": {
@@ -1,4 +1,4 @@
1
- URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
1
+ URBANopt, 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,
@@ -5,7 +5,7 @@
5
5
  # DefaultFeatureReports
6
6
 
7
7
  ## Description
8
- Writes default_feature_reports.json file used by URBANopt Scenario Default Post Processor
8
+ Writes default_feature_reports.json and default_feature_reports.csv files used by URBANopt Scenario Default Post Processor
9
9
 
10
10
  ## Modeler Description
11
11
  This measure only allows for one feature_report per simulation. If multiple features are simulated in a single simulation, a new measure must be written to disaggregate simulation results to multiple features.
@@ -44,7 +44,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
44
44
 
45
45
  # human readable description
46
46
  def description
47
- return 'Writes default_feature_reports.json file used by URBANopt Scenario Default Post Processor'
47
+ return 'Writes default_feature_reports.json and default_feature_reports.csv files used by URBANopt Scenario Default Post Processor'
48
48
  end
49
49
 
50
50
  # human readable description of modeling approach
@@ -77,7 +77,8 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
77
77
  reporting_frequency_chs << 'Timestep'
78
78
  reporting_frequency_chs << 'Hourly'
79
79
  reporting_frequency_chs << 'Daily'
80
- # reporting_frequency_chs << "BillingPeriod" # match it to utility bill object
80
+ # reporting_frequency_chs << 'Zone Timestep'
81
+ reporting_frequency_chs << 'BillingPeriod' # match it to utility bill object
81
82
  ## Utility report here to report the start and end for each fueltype
82
83
  reporting_frequency_chs << 'Monthly'
83
84
  reporting_frequency_chs << 'Runperiod'
@@ -85,17 +86,13 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
85
86
  reporting_frequency = OpenStudio::Measure::OSArgument.makeChoiceArgument('reporting_frequency', reporting_frequency_chs, true)
86
87
  reporting_frequency.setDisplayName('Reporting Frequency')
87
88
  reporting_frequency.setDescription('The frequency at which to report timeseries output data.')
88
- reporting_frequency.setDefaultValue('Hourly')
89
+ reporting_frequency.setDefaultValue('Timestep')
89
90
  args << reporting_frequency
90
91
 
91
- # move this in the run method
92
- if reporting_frequency.defaultValueDisplayName == 'BillingPeriod'
93
- @@logger.error('BillingPeriod frequency is not implemented yet')
94
- end
95
-
96
92
  return args
97
93
  end
98
94
 
95
+ # define fuel types
99
96
  def fuel_types
100
97
  fuel_types = [
101
98
  'Electricity',
@@ -109,6 +106,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
109
106
  return fuel_types
110
107
  end
111
108
 
109
+ # define enduses
112
110
  def end_uses
113
111
  end_uses = [
114
112
  'Heating',
@@ -131,6 +129,24 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
131
129
  return end_uses
132
130
  end
133
131
 
132
+ # format datetime
133
+ def format_datetime(date_time)
134
+ date_time.tr!('-', '/')
135
+ date_time.gsub!('Jan', '01')
136
+ date_time.gsub!('Feb', '02')
137
+ date_time.gsub!('Mar', '03')
138
+ date_time.gsub!('Apr', '04')
139
+ date_time.gsub!('May', '05')
140
+ date_time.gsub!('Jun', '06')
141
+ date_time.gsub!('Jul', '07')
142
+ date_time.gsub!('Aug', '08')
143
+ date_time.gsub!('Sep', '09')
144
+ date_time.gsub!('Oct', '10')
145
+ date_time.gsub!('Nov', '11')
146
+ date_time.gsub!('Dec', '12')
147
+ return date_time
148
+ end
149
+
134
150
  # return a vector of IdfObject's to request EnergyPlus objects needed by the run method
135
151
  # rubocop:disable Naming/MethodName
136
152
  def energyPlusOutputRequests(runner, user_arguments)
@@ -152,7 +168,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
152
168
  end
153
169
  end
154
170
 
155
- ### Request the output for each end use/fuel type combination
171
+ # Request the output for each end use/fuel type combination
156
172
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Electricity:Facility,#{reporting_frequency};").get
157
173
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,ElectricityProduced:Facility,#{reporting_frequency};").get
158
174
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Gas:Facility,#{reporting_frequency};").get
@@ -229,6 +245,11 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
229
245
  # Assign the user inputs to variables
230
246
  reporting_frequency = runner.getStringArgumentValue('reporting_frequency', user_arguments)
231
247
 
248
+ # BilingPeriod reporting frequency not implemented yet
249
+ if reporting_frequency == 'BillingPeriod'
250
+ @@logger.error('BillingPeriod frequency is not implemented yet')
251
+ end
252
+
232
253
  # cache runner for this instance of the measure
233
254
  @runner = runner
234
255
 
@@ -271,7 +292,10 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
271
292
  feature_report.name = feature_name
272
293
  feature_report.feature_type = feature_type
273
294
  feature_report.directory_name = workflow.absoluteRunDir
274
- feature_report.timesteps_per_hour = model.getTimestep.numberOfTimestepsPerHour
295
+
296
+ timesteps_per_hour = model.getTimestep.numberOfTimestepsPerHour
297
+ feature_report.timesteps_per_hour = timesteps_per_hour
298
+
275
299
  feature_report.simulation_status = 'Complete'
276
300
 
277
301
  feature_report.reporting_periods << URBANopt::Scenario::DefaultReports::ReportingPeriod.new
@@ -434,6 +458,10 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
434
458
  aspect_ratio ||= nil
435
459
  feature_report.program.aspect_ratio = aspect_ratio
436
460
 
461
+ # total_construction_cost
462
+ 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'")
463
+ feature_report.program.total_construction_cost = total_construction_cost
464
+
437
465
  ############################################################################
438
466
  ##
439
467
  # Get Reporting Periods information and store in the feature_report
@@ -592,23 +620,53 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
592
620
  'District Heating Outlet Temperature'
593
621
  ]
594
622
 
623
+ # add thermal comfort timeseries
624
+ comfortTimeseries = ['Zone Thermal Comfort Fanger Model PMV', 'Zone Thermal Comfort Fanger Model PPD']
625
+ requested_timeseries_names += comfortTimeseries
626
+
627
+ # add additional power timeseries (for calculating transformer apparent power to compare to rating ) in VA
628
+ powerTimeseries = ['Net Electric Energy', 'Electricity:Facility Power', 'ElectricityProduced:Facility Power', 'Electricity:Facility Apparent Power', 'ElectricityProduced:Facility Apparent Power', 'Net Power', 'Net Apparent Power']
629
+ requested_timeseries_names += powerTimeseries
630
+
631
+ # register info all timeseries
632
+ runner.registerInfo("All timeseries: #{requested_timeseries_names}")
633
+
634
+ # timeseries variables to keep to calculate power
635
+ tsToKeep = ['Electricity:Facility', 'ElectricityProduced:Facility']
636
+ tsToKeepIndexes = {}
637
+
638
+ ### powerFactor ###
639
+ # use power_factor default: 0.9
640
+ # TODO: Set powerFactor default based on building type
641
+ powerFactor = 0.9
642
+
643
+ ### power_conversion ###
644
+ # divide values by total_seconds to convert J to W (W = J/sec)
645
+ # divide values by total_hours to convert kWh to kW (kW = kWh/hrs)
646
+ total_seconds = (60 / timesteps_per_hour.to_f) * 60 # make sure timesteps_per_hour is a float in the division
647
+ total_hours = 1 / timesteps_per_hour.to_f # make sure timesteps_per_hour is a float in the division
648
+ # set power_conversion
649
+ power_conversion = total_hours
650
+ puts "Power Converion: to convert kWh to kW values will be divided by #{power_conversion}"
651
+
595
652
  # number of values in each timeseries
596
653
  n = nil
597
-
598
- # all numeric timeseries values, transpose of CSV file (e.g. values[j] is column, values[j][i] is column and row)
654
+ # all numeric timeseries values, transpose of CSV file (e.g. values[key_cnt] is column, values[key_cnt][i] is column and row)
599
655
  values = []
600
-
601
- # Since schedule value will have a bunch of key_values, we need to keep track of these as additional timeseries
656
+ tmpArray = []
657
+ # since schedule value will have a bunch of key_values, we need to keep track of these as additional timeseries
658
+ key_cnt = 0
602
659
  # this is recording the name of these final timeseries to write in the header of the CSV
603
660
  final_timeseries_names = []
604
661
 
605
662
  # loop over requested timeseries
606
663
  # rubocop: disable Metrics/BlockLength
607
- requested_timeseries_names.each_with_index do |timeseries_name, j|
664
+ requested_timeseries_names.each_index do |i|
665
+ timeseries_name = requested_timeseries_names[i]
608
666
  runner.registerInfo("TIMESERIES: #{timeseries_name}")
609
667
 
610
- # get all the key values that this timeseries can be reported for (e.g. if power is requested for each zone)
611
- key_values = sql_file.availableKeyValues(ann_env_pd.to_s, reporting_frequency.to_s, timeseries_name)
668
+ # get all the key values that this timeseries can be reported for (e.g. if PMV is requested for each zone)
669
+ key_values = sql_file.availableKeyValues('RUN PERIOD 1', 'Zone Timestep', timeseries_name)
612
670
  runner.registerInfo("KEY VALUES: #{key_values}")
613
671
  if key_values.empty?
614
672
  key_values = ['']
@@ -616,7 +674,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
616
674
 
617
675
  # sort keys
618
676
  sorted_keys = key_values.sort
619
- requested_keys = ['SUMMED ELECTRICITY:FACILITY', 'SUMMED ELECTRICITY:FACILITY POWER', 'SUMMED ELECTRICITYPRODUCED:FACILITY', 'SUMMED ELECTRICITYPRODUCED:FACILITY POWER', 'SUMMED NET APPARENT POWER', 'SUMMED NET ELECTRIC ENERGY', 'SUMMED NET POWER', 'TRANSFORMER OUTPUT ELECTRIC ENERGY SCHEDULE']
677
+ requested_keys = requested_timeseries_names
620
678
  final_keys = []
621
679
  # make sure aggregated timeseries are listed in sorted order before all individual feature timeseries
622
680
  sorted_keys.each do |k|
@@ -649,7 +707,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
649
707
  new_timeseries_name = key_value
650
708
  end
651
709
  end
652
- final_timeseries_names << new_timeseries_name
710
+ # final_timeseries_names << new_timeseries_name
653
711
 
654
712
  # get the actual timeseries
655
713
  ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, timeseries_name, key_value)
@@ -657,38 +715,195 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
657
715
  if n.nil?
658
716
  # first timeseries should always be set
659
717
  runner.registerInfo('First timeseries')
660
- values[j] = ts.get.values
661
- n = values[j].size
718
+ values[key_cnt] = ts.get.values
719
+ n = values[key_cnt].size
662
720
  elsif ts.is_initialized
663
721
  runner.registerInfo('Is Initialized')
664
- values[j] = ts.get.values
722
+ values[key_cnt] = ts.get.values
665
723
  else
666
724
  runner.registerInfo('Is NOT Initialized')
667
- values[j] = Array.new(n, 0)
725
+ values[key_cnt] = Array.new(n, 0)
668
726
  end
669
727
 
670
- # ##Unit conversion
671
- old_units = ts.get.units if ts.is_initialized
672
- new_units = case old_units.to_s
673
- when 'J'
674
- 'kBtu'
675
- when 'kWh'
676
- 'kBtu'
677
- when 'm3'
678
- 'gal'
679
- end
680
-
681
- # Unit conversion here
682
- os_vec = values[j]
683
-
684
- # loop through each value to retrieve it
685
- for i in 0..os_vec.length - 1
686
- unless new_units == old_units
687
- os_vec[i] = OpenStudio.convert(os_vec[i], old_units, new_units).get
728
+ # unit conversion
729
+ old_unit = ts.get.units if ts.is_initialized
730
+
731
+ if timeseries_name.include? 'Gas'
732
+ new_unit = 'kBtu'
733
+ else
734
+ new_unit = case old_unit.to_s
735
+ when 'J'
736
+ 'kWh'
737
+ when 'kBtu'
738
+ 'kWh'
739
+ when 'gal'
740
+ 'm3'
741
+ end
742
+ end
743
+ # loop through each value and apply unit conversion
744
+ os_vec = values[key_cnt]
745
+ if !timeseries_name.include? 'Zone Thermal Comfort'
746
+ for i in 0..os_vec.length - 1
747
+ unless new_unit == old_unit
748
+ os_vec[i] = OpenStudio.convert(os_vec[i], old_unit, new_unit).get
749
+ end
688
750
  end
689
751
  end
752
+
753
+ # keep certain timeseries to calculate power
754
+ if tsToKeep.include? timeseries_name
755
+ tsToKeepIndexes[timeseries_name] = key_cnt
756
+ end
757
+
758
+ # special processing: power
759
+ if powerTimeseries.include? timeseries_name
760
+ # special case: net series (subtract generation from load)
761
+ if timeseries_name.include? 'Net'
762
+
763
+ newVals = Array.new(n, 0)
764
+ # Apparent power calculation
765
+
766
+ if timeseries_name.include?('Apparent')
767
+ (0..n - 1).each do |j|
768
+ newVals[j] = (values[tsToKeepIndexes['Electricity:Facility']][j].to_f - values[tsToKeepIndexes['ElectricityProduced:Facility']][j].to_f) / power_conversion / powerFactor
769
+ j += 1
770
+ end
771
+ new_unit = 'kW'
772
+ elsif timeseries_name.include? 'Net Electric Energy'
773
+ (0..n - 1).each do |j|
774
+ newVals[j] = (values[tsToKeepIndexes['Electricity:Facility']][j].to_f - values[tsToKeepIndexes['ElectricityProduced:Facility']][j].to_f)
775
+ j += 1
776
+ end
777
+ new_unit = 'kWh'
778
+ else
779
+ runner.registerInfo('Power calc')
780
+ # Power calculation
781
+ (0..n - 1).each do |j|
782
+ newVals[j] = (values[tsToKeepIndexes['Electricity:Facility']][j].to_f - values[tsToKeepIndexes['ElectricityProduced:Facility']][j].to_f) / power_conversion
783
+ j += 1
784
+ end
785
+ new_unit = 'kW'
786
+ end
787
+
788
+ values[key_cnt] = newVals
789
+ else
790
+ tsToKeepIndexes.each do |key, indexValue|
791
+ if timeseries_name.include? key
792
+ runner.registerInfo("timeseries_name: #{timeseries_name}, key: #{key}")
793
+ # use this timeseries
794
+ newVals = Array.new(n, 0)
795
+ # Apparent power calculation
796
+ if timeseries_name.include?('Apparent')
797
+ (0..n - 1).each do |j|
798
+ newVals[j] = values[indexValue][j].to_f / power_conversion / powerFactor
799
+ j += 1
800
+ end
801
+ new_unit = 'kW'
802
+ else
803
+ # Power calculation
804
+ (0..n - 1).each do |j|
805
+ newVals[j] = values[indexValue][j].to_f / power_conversion
806
+ j += 1
807
+ end
808
+ new_unit = 'kW'
809
+ end
810
+ values[key_cnt] = newVals
811
+ end
812
+ end
813
+ end
814
+ end
815
+
816
+ # append units to headers
817
+ new_timeseries_name += "(#{new_unit})"
818
+ final_timeseries_names << new_timeseries_name
819
+
820
+ # TODO: DELETE PUTS
821
+ # puts " *********timeseries_name = #{timeseries_name}******************"
822
+ # if timeseries_name.include? 'Power'
823
+ # puts "values = #{values[key_cnt]}"
824
+ # puts "units = #{new_unit}"
825
+ # end
826
+
827
+ # comfort results usually have multiple timeseries (per zone), aggregate into a single series with consistent name and use worst value at each timestep
828
+ if comfortTimeseries.include? timeseries_name
829
+
830
+ # set up array if 1st key_value
831
+ if key_i == 0
832
+ runner.registerInfo("SETTING UP NEW ARRAY FOR: #{timeseries_name}")
833
+ tmpArray = Array.new(n, 0)
834
+ end
835
+
836
+ # add to array (keep max value at each timestep)
837
+ (0..(n - 1)).each do |ind|
838
+ # process negative and positive values differently
839
+ tVal = values[key_cnt][ind].to_f
840
+ if tVal < 0
841
+ tmpArray[ind] = [tVal, tmpArray[ind]].min
842
+ else
843
+ tmpArray[ind] = [tVal, tmpArray[ind]].max
844
+ end
845
+ end
846
+
847
+ # aggregate and save when all keyvalues have been processed
848
+ if key_i == final_keys.size - 1
849
+
850
+ hrsOutOfBounds = 0
851
+ if timeseries_name === 'Zone Thermal Comfort Fanger Model PMV'
852
+ (0..(n - 1)).each do |ind|
853
+ # -0.5 < x < 0.5 is within bounds
854
+ if values[key_cnt][ind].to_f > 0.5 || values[key_cnt][ind].to_f < -0.5
855
+ hrsOutOfBounds += 1
856
+ end
857
+ end
858
+ hrsOutOfBounds = hrsOutOfBounds.to_f / timesteps_per_hour
859
+ elsif timeseries_name === 'Zone Thermal Comfort Fanger Model PPD'
860
+ (0..(n - 1)).each do |ind|
861
+ # > 20 is outside bounds
862
+ if values[key_cnt][ind].to_f > 20
863
+ hrsOutOfBounds += 1
864
+ end
865
+ end
866
+ hrsOutOfBounds = hrsOutOfBounds.to_f / timesteps_per_hour
867
+ else
868
+ # this one is already scaled by timestep, no need to divide total
869
+ (0..(n - 1)).each do |ind|
870
+ hrsOutOfBounds += values[key_cnt][ind].to_f if values[key_cnt][ind].to_f > 0
871
+ end
872
+ end
873
+
874
+ # save variable to feature_reports hash
875
+ runner.registerInfo("timeseries #{timeseries_name}: hours out of bounds: #{hrsOutOfBounds}")
876
+ if timeseries_name === 'Zone Thermal Comfort Fanger Model PMV'
877
+ feature_report.reporting_periods[0].comfort_result[:hours_out_of_comfort_bounds_PMV] = hrsOutOfBounds
878
+ elsif timeseries_name == 'Zone Thermal Comfort Fanger Model PPD'
879
+ feature_report.reporting_periods[0].comfort_result[:hours_out_of_comfort_bounds_PPD] = hrsOutOfBounds
880
+ end
881
+
882
+ end
883
+
884
+ end
885
+
886
+ # increment key_cnt in new_keys loop
887
+ key_cnt += 1
690
888
  end
691
889
  end
890
+
891
+ # Add datime column
892
+ datetimes = []
893
+ # check what timeseries is available
894
+ available_ts = sql_file.availableTimeSeries
895
+ # get the timeseries for any of available timeseries
896
+ ts_d = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, available_ts[0], '')
897
+ timeseries_d = ts_d.get
898
+ # get formated datetimes
899
+ timeseries_d.dateTimes.each do |datetime|
900
+ datetimes << format_datetime(datetime.to_s)
901
+ end
902
+ # insert datetimes to values
903
+ values.insert(0, datetimes)
904
+ # insert datetime header to names
905
+ final_timeseries_names.insert(0, 'Datetime')
906
+
692
907
  # rubocop: enable Metrics/BlockLength
693
908
  runner.registerInfo("new final_timeseries_names size: #{final_timeseries_names.size}")
694
909
 
@@ -2,12 +2,12 @@
2
2
  <schema_version>3.0</schema_version>
3
3
  <name>default_feature_reports</name>
4
4
  <uid>9ee3135a-8070-4408-bfa1-b75fecf9dd4f</uid>
5
- <version_id>803f9d76-a088-489d-88d3-6f3a5ae50d8a</version_id>
6
- <version_modified>20191030T020950Z</version_modified>
5
+ <version_id>607df4a0-d1ff-4c14-8d2f-93cde078dc47</version_id>
6
+ <version_modified>20200308T020104Z</version_modified>
7
7
  <xml_checksum>FB304155</xml_checksum>
8
8
  <class_name>DefaultFeatureReports</class_name>
9
9
  <display_name>DefaultFeatureReports</display_name>
10
- <description>Writes default_feature_reports.json file used by URBANopt Scenario Default Post Processor</description>
10
+ <description>Writes default_feature_reports.json and default_feature_reports.csv files used by URBANopt Scenario Default Post Processor</description>
11
11
  <modeler_description>This measure only allows for one feature_report per simulation. If multiple features are simulated in a single simulation, a new measure must be written to disaggregate simulation results to multiple features.</modeler_description>
12
12
  <arguments>
13
13
  <argument>
@@ -41,7 +41,7 @@
41
41
  <type>Choice</type>
42
42
  <required>true</required>
43
43
  <model_dependent>false</model_dependent>
44
- <default_value>Hourly</default_value>
44
+ <default_value>Timestep</default_value>
45
45
  <choices>
46
46
  <choice>
47
47
  <value>Detailed</value>
@@ -59,6 +59,10 @@
59
59
  <value>Daily</value>
60
60
  <display_name>Daily</display_name>
61
61
  </choice>
62
+ <choice>
63
+ <value>BillingPeriod</value>
64
+ <display_name>BillingPeriod</display_name>
65
+ </choice>
62
66
  <choice>
63
67
  <value>Monthly</value>
64
68
  <display_name>Monthly</display_name>
@@ -94,12 +98,6 @@
94
98
  <usage_type>test</usage_type>
95
99
  <checksum>BDF687C1</checksum>
96
100
  </file>
97
- <file>
98
- <filename>LICENSE.md</filename>
99
- <filetype>md</filetype>
100
- <usage_type>license</usage_type>
101
- <checksum>B646B327</checksum>
102
- </file>
103
101
  <file>
104
102
  <filename>README.md.erb</filename>
105
103
  <filetype>erb</filetype>
@@ -113,16 +111,22 @@
113
111
  <checksum>CC4BFFAF</checksum>
114
112
  </file>
115
113
  <file>
116
- <filename>README.md</filename>
114
+ <filename>LICENSE.md</filename>
117
115
  <filetype>md</filetype>
118
- <usage_type>readme</usage_type>
119
- <checksum>FDBC6AE2</checksum>
116
+ <usage_type>license</usage_type>
117
+ <checksum>EA283B74</checksum>
120
118
  </file>
121
119
  <file>
122
120
  <filename>default_feature_reports_test.rb</filename>
123
121
  <filetype>rb</filetype>
124
122
  <usage_type>test</usage_type>
125
- <checksum>8E37E2D9</checksum>
123
+ <checksum>56E0804B</checksum>
124
+ </file>
125
+ <file>
126
+ <filename>README.md</filename>
127
+ <filetype>md</filetype>
128
+ <usage_type>readme</usage_type>
129
+ <checksum>5C1DD676</checksum>
126
130
  </file>
127
131
  <file>
128
132
  <version>
@@ -133,7 +137,7 @@
133
137
  <filename>measure.rb</filename>
134
138
  <filetype>rb</filetype>
135
139
  <usage_type>script</usage_type>
136
- <checksum>8C94E56E</checksum>
140
+ <checksum>DC29E5E6</checksum>
137
141
  </file>
138
142
  </files>
139
143
  </measure>