urbanopt-reporting 0.4.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|