urbanopt-reopt 1.3.0 → 1.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/lib/urbanopt/reopt/feature_report_adapter.rb +53 -22
- data/lib/urbanopt/reopt/reopt_ghp_adapter_ghp.rb +27 -29
- data/lib/urbanopt/reopt/reopt_ghp_api.rb +3 -8
- data/lib/urbanopt/reopt/scenario_report_adapter.rb +54 -23
- data/lib/urbanopt/reopt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16f2855f1542984a58e3c18227c04edd4ed17e6a7a363989b38ca51b930824c1
|
|
4
|
+
data.tar.gz: b968cf095c32503e8ddba6bfde6a4a7d781bff5326108da9ed87fd69f4a6385e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c6c52124fb29ca5c298d61377f95b0d060bd066bfe1ebd254f09f9c47ba870e050c34c4f395b3e23b0823879af60699a1fa0e24985dba87c02ea78fcada2cd8
|
|
7
|
+
data.tar.gz: 0cc3b7e46f640af234307a8b62e6665067d8a4ec3a303ffda482d2b3c0bb488dd3fb0062ab4507d26f2e72281b2274a47987050a23f9f43f949d9f4350c90802
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# URBANopt REopt Gem
|
|
2
2
|
|
|
3
|
+
## Version 1.3.1
|
|
4
|
+
|
|
5
|
+
* Fix showing the battery and PV columns in scenario_optimization in https://github.com/urbanopt/urbanopt-reopt-gem/pull/176
|
|
6
|
+
* Update error handling for ghp LCCA in https://github.com/urbanopt/urbanopt-reopt-gem/pull/177
|
|
7
|
+
|
|
3
8
|
## Version 1.3.0
|
|
9
|
+
|
|
4
10
|
* Updates for developer.nlr.gov URL change
|
|
5
11
|
* Timeseries shift bug fix
|
|
6
12
|
* Added Domestic Hot Water to baseline load
|
|
@@ -14,7 +20,7 @@
|
|
|
14
20
|
|
|
15
21
|
## Version 1.1.0
|
|
16
22
|
|
|
17
|
-
* Upgrade to OpenStudio 3.10
|
|
23
|
+
* Upgrade to OpenStudio 3.10
|
|
18
24
|
|
|
19
25
|
## Version 1.0.0
|
|
20
26
|
|
|
@@ -226,6 +226,10 @@ module URBANopt # :nodoc:
|
|
|
226
226
|
end
|
|
227
227
|
end
|
|
228
228
|
|
|
229
|
+
wind = nil
|
|
230
|
+
generator = nil
|
|
231
|
+
storage = nil
|
|
232
|
+
|
|
229
233
|
if reopt_output['outputs'].key?('Wind')
|
|
230
234
|
wind = reopt_output['outputs']['Wind']
|
|
231
235
|
feature_report.distributed_generation.add_tech 'wind', URBANopt::Reporting::DefaultReports::Wind.new({ size_kw: (wind['size_kw'] || 0) })
|
|
@@ -235,29 +239,49 @@ module URBANopt # :nodoc:
|
|
|
235
239
|
generator = reopt_output['outputs']['Generator']
|
|
236
240
|
feature_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new({ size_kw: (generator['size_kw'] || 0) })
|
|
237
241
|
end
|
|
242
|
+
$has_generator = !generator.nil?
|
|
238
243
|
|
|
239
244
|
if reopt_output['outputs'].key?('ElectricStorage')
|
|
240
245
|
storage = reopt_output['outputs']['ElectricStorage']
|
|
241
246
|
feature_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new({ size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
|
|
242
247
|
end
|
|
248
|
+
$has_storage = !storage.nil?
|
|
249
|
+
$has_wind = !wind.nil?
|
|
243
250
|
|
|
244
251
|
generation_timeseries_kwh = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
|
|
245
252
|
reopt_resolution = reopt_output['inputs']['Settings']['time_steps_per_hour']
|
|
246
253
|
|
|
247
254
|
if reopt_output['outputs'].key?('PV') && !reopt_output['outputs']['PV'].nil?
|
|
248
255
|
reopt_output['outputs']['PV'].each do |pv|
|
|
249
|
-
|
|
250
|
-
|
|
256
|
+
next unless (pv['size_kw'] || 0) > 0
|
|
257
|
+
|
|
258
|
+
pv_production_series = pv['year_one_power_production_series_kw']
|
|
259
|
+
pv_production_series ||= pv['production_factor_series']&.map { |v| v * pv['size_kw'] }
|
|
260
|
+
if !pv_production_series.nil?
|
|
261
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv_production_series, reopt_resolution, feature_report.timesteps_per_hour)]
|
|
251
262
|
end
|
|
252
263
|
end
|
|
253
264
|
end
|
|
254
265
|
|
|
255
|
-
if reopt_output['outputs'].key?('Wind') && !reopt_output['outputs']['Wind'].nil? && ((reopt_output['outputs']['Wind']['size_kw'] || 0) > 0)
|
|
256
|
-
|
|
266
|
+
if reopt_output['outputs'].key?('Wind') && !reopt_output['outputs']['Wind'].nil? && ((reopt_output['outputs']['Wind']['size_kw'] || 0) > 0)
|
|
267
|
+
wind_production_series = reopt_output['outputs']['Wind']['year_one_power_production_series_kw']
|
|
268
|
+
wind_production_series ||= reopt_output['outputs']['Wind']['production_factor_series']&.map { |v| v * reopt_output['outputs']['Wind']['size_kw'] }
|
|
269
|
+
if !wind_production_series.nil?
|
|
270
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(wind_production_series, reopt_resolution, feature_report.timesteps_per_hour)]
|
|
271
|
+
end
|
|
257
272
|
end
|
|
258
273
|
|
|
259
|
-
if reopt_output['outputs'].key?('Generator') && !reopt_output['outputs']['Generator'].nil? && ((reopt_output['outputs']['Generator']['size_kw'] || 0) > 0)
|
|
260
|
-
|
|
274
|
+
if reopt_output['outputs'].key?('Generator') && !reopt_output['outputs']['Generator'].nil? && ((reopt_output['outputs']['Generator']['size_kw'] || 0) > 0)
|
|
275
|
+
generator_production_series = reopt_output['outputs']['Generator']['year_one_power_production_series_kw']
|
|
276
|
+
if generator_production_series.nil?
|
|
277
|
+
eto_load = reopt_output['outputs']['Generator']['electric_to_load_series_kw']
|
|
278
|
+
eto_storage = reopt_output['outputs']['Generator']['electric_to_storage_series_kw']
|
|
279
|
+
eto_grid = reopt_output['outputs']['Generator']['electric_to_grid_series_kw']
|
|
280
|
+
generator_production_series = eto_load.zip(eto_storage, eto_grid).map { |vals| vals.compact.sum } if eto_load && eto_storage && eto_grid
|
|
281
|
+
end
|
|
282
|
+
if !generator_production_series.nil?
|
|
283
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(generator_production_series, reopt_resolution, feature_report.timesteps_per_hour)]
|
|
284
|
+
end
|
|
261
285
|
end
|
|
262
286
|
|
|
263
287
|
$generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * (8760 * feature_report.timesteps_per_hour)
|
|
@@ -312,7 +336,9 @@ module URBANopt # :nodoc:
|
|
|
312
336
|
end
|
|
313
337
|
|
|
314
338
|
if !generator.nil?
|
|
315
|
-
|
|
339
|
+
generator_production_series = reopt_output['outputs']['Generator']['year_one_power_production_series_kw']
|
|
340
|
+
generator_production_series ||= reopt_output['outputs']['Generator']['electric_to_storage_series_kw']&.zip(reopt_output['outputs']['Generator']['electric_to_load_series_kw'], reopt_output['outputs']['Generator']['electric_to_grid_series_kw'])&.map { |vals| vals.compact.sum }
|
|
341
|
+
$generator_total = convert_powerflow_resolution(generator_production_series, reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
|
|
316
342
|
$generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
|
|
317
343
|
if $generator_total_col.nil?
|
|
318
344
|
$generator_total_col = feature_report.timeseries_csv.column_names.length
|
|
@@ -379,7 +405,9 @@ module URBANopt # :nodoc:
|
|
|
379
405
|
|
|
380
406
|
reopt_output['outputs']['PV'].each_with_index do |pv, i|
|
|
381
407
|
if (pv['size_kw'] || 0) > 0
|
|
382
|
-
|
|
408
|
+
pv_production_series = pv['year_one_power_production_series_kw']
|
|
409
|
+
pv_production_series ||= pv['production_factor_series']&.map { |v| v * pv['size_kw'] }
|
|
410
|
+
$pv_total += Matrix[convert_powerflow_resolution(pv_production_series, reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
|
383
411
|
if !storage.nil?
|
|
384
412
|
$pv_to_battery += Matrix[convert_powerflow_resolution(pv['electric_to_storage_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)]
|
|
385
413
|
end
|
|
@@ -396,7 +424,6 @@ module URBANopt # :nodoc:
|
|
|
396
424
|
$pv_to_grid = $pv_to_grid.to_a[0]
|
|
397
425
|
end
|
|
398
426
|
|
|
399
|
-
# $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)
|
|
400
427
|
$wind_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
|
|
401
428
|
if $wind_total_col.nil?
|
|
402
429
|
$wind_total_col = feature_report.timeseries_csv.column_names.length
|
|
@@ -404,6 +431,10 @@ module URBANopt # :nodoc:
|
|
|
404
431
|
end
|
|
405
432
|
|
|
406
433
|
if !wind.nil?
|
|
434
|
+
wind_production_series = reopt_output['outputs']['Wind']['year_one_power_production_series_kw']
|
|
435
|
+
wind_production_series ||= reopt_output['outputs']['Wind']['production_factor_series']&.map { |v| v * reopt_output['outputs']['Wind']['size_kw'] }
|
|
436
|
+
$wind_total = convert_powerflow_resolution(wind_production_series, reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
|
|
437
|
+
|
|
407
438
|
if !storage.nil?
|
|
408
439
|
$wind_to_battery = convert_powerflow_resolution(reopt_output['outputs']['Wind']['electric_to_storage_series_kw'], reopt_resolution, feature_report.timesteps_per_hour) || [0] * (8760 * feature_report.timesteps_per_hour)
|
|
409
440
|
$wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
|
|
@@ -432,22 +463,22 @@ module URBANopt # :nodoc:
|
|
|
432
463
|
x[$generation_timeseries_kwh_col] = $generation_timeseries_kwh[i] || 0
|
|
433
464
|
x[$load_col] = $load[i] || 0
|
|
434
465
|
x[$utility_to_load_col] = $utility_to_load[i] || 0
|
|
435
|
-
x[$utility_to_battery_col] = $utility_to_battery[i] || 0 if
|
|
436
|
-
x[$storage_to_load_col] = $storage_to_load[i] || 0 if
|
|
437
|
-
x[$storage_to_grid_col] = $storage_to_grid[i] || 0 if
|
|
438
|
-
x[$storage_soc_col] = $storage_soc[i] || 0 if
|
|
439
|
-
x[$generator_total_col] = $generator_total[i] || 0 if
|
|
440
|
-
x[$generator_to_battery_col] = $generator_to_battery[i] || 0 if
|
|
441
|
-
x[$generator_to_load_col] = $generator_to_load[i] || 0 if
|
|
442
|
-
x[$generator_to_grid_col] = $generator_to_grid[i] || 0 if
|
|
466
|
+
x[$utility_to_battery_col] = $utility_to_battery[i] || 0 if $has_storage
|
|
467
|
+
x[$storage_to_load_col] = $storage_to_load[i] || 0 if $has_storage
|
|
468
|
+
x[$storage_to_grid_col] = $storage_to_grid[i] || 0 if $has_storage
|
|
469
|
+
x[$storage_soc_col] = $storage_soc[i] || 0 if $has_storage
|
|
470
|
+
x[$generator_total_col] = $generator_total[i] || 0 if $has_generator
|
|
471
|
+
x[$generator_to_battery_col] = $generator_to_battery[i] || 0 if $has_generator && $has_storage
|
|
472
|
+
x[$generator_to_load_col] = $generator_to_load[i] || 0 if $has_generator
|
|
473
|
+
x[$generator_to_grid_col] = $generator_to_grid[i] || 0 if $has_generator
|
|
443
474
|
x[$pv_total_col] = $pv_total[i] || 0
|
|
444
|
-
x[$pv_to_battery_col] = $pv_to_battery[i] || 0 if
|
|
475
|
+
x[$pv_to_battery_col] = $pv_to_battery[i] || 0 if $has_storage
|
|
445
476
|
x[$pv_to_load_col] = $pv_to_load[i] || 0
|
|
446
477
|
x[$pv_to_grid_col] = $pv_to_grid[i] || 0
|
|
447
|
-
x[$wind_total_col] = $wind_total[i] || 0 if
|
|
448
|
-
x[$wind_to_battery_col] = $wind_to_battery[i] || 0 if
|
|
449
|
-
x[$wind_to_load_col] = $wind_to_load[i] || 0 if
|
|
450
|
-
x[$wind_to_grid_col] = $wind_to_grid[i] || 0 if
|
|
478
|
+
x[$wind_total_col] = $wind_total[i] || 0 if $has_wind
|
|
479
|
+
x[$wind_to_battery_col] = $wind_to_battery[i] || 0 if $has_wind && $has_storage
|
|
480
|
+
x[$wind_to_load_col] = $wind_to_load[i] || 0 if $has_wind
|
|
481
|
+
x[$wind_to_grid_col] = $wind_to_grid[i] || 0 if $has_wind
|
|
451
482
|
return x
|
|
452
483
|
end
|
|
453
484
|
|
|
@@ -261,7 +261,7 @@ module URBANopt # :nodoc:
|
|
|
261
261
|
|
|
262
262
|
end
|
|
263
263
|
|
|
264
|
-
#save output report in reopt_ghp directory
|
|
264
|
+
# save output report in reopt_ghp directory
|
|
265
265
|
reopt_ghp_dir = File.join(run_dir, "reopt_ghp", "reopt_ghp_inputs")
|
|
266
266
|
json_file_path = File.join(reopt_ghp_dir, "GHP_building_#{building_id}.json")
|
|
267
267
|
pretty_json = JSON.pretty_generate(reopt_inputs_building)
|
|
@@ -333,38 +333,36 @@ module URBANopt # :nodoc:
|
|
|
333
333
|
|
|
334
334
|
|
|
335
335
|
# Read GHX sizes from system parameter hash
|
|
336
|
-
ghe_specific_params = system_parameter_hash
|
|
337
|
-
|
|
338
|
-
ghe_specific_params.each do |ghe|
|
|
339
|
-
if ghe[:ghe_id] == ghp_id
|
|
340
|
-
unless ghe[:pre_designed_borefield]
|
|
341
|
-
if ghe[:autosized_rectangle_borefield]
|
|
342
|
-
borefield = ghe[:autosized_rectangle_borefield]
|
|
343
|
-
|
|
344
|
-
elsif ghe[:autosized_rectangle_constrained_borefield]
|
|
345
|
-
borefield = ghe[:autosized_rectangle_constrained_borefield]
|
|
336
|
+
ghe_specific_params = system_parameter_hash.dig(:district_system, :fifth_generation, :ghe_parameters, :borefields)
|
|
346
337
|
|
|
347
|
-
|
|
348
|
-
|
|
338
|
+
# Initialize outputs; validation below will raise if borefield sizing is missing.
|
|
339
|
+
ghpghx_output[:outputs][:number_of_boreholes] = 0
|
|
340
|
+
ghpghx_output[:outputs][:length_boreholes_ft] = 0
|
|
349
341
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
borefield = ghe[:autosized_bizoned_rectangle_borefield]
|
|
355
|
-
|
|
356
|
-
elsif ghe[:autosized_near_square_borefield]
|
|
357
|
-
borefield = ghe[:autosized_near_square_borefield]
|
|
342
|
+
if ghe_specific_params.nil? || ghe_specific_params.empty?
|
|
343
|
+
raise 'No borefields found at district_system.fifth_generation.ghe_parameters.borefields in the system parameters file. Run `uo ghe_size` to size your GHE before running this workflow.'
|
|
344
|
+
else
|
|
345
|
+
ghe = ghe_specific_params.find { |candidate| candidate[:ghe_id] == ghp_id }
|
|
358
346
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
347
|
+
if ghe.nil?
|
|
348
|
+
raise "No borefield found with ghe_id '#{ghp_id}' in the system parameters file. Make sure your ghe_id matches one of the sized GHE entries from the uo ghe_size command"
|
|
349
|
+
else
|
|
350
|
+
borefield = ghe[:pre_designed_borefield] ||
|
|
351
|
+
ghe[:autosized_rectangle_borefield] ||
|
|
352
|
+
ghe[:autosized_rectangle_constrained_borefield] ||
|
|
353
|
+
ghe[:autosized_birectangle_borefield] ||
|
|
354
|
+
ghe[:autosized_birectangle_constrained_borefield] ||
|
|
355
|
+
ghe[:autosized_bizoned_rectangle_borefield] ||
|
|
356
|
+
ghe[:autosized_near_square_borefield] ||
|
|
357
|
+
ghe[:autosized_rowwise_borefield]
|
|
358
|
+
|
|
359
|
+
if borefield.nil?
|
|
360
|
+
raise "No borefield sizing found for ghe_id '#{ghp_id}'. Expected one of: pre_designed_borefield, autosized_rectangle_borefield, autosized_rectangle_constrained_borefield, autosized_birectangle_borefield, autosized_birectangle_constrained_borefield, autosized_bizoned_rectangle_borefield, autosized_near_square_borefield, autosized_rowwise_borefield. Run `uo ghe_size` or provide a pre_designed_borefield."
|
|
361
|
+
else
|
|
362
|
+
ghpghx_output[:outputs][:number_of_boreholes] = borefield[:number_of_boreholes].to_i
|
|
363
|
+
# convert meters to feet by multiplying with 3.28084
|
|
364
|
+
ghpghx_output[:outputs][:length_boreholes_ft] = borefield[:borehole_length].to_f * 3.28084
|
|
362
365
|
end
|
|
363
|
-
|
|
364
|
-
ghpghx_output[:outputs][:number_of_boreholes] = borefield[:number_of_boreholes]
|
|
365
|
-
# convert meters to feet by multiplying with 3.28084
|
|
366
|
-
ghpghx_output[:outputs][:length_boreholes_ft] = (borefield[:borehole_length])*3.28084
|
|
367
|
-
|
|
368
366
|
end
|
|
369
367
|
end
|
|
370
368
|
|
|
@@ -53,7 +53,7 @@ module URBANopt # :nodoc:
|
|
|
53
53
|
reopt_output_file = @reopt_output_file
|
|
54
54
|
|
|
55
55
|
if run_id.nil?
|
|
56
|
-
run_id = get_run_uuid
|
|
56
|
+
run_id = get_run_uuid
|
|
57
57
|
end
|
|
58
58
|
if !run_id.nil?
|
|
59
59
|
results_url = @url_config.url_for('job', run_uuid: run_id)
|
|
@@ -71,13 +71,8 @@ module URBANopt # :nodoc:
|
|
|
71
71
|
results
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def get_run_uuid
|
|
75
|
-
|
|
76
|
-
reopt_input_file = @reopt_input_file
|
|
77
|
-
api_key = @api_key
|
|
78
|
-
root_url = @root_url
|
|
74
|
+
def get_run_uuid
|
|
79
75
|
post_url = @url_config.url_for('job')
|
|
80
|
-
puts "This is URL: #{post_url}"
|
|
81
76
|
@@logger.info("Connecting to #{post_url}")
|
|
82
77
|
|
|
83
78
|
# Parse the URL and prepare the HTTP request
|
|
@@ -86,7 +81,7 @@ module URBANopt # :nodoc:
|
|
|
86
81
|
request.content_type = 'application/json'
|
|
87
82
|
|
|
88
83
|
# Add the JSON payload (assuming 'post' is the body data)
|
|
89
|
-
request.body = reopt_input_file.to_json
|
|
84
|
+
request.body = @reopt_input_file.to_json
|
|
90
85
|
|
|
91
86
|
# Send the HTTP request
|
|
92
87
|
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
@@ -272,6 +272,10 @@ module URBANopt # :nodoc:
|
|
|
272
272
|
end
|
|
273
273
|
end
|
|
274
274
|
|
|
275
|
+
wind = nil
|
|
276
|
+
generator = nil
|
|
277
|
+
storage = nil
|
|
278
|
+
|
|
275
279
|
if reopt_output['outputs'].key?('Wind')
|
|
276
280
|
wind = reopt_output['outputs']['Wind']
|
|
277
281
|
# find size_class
|
|
@@ -284,29 +288,49 @@ module URBANopt # :nodoc:
|
|
|
284
288
|
generator = reopt_output['outputs']['Generator']
|
|
285
289
|
scenario_report.distributed_generation.add_tech 'generator', URBANopt::Reporting::DefaultReports::Generator.new({ size_kw: (generator['size_kw'] || 0) })
|
|
286
290
|
end
|
|
291
|
+
$has_generator = !generator.nil?
|
|
287
292
|
|
|
288
293
|
if reopt_output['outputs'].key?('ElectricStorage')
|
|
289
294
|
storage = reopt_output['outputs']['ElectricStorage']
|
|
290
295
|
scenario_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new({ size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
|
|
291
296
|
end
|
|
297
|
+
$has_storage = !storage.nil?
|
|
298
|
+
$has_wind = !wind.nil?
|
|
292
299
|
|
|
293
300
|
reopt_resolution = reopt_output['inputs']['Settings']['time_steps_per_hour']
|
|
294
301
|
generation_timeseries_kwh = Matrix[[0] * (8760 * scenario_report.timesteps_per_hour)]
|
|
295
302
|
|
|
296
303
|
if reopt_output['outputs'].key?('PV') && !reopt_output['outputs']['PV'].nil?
|
|
297
304
|
reopt_output['outputs']['PV'].each do |pv|
|
|
298
|
-
|
|
299
|
-
|
|
305
|
+
next unless (pv['size_kw'] || 0) > 0
|
|
306
|
+
|
|
307
|
+
pv_production_series = pv['year_one_power_production_series_kw']
|
|
308
|
+
pv_production_series ||= pv['production_factor_series']&.map { |v| v * pv['size_kw'] }
|
|
309
|
+
if !pv_production_series.nil?
|
|
310
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv_production_series, reopt_resolution, scenario_report.timesteps_per_hour)]
|
|
300
311
|
end
|
|
301
312
|
end
|
|
302
313
|
end
|
|
303
314
|
|
|
304
|
-
if reopt_output['outputs'].key?('Wind') && !reopt_output['outputs']['Wind'].nil? && ((reopt_output['outputs']['Wind']['size_kw'] || 0) > 0)
|
|
305
|
-
|
|
315
|
+
if reopt_output['outputs'].key?('Wind') && !reopt_output['outputs']['Wind'].nil? && ((reopt_output['outputs']['Wind']['size_kw'] || 0) > 0)
|
|
316
|
+
wind_production_series = reopt_output['outputs']['Wind']['year_one_power_production_series_kw']
|
|
317
|
+
wind_production_series ||= reopt_output['outputs']['Wind']['production_factor_series']&.map { |v| v * reopt_output['outputs']['Wind']['size_kw'] }
|
|
318
|
+
if !wind_production_series.nil?
|
|
319
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(wind_production_series, reopt_resolution, scenario_report.timesteps_per_hour)]
|
|
320
|
+
end
|
|
306
321
|
end
|
|
307
322
|
|
|
308
|
-
if reopt_output['outputs'].key?('Generator') && !reopt_output['outputs']['Generator'].nil? && ((reopt_output['outputs']['Generator']['size_kw'] || 0) > 0)
|
|
309
|
-
|
|
323
|
+
if reopt_output['outputs'].key?('Generator') && !reopt_output['outputs']['Generator'].nil? && ((reopt_output['outputs']['Generator']['size_kw'] || 0) > 0)
|
|
324
|
+
generator_production_series = reopt_output['outputs']['Generator']['year_one_power_production_series_kw']
|
|
325
|
+
if generator_production_series.nil?
|
|
326
|
+
eto_load = reopt_output['outputs']['Generator']['electric_to_load_series_kw']
|
|
327
|
+
eto_storage = reopt_output['outputs']['Generator']['electric_to_storage_series_kw']
|
|
328
|
+
eto_grid = reopt_output['outputs']['Generator']['electric_to_grid_series_kw']
|
|
329
|
+
generator_production_series = eto_load.zip(eto_storage, eto_grid).map { |vals| vals.compact.sum } if eto_load && eto_storage && eto_grid
|
|
330
|
+
end
|
|
331
|
+
if !generator_production_series.nil?
|
|
332
|
+
generation_timeseries_kwh += Matrix[convert_powerflow_resolution(generator_production_series, reopt_resolution, scenario_report.timesteps_per_hour)]
|
|
333
|
+
end
|
|
310
334
|
end
|
|
311
335
|
|
|
312
336
|
$generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * (8760 * scenario_report.timesteps_per_hour)
|
|
@@ -316,7 +340,8 @@ module URBANopt # :nodoc:
|
|
|
316
340
|
scenario_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
|
|
317
341
|
end
|
|
318
342
|
|
|
319
|
-
|
|
343
|
+
electric_load_series = reopt_output['outputs']['ElectricLoad']['year_one_electric_load_series_kw'] || reopt_output['outputs']['ElectricLoad']['load_series_kw']
|
|
344
|
+
$load = convert_powerflow_resolution(electric_load_series, reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
|
320
345
|
$load_col = scenario_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
|
|
321
346
|
if $load_col.nil?
|
|
322
347
|
$load_col = scenario_report.timeseries_csv.column_names.length
|
|
@@ -361,7 +386,9 @@ module URBANopt # :nodoc:
|
|
|
361
386
|
end
|
|
362
387
|
|
|
363
388
|
if !generator.nil?
|
|
364
|
-
|
|
389
|
+
generator_production_series = reopt_output['outputs']['Generator']['year_one_power_production_series_kw']
|
|
390
|
+
generator_production_series ||= reopt_output['outputs']['Generator']['electric_to_load_series_kw']&.zip(reopt_output['outputs']['Generator']['electric_to_storage_series_kw'], reopt_output['outputs']['Generator']['electric_to_grid_series_kw'])&.map { |vals| vals.compact.sum }
|
|
391
|
+
$generator_total = convert_powerflow_resolution(generator_production_series, reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
|
365
392
|
$generator_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
|
|
366
393
|
if $generator_total_col.nil?
|
|
367
394
|
$generator_total_col = scenario_report.timeseries_csv.column_names.length
|
|
@@ -428,7 +455,9 @@ module URBANopt # :nodoc:
|
|
|
428
455
|
|
|
429
456
|
reopt_output['outputs']['PV'].each_with_index do |pv, i|
|
|
430
457
|
if (pv['size_kw'] || 0) > 0
|
|
431
|
-
|
|
458
|
+
pv_production_series = pv['year_one_power_production_series_kw']
|
|
459
|
+
pv_production_series ||= pv['production_factor_series']&.map { |v| v * pv['size_kw'] }
|
|
460
|
+
$pv_total += Matrix[convert_powerflow_resolution(pv_production_series, reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
|
432
461
|
if !storage.nil?
|
|
433
462
|
$pv_to_battery += Matrix[convert_powerflow_resolution(pv['electric_to_storage_series_kw'], reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)]
|
|
434
463
|
end
|
|
@@ -446,7 +475,9 @@ module URBANopt # :nodoc:
|
|
|
446
475
|
end
|
|
447
476
|
|
|
448
477
|
if !wind.nil?
|
|
449
|
-
|
|
478
|
+
wind_production_series = reopt_output['outputs']['Wind']['year_one_power_production_series_kw']
|
|
479
|
+
wind_production_series ||= reopt_output['outputs']['Wind']['production_factor_series']&.map { |v| v * reopt_output['outputs']['Wind']['size_kw'] }
|
|
480
|
+
$wind_total = convert_powerflow_resolution(wind_production_series, reopt_resolution, scenario_report.timesteps_per_hour) || [0] * (8760 * scenario_report.timesteps_per_hour)
|
|
450
481
|
$wind_total_col = scenario_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
|
|
451
482
|
if $wind_total_col.nil?
|
|
452
483
|
$wind_total_col = scenario_report.timeseries_csv.column_names.length
|
|
@@ -481,22 +512,22 @@ module URBANopt # :nodoc:
|
|
|
481
512
|
data[$generation_timeseries_kwh_col] = $generation_timeseries_kwh[idx] || 0
|
|
482
513
|
data[$load_col] = $load[idx] || 0
|
|
483
514
|
data[$utility_to_load_col] = $utility_to_load[idx] || 0
|
|
484
|
-
data[$utility_to_battery_col] = $utility_to_battery[idx] || 0 if
|
|
485
|
-
data[$storage_to_load_col] = $storage_to_load[idx] || 0 if
|
|
486
|
-
data[$storage_to_grid_col] = $storage_to_grid[idx] || 0 if
|
|
487
|
-
data[$storage_soc_col] = $storage_soc[idx] || 0 if
|
|
488
|
-
data[$generator_total_col] = $generator_total[idx] || 0 if
|
|
489
|
-
data[$generator_to_battery_col] = $generator_to_battery[idx] || 0 if
|
|
490
|
-
data[$generator_to_load_col] = $generator_to_load[idx] || 0 if
|
|
491
|
-
data[$generator_to_grid_col] = $generator_to_grid[idx] || 0 if
|
|
515
|
+
data[$utility_to_battery_col] = $utility_to_battery[idx] || 0 if $has_storage
|
|
516
|
+
data[$storage_to_load_col] = $storage_to_load[idx] || 0 if $has_storage
|
|
517
|
+
data[$storage_to_grid_col] = $storage_to_grid[idx] || 0 if $has_storage
|
|
518
|
+
data[$storage_soc_col] = $storage_soc[idx] || 0 if $has_storage
|
|
519
|
+
data[$generator_total_col] = $generator_total[idx] || 0 if $has_generator
|
|
520
|
+
data[$generator_to_battery_col] = $generator_to_battery[idx] || 0 if $has_generator && $has_storage
|
|
521
|
+
data[$generator_to_load_col] = $generator_to_load[idx] || 0 if $has_generator
|
|
522
|
+
data[$generator_to_grid_col] = $generator_to_grid[idx] || 0 if $has_generator
|
|
492
523
|
data[$pv_total_col] = $pv_total[idx] || 0
|
|
493
|
-
data[$pv_to_battery_col] = $pv_to_battery[idx] || 0 if
|
|
524
|
+
data[$pv_to_battery_col] = $pv_to_battery[idx] || 0 if $has_storage
|
|
494
525
|
data[$pv_to_load_col] = $pv_to_load[idx] || 0
|
|
495
526
|
data[$pv_to_grid_col] = $pv_to_grid[idx] || 0
|
|
496
|
-
data[$wind_total_col] = $wind_total[idx] || 0 if
|
|
497
|
-
data[$wind_to_battery_col] = $wind_to_battery[idx] || 0 if
|
|
498
|
-
data[$wind_to_load_col] = $wind_to_load[idx] || 0 if
|
|
499
|
-
data[$wind_to_grid_col] = $wind_to_grid[idx] || 0 if
|
|
527
|
+
data[$wind_total_col] = $wind_total[idx] || 0 if $has_wind
|
|
528
|
+
data[$wind_to_battery_col] = $wind_to_battery[idx] || 0 if $has_wind && $has_storage
|
|
529
|
+
data[$wind_to_load_col] = $wind_to_load[idx] || 0 if $has_wind
|
|
530
|
+
data[$wind_to_grid_col] = $wind_to_grid[idx] || 0 if $has_wind
|
|
500
531
|
return data
|
|
501
532
|
end
|
|
502
533
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: urbanopt-reopt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ''
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: openstudio-extension
|