urbanopt-reporting 0.4.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/LICENSE.md +17 -17
- data/doc_templates/LICENSE.md +17 -17
- data/doc_templates/copyright_erb.txt +2 -2
- data/doc_templates/copyright_js.txt +2 -2
- data/doc_templates/copyright_ruby.txt +1 -1
- data/docs/package-lock.json +15717 -1407
- data/lib/measures/.rubocop.yml +4 -2
- data/lib/measures/default_feature_reports/measure.rb +101 -36
- data/lib/measures/export_modelica_loads/measure.rb +2 -1
- data/lib/measures/export_time_series_modelica/measure.rb +58 -59
- data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +3 -5
- data/lib/urbanopt/reporting/default_reports/construction_cost.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/date.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +25 -7
- data/lib/urbanopt/reporting/default_reports/end_use.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/end_uses.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/extension.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +9 -8
- data/lib/urbanopt/reporting/default_reports/generator.rb +1 -2
- data/lib/urbanopt/reporting/default_reports/location.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/logger.rb +2 -2
- data/lib/urbanopt/reporting/default_reports/power_distribution.rb +22 -6
- data/lib/urbanopt/reporting/default_reports/program.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/reporting_period.rb +30 -7
- data/lib/urbanopt/reporting/default_reports/scenario_power_distribution.rb +148 -0
- data/lib/urbanopt/reporting/default_reports/scenario_report.rb +20 -14
- data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +18 -0
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +240 -6
- data/lib/urbanopt/reporting/default_reports/solar_pv.rb +42 -3
- data/lib/urbanopt/reporting/default_reports/storage.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/timeseries_csv.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/validator.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/wind.rb +11 -2
- data/lib/urbanopt/reporting/default_reports.rb +1 -1
- data/lib/urbanopt/reporting/derived_extension.rb +1 -1
- data/lib/urbanopt/reporting/version.rb +2 -2
- data/lib/urbanopt/reporting.rb +1 -1
- data/urbanopt-reporting-gem.gemspec +3 -4
- metadata +16 -15
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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
|
@@ -234,7 +250,7 @@ module URBANopt
|
|
234
250
|
@total_storage_kwh = nil
|
235
251
|
|
236
252
|
@solar_pv = []
|
237
|
-
if hash[:solar_pv].
|
253
|
+
if hash[:solar_pv].instance_of?(Hash)
|
238
254
|
hash[:solar_pv] = [hash[:solar_pv]]
|
239
255
|
elsif hash[:solar_pv].nil?
|
240
256
|
hash[:solar_pv] = []
|
@@ -252,7 +268,7 @@ module URBANopt
|
|
252
268
|
end
|
253
269
|
|
254
270
|
@wind = []
|
255
|
-
if hash[:wind].
|
271
|
+
if hash[:wind].instance_of?(Hash)
|
256
272
|
hash[:wind] = [hash[:wind]]
|
257
273
|
elsif hash[:wind].nil?
|
258
274
|
hash[:wind] = []
|
@@ -270,7 +286,7 @@ module URBANopt
|
|
270
286
|
end
|
271
287
|
|
272
288
|
@generator = []
|
273
|
-
if hash[:generator].
|
289
|
+
if hash[:generator].instance_of?(Hash)
|
274
290
|
hash[:generator] = [hash[:generator]]
|
275
291
|
elsif hash[:generator].nil?
|
276
292
|
hash[:generator] = []
|
@@ -288,7 +304,7 @@ module URBANopt
|
|
288
304
|
end
|
289
305
|
|
290
306
|
@storage = []
|
291
|
-
if hash[:storage].
|
307
|
+
if hash[:storage].instance_of?(Hash)
|
292
308
|
hash[:storage] = [hash[:storage]]
|
293
309
|
elsif hash[:storage].nil?
|
294
310
|
hash[:storage] = []
|
@@ -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)
|
@@ -476,7 +494,7 @@ module URBANopt
|
|
476
494
|
|
477
495
|
new_dgen.storage.each do |storage|
|
478
496
|
existing_dgen.storage.push storage
|
479
|
-
if existing_dgen.
|
497
|
+
if existing_dgen.total_storage_kw.nil?
|
480
498
|
existing_dgen.total_storage_kw = storage.size_kw
|
481
499
|
existing_dgen.total_storage_kwh = storage.size_kwh
|
482
500
|
else
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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-
|
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,6 +50,7 @@ module URBANopt
|
|
50
50
|
##
|
51
51
|
class EndUses
|
52
52
|
attr_accessor :electricity_kwh, :natural_gas_kwh, :propane_kwh, :fuel_oil_kwh, :other_fuels_kwh, :district_cooling_kwh, :district_heating_kwh, :water_qbft # :nodoc:
|
53
|
+
|
53
54
|
##
|
54
55
|
# EndUses class intialize end_uses(fuel type) attributes: +:electricity_kwh+ , +:natural_gas_kwh+ , +:propane_kwh+ , +:fuel_oil_kwh+ , +:other_fuels_kwh+ ,
|
55
56
|
# +:district_cooling_kwh+ , +:district_heating_kwh+ , +:water_qbft+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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-
|
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,
|
@@ -65,6 +65,7 @@ module URBANopt
|
|
65
65
|
class FeatureReport
|
66
66
|
attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
|
67
67
|
:timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution, :thermal_storage # :nodoc:
|
68
|
+
|
68
69
|
##
|
69
70
|
# Each FeatureReport object corresponds to a single Feature.
|
70
71
|
##
|
@@ -254,15 +255,15 @@ module URBANopt
|
|
254
255
|
# create feature reports directory
|
255
256
|
Dir.mkdir(results_dir_path) unless Dir.exist?(File.join(@directory_name, 'feature_reports'))
|
256
257
|
|
257
|
-
@timeseries_csv.path = File.join(@directory_name, 'feature_reports', file_name
|
258
|
+
@timeseries_csv.path = File.join(@directory_name, 'feature_reports', "#{file_name}.csv")
|
258
259
|
FileUtils.mkdir_p File.dirname(@timeseries_csv.path)
|
259
260
|
@timeseries_csv.save_data
|
260
261
|
|
261
|
-
## save json
|
262
|
+
## save json report
|
262
263
|
# feature_hash
|
263
264
|
feature_hash = to_hash
|
264
265
|
|
265
|
-
json_name_path = File.join(results_dir_path, file_name
|
266
|
+
json_name_path = File.join(results_dir_path, "#{file_name}.json")
|
266
267
|
|
267
268
|
File.open(json_name_path, 'w') do |f|
|
268
269
|
f.puts JSON.pretty_generate(feature_hash)
|
@@ -277,7 +278,7 @@ module URBANopt
|
|
277
278
|
if !old_timeseries_path.nil?
|
278
279
|
@timeseries_csv.path = old_timeseries_path
|
279
280
|
else
|
280
|
-
@timeseries_csv.path = File.join(@directory_name, file_name
|
281
|
+
@timeseries_csv.path = File.join(@directory_name, "#{file_name}.csv")
|
281
282
|
end
|
282
283
|
|
283
284
|
return true
|
@@ -312,7 +313,7 @@ module URBANopt
|
|
312
313
|
# feature_hash
|
313
314
|
feature_hash = to_hash
|
314
315
|
|
315
|
-
json_name_path = File.join(results_dir_path, file_name
|
316
|
+
json_name_path = File.join(results_dir_path, "#{file_name}.json")
|
316
317
|
|
317
318
|
File.open(json_name_path, 'w') do |f|
|
318
319
|
f.puts JSON.pretty_generate(feature_hash)
|
@@ -327,7 +328,7 @@ module URBANopt
|
|
327
328
|
|
328
329
|
##
|
329
330
|
# Saves the 'default_feature_report.csv' file to the results directory
|
330
|
-
# This method only copies the CSV feature reports from the folder generated by the reporting measure
|
331
|
+
# This method only copies the CSV feature reports from the folder generated by the reporting measure
|
331
332
|
# (<meausure number>_default_feature_reports/) to the new feature_reports/ folder
|
332
333
|
##
|
333
334
|
# [parameters]:
|
@@ -347,7 +348,7 @@ module URBANopt
|
|
347
348
|
# copy the CSV report to the new feature_reports folder
|
348
349
|
directory_folders.each do |f|
|
349
350
|
if f.include? '_default_feature_reports'
|
350
|
-
FileUtils.cp(File.join(f, 'default_feature_reports.csv'), File.join(results_dir_path, @file_name
|
351
|
+
FileUtils.cp(File.join(f, 'default_feature_reports.csv'), File.join(results_dir_path, "#{@file_name}.csv"))
|
351
352
|
end
|
352
353
|
end
|
353
354
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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-
|
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,6 +50,7 @@ module URBANopt
|
|
50
50
|
##
|
51
51
|
class Location
|
52
52
|
attr_accessor :latitude_deg, :longitude_deg, :surface_elevation_ft, :weather_filename #:nodoc:
|
53
|
+
|
53
54
|
##
|
54
55
|
# Location class initialize location attributes: +:latitude_deg+ , +:longitude_deg+ , +:surface_elevation_ft+ , +:weather_filename+
|
55
56
|
##
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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,
|
@@ -43,7 +43,7 @@ require 'logger'
|
|
43
43
|
module URBANopt
|
44
44
|
module Reporting
|
45
45
|
module DefaultReports
|
46
|
-
@@logger = Logger.new(
|
46
|
+
@@logger = Logger.new($stdout)
|
47
47
|
##
|
48
48
|
# Definining class variable "@@logger" to log errors, info and warning messages.
|
49
49
|
def self.logger
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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,10 +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
|
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:
|
55
|
+
|
54
56
|
##
|
55
|
-
#
|
56
|
-
# +: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+
|
57
59
|
##
|
58
60
|
# [parameters:]
|
59
61
|
# +hash+ - _Hash_ - A hash which may contain a deserialized power_distribution.
|
@@ -64,7 +66,11 @@ module URBANopt
|
|
64
66
|
|
65
67
|
@under_voltage_hours = hash[:under_voltage_hours]
|
66
68
|
@over_voltage_hours = hash[:over_voltage_hours]
|
67
|
-
|
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]
|
68
74
|
# initialize class variables @@validator and @@schema
|
69
75
|
@@validator ||= Validator.new
|
70
76
|
@@schema ||= @@validator.schema
|
@@ -77,6 +83,11 @@ module URBANopt
|
|
77
83
|
hash = {}
|
78
84
|
hash[:under_voltage_hours] = nil
|
79
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
|
80
91
|
|
81
92
|
return hash
|
82
93
|
end
|
@@ -91,6 +102,11 @@ module URBANopt
|
|
91
102
|
result = {}
|
92
103
|
result[:under_voltage_hours] = @under_voltage_hours if @under_voltage_hours
|
93
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
|
94
110
|
|
95
111
|
# validate power_distribution properties against schema
|
96
112
|
if @@validator.validate(@@schema[:definitions][:PowerDistribution][:properties], result).any?
|
@@ -104,7 +120,7 @@ module URBANopt
|
|
104
120
|
# Merges muliple power distribution results together.
|
105
121
|
##
|
106
122
|
# +new_costs+ - _Array_ - An array of ConstructionCost objects.
|
107
|
-
def
|
123
|
+
def merge_power_distribution
|
108
124
|
# method to be developed for any attributes to be aggregated or merged
|
109
125
|
end
|
110
126
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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,
|
@@ -56,6 +56,7 @@ module URBANopt
|
|
56
56
|
:maximum_number_of_parking_stories_above_ground, :number_of_residential_units, :building_types, :building_type, :maximum_occupancy,
|
57
57
|
:area_sqft, :window_area_sqft, :north_window_area_sqft, :south_window_area_sqft, :east_window_area_sqft, :west_window_area_sqft, :wall_area_sqft, :roof_area_sqft, :equipment_roof_area_sqft,
|
58
58
|
:photovoltaic_roof_area_sqft, :available_roof_area_sqft, :total_roof_area_sqft, :orientation_deg, :aspect_ratio, :total_construction_cost_dollar # :nodoc:
|
59
|
+
|
59
60
|
# Program class initialize building program attributes: +:site_area_sqft+ , +:floor_area_sqft+ , +:conditioned_area_sqft+ , +:unconditioned_area_sqft+ ,
|
60
61
|
# +:footprint_area_sqft+ , +:maximum_roof_height_ft, +:maximum_number_of_stories+ , +:maximum_number_of_stories_above_ground+ , +:parking_area_sqft+ ,
|
61
62
|
# +:number_of_parking_spaces+ , +:number_of_parking_spaces_charging+ , +:parking_footprint_area_sqft+ , +:maximum_parking_height_ft+ , +:maximum_number_of_parking_stories+ ,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
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,13 +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
|
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:
|
63
|
+
|
61
64
|
# ReportingPeriod class initializes the reporting period attributes:
|
62
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+,
|
63
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+ ,
|
64
67
|
# +:district_heating_kwh+ , +:water_qbft+ , +:electricity_produced_kwh+ , +:end_uses+ , +:energy_production_kwh+ , +:photovoltaic_kwh+ ,
|
65
68
|
# +:fuel_type+ , +:total_cost_dollar+ , +:usage_cost_dollar+ , +:demand_cost_dollar+ , +:comfort_result+ , +:time_setpoint_not_met_during_occupied_cooling+ ,
|
66
|
-
# +: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
|
67
72
|
##
|
68
73
|
# [parameters:]
|
69
74
|
# +hash+ - _Hash_ - A hash which may contain a deserialized reporting_period.
|
@@ -105,6 +110,8 @@ module URBANopt
|
|
105
110
|
|
106
111
|
@comfort_result = hash[:comfort_result]
|
107
112
|
|
113
|
+
@emissions = hash[:emissions]
|
114
|
+
|
108
115
|
# initialize class variables @@validator and @@schema
|
109
116
|
@@validator ||= Validator.new
|
110
117
|
@@schema ||= @@validator.schema
|
@@ -146,6 +153,8 @@ module URBANopt
|
|
146
153
|
hash[:utility_costs_dollar] = [{ fuel_type: nil, total_cost_dollar: nil, usage_cost_dollar: nil, demand_cost_dollar: nil }]
|
147
154
|
hash[:comfort_result] = { time_setpoint_not_met_during_occupied_cooling: nil, time_setpoint_not_met_during_occupied_heating: nil,
|
148
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 }
|
149
158
|
|
150
159
|
return hash
|
151
160
|
end
|
@@ -204,6 +213,10 @@ module URBANopt
|
|
204
213
|
comfort_result_hash.delete_if { |k, v| v.nil? }
|
205
214
|
result[:comfort_result] = comfort_result_hash if @comfort_result
|
206
215
|
|
216
|
+
emissions_hash = @emissions if @emissions
|
217
|
+
emissions_hash.delete_if { |k, v| v.nil? }
|
218
|
+
result[:emissions] = emissions_hash if @emissions
|
219
|
+
|
207
220
|
# validates +reporting_period+ properties against schema for reporting period.
|
208
221
|
if @@validator.validate(@@schema[:definitions][:ReportingPeriod][:properties], result).any?
|
209
222
|
raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:ReportingPeriod][:properties], result)}"
|
@@ -258,10 +271,8 @@ module URBANopt
|
|
258
271
|
new_end_uses = new_period.end_uses
|
259
272
|
existing_period.end_uses&.merge_end_uses!(new_end_uses)
|
260
273
|
|
261
|
-
if existing_period.energy_production_kwh
|
262
|
-
|
263
|
-
existing_period.energy_production_kwh[:electricity_produced_kwh][:photovoltaic_kwh] = add_values(existing_period.energy_production_kwh[:electricity_produced][:photovoltaic], new_period.energy_production_kwh[:electricity_produced_kwh][:photovoltaic_kwh])
|
264
|
-
end
|
274
|
+
if existing_period.energy_production_kwh && existing_period.energy_production_kwh[:electricity_produced_kwh]
|
275
|
+
existing_period.energy_production_kwh[:electricity_produced_kwh][:photovoltaic_kwh] = add_values(existing_period.energy_production_kwh[:electricity_produced][:photovoltaic], new_period.energy_production_kwh[:electricity_produced_kwh][:photovoltaic_kwh])
|
265
276
|
end
|
266
277
|
|
267
278
|
existing_period.utility_costs_dollar&.each_with_index do |item, i|
|
@@ -279,6 +290,18 @@ module URBANopt
|
|
279
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])
|
280
291
|
end
|
281
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
|
+
|
282
305
|
return existing_period
|
283
306
|
end
|
284
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
|