urbanopt-rnm-us 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 977f93affe9c5d526cd2cb0af1232f443e07693a78d45da7827563f9f804c30e
4
- data.tar.gz: 03e3f2642b6ddc140b36d9385e0a77790e1308a1f5bd1b96647775d03f4e4830
3
+ metadata.gz: 843ba686ad41687f6890709b5d53d3b30ed8bac33cfe726a0e907f2c0fe1e26f
4
+ data.tar.gz: 22cf46e48542910962f8c29da8c6721b885513bdd9f130083ae48b94028a264f
5
5
  SHA512:
6
- metadata.gz: e86574dc52de1655eace0ba423350343257cb234a2e110a2670fd80163fe07fc2f6b7ab7cf56decb02260bcf307b8620ddde128bb9c157ceeb6a94f59487dd16
7
- data.tar.gz: 8e7bba90ab83607932f8eecc5bda1487d86c5da2864a32d92fd88d3ae20d4aa18f8567244042dc66a9e640304aa65a0ec44f9090f6a2472124aa191be27db523
6
+ metadata.gz: 995c88f12b677995d076315afffc5254a6a2ba321926738d754b7e8d540396353a24ac357dc34d6d8754dd763eecae75dfea3f9ce6163203e00961ce48f8ae7d
7
+ data.tar.gz: c1913789eba31eb44bf3fa4f6abfb7a11715c0ccefd2b739d739c7c92c7636187945309de5f8fb3e7783ebc8c50fe1cd1b76ef3a040c898117f937e8c47c5065
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 0.3.0
4
+ Date Range 11/23/21 - 05/10/22
5
+
6
+ - Update copyrights
7
+
3
8
  ## Version 0.2.0
4
9
 
5
10
  Date Range 11/09/21 - 11/22/21
data/Gemfile CHANGED
@@ -8,3 +8,9 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
8
8
 
9
9
  # Below is an example of how to configure the gemfile for developing with local gems
10
10
  # modify as appropriate
11
+
12
+ if allow_local && File.exists?('../urbanopt-geojson-gem')
13
+ gem 'urbanopt-geojson', path: '../urbanopt-geojson-gem'
14
+ elsif allow_local
15
+ gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
16
+ end
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
1
+ URBANopt (tm), Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
2
2
  contributors. All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
@@ -35,4 +35,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35
35
  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
36
36
  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37
37
  OF THE POSSIBILITY OF SUCH DAMAGE.
38
- *********************************************************************************
38
+ *********************************************************************************
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -94,7 +94,7 @@ end
94
94
  desc 'Create input files with defaults'
95
95
  task :create_inputs_default, [:scenario_csv_path, :feature_file_path] do |t, args|
96
96
  puts 'Creating input files with defaulted settings'
97
- # if no path passed in, use default:
97
+ # if no path passed in, use default:
98
98
  scenario_csv_path = args[:scenario_csv_path] || 'spec/test/example_project/baseline_scenario.csv'
99
99
  root_dir, scenario_file_name = File.split(File.expand_path(scenario_csv_path))
100
100
  scenario_name = File.basename(scenario_file_name, File.extname(scenario_file_name))
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -197,21 +197,21 @@ module URBANopt
197
197
  else
198
198
  # edge case, check for results
199
199
  if data['results'].nil?
200
- puts "got a 200 but results are null...trying again"
200
+ puts 'got a 200 but results are null...trying again'
201
201
  tries += 1
202
202
  sleep(3)
203
203
  else
204
204
  # get results
205
205
  @results = data['results'] || []
206
206
 
207
- puts "downloading results"
207
+ puts 'downloading results'
208
208
  # download results
209
209
  download_results
210
210
  return @results
211
211
  end
212
212
  end
213
213
  else
214
- puts "no status yet...trying again"
214
+ puts 'no status yet...trying again'
215
215
  tries += 1
216
216
  sleep(3)
217
217
  end
@@ -231,10 +231,10 @@ module URBANopt
231
231
  sleep(3)
232
232
  end
233
233
  end
234
- rescue => error
234
+ rescue StandardError => e
235
235
  @@logger.error("Error retrieving simulation #{@sim_id}.")
236
- @@logger.error(error.message)
237
- raise error.message
236
+ @@logger.error(e.message)
237
+ raise e.message
238
238
  end
239
239
  end
240
240
  if !done
@@ -268,7 +268,7 @@ module URBANopt
268
268
 
269
269
  File.open(file_path, 'wb') { |f| f.write streamed.join }
270
270
  puts "RNM-US results.zip downloaded to #{@rnm_dir}"
271
-
271
+
272
272
  # unzip
273
273
  Zip::File.open(file_path) do |zip_file|
274
274
  zip_file.each do |f|
@@ -277,7 +277,7 @@ module URBANopt
277
277
  zip_file.extract(f, f_path) unless File.exist?(f_path)
278
278
  end
279
279
  end
280
- puts "results.zip extracted"
280
+ puts 'results.zip extracted'
281
281
  # delete zip
282
282
  File.delete(file_path)
283
283
 
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -79,7 +79,7 @@ module URBANopt
79
79
  yearly_profile_node_reactive = []
80
80
  nodes_per_bldg, area, medium_voltage = av_peak_cons_per_building_type(folder['building_types'])
81
81
  # the default variables are defined (i.e. type and rurality type)
82
- puts "consumers 82"
82
+ puts 'consumers 82'
83
83
  closest_node = building_map[3].split('_')[1].to_i # refers to the node, found in the class above
84
84
  node = closest_node
85
85
  cont = 1
@@ -176,7 +176,7 @@ module URBANopt
176
176
  conservative_factor = 0.8 # considered as a reasonable assumption, but this value could be changed
177
177
  average_peak_folder = JSON.parse(File.read(@average_building_peak_catalog_path))
178
178
  for i in 0..feature_file.length - 1
179
- area = feature_file[i].has_key?('floor_area') ? (feature_file[i]['floor_area']).round(2) : feature_file[i]['floor_area_sqft'].round(2)
179
+ area = feature_file[i].key?('floor_area') ? (feature_file[i]['floor_area']).round(2) : feature_file[i]['floor_area_sqft'].round(2)
180
180
  building_type = feature_file[i]['building_type'] # it specifies the type of building, sometimes it is directly the sub-type
181
181
  counter = 0 # counter to find number of buildings type belonging to same "category"
182
182
  average_peak_folder.each do |building_class|
@@ -215,10 +215,10 @@ module URBANopt
215
215
  # the method passes as arguments the urbanopt json and csv output file for each feature and the building coordinates previously calculated
216
216
  # and the "extreme" hour used to plan the network
217
217
  def customer_files_load(csv_feature_report, json_feature_report, building_map, building_nodes, hour)
218
- n_timestep_per_hour = json_feature_report["timesteps_per_hour"].to_i
218
+ n_timestep_per_hour = json_feature_report['timesteps_per_hour'].to_i
219
219
  profiles = Hash.new { |h, k| h[k] = [] }
220
220
  single_values = Hash.new(0)
221
- hours = 24 * n_timestep_per_hour -1
221
+ hours = 24 * n_timestep_per_hour - 1
222
222
  feature_type = json_feature_report['program']['building_types'][0]['building_type']
223
223
  residential_building_types = ['Single-Family Detached', 'Single-Family Attached', 'Multifamily', 'Single-Family', 'Multifamily Detached (2 to 4 units)', 'Multifamily Detached (5 or more units)']
224
224
 
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -143,7 +143,7 @@ module URBANopt
143
143
  # creating a method passing the GeoJSON file from URBANopt as the argument to define options that can be modified by the user
144
144
  # streets and building and primary substation coordinates
145
145
  # and returning the street coordinates array, the building coordinates array and the tot number of buildings in the project
146
- def coordinates_feature_hash(geojson_hash,scenario_features=[])
146
+ def coordinates_feature_hash(geojson_hash, scenario_features = [])
147
147
  i = 0 # index representing the number of street_nodes
148
148
  building_number = 0 # variable created to keep track the number of buildings in the project
149
149
  street_number = 0 # variable created to keep track the number of streets in the project
@@ -209,7 +209,7 @@ module URBANopt
209
209
  end
210
210
  street_coordinates[street_number] = each_street
211
211
  street_number += 1
212
- elsif street['geometry']['type'] == 'Polygon' && street['properties']['type'] == 'Building' and scenario_features.include? street['properties']['id']
212
+ elsif street['geometry']['type'] == 'Polygon' && street['properties']['type'] == 'Building' && scenario_features.include?(street['properties']['id'])
213
213
  for k in 0..street['geometry']['coordinates'].length - 1
214
214
  h = 0 # index representing number of nodes for each single building
215
215
  building = [] # array containing every building node coordinates and id of 1 building
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -59,7 +59,7 @@ module URBANopt
59
59
  @reopt = reopt
60
60
  end
61
61
 
62
- ##
62
+ ##
63
63
  # Post Process report and feature file
64
64
  ##
65
65
  def post_process
@@ -68,11 +68,10 @@ module URBANopt
68
68
  puts "RNM results were added to scenario report and feature file. New files can be found in #{@results_dir}"
69
69
  end
70
70
 
71
- ##
71
+ ##
72
72
  # Generate Scenario report
73
73
  ##
74
74
  def generate_report
75
-
76
75
  # calculate rnm statistics
77
76
  rnm_stats = calculate_stats
78
77
 
@@ -80,17 +79,16 @@ module URBANopt
80
79
  scenario = get_scenario
81
80
 
82
81
  # merge stats with scenario report (before feature_reports section)
83
-
82
+
84
83
  scenario['scenario_report']['rnm_results'] = rnm_stats
85
-
84
+
86
85
  # save back to scenario directory as scenario_report_rnm.json
87
- File.open(File.join(@scenario_dir, @report_filename), "w") do |f|
86
+ File.open(File.join(@scenario_dir, @report_filename), 'w') do |f|
88
87
  f.write(JSON.pretty_generate(scenario))
89
88
  end
90
-
91
89
  end
92
90
 
93
- ##
91
+ ##
94
92
  # Load Scenario Report
95
93
  ##
96
94
  def get_scenario
@@ -98,16 +96,15 @@ module URBANopt
98
96
  # get reopt scenario report
99
97
  return JSON.parse(File.read(File.join(@scenario_dir, 'feature_optimization.json')))
100
98
  else
101
- # get default scenario report
99
+ # get default scenario report
102
100
  return JSON.parse(File.read(File.join(@scenario_dir, 'default_scenario_report.json')))
103
101
  end
104
102
  end
105
103
 
106
- ##
104
+ ##
107
105
  # Generate new GeoJSON file
108
106
  ##
109
107
  def generate_feature_file
110
-
111
108
  # get results GeoJSON file and read in
112
109
  results = JSON.parse(File.read(File.join(@results_dir, 'GeoJSON', 'Distribution_system.json')))
113
110
 
@@ -117,7 +114,7 @@ module URBANopt
117
114
  end
118
115
 
119
116
  # save back to scenario directory as features_and_rnm.json
120
- File.open(File.join(@scenario_dir, @geojson_filename), "w") do |f|
117
+ File.open(File.join(@scenario_dir, @geojson_filename), 'w') do |f|
121
118
  f.write(JSON.pretty_generate(@feature_file))
122
119
  end
123
120
  end
@@ -132,6 +129,7 @@ module URBANopt
132
129
  stats['demand_generation_planning'] = []
133
130
  @results['Demand/generation and number of consumers/distributed generators'].each do |item|
134
131
  rec = {}
132
+ puts "ITEM VOLTAGE LEVEL: #{item['Voltage level']}, item type: #{item['Type'].strip}"
135
133
  case item['Voltage level']
136
134
  when 'LV'
137
135
  rec['type'] = "Low Voltage (LV) #{item['Type'].strip}"
@@ -155,7 +153,7 @@ module URBANopt
155
153
 
156
154
  # lines LV and MV
157
155
  stats['electrical_lines_length'] = {}
158
- km_to_mi = 0.621371
156
+ km_to_mi = 0.621371
159
157
  @results['Length of overhead and underground electrical lines'].each do |item|
160
158
  case item['Voltage level']
161
159
  when 'Lines LV'
@@ -181,8 +179,8 @@ module URBANopt
181
179
  @results['Summary'].each do |item|
182
180
  case item['Level']
183
181
  when 'LV'
184
- stats['costs']['investment']['low_voltage_network'] = item['Investment cost']
185
- stats['costs']['yearly_maintenance']['low_voltage_network'] = item['Preventive maintenance (yearly)']
182
+ stats['costs']['investment']['low_voltage_network'] = item['Investment cost']
183
+ stats['costs']['yearly_maintenance']['low_voltage_network'] = item['Preventive maintenance (yearly)']
186
184
  when 'MV'
187
185
  stats['costs']['investment']['medium_voltage_network'] = item['Investment cost']
188
186
  stats['costs']['yearly_maintenance']['medium_voltage_network'] = item['Preventive maintenance (yearly)']
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -84,8 +84,8 @@ module URBANopt
84
84
  # in the hour with generation max peak
85
85
  # in the hour with storage max peak
86
86
 
87
- for i in 0..profiles_planning[:planning_profile_cust_active].length-1
88
- hourly_app_power = ((profiles_planning[:planning_profile_cust_active][i] + profiles_planning[:planning_profile_storage_active][i] - profiles_planning[:planning_profile_dg_active][i])/@power_factor).abs
87
+ for i in 0..profiles_planning[:planning_profile_cust_active].length - 1
88
+ hourly_app_power = ((profiles_planning[:planning_profile_cust_active][i] + profiles_planning[:planning_profile_storage_active][i] - profiles_planning[:planning_profile_dg_active][i]) / @power_factor).abs
89
89
  if hourly_app_power > peak_app_power_node
90
90
  peak_app_power_node = hourly_app_power
91
91
  end
@@ -103,9 +103,9 @@ module URBANopt
103
103
  @profile_customer_p.push([id, 48, profiles_planning[:planning_profile_cust_active]])
104
104
  @profile_customer_p_ext.push([id, 8760, profiles[:yearly_profile_cust_active]])
105
105
  @profile_customer_q_ext.push([id, 8760, profiles[:yearly_profile_cust_reactive]])
106
-
107
- if der_capacity[:storage] != nil && der_capacity[:storage] > 0
108
- @customers.push([building_map, id_batt, voltage_default, single_values[:peak_active_power_storage],single_values[:peak_reactive_power_storage], phases])
106
+
107
+ if !der_capacity[:storage].nil? && der_capacity[:storage] > 0
108
+ @customers.push([building_map, id_batt, voltage_default, single_values[:peak_active_power_storage], single_values[:peak_reactive_power_storage], phases])
109
109
  @customers_ext.push([building_map, id_batt, voltage_default, single_values[:peak_active_power_storage], single_values[:peak_reactive_power_storage], phases, area, height, (single_values[:energy]).round(2), single_values[:peak_active_power_storage], single_values[:peak_reactive_power_storage], users])
110
110
  @profile_customer_q.push([id_batt, 48, profiles_planning[:planning_profile_storage_reactive]])
111
111
  @profile_customer_p.push([id_batt, 48, profiles_planning[:planning_profile_storage_active]])
@@ -138,7 +138,7 @@ module URBANopt
138
138
  cont = 1
139
139
  cont_reverse = 1
140
140
  nodes_consumers = nodes_per_bldg - 1
141
-
141
+
142
142
  for i in 1..nodes_per_bldg
143
143
  coordinates = building_map
144
144
  node = closest_node + cont # to set the new nodes with enough distance among each others
@@ -146,10 +146,10 @@ module URBANopt
146
146
  if i > 1 && node <= building_nodes.length - 2
147
147
  coordinates = building_nodes[node] # take the closest building node index to the street and pass the nodes after it
148
148
  cont += 1
149
- elsif i > 1
149
+ elsif i > 1
150
150
  coordinates = building_nodes[node_reverse]
151
151
  cont_reverse += 1
152
- end
152
+ end
153
153
  # this condition is used to firstly place the building consumption nodes and then the last node
154
154
  # to be placed is the one referred to DG and battery for the building
155
155
  if i < nodes_per_bldg # considering the consumers nodes
@@ -159,11 +159,11 @@ module URBANopt
159
159
  peak_reactive_power_cons = (single_values[:peak_reactive_power_cons] / nodes_consumers).round(2)
160
160
  voltage_default, phases = voltage_values(peak_active_power_cons / @power_factor)
161
161
  for k in 0..profiles_planning[:planning_profile_cust_active].length - 1
162
- planning_profile_node_active[k] = (profiles_planning[:planning_profile_cust_active][k] / nodes_consumers).round(2)
163
- planning_profile_node_reactive[k] = (profiles_planning[:planning_profile_cust_reactive][k] / nodes_consumers).round(2)
162
+ planning_profile_node_active[k] = (profiles_planning[:planning_profile_cust_active][k] / nodes_consumers).round(2)
163
+ planning_profile_node_reactive[k] = (profiles_planning[:planning_profile_cust_reactive][k] / nodes_consumers).round(2)
164
164
  end
165
165
  for k in 0..profiles[:yearly_profile_cust_active].length - 1
166
- yearly_profile_node_active[k] = (profiles[:yearly_profile_cust_active][k] / nodes_consumers).round(2)
166
+ yearly_profile_node_active[k] = (profiles[:yearly_profile_cust_active][k] / nodes_consumers).round(2)
167
167
  yearly_profile_node_reactive[k] = (profiles[:yearly_profile_cust_reactive][k] / nodes_consumers).round(2)
168
168
  end
169
169
  @customers.push([coordinates, id, voltage_default, peak_active_power_cons, peak_reactive_power_cons, phases])
@@ -174,7 +174,7 @@ module URBANopt
174
174
  @profile_customer_q_ext.push([id, 8760, yearly_profile_node_reactive])
175
175
  else
176
176
  # considering the DG and battery
177
- voltage_default, phases = voltage_values(der_capacity[:dg]) #assuming that the pv capacity is always higher than battery capacity
177
+ voltage_default, phases = voltage_values(der_capacity[:dg]) # assuming that the pv capacity is always higher than battery capacity
178
178
  id_dg = "#{coordinates[3]}_DG"
179
179
  id_batt = "#{coordinates[3]}_battery"
180
180
  coordinates.pop
@@ -183,7 +183,7 @@ module URBANopt
183
183
  @dg_profile_q.push([id_dg, 48, profiles_planning[:planning_profile_dg_reactive]])
184
184
  @profile_dg_p_extended.push([id_dg, 8760, profiles[:yearly_profile_dg_active]])
185
185
  @profile_dg_q_extended.push([id_dg, 8760, profiles[:yearly_profile_dg_reactive]])
186
- if der_capacity[:storage] != nil && der_capacity[:storage] > 0
186
+ if !der_capacity[:storage].nil? && der_capacity[:storage] > 0
187
187
  @customers.push([coordinates, id_batt, voltage_default, single_values[:peak_active_power_storage], single_values[:peak_reactive_power_storage], phases])
188
188
  @customers_ext.push([coordinates, id_batt, voltage_default, single_values[:peak_active_power_storage], single_values[:peak_reactive_power_storage], phases, area, height, (single_values[:energy]).round(2), single_values[:peak_active_power_storage], single_values[:peak_reactive_power_storage], users])
189
189
  @profile_customer_q.push([id_batt, 48, profiles_planning[:planning_profile_storage_reactive]])
@@ -249,15 +249,15 @@ module URBANopt
249
249
  average_peak_folder = JSON.parse(File.read(@average_building_peak_catalog_path))
250
250
  for i in 0..feature_file.length - 1
251
251
  area = feature_file[i].key?('floor_area') ? (feature_file[i]['floor_area']).round(2) : (feature_file[i]['floor_area_sqft']).round(2)
252
- building_type = feature_file[i]['building_type'] #it specifies the type of building, sometimes it is directly the sub-type
252
+ building_type = feature_file[i]['building_type'] # it specifies the type of building, sometimes it is directly the sub-type
253
253
  counter = 0 # counter to find number of buildings type belonging to same "category"
254
254
  average_peak_folder.each do |building_class|
255
- if (building_type == building_class["building type"] || building_type == building_class["sub-type"])
255
+ if building_type == building_class['building type'] || building_type == building_class['sub-type']
256
256
  average_peak = (building_class['average peak demand (kW/ft2)'].to_f * area).to_f.round(4) # finding the average peak considering the floor area of the bilding under consideration
257
257
  average_peak_by_size[counter] = average_peak
258
258
  floor_area[counter] = (building_class['floor_area (ft2)'] - area).abs # minimum difference among area and area from the prototypes defined by DOE
259
259
  counter += 1
260
- # in this way I don t consider residential and I assume it s average_peak = 0, it is ok because we assume always 1 node per RES consumers, single-detached family houses
260
+ # in this way I don t consider residential and I assume it s average_peak = 0, it is ok because we assume always 1 node per RES consumers, single-detached family houses
261
261
  end
262
262
  end
263
263
  if counter > 1
@@ -273,21 +273,21 @@ module URBANopt
273
273
  average_peak = mixed_use_av_peak # average peak per mixed use considering the building types which are in this building
274
274
  area = area_mixed_use
275
275
  end
276
- nodes_per_bldg = ((average_peak / (@lv_limit[:three_phase] * @power_factor * conservative_factor)).to_f).ceil # computing number of nodes per building
277
- if nodes_per_bldg > @max_num_lv_nodes #that it is equal to how it was before
276
+ nodes_per_bldg = (average_peak / (@lv_limit[:three_phase] * @power_factor * conservative_factor)).to_f.ceil # computing number of nodes per building
277
+ if nodes_per_bldg > @max_num_lv_nodes # that it is equal to how it was before
278
278
  nodes_per_bldg = 1
279
279
  @medium_voltage = true
280
280
  end
281
-
282
- nodes_per_bldg += 1 # tacking into account the extra node for distributed generation and the battery
281
+
282
+ nodes_per_bldg += 1 # tacking into account the extra node for distributed generation and the battery
283
283
  return nodes_per_bldg, area
284
284
  end
285
285
 
286
286
  # method to order profiles consistently
287
287
  def profiles_planning_creation(profiles_planning, power, single_values, i, hours, power_factor)
288
- profiles_planning[:planning_profile_cust_active][i] = power["REopt:Electricity:Load:Total(kw)"].to_f
288
+ profiles_planning[:planning_profile_cust_active][i] = power['REopt:Electricity:Load:Total(kw)'].to_f
289
289
  profiles_planning[:planning_profile_storage_active][i] = power['REopt:Electricity:Grid:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:Generator:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:PV:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:Wind:ToBattery(kw)'].to_f - power['REopt:Electricity:Storage:ToLoad(kw)'].to_f - power['REopt:Electricity:Storage:ToGrid(kw)'].to_f
290
- profiles_planning[:planning_profile_dg_active][i] = power["REopt:ElectricityProduced:Total(kw)"].to_f
290
+ profiles_planning[:planning_profile_dg_active][i] = power['REopt:ElectricityProduced:Total(kw)'].to_f
291
291
  profiles_planning[:planning_profile_cust_reactive][i] = profiles_planning[:planning_profile_cust_active][i] * Math.tan(Math.acos(power_factor))
292
292
  profiles_planning[:planning_profile_storage_reactive][i] = profiles_planning[:planning_profile_storage_active][i] * Math.tan(Math.acos(power_factor))
293
293
  profiles_planning[:planning_profile_dg_reactive][i] = profiles_planning[:planning_profile_dg_active][i] * Math.tan(Math.acos(power_factor))
@@ -301,7 +301,7 @@ module URBANopt
301
301
  end
302
302
  if profiles_planning[:planning_profile_dg_active][i] > single_values[:peak_active_power_dg]
303
303
  single_values[:peak_active_power_dg] = profiles_planning[:planning_profile_dg_active][i]
304
- single_values[:peak_reactive_power_dg] = single_values[:peak_active_power_dg] * (Math.tan(Math.acos(power_factor)))
304
+ single_values[:peak_reactive_power_dg] = single_values[:peak_active_power_dg] * Math.tan(Math.acos(power_factor))
305
305
  end
306
306
  return profiles_planning, single_values
307
307
  end
@@ -313,13 +313,13 @@ module URBANopt
313
313
  # and the "extreme" hours used to plan the network
314
314
  def prosumer_files_load(csv_feature_report, json_feature_report, building_map, building_nodes, hour)
315
315
  # add variable to include how many timestep per hour, so the profiles become 48 * n_timestep_per_hour
316
- n_timestep_per_hour = json_feature_report["timesteps_per_hour"].to_i
317
- profiles_planning = Hash.new{|h, k| h[k] = Array.new(48*n_timestep_per_hour, 0)} # initializing each profile hash to 0 for the number of intervals considered for the planning of the network
318
- profiles = Hash.new{|h, k| h[k] = []}
316
+ n_timestep_per_hour = json_feature_report['timesteps_per_hour'].to_i
317
+ profiles_planning = Hash.new { |h, k| h[k] = Array.new(48 * n_timestep_per_hour, 0) } # initializing each profile hash to 0 for the number of intervals considered for the planning of the network
318
+ profiles = Hash.new { |h, k| h[k] = [] }
319
319
  single_values = Hash.new(0)
320
320
  @medium_voltage = false
321
- hours = 24 * n_timestep_per_hour -1 # change name, maybe to intervals
322
- feature_type = json_feature_report['program']['building_types'][0]["building_type"]
321
+ hours = 24 * n_timestep_per_hour - 1 # change name, maybe to intervals
322
+ feature_type = json_feature_report['program']['building_types'][0]['building_type']
323
323
  residential_building_types = ['Single-Family Detached', 'Single-Family Attached', 'Multifamily', 'Single-Family', 'Multifamily Detached (2 to 4 units)', 'Multifamily Detached (5 or more units)']
324
324
 
325
325
  # finding the index where to start computing and saving the info, from the value of the "worst-case hour" for the max peak consumption of the district
@@ -332,49 +332,49 @@ module URBANopt
332
332
  profile_start_min = hour.hour_index_min_comm - ((hour.peak_hour_min_comm.split(':')[0].to_i + (hour.peak_hour_min_comm.split(':')[1].to_i / 60)) * n_timestep_per_hour)
333
333
  end
334
334
  # finding the index where to start computing and saving the info, from the value of the "most extreme hours" for the max peak consumption of the district
335
- k = 0 # index for each hour of the year represented in the csv file
336
- i = hours +1 # to represent the 24 hours in case of max_net_generation day
335
+ k = 0 # index for each hour of the year represented in the csv file
336
+ i = hours + 1 # to represent the 24 hours in case of max_net_generation day
337
337
  j = 0 # to represent the 24 hours in case of peak_demand_day
338
338
  h_cons_batt = 0
339
339
  h_dg_max = 0 # hour with max DG generation
340
340
  h_stor_max = 0 # hour with max storage absorption
341
341
  max_peak = 0
342
342
  CSV.foreach(csv_feature_report, headers: true) do |power|
343
- @power_factor = power["Electricity:Facility Power(kW)"].to_f / power["Electricity:Facility Apparent Power(kVA)"].to_f
344
- profiles[:yearly_profile_cust_active].push(power["REopt:Electricity:Load:Total(kw)"].to_f)
343
+ @power_factor = power['Electricity:Facility Power(kW)'].to_f / power['Electricity:Facility Apparent Power(kVA)'].to_f
344
+ profiles[:yearly_profile_cust_active].push(power['REopt:Electricity:Load:Total(kw)'].to_f)
345
345
  profiles[:yearly_profile_cust_reactive].push(profiles[:yearly_profile_cust_active][k] * Math.tan(Math.acos(@power_factor)))
346
- profiles[:yearly_profile_dg_active].push(power["REopt:ElectricityProduced:Total(kw)"].to_f)
346
+ profiles[:yearly_profile_dg_active].push(power['REopt:ElectricityProduced:Total(kw)'].to_f)
347
347
  profiles[:yearly_profile_dg_reactive].push(profiles[:yearly_profile_dg_active][k] * Math.tan(Math.acos(@power_factor)))
348
348
  profiles[:yearly_profile_storage_active].push(power['REopt:Electricity:Grid:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:Generator:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:PV:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:Wind:ToBattery(kw)'].to_f - power['REopt:Electricity:Storage:ToLoad(kw)'].to_f - power['REopt:Electricity:Storage:ToGrid(kw)'].to_f)
349
349
  profiles[:yearly_profile_storage_reactive].push(profiles[:yearly_profile_storage_active][k] * Math.tan(Math.acos(@power_factor)))
350
- single_values[:energy] += power["REopt:Electricity:Load:Total(kw)"].to_f # calculating the yearly energy consumed by each feature
351
- single_values[:energy_dg] += power["REopt:ElectricityProduced:Total(kw)"].to_f
350
+ single_values[:energy] += power['REopt:Electricity:Load:Total(kw)'].to_f # calculating the yearly energy consumed by each feature
351
+ single_values[:energy_dg] += power['REopt:ElectricityProduced:Total(kw)'].to_f
352
352
  single_values[:energy_storage] += power['REopt:Electricity:Grid:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:Generator:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:PV:ToBattery(kw)'].to_f + power['REopt:ElectricityProduced:Wind:ToBattery(kw)'].to_f - power['REopt:Electricity:Storage:ToLoad(kw)'].to_f - power['REopt:Electricity:Storage:ToGrid(kw)'].to_f
353
353
  case k
354
- when profile_start_min..profile_start_min + (hours)
355
- profiles_planning, single_values = self.profiles_planning_creation(profiles_planning, power, single_values, i, hours, power_factor)
356
- i+=1
357
- when profile_start_max..profile_start_max + (hours)
358
- profiles_planning, single_values = self.profiles_planning_creation(profiles_planning, power, single_values, j, hours, power_factor)
359
- j+=1
354
+ when profile_start_min..profile_start_min + hours
355
+ profiles_planning, single_values = profiles_planning_creation(profiles_planning, power, single_values, i, hours, power_factor)
356
+ i += 1
357
+ when profile_start_max..profile_start_max + hours
358
+ profiles_planning, single_values = profiles_planning_creation(profiles_planning, power, single_values, j, hours, power_factor)
359
+ j += 1
360
360
  end
361
- k+=1
361
+ k += 1
362
362
  end
363
363
  height = (json_feature_report['program']['maximum_roof_height_ft']).round(2)
364
364
  users = json_feature_report['program']['number_of_residential_units']
365
- der_capacity = self.sum_dg(json_feature_report['distributed_generation'])
365
+ der_capacity = sum_dg(json_feature_report['distributed_generation'])
366
366
  if @only_lv_consumers
367
- nodes_per_bldg, area = self.av_peak_cons_per_building_type(json_feature_report['program']['building_types'])
367
+ nodes_per_bldg, area = av_peak_cons_per_building_type(json_feature_report['program']['building_types'])
368
368
  if @max_num_nodes == 1
369
- self.construct_prosumer_general(profiles, profiles_planning, single_values, building_map, area, height, users, der_capacity)
369
+ construct_prosumer_general(profiles, profiles_planning, single_values, building_map, area, height, users, der_capacity)
370
370
  else
371
- self.construct_prosumer_lv(nodes_per_bldg, profiles, profiles_planning, single_values, building_map, building_nodes, area, height, users, der_capacity)
371
+ construct_prosumer_lv(nodes_per_bldg, profiles, profiles_planning, single_values, building_map, building_nodes, area, height, users, der_capacity)
372
372
  end
373
373
  else
374
- area = json_feature_report['program'].has_key?('floor_area') ? (json_feature_report['program']['floor_area']).round(2) : (json_feature_report['program']['floor_area_sqft']).round(2)
374
+ area = json_feature_report['program'].key?('floor_area') ? (json_feature_report['program']['floor_area']).round(2) : (json_feature_report['program']['floor_area_sqft']).round(2)
375
375
  # associating 2 nodes (consumers & DG and battery in the same node) per building considering the consumer, the battery and DG
376
- self.construct_prosumer_general(profiles, profiles_planning, single_values, building_map, area, height, users, der_capacity)
377
- end
376
+ construct_prosumer_general(profiles, profiles_planning, single_values, building_map, area, height, users, der_capacity)
377
+ end
378
378
  end
379
379
  end
380
380
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -105,7 +105,7 @@ module URBANopt
105
105
  csv << ["<#{key}>"]
106
106
  if ext_catalog[key].is_a?(Hash) # defining the section under consideration is an Hash or an Array
107
107
  if key == 'OTHERS'
108
- ext_catalog[key]["UTM Zone"] = utm_zone.to_s
108
+ ext_catalog[key]['UTM Zone'] = utm_zone.to_s
109
109
  end
110
110
  ext_catalog[key].each do |k, v|
111
111
  row = []
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -126,8 +126,7 @@ module URBANopt
126
126
  def get_scenario_features
127
127
  @num_header_rows = 1
128
128
  features = []
129
- CSV.foreach(@scenario_csv_path, :headers => true) do |row|
130
-
129
+ CSV.foreach(@scenario_csv_path, headers: true) do |row|
131
130
  break if row[0].nil?
132
131
 
133
132
  # gets +feature_id+ and append to list
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -109,6 +109,7 @@ module URBANopt
109
109
  end
110
110
  end
111
111
  end
112
+
112
113
  def aggregate_consumption(file_csv, file_json, n_feature)
113
114
  feature_type = file_json['program']['building_types'][0]['building_type']
114
115
  # residential_building_types = "Single-Family Detached" #add the other types
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -40,6 +40,6 @@
40
40
 
41
41
  module URBANopt
42
42
  module RNM
43
- VERSION = '0.2.0'.freeze
43
+ VERSION = '0.3.0'.freeze
44
44
  end
45
45
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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 (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -54,23 +54,23 @@ module URBANopt
54
54
  conductor.each do |k, v|
55
55
  if k.include? '(mm)'
56
56
  # new_key = "#{k.sub('(mm)', '')}(ft)"
57
- new_key = "#{k.sub(' (mm)', '').gsub(' ','_')}"
57
+ new_key = k.sub(' (mm)', '').gsub(' ', '_').to_s
58
58
  hash[new_key] = v
59
59
  elsif k.include? '(A)'
60
- new_key = "#{k.sub(' (A)', '').gsub(' ','_')}"
60
+ new_key = k.sub(' (A)', '').gsub(' ', '_').to_s
61
61
  hash[new_key] = v
62
62
  elsif k.include? '#'
63
- new_key = "#{k.sub('#', 'num').gsub(' ', '_')}"
63
+ new_key = k.sub('#', 'num').gsub(' ', '_').to_s
64
64
  hash[new_key] = v
65
65
  elsif k.include? '(ohm/km)'
66
66
  # new_key = "#{k.sub('(ohm/km)', '')}(ohm/mi)"
67
- new_key = "#{k.sub(' (ohm/km)', '').gsub(' ','_')}"
67
+ new_key = k.sub(' (ohm/km)', '').gsub(' ', '_').to_s
68
68
  hash[new_key] = v
69
69
  elsif k != 'voltage level' && k != 'type'
70
- new_key = "#{k.gsub(' ', '_')}"
70
+ new_key = k.gsub(' ', '_').to_s
71
71
  hash[new_key] = v
72
72
  else
73
- new_key = "#{k.gsub(' ', '_')}"
73
+ new_key = k.gsub(' ', '_').to_s
74
74
  hash[new_key] = v
75
75
  end
76
76
  end
@@ -82,7 +82,7 @@ module URBANopt
82
82
  elsif k.include? '(m)'
83
83
  hash.delete(k)
84
84
  k = k.split(' ')[0]
85
- new_key = "#{k.sub(' ', '_')}"
85
+ new_key = k.sub(' ', '_').to_s
86
86
  hash[new_key] = v
87
87
  end
88
88
  end
data/lib/urbanopt/rnm.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
data/lib/urbanopt-rnm.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt (tm), Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), 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,
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'faraday', '~> 1.0.1'
28
28
  spec.add_dependency 'geoutm', '~> 1.0.2'
29
29
  spec.add_dependency 'rubyzip', '~> 2.3.2'
30
- spec.add_dependency 'urbanopt-geojson', '~> 0.7.0'
30
+ spec.add_dependency 'urbanopt-geojson', '~> 0.8.0'
31
31
 
32
32
  spec.add_development_dependency 'bundler', '~> 2.1'
33
33
  spec.add_development_dependency 'rake', '~> 13.0'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanopt-rnm-us
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katherine Fleming
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-12-07 00:00:00.000000000 Z
12
+ date: 2022-05-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: certified
@@ -73,14 +73,14 @@ dependencies:
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: 0.7.0
76
+ version: 0.8.0
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: 0.7.0
83
+ version: 0.8.0
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: bundler
86
86
  requirement: !ruby/object:Gem::Requirement