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.
@@ -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/scenario/default_reports'
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::Scenario::ScenarioDefaultPostProcessor - used in creating default output file names in \REopt Lite optimizations.
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 !Dir.exist?(File.join(@scenario_report.directory_name, "reopt"))
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::Scenario::DefaultReports::FeatureReport_ - FeatureReport which will be used in creating and then updated by a \REopt Lite opimization response.
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::Scenario::DefaultReports::FeatureReport_ - Returns an updated FeatureReport
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
- result = adapter.update_feature_report(feature_report, reopt_output, timeseries_csv_path)
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::Scenario::DefaultReports::ScenarioReport_ - ScenarioReport which will be used in creating and then updated by a \REopt Lite opimization response.
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::Scenario::DefaultReports::FeatureReport_ objetcs which will each be used to create (and are subsquently updated by) a \REopt Lite opimization response.
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
- new_feature_report = feature_adapter.update_feature_report(feature_report, reopt_output, @feature_reports_timeseries_default_output_files[idx])
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::Scenario::DefaultReports::ScenarioReport_ which will each be used to create (and is subsquently updated by) \REopt Lite opimization responses for each of its FeatureReports.
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::Scenario::DefaultReports::ScenarioReport.new
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::Scenario::DefaultReports::TimeseriesCSV.new(timeseries_hash)
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/scenario/default_reports'
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::Scenario::DefaultReports::ScenarioReport_ - ScenarioReport to use in converting the +reopt_assumptions_hash+, if provided, to a \REopt Lite post. Otherwise, if the +reopt_assumptions_hash+ is nil a default post will be updated from this ScenarioReport and submitted to the \REopt Lite API.
54
+ # * +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.latitude.nil? || scenario_report.location.longitude.nil? || (scenario_report.location.latitude == 0) || (scenario_report.location.longitude == 0)
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
- if ![nil, 0].include?(x[:location][:latitude]) && ![nil, 0].include?(x[:location][:longitude])
79
- lats.push(x[:location][:latitude])
80
- longs.push(x[:location][:longitude])
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.latitude = lats.reduce(:+) / lats.size.to_f
86
- scenario_report.location.longitude = longs.reduce(:+) / longs.size.to_f
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.latitude, scenario_report.location.longitude]
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 |i, x|
97
- if [nil, 0].include? x
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.latitude
107
- reopt_inputs[:Scenario][:Site][:longitude] = scenario_report.location.longitude
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
- if !scenario_report.program.roof_area.nil?
111
- reopt_inputs[:Scenario][:Site][:roof_squarefeet] = scenario_report.program.roof_area[:available_roof_area]
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.site_area.nil?
115
- reopt_inputs[:Scenario][:Site][:land_acres] = scenario_report.program.site_area * 1.0 / 43560 # acres/sqft
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::Scenario::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.
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::Scenario::DefaultReports::ScenarioReport_ - ScenarioReport to update from a \REopt Lite response.
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::Scenario::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
178
+ # [*return:*] _URBANopt::Reporting::DefaultReports::ScenarioReport_ - Returns an updated ScenarioReport
176
179
  ##
177
- def update_scenario_report(scenario_report, reopt_output, timeseries_csv_path = nil)
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.latitude = reopt_output['inputs']['Scenario']['Site']['latitude']
205
- scenario_report.location.longitude = reopt_output['inputs']['Scenario']['Site']['longitude']
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::Scenario::DefaultReports::SolarPV.new( {size_kw: (pv['size_kw'] || 0), id: i })
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::Scenario::DefaultReports::Wind.new( {size_kw: (wind['size_kw'] || 0) })
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::Scenario::DefaultReports::Generator.new( {size_kw: (generator['size_kw'] || 0) })
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::Scenario::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
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.2.1'.freeze
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,
@@ -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 = 'Classes and measures for utilizing the REopt Lite API within OpenStudio workflows.'
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.add_development_dependency 'bundler', '~> 1.14'
26
- spec.add_development_dependency 'rake', '12.3.1'
27
- spec.add_development_dependency 'rspec', '3.7.0'
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