urbanopt-reopt 0.10.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/release.yml +25 -0
- data/.github/workflows/nightly_ci_build.yml +10 -3
- data/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/LICENSE.md +1 -1
- data/RDOC_MAIN.md +19 -19
- data/README.md +20 -20
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/docs/README.md +18 -18
- data/docs/package-lock.json +4806 -4836
- data/docs/schemas/reopt-input-schema.md +25 -23
- data/docs/schemas/reopt-output-schema.md +7 -7
- data/index.md +22 -22
- data/lib/urbanopt/reopt/feature_report_adapter.rb +241 -208
- data/lib/urbanopt/reopt/reopt_lite_api.rb +98 -59
- data/lib/urbanopt/reopt/reopt_post_processor.rb +34 -33
- data/lib/urbanopt/reopt/reopt_schema/reopt_input_schema.json +1126 -1106
- data/lib/urbanopt/reopt/reopt_schema/reopt_output_schema.json +449 -524
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +7 -7
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +275 -240
- data/lib/urbanopt/reopt/version.rb +1 -1
- data/urbanopt-reopt.gemspec +5 -3
- metadata +35 -8
- data/Jenkinsfile +0 -10
@@ -16,21 +16,21 @@ module URBANopt # :nodoc:
|
|
16
16
|
module REopt # :nodoc:
|
17
17
|
class REoptLiteAPI
|
18
18
|
##
|
19
|
-
# \REoptLiteAPI manages submitting optimization tasks to the \REopt
|
20
|
-
# Results can either be sourced from the production \REopt
|
19
|
+
# \REoptLiteAPI manages submitting optimization tasks to the \REopt API and recieving results.
|
20
|
+
# Results can either be sourced from the production \REopt API with an API key from developer.nrel.gov, or from
|
21
21
|
# a version running at localhost.
|
22
22
|
##
|
23
23
|
#
|
24
24
|
# [*parameters:*]
|
25
25
|
#
|
26
|
-
# * +use_localhost+ - _Bool_ - If this is true, requests will be sent to a version of the \REopt
|
27
|
-
# * +nrel_developer_key+ - _String_ - API key used to access the \REopt
|
26
|
+
# * +use_localhost+ - _Bool_ - If this is true, requests will be sent to a version of the \REopt API running on localhost. Default is false, such that the production version of \REopt is accessed.
|
27
|
+
# * +nrel_developer_key+ - _String_ - API key used to access the \REopt APi. Required only if localhost is false. Obtain from https://developer.nrel.gov/signup/
|
28
28
|
##
|
29
29
|
def initialize(nrel_developer_key = nil, use_localhost = false)
|
30
30
|
@use_localhost = use_localhost
|
31
31
|
if @use_localhost
|
32
|
-
@uri_submit = URI.parse('http//:127.0.0.1:8000/
|
33
|
-
@uri_submit_outagesimjob = URI.parse('http//:127.0.0.1:8000/
|
32
|
+
@uri_submit = URI.parse('http//:127.0.0.1:8000/v3/job/')
|
33
|
+
@uri_submit_outagesimjob = URI.parse('http//:127.0.0.1:8000/v3/outagesimjob/')
|
34
34
|
else
|
35
35
|
if [nil, '', '<insert your key here>'].include? nrel_developer_key
|
36
36
|
if [nil, '', '<insert your key here>'].include? DEVELOPER_NREL_KEY
|
@@ -40,8 +40,8 @@ module URBANopt # :nodoc:
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
@nrel_developer_key = nrel_developer_key
|
43
|
-
@uri_submit = URI.parse("https://developer.nrel.gov/api/reopt/
|
44
|
-
@uri_submit_outagesimjob = URI.parse("https://developer.nrel.gov/api/reopt/
|
43
|
+
@uri_submit = URI.parse("https://developer.nrel.gov/api/reopt/v3/job?api_key=#{@nrel_developer_key}")
|
44
|
+
@uri_submit_outagesimjob = URI.parse("https://developer.nrel.gov/api/reopt/v3/outagesimjob?api_key=#{@nrel_developer_key}")
|
45
45
|
# initialize @@logger
|
46
46
|
@@logger ||= URBANopt::REopt.reopt_logger
|
47
47
|
end
|
@@ -53,16 +53,16 @@ module URBANopt # :nodoc:
|
|
53
53
|
#
|
54
54
|
# [*parameters:*]
|
55
55
|
#
|
56
|
-
# * +run_uuid+ - _String_ - Unique run_uuid obtained from the \REopt
|
56
|
+
# * +run_uuid+ - _String_ - Unique run_uuid obtained from the \REopt job submittal URL for a specific optimization task.
|
57
57
|
#
|
58
|
-
# [*return:*] _URI_ - Returns URI object for use in calling the \REopt
|
58
|
+
# [*return:*] _URI_ - Returns URI object for use in calling the \REopt results endpoint for a specifc optimization task.
|
59
59
|
##
|
60
60
|
def uri_results(run_uuid) # :nodoc:
|
61
61
|
if @use_localhost
|
62
|
-
return URI.parse("http://127.0.0.1:8000/
|
62
|
+
return URI.parse("http://127.0.0.1:8000/v3/job/#{run_uuid}/results")
|
63
63
|
end
|
64
64
|
|
65
|
-
return URI.parse("https://developer.nrel.gov/api/reopt/
|
65
|
+
return URI.parse("https://developer.nrel.gov/api/reopt/v3/job/#{run_uuid}/results?api_key=#{@nrel_developer_key}")
|
66
66
|
end
|
67
67
|
|
68
68
|
##
|
@@ -71,16 +71,16 @@ module URBANopt # :nodoc:
|
|
71
71
|
#
|
72
72
|
# [*parameters:*]
|
73
73
|
#
|
74
|
-
# * +run_uuid+ - _String_ - Resilience statistics for a unique run_uuid obtained from the \REopt
|
74
|
+
# * +run_uuid+ - _String_ - Resilience statistics for a unique run_uuid obtained from the \REopt job submittal URL for a specific optimization task.
|
75
75
|
#
|
76
|
-
# [*return:*] _URI_ - Returns URI object for use in calling the \REopt
|
76
|
+
# [*return:*] _URI_ - Returns URI object for use in calling the \REopt resilience statistics endpoint for a specifc optimization task.
|
77
77
|
##
|
78
78
|
def uri_resilience(run_uuid) # :nodoc:
|
79
79
|
if @use_localhost
|
80
|
-
return URI.parse("http://127.0.0.1:8000/
|
80
|
+
return URI.parse("http://127.0.0.1:8000/v3/job/#{run_uuid}/resilience_stats")
|
81
81
|
end
|
82
82
|
|
83
|
-
return URI.parse("https://developer.nrel.gov/api/reopt/
|
83
|
+
return URI.parse("https://developer.nrel.gov/api/reopt/v3/job/#{run_uuid}/resilience_stats?api_key=#{@nrel_developer_key}")
|
84
84
|
end
|
85
85
|
|
86
86
|
def make_request(http, req, max_tries = 3)
|
@@ -91,7 +91,7 @@ module URBANopt # :nodoc:
|
|
91
91
|
result = http.request(req)
|
92
92
|
# Result codes sourced from https://developer.nrel.gov/docs/errors/
|
93
93
|
if result.code == '429'
|
94
|
-
@@logger.fatal('Exceeded the REopt
|
94
|
+
@@logger.fatal('Exceeded the REopt API limit of 300 requests per hour')
|
95
95
|
puts 'Using the URBANopt CLI to submit a Scenario optimization counts as one request per scenario'
|
96
96
|
puts 'Using the URBANopt CLI to submit a Feature optimization counts as one request per feature'
|
97
97
|
abort('Please wait and try again once the time period has elapsed. The URBANopt CLI flag --reopt-keep-existing can be used to resume the optimization')
|
@@ -101,7 +101,7 @@ module URBANopt # :nodoc:
|
|
101
101
|
tries += 1
|
102
102
|
next
|
103
103
|
elsif (result.code != '201') && (result.code != '200') # Anything in the 200s is success
|
104
|
-
@@logger.warn("REopt
|
104
|
+
@@logger.warn("REopt has returned a '#{result.code}' status code. Visit https://developer.nrel.gov/docs/errors/ for more status code information")
|
105
105
|
# display error messages
|
106
106
|
json_res = JSON.parse(result.body, allow_nan: true)
|
107
107
|
json_res['messages'].delete('warnings') if json_res['messages']['warnings']
|
@@ -112,7 +112,7 @@ module URBANopt # :nodoc:
|
|
112
112
|
end
|
113
113
|
tries = max_tries
|
114
114
|
rescue StandardError => e
|
115
|
-
@@logger.debug("error from REopt
|
115
|
+
@@logger.debug("error from REopt API: #{e}")
|
116
116
|
if tries + 1 < max_tries
|
117
117
|
@@logger.debug('trying again...')
|
118
118
|
else
|
@@ -126,12 +126,12 @@ module URBANopt # :nodoc:
|
|
126
126
|
end
|
127
127
|
|
128
128
|
##
|
129
|
-
# Checks if a optimization task can be submitted to the \REopt
|
129
|
+
# Checks if a optimization task can be submitted to the \REopt API
|
130
130
|
##
|
131
131
|
#
|
132
132
|
# [*parameters:*]
|
133
133
|
#
|
134
|
-
# * +data+ - _Hash_ - Default \REopt
|
134
|
+
# * +data+ - _Hash_ - Default \REopt formatted post containing at least all the required parameters.
|
135
135
|
#
|
136
136
|
# [*return:*] _Bool_ - Returns true if the post succeeeds. Otherwise returns false.
|
137
137
|
##
|
@@ -156,15 +156,15 @@ module URBANopt # :nodoc:
|
|
156
156
|
end
|
157
157
|
|
158
158
|
##
|
159
|
-
# Completes a \REopt
|
159
|
+
# Completes a \REopt optimization. From a formatted hash, an optimization task is submitted to the API.
|
160
160
|
# Results are polled at 5 second interval until they are ready or an error is returned from the API. Results
|
161
161
|
# are written to disk.
|
162
162
|
##
|
163
163
|
#
|
164
164
|
# [*parameters:*]
|
165
165
|
#
|
166
|
-
# * +reopt_input+ - _Hash_ - \REopt
|
167
|
-
# * +filename+ - _String_ - Path to file that will be created containing the full \REopt
|
166
|
+
# * +reopt_input+ - _Hash_ - \REopt formatted post containing at least required parameters.
|
167
|
+
# * +filename+ - _String_ - Path to file that will be created containing the full \REopt response.
|
168
168
|
#
|
169
169
|
# [*return:*] _Bool_ - Returns true if the post succeeeds. Otherwise returns false.
|
170
170
|
##
|
@@ -199,21 +199,21 @@ module URBANopt # :nodoc:
|
|
199
199
|
http.use_ssl = true
|
200
200
|
end
|
201
201
|
|
202
|
-
# Wait
|
203
|
-
sleep
|
202
|
+
# Wait for the REopt API before attempting to GET results
|
203
|
+
sleep 30
|
204
204
|
get_request = Net::HTTP::Get.new(uri.request_uri)
|
205
205
|
response = make_request(http, get_request, 8)
|
206
206
|
|
207
207
|
# Set a limit on retries when 404s are returned from REopt API
|
208
208
|
elapsed_time = 0
|
209
|
-
max_elapsed_time = 60 *
|
209
|
+
max_elapsed_time = 60 * 15
|
210
210
|
|
211
|
-
# If database still hasn't updated, wait
|
211
|
+
# If database still hasn't updated, wait longer and try again
|
212
212
|
while (elapsed_time < max_elapsed_time) && (response && response.code == '404')
|
213
213
|
response = make_request(http, get_request)
|
214
|
-
@@logger.warn('GET request was too fast for REOpt-
|
215
|
-
elapsed_time +=
|
216
|
-
sleep
|
214
|
+
@@logger.warn('GET request was too fast for REOpt-API. Retrying...')
|
215
|
+
elapsed_time += 15
|
216
|
+
sleep 15
|
217
217
|
end
|
218
218
|
|
219
219
|
data = JSON.parse(response.body, allow_nan: true)
|
@@ -236,22 +236,22 @@ module URBANopt # :nodoc:
|
|
236
236
|
end
|
237
237
|
|
238
238
|
##
|
239
|
-
# Completes a \REopt
|
239
|
+
# Completes a \REopt optimization. From a formatted hash, an optimization task is submitted to the API.
|
240
240
|
# Results are polled at 5 second interval until they are ready or an error is returned from the API. Results
|
241
241
|
# are written to disk.
|
242
242
|
##
|
243
243
|
#
|
244
244
|
# [*parameters:*]
|
245
245
|
#
|
246
|
-
# * +reopt_input+ - _Hash_ - \REopt
|
247
|
-
# * +filename+ - _String_ - Path to file that will be created containing the full \REopt
|
246
|
+
# * +reopt_input+ - _Hash_ - \REopt formatted post containing at least required parameters.
|
247
|
+
# * +filename+ - _String_ - Path to file that will be created containing the full \REopt response.
|
248
248
|
#
|
249
249
|
# [*return:*] _Bool_ - Returns true if the post succeeeds. Otherwise returns false.
|
250
250
|
##
|
251
251
|
def reopt_request(reopt_input, filename)
|
252
|
-
description = reopt_input[:
|
252
|
+
description = reopt_input[:description]
|
253
253
|
|
254
|
-
@@logger.info("Submitting #{description} to REopt
|
254
|
+
@@logger.info("Submitting #{description} to REopt API")
|
255
255
|
|
256
256
|
# Format the request
|
257
257
|
header = { 'Content-Type' => 'application/json' }
|
@@ -266,7 +266,7 @@ module URBANopt # :nodoc:
|
|
266
266
|
response = make_request(http, post_request)
|
267
267
|
if !response.is_a?(Net::HTTPSuccess)
|
268
268
|
@@logger.error('make_request Failed')
|
269
|
-
raise '
|
269
|
+
raise 'REopt connection Failed'
|
270
270
|
end
|
271
271
|
|
272
272
|
# Get UUID
|
@@ -301,45 +301,84 @@ module URBANopt # :nodoc:
|
|
301
301
|
|
302
302
|
get_request = Net::HTTP::Get.new(uri.request_uri)
|
303
303
|
|
304
|
+
counter = 0
|
304
305
|
while status == 'Optimizing...'
|
305
306
|
response = make_request(http, get_request)
|
306
307
|
|
307
308
|
data = JSON.parse(response.body, allow_nan: true)
|
308
309
|
|
309
|
-
if data['outputs']['
|
310
|
+
if !data['outputs']['PV']
|
310
311
|
pv_sizes = 0
|
311
|
-
|
312
|
-
pv_sizes += x['size_kw'].to_f
|
313
|
-
end
|
312
|
+
sizes = 0
|
314
313
|
else
|
315
|
-
|
314
|
+
# there should be results in there now
|
315
|
+
if data['outputs']['PV'].is_a?(Array)
|
316
|
+
pv_sizes = 0
|
317
|
+
data['outputs']['PV'].each do |x|
|
318
|
+
pv_sizes += x['size_kw'].to_f
|
319
|
+
end
|
320
|
+
else
|
321
|
+
data['outputs'].each do |energy_source, data|
|
322
|
+
if data.is_a?(Hash) && data.key?('size_kw')
|
323
|
+
@@logger.debug("#{energy_source}: size_kw = #{data['size_kw'].to_f}")
|
324
|
+
sizes += data['size_kw'].to_f
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
316
328
|
end
|
317
|
-
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)
|
318
|
-
status = data['outputs']['Scenario']['status']
|
319
329
|
|
320
|
-
|
330
|
+
status = data['status']
|
331
|
+
@@logger.debug("STATUS: #{status}")
|
332
|
+
|
333
|
+
if status == 'error'
|
334
|
+
puts "response.code: #{response.code}"
|
335
|
+
puts "message: #{response.message}"
|
336
|
+
error_message = data['messages']['errors']
|
337
|
+
raise "Error from REopt API - #{error_message}"
|
338
|
+
end
|
339
|
+
|
340
|
+
sleep 15
|
321
341
|
end
|
322
342
|
|
323
343
|
max_retry = 5
|
324
344
|
tries = 0
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
345
|
+
|
346
|
+
check_complete = sizes == 0
|
347
|
+
# I don't know what this line does:
|
348
|
+
# (((data['outputs'] && data['outputs'].key?('Financial') && data['outputs']['Financial']['npv']) || 0) > 0)
|
349
|
+
|
350
|
+
if check_complete
|
351
|
+
@@logger.info('sizes are 0...checking optimization complete')
|
352
|
+
|
353
|
+
while (tries < max_retry) && check_complete
|
354
|
+
sleep 3
|
355
|
+
response = make_request(http, get_request)
|
356
|
+
data = JSON.parse(response.body, allow_nan: true)
|
357
|
+
|
358
|
+
if data['outputs'].key?('PV') && data['outputs']['PV'].is_a?(Array)
|
359
|
+
pv_sizes = 0
|
360
|
+
data['outputs']['PV'].each do |x|
|
361
|
+
pv_sizes += x['size_kw'].to_f
|
362
|
+
end
|
363
|
+
else
|
364
|
+
data['outputs'].each do |energy_source, data|
|
365
|
+
if data.is_a?(Hash) && data.key?('size_kw')
|
366
|
+
@@logger.debug("#{energy_source}: size_kw = #{data['size_kw'].to_f}")
|
367
|
+
sizes += data['size_kw'].to_f
|
368
|
+
end
|
369
|
+
end
|
334
370
|
end
|
335
|
-
|
336
|
-
|
371
|
+
|
372
|
+
# I don't understand this line fully:
|
373
|
+
#(check_complete = sizes == 0) && ((data['outputs']['Financial']['npv'] || 0) > 0)
|
374
|
+
|
375
|
+
check_complete = sizes == 0
|
376
|
+
tries += 1
|
337
377
|
end
|
338
|
-
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)
|
339
|
-
(check_complete = sizes == 0) && ((data['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0) > 0)
|
340
|
-
tries += 1
|
341
378
|
end
|
342
379
|
|
380
|
+
@@logger.info('REopt optimization complete and processed')
|
381
|
+
|
343
382
|
data = JSON.parse(response.body, allow_nan: true)
|
344
383
|
text = JSON.pretty_generate(data)
|
345
384
|
begin
|
@@ -7,21 +7,22 @@ require 'bundler/setup'
|
|
7
7
|
require 'urbanopt/reporting/default_reports'
|
8
8
|
require 'urbanopt/reopt/reopt_logger'
|
9
9
|
require 'csv'
|
10
|
+
require 'json'
|
10
11
|
|
11
12
|
module URBANopt # :nodoc:
|
12
13
|
module REopt # :nodoc:
|
13
14
|
class REoptPostProcessor
|
14
15
|
##
|
15
|
-
# \REoptPostProcessor updates a ScenarioReport or FeatureReport based on \REopt
|
16
|
+
# \REoptPostProcessor updates a ScenarioReport or FeatureReport based on \REopt optimization response.
|
16
17
|
##
|
17
18
|
#
|
18
19
|
# [*parameters:*]
|
19
20
|
#
|
20
|
-
# * +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
|
21
|
-
# * +scenario_reopt_assumptions_file+ - _String_ - Optional. JSON file formatted for a \REopt
|
22
|
-
# * +reopt_feature_assumptions+ - _Array_ - Optional. A list of JSON file formatted for a \REopt
|
23
|
-
# * +use_localhost+ - _Bool_ - If this is true, requests will be sent to a version of the \REopt
|
24
|
-
# * +nrel_developer_key+ - _String_ - API used to access the \REopt
|
21
|
+
# * +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 optimizations.
|
22
|
+
# * +scenario_reopt_assumptions_file+ - _String_ - Optional. JSON file formatted for a \REopt analysis containing custom input parameters for optimizations at the Scenario Report level
|
23
|
+
# * +reopt_feature_assumptions+ - _Array_ - Optional. A list of JSON file formatted for a \REopt 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.
|
24
|
+
# * +use_localhost+ - _Bool_ - If this is true, requests will be sent to a version of the \REopt API running on localhost. Default is false, such that the production version of \REopt is accessed.
|
25
|
+
# * +nrel_developer_key+ - _String_ - API used to access the \REopt APi. Required only if +localhost+ is false. Obtain from https://developer.nrel.gov/signup/
|
25
26
|
##
|
26
27
|
def initialize(scenario_report, scenario_reopt_assumptions_file = nil, reopt_feature_assumptions = [], nrel_developer_key = nil, localhost = false)
|
27
28
|
# initialize @@logger
|
@@ -32,7 +33,7 @@ module URBANopt # :nodoc:
|
|
32
33
|
end
|
33
34
|
@nrel_developer_key = nrel_developer_key
|
34
35
|
@localhost = localhost
|
35
|
-
@reopt_base_post = {
|
36
|
+
@reopt_base_post = { ElectricTariff: {}, ElectricLoad: {}, Wind: { max_kw: 0 } }
|
36
37
|
|
37
38
|
@scenario_reopt_default_output_file = nil
|
38
39
|
@scenario_timeseries_default_output_file = nil
|
@@ -80,19 +81,19 @@ module URBANopt # :nodoc:
|
|
80
81
|
attr_accessor :scenario_reopt_default_assumptions_hash, :scenario_reopt_default_output_file, :scenario_timeseries_default_output_file, :feature_reports_reopt_default_assumption_hashes, :feature_reports_reopt_default_output_files, :feature_reports_timeseries_default_output_files
|
81
82
|
|
82
83
|
##
|
83
|
-
# Updates a FeatureReport based on an optional set of \REopt
|
84
|
+
# Updates a FeatureReport based on an optional set of \REopt optimization assumptions.
|
84
85
|
##
|
85
86
|
#
|
86
87
|
# [*parameters:*]
|
87
88
|
#
|
88
|
-
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport which will be used in creating and then updated by a \REopt
|
89
|
-
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A \REopt
|
90
|
-
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt
|
89
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport which will be used in creating and then updated by a \REopt opimization response.
|
90
|
+
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A \REopt formatted hash containing default parameters (i.e. utility rate, escalation rate) which will be updated by the FeatureReport (i.e. location, roof availability)
|
91
|
+
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt responses will be saved.
|
91
92
|
# * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the FeatureReport will be saved.
|
92
93
|
#
|
93
94
|
# [*return:*] _URBANopt::Reporting::DefaultReports::FeatureReport_ - Returns an updated FeatureReport
|
94
95
|
##
|
95
|
-
def run_feature_report(feature_report:, reopt_assumptions_hash: nil, reopt_output_file: nil, timeseries_csv_path: nil, save_name: nil, run_resilience:
|
96
|
+
def run_feature_report(feature_report:, reopt_assumptions_hash: nil, reopt_output_file: nil, timeseries_csv_path: nil, save_name: nil, run_resilience: false)
|
96
97
|
api = URBANopt::REopt::REoptLiteAPI.new(@nrel_developer_key, @localhost)
|
97
98
|
adapter = URBANopt::REopt::FeatureReportAdapter.new
|
98
99
|
|
@@ -103,7 +104,7 @@ module URBANopt # :nodoc:
|
|
103
104
|
reopt_output = api.reopt_request(reopt_input, reopt_output_file)
|
104
105
|
@@logger.debug("REOpt output file: #{reopt_output_file}")
|
105
106
|
if run_resilience
|
106
|
-
run_uuid = reopt_output['outputs']['
|
107
|
+
run_uuid = reopt_output['outputs']['run_uuid']
|
107
108
|
if File.directory? reopt_output_file
|
108
109
|
resilience_stats = api.resilience_request(run_uuid, reopt_output_file)
|
109
110
|
else
|
@@ -112,6 +113,7 @@ module URBANopt # :nodoc:
|
|
112
113
|
else
|
113
114
|
resilience_stats = nil
|
114
115
|
end
|
116
|
+
|
115
117
|
result = adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path, resilience_stats)
|
116
118
|
if !save_name.nil?
|
117
119
|
result.save save_name
|
@@ -120,19 +122,18 @@ module URBANopt # :nodoc:
|
|
120
122
|
end
|
121
123
|
|
122
124
|
##
|
123
|
-
# Updates a ScenarioReport based on an optional set of \REopt
|
125
|
+
# Updates a ScenarioReport based on an optional set of \REopt optimization assumptions.
|
124
126
|
##
|
125
127
|
#
|
126
128
|
# [*parameters:*]
|
127
129
|
#
|
128
|
-
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport which will be used in creating and then updated by a \REopt
|
129
|
-
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A \REopt
|
130
|
-
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt
|
130
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport which will be used in creating and then updated by a \REopt opimization response.
|
131
|
+
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A \REopt formatted hash containing default parameters (i.e. utility rate, escalation rate) which will be updated by the ScenarioReport (i.e. location, roof availability)
|
132
|
+
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt responses will be saved.
|
131
133
|
# * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the ScenarioReport will be saved.
|
132
134
|
#
|
133
135
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ Returns an updated ScenarioReport
|
134
|
-
def run_scenario_report(scenario_report:, reopt_assumptions_hash: nil, reopt_output_file: nil, timeseries_csv_path: nil, save_name: nil, run_resilience:
|
135
|
-
puts 'run scenario report'
|
136
|
+
def run_scenario_report(scenario_report:, reopt_assumptions_hash: nil, reopt_output_file: nil, timeseries_csv_path: nil, save_name: nil, run_resilience: false, community_photovoltaic: nil)
|
136
137
|
@save_assumptions_filepath = false
|
137
138
|
if !reopt_assumptions_hash.nil?
|
138
139
|
@scenario_reopt_default_assumptions_hash = reopt_assumptions_hash
|
@@ -150,10 +151,10 @@ module URBANopt # :nodoc:
|
|
150
151
|
adapter = URBANopt::REopt::ScenarioReportAdapter.new
|
151
152
|
|
152
153
|
reopt_input = adapter.reopt_json_from_scenario_report(scenario_report, @scenario_reopt_default_assumptions_hash, community_photovoltaic)
|
153
|
-
|
154
154
|
reopt_output = api.reopt_request(reopt_input, @scenario_reopt_default_output_file)
|
155
|
+
|
155
156
|
if run_resilience
|
156
|
-
run_uuid = reopt_output['outputs']['
|
157
|
+
run_uuid = reopt_output['outputs']['run_uuid']
|
157
158
|
if File.directory? @scenario_reopt_default_output_file
|
158
159
|
resilience_stats = api.resilience_request(run_uuid, @scenario_reopt_default_output_file)
|
159
160
|
else
|
@@ -176,18 +177,18 @@ module URBANopt # :nodoc:
|
|
176
177
|
return result
|
177
178
|
end
|
178
179
|
|
179
|
-
# Updates a set of FeatureReports based on an optional set of \REopt
|
180
|
+
# Updates a set of FeatureReports based on an optional set of \REopt optimization assumptions.
|
180
181
|
##
|
181
182
|
#
|
182
183
|
# [*parameters:*]
|
183
184
|
#
|
184
|
-
# * +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
|
185
|
-
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of \REopt
|
186
|
-
# * +reopt_output_files+ - _Array_ - Optional. A array of paths to files at which REpopt
|
185
|
+
# * +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 opimization response.
|
186
|
+
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of \REopt 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.
|
187
|
+
# * +reopt_output_files+ - _Array_ - Optional. A array of paths to files at which REpopt responses will be saved. The number and order of the paths should match the feature_reports array.
|
187
188
|
# * +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.
|
188
189
|
#
|
189
190
|
# [*return:*] _Array_ Returns an array of updated _URBANopt::Scenario::DefaultReports::FeatureReport_ objects
|
190
|
-
def run_feature_reports(feature_reports:, reopt_assumptions_hashes: [], reopt_output_files: [], timeseries_csv_paths: [], save_names: nil, run_resilience:
|
191
|
+
def run_feature_reports(feature_reports:, reopt_assumptions_hashes: [], reopt_output_files: [], timeseries_csv_paths: [], save_names: nil, run_resilience: false, keep_existing_output: false, groundmount_photovoltaic: nil)
|
191
192
|
if !reopt_assumptions_hashes.empty?
|
192
193
|
@feature_reports_reopt_default_assumption_hashes = reopt_assumptions_hashes
|
193
194
|
end
|
@@ -222,7 +223,7 @@ module URBANopt # :nodoc:
|
|
222
223
|
reopt_input = feature_adapter.reopt_json_from_feature_report(feature_report, @feature_reports_reopt_default_assumption_hashes[idx], groundmount_photovoltaic)
|
223
224
|
reopt_output = api.reopt_request(reopt_input, @feature_reports_reopt_default_output_files[idx])
|
224
225
|
if run_resilience
|
225
|
-
run_uuid = reopt_output['outputs']['
|
226
|
+
run_uuid = reopt_output['outputs']['run_uuid']
|
226
227
|
if File.directory? @feature_reports_reopt_default_output_files[idx]
|
227
228
|
resilience_stats = api.resilience_request(run_uuid, @feature_reports_reopt_default_output_files[idx])
|
228
229
|
else
|
@@ -257,7 +258,7 @@ module URBANopt # :nodoc:
|
|
257
258
|
#
|
258
259
|
# [*parameters:*]
|
259
260
|
#
|
260
|
-
# * +output_file+ - _Array_ - Optional. An array of paths to files at which REpopt
|
261
|
+
# * +output_file+ - _Array_ - Optional. An array of paths to files at which REpopt responses will be saved. The number and order of the paths should match the array in ScenarioReport.feature_reports.
|
261
262
|
# [*return:*] _Boolean_ - Returns true if file or nonempty directory exist
|
262
263
|
def output_exists(output_file)
|
263
264
|
res = false
|
@@ -270,18 +271,18 @@ module URBANopt # :nodoc:
|
|
270
271
|
return res
|
271
272
|
end
|
272
273
|
|
273
|
-
# Updates a ScenarioReport based on an optional set of \REopt
|
274
|
+
# Updates a ScenarioReport based on an optional set of \REopt optimization assumptions.
|
274
275
|
##
|
275
276
|
#
|
276
277
|
# [*parameters:*]
|
277
278
|
#
|
278
|
-
# * +scenario_report+ - _Array_ - A _URBANopt::Reporting::DefaultReports::ScenarioReport_ which will each be used to create (and is subsquently updated by) \REopt
|
279
|
-
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of \REopt
|
280
|
-
# * +reopt_output_files+ - _Array_ - Optional. An array of paths to files at which REpopt
|
279
|
+
# * +scenario_report+ - _Array_ - A _URBANopt::Reporting::DefaultReports::ScenarioReport_ which will each be used to create (and is subsquently updated by) \REopt opimization responses for each of its FeatureReports.
|
280
|
+
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of \REopt 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.
|
281
|
+
# * +reopt_output_files+ - _Array_ - Optional. An array of paths to files at which REpopt responses will be saved. The number and order of the paths should match the array in ScenarioReport.feature_reports.
|
281
282
|
# * +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.
|
282
283
|
#
|
283
284
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
|
284
|
-
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:
|
285
|
+
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: false, keep_existing_output: false, groundmount_photovoltaic: nil)
|
285
286
|
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, keep_existing_output: keep_existing_output, groundmount_photovoltaic: groundmount_photovoltaic)
|
286
287
|
|
287
288
|
# only do this if you have run feature reports
|