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,
|
@@ -56,6 +56,7 @@ module URBANopt # :nodoc:
|
|
56
56
|
@use_localhost = use_localhost
|
57
57
|
if @use_localhost
|
58
58
|
@uri_submit = URI.parse('http//:127.0.0.1:8000/v1/job/')
|
59
|
+
@uri_submit_outagesimjob = URI.parse('http//:127.0.0.1:8000/v1/outagesimjob/')
|
59
60
|
else
|
60
61
|
if [nil, '', '<insert your key here>'].include? nrel_developer_key
|
61
62
|
if [nil, '', '<insert your key here>'].include? DEVELOPER_NREL_KEY
|
@@ -66,6 +67,7 @@ module URBANopt # :nodoc:
|
|
66
67
|
end
|
67
68
|
@nrel_developer_key = nrel_developer_key
|
68
69
|
@uri_submit = URI.parse("https://developer.nrel.gov/api/reopt/v1/job/?api_key=#{@nrel_developer_key}")
|
70
|
+
@uri_submit_outagesimjob = URI.parse("https://developer.nrel.gov/api/reopt/v1/outagesimjob/?api_key=#{@nrel_developer_key}")
|
69
71
|
# initialize @@logger
|
70
72
|
@@logger ||= URBANopt::REopt.reopt_logger
|
71
73
|
end
|
@@ -88,6 +90,23 @@ module URBANopt # :nodoc:
|
|
88
90
|
return URI.parse("https://developer.nrel.gov/api/reopt/v1/job/#{run_uuid}/results?api_key=#{@nrel_developer_key}")
|
89
91
|
end
|
90
92
|
|
93
|
+
##
|
94
|
+
# URL of the resilience statistics end point for a specific optimization task
|
95
|
+
##
|
96
|
+
#
|
97
|
+
# [*parameters:*]
|
98
|
+
#
|
99
|
+
# * +run_uuid+ - _String_ - Resilience statistics for a unique run_uuid obtained from the \REopt Lite job submittal URL for a specific optimization task.
|
100
|
+
#
|
101
|
+
# [*return:*] _URI_ - Returns URI object for use in calling the \REopt Lite resilience statistics endpoint for a specifc optimization task.
|
102
|
+
##
|
103
|
+
def uri_resilience(run_uuid) # :nodoc:
|
104
|
+
if @use_localhost
|
105
|
+
return URI.parse("http://127.0.0.1:8000/v1/job/#{run_uuid}/resilience_stats")
|
106
|
+
end
|
107
|
+
return URI.parse("https://developer.nrel.gov/api/reopt/v1/job/#{run_uuid}/resilience_stats?api_key=#{@nrel_developer_key}")
|
108
|
+
end
|
109
|
+
|
91
110
|
def make_request(http, r, max_tries = 3)
|
92
111
|
result = nil
|
93
112
|
tries = 0
|
@@ -117,10 +136,10 @@ module URBANopt # :nodoc:
|
|
117
136
|
http = Net::HTTP.new(@uri_submit.host, @uri_submit.port)
|
118
137
|
if !@use_localhost
|
119
138
|
http.use_ssl = true
|
120
|
-
|
139
|
+
end
|
121
140
|
|
122
141
|
request = Net::HTTP::Post.new(@uri_submit, header)
|
123
|
-
request.body = data
|
142
|
+
request.body = ::JSON.generate(data, allow_nan: true)
|
124
143
|
|
125
144
|
# Send the request
|
126
145
|
response = make_request(http, request)
|
@@ -132,6 +151,80 @@ module URBANopt # :nodoc:
|
|
132
151
|
return true
|
133
152
|
end
|
134
153
|
|
154
|
+
##
|
155
|
+
# Completes a \REopt Lite optimization. From a formatted hash, an optimization task is submitted to the API.
|
156
|
+
# Results are polled at 5 second interval until they are ready or an error is returned from the API. Results
|
157
|
+
# are written to disk.
|
158
|
+
##
|
159
|
+
#
|
160
|
+
# [*parameters:*]
|
161
|
+
#
|
162
|
+
# * +reopt_input+ - _Hash_ - \REopt Lite formatted post containing at least required parameters.
|
163
|
+
# * +filename+ - _String_ - Path to file that will be created containing the full \REopt Lite response.
|
164
|
+
#
|
165
|
+
# [*return:*] _Bool_ - Returns true if the post succeeeds. Otherwise returns false.
|
166
|
+
##
|
167
|
+
def resilience_request(run_uuid, filename)
|
168
|
+
|
169
|
+
if File.directory? filename
|
170
|
+
if run_uuid.nil?
|
171
|
+
run_uuid = 'error'
|
172
|
+
end
|
173
|
+
if run_uuid.downcase.include? 'error'
|
174
|
+
run_uuid = "error#{SecureRandom.uuid}"
|
175
|
+
end
|
176
|
+
filename = File.join(filename, "#{run_uuid}_resilience.json")
|
177
|
+
@@logger.info("REopt results saved to #{filename}")
|
178
|
+
end
|
179
|
+
|
180
|
+
#Submit Job
|
181
|
+
@@logger.info("Submitting Resilience Statistics job for #{run_uuid}")
|
182
|
+
header = { 'Content-Type' => 'application/json' }
|
183
|
+
http = Net::HTTP.new(@uri_submit_outagesimjob.host, @uri_submit_outagesimjob.port)
|
184
|
+
if !@use_localhost
|
185
|
+
http.use_ssl = true
|
186
|
+
end
|
187
|
+
request = Net::HTTP::Post.new(@uri_submit_outagesimjob, header)
|
188
|
+
request.body = ::JSON.generate({"run_uuid" => run_uuid, "bau" => false }, allow_nan: true)
|
189
|
+
submit_response = make_request(http, request)
|
190
|
+
@@logger.info(submit_response.body)
|
191
|
+
|
192
|
+
#Fetch Results
|
193
|
+
uri = uri_resilience(run_uuid)
|
194
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
195
|
+
if !@use_localhost
|
196
|
+
http.use_ssl = true
|
197
|
+
end
|
198
|
+
|
199
|
+
elapsed_time = 0
|
200
|
+
max_elapsed_time = 60
|
201
|
+
|
202
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
203
|
+
response = make_request(http, request)
|
204
|
+
|
205
|
+
while (elapsed_time < max_elapsed_time) & (response.code == "404")
|
206
|
+
response = make_request(http, request)
|
207
|
+
elapsed_time += 5
|
208
|
+
sleep 5
|
209
|
+
end
|
210
|
+
|
211
|
+
data = JSON.parse(response.body)
|
212
|
+
text = ::JSON.generate(data, allow_nan: true)
|
213
|
+
begin
|
214
|
+
File.open(filename, 'w+') do |f|
|
215
|
+
f.puts(text)
|
216
|
+
end
|
217
|
+
rescue
|
218
|
+
@@logger.info("Cannot write - #{filename}")
|
219
|
+
end
|
220
|
+
|
221
|
+
if response.code == "200"
|
222
|
+
return data
|
223
|
+
end
|
224
|
+
|
225
|
+
raise "Error from REopt API - #{data['Error']}"
|
226
|
+
end
|
227
|
+
|
135
228
|
##
|
136
229
|
# Completes a \REopt Lite optimization. From a formatted hash, an optimization task is submitted to the API.
|
137
230
|
# Results are polled at 5 second interval until they are ready or an error is returned from the API. Results
|
@@ -157,13 +250,13 @@ module URBANopt # :nodoc:
|
|
157
250
|
http.use_ssl = true
|
158
251
|
end
|
159
252
|
request = Net::HTTP::Post.new(@uri_submit, header)
|
160
|
-
request.body = reopt_input
|
253
|
+
request.body = ::JSON.generate(reopt_input, allow_nan: true)
|
161
254
|
|
162
255
|
# Send the request
|
163
256
|
response = make_request(http, request)
|
164
257
|
|
165
258
|
# Get UUID
|
166
|
-
run_uuid = JSON.parse(response.body)['run_uuid']
|
259
|
+
run_uuid = JSON.parse(response.body, allow_nan:true)['run_uuid']
|
167
260
|
|
168
261
|
if File.directory? filename
|
169
262
|
if run_uuid.nil?
|
@@ -176,10 +269,12 @@ module URBANopt # :nodoc:
|
|
176
269
|
@@logger.info("REopt results saved to #{filename}")
|
177
270
|
end
|
178
271
|
|
272
|
+
text = ::JSON.generate(response.body, allow_nan: true)
|
179
273
|
if response.code != '201'
|
180
|
-
File.open(filename, 'w') do |f|
|
181
|
-
f.
|
274
|
+
File.open(filename, 'w+') do |f|
|
275
|
+
f.puts(text)
|
182
276
|
end
|
277
|
+
@@logger.info("Cannot write - #{filename}")
|
183
278
|
raise "Error in REopt optimization post - see #{filename}"
|
184
279
|
end
|
185
280
|
|
@@ -195,8 +290,18 @@ module URBANopt # :nodoc:
|
|
195
290
|
|
196
291
|
while status == 'Optimizing...'
|
197
292
|
response = make_request(http, request)
|
198
|
-
|
199
|
-
|
293
|
+
|
294
|
+
data = JSON.parse(response.body, allow_nan:true)
|
295
|
+
|
296
|
+
if data['outputs']['Scenario']['Site']['PV'].kind_of?(Array)
|
297
|
+
pv_sizes = 0
|
298
|
+
data['outputs']['Scenario']['Site']['PV'].each do |x|
|
299
|
+
pv_sizes = pv_sizes + x['size_kw'].to_f
|
300
|
+
end
|
301
|
+
else
|
302
|
+
pv_sizes = data['outputs']['Scenario']['Site']['PV']['size_kw'] || 0
|
303
|
+
end
|
304
|
+
sizes = pv_sizes + (data['outputs']['Scenario']['Site']['Storage']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0)
|
200
305
|
status = data['outputs']['Scenario']['status']
|
201
306
|
|
202
307
|
sleep 5
|
@@ -208,14 +313,28 @@ module URBANopt # :nodoc:
|
|
208
313
|
while (_tries < _max_retry) && check_complete
|
209
314
|
sleep 1
|
210
315
|
response = make_request(http, request)
|
211
|
-
data = JSON.parse(response.body)
|
212
|
-
|
316
|
+
data = JSON.parse(response.body, allow_nan:true)
|
317
|
+
if data['outputs']['Scenario']['Site']['PV'].kind_of?(Array)
|
318
|
+
pv_sizes = 0
|
319
|
+
data['outputs']['Scenario']['Site']['PV'].each do |x|
|
320
|
+
pv_sizes = pv_sizes + x['size_kw'].to_f
|
321
|
+
end
|
322
|
+
else
|
323
|
+
pv_sizes = data['outputs']['Scenario']['Site']['PV']['size_kw'] || 0
|
324
|
+
end
|
325
|
+
sizes = pv_sizes + (data['outputs']['Scenario']['Site']['Storage']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) + (data['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0)
|
213
326
|
(check_complete = sizes == 0) && ((data['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0) > 0)
|
214
327
|
_tries += 1
|
215
328
|
end
|
216
329
|
|
217
|
-
|
218
|
-
|
330
|
+
data = JSON.parse(response.body)
|
331
|
+
text = ::JSON.generate(data, allow_nan: true)
|
332
|
+
begin
|
333
|
+
File.open(filename, 'w+') do |f|
|
334
|
+
f.puts(text)
|
335
|
+
end
|
336
|
+
rescue
|
337
|
+
@@logger.info("Cannot write - #{filename}")
|
219
338
|
end
|
220
339
|
|
221
340
|
if status == 'optimal'
|
@@ -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,
|
@@ -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,
|
@@ -29,7 +29,7 @@
|
|
29
29
|
# *********************************************************************************
|
30
30
|
|
31
31
|
require 'bundler/setup'
|
32
|
-
require 'urbanopt/
|
32
|
+
require 'urbanopt/reporting/default_reports'
|
33
33
|
require 'urbanopt/reopt/reopt_logger'
|
34
34
|
require 'urbanopt/reopt'
|
35
35
|
require 'csv'
|
@@ -43,7 +43,7 @@ module URBANopt # :nodoc:
|
|
43
43
|
#
|
44
44
|
# [*parameters:*]
|
45
45
|
#
|
46
|
-
# * +scenario_report+ - _ScenarioReport_ - Optional. A scenario report that has been returned from the URBANopt::
|
46
|
+
# * +scenario_report+ - _ScenarioReport_ - Optional. A scenario report that has been returned from the URBANopt::Reporting::ScenarioDefaultPostProcessor - used in creating default output file names in \REopt Lite optimizations.
|
47
47
|
# * +scenario_reopt_assumptions_file+ - _String_ - Optional. JSON file formatted for a \REopt Lite analysis containing custom input parameters for optimizations at the Scenario Report level
|
48
48
|
# * +reopt_feature_assumptions+ - _Array_ - Optional. A list of JSON file formatted for a \REopt Lite analysis containing custom input parameters for optimizations at the Feature Report level. The order and number of files must match the Feature Reports in the scenario_report input.
|
49
49
|
# * +use_localhost+ - _Bool_ - If this is true, requests will be sent to a version of the \REopt Lite API running on localhost. Default is false, such that the production version of \REopt Lite is accessed.
|
@@ -70,11 +70,20 @@ module URBANopt # :nodoc:
|
|
70
70
|
if !scenario_report.nil?
|
71
71
|
@scenario_report = scenario_report
|
72
72
|
|
73
|
-
|
73
|
+
if !Dir.exist?(File.join(@scenario_report.directory_name, "reopt"))
|
74
|
+
Dir.mkdir(File.join(@scenario_report.directory_name, "reopt"))
|
75
|
+
@@logger.info("Created directory: " + File.join(@scenario_report.directory_name, "reopt"))
|
76
|
+
end
|
77
|
+
|
78
|
+
@scenario_reopt_default_output_file = File.join(@scenario_report.directory_name, "reopt/scenario_report_#{@scenario_report.id}_reopt_run.json")
|
74
79
|
@scenario_timeseries_default_output_file = File.join(@scenario_report.directory_name, "scenario_report_#{@scenario_report.id}_timeseries.csv")
|
75
80
|
|
76
81
|
@scenario_report.feature_reports.each do |fr|
|
77
|
-
|
82
|
+
if !Dir.exist?(File.join(fr.directory_name, "reopt"))
|
83
|
+
Dir.mkdir(File.join(fr.directory_name, "reopt"))
|
84
|
+
@@logger.info("Created directory: " + File.join(fr.directory_name, "reopt"))
|
85
|
+
end
|
86
|
+
@feature_reports_reopt_default_output_files << File.join(fr.directory_name, "reopt/feature_report_#{fr.id}_reopt_run.json")
|
78
87
|
end
|
79
88
|
|
80
89
|
@scenario_report.feature_reports.each do |fr|
|
@@ -104,23 +113,37 @@ module URBANopt # :nodoc:
|
|
104
113
|
#
|
105
114
|
# [*parameters:*]
|
106
115
|
#
|
107
|
-
# * +feature_report+ - _URBANopt::
|
116
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport which will be used in creating and then updated by a \REopt Lite opimization response.
|
108
117
|
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A \REopt Lite formatted hash containing default parameters (i.e. utility rate, escalation rate) which will be updated by the FeatureReport (i.e. location, roof availability)
|
109
118
|
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt Lite responses will be saved.
|
110
119
|
# * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the FeatureReport will be saved.
|
111
120
|
#
|
112
|
-
# [*return:*] _URBANopt::
|
121
|
+
# [*return:*] _URBANopt::Reporting::DefaultReports::FeatureReport_ - Returns an updated FeatureReport
|
113
122
|
##
|
114
|
-
def run_feature_report(feature_report
|
123
|
+
def run_feature_report(feature_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil, run_resilience:true)
|
115
124
|
api = URBANopt::REopt::REoptLiteAPI.new(@nrel_developer_key, @localhost)
|
116
125
|
adapter = URBANopt::REopt::FeatureReportAdapter.new
|
117
126
|
|
118
127
|
reopt_input = adapter.reopt_json_from_feature_report(feature_report, reopt_assumptions_hash)
|
119
128
|
if reopt_output_file.nil?
|
120
|
-
reopt_output_file = feature_report.directory_name
|
129
|
+
reopt_output_file = File.join(feature_report.directory_name, 'reopt')
|
121
130
|
end
|
122
131
|
reopt_output = api.reopt_request(reopt_input, reopt_output_file)
|
123
|
-
|
132
|
+
if run_resilience
|
133
|
+
run_uuid = reopt_output['outputs']['Scenario']['run_uuid']
|
134
|
+
if File.directory? reopt_output_file
|
135
|
+
resilience_stats = api.resilience_request(run_uuid, reopt_output_file)
|
136
|
+
else
|
137
|
+
resilience_stats = api.resilience_request(run_uuid, reopt_output_file.sub!('.json','_resilience.json'))
|
138
|
+
end
|
139
|
+
else
|
140
|
+
resilience_stats = nil
|
141
|
+
end
|
142
|
+
result = adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path, resilience_stats)
|
143
|
+
if !save_name.nil?
|
144
|
+
result.save_feature_report save_name
|
145
|
+
end
|
146
|
+
return result
|
124
147
|
end
|
125
148
|
|
126
149
|
##
|
@@ -129,13 +152,13 @@ module URBANopt # :nodoc:
|
|
129
152
|
#
|
130
153
|
# [*parameters:*]
|
131
154
|
#
|
132
|
-
# * +feature_report+ - _URBANopt::
|
155
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport which will be used in creating and then updated by a \REopt Lite opimization response.
|
133
156
|
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A \REopt Lite formatted hash containing default parameters (i.e. utility rate, escalation rate) which will be updated by the ScenarioReport (i.e. location, roof availability)
|
134
157
|
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt Lite responses will be saved.
|
135
158
|
# * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the ScenarioReport will be saved.
|
136
159
|
#
|
137
160
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ Returns an updated ScenarioReport
|
138
|
-
def run_scenario_report(scenario_report
|
161
|
+
def run_scenario_report(scenario_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil, run_resilience:true)
|
139
162
|
if !reopt_assumptions_hash.nil?
|
140
163
|
@scenario_reopt_default_assumptions_hash = reopt_assumptions_hash
|
141
164
|
end
|
@@ -152,8 +175,22 @@ module URBANopt # :nodoc:
|
|
152
175
|
reopt_input = adapter.reopt_json_from_scenario_report(scenario_report, @scenario_reopt_default_assumptions_hash)
|
153
176
|
|
154
177
|
reopt_output = api.reopt_request(reopt_input, @scenario_reopt_default_output_file)
|
178
|
+
if run_resilience
|
179
|
+
run_uuid = reopt_output['outputs']['Scenario']['run_uuid']
|
180
|
+
if File.directory? @scenario_reopt_default_output_file
|
181
|
+
resilience_stats = api.resilience_request(run_uuid, @scenario_reopt_default_output_file)
|
182
|
+
else
|
183
|
+
resilience_stats = api.resilience_request(run_uuid, @scenario_reopt_default_output_file.sub!('.json','_resilience.json'))
|
184
|
+
end
|
185
|
+
else
|
186
|
+
resilience_stats = nil
|
187
|
+
end
|
155
188
|
|
156
|
-
|
189
|
+
result = adapter.update_scenario_report(scenario_report, reopt_output, @scenario_timeseries_default_output_file, resilience_stats)
|
190
|
+
if !save_name.nil?
|
191
|
+
result.save save_name
|
192
|
+
end
|
193
|
+
return result
|
157
194
|
end
|
158
195
|
|
159
196
|
# Updates a set of FeatureReports based on an optional set of \REopt Lite optimization assumptions.
|
@@ -161,13 +198,14 @@ module URBANopt # :nodoc:
|
|
161
198
|
#
|
162
199
|
# [*parameters:*]
|
163
200
|
#
|
164
|
-
# * +feature_reports+ - _Array_ - An array of _URBANopt::
|
201
|
+
# * +feature_reports+ - _Array_ - An array of _URBANopt::Reporting::DefaultReports::FeatureReport_ objetcs which will each be used to create (and are subsquently updated by) a \REopt Lite opimization response.
|
165
202
|
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of \REopt Lite formatted hashes containing default parameters (i.e. utility rate, escalation rate) which will be updated by the ScenarioReport (i.e. location, roof availability). The number and order of the hashes should match the feature_reports array.
|
166
203
|
# * +reopt_output_files+ - _Array_ - Optional. A array of paths to files at which REpopt Lite responses will be saved. The number and order of the paths should match the feature_reports array.
|
167
204
|
# * +timeseries_csv_path+ - _Array_ - Optional. A array of paths to files at which the new timeseries CSV for the FeatureReports will be saved. The number and order of the paths should match the feature_reports array.
|
168
205
|
#
|
169
206
|
# [*return:*] _Array_ Returns an array of updated _URBANopt::Scenario::DefaultReports::FeatureReport_ objects
|
170
|
-
def run_feature_reports(feature_reports
|
207
|
+
def run_feature_reports(feature_reports:, reopt_assumptions_hashes:[], reopt_output_files:[], timeseries_csv_paths:[], save_names:nil, run_resilience:true)
|
208
|
+
|
171
209
|
if !reopt_assumptions_hashes.empty?
|
172
210
|
@feature_reports_reopt_default_assumption_hashes = reopt_assumptions_hashes
|
173
211
|
end
|
@@ -182,7 +220,7 @@ module URBANopt # :nodoc:
|
|
182
220
|
|
183
221
|
if @feature_reports_reopt_default_output_files.empty?
|
184
222
|
feature_reports.each do |fr|
|
185
|
-
@feature_reports_reopt_default_output_files << File.join(fr.directory_name, "feature_report_#{fr.id}_reopt_run.json")
|
223
|
+
@feature_reports_reopt_default_output_files << File.join(fr.directory_name, "reopt/feature_report_#{fr.id}_reopt_run.json")
|
186
224
|
end
|
187
225
|
end
|
188
226
|
|
@@ -198,12 +236,26 @@ module URBANopt # :nodoc:
|
|
198
236
|
feature_reports.each_with_index do |feature_report, idx|
|
199
237
|
begin
|
200
238
|
reopt_input = feature_adapter.reopt_json_from_feature_report(feature_report, @feature_reports_reopt_default_assumption_hashes[idx])
|
201
|
-
if reopt_output_files[idx].nil?
|
202
|
-
reopt_output_files[idx] = feature_report.directory_name
|
203
|
-
end
|
204
239
|
reopt_output = api.reopt_request(reopt_input, @feature_reports_reopt_default_output_files[idx])
|
205
|
-
|
240
|
+
if run_resilience
|
241
|
+
run_uuid = reopt_output['outputs']['Scenario']['run_uuid']
|
242
|
+
if File.directory? @feature_reports_reopt_default_output_files[idx]
|
243
|
+
resilience_stats = api.resilience_request(run_uuid, @feature_reports_reopt_default_output_files[idx])
|
244
|
+
else
|
245
|
+
resilience_stats = api.resilience_request(run_uuid, @feature_reports_reopt_default_output_files[idx].sub!('.json','_resilience.json'))
|
246
|
+
end
|
247
|
+
else
|
248
|
+
resilience_stats = nil
|
249
|
+
end
|
250
|
+
new_feature_report = feature_adapter.update_feature_report(feature_report, reopt_output, @feature_reports_timeseries_default_output_files[idx], resilience_stats)
|
206
251
|
new_feature_reports.push(new_feature_report)
|
252
|
+
if !save_names.nil?
|
253
|
+
if save_names.length == feature_reports.length
|
254
|
+
new_feature_report.save_feature_report save_names[idx]
|
255
|
+
else
|
256
|
+
warn "Could not save feature reports - the number of save names provided did not match the number of feature reports"
|
257
|
+
end
|
258
|
+
end
|
207
259
|
rescue StandardError
|
208
260
|
@@logger.info("Could not optimize Feature Report #{feature_report.name} #{feature_report.id}")
|
209
261
|
end
|
@@ -217,27 +269,29 @@ module URBANopt # :nodoc:
|
|
217
269
|
#
|
218
270
|
# [*parameters:*]
|
219
271
|
#
|
220
|
-
# * +scenario_report+ - _Array_ - A _URBANopt::
|
272
|
+
# * +scenario_report+ - _Array_ - A _URBANopt::Reporting::DefaultReports::ScenarioReport_ which will each be used to create (and is subsquently updated by) \REopt Lite opimization responses for each of its FeatureReports.
|
221
273
|
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of \REopt Lite formatted hashes containing default parameters (i.e. utility rate, escalation rate) which will be updated by the ScenarioReport (i.e. location, roof availability). The number and order of the hashes should match the array in ScenarioReport.feature_reports.
|
222
274
|
# * +reopt_output_files+ - _Array_ - Optional. An array of paths to files at which REpopt Lite responses will be saved. The number and order of the paths should match the array in ScenarioReport.feature_reports.
|
223
275
|
# * +feature_report_timeseries_csv_paths+ - _Array_ - Optional. An array of paths to files at which the new timeseries CSV for the FeatureReports will be saved. The number and order of the paths should match the array in ScenarioReport.feature_reports.
|
224
276
|
#
|
225
277
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
|
226
|
-
def run_scenario_report_features(scenario_report
|
227
|
-
new_feature_reports = run_feature_reports(scenario_report.feature_reports, reopt_assumptions_hashes, reopt_output_files, feature_report_timeseries_csv_paths)
|
278
|
+
def run_scenario_report_features(scenario_report:, reopt_assumptions_hashes:[], reopt_output_files:[], feature_report_timeseries_csv_paths:[], save_names_feature_reports:nil, save_name_scenario_report:nil, run_resilience:true)
|
279
|
+
new_feature_reports = run_feature_reports(feature_reports:scenario_report.feature_reports, reopt_assumptions_hashes:reopt_assumptions_hashes, reopt_output_files:reopt_output_files, timeseries_csv_paths:feature_report_timeseries_csv_paths,save_names:save_names_feature_reports, run_resilience:run_resilience)
|
228
280
|
|
229
|
-
new_scenario_report = URBANopt::
|
281
|
+
new_scenario_report = URBANopt::Reporting::DefaultReports::ScenarioReport.new
|
230
282
|
new_scenario_report.id = scenario_report.id
|
231
283
|
new_scenario_report.name = scenario_report.name
|
232
284
|
new_scenario_report.directory_name = scenario_report.directory_name
|
233
285
|
|
234
286
|
timeseries_hash = { column_names: scenario_report.timeseries_csv.column_names }
|
235
|
-
new_scenario_report.timeseries_csv = URBANopt::
|
287
|
+
new_scenario_report.timeseries_csv = URBANopt::Reporting::DefaultReports::TimeseriesCSV.new(timeseries_hash)
|
236
288
|
|
237
289
|
new_feature_reports.each do |feature_report|
|
238
290
|
new_scenario_report.add_feature_report(feature_report)
|
239
291
|
end
|
240
|
-
|
292
|
+
if !save_name_scenario_report.nil?
|
293
|
+
new_scenario_report.save save_name_scenario_report
|
294
|
+
end
|
241
295
|
return new_scenario_report
|
242
296
|
end
|
243
297
|
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,
|