urbanopt-reporting 0.5.0 → 0.6.0

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -1
  3. data/LICENSE.md +17 -17
  4. data/doc_templates/LICENSE.md +17 -17
  5. data/doc_templates/copyright_erb.txt +2 -2
  6. data/doc_templates/copyright_js.txt +2 -2
  7. data/doc_templates/copyright_ruby.txt +1 -1
  8. data/docs/package-lock.json +15717 -1407
  9. data/lib/measures/.rubocop.yml +4 -2
  10. data/lib/measures/default_feature_reports/measure.rb +80 -16
  11. data/lib/measures/export_modelica_loads/measure.rb +1 -1
  12. data/lib/measures/export_time_series_modelica/measure.rb +1 -1
  13. data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +1 -1
  14. data/lib/urbanopt/reporting/default_reports/construction_cost.rb +1 -1
  15. data/lib/urbanopt/reporting/default_reports/date.rb +1 -1
  16. data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +20 -2
  17. data/lib/urbanopt/reporting/default_reports/end_use.rb +1 -1
  18. data/lib/urbanopt/reporting/default_reports/end_uses.rb +1 -1
  19. data/lib/urbanopt/reporting/default_reports/extension.rb +1 -1
  20. data/lib/urbanopt/reporting/default_reports/feature_report.rb +2 -2
  21. data/lib/urbanopt/reporting/default_reports/generator.rb +1 -2
  22. data/lib/urbanopt/reporting/default_reports/location.rb +1 -1
  23. data/lib/urbanopt/reporting/default_reports/logger.rb +1 -1
  24. data/lib/urbanopt/reporting/default_reports/power_distribution.rb +21 -6
  25. data/lib/urbanopt/reporting/default_reports/program.rb +1 -1
  26. data/lib/urbanopt/reporting/default_reports/reporting_period.rb +27 -3
  27. data/lib/urbanopt/reporting/default_reports/scenario_power_distribution.rb +148 -0
  28. data/lib/urbanopt/reporting/default_reports/scenario_report.rb +7 -3
  29. data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +18 -0
  30. data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +240 -6
  31. data/lib/urbanopt/reporting/default_reports/solar_pv.rb +42 -3
  32. data/lib/urbanopt/reporting/default_reports/storage.rb +1 -1
  33. data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +1 -1
  34. data/lib/urbanopt/reporting/default_reports/timeseries_csv.rb +1 -1
  35. data/lib/urbanopt/reporting/default_reports/validator.rb +1 -1
  36. data/lib/urbanopt/reporting/default_reports/wind.rb +11 -2
  37. data/lib/urbanopt/reporting/default_reports.rb +1 -1
  38. data/lib/urbanopt/reporting/derived_extension.rb +1 -1
  39. data/lib/urbanopt/reporting/version.rb +2 -2
  40. data/lib/urbanopt/reporting.rb +1 -1
  41. metadata +3 -2
@@ -1,5 +1,7 @@
1
1
  AllCops:
2
2
  Exclude:
3
- - 'spec/test_measures/**/*'
3
+ - gems/**/*
4
+ require: rubocop-performance
5
+
4
6
  inherit_from:
5
- - http://s3.amazonaws.com/openstudio-resources/styles/rubocop_v3.yml
7
+ - http://s3.amazonaws.com/openstudio-resources/styles/rubocop_v4.yml
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -240,7 +240,11 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
240
240
 
241
241
  ev_timeseries_data = ['Exterior Equipment:Electric Vehicles']
242
242
 
243
+ emissions_timeseries_data = ['Future_Annual_Emissions_Var', 'Future_Hourly_Emissions_Var', 'Historical_Annual_Emissions_Var', 'Historical_Hourly_Emissions_Var',
244
+ 'Future_Annual_Emissions_Intensity_Var', 'Future_Hourly_Emissions_Intensity_Var', 'Historical_Annual_Emissions_Intensity_Var', 'Historical_Hourly_Emissions_Intensity_Var']
245
+
243
246
  timeseries_data += tes_timeseries_data
247
+ timeseries_data += emissions_timeseries_data
244
248
 
245
249
  timeseries_data.each do |ts|
246
250
  result << OpenStudio::IdfObject.load("Output:Variable,*,#{ts},#{reporting_frequency};").get
@@ -344,6 +348,20 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
344
348
  sql_file = sql_file.get
345
349
  model.setSqlFile(sql_file)
346
350
 
351
+ # Get the weather file run period (as opposed to design day run period)
352
+ ann_env_pd = nil
353
+ sql_file.availableEnvPeriods.each do |env_pd|
354
+ env_type = sql_file.environmentType(env_pd)
355
+ if env_type.is_initialized && (env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod'))
356
+ ann_env_pd = env_pd
357
+ end
358
+ end
359
+
360
+ if ann_env_pd == false
361
+ runner.registerError("Can't find a weather runperiod, make sure you ran an annual simulation, not just the design days.")
362
+ return false
363
+ end
364
+
347
365
  # get building from model
348
366
  building = model.getBuilding
349
367
 
@@ -801,21 +819,43 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
801
819
  time_setpoint_not_met_during_occupied_hours = time_setpoint_not_met_during_occupied_heating + time_setpoint_not_met_during_occupied_cooling
802
820
  feature_report.reporting_periods[0].comfort_result[:time_setpoint_not_met_during_occupied_hours] = time_setpoint_not_met_during_occupied_hours
803
821
 
804
- ######################################## Reporting TImeseries Results FOR CSV File ######################################
805
-
806
- # Get the weather file run period (as opposed to design day run period)
807
- ann_env_pd = nil
808
- sql_file.availableEnvPeriods.each do |env_pd|
809
- env_type = sql_file.environmentType(env_pd)
810
- if env_type.is_initialized && (env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod'))
811
- ann_env_pd = env_pd
812
- end
813
- end
814
-
815
- if ann_env_pd == false
816
- runner.registerError("Can't find a weather runperiod, make sure you ran an annual simulation, not just the design days.")
817
- return false
822
+ # #emissions
823
+ begin
824
+ # future_annual_emissions
825
+ future_annual_emissions_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Future_Annual_Emissions_Var', 'EMS')
826
+ feature_report.reporting_periods[0].emissions[:future_annual_emissions_mt] = future_annual_emissions_ts.get.values.sum
827
+
828
+ # future_hourly_emissions
829
+ future_hourly_emissions_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Future_Hourly_Emissions_Var', 'EMS')
830
+ feature_report.reporting_periods[0].emissions[:future_hourly_emissions_mt] = future_hourly_emissions_ts.get.values.sum
831
+
832
+ # historical_annual_emissions
833
+ historical_annual_emissions_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Historical_Annual_Emissions_Var', 'EMS')
834
+ feature_report.reporting_periods[0].emissions[:historical_annual_emissions_mt] = historical_annual_emissions_ts.get.values.sum
835
+
836
+ # historical_annual_emissions
837
+ historical_hourly_emissions_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Historical_Hourly_Emissions_Var', 'EMS')
838
+ feature_report.reporting_periods[0].emissions[:historical_hourly_emissions_mt] = historical_hourly_emissions_ts.get.values.sum
839
+
840
+ # future_annual_emissions
841
+ future_annual_emissions_intensity_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Future_Annual_Emissions_Intensity_Var', 'EMS')
842
+ feature_report.reporting_periods[0].emissions[:future_annual_emissions_intensity_kg_per_ft2] = future_annual_emissions_intensity_ts.get.values.sum
843
+
844
+ # future_hourly_emissions
845
+ future_hourly_emissions_intensity_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Future_Hourly_Emissions_Intensity_Var', 'EMS')
846
+ feature_report.reporting_periods[0].emissions[:future_hourly_emissions_intensity_kg_per_ft2] = future_hourly_emissions_intensity_ts.get.values.sum
847
+
848
+ # historical_annual_emissions
849
+ historical_annual_emissions_intensity_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Historical_Annual_Emissions_Intensity_Var', 'EMS')
850
+ feature_report.reporting_periods[0].emissions[:historical_annual_emissions_intensity_kg_per_ft2] = historical_annual_emissions_intensity_ts.get.values.sum
851
+
852
+ # historical_annual_emissions
853
+ historical_hourly_emissions_intensity_ts = sql_file.timeSeries(ann_env_pd.to_s, reporting_frequency.to_s, 'Historical_Hourly_Emissions_Intensity_Var', 'EMS')
854
+ feature_report.reporting_periods[0].emissions[:historical_hourly_emissions_intensity_kg_per_ft2] = historical_hourly_emissions_intensity_ts.get.values.sum
855
+ rescue StandardError
856
+ @@logger.info('Emissions are not reported for this feature')
818
857
  end
858
+ ######################################## Reporting TImeseries Results FOR CSV File #######################################
819
859
 
820
860
  # timeseries we want to report
821
861
  requested_timeseries_names = [
@@ -862,7 +902,25 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
862
902
  'District Heating Inlet Temperature',
863
903
  'District Heating Outlet Temperature',
864
904
  'Cooling Coil Total Cooling Rate',
865
- 'Heating Coil Heating Rate'
905
+ 'Heating Coil Heating Rate',
906
+ 'Future_Annual_Emissions_Var',
907
+ 'Future_Hourly_Emissions_Var',
908
+ 'Historical_Annual_Emissions_Var',
909
+ 'Historical_Hourly_Emissions_Var',
910
+ 'Future_Annual_Emissions_Intensity_Var',
911
+ 'Future_Hourly_Emissions_Intensity_Var',
912
+ 'Historical_Annual_Emissions_Intensity_Var',
913
+ 'Historical_Hourly_Emissions_Intensity_Var',
914
+ 'Curtailed EV Power',
915
+ 'Daily EV Charge Energy Capacity',
916
+ 'EV Charge Ratio',
917
+ 'Total Charged EV Energy',
918
+ 'Total Curtailed EV Energy',
919
+ 'Total Scheduled EV Energy',
920
+ 'Emission Intensity Schedule Output',
921
+ 'EV Charging Effective Schedule',
922
+ 'EV Charging Original Schedule',
923
+ 'EV Charging Original Load'
866
924
  ]
867
925
 
868
926
  # add thermal comfort timeseries
@@ -1002,6 +1060,12 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
1002
1060
  'm3'
1003
1061
  when 'W'
1004
1062
  'W'
1063
+ when 'kg'
1064
+ 'kg'
1065
+ when 'MT'
1066
+ 'MT'
1067
+ when 'KG/FT2'
1068
+ 'KG/FT2'
1005
1069
  end
1006
1070
  end
1007
1071
 
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -192,6 +192,15 @@ module URBANopt
192
192
  #
193
193
  attr_accessor :probs_of_surviving_by_hour_of_the_day
194
194
 
195
+ ##
196
+ # _String_ - Filepath of reopt assumptions file used, if known
197
+ attr_accessor :reopt_assumptions_file_path
198
+
199
+ ##
200
+ # _Float_ - Annual percentage of electricity supplied by renewable sources
201
+ #
202
+ attr_accessor :annual_renewable_electricity_pct
203
+
195
204
  ##
196
205
  # Initialize distributed generation system design and financial metrics.
197
206
  #
@@ -206,6 +215,7 @@ module URBANopt
206
215
  def initialize(hash = {})
207
216
  hash.delete_if { |k, v| v.nil? }
208
217
 
218
+ @annual_renewable_electricity_pct = hash[:annual_renewable_electricity_pct]
209
219
  @lcc_us_dollars = hash[:lcc_us_dollars]
210
220
  @lcc_bau_us_dollars = hash[:lcc_bau_us_dollars]
211
221
  @npv_us_dollars = hash[:npv_us_dollars]
@@ -227,6 +237,12 @@ module URBANopt
227
237
  @probs_of_surviving_by_month = hash[:probs_of_surviving_by_month]
228
238
  @probs_of_surviving_by_hour_of_the_day = hash[:probs_of_surviving_by_hour_of_the_day]
229
239
 
240
+ # optional
241
+ @reopt_assumptions_file_path = nil
242
+ if hash[:reopt_assumptions_file_path]
243
+ @reopt_assumptions_file_path = hash[:reopt_assumptions_file_path]
244
+ end
245
+
230
246
  @total_solar_pv_kw = nil
231
247
  @total_wind_kw = nil
232
248
  @total_generator_kw = nil
@@ -363,7 +379,8 @@ module URBANopt
363
379
  ##
364
380
  def to_hash
365
381
  result = {}
366
-
382
+ result[:reopt_assumptions_file_path] = @reopt_assumptions_file_path if @reopt_assumptions_file_path
383
+ result[:annual_renewable_electricity_pct] = @annual_renewable_electricity_pct if @annual_renewable_electricity_pct
367
384
  result[:lcc_us_dollars] = @lcc_us_dollars if @lcc_us_dollars
368
385
  result[:lcc_bau_us_dollars] = @lcc_bau_us_dollars if @lcc_bau_us_dollars
369
386
  result[:npv_us_dollars] = @npv_us_dollars if @npv_us_dollars
@@ -433,6 +450,7 @@ module URBANopt
433
450
  # Merge a distributed generation system with a new system
434
451
  ##
435
452
  def self.merge_distributed_generation(existing_dgen, new_dgen)
453
+ existing_dgen.annual_renewable_electricity_pct = add_values(existing_dgen.annual_renewable_electricity_pct, new_dgen.annual_renewable_electricity_pct)
436
454
  existing_dgen.lcc_us_dollars = add_values(existing_dgen.lcc_us_dollars, new_dgen.lcc_us_dollars)
437
455
  existing_dgen.lcc_bau_us_dollars = add_values(existing_dgen.lcc_bau_us_dollars, new_dgen.lcc_bau_us_dollars)
438
456
  existing_dgen.npv_us_dollars = add_values(existing_dgen.npv_us_dollars, new_dgen.npv_us_dollars)
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -259,7 +259,7 @@ module URBANopt
259
259
  FileUtils.mkdir_p File.dirname(@timeseries_csv.path)
260
260
  @timeseries_csv.save_data
261
261
 
262
- ## save json rport
262
+ ## save json report
263
263
  # feature_hash
264
264
  feature_hash = to_hash
265
265
 
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -80,7 +80,6 @@ module URBANopt
80
80
  result = {}
81
81
 
82
82
  result[:size_kw] = @size_kw if @size_kw
83
-
84
83
  return result
85
84
  end
86
85
 
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -50,11 +50,12 @@ module URBANopt
50
50
  # power_distributio include eletrical power distribution systems information.
51
51
  ##
52
52
  class PowerDistribution
53
- attr_accessor :under_voltage_hours, :over_voltage_hours # :nodoc:
53
+ attr_accessor :under_voltage_hours, :over_voltage_hours, :nominal_capacity,
54
+ :reactance_resistance_ratio, :nominal_voltage, :max_power_kw, :max_reactive_power_kvar # :nodoc:
54
55
 
55
56
  ##
56
- # PowerDistrinution class intialize all power_distribution attributes:
57
- # +:under_voltage_hours+ , +:over_voltage_hours+
57
+ # PowerDistribution class initialize all power_distribution attributes:
58
+ # +:under_voltage_hours+ , +:over_voltage_hours+, +:nominal_capacity+, +:reactance_resistance_ratio+
58
59
  ##
59
60
  # [parameters:]
60
61
  # +hash+ - _Hash_ - A hash which may contain a deserialized power_distribution.
@@ -65,7 +66,11 @@ module URBANopt
65
66
 
66
67
  @under_voltage_hours = hash[:under_voltage_hours]
67
68
  @over_voltage_hours = hash[:over_voltage_hours]
68
-
69
+ @nominal_capacity = hash[:nominal_capacity]
70
+ @reactance_resistance_ratio = hash[:reactance_resistance_ratio]
71
+ @nominal_voltage = hash[:nominal_voltage] # in V
72
+ @max_power_kw = hash[:max_power_kw]
73
+ @max_reactive_power_kvar = hash[:max_reactive_power_kvar]
69
74
  # initialize class variables @@validator and @@schema
70
75
  @@validator ||= Validator.new
71
76
  @@schema ||= @@validator.schema
@@ -78,6 +83,11 @@ module URBANopt
78
83
  hash = {}
79
84
  hash[:under_voltage_hours] = nil
80
85
  hash[:over_voltage_hours] = nil
86
+ hash[:nominal_capacity] = nil
87
+ hash[:reactance_resistance_ratio] = nil
88
+ hash[:nominal_voltage] = nil
89
+ hash[:max_power_kw] = nil
90
+ hash[:max_reactive_power_kvar] = nil
81
91
 
82
92
  return hash
83
93
  end
@@ -92,6 +102,11 @@ module URBANopt
92
102
  result = {}
93
103
  result[:under_voltage_hours] = @under_voltage_hours if @under_voltage_hours
94
104
  result[:over_voltage_hours] = @over_voltage_hours if @over_voltage_hours
105
+ result[:nominal_capacity] = @nominal_capacity if @nominal_capacity
106
+ result[:reactance_resistance_ratio] = @reactance_resistance_ratio if @reactance_resistance_ratio
107
+ result[:nominal_voltage] = @nominal_voltage if @nominal_voltage
108
+ result[:max_power_kw] = @max_power_kw if @max_power_kw
109
+ result[:max_reactive_power_kvar] = @max_reactive_power_kvar if @max_reactive_power_kvar
95
110
 
96
111
  # validate power_distribution properties against schema
97
112
  if @@validator.validate(@@schema[:definitions][:PowerDistribution][:properties], result).any?
@@ -105,7 +120,7 @@ module URBANopt
105
120
  # Merges muliple power distribution results together.
106
121
  ##
107
122
  # +new_costs+ - _Array_ - An array of ConstructionCost objects.
108
- def merge_power_distribition
123
+ def merge_power_distribution
109
124
  # method to be developed for any attributes to be aggregated or merged
110
125
  end
111
126
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, 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,
@@ -57,14 +57,18 @@ module URBANopt
57
57
  :net_site_energy_kwh, :net_source_energy_kwh, :total_utility_cost_dollar, :net_utility_cost_dollar, :utility_costs_dollar, :electricity_kwh, :natural_gas_kwh, :propane_kwh, :fuel_oil_kwh, :other_fuels_kwh, :district_cooling_kwh,
58
58
  :district_heating_kwh, :water_qbft, :electricity_produced_kwh, :end_uses, :energy_production_kwh, :photovoltaic,
59
59
  :fuel_type, :total_cost_dollar, :usage_cost_dollar, :demand_cost_dollar, :comfort_result, :time_setpoint_not_met_during_occupied_cooling,
60
- :time_setpoint_not_met_during_occupied_heating, :time_setpoint_not_met_during_occupied_hours, :hours_out_of_comfort_bounds_PMV, :hours_out_of_comfort_bounds_PPD #:nodoc:
60
+ :time_setpoint_not_met_during_occupied_heating, :time_setpoint_not_met_during_occupied_hours, :hours_out_of_comfort_bounds_PMV, :hours_out_of_comfort_bounds_PPD,
61
+ :emissions, :future_annual_emissions_mt, :future_hourly_emissions_mt, :historical_annual_emissions_mt, :historical_hourly_emissions_mt,
62
+ :future_annual_emissions_intensity_kg_per_ft2, :future_hourly_emissions_intensity_kg_per_ft2, :historical_annual_emissions_intensity_kg_per_ft2, :historical_hourly_emissions_intensity_kg_per_ft2 #:nodoc:
61
63
 
62
64
  # ReportingPeriod class initializes the reporting period attributes:
63
65
  # +:id+ , +:name+ , +:multiplier+ , +:start_date+ , +:end_date+ , +:month+ , +:day_of_month+ , +:year+ , +:total_site_energy_kwh+ , +:total_source_energy_kwh+ , +:site_EUI_kwh_per_m2+, +:site_EUI_kbtu_per_ft2+, +:source_EUI_kwh_per_m2+, +:source_EUI_kbtu_per_ft2+,
64
66
  # +:net_site_energy_kwh+ , +:net_source_energy_kwh+ , +:total_utility_cost_dollar , +:net_utility_cost_dollar+ , +:utility_costs_dollar+ , +:electricity_kwh+ , +:natural_gas_kwh+ , +:propane_kwh+ , +:fuel_oil_kwh+ , +:other_fuels_kwh+ , +:district_cooling_kwh+ ,
65
67
  # +:district_heating_kwh+ , +:water_qbft+ , +:electricity_produced_kwh+ , +:end_uses+ , +:energy_production_kwh+ , +:photovoltaic_kwh+ ,
66
68
  # +:fuel_type+ , +:total_cost_dollar+ , +:usage_cost_dollar+ , +:demand_cost_dollar+ , +:comfort_result+ , +:time_setpoint_not_met_during_occupied_cooling+ ,
67
- # +:time_setpoint_not_met_during_occupied_heating+ , +:time_setpoint_not_met_during_occupied_hours+
69
+ # +:time_setpoint_not_met_during_occupied_heating+ , +:time_setpoint_not_met_during_occupied_hours+ , +:hours_out_of_comfort_bounds_PMV , +:hours_out_of_comfort_bounds_PPD ,
70
+ # +:emissions, +:future_annual_emissions_mt, +:future_hourly_emissions_mt, +:historical_annual_emissions_mt, +:historical_hourly_emissions_mt,
71
+ # +:future_annual_emissions_intensity_kg_per_ft2, +:future_hourly_emissions_intensity_kg_per_ft2, +:historical_annual_emissions_intensity_kg_per_ft2, +:historical_hourly_emissions_intensity_kg_per_ft2
68
72
  ##
69
73
  # [parameters:]
70
74
  # +hash+ - _Hash_ - A hash which may contain a deserialized reporting_period.
@@ -106,6 +110,8 @@ module URBANopt
106
110
 
107
111
  @comfort_result = hash[:comfort_result]
108
112
 
113
+ @emissions = hash[:emissions]
114
+
109
115
  # initialize class variables @@validator and @@schema
110
116
  @@validator ||= Validator.new
111
117
  @@schema ||= @@validator.schema
@@ -147,6 +153,8 @@ module URBANopt
147
153
  hash[:utility_costs_dollar] = [{ fuel_type: nil, total_cost_dollar: nil, usage_cost_dollar: nil, demand_cost_dollar: nil }]
148
154
  hash[:comfort_result] = { time_setpoint_not_met_during_occupied_cooling: nil, time_setpoint_not_met_during_occupied_heating: nil,
149
155
  time_setpoint_not_met_during_occupied_hours: nil, hours_out_of_comfort_bounds_PMV: nil, hours_out_of_comfort_bounds_PPD: nil }
156
+ hash[:emissions] = { future_annual_emissions_mt: nil, future_hourly_emissions_mt: nil, historical_annual_emissions_mt: nil, historical_hourly_emissions_mt: nil,
157
+ future_annual_emissions_intensity_kg_per_ft2: nil, future_hourly_emissions_kg_per_ft2: nil, historical_annual_emissions_kg_per_ft2: nil, historical_hourly_emissions_kg_per_ft2: nil }
150
158
 
151
159
  return hash
152
160
  end
@@ -205,6 +213,10 @@ module URBANopt
205
213
  comfort_result_hash.delete_if { |k, v| v.nil? }
206
214
  result[:comfort_result] = comfort_result_hash if @comfort_result
207
215
 
216
+ emissions_hash = @emissions if @emissions
217
+ emissions_hash.delete_if { |k, v| v.nil? }
218
+ result[:emissions] = emissions_hash if @emissions
219
+
208
220
  # validates +reporting_period+ properties against schema for reporting period.
209
221
  if @@validator.validate(@@schema[:definitions][:ReportingPeriod][:properties], result).any?
210
222
  raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:ReportingPeriod][:properties], result)}"
@@ -278,6 +290,18 @@ module URBANopt
278
290
  existing_period.comfort_result[:hours_out_of_comfort_bounds_PPD] = add_values(existing_period.comfort_result[:hours_out_of_comfort_bounds_PPD], new_period.comfort_result[:hours_out_of_comfort_bounds_PPD])
279
291
  end
280
292
 
293
+ if existing_period.emissions
294
+ existing_period.emissions[:future_annual_emissions_mt] = add_values(existing_period.emissions[:future_annual_emissions_mt], new_period.emissions[:future_annual_emissions_mt])
295
+ existing_period.emissions[:future_hourly_emissions_mt] = add_values(existing_period.emissions[:future_hourly_emissions_mt], new_period.emissions[:future_hourly_emissions_mt])
296
+ existing_period.emissions[:historical_annual_emissions_mt] = add_values(existing_period.emissions[:historical_annual_emissions_mt], new_period.emissions[:historical_annual_emissions_mt])
297
+ existing_period.emissions[:historical_hourly_emissions_mt] = add_values(existing_period.emissions[:historical_hourly_emissions_mt], new_period.emissions[:historical_hourly_emissions_mt])
298
+
299
+ existing_period.emissions[:future_annual_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:future_annual_emissions_intensity_kg_per_ft2], new_period.emissions[:future_annual_emissions_intensity_kg_per_ft2])
300
+ existing_period.emissions[:future_hourly_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:future_hourly_emissions_intensity_kg_per_ft2], new_period.emissions[:future_hourly_emissions_intensity_kg_per_ft2])
301
+ existing_period.emissions[:historical_annual_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:historical_annual_emissions_intensity_kg_per_ft2], new_period.emissions[:historical_annual_emissions_intensity_kg_per_ft2])
302
+ existing_period.emissions[:historical_hourly_emissions_intensity_kg_per_ft2] = add_values(existing_period.emissions[:historical_hourly_emissions_intensity_kg_per_ft2], new_period.emissions[:historical_hourly_emissions_intensity_kg_per_ft2])
303
+ end
304
+
281
305
  return existing_period
282
306
  end
283
307
 
@@ -0,0 +1,148 @@
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_relative 'validator'
42
+
43
+ require 'json'
44
+ require 'json-schema'
45
+
46
+ module URBANopt
47
+ module Reporting
48
+ module DefaultReports
49
+ ##
50
+ # scenario_power_distribution include eletrical power distribution systems information.
51
+ ##
52
+ class ScenarioPowerDistribution
53
+ attr_accessor :substations, :distribution_lines, :capacitors
54
+
55
+ ##
56
+ # ScenarioPowerDistribution class initialize all scenario_power_distribution attributes:
57
+ # +:substations+ , +:distribution_lines+
58
+ ##
59
+ # [parameters:]
60
+ # +hash+ - _Hash_ - A hash which may contain a deserialized power_distribution.
61
+ ##
62
+ def initialize(hash = {})
63
+ hash.delete_if { |k, v| v.nil? }
64
+ hash = defaults.merge(hash)
65
+
66
+ @substations = hash[:substations]
67
+ @distribution_lines = hash[:distribution_lines]
68
+ @capacitors = hash[:capacitors]
69
+
70
+ # initialize class variables @@validator and @@schema
71
+ @@validator ||= Validator.new
72
+ @@schema ||= @@validator.schema
73
+ end
74
+
75
+ ##
76
+ # Assigns default values if attribute values do not exist.
77
+ ##
78
+ def defaults
79
+ hash = {}
80
+ hash[:substations] = []
81
+ hash[:distribution_lines] = []
82
+ hash[:capacitors] = []
83
+
84
+ return hash
85
+ end
86
+
87
+ ##
88
+ # Converts to a Hash equivalent for JSON serialization.
89
+ ##
90
+ # - Exclude attributes with nil values.
91
+ # - Validate power_distribution hash properties against schema.
92
+ ##
93
+ def to_hash
94
+ result = {}
95
+ result[:substations] = @substations if @substations
96
+ result[:distribution_lines] = @distribution_lines if @distribution_lines
97
+ result[:capacitors] = @capacitors if @capacitors
98
+
99
+ # validate power_distribution properties against schema
100
+ if @@validator.validate(@@schema[:definitions][:ScenarioPowerDistribution][:properties], result).any?
101
+ raise "scenario_power_distribution properties does not match schema: #{@@validator.validate(@@schema[:definitions][:ScenarioPowerDistribution][:properties], result)}"
102
+ end
103
+
104
+ return result
105
+ end
106
+
107
+ ##
108
+ # Add a substation
109
+ ##
110
+ def add_substation(hash = {})
111
+ hash.delete_if { |k, v| v.nil? }
112
+ hash = defaults.merge(hash)
113
+ # field: nominal_voltage
114
+ substation = {}
115
+ substation['nominal_voltage'] = hash[:nominal_voltage]
116
+ @substations << substation
117
+ end
118
+
119
+ ##
120
+ # Add a line
121
+ ##
122
+ def add_line(hash = {})
123
+ hash.delete_if { |k, v| v.nil? }
124
+ hash = defaults.merge(hash)
125
+ # fields: length, ampacity, commercial_line_type
126
+ line = {}
127
+ line['length'] = hash[:length]
128
+ line['ampacity'] = hash[:ampacity]
129
+ line['commercial_line_type'] = hash[:commercial_line_type]
130
+
131
+ @distribution_lines << line
132
+ end
133
+
134
+ ##
135
+ # Add a capacitor
136
+ ##
137
+ def add_capacitor(hash = {})
138
+ hash.delete_if { |k, v| v.nil? }
139
+ hash = defaults.merge(hash)
140
+ # fields: nominal_capacity
141
+ cap = {}
142
+ cap['nominal_capacity'] = hash[:nominal_capacity]
143
+ cap
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end