urbanopt-reopt 0.4.1 → 0.5.7

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