urbanopt-reopt 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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