urbanopt-reopt 0.5.0 → 0.6.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/CHANGELOG.md +52 -0
- data/Gemfile +1 -1
- data/LICENSE.md +33 -21
- data/Rakefile +16 -6
- data/docs/package-lock.json +17551 -6268
- data/docs/package.json +10 -2
- data/lib/urbanopt-reopt.rb +16 -6
- data/lib/urbanopt/reopt.rb +16 -6
- data/lib/urbanopt/reopt/extension.rb +16 -6
- data/lib/urbanopt/reopt/feature_report_adapter.rb +90 -70
- data/lib/urbanopt/reopt/reopt_lite_api.rb +29 -17
- data/lib/urbanopt/reopt/reopt_logger.rb +16 -6
- data/lib/urbanopt/reopt/reopt_post_processor.rb +18 -10
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +16 -6
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +84 -72
- data/lib/urbanopt/reopt/utilities.rb +111 -0
- data/lib/urbanopt/reopt/version.rb +17 -7
- data/lib/urbanopt/reopt_scenario.rb +16 -6
- data/urbanopt-reopt.gemspec +3 -3
- metadata +10 -10
- data/a.txt +0 -1
@@ -1,21 +1,31 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt
|
2
|
+
# URBANopt™, Copyright (c) 2019-2021, 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,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
+
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
19
29
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
30
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
31
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -165,7 +175,7 @@ module URBANopt # :nodoc:
|
|
165
175
|
# [*return:*] _Bool_ - Returns true if the post succeeeds. Otherwise returns false.
|
166
176
|
##
|
167
177
|
def resilience_request(run_uuid, filename)
|
168
|
-
|
178
|
+
|
169
179
|
if File.directory? filename
|
170
180
|
if run_uuid.nil?
|
171
181
|
run_uuid = 'error'
|
@@ -176,7 +186,7 @@ module URBANopt # :nodoc:
|
|
176
186
|
filename = File.join(filename, "#{run_uuid}_resilience.json")
|
177
187
|
@@logger.info("REopt results saved to #{filename}")
|
178
188
|
end
|
179
|
-
|
189
|
+
|
180
190
|
#Submit Job
|
181
191
|
@@logger.info("Submitting Resilience Statistics job for #{run_uuid}")
|
182
192
|
header = { 'Content-Type' => 'application/json' }
|
@@ -197,17 +207,17 @@ module URBANopt # :nodoc:
|
|
197
207
|
end
|
198
208
|
|
199
209
|
elapsed_time = 0
|
200
|
-
max_elapsed_time = 60
|
201
|
-
|
210
|
+
max_elapsed_time = 60 * 5
|
211
|
+
|
202
212
|
request = Net::HTTP::Get.new(uri.request_uri)
|
203
213
|
response = make_request(http, request)
|
204
|
-
|
214
|
+
|
205
215
|
while (elapsed_time < max_elapsed_time) & (response.code == "404")
|
206
216
|
response = make_request(http, request)
|
207
|
-
elapsed_time += 5
|
217
|
+
elapsed_time += 5
|
208
218
|
sleep 5
|
209
219
|
end
|
210
|
-
|
220
|
+
|
211
221
|
data = JSON.parse(response.body)
|
212
222
|
text = ::JSON.generate(data, allow_nan: true)
|
213
223
|
begin
|
@@ -222,7 +232,9 @@ module URBANopt # :nodoc:
|
|
222
232
|
return data
|
223
233
|
end
|
224
234
|
|
225
|
-
|
235
|
+
@@logger.info("Error from REopt API - #{data['Error']}")
|
236
|
+
return {}
|
237
|
+
|
226
238
|
end
|
227
239
|
|
228
240
|
##
|
@@ -290,14 +302,14 @@ module URBANopt # :nodoc:
|
|
290
302
|
|
291
303
|
while status == 'Optimizing...'
|
292
304
|
response = make_request(http, request)
|
293
|
-
|
305
|
+
|
294
306
|
data = JSON.parse(response.body, allow_nan:true)
|
295
307
|
|
296
308
|
if data['outputs']['Scenario']['Site']['PV'].kind_of?(Array)
|
297
309
|
pv_sizes = 0
|
298
310
|
data['outputs']['Scenario']['Site']['PV'].each do |x|
|
299
311
|
pv_sizes = pv_sizes + x['size_kw'].to_f
|
300
|
-
end
|
312
|
+
end
|
301
313
|
else
|
302
314
|
pv_sizes = data['outputs']['Scenario']['Site']['PV']['size_kw'] || 0
|
303
315
|
end
|
@@ -318,7 +330,7 @@ module URBANopt # :nodoc:
|
|
318
330
|
pv_sizes = 0
|
319
331
|
data['outputs']['Scenario']['Site']['PV'].each do |x|
|
320
332
|
pv_sizes = pv_sizes + x['size_kw'].to_f
|
321
|
-
end
|
333
|
+
end
|
322
334
|
else
|
323
335
|
pv_sizes = data['outputs']['Scenario']['Site']['PV']['size_kw'] || 0
|
324
336
|
end
|
@@ -1,21 +1,31 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt
|
2
|
+
# URBANopt™, Copyright (c) 2019-2021, 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,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
+
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
19
29
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
30
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
31
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -1,21 +1,31 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt
|
2
|
+
# URBANopt™, Copyright (c) 2019-2021, 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,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
+
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
19
29
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
30
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
31
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -140,8 +150,7 @@ module URBANopt # :nodoc:
|
|
140
150
|
end
|
141
151
|
result = adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path, resilience_stats)
|
142
152
|
if !save_name.nil?
|
143
|
-
|
144
|
-
result.save_json_report(save_name)
|
153
|
+
result.save save_name
|
145
154
|
end
|
146
155
|
return result
|
147
156
|
end
|
@@ -251,8 +260,7 @@ module URBANopt # :nodoc:
|
|
251
260
|
new_feature_reports.push(new_feature_report)
|
252
261
|
if !save_names.nil?
|
253
262
|
if save_names.length == feature_reports.length
|
254
|
-
|
255
|
-
new_feature_report.save_json_report save_names[idx]
|
263
|
+
new_feature_report.save save_names[idx]
|
256
264
|
else
|
257
265
|
warn "Could not save feature reports - the number of save names provided did not match the number of feature reports"
|
258
266
|
end
|
@@ -1,21 +1,31 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt
|
2
|
+
# URBANopt™, Copyright (c) 2019-2021, 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,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
+
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
19
29
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
30
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
31
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -1,21 +1,31 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt
|
2
|
+
# URBANopt™, Copyright (c) 2019-2021, 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,
|
6
6
|
# are permitted provided that the following conditions are met:
|
7
|
-
|
7
|
+
|
8
8
|
# Redistributions of source code must retain the above copyright notice, this list
|
9
9
|
# of conditions and the following disclaimer.
|
10
|
-
|
10
|
+
|
11
11
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
12
|
# list of conditions and the following disclaimer in the documentation and/or other
|
13
13
|
# materials provided with the distribution.
|
14
|
-
|
14
|
+
|
15
15
|
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
16
|
# used to endorse or promote products derived from this software without specific
|
17
17
|
# prior written permission.
|
18
|
-
|
18
|
+
|
19
|
+
# Redistribution of this software, without modification, must refer to the software
|
20
|
+
# by the same designation. Redistribution of a modified version of this software
|
21
|
+
# (i) may not refer to the modified version by the same designation, or by any
|
22
|
+
# confusingly similar designation, and (ii) must refer to the underlying software
|
23
|
+
# originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
|
24
|
+
# the term “URBANopt”, or any confusingly similar designation may not be used to
|
25
|
+
# refer to any modified version of this software or any modified version of the
|
26
|
+
# underlying software originally provided by Alliance without the prior written
|
27
|
+
# consent of Alliance.
|
28
|
+
|
19
29
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
30
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
31
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
@@ -33,6 +43,7 @@ require 'urbanopt/reopt/reopt_logger'
|
|
33
43
|
require 'matrix'
|
34
44
|
require 'csv'
|
35
45
|
require 'time'
|
46
|
+
require_relative 'utilities'
|
36
47
|
|
37
48
|
module URBANopt # :nodoc:
|
38
49
|
module REopt # :nodoc:
|
@@ -93,7 +104,6 @@ module URBANopt # :nodoc:
|
|
93
104
|
requireds_names = ['latitude', 'longitude']
|
94
105
|
requireds = [scenario_report.location.latitude_deg, scenario_report.location.longitude_deg]
|
95
106
|
|
96
|
-
|
97
107
|
if requireds.include?(nil) || requireds.include?(0)
|
98
108
|
requireds.each_with_index do |x, i|
|
99
109
|
if [nil].include? x
|
@@ -110,16 +120,20 @@ module URBANopt # :nodoc:
|
|
110
120
|
|
111
121
|
# Update optional info
|
112
122
|
# REK: attribute names should be updated
|
113
|
-
if
|
114
|
-
|
123
|
+
if reopt_inputs[:Scenario][:Site][:roof_squarefeet].nil?
|
124
|
+
if !scenario_report.program.roof_area_sqft.nil?
|
125
|
+
reopt_inputs[:Scenario][:Site][:roof_squarefeet] = scenario_report.program.roof_area_sqft[:available_roof_area_sqft]
|
126
|
+
end
|
115
127
|
end
|
116
128
|
|
117
|
-
if
|
118
|
-
|
129
|
+
if reopt_inputs[:Scenario][:Site][:land_acres].nil?
|
130
|
+
if !scenario_report.program.site_area_sqft.nil?
|
131
|
+
reopt_inputs[:Scenario][:Site][:land_acres] = scenario_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
|
132
|
+
end
|
119
133
|
end
|
120
134
|
|
121
|
-
|
122
|
-
reopt_inputs[:Scenario][:time_steps_per_hour] =
|
135
|
+
if reopt_inputs[:Scenario][:time_steps_per_hour].nil?
|
136
|
+
reopt_inputs[:Scenario][:time_steps_per_hour] = 1
|
123
137
|
end
|
124
138
|
|
125
139
|
# Update load profile info
|
@@ -136,14 +150,38 @@ module URBANopt # :nodoc:
|
|
136
150
|
(( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
|
137
151
|
energy_timeseries_kw = [0.0]*(start_ts-1) + energy_timeseries_kw + [0.0]*((scenario_report.timesteps_per_hour * 8760) - end_ts)
|
138
152
|
end
|
139
|
-
|
153
|
+
energy_timeseries_kw = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(scenario_report.timesteps_per_hour * 8760)]
|
140
154
|
rescue StandardError
|
141
155
|
@@logger.error("Could not parse the annual electric load from the timeseries csv - #{scenario_report.timeseries_csv.path}")
|
142
156
|
raise "Could not parse the annual electric load from the timeseries csv - #{scenario_report.timeseries_csv.path}"
|
143
157
|
end
|
158
|
+
|
159
|
+
# Convert load to REopt Resolution
|
160
|
+
begin
|
161
|
+
reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, scenario_report.timesteps_per_hour, reopt_inputs[:Scenario][:time_steps_per_hour])
|
162
|
+
rescue
|
163
|
+
@@logger.error("Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}")
|
164
|
+
raise "Could not convert the annual electric load from a resolution of #{scenario_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}"
|
165
|
+
end
|
166
|
+
|
167
|
+
if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps].nil?
|
168
|
+
n_top_values = 100
|
169
|
+
tmp1 = reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw]
|
170
|
+
tmp2 = tmp1.each_index.max_by(n_top_values*reopt_inputs[:Scenario][:time_steps_per_hour]){|i| tmp1[i]}
|
171
|
+
for i in (0...tmp2.count)
|
172
|
+
tmp2[i] += 1
|
173
|
+
end
|
174
|
+
reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps] = tmp2
|
175
|
+
end
|
176
|
+
|
177
|
+
if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw].nil?
|
178
|
+
reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw] = 0
|
179
|
+
end
|
180
|
+
|
144
181
|
return reopt_inputs
|
145
182
|
end
|
146
183
|
|
184
|
+
|
147
185
|
##
|
148
186
|
# Converts a FeatureReport list from a ScenarioReport into an array of \REopt Lite posts
|
149
187
|
#
|
@@ -183,33 +221,10 @@ module URBANopt # :nodoc:
|
|
183
221
|
return scenario_report
|
184
222
|
end
|
185
223
|
|
186
|
-
$ts_per_hour = scenario_report.timesteps_per_hour
|
187
|
-
def scale_timeseries(input, ts_per_hr=$ts_per_hour)
|
188
|
-
if input.nil?
|
189
|
-
return nil
|
190
|
-
end
|
191
|
-
if input.length ==0
|
192
|
-
return nil
|
193
|
-
end
|
194
|
-
if input.length == (8760 * ts_per_hr)
|
195
|
-
return input
|
196
|
-
end
|
197
|
-
result = []
|
198
|
-
input.each do |val|
|
199
|
-
(1..ts_per_hr).each do |x|
|
200
|
-
result.push(val/ts_per_hr.to_f)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
return result
|
204
|
-
end
|
205
|
-
|
206
224
|
# Update location
|
207
225
|
scenario_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
|
208
226
|
scenario_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
|
209
227
|
|
210
|
-
# Update timeseries csv from \REopt Lite dispatch data
|
211
|
-
scenario_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
|
212
|
-
|
213
228
|
# Update distributed generation sizing and financials
|
214
229
|
|
215
230
|
scenario_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
|
@@ -230,7 +245,7 @@ module URBANopt # :nodoc:
|
|
230
245
|
scenario_report.distributed_generation.resilience_hours_avg = resilience_stats['resilience_hours_avg']
|
231
246
|
scenario_report.distributed_generation.probs_of_surviving = resilience_stats['probs_of_surviving']
|
232
247
|
scenario_report.distributed_generation.probs_of_surviving_by_month = resilience_stats['probs_of_surviving_by_month']
|
233
|
-
scenario_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
|
248
|
+
scenario_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
|
234
249
|
end
|
235
250
|
|
236
251
|
if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
|
@@ -258,29 +273,21 @@ module URBANopt # :nodoc:
|
|
258
273
|
scenario_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
|
259
274
|
end
|
260
275
|
|
276
|
+
reopt_resolution = reopt_output['inputs']['Scenario']['time_steps_per_hour']
|
261
277
|
generation_timeseries_kwh = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
262
278
|
|
263
|
-
|
264
279
|
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
|
265
280
|
if (pv['size_kw'] || 0) > 0
|
266
281
|
if !pv['year_one_power_production_series_kw'].nil?
|
267
|
-
generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
|
282
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
|
268
283
|
end
|
269
284
|
end
|
270
285
|
end
|
271
286
|
|
272
|
-
unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
|
273
|
-
if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
|
274
|
-
if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
|
275
|
-
generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
287
|
unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
|
281
288
|
if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
|
282
289
|
if !reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'].nil?
|
283
|
-
generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']]
|
290
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
|
284
291
|
end
|
285
292
|
end
|
286
293
|
end
|
@@ -288,7 +295,7 @@ module URBANopt # :nodoc:
|
|
288
295
|
unless reopt_output['outputs']['Scenario']['Site']['Generator'].nil?
|
289
296
|
if (reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0) > 0
|
290
297
|
if !reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'].nil?
|
291
|
-
generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']]
|
298
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour)]
|
292
299
|
end
|
293
300
|
end
|
294
301
|
end
|
@@ -300,70 +307,70 @@ module URBANopt # :nodoc:
|
|
300
307
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
|
301
308
|
end
|
302
309
|
|
303
|
-
$load =
|
310
|
+
$load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
304
311
|
$load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
|
305
312
|
if $load_col.nil?
|
306
313
|
$load_col = scenario_report.timeseries_csv.column_names.length
|
307
314
|
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
|
308
315
|
end
|
309
316
|
|
310
|
-
$utility_to_load =
|
317
|
+
$utility_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
311
318
|
$utility_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
|
312
319
|
if $utility_to_load_col.nil?
|
313
320
|
$utility_to_load_col = scenario_report.timeseries_csv.column_names.length
|
314
321
|
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
|
315
322
|
end
|
316
323
|
|
317
|
-
$utility_to_battery =
|
324
|
+
$utility_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
318
325
|
$utility_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
|
319
326
|
if $utility_to_battery_col.nil?
|
320
327
|
$utility_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
321
328
|
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
|
322
329
|
end
|
323
330
|
|
324
|
-
$storage_to_load =
|
331
|
+
$storage_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
325
332
|
$storage_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
|
326
333
|
if $storage_to_load_col.nil?
|
327
334
|
$storage_to_load_col = scenario_report.timeseries_csv.column_names.length
|
328
335
|
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
|
329
336
|
end
|
330
337
|
|
331
|
-
$storage_to_grid =
|
338
|
+
$storage_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
332
339
|
$storage_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
|
333
340
|
if $storage_to_grid_col.nil?
|
334
341
|
$storage_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
335
342
|
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
|
336
343
|
end
|
337
344
|
|
338
|
-
$storage_soc =
|
345
|
+
$storage_soc = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
339
346
|
$storage_soc_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
|
340
347
|
if $storage_soc_col.nil?
|
341
348
|
$storage_soc_col = scenario_report.timeseries_csv.column_names.length
|
342
349
|
scenario_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
|
343
350
|
end
|
344
351
|
|
345
|
-
$generator_total =
|
352
|
+
$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)
|
346
353
|
$generator_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
|
347
354
|
if $generator_total_col.nil?
|
348
355
|
$generator_total_col = scenario_report.timeseries_csv.column_names.length
|
349
356
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
|
350
357
|
end
|
351
358
|
|
352
|
-
$generator_to_battery =
|
359
|
+
$generator_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
353
360
|
$generator_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
|
354
361
|
if $generator_to_battery_col.nil?
|
355
362
|
$generator_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
356
363
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
|
357
364
|
end
|
358
365
|
|
359
|
-
$generator_to_load =
|
366
|
+
$generator_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
360
367
|
$generator_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
|
361
368
|
if $generator_to_load_col.nil?
|
362
369
|
$generator_to_load_col = scenario_report.timeseries_csv.column_names.length
|
363
370
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
|
364
371
|
end
|
365
372
|
|
366
|
-
$generator_to_grid =
|
373
|
+
$generator_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
367
374
|
$generator_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
|
368
375
|
if $generator_to_grid_col.nil?
|
369
376
|
$generator_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
@@ -401,10 +408,10 @@ module URBANopt # :nodoc:
|
|
401
408
|
|
402
409
|
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
403
410
|
if (pv['size_kw'] || 0) > 0
|
404
|
-
$pv_total += Matrix[
|
405
|
-
$pv_to_battery += Matrix[
|
406
|
-
$pv_to_load += Matrix[
|
407
|
-
$pv_to_grid += Matrix[
|
411
|
+
$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)]
|
412
|
+
$pv_to_battery += Matrix[convert_powerflow_resolution(pv['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
413
|
+
$pv_to_load += Matrix[convert_powerflow_resolution(pv['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
414
|
+
$pv_to_grid += Matrix[convert_powerflow_resolution(pv['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
408
415
|
end
|
409
416
|
end
|
410
417
|
|
@@ -413,28 +420,28 @@ module URBANopt # :nodoc:
|
|
413
420
|
$pv_to_load = $pv_to_load.to_a[0]
|
414
421
|
$pv_to_grid = $pv_to_grid.to_a[0]
|
415
422
|
|
416
|
-
$wind_total =
|
423
|
+
$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)
|
417
424
|
$wind_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
|
418
425
|
if $wind_total_col.nil?
|
419
426
|
$wind_total_col = scenario_report.timeseries_csv.column_names.length
|
420
427
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
|
421
428
|
end
|
422
429
|
|
423
|
-
$wind_to_battery =
|
430
|
+
$wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
424
431
|
$wind_to_battery_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
425
432
|
if $wind_to_battery_col.nil?
|
426
433
|
$wind_to_battery_col = scenario_report.timeseries_csv.column_names.length
|
427
434
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
428
435
|
end
|
429
436
|
|
430
|
-
$wind_to_load =
|
437
|
+
$wind_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
431
438
|
$wind_to_load_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
|
432
439
|
if $wind_to_load_col.nil?
|
433
440
|
$wind_to_load_col = scenario_report.timeseries_csv.column_names.length
|
434
441
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
|
435
442
|
end
|
436
443
|
|
437
|
-
$wind_to_grid =
|
444
|
+
$wind_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
438
445
|
$wind_to_grid_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
|
439
446
|
if $wind_to_grid_col.nil?
|
440
447
|
$wind_to_grid_col = scenario_report.timeseries_csv.column_names.length
|
@@ -465,17 +472,22 @@ module URBANopt # :nodoc:
|
|
465
472
|
end
|
466
473
|
|
467
474
|
old_data = CSV.open(scenario_report.timeseries_csv.path).read
|
468
|
-
start_date = Time.parse(old_data[1][0])
|
469
|
-
start_ts = (
|
475
|
+
start_date = Time.parse(old_data[1][0]) # Time is the end of the timestep
|
476
|
+
start_ts = (
|
477
|
+
(
|
478
|
+
((start_date.yday - 1) * 60.0 * 60.0 * 24) +
|
479
|
+
(((start_date.hour) - 1) * 60.0 * 60.0) +
|
480
|
+
(start_date.min * 60.0) + start_date.sec ) /
|
481
|
+
(( 60 / scenario_report.timesteps_per_hour ) * 60)
|
482
|
+
).to_int
|
470
483
|
mod_data = old_data.map.with_index do |x, i|
|
471
484
|
if i > 0
|
472
|
-
modrow(x, start_ts + i -
|
485
|
+
modrow(x, start_ts + i -1)
|
473
486
|
else
|
474
487
|
x
|
475
488
|
end
|
476
489
|
end
|
477
490
|
mod_data[0] = scenario_report.timeseries_csv.column_names
|
478
|
-
|
479
491
|
scenario_report.timeseries_csv.reload_data(mod_data)
|
480
492
|
return scenario_report
|
481
493
|
end
|