urbanopt-reopt 0.5.4 → 0.6.1

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