urbanopt-reopt 0.5.4 → 0.6.1

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
@@ -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