urbanopt-reopt 0.1.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- data/.github/pull_request_template.md +13 -0
- data/.gitignore +6 -1
- data/.rdoc_options +1 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +39 -0
- data/CONTRIBUTING.md +58 -0
- data/Gemfile +14 -19
- data/LICENSE.md +1 -1
- data/RDOC_MAIN.md +13 -13
- data/README.md +15 -15
- data/Rakefile +31 -1
- data/a.txt +1 -0
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/docs/README.md +16 -16
- data/index.md +13 -13
- data/lib/urbanopt-reopt.rb +1 -1
- data/lib/urbanopt/reopt.rb +1 -1
- data/lib/urbanopt/reopt/extension.rb +1 -1
- data/lib/urbanopt/reopt/feature_report_adapter.rb +179 -99
- data/lib/urbanopt/reopt/reopt_lite_api.rb +132 -13
- data/lib/urbanopt/reopt/reopt_logger.rb +1 -1
- data/lib/urbanopt/reopt/reopt_post_processor.rb +80 -26
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +1 -1
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +182 -105
- data/lib/urbanopt/reopt/version.rb +2 -2
- data/lib/urbanopt/reopt_scenario.rb +1 -1
- data/urbanopt-reopt.gemspec +10 -7
- metadata +35 -30
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -28,10 +28,11 @@
|
|
28
28
|
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
# *********************************************************************************
|
30
30
|
|
31
|
-
require 'urbanopt/
|
31
|
+
require 'urbanopt/reporting/default_reports'
|
32
32
|
require 'urbanopt/reopt/reopt_logger'
|
33
|
-
|
33
|
+
require 'matrix'
|
34
34
|
require 'csv'
|
35
|
+
require 'time'
|
35
36
|
|
36
37
|
module URBANopt # :nodoc:
|
37
38
|
module REopt # :nodoc:
|
@@ -50,7 +51,7 @@ module URBANopt # :nodoc:
|
|
50
51
|
#
|
51
52
|
# [*parameters:*]
|
52
53
|
#
|
53
|
-
# * +scenario_report+ - _URBANopt::
|
54
|
+
# * +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.
|
54
55
|
# * +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.
|
55
56
|
#
|
56
57
|
# [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt Lite API
|
@@ -114,25 +115,29 @@ module URBANopt # :nodoc:
|
|
114
115
|
reopt_inputs[:Scenario][:Site][:land_acres] = scenario_report.program.site_area * 1.0 / 43560 # acres/sqft
|
115
116
|
end
|
116
117
|
|
118
|
+
unless scenario_report.timesteps_per_hour.nil?
|
119
|
+
reopt_inputs[:Scenario][:time_steps_per_hour] = scenario_report.timesteps_per_hour
|
120
|
+
end
|
121
|
+
|
117
122
|
# Update load profile info
|
118
123
|
begin
|
119
|
-
col_num = scenario_report.timeseries_csv.column_names.index('Electricity:Facility')
|
124
|
+
col_num = scenario_report.timeseries_csv.column_names.index('Electricity:Facility(kWh)')
|
120
125
|
t = CSV.read(scenario_report.timeseries_csv.path, headers: true, converters: :numeric)
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
126
|
+
energy_timeseries_kw = t.by_col[col_num].map { |e| ((e * scenario_report.timesteps_per_hour || 0) ) }
|
127
|
+
if energy_timeseries_kw.length < (scenario_report.timesteps_per_hour * 8760)
|
128
|
+
start_date = Time.parse(t.by_col["Datetime"][0])
|
129
|
+
start_ts = (((start_date.yday * 60.0 * 60.0 * 24) + (start_date.hour * 60.0 * 60.0) + (start_date.min * 60.0) + start_date.sec) / \
|
130
|
+
(( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
|
131
|
+
end_date = Time.parse(t.by_col["Datetime"][-1])
|
132
|
+
end_ts = (((end_date.yday * 60.0 * 60.0 * 24) + (end_date.hour * 60.0 * 60.0) + (end_date.min * 60.0) + end_date.sec) / \
|
133
|
+
(( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
|
134
|
+
energy_timeseries_kw = [0.0]*(start_ts-1) + energy_timeseries_kw + [0.0]*((scenario_report.timesteps_per_hour * 8760) - end_ts)
|
130
135
|
end
|
131
|
-
reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] =
|
136
|
+
reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(scenario_report.timesteps_per_hour * 8760)]
|
132
137
|
rescue StandardError
|
138
|
+
@@logger.error("Could not parse the annual electric load from the timeseries csv - #{scenario_report.timeseries_csv.path}")
|
133
139
|
raise "Could not parse the annual electric load from the timeseries csv - #{scenario_report.timeseries_csv.path}"
|
134
140
|
end
|
135
|
-
|
136
141
|
return reopt_inputs
|
137
142
|
end
|
138
143
|
|
@@ -141,7 +146,7 @@ module URBANopt # :nodoc:
|
|
141
146
|
#
|
142
147
|
# [*parameters:*]
|
143
148
|
#
|
144
|
-
# * +scenario_report+ - _URBANopt::
|
149
|
+
# * +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.
|
145
150
|
# * +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.
|
146
151
|
#
|
147
152
|
# [*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.
|
@@ -163,18 +168,38 @@ module URBANopt # :nodoc:
|
|
163
168
|
#
|
164
169
|
# [*parameters:*]
|
165
170
|
#
|
166
|
-
# * +scenario_report+ - _URBANopt::
|
171
|
+
# * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to update from a \REopt Lite response.
|
167
172
|
# * +reopt_output+ - _Hash_ - A hash response from the \REopt Lite API.
|
168
173
|
# * +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.
|
169
174
|
#
|
170
|
-
# [*return:*] _URBANopt::
|
175
|
+
# [*return:*] _URBANopt::Reporting::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
|
171
176
|
##
|
172
|
-
def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path =
|
177
|
+
def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path=nil, resilience_stats=nil)
|
173
178
|
if reopt_output['outputs']['Scenario']['status'] != 'optimal'
|
174
179
|
@@logger.info("Warning cannot Feature Report #{scenario_report.name} #{scenario_report.id} - REopt optimization was non-optimal")
|
175
180
|
return scenario_report
|
176
181
|
end
|
177
182
|
|
183
|
+
$ts_per_hour = scenario_report.timesteps_per_hour
|
184
|
+
def scale_timeseries(input, ts_per_hr=$ts_per_hour)
|
185
|
+
if input.nil?
|
186
|
+
return nil
|
187
|
+
end
|
188
|
+
if input.length ==0
|
189
|
+
return nil
|
190
|
+
end
|
191
|
+
if input.length == (8760 * ts_per_hr)
|
192
|
+
return input
|
193
|
+
end
|
194
|
+
result = []
|
195
|
+
input.each do |val|
|
196
|
+
(1..ts_per_hr).each do |x|
|
197
|
+
result.push(val/ts_per_hr.to_f)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
return result
|
201
|
+
end
|
202
|
+
|
178
203
|
# Update location
|
179
204
|
scenario_report.location.latitude = reopt_output['inputs']['Scenario']['Site']['latitude']
|
180
205
|
scenario_report.location.longitude = reopt_output['inputs']['Scenario']['Site']['longitude']
|
@@ -183,36 +208,71 @@ module URBANopt # :nodoc:
|
|
183
208
|
scenario_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
|
184
209
|
|
185
210
|
# Update distributed generation sizing and financials
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
211
|
+
|
212
|
+
scenario_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
|
213
|
+
scenario_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
|
214
|
+
scenario_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
|
215
|
+
scenario_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
|
216
|
+
scenario_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
|
217
|
+
scenario_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
|
218
|
+
scenario_report.distributed_generation.total_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_us_dollars'] || 0
|
219
|
+
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
|
220
|
+
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
|
221
|
+
scenario_report.distributed_generation.year_one_bill_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_bau_us_dollars'] || 0
|
222
|
+
scenario_report.distributed_generation.total_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_bau_us_dollars'] || 0
|
223
|
+
scenario_report.distributed_generation.total_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_bau_us_dollars'] || 0
|
224
|
+
if !resilience_stats.nil?
|
225
|
+
scenario_report.distributed_generation.resilience_hours_min = resilience_stats['resilience_hours_min']
|
226
|
+
scenario_report.distributed_generation.resilience_hours_max = resilience_stats['resilience_hours_max']
|
227
|
+
scenario_report.distributed_generation.resilience_hours_avg = resilience_stats['resilience_hours_avg']
|
228
|
+
scenario_report.distributed_generation.probs_of_surviving = resilience_stats['probs_of_surviving']
|
229
|
+
scenario_report.distributed_generation.probs_of_surviving_by_month = resilience_stats['probs_of_surviving_by_month']
|
230
|
+
scenario_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
|
231
|
+
end
|
232
|
+
|
233
|
+
if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
|
234
|
+
reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
|
235
|
+
elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
|
236
|
+
reopt_output['outputs']['Scenario']['Site']['PV'] = []
|
237
|
+
end
|
238
|
+
|
239
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
240
|
+
scenario_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new( {size_kw: (pv['size_kw'] || 0), id: i })
|
241
|
+
end
|
242
|
+
|
243
|
+
wind = reopt_output['outputs']['Scenario']['Site']['Wind']
|
244
|
+
if !wind['size_kw'].nil? and wind['size_kw'] != 0
|
245
|
+
scenario_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new( {size_kw: (wind['size_kw'] || 0) })
|
246
|
+
end
|
247
|
+
|
248
|
+
generator = reopt_output['outputs']['Scenario']['Site']['Generator']
|
249
|
+
if !generator['size_kw'].nil? and generator['size_kw'] != 0
|
250
|
+
scenario_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new( {size_kw: (generator['size_kw'] || 0) })
|
251
|
+
end
|
252
|
+
|
253
|
+
storage = reopt_output['outputs']['Scenario']['Site']['Storage']
|
254
|
+
if !storage['size_kw'].nil? and storage['size_kw'] != 0
|
255
|
+
scenario_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
|
256
|
+
end
|
257
|
+
|
258
|
+
generation_timeseries_kwh = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
259
|
+
|
260
|
+
|
261
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
|
262
|
+
if (pv['size_kw'] || 0) > 0
|
263
|
+
if !pv['year_one_power_production_series_kw'].nil?
|
264
|
+
generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
|
205
265
|
end
|
206
266
|
end
|
207
|
-
|
267
|
+
end
|
208
268
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
269
|
+
unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
|
270
|
+
if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
|
271
|
+
if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
|
272
|
+
generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
216
276
|
|
217
277
|
unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
|
218
278
|
if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
|
@@ -230,137 +290,152 @@ module URBANopt # :nodoc:
|
|
230
290
|
end
|
231
291
|
end
|
232
292
|
|
233
|
-
$generation_timeseries_kwh = generation_timeseries_kwh.to_a[0]
|
234
|
-
$generation_timeseries_kwh_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Total')
|
293
|
+
$generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * (8760 * scenario_report.timesteps_per_hour)
|
294
|
+
$generation_timeseries_kwh_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Total(kw)')
|
235
295
|
if $generation_timeseries_kwh_col.nil?
|
236
296
|
$generation_timeseries_kwh_col = scenario_report.timeseries_csv.column_names.length
|
237
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Total')
|
297
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
|
238
298
|
end
|
239
299
|
|
240
|
-
$load = reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'] || [0] * 8760
|
241
|
-
$load_col = scenario_report.timeseries_csv.column_names.index('Electricity:Load:Total')
|
300
|
+
$load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
301
|
+
$load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
|
242
302
|
if $load_col.nil?
|
243
303
|
$load_col = scenario_report.timeseries_csv.column_names.length
|
244
|
-
scenario_report.timeseries_csv.column_names.push('Electricity:Load:Total')
|
304
|
+
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
|
245
305
|
end
|
246
306
|
|
247
|
-
$utility_to_load = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'] || [0] * 8760
|
248
|
-
$utility_to_load_col = scenario_report.timeseries_csv.column_names.index('Electricity:Grid:ToLoad')
|
307
|
+
$utility_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
308
|
+
$utility_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
|
249
309
|
if $utility_to_load_col.nil?
|
250
310
|
$utility_to_load_col = scenario_report.timeseries_csv.column_names.length
|
251
|
-
scenario_report.timeseries_csv.column_names.push('Electricity:Grid:ToLoad')
|
311
|
+
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
|
252
312
|
end
|
253
313
|
|
254
|
-
$utility_to_battery = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'] || [0] * 8760
|
255
|
-
$utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('Electricity:Grid:ToBattery')
|
314
|
+
$utility_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
315
|
+
$utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
|
256
316
|
if $utility_to_battery_col.nil?
|
257
317
|
$utility_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
258
|
-
scenario_report.timeseries_csv.column_names.push('Electricity:Grid:ToBattery')
|
318
|
+
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
|
259
319
|
end
|
260
320
|
|
261
|
-
$storage_to_load = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'] || [0] * 8760
|
262
|
-
$storage_to_load_col = scenario_report.timeseries_csv.column_names.index('Electricity:Storage:ToLoad')
|
321
|
+
$storage_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
322
|
+
$storage_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
|
263
323
|
if $storage_to_load_col.nil?
|
264
324
|
$storage_to_load_col = scenario_report.timeseries_csv.column_names.length
|
265
|
-
scenario_report.timeseries_csv.column_names.push('Electricity:Storage:ToLoad')
|
325
|
+
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
|
266
326
|
end
|
267
327
|
|
268
|
-
$storage_to_grid = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'] || [0] * 8760
|
269
|
-
$storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('Electricity:Storage:ToGrid')
|
328
|
+
$storage_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
329
|
+
$storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
|
270
330
|
if $storage_to_grid_col.nil?
|
271
331
|
$storage_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
272
|
-
scenario_report.timeseries_csv.column_names.push('Electricity:Storage:ToGrid')
|
332
|
+
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
|
273
333
|
end
|
274
334
|
|
275
|
-
$storage_soc = reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'] || [0] * 8760
|
276
|
-
$storage_soc_col = scenario_report.timeseries_csv.column_names.index('Electricity:Storage:StateOfCharge')
|
335
|
+
$storage_soc = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
336
|
+
$storage_soc_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
|
277
337
|
if $storage_soc_col.nil?
|
278
338
|
$storage_soc_col = scenario_report.timeseries_csv.column_names.length
|
279
|
-
scenario_report.timeseries_csv.column_names.push('Electricity:Storage:StateOfCharge')
|
339
|
+
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
|
280
340
|
end
|
281
341
|
|
282
|
-
$generator_total = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'] || [0] * 8760
|
283
|
-
$generator_total_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:Total')
|
342
|
+
$generator_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
343
|
+
$generator_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
|
284
344
|
if $generator_total_col.nil?
|
285
345
|
$generator_total_col = scenario_report.timeseries_csv.column_names.length
|
286
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:Total')
|
346
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
|
287
347
|
end
|
288
348
|
|
289
|
-
$generator_to_battery = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'] || [0] * 8760
|
290
|
-
$generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToBattery')
|
349
|
+
$generator_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
350
|
+
$generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
|
291
351
|
if $generator_to_battery_col.nil?
|
292
352
|
$generator_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
293
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToBattery')
|
353
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
|
294
354
|
end
|
295
355
|
|
296
|
-
$generator_to_load = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'] || [0] * 8760
|
297
|
-
$generator_to_load_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToLoad')
|
356
|
+
$generator_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
357
|
+
$generator_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
|
298
358
|
if $generator_to_load_col.nil?
|
299
359
|
$generator_to_load_col = scenario_report.timeseries_csv.column_names.length
|
300
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToLoad')
|
360
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
|
301
361
|
end
|
302
362
|
|
303
|
-
$generator_to_grid = reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'] || [0] * 8760
|
304
|
-
$generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Generator:ToGrid')
|
363
|
+
$generator_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
364
|
+
$generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
|
305
365
|
if $generator_to_grid_col.nil?
|
306
366
|
$generator_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
307
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Generator:ToGrid')
|
367
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
|
308
368
|
end
|
309
369
|
|
310
|
-
$
|
311
|
-
$pv_total_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:Total')
|
370
|
+
$pv_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:Total(kw)')
|
312
371
|
if $pv_total_col.nil?
|
313
372
|
$pv_total_col = scenario_report.timeseries_csv.column_names.length
|
314
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:Total')
|
373
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:Total(kw)')
|
315
374
|
end
|
316
375
|
|
317
|
-
$
|
318
|
-
$pv_to_battery_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToBattery')
|
376
|
+
$pv_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToBattery(kw)')
|
319
377
|
if $pv_to_battery_col.nil?
|
320
378
|
$pv_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
321
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToBattery')
|
379
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToBattery(kw)')
|
322
380
|
end
|
323
381
|
|
324
|
-
$
|
325
|
-
$pv_to_load_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToLoad')
|
382
|
+
$pv_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToLoad(kw)')
|
326
383
|
if $pv_to_load_col.nil?
|
327
384
|
$pv_to_load_col = scenario_report.timeseries_csv.column_names.length
|
328
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToLoad')
|
385
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToLoad(kw)')
|
329
386
|
end
|
330
387
|
|
331
|
-
$
|
332
|
-
$pv_to_grid_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:PV:ToGrid')
|
388
|
+
$pv_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:PV:ToGrid(kw)')
|
333
389
|
if $pv_to_grid_col.nil?
|
334
390
|
$pv_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
335
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:PV:ToGrid')
|
391
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:PV:ToGrid(kw)')
|
336
392
|
end
|
337
393
|
|
338
|
-
$
|
339
|
-
$
|
394
|
+
$pv_total = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
395
|
+
$pv_to_battery = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
396
|
+
$pv_to_load = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
397
|
+
$pv_to_grid = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
398
|
+
|
399
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
400
|
+
if (pv['size_kw'] || 0) > 0
|
401
|
+
$pv_total += Matrix[scale_timeseries(pv['year_one_power_production_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
402
|
+
$pv_to_battery += Matrix[scale_timeseries(pv['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
403
|
+
$pv_to_load += Matrix[scale_timeseries(pv['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
404
|
+
$pv_to_grid += Matrix[scale_timeseries(pv['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
$pv_total = $pv_total.to_a[0]
|
409
|
+
$pv_to_battery = $pv_to_battery.to_a[0]
|
410
|
+
$pv_to_load = $pv_to_load.to_a[0]
|
411
|
+
$pv_to_grid = $pv_to_grid.to_a[0]
|
412
|
+
|
413
|
+
$wind_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
414
|
+
$wind_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
|
340
415
|
if $wind_total_col.nil?
|
341
416
|
$wind_total_col = scenario_report.timeseries_csv.column_names.length
|
342
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:Total')
|
417
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
|
343
418
|
end
|
344
419
|
|
345
|
-
$wind_to_battery = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'] || [0] * 8760
|
346
|
-
$wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToBattery')
|
420
|
+
$wind_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
421
|
+
$wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
347
422
|
if $wind_to_battery_col.nil?
|
348
423
|
$wind_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
349
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToBattery')
|
424
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
350
425
|
end
|
351
426
|
|
352
|
-
$wind_to_load = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'] || [0] * 8760
|
353
|
-
$wind_to_load_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToLoad')
|
427
|
+
$wind_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
428
|
+
$wind_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
|
354
429
|
if $wind_to_load_col.nil?
|
355
430
|
$wind_to_load_col = scenario_report.timeseries_csv.column_names.length
|
356
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToLoad')
|
431
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
|
357
432
|
end
|
358
433
|
|
359
|
-
$wind_to_grid = reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'] || [0] * 8760
|
360
|
-
$wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('ElectricityProduced:Wind:ToGrid')
|
434
|
+
$wind_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw']) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
435
|
+
$wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
|
361
436
|
if $wind_to_grid_col.nil?
|
362
437
|
$wind_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
363
|
-
scenario_report.timeseries_csv.column_names.push('ElectricityProduced:Wind:ToGrid')
|
438
|
+
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
|
364
439
|
end
|
365
440
|
|
366
441
|
def modrow(x, i) # :nodoc:
|
@@ -387,9 +462,11 @@ module URBANopt # :nodoc:
|
|
387
462
|
end
|
388
463
|
|
389
464
|
old_data = CSV.open(scenario_report.timeseries_csv.path).read
|
465
|
+
start_date = Time.parse(old_data[1][0])
|
466
|
+
start_ts = (((start_date.yday * 60.0 * 60.0 * 24) + (start_date.hour * 60.0 * 60.0) + (start_date.min * 60.0) + start_date.sec) / (( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
|
390
467
|
mod_data = old_data.map.with_index do |x, i|
|
391
468
|
if i > 0
|
392
|
-
modrow(x, i)
|
469
|
+
modrow(x, start_ts + i -2)
|
393
470
|
else
|
394
471
|
x
|
395
472
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -30,6 +30,6 @@
|
|
30
30
|
|
31
31
|
module URBANopt # :nodoc:
|
32
32
|
module REopt # :nodoc:
|
33
|
-
VERSION = '0.
|
33
|
+
VERSION = '0.4.0'.freeze
|
34
34
|
end
|
35
35
|
end
|