urbanopt-reopt 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@ module URBANopt # :nodoc:
14
14
  module REopt # :nodoc:
15
15
  class FeatureReportAdapter
16
16
  ##
17
- # FeatureReportAdapter can convert a URBANopt::Reporting::DefaultReports::FeatureReport into a \REopt Lite posts or update a URBANopt::Reporting::DefaultReports::FeatureReport from a \REopt Lite response.
17
+ # FeatureReportAdapter can convert a URBANopt::Reporting::DefaultReports::FeatureReport into a \REopt posts or update a URBANopt::Reporting::DefaultReports::FeatureReport from a \REopt response.
18
18
  ##
19
19
  # [*parameters:*]
20
20
  ##
@@ -24,23 +24,32 @@ module URBANopt # :nodoc:
24
24
  end
25
25
 
26
26
  ##
27
- # Convert a FeatureReport into a \REopt Lite post
27
+ # Convert a FeatureReport into a \REopt post
28
28
  #
29
29
  # [*parameters:*]
30
30
  #
31
- # * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport to use in converting the optional +reopt_assumptions_hash+ to a \REopt Lite post. If a +reopt_assumptions_hash+ is not provided, a default post will be updated from this FeatureReport and submitted to the \REopt Lite API.
32
- # * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt Lite API containing default values. Values will be overwritten from the FeatureReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API.
31
+ # * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport to use in converting the optional +reopt_assumptions_hash+ to a \REopt post. If a +reopt_assumptions_hash+ is not provided, a default post will be updated from this FeatureReport and submitted to the \REopt API.
32
+ # * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt API containing default values. Values will be overwritten from the FeatureReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API.
33
33
  #
34
- # [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt Lite API
34
+ # [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt API
35
35
  ##
36
36
  def reopt_json_from_feature_report(feature_report, reopt_assumptions_hash = nil, groundmount_photovoltaic = nil)
37
37
  name = feature_report.name.delete ' '
38
38
  description = "feature_report_#{name}_#{feature_report.id}"
39
- 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
39
  if !reopt_assumptions_hash.nil?
41
40
  reopt_inputs = reopt_assumptions_hash
42
41
  else
43
- @@logger.info('Using default REopt Lite assumptions')
42
+ @@logger.info('Using default REopt assumptions')
43
+ reopt_inputs = {
44
+ Settings:{},
45
+ Site: {},
46
+ Financial:{},
47
+ ElectricTariff: {
48
+ monthly_demand_rates: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
49
+ 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]
50
+ },
51
+ ElectricLoad: {}
52
+ }
44
53
  end
45
54
 
46
55
  # Check FeatureReport has required data
@@ -57,33 +66,33 @@ module URBANopt # :nodoc:
57
66
  end
58
67
  end
59
68
 
60
- reopt_inputs[:Scenario][:description] = description
69
+ reopt_inputs[:description] = description
61
70
 
62
71
  # Parse Location
63
- reopt_inputs[:Scenario][:Site][:latitude] = feature_report.location.latitude_deg
64
- reopt_inputs[:Scenario][:Site][:longitude] = feature_report.location.longitude_deg
72
+ reopt_inputs[:Site][:latitude] = feature_report.location.latitude_deg
73
+ reopt_inputs[:Site][:longitude] = feature_report.location.longitude_deg
65
74
 
66
75
  # Parse Optional FeatureReport metrics - do not overwrite from assumptions file
67
- if reopt_inputs[:Scenario][:Site][:roof_squarefeet].nil? && !feature_report.program.roof_area_sqft.nil?
68
- reopt_inputs[:Scenario][:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area_sqft]
76
+ if reopt_inputs[:Site][:roof_squarefeet].nil? && !feature_report.program.roof_area_sqft.nil?
77
+ reopt_inputs[:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area_sqft]
69
78
  end
70
79
 
71
- if reopt_inputs[:Scenario][:Site][:land_acres].nil?
80
+ if reopt_inputs[:Site][:land_acres].nil?
72
81
  # Check if ground-mount PV is specified with the Feature ID and take footprint area of PV
73
82
  # constrain for REopt optimization
74
83
  begin
75
84
  if !groundmount_photovoltaic[feature_report.id].nil?
76
- reopt_inputs[:Scenario][:Site][:land_acres] = groundmount_photovoltaic[feature_report.id] * 1.0 / 43560 # acres/sqft
85
+ reopt_inputs[:Site][:land_acres] = groundmount_photovoltaic[feature_report.id] * 1.0 / 43560 # acres/sqft
77
86
  # If no ground-mount PV associated with feature use site area as constrain for REopt optimization
78
87
  elsif !feature_report.program.site_area_sqft.nil?
79
- reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
88
+ reopt_inputs[:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
80
89
  end
81
90
  rescue StandardError
82
91
  end
83
92
  end
84
93
 
85
- if reopt_inputs[:Scenario][:time_steps_per_hour].nil?
86
- reopt_inputs[:Scenario][:time_steps_per_hour] = 1
94
+ if reopt_inputs[:Settings][:time_steps_per_hour].nil?
95
+ reopt_inputs[:Settings][:time_steps_per_hour] = 1
87
96
  end
88
97
 
89
98
  # Parse Load Profile
@@ -104,7 +113,7 @@ module URBANopt # :nodoc:
104
113
  end
105
114
  # Clip to one non-leap year's worth of data
106
115
  energy_timeseries_kw = energy_timeseries_kw.map { |e| e || 0 }[0, (feature_report.timesteps_per_hour * 8760)]
107
- # Convert from the OpenDSS resolution to the REopt Lite resolution, if necessary
116
+ # Convert from the OpenDSS resolution to the REopt resolution, if necessary
108
117
  rescue StandardError
109
118
  @@logger.error("Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}")
110
119
  raise "Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}"
@@ -112,65 +121,68 @@ module URBANopt # :nodoc:
112
121
 
113
122
  # Convert load to REopt Resolution
114
123
  begin
115
- reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, feature_report.timesteps_per_hour, reopt_inputs[:Scenario][:time_steps_per_hour])
124
+ reopt_inputs[:ElectricLoad][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, feature_report.timesteps_per_hour, reopt_inputs[:Settings][:time_steps_per_hour])
116
125
  rescue StandardError
117
- @@logger.error("Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}")
118
- raise "Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}"
119
- end
120
-
121
- if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps].nil?
122
- n_top_values = 100
123
- tmp1 = reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw]
124
- tmp2 = tmp1.each_index.max_by(n_top_values * reopt_inputs[:Scenario][:time_steps_per_hour]) { |i| tmp1[i] }
125
- for i in (0...tmp2.count)
126
- tmp2[i] += 1
127
- end
128
- reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps] = tmp2
129
- end
130
-
131
- if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw].nil?
132
- reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw] = 0
133
- end
126
+ @@logger.error("Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Settings][:time_steps_per_hour]}")
127
+ raise "Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Settings][:time_steps_per_hour]}"
128
+ end
129
+
130
+ # TODO: Restore coincident_peak stuff here and in Scenario Report adapter
131
+ # if reopt_inputs[:ElectricTariff][:coincident_peak_load_active_time_steps].nil?
132
+ # n_top_values = 100
133
+ # tmp1 = reopt_inputs[:ElectricLoad][:loads_kw]
134
+ # tmp2 = tmp1.each_index.max_by(n_top_values * reopt_inputs[:Settings][:time_steps_per_hour]) { |i| tmp1[i] }
135
+ # for i in (0...tmp2.count)
136
+ # tmp2[i] += 1
137
+ # end
138
+ # # this needs to be a 2D array
139
+ # reopt_inputs[:ElectricTariff][:coincident_peak_load_active_time_steps] = [tmp2]
140
+ # end
141
+
142
+ # if reopt_inputs[:ElectricTariff][:coincident_peak_load_charge_per_kw].nil?
143
+ # reopt_inputs[:ElectricTariff][:coincident_peak_load_charge_per_kw] = 0
144
+ # end
134
145
 
135
146
  return reopt_inputs
136
147
  end
137
148
 
138
149
  ##
139
- # Update a FeatureReport from a \REopt Lite response
150
+ # Update a FeatureReport from a \REopt response
140
151
  #
141
152
  # [*parameters:*]
142
153
  #
143
- # * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport to update from a \REopt Lite reponse hash.
144
- # * +reopt_output+ - _Hash_ - A reponse hash from the \REopt Lite API to use in overwriting FeatureReport technology sizes, costs and dispatch strategies.
145
- # * +timeseries_csv_path+ - _String_ - Optional. The path to a file at which a new timeseries CSV will be written. If not provided a file is created based on the run_uuid of the \REopt Lite optimization task.
154
+ # * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport to update from a \REopt reponse hash.
155
+ # * +reopt_output+ - _Hash_ - A reponse hash from the \REopt API to use in overwriting FeatureReport technology sizes, costs and dispatch strategies.
156
+ # * +timeseries_csv_path+ - _String_ - Optional. The path to a file at which a new timeseries CSV will be written. If not provided a file is created based on the run_uuid of the \REopt optimization task.
146
157
  #
147
158
  # [*return:*] _URBANopt::Reporting::DefaultReports::FeatureReport_ - Returns an updated FeatureReport.
148
159
  ##
149
160
  def update_feature_report(feature_report, reopt_output, timeseries_csv_path = nil, resilience_stats = nil)
150
- # Check if the \REopt Lite response is valid
151
- if reopt_output['outputs']['Scenario']['status'] != 'optimal'
152
- @@logger.info("Warning cannot Feature Report #{feature_report.name} #{feature_report.id} - REopt optimization was non-optimal")
161
+
162
+ # Check if the \REopt response is valid
163
+ if reopt_output['status'] != 'optimal'
164
+ @@logger.error("ERROR cannot update Feature Report #{feature_report.name} #{feature_report.id} - REopt optimization was non-optimal")
153
165
  return feature_report
154
166
  end
155
167
 
156
168
  # Update location
157
- feature_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
158
- feature_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
169
+ feature_report.location.latitude_deg = reopt_output['inputs']['Site']['latitude']
170
+ feature_report.location.longitude_deg = reopt_output['inputs']['Site']['longitude']
159
171
 
160
172
  # Update distributed generation sizing and financials
161
- feature_report.distributed_generation.annual_renewable_electricity_pct = reopt_output['outputs']['Scenario']['Site']['annual_renewable_electricity_pct'] || 0
162
- feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
163
- feature_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
164
- feature_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
165
- feature_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
166
- feature_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
167
- feature_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
168
- feature_report.distributed_generation.total_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_us_dollars'] || 0
169
- feature_report.distributed_generation.year_one_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_bau_us_dollars'] || 0
170
- feature_report.distributed_generation.year_one_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_bau_us_dollars'] || 0
171
- feature_report.distributed_generation.year_one_bill_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_bau_us_dollars'] || 0
172
- feature_report.distributed_generation.total_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_bau_us_dollars'] || 0
173
- feature_report.distributed_generation.total_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_bau_us_dollars'] || 0
173
+ feature_report.distributed_generation.renewable_electricity_fraction = reopt_output['outputs']['Site']['renewable_electricity_fraction'] || 0
174
+ feature_report.distributed_generation.lcc = reopt_output['outputs']['Financial']['lcc'] || 0
175
+ feature_report.distributed_generation.npv = reopt_output['outputs']['Financial']['npv'] || 0
176
+ feature_report.distributed_generation.year_one_energy_cost_before_tax = reopt_output['outputs']['ElectricTariff']['year_one_energy_cost_before_tax'] || 0
177
+ feature_report.distributed_generation.year_one_demand_cost_before_tax = reopt_output['outputs']['ElectricTariff']['year_one_demand_cost_before_tax'] || 0
178
+ feature_report.distributed_generation.year_one_bill_before_tax = reopt_output['outputs']['ElectricTariff']['year_one_bill_before_tax'] || 0
179
+ feature_report.distributed_generation.lifecycle_energy_cost_after_tax = reopt_output['outputs']['ElectricTariff']['lifecycle_energy_cost_after_tax'] || 0
180
+ feature_report.distributed_generation.lifecycle_demand_cost_after_tax = reopt_output['outputs']['ElectricTariff']['lifecycle_demand_cost_after_tax'] || 0
181
+ feature_report.distributed_generation.year_one_energy_cost_before_tax_bau = reopt_output['outputs']['ElectricTariff']['year_one_energy_cost_before_tax_bau'] || 0
182
+ feature_report.distributed_generation.year_one_demand_cost_before_tax_bau = reopt_output['outputs']['ElectricTariff']['year_one_demand_cost_before_tax_bau'] || 0
183
+ feature_report.distributed_generation.year_one_bill_before_tax_bau = reopt_output['outputs']['ElectricTariff']['year_one_bill_before_tax_bau'] || 0
184
+ feature_report.distributed_generation.lifecycle_demand_cost_after_tax_bau = reopt_output['outputs']['ElectricTariff']['lifecycle_demand_cost_after_tax_bau'] || 0
185
+ feature_report.distributed_generation.lifecycle_energy_cost_after_tax_bau = reopt_output['outputs']['ElectricTariff']['lifecycle_energy_cost_after_tax_bau'] || 0
174
186
  if !resilience_stats.nil?
175
187
  feature_report.distributed_generation.resilience_hours_min = resilience_stats['resilience_hours_min']
176
188
  feature_report.distributed_generation.resilience_hours_max = resilience_stats['resilience_hours_max']
@@ -180,10 +192,10 @@ module URBANopt # :nodoc:
180
192
  feature_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
181
193
  end
182
194
 
183
- if reopt_output['outputs']['Scenario']['Site']['PV'].instance_of?(Hash)
184
- reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
185
- elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
186
- reopt_output['outputs']['Scenario']['Site']['PV'] = []
195
+ if reopt_output['outputs']['PV'].is_a?(Hash)
196
+ reopt_output['outputs']['PV'] = [reopt_output['outputs']['PV']]
197
+ elsif reopt_output['outputs']['PV'].nil?
198
+ reopt_output['outputs']['PV'] = []
187
199
  end
188
200
 
189
201
  # Store the PV name and location in a hash
@@ -194,58 +206,60 @@ module URBANopt # :nodoc:
194
206
  gcr = {}
195
207
 
196
208
  # Check whether multi PV assumption input file is used or single PV
197
- if reopt_output['inputs']['Scenario']['Site']['PV'].is_a?(Array)
198
- reopt_output['inputs']['Scenario']['Site']['PV'].each do |pv|
199
- location[pv['pv_name']] = pv['location']
200
- azimuth[pv['pv_name']] = pv['azimuth']
201
- tilt[pv['pv_name']] = pv['tilt']
202
- module_type[pv['pv_name']] = pv['module_type']
203
- gcr[pv['pv_name']] = pv['gcr']
209
+ if reopt_output['inputs'].key?('PV')
210
+ if reopt_output['inputs']['PV'].is_a?(Array)
211
+ reopt_output['inputs']['PV'].each do |pv|
212
+ location[pv['name']] = pv['location']
213
+ azimuth[pv['name']] = pv['azimuth']
214
+ tilt[pv['name']] = pv['tilt']
215
+ module_type[pv['name']] = pv['module_type']
216
+ gcr[pv['name']] = pv['gcr']
217
+ end
218
+ else
219
+ location[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['location']
220
+ azimuth[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['azimuth']
221
+ tilt[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['tilt']
222
+ module_type[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['module_type']
223
+ gcr[reopt_output['inputs']['PV']['name']] = reopt_output['inputs']['PV']['gcr']
204
224
  end
205
- else
206
- location[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['location']
207
- azimuth[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['azimuth']
208
- tilt[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['tilt']
209
- module_type[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['module_type']
210
- gcr[reopt_output['inputs']['Scenario']['Site']['PV']['pv_name']] = reopt_output['inputs']['Scenario']['Site']['PV']['gcr']
211
- end
212
225
 
213
- reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
214
- feature_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']] })
226
+ reopt_output['outputs']['PV'].each_with_index do |pv, i|
227
+ feature_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['annual_energy_produced_kwh'], azimuth: azimuth[pv['name']], tilt: tilt[pv['name']], module_type: module_type[pv['name']], gcr: gcr[pv['name']] })
228
+ end
215
229
  end
216
230
 
217
- wind = reopt_output['outputs']['Scenario']['Site']['Wind']
218
- if !wind['size_kw'].nil? && (wind['size_kw'] != 0)
231
+ if reopt_output['outputs'].key?('Wind')
232
+ wind = reopt_output['outputs']['Wind']
219
233
  feature_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new({ size_kw: (wind['size_kw'] || 0) })
220
234
  end
221
235
 
222
- generator = reopt_output['outputs']['Scenario']['Site']['Generator']
223
- if !generator['size_kw'].nil? && (generator['size_kw'] != 0)
236
+ if reopt_output['outputs'].key?('Generator')
237
+ generator = reopt_output['outputs']['Generator']
224
238
  feature_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new({ size_kw: (generator['size_kw'] || 0) })
225
239
  end
226
240
 
227
- storage = reopt_output['outputs']['Scenario']['Site']['Storage']
228
- if !storage['size_kw'].nil? && (storage['size_kw'] != 0)
241
+ if reopt_output['outputs'].key?('ElectricStorage')
242
+ storage = reopt_output['outputs']['ElectricStorage']
229
243
  feature_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new({ size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
230
244
  end
231
245
 
232
246
  generation_timeseries_kwh = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
233
- reopt_resolution = reopt_output['inputs']['Scenario']['time_steps_per_hour']
247
+ reopt_resolution = reopt_output['inputs']['Settings']['time_steps_per_hour']
234
248
 
235
- unless reopt_output['outputs']['Scenario']['Site']['PV'].nil?
236
- reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
249
+ if reopt_output['outputs'].key?('PV') && !reopt_output['outputs']['PV'].nil?
250
+ reopt_output['outputs']['PV'].each do |pv|
237
251
  if (pv['size_kw'] || 0) > 0 && !pv['year_one_power_production_series_kw'].nil?
238
252
  generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
239
253
  end
240
254
  end
241
255
  end
242
256
 
243
- 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?
244
- generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
257
+ 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?
258
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
245
259
  end
246
260
 
247
- 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?
248
- generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
261
+ 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?
262
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
249
263
  end
250
264
 
251
265
  $generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * (8760 * feature_report.timesteps_per_hour)
@@ -255,167 +269,187 @@ module URBANopt # :nodoc:
255
269
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
256
270
  end
257
271
 
258
- $load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
272
+ $load = convert_powerflow_resolution(reopt_output['outputs']['ElectricLoad']['load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
259
273
  $load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
260
274
  if $load_col.nil?
261
275
  $load_col = feature_report.timeseries_csv.column_names.length
262
276
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
263
277
  end
264
278
 
265
- $utility_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
279
+ $utility_to_load = convert_powerflow_resolution(reopt_output['outputs']['ElectricUtility']['electric_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
266
280
  $utility_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
267
281
  if $utility_to_load_col.nil?
268
282
  $utility_to_load_col = feature_report.timeseries_csv.column_names.length
269
283
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
270
284
  end
271
285
 
272
- $utility_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
273
- $utility_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
274
- if $utility_to_battery_col.nil?
275
- $utility_to_battery_col = feature_report.timeseries_csv.column_names.length
276
- feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
277
- end
286
+ if !storage.nil?
287
+ $utility_to_battery = convert_powerflow_resolution(reopt_output['outputs']['ElectricUtility']['electric_to_storage_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
288
+ $utility_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
289
+ if $utility_to_battery_col.nil?
290
+ $utility_to_battery_col = feature_report.timeseries_csv.column_names.length
291
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
292
+ end
278
293
 
279
- $storage_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
280
- $storage_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
281
- if $storage_to_load_col.nil?
282
- $storage_to_load_col = feature_report.timeseries_csv.column_names.length
283
- feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
284
- end
294
+ $storage_to_load = convert_powerflow_resolution(reopt_output['outputs']['ElectricStorage']['storage_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
295
+ $storage_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
296
+ if $storage_to_load_col.nil?
297
+ $storage_to_load_col = feature_report.timeseries_csv.column_names.length
298
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
299
+ end
285
300
 
286
- $storage_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
287
- $storage_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
288
- if $storage_to_grid_col.nil?
289
- $storage_to_grid_col = feature_report.timeseries_csv.column_names.length
290
- feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
291
- end
301
+ $storage_to_grid = convert_powerflow_resolution(reopt_output['outputs']['ElectricStorage']['electric_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
302
+ $storage_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
303
+ if $storage_to_grid_col.nil?
304
+ $storage_to_grid_col = feature_report.timeseries_csv.column_names.length
305
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
306
+ end
292
307
 
293
- $storage_soc = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
294
- $storage_soc_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
295
- if $storage_soc_col.nil?
296
- $storage_soc_col = feature_report.timeseries_csv.column_names.length
297
- feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
308
+ $storage_soc = convert_powerflow_resolution(reopt_output['outputs']['ElectricStorage']['soc_series_fraction'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
309
+ $storage_soc_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
310
+ if $storage_soc_col.nil?
311
+ $storage_soc_col = feature_report.timeseries_csv.column_names.length
312
+ feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
313
+ end
298
314
  end
299
315
 
300
- $generator_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
301
- $generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
302
- if $generator_total_col.nil?
303
- $generator_total_col = feature_report.timeseries_csv.column_names.length
304
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
305
- end
316
+ if !generator.nil?
317
+ # $generator_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
318
+ $generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
319
+ if $generator_total_col.nil?
320
+ $generator_total_col = feature_report.timeseries_csv.column_names.length
321
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
322
+ end
306
323
 
307
- $generator_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
308
- $generator_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
309
- if $generator_to_battery_col.nil?
310
- $generator_to_battery_col = feature_report.timeseries_csv.column_names.length
311
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
312
- end
324
+ if !storage.nil?
325
+ $generator_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Generator']['electric_to_storage_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
326
+ $generator_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
327
+ if $generator_to_battery_col.nil?
328
+ $generator_to_battery_col = feature_report.timeseries_csv.column_names.length
329
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
330
+ end
331
+ end
313
332
 
314
- $generator_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
315
- $generator_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
316
- if $generator_to_load_col.nil?
317
- $generator_to_load_col = feature_report.timeseries_csv.column_names.length
318
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
319
- end
333
+ $generator_to_load = convert_powerflow_resolution(reopt_output['outputs']['Generator']['electric_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
334
+ $generator_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
335
+ if $generator_to_load_col.nil?
336
+ $generator_to_load_col = feature_report.timeseries_csv.column_names.length
337
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
338
+ end
320
339
 
321
- $generator_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
322
- $generator_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
323
- if $generator_to_grid_col.nil?
324
- $generator_to_grid_col = feature_report.timeseries_csv.column_names.length
325
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
340
+ $generator_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Generator']['electric_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
341
+ $generator_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
342
+ if $generator_to_grid_col.nil?
343
+ $generator_to_grid_col = feature_report.timeseries_csv.column_names.length
344
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
345
+ end
326
346
  end
327
347
 
328
- $pv_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
329
- if $pv_total_col.nil?
330
- $pv_total_col = feature_report.timeseries_csv.column_names.length
331
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
332
- end
348
+ if reopt_output['outputs'].key?('PV') && !reopt_output['outputs']['PV'].nil?
349
+ $pv_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
350
+ if $pv_total_col.nil?
351
+ $pv_total_col = feature_report.timeseries_csv.column_names.length
352
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
353
+ end
333
354
 
334
- $pv_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
335
- if $pv_to_battery_col.nil?
336
- $pv_to_battery_col = feature_report.timeseries_csv.column_names.length
337
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
338
- end
355
+ if !storage.nil?
356
+ $pv_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
357
+ if $pv_to_battery_col.nil?
358
+ $pv_to_battery_col = feature_report.timeseries_csv.column_names.length
359
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
360
+ end
361
+ end
339
362
 
340
- $pv_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
341
- if $pv_to_load_col.nil?
342
- $pv_to_load_col = feature_report.timeseries_csv.column_names.length
343
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
344
- end
363
+ $pv_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
364
+ if $pv_to_load_col.nil?
365
+ $pv_to_load_col = feature_report.timeseries_csv.column_names.length
366
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
367
+ end
345
368
 
346
- $pv_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
347
- if $pv_to_grid_col.nil?
348
- $pv_to_grid_col = feature_report.timeseries_csv.column_names.length
349
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
350
- end
369
+ $pv_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
370
+ if $pv_to_grid_col.nil?
371
+ $pv_to_grid_col = feature_report.timeseries_csv.column_names.length
372
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
373
+ end
351
374
 
352
- $pv_total = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
353
- $pv_to_battery = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
354
- $pv_to_load = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
355
- $pv_to_grid = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
356
-
357
- reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
358
- if (pv['size_kw'] || 0) > 0
359
- $pv_total += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
360
- $pv_to_battery += Matrix[convert_powerflow_resolution(pv['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
361
- $pv_to_load += Matrix[convert_powerflow_resolution(pv['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
362
- $pv_to_grid += Matrix[convert_powerflow_resolution(pv['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
375
+ $pv_total = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
376
+ if !storage.nil?
377
+ $pv_to_battery = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
378
+ end
379
+ $pv_to_load = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
380
+ $pv_to_grid = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
381
+
382
+ reopt_output['outputs']['PV'].each_with_index do |pv, i|
383
+ if (pv['size_kw'] || 0) > 0
384
+ # $pv_total += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
385
+ if !storage.nil?
386
+ $pv_to_battery += Matrix[convert_powerflow_resolution(pv['electric_to_storage_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
387
+ end
388
+ $pv_to_load += Matrix[convert_powerflow_resolution(pv['electric_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
389
+ $pv_to_grid += Matrix[convert_powerflow_resolution(pv['electric_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
390
+ end
363
391
  end
364
- end
365
392
 
366
- $pv_total = $pv_total.to_a[0]
367
- $pv_to_battery = $pv_to_battery.to_a[0]
368
- $pv_to_load = $pv_to_load.to_a[0]
369
- $pv_to_grid = $pv_to_grid.to_a[0]
393
+ $pv_total = $pv_total.to_a[0]
394
+ if !storage.nil?
395
+ $pv_to_battery = $pv_to_battery.to_a[0]
396
+ end
397
+ $pv_to_load = $pv_to_load.to_a[0]
398
+ $pv_to_grid = $pv_to_grid.to_a[0]
399
+ end
370
400
 
371
- $wind_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
401
+ # $wind_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
372
402
  $wind_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
373
403
  if $wind_total_col.nil?
374
404
  $wind_total_col = feature_report.timeseries_csv.column_names.length
375
405
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
376
406
  end
377
407
 
378
- $wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
379
- $wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
380
- if $wind_to_battery_col.nil?
381
- $wind_to_battery_col = feature_report.timeseries_csv.column_names.length
382
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
383
- end
408
+ if !wind.nil?
409
+ if !storage.nil?
410
+ $wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_storage_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
411
+ $wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
412
+ if $wind_to_battery_col.nil?
413
+ $wind_to_battery_col = feature_report.timeseries_csv.column_names.length
414
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
415
+ end
416
+ end
384
417
 
385
- $wind_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
386
- $wind_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
387
- if $wind_to_load_col.nil?
388
- $wind_to_load_col = feature_report.timeseries_csv.column_names.length
389
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
390
- end
418
+ $wind_to_load = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
419
+ $wind_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
420
+ if $wind_to_load_col.nil?
421
+ $wind_to_load_col = feature_report.timeseries_csv.column_names.length
422
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
423
+ end
391
424
 
392
- $wind_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
393
- $wind_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
394
- if $wind_to_grid_col.nil?
395
- $wind_to_grid_col = feature_report.timeseries_csv.column_names.length
396
- feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
425
+ $wind_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
426
+ $wind_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
427
+ if $wind_to_grid_col.nil?
428
+ $wind_to_grid_col = feature_report.timeseries_csv.column_names.length
429
+ feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
430
+ end
397
431
  end
398
432
 
399
433
  def modrow(x, i) # :nodoc:
400
434
  x[$generation_timeseries_kwh_col] = $generation_timeseries_kwh[i] || 0
401
435
  x[$load_col] = $load[i] || 0
402
436
  x[$utility_to_load_col] = $utility_to_load[i] || 0
403
- x[$utility_to_battery_col] = $utility_to_battery[i] || 0
404
- x[$storage_to_load_col] = $storage_to_load[i] || 0
405
- x[$storage_to_grid_col] = $storage_to_grid[i] || 0
406
- x[$storage_soc_col] = $storage_soc[i] || 0
407
- x[$generator_total_col] = $generator_total[i] || 0
408
- x[$generator_to_battery_col] = $generator_to_battery[i] || 0
409
- x[$generator_to_load_col] = $generator_to_load[i] || 0
410
- x[$generator_to_grid_col] = $generator_to_grid[i] || 0
437
+ x[$utility_to_battery_col] = $utility_to_battery[i] || 0 if defined?(storage)
438
+ x[$storage_to_load_col] = $storage_to_load[i] || 0 if defined?(storage)
439
+ x[$storage_to_grid_col] = $storage_to_grid[i] || 0 if defined?(storage)
440
+ x[$storage_soc_col] = $storage_soc[i] || 0 if defined?(storage)
441
+ x[$generator_total_col] = $generator_total[i] || 0 if defined?(generator)
442
+ x[$generator_to_battery_col] = $generator_to_battery[i] || 0 if (defined?(generator) && defined?(storage))
443
+ x[$generator_to_load_col] = $generator_to_load[i] || 0 if defined?(generator)
444
+ x[$generator_to_grid_col] = $generator_to_grid[i] || 0 if defined?(generator)
411
445
  x[$pv_total_col] = $pv_total[i] || 0
412
- x[$pv_to_battery_col] = $pv_to_battery[i] || 0
446
+ x[$pv_to_battery_col] = $pv_to_battery[i] || 0 if defined?(storage)
413
447
  x[$pv_to_load_col] = $pv_to_load[i] || 0
414
448
  x[$pv_to_grid_col] = $pv_to_grid[i] || 0
415
- x[$wind_total_col] = $wind_total[i] || 0
416
- x[$wind_to_battery_col] = $wind_to_battery[i] || 0
417
- x[$wind_to_load_col] = $wind_to_load[i] || 0
418
- x[$wind_to_grid_col] = $wind_to_grid[i] || 0
449
+ x[$wind_total_col] = $wind_total[i] || 0 if defined?(wind)
450
+ x[$wind_to_battery_col] = $wind_to_battery[i] || 0 if (defined?(wind) && defined?(storage))
451
+ x[$wind_to_load_col] = $wind_to_load[i] || 0 if defined?(wind)
452
+ x[$wind_to_grid_col] = $wind_to_grid[i] || 0 if defined?(wind)
419
453
  return x
420
454
  end
421
455
 
@@ -425,8 +459,7 @@ module URBANopt # :nodoc:
425
459
  (
426
460
  ((start_date.yday - 1) * 60.0 * 60.0 * 24) +
427
461
  ((start_date.hour - 1) * 60.0 * 60.0) +
428
- (start_date.min * 60.0) + start_date.sec) /
429
- ((60 / feature_report.timesteps_per_hour) * 60)
462
+ (start_date.min * 60.0) + start_date.sec) / ((60 / feature_report.timesteps_per_hour) * 60)
430
463
  ).to_int
431
464
 
432
465
  mod_data = old_data.map.with_index do |x, i|