urbanopt-reopt 0.10.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,7 +14,7 @@ module URBANopt # :nodoc:
14
14
  module REopt # :nodoc:
15
15
  class ScenarioReportAdapter
16
16
  ##
17
- # ScenarioReportAdapter can convert a ScenarioReport into a \REopt Lite posts or updates a ScenarioReport and its FeatureReports from \REopt Lite response(s)
17
+ # ScenarioReportAdapter can convert a ScenarioReport into a \REopt posts or updates a ScenarioReport and its FeatureReports from \REopt response(s)
18
18
  ##
19
19
  # [*parameters:*]
20
20
  def initialize
@@ -23,26 +23,35 @@ module URBANopt # :nodoc:
23
23
  end
24
24
 
25
25
  ##
26
- # Convert a ScenarioReport into a \REopt Lite post
26
+ # Convert a ScenarioReport into a \REopt post
27
27
  #
28
28
  # [*parameters:*]
29
29
  #
30
- # * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting the +reopt_assumptions_hash+, if provided, to a \REopt Lite post. Otherwise, if the +reopt_assumptions_hash+ is nil a default post will be updated from this ScenarioReport and submitted to the \REopt Lite API.
31
- # * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt Lite API containing default values. Values will be overwritten from the ScenarioReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API.
30
+ # * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting the +reopt_assumptions_hash+, if provided, to a \REopt post. Otherwise, if the +reopt_assumptions_hash+ is nil a default post will be updated from this ScenarioReport and submitted to the \REopt API.
31
+ # * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt API containing default values. Values will be overwritten from the ScenarioReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API.
32
32
  #
33
- # [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt Lite API
33
+ # [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt API
34
34
  ##
35
35
  def reopt_json_from_scenario_report(scenario_report, reopt_assumptions_json = nil, community_photovoltaic = nil)
36
36
  name = scenario_report.name.delete ' '
37
37
  scenario_id = scenario_report.id.delete ' '
38
38
  description = "scenario_report_#{name}_#{scenario_id}"
39
39
 
40
- # Create base REpopt Lite post
41
- reopt_inputs = { Scenario: { Site: { ElectricTariff: { blended_monthly_demand_charges_us_dollars_per_kw: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], blended_monthly_rates_us_dollars_per_kwh: [0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13] }, LoadProfile: {}, Wind: { max_kw: 0 } } } }
40
+ # Create base REpopt post
42
41
  if !reopt_assumptions_json.nil?
43
42
  reopt_inputs = reopt_assumptions_json
44
43
  else
45
- @@logger.info('Using default REopt Lite assumptions')
44
+ @@logger.info('Using default REopt assumptions')
45
+ reopt_inputs = {
46
+ Settings:{},
47
+ Site: {},
48
+ Financial:{},
49
+ ElectricTariff: {
50
+ monthly_demand_rates: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
51
+ monthly_energy_rates: [0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
52
+ },
53
+ ElectricLoad: {}
54
+ }
46
55
  end
47
56
 
48
57
  # Update required info
@@ -76,26 +85,26 @@ module URBANopt # :nodoc:
76
85
  end
77
86
  end
78
87
 
79
- reopt_inputs[:Scenario][:description] = description
88
+ reopt_inputs[:description] = description
80
89
 
81
- reopt_inputs[:Scenario][:Site][:latitude] = scenario_report.location.latitude_deg
82
- reopt_inputs[:Scenario][:Site][:longitude] = scenario_report.location.longitude_deg
90
+ reopt_inputs[:Site][:latitude] = scenario_report.location.latitude_deg
91
+ reopt_inputs[:Site][:longitude] = scenario_report.location.longitude_deg
83
92
 
84
93
  # Update optional info
85
94
  # REK: attribute names should be updated
86
- if reopt_inputs[:Scenario][:Site][:roof_squarefeet].nil? && !scenario_report.program.roof_area_sqft.nil?
87
- reopt_inputs[:Scenario][:Site][:roof_squarefeet] = scenario_report.program.roof_area_sqft[:available_roof_area_sqft]
95
+ if reopt_inputs[:Site][:roof_squarefeet].nil? && !scenario_report.program.roof_area_sqft.nil?
96
+ reopt_inputs[:Site][:roof_squarefeet] = scenario_report.program.roof_area_sqft[:available_roof_area_sqft]
88
97
  end
89
98
 
90
99
  begin
91
- if reopt_inputs[:Scenario][:Site][:land_acres].nil? && !community_photovoltaic[0][:properties][:footprint_area].nil?
92
- reopt_inputs[:Scenario][:Site][:land_acres] = community_photovoltaic[0][:properties][:footprint_area] * 1.0 / 43560 # acres/sqft
100
+ if reopt_inputs[:Site][:land_acres].nil? && !community_photovoltaic[0][:properties][:footprint_area].nil?
101
+ reopt_inputs[:Site][:land_acres] = community_photovoltaic[0][:properties][:footprint_area] * 1.0 / 43560 # acres/sqft
93
102
  end
94
103
  rescue StandardError
95
104
  end
96
105
 
97
- if reopt_inputs[:Scenario][:time_steps_per_hour].nil?
98
- reopt_inputs[:Scenario][:time_steps_per_hour] = 1
106
+ if reopt_inputs[:Settings][:time_steps_per_hour].nil?
107
+ reopt_inputs[:Settings][:time_steps_per_hour] = 1
99
108
  end
100
109
 
101
110
  # Update load profile info
@@ -120,38 +129,40 @@ module URBANopt # :nodoc:
120
129
 
121
130
  # Convert load to REopt Resolution
122
131
  begin
123
- reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, scenario_report.timesteps_per_hour, reopt_inputs[:Scenario][:time_steps_per_hour])
132
+ reopt_inputs[:ElectricLoad][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, scenario_report.timesteps_per_hour, reopt_inputs[:Settings][:time_steps_per_hour])
124
133
  rescue StandardError
125
- @@logger.error("Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}")
126
- raise "Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}"
127
- end
128
-
129
- if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps].nil?
130
- n_top_values = 100
131
- tmp1 = reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw]
132
- tmp2 = tmp1.each_index.max_by(n_top_values * reopt_inputs[:Scenario][:time_steps_per_hour]) { |i| tmp1[i] }
133
- for i in (0...tmp2.count)
134
- tmp2[i] += 1
135
- end
136
- reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps] = tmp2
137
- end
138
-
139
- if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw].nil?
140
- reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw] = 0
141
- end
134
+ @@logger.error("Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:Settings][:time_steps_per_hour]}")
135
+ raise "Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:Settings][:time_steps_per_hour]}"
136
+ end
137
+
138
+ # REMOVE COINCIDENT PEAKS STUFF JUST FOR TESTING
139
+ # if reopt_inputs[:ElectricTariff][:coincident_peak_load_active_time_steps].nil?
140
+ # n_top_values = 10
141
+ # tmp1 = reopt_inputs[:ElectricLoad][:loads_kw]
142
+ # tmp2 = tmp1.each_index.max_by(n_top_values * reopt_inputs[:Settings][:time_steps_per_hour]) { |i| tmp1[i] }
143
+ # for i in (0...tmp2.count)
144
+ # tmp2[i] += 1
145
+ # end
146
+ # # this needs to be a 2D array
147
+ # reopt_inputs[:ElectricTariff][:coincident_peak_load_active_time_steps] = [tmp2]
148
+ # end
149
+
150
+ # if reopt_inputs[:ElectricTariff][:coincident_peak_load_charge_per_kw].nil?
151
+ # reopt_inputs[:ElectricTariff][:coincident_peak_load_charge_per_kw] = 0
152
+ # end
142
153
 
143
154
  return reopt_inputs
144
155
  end
145
156
 
146
157
  ##
147
- # Converts a FeatureReport list from a ScenarioReport into an array of \REopt Lite posts
158
+ # Converts a FeatureReport list from a ScenarioReport into an array of \REopt posts
148
159
  #
149
160
  # [*parameters:*]
150
161
  #
151
- # * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting FeatureReports and respecitive +reopt_assumptions_hashes+, if provided, to a \REopt Lite post. If no +reopt_assumptions_hashes+ are provided default posts will be updated from these FeatureReports and submitted to the \REopt Lite API.
152
- # * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of hashes formatted for submittal to the \REopt Lite API containing default values. Values will be overwritten from the ScenarioReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API. The order should match the list in ScenarioReport.feature_reports.
162
+ # * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting FeatureReports and respecitive +reopt_assumptions_hashes+, if provided, to a \REopt post. If no +reopt_assumptions_hashes+ are provided default posts will be updated from these FeatureReports and submitted to the \REopt API.
163
+ # * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of hashes formatted for submittal to the \REopt API containing default values. Values will be overwritten from the ScenarioReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API. The order should match the list in ScenarioReport.feature_reports.
153
164
  #
154
- # [*return:*] _Array_ - Returns an array of hashes formatted for submittal to the \REopt Lite API in the order of the FeatureReports lited in ScenarioReport.feature_reports.
165
+ # [*return:*] _Array_ - Returns an array of hashes formatted for submittal to the \REopt API in the order of the FeatureReports lited in ScenarioReport.feature_reports.
155
166
  ##
156
167
  def reopt_jsons_from_scenario_feature_reports(scenario_report, reopt_assumptions_hashes = [])
157
168
  results = []
@@ -165,64 +176,41 @@ module URBANopt # :nodoc:
165
176
  return results
166
177
  end
167
178
 
168
- def modrow(data, idx) # :nodoc:
169
- data[$generation_timeseries_kwh_col] = $generation_timeseries_kwh[idx] || 0
170
- data[$load_col] = $load[idx] || 0
171
- data[$utility_to_load_col] = $utility_to_load[idx] || 0
172
- data[$utility_to_battery_col] = $utility_to_battery[idx] || 0
173
- data[$storage_to_load_col] = $storage_to_load[idx] || 0
174
- data[$storage_to_grid_col] = $storage_to_grid[idx] || 0
175
- data[$storage_soc_col] = $storage_soc[idx] || 0
176
- data[$generator_total_col] = $generator_total[idx] || 0
177
- data[$generator_to_battery_col] = $generator_to_battery[idx] || 0
178
- data[$generator_to_load_col] = $generator_to_load[idx] || 0
179
- data[$generator_to_grid_col] = $generator_to_grid[idx] || 0
180
- data[$pv_total_col] = $pv_total[idx] || 0
181
- data[$pv_to_battery_col] = $pv_to_battery[idx] || 0
182
- data[$pv_to_load_col] = $pv_to_load[idx] || 0
183
- data[$pv_to_grid_col] = $pv_to_grid[idx] || 0
184
- data[$wind_total_col] = $wind_total[idx] || 0
185
- data[$wind_to_battery_col] = $wind_to_battery[idx] || 0
186
- data[$wind_to_load_col] = $wind_to_load[idx] || 0
187
- data[$wind_to_grid_col] = $wind_to_grid[idx] || 0
188
- return data
189
- end
190
-
191
179
  ##
192
- # Updates a ScenarioReport from a \REopt Lite response
180
+ # Updates a ScenarioReport from a \REopt response
193
181
  #
194
182
  # [*parameters:*]
195
183
  #
196
- # * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to update from a \REopt Lite response.
197
- # * +reopt_output+ - _Hash_ - A hash response from the \REopt Lite API.
198
- # * +timeseries_csv_path+ - _String_ - Optional. The path to a file at which new timeseries data will be written. If not provided a file is created based on the run_uuid of the \REopt Lite optimization task.
184
+ # * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to update from a \REopt response.
185
+ # * +reopt_output+ - _Hash_ - A hash response from the \REopt API.
186
+ # * +timeseries_csv_path+ - _String_ - Optional. The path to a file at which new timeseries data will be written. If not provided a file is created based on the run_uuid of the \REopt optimization task.
199
187
  #
200
188
  # [*return:*] _URBANopt::Reporting::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
201
189
  ##
202
190
  def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path = nil, resilience_stats = nil)
203
- if reopt_output['outputs']['Scenario']['status'] != 'optimal'
191
+ if reopt_output['status'] != 'optimal'
204
192
  @@logger.info("Warning cannot Feature Report #{scenario_report.name} #{scenario_report.id} - REopt optimization was non-optimal")
205
193
  return scenario_report
206
194
  end
207
195
 
208
196
  # Update location
209
- scenario_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
210
- scenario_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
197
+ scenario_report.location.latitude_deg = reopt_output['inputs']['Site']['latitude']
198
+ scenario_report.location.longitude_deg = reopt_output['inputs']['Site']['longitude']
211
199
 
212
200
  # Update distributed generation sizing and financials
213
- scenario_report.distributed_generation.annual_renewable_electricity_pct = reopt_output['outputs']['Scenario']['Site']['annual_renewable_electricity_pct'] || 0
214
- scenario_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
215
- scenario_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
216
- scenario_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
217
- scenario_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
218
- scenario_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
219
- scenario_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
220
- scenario_report.distributed_generation.total_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_us_dollars'] || 0
221
- scenario_report.distributed_generation.year_one_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_bau_us_dollars'] || 0
222
- scenario_report.distributed_generation.year_one_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_bau_us_dollars'] || 0
223
- scenario_report.distributed_generation.year_one_bill_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_bau_us_dollars'] || 0
224
- scenario_report.distributed_generation.total_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_bau_us_dollars'] || 0
225
- scenario_report.distributed_generation.total_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_bau_us_dollars'] || 0
201
+ scenario_report.distributed_generation.renewable_electricity_fraction = reopt_output['outputs']['Site']['renewable_electricity_fraction'] || 0
202
+ scenario_report.distributed_generation.lcc = reopt_output['outputs']['Financial']['lcc'] || 0
203
+ scenario_report.distributed_generation.npv = reopt_output['outputs']['Financial']['npv'] || 0
204
+ scenario_report.distributed_generation.year_one_energy_cost_before_tax = reopt_output['outputs']['ElectricTariff']['year_one_energy_cost_before_tax'] || 0
205
+ scenario_report.distributed_generation.year_one_demand_cost_before_tax = reopt_output['outputs']['ElectricTariff']['year_one_demand_cost_before_tax'] || 0
206
+ scenario_report.distributed_generation.year_one_bill_before_tax = reopt_output['outputs']['ElectricTariff']['year_one_bill_before_tax'] || 0
207
+ scenario_report.distributed_generation.lifecycle_energy_cost_after_tax = reopt_output['outputs']['ElectricTariff']['lifecycle_energy_cost_after_tax'] || 0
208
+ scenario_report.distributed_generation.lifecycle_demand_cost_after_tax = reopt_output['outputs']['ElectricTariff']['lifecycle_demand_cost_after_tax'] || 0
209
+ scenario_report.distributed_generation.year_one_energy_cost_before_tax_bau = reopt_output['outputs']['ElectricTariff']['year_one_energy_cost_before_tax_bau'] || 0
210
+ scenario_report.distributed_generation.year_one_demand_cost_before_tax_bau = reopt_output['outputs']['ElectricTariff']['year_one_demand_cost_before_tax_bau'] || 0
211
+ scenario_report.distributed_generation.year_one_bill_before_tax_bau = reopt_output['outputs']['ElectricTariff']['year_one_bill_before_tax_bau'] || 0
212
+ scenario_report.distributed_generation.lifecycle_demand_cost_after_tax_bau = reopt_output['outputs']['ElectricTariff']['lifecycle_demand_cost_after_tax_bau'] || 0
213
+ scenario_report.distributed_generation.lifecycle_energy_cost_after_tax_bau = reopt_output['outputs']['ElectricTariff']['lifecycle_energy_cost_after_tax_bau'] || 0
226
214
  if !resilience_stats.nil?
227
215
  scenario_report.distributed_generation.resilience_hours_min = resilience_stats['resilience_hours_min']
228
216
  scenario_report.distributed_generation.resilience_hours_max = resilience_stats['resilience_hours_max']
@@ -232,10 +220,10 @@ module URBANopt # :nodoc:
232
220
  scenario_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
233
221
  end
234
222
 
235
- if reopt_output['outputs']['Scenario']['Site']['PV'].instance_of?(Hash)
236
- reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
237
- elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
238
- reopt_output['outputs']['Scenario']['Site']['PV'] = []
223
+ if reopt_output['outputs']['PV'].is_a?(Hash)
224
+ reopt_output['outputs']['PV'] = [reopt_output['outputs']['PV']]
225
+ elsif reopt_output['outputs']['PV'].nil?
226
+ reopt_output['outputs']['PV'] = []
239
227
  end
240
228
 
241
229
  # Store the PV name and location in a hash
@@ -245,81 +233,85 @@ module URBANopt # :nodoc:
245
233
  module_type = {}
246
234
  gcr = {}
247
235
  # Check whether multi PV assumption input file is used or single PV
248
- if reopt_output['inputs']['Scenario']['Site']['PV'].is_a?(Array)
249
- reopt_output['inputs']['Scenario']['Site']['PV'].each do |pv|
250
- location[pv['pv_name']] = pv['location']
251
- azimuth[pv['pv_name']] = pv['azimuth']
252
- tilt[pv['pv_name']] = pv['tilt']
253
- module_type[pv['pv_name']] = pv['module_type']
254
- gcr[pv['pv_name']] = pv['gcr']
255
- end
256
- else
257
- location[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['location']
258
- azimuth[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['azimuth']
259
- tilt[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['tilt']
260
- module_type[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['module_type']
261
- gcr[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['gcr']
262
- end
263
- pv_inputs = reopt_output['inputs']['Scenario']['Site']['PV']
264
- if pv_inputs.is_a?(Hash)
265
- pv_inputs = [pv_inputs]
266
- end
267
- pv_outputs = reopt_output['outputs']['Scenario']['Site']['PV']
268
- if pv_outputs.is_a?(Hash)
269
- pv_outputs = [pv_outputs]
270
- end
271
- pv_outputs.each_with_index do |pv, i|
272
- if pv_inputs[i]
273
- if pv_inputs[i]['tilt']
274
- tilt[pv['pv_name']] = pv_inputs[i]['tilt']
275
- end
276
- if pv_inputs[i]['azimuth']
277
- azimuth[pv['pv_name']] = pv_inputs[i]['azimuth']
236
+ if reopt_output['inputs'].key?('PV')
237
+ if reopt_output['inputs']['PV'].is_a?(Array)
238
+ reopt_output['inputs']['PV'].each do |pv|
239
+ location[pv['name']] = pv['location']
240
+ azimuth[pv['name']] = pv['azimuth']
241
+ tilt[pv['name']] = pv['tilt']
242
+ module_type[pv['name']] = pv['module_type']
243
+ gcr[pv['name']] = pv['gcr']
278
244
  end
279
- if pv_inputs[i]['module_type']
280
- module_type[pv['pv_name']] = pv_inputs[i]['module_type']
245
+ else
246
+ location[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['location']
247
+ azimuth[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['azimuth']
248
+ tilt[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['tilt']
249
+ module_type[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['module_type']
250
+ gcr[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['gcr']
251
+ end
252
+ pv_inputs = reopt_output['inputs']['PV']
253
+ if pv_inputs.is_a?(Hash)
254
+ pv_inputs = [pv_inputs]
255
+ end
256
+ pv_outputs = reopt_output['outputs']['PV']
257
+ if pv_outputs.is_a?(Hash)
258
+ pv_outputs = [pv_outputs]
259
+ end
260
+ pv_outputs.each_with_index do |pv, i|
261
+ if pv_inputs[i]
262
+ if pv_inputs[i]['tilt']
263
+ tilt[pv['name']] = pv_inputs[i]['tilt']
264
+ end
265
+ if pv_inputs[i]['azimuth']
266
+ azimuth[pv['name']] = pv_inputs[i]['azimuth']
267
+ end
268
+ if pv_inputs[i]['module_type']
269
+ module_type[pv['name']] = pv_inputs[i]['module_type']
270
+ end
281
271
  end
272
+ scenario_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new({ size_kw: (pv['size_kw'] || 0), id: i, location: location[pv['name']], average_yearly_energy_produced_kwh: pv['average_yearly_energy_produced_kwh'], azimuth: azimuth[pv['name']], tilt: tilt[pv['name']], module_type: module_type[pv['name']], gcr: gcr[pv['name']] })
282
273
  end
283
- scenario_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new({ size_kw: (pv['size_kw'] || 0), id: i, location: location[pv['pv_name']], average_yearly_energy_produced_kwh: pv['average_yearly_energy_produced_kwh'], azimuth: azimuth[pv['pv_name']], tilt: tilt[pv['pv_name']], module_type: module_type[pv['pv_name']], gcr: gcr[pv['pv_name']] })
284
274
  end
285
275
 
286
- wind = reopt_output['outputs']['Scenario']['Site']['Wind']
287
- if !wind['size_kw'].nil? && (wind['size_kw'] != 0)
276
+ if reopt_output['outputs'].key?('Wind')
277
+ wind = reopt_output['outputs']['Wind']
288
278
  # find size_class
289
279
  size_class = nil
290
- if reopt_output['inputs']['Scenario']['Site']['Wind']['size_class']
291
- size_class = reopt_output['inputs']['Scenario']['Site']['Wind']['size_class']
280
+ if reopt_output['inputs']['Wind']['size_class']
281
+ size_class = reopt_output['inputs']['Wind']['size_class']
292
282
  else
293
283
  size_class = 'commercial' # default
294
284
  end
295
285
  scenario_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new({ size_kw: (wind['size_kw'] || 0), size_class: size_class, average_yearly_energy_produced_kwh: (wind['average_yearly_energy_produced_kwh'] || 0) })
296
286
  end
297
287
 
298
- generator = reopt_output['outputs']['Scenario']['Site']['Generator']
299
- if !generator['size_kw'].nil? && (generator['size_kw'] != 0)
288
+ if reopt_output['outputs'].key?('Generator')
289
+ generator = reopt_output['outputs']['Generator']
300
290
  scenario_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new({ size_kw: (generator['size_kw'] || 0) })
301
291
  end
302
292
 
303
- storage = reopt_output['outputs']['Scenario']['Site']['Storage']
304
- if !storage['size_kw'].nil? && (storage['size_kw'] != 0)
293
+ if reopt_output['outputs'].key?('ElectricStorage')
294
+ storage = reopt_output['outputs']['ElectricStorage']
305
295
  scenario_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new({ size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
306
296
  end
307
297
 
308
- reopt_resolution = reopt_output['inputs']['Scenario']['time_steps_per_hour']
298
+ reopt_resolution = reopt_output['inputs']['Settings']['time_steps_per_hour']
309
299
  generation_timeseries_kwh = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
310
300
 
311
- reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
312
- if (pv['size_kw'] || 0) > 0 && !pv['year_one_power_production_series_kw'].nil?
313
- generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
301
+ if reopt_output['outputs'].key?('PV') && !reopt_output['outputs']['PV'].nil?
302
+ reopt_output['outputs']['PV'].each do |pv|
303
+ if (pv['size_kw'] || 0) > 0 && !pv['year_one_power_production_series_kw'].nil?
304
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
305
+ end
314
306
  end
315
307
  end
316
308
 
317
- if !reopt_output['outputs']['Scenario']['Site']['Wind'].nil? && ((reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0) && !reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'].nil?
318
- generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
309
+ if reopt_output['outputs'].key?('Wind') && !reopt_output['outputs']['Wind'].nil? && ((reopt_output['outputs']['Wind']['size_kw'] || 0) > 0) && !reopt_output['outputs']['Wind']['year_one_power_production_series_kw'].nil?
310
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Wind']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
319
311
  end
320
312
 
321
- if !reopt_output['outputs']['Scenario']['Site']['Generator'].nil? && ((reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0) > 0) && !reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'].nil?
322
- generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
313
+ if reopt_output['outputs'].key?('Generator') && !reopt_output['outputs']['Generator'].nil? && ((reopt_output['outputs']['Generator']['size_kw'] || 0) > 0) && !reopt_output['outputs']['Generator']['year_one_power_production_series_kw'].nil?
314
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Generator']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
323
315
  end
324
316
 
325
317
  $generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * (8760 * scenario_report.timesteps_per_hour)
@@ -329,145 +321,188 @@ module URBANopt # :nodoc:
329
321
  scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
330
322
  end
331
323
 
332
- $load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
324
+ $load = convert_powerflow_resolution(reopt_output['outputs']['ElectricLoad']['year_one_electric_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
333
325
  $load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
334
326
  if $load_col.nil?
335
327
  $load_col = scenario_report.timeseries_csv.column_names.length
336
328
  scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
337
329
  end
338
330
 
339
- $utility_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
331
+ $utility_to_load = convert_powerflow_resolution(reopt_output['outputs']['ElectricUtility']['electric_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
340
332
  $utility_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
341
333
  if $utility_to_load_col.nil?
342
334
  $utility_to_load_col = scenario_report.timeseries_csv.column_names.length
343
335
  scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
344
336
  end
345
337
 
346
- $utility_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
347
- $utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
348
- if $utility_to_battery_col.nil?
349
- $utility_to_battery_col = scenario_report.timeseries_csv.column_names.length
350
- scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
351
- end
338
+ if !storage.nil?
339
+ $utility_to_battery = convert_powerflow_resolution(reopt_output['outputs']['ElectricUtility']['electric_to_storage_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
340
+ $utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
341
+ if $utility_to_battery_col.nil?
342
+ $utility_to_battery_col = scenario_report.timeseries_csv.column_names.length
343
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
344
+ end
352
345
 
353
- $storage_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
354
- $storage_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
355
- if $storage_to_load_col.nil?
356
- $storage_to_load_col = scenario_report.timeseries_csv.column_names.length
357
- scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
358
- end
346
+ $storage_to_load = convert_powerflow_resolution(reopt_output['outputs']['ElectricStorage']['storage_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
347
+ $storage_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
348
+ if $storage_to_load_col.nil?
349
+ $storage_to_load_col = scenario_report.timeseries_csv.column_names.length
350
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
351
+ end
359
352
 
360
- $storage_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
361
- $storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
362
- if $storage_to_grid_col.nil?
363
- $storage_to_grid_col = scenario_report.timeseries_csv.column_names.length
364
- scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
365
- end
353
+ $storage_to_grid = convert_powerflow_resolution(reopt_output['outputs']['ElectricStorage']['electric_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
354
+ $storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
355
+ if $storage_to_grid_col.nil?
356
+ $storage_to_grid_col = scenario_report.timeseries_csv.column_names.length
357
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
358
+ end
366
359
 
367
- $storage_soc = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
368
- $storage_soc_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
369
- if $storage_soc_col.nil?
370
- $storage_soc_col = scenario_report.timeseries_csv.column_names.length
371
- scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
360
+ $storage_soc = convert_powerflow_resolution(reopt_output['outputs']['ElectricStorage']['soc_series_fraction'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
361
+ $storage_soc_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
362
+ if $storage_soc_col.nil?
363
+ $storage_soc_col = scenario_report.timeseries_csv.column_names.length
364
+ scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
365
+ end
372
366
  end
373
367
 
374
- $generator_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
375
- $generator_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
376
- if $generator_total_col.nil?
377
- $generator_total_col = scenario_report.timeseries_csv.column_names.length
378
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
379
- end
368
+ if !generator.nil?
369
+ # $generator_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
370
+ $generator_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
371
+ if $generator_total_col.nil?
372
+ $generator_total_col = scenario_report.timeseries_csv.column_names.length
373
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
374
+ end
380
375
 
381
- $generator_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
382
- $generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
383
- if $generator_to_battery_col.nil?
384
- $generator_to_battery_col = scenario_report.timeseries_csv.column_names.length
385
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
386
- end
376
+ if !storage.nil?
377
+ $generator_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Generator']['electric_to_storage_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
378
+ $generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
379
+ if $generator_to_battery_col.nil?
380
+ $generator_to_battery_col = scenario_report.timeseries_csv.column_names.length
381
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
382
+ end
383
+ end
387
384
 
388
- $generator_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
389
- $generator_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
390
- if $generator_to_load_col.nil?
391
- $generator_to_load_col = scenario_report.timeseries_csv.column_names.length
392
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
393
- end
385
+ $generator_to_load = convert_powerflow_resolution(reopt_output['outputs']['Generator']['electric_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
386
+ $generator_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
387
+ if $generator_to_load_col.nil?
388
+ $generator_to_load_col = scenario_report.timeseries_csv.column_names.length
389
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
390
+ end
394
391
 
395
- $generator_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
396
- $generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
397
- if $generator_to_grid_col.nil?
398
- $generator_to_grid_col = scenario_report.timeseries_csv.column_names.length
399
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
392
+ $generator_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Generator']['electric_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
393
+ $generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
394
+ if $generator_to_grid_col.nil?
395
+ $generator_to_grid_col = scenario_report.timeseries_csv.column_names.length
396
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
397
+ end
400
398
  end
401
399
 
402
- $pv_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
403
- if $pv_total_col.nil?
404
- $pv_total_col = scenario_report.timeseries_csv.column_names.length
405
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
406
- end
400
+ if reopt_output['outputs'].key?('PV') && !reopt_output['outputs']['PV'].nil?
401
+ $pv_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
402
+ if $pv_total_col.nil?
403
+ $pv_total_col = scenario_report.timeseries_csv.column_names.length
404
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
405
+ end
407
406
 
408
- $pv_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
409
- if $pv_to_battery_col.nil?
410
- $pv_to_battery_col = scenario_report.timeseries_csv.column_names.length
411
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
412
- end
407
+ if !storage.nil?
408
+ $pv_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
409
+ if $pv_to_battery_col.nil?
410
+ $pv_to_battery_col = scenario_report.timeseries_csv.column_names.length
411
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
412
+ end
413
+ end
413
414
 
414
- $pv_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
415
- if $pv_to_load_col.nil?
416
- $pv_to_load_col = scenario_report.timeseries_csv.column_names.length
417
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
418
- end
415
+ $pv_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
416
+ if $pv_to_load_col.nil?
417
+ $pv_to_load_col = scenario_report.timeseries_csv.column_names.length
418
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
419
+ end
419
420
 
420
- $pv_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
421
- if $pv_to_grid_col.nil?
422
- $pv_to_grid_col = scenario_report.timeseries_csv.column_names.length
423
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
424
- end
421
+ $pv_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
422
+ if $pv_to_grid_col.nil?
423
+ $pv_to_grid_col = scenario_report.timeseries_csv.column_names.length
424
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
425
+ end
425
426
 
426
- $pv_total = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
427
- $pv_to_battery = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
428
- $pv_to_load = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
429
- $pv_to_grid = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
430
-
431
- reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
432
- if (pv['size_kw'] || 0) > 0
433
- $pv_total += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
434
- $pv_to_battery += Matrix[convert_powerflow_resolution(pv['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
435
- $pv_to_load += Matrix[convert_powerflow_resolution(pv['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
436
- $pv_to_grid += Matrix[convert_powerflow_resolution(pv['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
427
+ $pv_total = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
428
+ if !storage.nil?
429
+ $pv_to_battery = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
430
+ end
431
+ $pv_to_load = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
432
+ $pv_to_grid = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
433
+
434
+ reopt_output['outputs']['PV'].each_with_index do |pv, i|
435
+ if (pv['size_kw'] || 0) > 0
436
+ # $pv_total += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
437
+ if !storage.nil?
438
+ $pv_to_battery += Matrix[convert_powerflow_resolution(pv['electric_to_storage_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
439
+ end
440
+ $pv_to_load += Matrix[convert_powerflow_resolution(pv['electric_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
441
+ $pv_to_grid += Matrix[convert_powerflow_resolution(pv['electric_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
442
+ end
437
443
  end
444
+
445
+ $pv_total = $pv_total.to_a[0]
446
+ if !storage.nil?
447
+ $pv_to_battery = $pv_to_battery.to_a[0]
448
+ end
449
+ $pv_to_load = $pv_to_load.to_a[0]
450
+ $pv_to_grid = $pv_to_grid.to_a[0]
438
451
  end
439
452
 
440
- $pv_total = $pv_total.to_a[0]
441
- $pv_to_battery = $pv_to_battery.to_a[0]
442
- $pv_to_load = $pv_to_load.to_a[0]
443
- $pv_to_grid = $pv_to_grid.to_a[0]
453
+ if !wind.nil?
454
+ # $wind_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
455
+ $wind_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
456
+ if $wind_total_col.nil?
457
+ $wind_total_col = scenario_report.timeseries_csv.column_names.length
458
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
459
+ end
444
460
 
445
- $wind_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
446
- $wind_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
447
- if $wind_total_col.nil?
448
- $wind_total_col = scenario_report.timeseries_csv.column_names.length
449
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
450
- end
461
+ if !storage.nil?
462
+ $wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_storage_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
463
+ $wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
464
+ if $wind_to_battery_col.nil?
465
+ $wind_to_battery_col = scenario_report.timeseries_csv.column_names.length
466
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
467
+ end
468
+ end
451
469
 
452
- $wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
453
- $wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
454
- if $wind_to_battery_col.nil?
455
- $wind_to_battery_col = scenario_report.timeseries_csv.column_names.length
456
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
457
- end
470
+ $wind_to_load = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
471
+ $wind_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
472
+ if $wind_to_load_col.nil?
473
+ $wind_to_load_col = scenario_report.timeseries_csv.column_names.length
474
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
475
+ end
458
476
 
459
- $wind_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
460
- $wind_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
461
- if $wind_to_load_col.nil?
462
- $wind_to_load_col = scenario_report.timeseries_csv.column_names.length
463
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
477
+ $wind_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
478
+ $wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
479
+ if $wind_to_grid_col.nil?
480
+ $wind_to_grid_col = scenario_report.timeseries_csv.column_names.length
481
+ scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
482
+ end
464
483
  end
465
484
 
466
- $wind_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
467
- $wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
468
- if $wind_to_grid_col.nil?
469
- $wind_to_grid_col = scenario_report.timeseries_csv.column_names.length
470
- scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
485
+ def modrow(data, idx) # :nodoc:
486
+ data[$generation_timeseries_kwh_col] = $generation_timeseries_kwh[idx] || 0
487
+ data[$load_col] = $load[idx] || 0
488
+ data[$utility_to_load_col] = $utility_to_load[idx] || 0
489
+ data[$utility_to_battery_col] = $utility_to_battery[idx] || 0 if defined?(storage)
490
+ data[$storage_to_load_col] = $storage_to_load[idx] || 0 if defined?(storage)
491
+ data[$storage_to_grid_col] = $storage_to_grid[idx] || 0 if defined?(storage)
492
+ data[$storage_soc_col] = $storage_soc[idx] || 0 if defined?(storage)
493
+ data[$generator_total_col] = $generator_total[idx] || 0 if defined?(generator)
494
+ data[$generator_to_battery_col] = $generator_to_battery[idx] || 0 if (defined?(generator) && defined?(storage))
495
+ data[$generator_to_load_col] = $generator_to_load[idx] || 0 if defined?(generator)
496
+ data[$generator_to_grid_col] = $generator_to_grid[idx] || 0 if defined?(generator)
497
+ data[$pv_total_col] = $pv_total[idx] || 0
498
+ data[$pv_to_battery_col] = $pv_to_battery[idx] || 0 if defined?(storage)
499
+ data[$pv_to_load_col] = $pv_to_load[idx] || 0
500
+ data[$pv_to_grid_col] = $pv_to_grid[idx] || 0
501
+ data[$wind_total_col] = $wind_total[idx] || 0 if defined?(wind)
502
+ data[$wind_to_battery_col] = $wind_to_battery[idx] || 0 if (defined?(wind) && defined?(storage))
503
+ data[$wind_to_load_col] = $wind_to_load[idx] || 0 if defined?(wind)
504
+ data[$wind_to_grid_col] = $wind_to_grid[idx] || 0 if defined?(wind)
505
+ return data
471
506
  end
472
507
 
473
508
  old_data = CSV.open(scenario_report.timeseries_csv.path).read