urbanopt-reopt 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/docs/package.json CHANGED
@@ -13,10 +13,18 @@
13
13
  "highlight.js": "^10.4.1",
14
14
  "json-schema-ref-parser": "^6.1.0",
15
15
  "json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
16
- "vuepress": "^0.14.10",
16
+ "vuepress": "^1.8.2",
17
17
  "webpack-dev-middleware": "^3.6.0"
18
18
  },
19
19
  "devDependencies": {
20
- "gh-pages": "^2.0.1"
20
+ "braces": "^3.0.2",
21
+ "chokidar": ">=3.5.1",
22
+ "fsevents": ">=2.3.2",
23
+ "gh-pages": "^2.0.1",
24
+ "ini": "^2.0.0",
25
+ "is-svg": "4.3.1",
26
+ "serialize-javascript": "^5.0.1",
27
+ "ssri": "8.0.1",
28
+ "yargs-parser": "^18.1.1"
21
29
  }
22
30
  }
@@ -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.
@@ -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.
@@ -32,6 +42,7 @@ require 'urbanopt/reporting/default_reports'
32
42
  require 'urbanopt/reopt/reopt_logger'
33
43
  require 'csv'
34
44
  require 'matrix'
45
+ require_relative 'utilities'
35
46
  require 'time'
36
47
 
37
48
  module URBANopt # :nodoc:
@@ -87,24 +98,30 @@ module URBANopt # :nodoc:
87
98
  reopt_inputs[:Scenario][:Site][:latitude] = feature_report.location.latitude_deg
88
99
  reopt_inputs[:Scenario][:Site][:longitude] = feature_report.location.longitude_deg
89
100
 
90
- # Parse Optional FeatureReport metrics
91
- unless feature_report.program.roof_area_sqft.nil?
92
- reopt_inputs[:Scenario][:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area]
101
+ # Parse Optional FeatureReport metrics - do not overwrite from assumptions file
102
+ if reopt_inputs[:Scenario][:Site][:roof_squarefeet].nil?
103
+ unless feature_report.program.roof_area_sqft.nil?
104
+ reopt_inputs[:Scenario][:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area_sqft]
105
+ end
93
106
  end
94
107
 
95
- unless feature_report.program.site_area_sqft.nil?
96
- reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
108
+ if reopt_inputs[:Scenario][:Site][:land_acres].nil?
109
+ unless feature_report.program.site_area_sqft.nil?
110
+ reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
111
+ end
97
112
  end
98
113
 
99
- unless feature_report.timesteps_per_hour.nil?
100
- reopt_inputs[:Scenario][:time_steps_per_hour] = feature_report.timesteps_per_hour
114
+ if reopt_inputs[:Scenario][:time_steps_per_hour].nil?
115
+ reopt_inputs[:Scenario][:time_steps_per_hour] = 1
101
116
  end
102
117
 
103
118
  # Parse Load Profile
104
119
  begin
120
+ #Convert kWh values in the timeseries CSV to kW
105
121
  col_num = feature_report.timeseries_csv.column_names.index('Electricity:Facility(kWh)')
106
122
  t = CSV.read(feature_report.timeseries_csv.path, headers: true, converters: :numeric)
107
123
  energy_timeseries_kw = t.by_col[col_num].map { |e| ((e * feature_report.timesteps_per_hour || 0) ) }
124
+ #Fill in missing timestep values with 0 if a full year is not provided
108
125
  if energy_timeseries_kw.length < (feature_report.timesteps_per_hour * 8760)
109
126
  start_date = Time.parse(t.by_col["Datetime"][0])
110
127
  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) /
@@ -114,14 +131,41 @@ module URBANopt # :nodoc:
114
131
  (( 60 / feature_report.timesteps_per_hour ) * 60)).to_int
115
132
  energy_timeseries_kw = [0.0]*(start_ts-1) + energy_timeseries_kw + [0.0]*((feature_report.timesteps_per_hour * 8760) - end_ts)
116
133
  end
117
- reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(feature_report.timesteps_per_hour * 8760)]
134
+ #Clip to one non-leap year's worth of data
135
+ energy_timeseries_kw = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(feature_report.timesteps_per_hour * 8760)]
136
+ #Convert from the OpenDSS resolution to the REopt Lite resolution, if necessary
118
137
  rescue StandardError
119
138
  @@logger.error("Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}")
120
139
  raise "Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}"
121
140
  end
141
+
142
+ # Convert load to REopt Resolution
143
+ begin
144
+ reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = convert_powerflow_resolution(energy_timeseries_kw, feature_report.timesteps_per_hour, reopt_inputs[:Scenario][:time_steps_per_hour])
145
+
146
+ rescue
147
+ @@logger.error("Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}")
148
+ raise "Could not convert the annual electric load from a resolution of #{feature_report.timesteps_per_hour} to #{reopt_inputs[:Scenario][:time_steps_per_hour]}"
149
+ end
150
+
151
+ if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps].nil?
152
+ n_top_values = 100
153
+ tmp1 = reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw]
154
+ tmp2 = tmp1.each_index.max_by(n_top_values*reopt_inputs[:Scenario][:time_steps_per_hour]){|i| tmp1[i]}
155
+ for i in (0...tmp2.count)
156
+ tmp2[i] += 1
157
+ end
158
+ reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps] = tmp2
159
+ end
160
+
161
+ if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw].nil?
162
+ reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw] = 0
163
+ end
164
+
122
165
  return reopt_inputs
123
166
  end
124
167
 
168
+
125
169
  ##
126
170
  # Update a FeatureReport from a \REopt Lite response
127
171
  #
@@ -140,33 +184,10 @@ module URBANopt # :nodoc:
140
184
  return feature_report
141
185
  end
142
186
 
143
- $ts_per_hour = feature_report.timesteps_per_hour
144
- def scale_timeseries(input, ts_per_hr=$ts_per_hour)
145
- if input.nil?
146
- return nil
147
- end
148
- if input.length ==0
149
- return nil
150
- end
151
- if input.length == (8760 * ts_per_hr)
152
- return input
153
- end
154
- result = []
155
- input.each do |val|
156
- (1..ts_per_hr).each do |x|
157
- result.push(val/ts_per_hr.to_f)
158
- end
159
- end
160
- return result
161
- end
162
-
163
187
  # Update location
164
188
  feature_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
165
189
  feature_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
166
190
 
167
- # Update timeseries csv from \REopt Lite dispatch data
168
- feature_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
169
-
170
191
  # Update distributed generation sizing and financials
171
192
  feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
172
193
  feature_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
@@ -186,9 +207,9 @@ module URBANopt # :nodoc:
186
207
  feature_report.distributed_generation.resilience_hours_avg = resilience_stats['resilience_hours_avg']
187
208
  feature_report.distributed_generation.probs_of_surviving = resilience_stats['probs_of_surviving']
188
209
  feature_report.distributed_generation.probs_of_surviving_by_month = resilience_stats['probs_of_surviving_by_month']
189
- feature_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
210
+ feature_report.distributed_generation.probs_of_surviving_by_hour_of_the_day = resilience_stats['probs_of_surviving_by_hour_of_the_day']
190
211
  end
191
-
212
+
192
213
  if reopt_output['outputs']['Scenario']['Site']['PV'].class == Hash
193
214
  reopt_output['outputs']['Scenario']['Site']['PV'] = [reopt_output['outputs']['Scenario']['Site']['PV']]
194
215
  elsif reopt_output['outputs']['Scenario']['Site']['PV'].nil?
@@ -215,29 +236,22 @@ module URBANopt # :nodoc:
215
236
  end
216
237
 
217
238
  generation_timeseries_kwh = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
239
+ reopt_resolution = reopt_output['inputs']['Scenario']['time_steps_per_hour']
218
240
 
219
241
  unless reopt_output['outputs']['Scenario']['Site']['PV'].nil?
220
242
  reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
221
243
  if (pv['size_kw'] || 0) > 0
222
244
  if !pv['year_one_power_production_series_kw'].nil?
223
- generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
245
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
224
246
  end
225
247
  end
226
248
  end
227
249
  end
228
250
 
229
- unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
230
- if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
231
- if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
232
- generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
233
- end
234
- end
235
- end
236
-
237
251
  unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
238
252
  if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
239
253
  if !reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'].nil?
240
- generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']]
254
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
241
255
  end
242
256
  end
243
257
  end
@@ -245,7 +259,7 @@ module URBANopt # :nodoc:
245
259
  unless reopt_output['outputs']['Scenario']['Site']['Generator'].nil?
246
260
  if (reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0) > 0
247
261
  if !reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'].nil?
248
- generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']]
262
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
249
263
  end
250
264
  end
251
265
  end
@@ -257,70 +271,70 @@ module URBANopt # :nodoc:
257
271
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
258
272
  end
259
273
 
260
- $load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
274
+ $load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
261
275
  $load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
262
276
  if $load_col.nil?
263
277
  $load_col = feature_report.timeseries_csv.column_names.length
264
278
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
265
279
  end
266
280
 
267
- $utility_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
281
+ $utility_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
268
282
  $utility_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
269
283
  if $utility_to_load_col.nil?
270
284
  $utility_to_load_col = feature_report.timeseries_csv.column_names.length
271
285
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
272
286
  end
273
287
 
274
- $utility_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
288
+ $utility_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
275
289
  $utility_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
276
290
  if $utility_to_battery_col.nil?
277
291
  $utility_to_battery_col = feature_report.timeseries_csv.column_names.length
278
292
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
279
293
  end
280
294
 
281
- $storage_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
295
+ $storage_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
282
296
  $storage_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
283
297
  if $storage_to_load_col.nil?
284
298
  $storage_to_load_col = feature_report.timeseries_csv.column_names.length
285
299
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
286
300
  end
287
301
 
288
- $storage_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
302
+ $storage_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
289
303
  $storage_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
290
304
  if $storage_to_grid_col.nil?
291
305
  $storage_to_grid_col = feature_report.timeseries_csv.column_names.length
292
306
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
293
307
  end
294
308
 
295
- $storage_soc = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct']) || [0] * (8760 * feature_report.timesteps_per_hour)
309
+ $storage_soc = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
296
310
  $storage_soc_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
297
311
  if $storage_soc_col.nil?
298
312
  $storage_soc_col = feature_report.timeseries_csv.column_names.length
299
313
  feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
300
314
  end
301
315
 
302
- $generator_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
316
+ $generator_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
303
317
  $generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
304
318
  if $generator_total_col.nil?
305
319
  $generator_total_col = feature_report.timeseries_csv.column_names.length
306
320
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
307
321
  end
308
322
 
309
- $generator_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
323
+ $generator_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
310
324
  $generator_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
311
325
  if $generator_to_battery_col.nil?
312
326
  $generator_to_battery_col = feature_report.timeseries_csv.column_names.length
313
327
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
314
328
  end
315
329
 
316
- $generator_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
330
+ $generator_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
317
331
  $generator_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
318
332
  if $generator_to_load_col.nil?
319
333
  $generator_to_load_col = feature_report.timeseries_csv.column_names.length
320
334
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
321
335
  end
322
336
 
323
- $generator_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
337
+ $generator_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
324
338
  $generator_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
325
339
  if $generator_to_grid_col.nil?
326
340
  $generator_to_grid_col = feature_report.timeseries_csv.column_names.length
@@ -359,10 +373,10 @@ module URBANopt # :nodoc:
359
373
 
360
374
  reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
361
375
  if (pv['size_kw'] || 0) > 0
362
- $pv_total += Matrix[scale_timeseries(pv['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
363
- $pv_to_battery += Matrix[scale_timeseries(pv['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
364
- $pv_to_load += Matrix[scale_timeseries(pv['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
365
- $pv_to_grid += Matrix[scale_timeseries(pv['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
376
+ $pv_total += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
377
+ $pv_to_battery += Matrix[convert_powerflow_resolution(pv['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
378
+ $pv_to_load += Matrix[convert_powerflow_resolution(pv['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
379
+ $pv_to_grid += Matrix[convert_powerflow_resolution(pv['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
366
380
  end
367
381
  end
368
382
 
@@ -371,28 +385,28 @@ module URBANopt # :nodoc:
371
385
  $pv_to_load = $pv_to_load.to_a[0]
372
386
  $pv_to_grid = $pv_to_grid.to_a[0]
373
387
 
374
- $wind_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
388
+ $wind_total = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
375
389
  $wind_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
376
390
  if $wind_total_col.nil?
377
391
  $wind_total_col = feature_report.timeseries_csv.column_names.length
378
392
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
379
393
  end
380
394
 
381
- $wind_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
395
+ $wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
382
396
  $wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
383
397
  if $wind_to_battery_col.nil?
384
398
  $wind_to_battery_col = feature_report.timeseries_csv.column_names.length
385
399
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
386
400
  end
387
401
 
388
- $wind_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
402
+ $wind_to_load = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
389
403
  $wind_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
390
404
  if $wind_to_load_col.nil?
391
405
  $wind_to_load_col = feature_report.timeseries_csv.column_names.length
392
406
  feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
393
407
  end
394
408
 
395
- $wind_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
409
+ $wind_to_grid = convert_powerflow_resolution(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
396
410
  $wind_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
397
411
  if $wind_to_grid_col.nil?
398
412
  $wind_to_grid_col = feature_report.timeseries_csv.column_names.length
@@ -424,11 +438,17 @@ module URBANopt # :nodoc:
424
438
 
425
439
  old_data = CSV.open(feature_report.timeseries_csv.path).read
426
440
  start_date = Time.parse(old_data[1][0])
427
- 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 / feature_report.timesteps_per_hour ) * 60)).to_int
441
+ start_ts = (
442
+ (
443
+ ((start_date.yday - 1) * 60.0 * 60.0 * 24) +
444
+ (((start_date.hour) - 1) * 60.0 * 60.0) +
445
+ (start_date.min * 60.0) + start_date.sec ) /
446
+ (( 60 / feature_report.timesteps_per_hour ) * 60)
447
+ ).to_int
428
448
 
429
449
  mod_data = old_data.map.with_index do |x, i|
430
450
  if i > 0
431
- modrow(x, start_ts + i -2)
451
+ modrow(x, start_ts + i -1)
432
452
  else
433
453
  x
434
454
  end