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.
- checksums.yaml +4 -4
- data/.github/release.yml +25 -0
- data/.github/workflows/nightly_ci_build.yml +10 -3
- data/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/LICENSE.md +1 -1
- data/RDOC_MAIN.md +19 -19
- data/README.md +20 -20
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/docs/README.md +18 -18
- data/docs/package-lock.json +4806 -4836
- data/docs/schemas/reopt-input-schema.md +25 -23
- data/docs/schemas/reopt-output-schema.md +7 -7
- data/index.md +22 -22
- data/lib/urbanopt/reopt/feature_report_adapter.rb +241 -208
- data/lib/urbanopt/reopt/reopt_lite_api.rb +98 -59
- data/lib/urbanopt/reopt/reopt_post_processor.rb +34 -33
- data/lib/urbanopt/reopt/reopt_schema/reopt_input_schema.json +1126 -1106
- data/lib/urbanopt/reopt/reopt_schema/reopt_output_schema.json +449 -524
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +7 -7
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +275 -240
- data/lib/urbanopt/reopt/version.rb +1 -1
- data/urbanopt-reopt.gemspec +5 -3
- metadata +35 -8
- data/Jenkinsfile +0 -10
@@ -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
|
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
|
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
|
31
|
-
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt
|
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
|
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
|
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
|
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[:
|
88
|
+
reopt_inputs[:description] = description
|
80
89
|
|
81
|
-
reopt_inputs[:
|
82
|
-
reopt_inputs[:
|
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[:
|
87
|
-
reopt_inputs[:
|
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[:
|
92
|
-
reopt_inputs[:
|
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[:
|
98
|
-
reopt_inputs[:
|
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[:
|
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[:
|
126
|
-
raise "Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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
|
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
|
152
|
-
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of hashes formatted for submittal to the \REopt
|
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
|
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
|
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
|
197
|
-
# * +reopt_output+ - _Hash_ - A hash response from the \REopt
|
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
|
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['
|
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']['
|
210
|
-
scenario_report.location.longitude_deg = reopt_output['inputs']['
|
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.
|
214
|
-
scenario_report.distributed_generation.
|
215
|
-
scenario_report.distributed_generation.
|
216
|
-
scenario_report.distributed_generation.
|
217
|
-
scenario_report.distributed_generation.
|
218
|
-
scenario_report.distributed_generation.
|
219
|
-
scenario_report.distributed_generation.
|
220
|
-
scenario_report.distributed_generation.
|
221
|
-
scenario_report.distributed_generation.
|
222
|
-
scenario_report.distributed_generation.
|
223
|
-
scenario_report.distributed_generation.
|
224
|
-
scenario_report.distributed_generation.
|
225
|
-
scenario_report.distributed_generation.
|
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']['
|
236
|
-
reopt_output['outputs']['
|
237
|
-
elsif reopt_output['outputs']['
|
238
|
-
reopt_output['outputs']['
|
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']
|
249
|
-
reopt_output['inputs']['
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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
|
-
|
280
|
-
|
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
|
-
|
287
|
-
|
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']['
|
291
|
-
size_class = reopt_output['inputs']['
|
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
|
-
|
299
|
-
|
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
|
-
|
304
|
-
|
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']['
|
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']
|
312
|
-
|
313
|
-
|
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
|
318
|
-
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['
|
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
|
322
|
-
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['
|
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']['
|
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']['
|
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
|
-
|
347
|
-
|
348
|
-
|
349
|
-
$utility_to_battery_col
|
350
|
-
|
351
|
-
|
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
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
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
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
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
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
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
|
-
|
375
|
-
|
376
|
-
|
377
|
-
$generator_total_col
|
378
|
-
|
379
|
-
|
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
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
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
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
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
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
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
|
-
|
403
|
-
|
404
|
-
$pv_total_col
|
405
|
-
|
406
|
-
|
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
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
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
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
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
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
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
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
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
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
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
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
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
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
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
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
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
|
-
|
467
|
-
|
468
|
-
|
469
|
-
$
|
470
|
-
|
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
|