urbanopt-reopt 0.1.0 → 0.4.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 +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
|