urbanopt-reopt 0.2.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/pull_request_template.md +2 -2
- data/.gitignore +3 -0
- data/.rdoc_options +1 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +43 -0
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +12 -22
- 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/docs/package-lock.json +11376 -1
- data/docs/package.json +1 -1
- 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 +41 -27
- data/lib/urbanopt/reopt/reopt_lite_api.rb +114 -11
- data/lib/urbanopt/reopt/reopt_logger.rb +1 -1
- data/lib/urbanopt/reopt/reopt_post_processor.rb +57 -24
- data/lib/urbanopt/reopt/scenario/reopt_scenario_csv.rb +1 -1
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +55 -38
- data/lib/urbanopt/reopt/version.rb +2 -2
- data/lib/urbanopt/reopt_scenario.rb +1 -1
- data/urbanopt-reopt.gemspec +12 -7
- metadata +55 -27
- data/.travis.yml +0 -22
@@ -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,9 +29,8 @@
|
|
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
|
-
require 'urbanopt/reopt'
|
35
34
|
require 'csv'
|
36
35
|
|
37
36
|
module URBANopt # :nodoc:
|
@@ -43,7 +42,7 @@ module URBANopt # :nodoc:
|
|
43
42
|
#
|
44
43
|
# [*parameters:*]
|
45
44
|
#
|
46
|
-
# * +scenario_report+ - _ScenarioReport_ - Optional. A scenario report that has been returned from the URBANopt::
|
45
|
+
# * +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
46
|
# * +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
47
|
# * +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
48
|
# * +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,8 +69,9 @@ module URBANopt # :nodoc:
|
|
70
69
|
if !scenario_report.nil?
|
71
70
|
@scenario_report = scenario_report
|
72
71
|
|
73
|
-
if
|
72
|
+
if !Dir.exist?(File.join(@scenario_report.directory_name, "reopt"))
|
74
73
|
Dir.mkdir(File.join(@scenario_report.directory_name, "reopt"))
|
74
|
+
@@logger.info("Created directory: " + File.join(@scenario_report.directory_name, "reopt"))
|
75
75
|
end
|
76
76
|
|
77
77
|
@scenario_reopt_default_output_file = File.join(@scenario_report.directory_name, "reopt/scenario_report_#{@scenario_report.id}_reopt_run.json")
|
@@ -80,6 +80,7 @@ module URBANopt # :nodoc:
|
|
80
80
|
@scenario_report.feature_reports.each do |fr|
|
81
81
|
if !Dir.exist?(File.join(fr.directory_name, "reopt"))
|
82
82
|
Dir.mkdir(File.join(fr.directory_name, "reopt"))
|
83
|
+
@@logger.info("Created directory: " + File.join(fr.directory_name, "reopt"))
|
83
84
|
end
|
84
85
|
@feature_reports_reopt_default_output_files << File.join(fr.directory_name, "reopt/feature_report_#{fr.id}_reopt_run.json")
|
85
86
|
end
|
@@ -111,25 +112,36 @@ module URBANopt # :nodoc:
|
|
111
112
|
#
|
112
113
|
# [*parameters:*]
|
113
114
|
#
|
114
|
-
# * +feature_report+ - _URBANopt::
|
115
|
+
# * +feature_report+ - _URBANopt::Reporting::DefaultReports::FeatureReport_ - FeatureReport which will be used in creating and then updated by a \REopt Lite opimization response.
|
115
116
|
# * +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)
|
116
117
|
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt Lite responses will be saved.
|
117
118
|
# * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the FeatureReport will be saved.
|
118
119
|
#
|
119
|
-
# [*return:*] _URBANopt::
|
120
|
+
# [*return:*] _URBANopt::Reporting::DefaultReports::FeatureReport_ - Returns an updated FeatureReport
|
120
121
|
##
|
121
|
-
def run_feature_report(feature_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil)
|
122
|
+
def run_feature_report(feature_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil, run_resilience:true)
|
122
123
|
api = URBANopt::REopt::REoptLiteAPI.new(@nrel_developer_key, @localhost)
|
123
124
|
adapter = URBANopt::REopt::FeatureReportAdapter.new
|
124
125
|
|
125
126
|
reopt_input = adapter.reopt_json_from_feature_report(feature_report, reopt_assumptions_hash)
|
126
127
|
if reopt_output_file.nil?
|
127
|
-
reopt_output_file = feature_report.directory_name
|
128
|
+
reopt_output_file = File.join(feature_report.directory_name, 'reopt')
|
128
129
|
end
|
129
130
|
reopt_output = api.reopt_request(reopt_input, reopt_output_file)
|
130
|
-
|
131
|
+
if run_resilience
|
132
|
+
run_uuid = reopt_output['outputs']['Scenario']['run_uuid']
|
133
|
+
if File.directory? reopt_output_file
|
134
|
+
resilience_stats = api.resilience_request(run_uuid, reopt_output_file)
|
135
|
+
else
|
136
|
+
resilience_stats = api.resilience_request(run_uuid, reopt_output_file.sub!('.json','_resilience.json'))
|
137
|
+
end
|
138
|
+
else
|
139
|
+
resilience_stats = nil
|
140
|
+
end
|
141
|
+
result = adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path, resilience_stats)
|
131
142
|
if !save_name.nil?
|
132
|
-
result.save_feature_report save_name
|
143
|
+
#result.save_feature_report save_name
|
144
|
+
result.save_json_report(save_name)
|
133
145
|
end
|
134
146
|
return result
|
135
147
|
end
|
@@ -140,13 +152,13 @@ module URBANopt # :nodoc:
|
|
140
152
|
#
|
141
153
|
# [*parameters:*]
|
142
154
|
#
|
143
|
-
# * +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.
|
144
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)
|
145
157
|
# * +reopt_output_file+ - _String_ - Optional. Path to a file at which REpopt Lite responses will be saved.
|
146
158
|
# * +timeseries_csv_path+ - _String_ - Optional. Path to a file at which the new timeseries CSV for the ScenarioReport will be saved.
|
147
159
|
#
|
148
160
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ Returns an updated ScenarioReport
|
149
|
-
def run_scenario_report(scenario_report:, reopt_assumptions_hash:nil, reopt_output_file:nil, timeseries_csv_path:nil, save_name:nil)
|
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)
|
150
162
|
if !reopt_assumptions_hash.nil?
|
151
163
|
@scenario_reopt_default_assumptions_hash = reopt_assumptions_hash
|
152
164
|
end
|
@@ -163,8 +175,18 @@ module URBANopt # :nodoc:
|
|
163
175
|
reopt_input = adapter.reopt_json_from_scenario_report(scenario_report, @scenario_reopt_default_assumptions_hash)
|
164
176
|
|
165
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
|
166
188
|
|
167
|
-
result = adapter.update_scenario_report(scenario_report, reopt_output, @scenario_timeseries_default_output_file)
|
189
|
+
result = adapter.update_scenario_report(scenario_report, reopt_output, @scenario_timeseries_default_output_file, resilience_stats)
|
168
190
|
if !save_name.nil?
|
169
191
|
result.save save_name
|
170
192
|
end
|
@@ -176,13 +198,13 @@ module URBANopt # :nodoc:
|
|
176
198
|
#
|
177
199
|
# [*parameters:*]
|
178
200
|
#
|
179
|
-
# * +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.
|
180
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.
|
181
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.
|
182
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.
|
183
205
|
#
|
184
206
|
# [*return:*] _Array_ Returns an array of updated _URBANopt::Scenario::DefaultReports::FeatureReport_ objects
|
185
|
-
def run_feature_reports(feature_reports:, reopt_assumptions_hashes:[], reopt_output_files:[], timeseries_csv_paths:[], save_names:nil)
|
207
|
+
def run_feature_reports(feature_reports:, reopt_assumptions_hashes:[], reopt_output_files:[], timeseries_csv_paths:[], save_names:nil, run_resilience:true)
|
186
208
|
|
187
209
|
if !reopt_assumptions_hashes.empty?
|
188
210
|
@feature_reports_reopt_default_assumption_hashes = reopt_assumptions_hashes
|
@@ -215,11 +237,22 @@ module URBANopt # :nodoc:
|
|
215
237
|
begin
|
216
238
|
reopt_input = feature_adapter.reopt_json_from_feature_report(feature_report, @feature_reports_reopt_default_assumption_hashes[idx])
|
217
239
|
reopt_output = api.reopt_request(reopt_input, @feature_reports_reopt_default_output_files[idx])
|
218
|
-
|
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)
|
219
251
|
new_feature_reports.push(new_feature_report)
|
220
252
|
if !save_names.nil?
|
221
253
|
if save_names.length == feature_reports.length
|
222
|
-
new_feature_report.save_feature_report save_names[idx]
|
254
|
+
#new_feature_report.save_feature_report save_names[idx]
|
255
|
+
new_feature_report.save_json_report save_names[idx]
|
223
256
|
else
|
224
257
|
warn "Could not save feature reports - the number of save names provided did not match the number of feature reports"
|
225
258
|
end
|
@@ -228,7 +261,7 @@ module URBANopt # :nodoc:
|
|
228
261
|
@@logger.info("Could not optimize Feature Report #{feature_report.name} #{feature_report.id}")
|
229
262
|
end
|
230
263
|
end
|
231
|
-
|
264
|
+
|
232
265
|
return new_feature_reports
|
233
266
|
end
|
234
267
|
|
@@ -237,22 +270,22 @@ module URBANopt # :nodoc:
|
|
237
270
|
#
|
238
271
|
# [*parameters:*]
|
239
272
|
#
|
240
|
-
# * +scenario_report+ - _Array_ - A _URBANopt::
|
273
|
+
# * +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.
|
241
274
|
# * +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.
|
242
275
|
# * +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.
|
243
276
|
# * +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.
|
244
277
|
#
|
245
278
|
# [*return:*] _URBANopt::Scenario::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
|
246
|
-
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)
|
247
|
-
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)
|
279
|
+
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)
|
280
|
+
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)
|
248
281
|
|
249
|
-
new_scenario_report = URBANopt::
|
282
|
+
new_scenario_report = URBANopt::Reporting::DefaultReports::ScenarioReport.new
|
250
283
|
new_scenario_report.id = scenario_report.id
|
251
284
|
new_scenario_report.name = scenario_report.name
|
252
285
|
new_scenario_report.directory_name = scenario_report.directory_name
|
253
286
|
|
254
287
|
timeseries_hash = { column_names: scenario_report.timeseries_csv.column_names }
|
255
|
-
new_scenario_report.timeseries_csv = URBANopt::
|
288
|
+
new_scenario_report.timeseries_csv = URBANopt::Reporting::DefaultReports::TimeseriesCSV.new(timeseries_hash)
|
256
289
|
|
257
290
|
new_feature_reports.each do |feature_report|
|
258
291
|
new_scenario_report.add_feature_report(feature_report)
|
@@ -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,
|
@@ -28,7 +28,7 @@
|
|
28
28
|
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
# *********************************************************************************
|
30
30
|
|
31
|
-
require 'urbanopt/
|
31
|
+
require 'urbanopt/reporting/default_reports'
|
32
32
|
require 'urbanopt/reopt/reopt_logger'
|
33
33
|
require 'matrix'
|
34
34
|
require 'csv'
|
@@ -51,7 +51,7 @@ module URBANopt # :nodoc:
|
|
51
51
|
#
|
52
52
|
# [*parameters:*]
|
53
53
|
#
|
54
|
-
# * +scenario_report+ - _URBANopt::
|
54
|
+
# * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting the +reopt_assumptions_hash+, if provided, to a \REopt Lite post. Otherwise, if the +reopt_assumptions_hash+ is nil a default post will be updated from this ScenarioReport and submitted to the \REopt Lite API.
|
55
55
|
# * +reopt_assumptions_hash+ - _Hash_ - Optional. A hash formatted for submittal to the \REopt Lite API containing default values. Values will be overwritten from the ScenarioReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API.
|
56
56
|
#
|
57
57
|
# [*return:*] _Hash_ - Returns hash formatted for submittal to the \REopt Lite API
|
@@ -70,31 +70,33 @@ module URBANopt # :nodoc:
|
|
70
70
|
end
|
71
71
|
|
72
72
|
# Update required info
|
73
|
-
if scenario_report.location.
|
73
|
+
if scenario_report.location.latitude_deg.nil? || scenario_report.location.longitude_deg.nil? || (scenario_report.location.latitude_deg == 0) || (scenario_report.location.longitude_deg == 0)
|
74
74
|
if !scenario_report.feature_reports.nil? && (scenario_report.feature_reports != [])
|
75
75
|
lats = []
|
76
76
|
longs = []
|
77
77
|
scenario_report.feature_reports.each do |x|
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
puts " ERROR: #{x.location.latitude_deg}"
|
79
|
+
if ![nil].include?(x.location.latitude_deg) && ![nil].include?(x.location.longitude_deg)
|
80
|
+
lats.push(x.location.latitude_deg)
|
81
|
+
longs.push(x.location.longitude_deg)
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
84
85
|
if !lats.empty? && !longs.empty?
|
85
|
-
scenario_report.location.
|
86
|
-
scenario_report.location.
|
86
|
+
scenario_report.location.latitude_deg = lats.reduce(:+) / lats.size.to_f
|
87
|
+
scenario_report.location.longitude_deg = longs.reduce(:+) / longs.size.to_f
|
87
88
|
end
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
91
92
|
# Update required info
|
92
93
|
requireds_names = ['latitude', 'longitude']
|
93
|
-
requireds = [scenario_report.location.
|
94
|
+
requireds = [scenario_report.location.latitude_deg, scenario_report.location.longitude_deg]
|
95
|
+
|
94
96
|
|
95
97
|
if requireds.include?(nil) || requireds.include?(0)
|
96
|
-
requireds.each_with_index do |
|
97
|
-
if [nil
|
98
|
+
requireds.each_with_index do |x, i|
|
99
|
+
if [nil].include? x
|
98
100
|
n = requireds_names[i]
|
99
101
|
raise "Missing value for #{n} - this is a required input"
|
100
102
|
end
|
@@ -103,16 +105,17 @@ module URBANopt # :nodoc:
|
|
103
105
|
|
104
106
|
reopt_inputs[:Scenario][:description] = description
|
105
107
|
|
106
|
-
reopt_inputs[:Scenario][:Site][:latitude] = scenario_report.location.
|
107
|
-
reopt_inputs[:Scenario][:Site][:longitude] = scenario_report.location.
|
108
|
+
reopt_inputs[:Scenario][:Site][:latitude] = scenario_report.location.latitude_deg
|
109
|
+
reopt_inputs[:Scenario][:Site][:longitude] = scenario_report.location.longitude_deg
|
108
110
|
|
109
111
|
# Update optional info
|
110
|
-
|
111
|
-
|
112
|
+
# REK: attribute names should be updated
|
113
|
+
if !scenario_report.program.roof_area_sqft.nil?
|
114
|
+
reopt_inputs[:Scenario][:Site][:roof_squarefeet] = scenario_report.program.roof_area_sqft[:available_roof_area]
|
112
115
|
end
|
113
116
|
|
114
|
-
if !scenario_report.program.
|
115
|
-
reopt_inputs[:Scenario][:Site][:land_acres] = scenario_report.program.
|
117
|
+
if !scenario_report.program.site_area_sqft.nil?
|
118
|
+
reopt_inputs[:Scenario][:Site][:land_acres] = scenario_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
|
116
119
|
end
|
117
120
|
|
118
121
|
unless scenario_report.timesteps_per_hour.nil?
|
@@ -126,10 +129,10 @@ module URBANopt # :nodoc:
|
|
126
129
|
energy_timeseries_kw = t.by_col[col_num].map { |e| ((e * scenario_report.timesteps_per_hour || 0) ) }
|
127
130
|
if energy_timeseries_kw.length < (scenario_report.timesteps_per_hour * 8760)
|
128
131
|
start_date = Time.parse(t.by_col["Datetime"][0])
|
129
|
-
start_ts = (((start_date.yday * 60.0 * 60.0 * 24) + (start_date.hour * 60.0 * 60.0) + (start_date.min * 60.0) + start_date.sec) /
|
132
|
+
start_ts = (((start_date.yday * 60.0 * 60.0 * 24) + (start_date.hour * 60.0 * 60.0) + (start_date.min * 60.0) + start_date.sec) / \
|
130
133
|
(( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
|
131
134
|
end_date = Time.parse(t.by_col["Datetime"][-1])
|
132
|
-
end_ts = (((end_date.yday * 60.0 * 60.0 * 24) + (end_date.hour * 60.0 * 60.0) + (end_date.min * 60.0) + end_date.sec) /
|
135
|
+
end_ts = (((end_date.yday * 60.0 * 60.0 * 24) + (end_date.hour * 60.0 * 60.0) + (end_date.min * 60.0) + end_date.sec) / \
|
133
136
|
(( 60 / scenario_report.timesteps_per_hour ) * 60)).to_int
|
134
137
|
energy_timeseries_kw = [0.0]*(start_ts-1) + energy_timeseries_kw + [0.0]*((scenario_report.timesteps_per_hour * 8760) - end_ts)
|
135
138
|
end
|
@@ -146,7 +149,7 @@ module URBANopt # :nodoc:
|
|
146
149
|
#
|
147
150
|
# [*parameters:*]
|
148
151
|
#
|
149
|
-
# * +scenario_report+ - _URBANopt::
|
152
|
+
# * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting FeatureReports and respecitive +reopt_assumptions_hashes+, if provided, to a \REopt Lite post. If no +reopt_assumptions_hashes+ are provided default posts will be updated from these FeatureReports and submitted to the \REopt Lite API.
|
150
153
|
# * +reopt_assumptions_hashes+ - _Array_ - Optional. An array of hashes formatted for submittal to the \REopt Lite API containing default values. Values will be overwritten from the ScenarioReport where available (i.e. latitude, roof_squarefeet). Missing optional parameters will be filled in with default values by the API. The order should match the list in ScenarioReport.feature_reports.
|
151
154
|
#
|
152
155
|
# [*return:*] _Array_ - Returns an array of hashes formatted for submittal to the \REopt Lite API in the order of the FeatureReports lited in ScenarioReport.feature_reports.
|
@@ -168,18 +171,18 @@ module URBANopt # :nodoc:
|
|
168
171
|
#
|
169
172
|
# [*parameters:*]
|
170
173
|
#
|
171
|
-
# * +scenario_report+ - _URBANopt::
|
174
|
+
# * +scenario_report+ - _URBANopt::Reporting::DefaultReports::ScenarioReport_ - ScenarioReport to update from a \REopt Lite response.
|
172
175
|
# * +reopt_output+ - _Hash_ - A hash response from the \REopt Lite API.
|
173
176
|
# * +timeseries_csv_path+ - _String_ - Optional. The path to a file at which new timeseries data will be written. If not provided a file is created based on the run_uuid of the \REopt Lite optimization task.
|
174
177
|
#
|
175
|
-
# [*return:*] _URBANopt::
|
178
|
+
# [*return:*] _URBANopt::Reporting::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
|
176
179
|
##
|
177
|
-
def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path =
|
180
|
+
def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path=nil, resilience_stats=nil)
|
178
181
|
if reopt_output['outputs']['Scenario']['status'] != 'optimal'
|
179
182
|
@@logger.info("Warning cannot Feature Report #{scenario_report.name} #{scenario_report.id} - REopt optimization was non-optimal")
|
180
183
|
return scenario_report
|
181
184
|
end
|
182
|
-
|
185
|
+
|
183
186
|
$ts_per_hour = scenario_report.timesteps_per_hour
|
184
187
|
def scale_timeseries(input, ts_per_hr=$ts_per_hour)
|
185
188
|
if input.nil?
|
@@ -192,7 +195,7 @@ module URBANopt # :nodoc:
|
|
192
195
|
return input
|
193
196
|
end
|
194
197
|
result = []
|
195
|
-
input.each do |val|
|
198
|
+
input.each do |val|
|
196
199
|
(1..ts_per_hr).each do |x|
|
197
200
|
result.push(val/ts_per_hr.to_f)
|
198
201
|
end
|
@@ -201,8 +204,8 @@ module URBANopt # :nodoc:
|
|
201
204
|
end
|
202
205
|
|
203
206
|
# Update location
|
204
|
-
scenario_report.location.
|
205
|
-
scenario_report.location.
|
207
|
+
scenario_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
|
208
|
+
scenario_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
|
206
209
|
|
207
210
|
# Update timeseries csv from \REopt Lite dispatch data
|
208
211
|
scenario_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
|
@@ -215,36 +218,50 @@ module URBANopt # :nodoc:
|
|
215
218
|
scenario_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
|
216
219
|
scenario_report.distributed_generation.year_one_bill_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_us_dollars'] || 0
|
217
220
|
scenario_report.distributed_generation.total_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_us_dollars'] || 0
|
218
|
-
|
221
|
+
scenario_report.distributed_generation.total_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_us_dollars'] || 0
|
222
|
+
scenario_report.distributed_generation.year_one_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_bau_us_dollars'] || 0
|
223
|
+
scenario_report.distributed_generation.year_one_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_bau_us_dollars'] || 0
|
224
|
+
scenario_report.distributed_generation.year_one_bill_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_bill_bau_us_dollars'] || 0
|
225
|
+
scenario_report.distributed_generation.total_demand_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_demand_cost_bau_us_dollars'] || 0
|
226
|
+
scenario_report.distributed_generation.total_energy_cost_bau_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['total_energy_cost_bau_us_dollars'] || 0
|
227
|
+
if !resilience_stats.nil?
|
228
|
+
scenario_report.distributed_generation.resilience_hours_min = resilience_stats['resilience_hours_min']
|
229
|
+
scenario_report.distributed_generation.resilience_hours_max = resilience_stats['resilience_hours_max']
|
230
|
+
scenario_report.distributed_generation.resilience_hours_avg = resilience_stats['resilience_hours_avg']
|
231
|
+
scenario_report.distributed_generation.probs_of_surviving = resilience_stats['probs_of_surviving']
|
232
|
+
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']
|
234
|
+
end
|
235
|
+
|
219
236
|
if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
|
220
237
|
reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
|
221
238
|
elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
|
222
239
|
reopt_output['outputs']['Scenario']['Site']['PV'] = []
|
223
240
|
end
|
224
|
-
|
225
|
-
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
226
|
-
scenario_report.distributed_generation.add_tech 'solar_pv', URBANopt::
|
241
|
+
|
242
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
|
243
|
+
scenario_report.distributed_generation.add_tech 'solar_pv', URBANopt::Reporting::DefaultReports::SolarPV.new( {size_kw: (pv['size_kw'] || 0), id: i })
|
227
244
|
end
|
228
245
|
|
229
246
|
wind = reopt_output['outputs']['Scenario']['Site']['Wind']
|
230
247
|
if !wind['size_kw'].nil? and wind['size_kw'] != 0
|
231
|
-
scenario_report.distributed_generation.add_tech 'wind', URBANopt::
|
248
|
+
scenario_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new( {size_kw: (wind['size_kw'] || 0) })
|
232
249
|
end
|
233
250
|
|
234
251
|
generator = reopt_output['outputs']['Scenario']['Site']['Generator']
|
235
252
|
if !generator['size_kw'].nil? and generator['size_kw'] != 0
|
236
|
-
scenario_report.distributed_generation.add_tech 'generator', URBANopt::
|
253
|
+
scenario_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new( {size_kw: (generator['size_kw'] || 0) })
|
237
254
|
end
|
238
255
|
|
239
256
|
storage = reopt_output['outputs']['Scenario']['Site']['Storage']
|
240
257
|
if !storage['size_kw'].nil? and storage['size_kw'] != 0
|
241
|
-
scenario_report.distributed_generation.add_tech 'storage', URBANopt::
|
258
|
+
scenario_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
|
242
259
|
end
|
243
|
-
|
260
|
+
|
244
261
|
generation_timeseries_kwh = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
245
262
|
|
246
|
-
|
247
|
-
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
|
263
|
+
|
264
|
+
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
|
248
265
|
if (pv['size_kw'] || 0) > 0
|
249
266
|
if !pv['year_one_power_production_series_kw'].nil?
|
250
267
|
generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -30,6 +30,6 @@
|
|
30
30
|
|
31
31
|
module URBANopt # :nodoc:
|
32
32
|
module REopt # :nodoc:
|
33
|
-
VERSION = '0.
|
33
|
+
VERSION = '0.5.0'.freeze
|
34
34
|
end
|
35
35
|
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,
|
data/urbanopt-reopt.gemspec
CHANGED
@@ -8,8 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = URBANopt::REopt::VERSION
|
9
9
|
spec.authors = ['']
|
10
10
|
spec.email = ['']
|
11
|
+
spec.licenses = 'Nonstandard'
|
11
12
|
|
12
|
-
spec.summary = '
|
13
|
+
spec.summary = 'Accessing the REopt Lite API within OpenStudio workflows.'
|
13
14
|
spec.description = 'Classes and measures for utilizing the REopt Lite API within OpenStudio workflows.'
|
14
15
|
spec.homepage = 'https://github.com/urbanopt/urbanopt-reopt-gem'
|
15
16
|
|
@@ -22,12 +23,16 @@ Gem::Specification.new do |spec|
|
|
22
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
24
|
spec.require_paths = ['lib']
|
24
25
|
|
25
|
-
spec.
|
26
|
-
|
27
|
-
spec.add_development_dependency '
|
26
|
+
spec.required_ruby_version = '~> 2.5.0'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 2.1'
|
29
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
30
|
+
spec.add_development_dependency 'rspec', '~> 3.7'
|
28
31
|
spec.add_development_dependency 'rubocop', '~> 0.54.0'
|
32
|
+
spec.add_development_dependency 'rdoc', '~> 4.3.0'
|
33
|
+
|
34
|
+
spec.add_dependency 'certified', '~> 1'
|
35
|
+
spec.add_dependency 'json_pure', '~> 2'
|
36
|
+
spec.add_dependency 'urbanopt-scenario', '~> 0.5.0'
|
29
37
|
|
30
|
-
spec.add_dependency 'certified'
|
31
|
-
spec.add_dependency 'json_pure'
|
32
|
-
#spec.add_dependency 'urbanopt-scenario', '0.1.1'
|
33
38
|
end
|