lib/urbanopt/reopt/feature_report_adapter.rb in urbanopt-reopt-0.5.0 vs lib/urbanopt/reopt/feature_report_adapter.rb in urbanopt-reopt-0.5.4
- old
+ new
@@ -30,10 +30,11 @@
require 'urbanopt/reporting/default_reports'
require 'urbanopt/reopt/reopt_logger'
require 'csv'
require 'matrix'
+require_relative 'utilities'
require 'time'
module URBANopt # :nodoc:
module REopt # :nodoc:
class FeatureReportAdapter
@@ -85,45 +86,78 @@
# Parse Location
reopt_inputs[:Scenario][:Site][:latitude] = feature_report.location.latitude_deg
reopt_inputs[:Scenario][:Site][:longitude] = feature_report.location.longitude_deg
- # Parse Optional FeatureReport metrics
- unless feature_report.program.roof_area_sqft.nil?
- reopt_inputs[:Scenario][:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area]
+ # Parse Optional FeatureReport metrics - do not overwrite from assumptions file
+ if reopt_inputs[:Scenario][:Site][:roof_squarefeet].nil?
+ unless feature_report.program.roof_area_sqft.nil?
+ reopt_inputs[:Scenario][:Site][:roof_squarefeet] = feature_report.program.roof_area_sqft[:available_roof_area_sqft]
+ end
end
- unless feature_report.program.site_area_sqft.nil?
- reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
+ if reopt_inputs[:Scenario][:Site][:land_acres].nil?
+ unless feature_report.program.site_area_sqft.nil?
+ reopt_inputs[:Scenario][:Site][:land_acres] = feature_report.program.site_area_sqft * 1.0 / 43560 # acres/sqft
+ end
end
- unless feature_report.timesteps_per_hour.nil?
- reopt_inputs[:Scenario][:time_steps_per_hour] = feature_report.timesteps_per_hour
+ if reopt_inputs[:Scenario][:time_steps_per_hour].nil?
+ reopt_inputs[:Scenario][:time_steps_per_hour] = 1
end
# Parse Load Profile
begin
+ #Convert kWh values in the timeseries CSV to kW
col_num = feature_report.timeseries_csv.column_names.index('Electricity:Facility(kWh)')
t = CSV.read(feature_report.timeseries_csv.path, headers: true, converters: :numeric)
energy_timeseries_kw = t.by_col[col_num].map { |e| ((e * feature_report.timesteps_per_hour || 0) ) }
+ #Fill in missing timestep values with 0 if a full year is not provided
if energy_timeseries_kw.length < (feature_report.timesteps_per_hour * 8760)
start_date = Time.parse(t.by_col["Datetime"][0])
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
end_date = Time.parse(t.by_col["Datetime"][-1])
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) /
(( 60 / feature_report.timesteps_per_hour ) * 60)).to_int
energy_timeseries_kw = [0.0]*(start_ts-1) + energy_timeseries_kw + [0.0]*((feature_report.timesteps_per_hour * 8760) - end_ts)
- end
- reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw] = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(feature_report.timesteps_per_hour * 8760)]
+ end
+ #Clip to one non-leap year's worth of data
+ energy_timeseries_kw = energy_timeseries_kw.map { |e| e ? e : 0 }[0,(feature_report.timesteps_per_hour * 8760)]
+ #Convert from the OpenDSS resolution to the REopt Lite resolution, if necessary
rescue StandardError
@@logger.error("Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}")
raise "Could not parse the annual electric load from the timeseries csv - #{feature_report.timeseries_csv.path}"
end
+
+ # Convert load to REopt Resolution
+ begin
+ 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])
+
+ rescue
+ @@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]}")
+ 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]}"
+ end
+
+ if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps].nil?
+ n_top_values = 100
+ tmp1 = reopt_inputs[:Scenario][:Site][:LoadProfile][:loads_kw]
+ tmp2 = tmp1.each_index.max_by(n_top_values*reopt_inputs[:Scenario][:time_steps_per_hour]){|i| tmp1[i]}
+ for i in (0...tmp2.count)
+ tmp2[i] += 1
+ end
+ reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_active_timesteps] = tmp2
+ end
+
+ if reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw].nil?
+ reopt_inputs[:Scenario][:Site][:ElectricTariff][:coincident_peak_load_charge_us_dollars_per_kw] = 0
+ end
+
return reopt_inputs
end
+
##
# Update a FeatureReport from a \REopt Lite response
#
# [*parameters:*]
#
@@ -162,13 +196,10 @@
# Update location
feature_report.location.latitude_deg = reopt_output['inputs']['Scenario']['Site']['latitude']
feature_report.location.longitude_deg = reopt_output['inputs']['Scenario']['Site']['longitude']
- # Update timeseries csv from \REopt Lite dispatch data
- feature_report.timesteps_per_hour = reopt_output['inputs']['Scenario']['time_steps_per_hour']
-
# Update distributed generation sizing and financials
feature_report.distributed_generation.lcc_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['lcc_us_dollars'] || 0
feature_report.distributed_generation.npv_us_dollars = reopt_output['outputs']['Scenario']['Site']['Financial']['npv_us_dollars'] || 0
feature_report.distributed_generation.year_one_energy_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_energy_cost_us_dollars'] || 0
feature_report.distributed_generation.year_one_demand_cost_us_dollars = reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_demand_cost_us_dollars'] || 0
@@ -213,41 +244,34 @@
if !storage['size_kw'].nil? and storage['size_kw'] != 0
feature_report.distributed_generation.add_tech 'storage', URBANopt::Reporting::DefaultReports::Storage.new( {size_kwh: (storage['size_kwh'] || 0), size_kw: (storage['size_kw'] || 0) })
end
generation_timeseries_kwh = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
+ reopt_resolution = reopt_output['inputs']['Scenario']['time_steps_per_hour']
unless reopt_output['outputs']['Scenario']['Site']['PV'].nil?
reopt_output['outputs']['Scenario']['Site']['PV'].each do |pv|
if (pv['size_kw'] || 0) > 0
if !pv['year_one_power_production_series_kw'].nil?
- generation_timeseries_kwh += Matrix[pv['year_one_power_production_series_kw']]
+ generation_timeseries_kwh += Matrix[convert_powerflow_resolution(pv['year_one_power_production_series_kw'], reopt_resolution, feature_report.timesteps_per_hour)]
end
end
end
end
- unless reopt_output['outputs']['Scenario']['Site']['Storage'].nil?
- if (reopt_output['outputs']['Scenario']['Site']['Storage']['size_kw'] or 0) > 0
- if !reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw'].nil?
- generation_timeseries_kwh = generation_timeseries_kwh + Matrix[reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']]
- end
- end
- end
-
unless reopt_output['outputs']['Scenario']['Site']['Wind'].nil?
if (reopt_output['outputs']['Scenario']['Site']['Wind']['size_kw'] || 0) > 0
if !reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw'].nil?
- generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']]
+ 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)]
end
end
end
unless reopt_output['outputs']['Scenario']['Site']['Generator'].nil?
if (reopt_output['outputs']['Scenario']['Site']['Generator']['size_kw'] || 0) > 0
if !reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw'].nil?
- generation_timeseries_kwh += Matrix[reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']]
+ 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)]
end
end
end
$generation_timeseries_kwh = generation_timeseries_kwh.to_a[0] || [0] * (8760 * feature_report.timesteps_per_hour)
@@ -255,74 +279,74 @@
if $generation_timeseries_kwh_col.nil?
$generation_timeseries_kwh_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Total(kw)')
end
- $load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['LoadProfile']['year_one_electric_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Load:Total(kw)')
if $load_col.nil?
$load_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Load:Total(kw)')
end
- $utility_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$utility_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToLoad(kw)')
if $utility_to_load_col.nil?
$utility_to_load_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToLoad(kw)')
end
- $utility_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['ElectricTariff']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$utility_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Grid:ToBattery(kw)')
if $utility_to_battery_col.nil?
$utility_to_battery_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Grid:ToBattery(kw)')
end
- $storage_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$storage_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToLoad(kw)')
if $storage_to_load_col.nil?
$storage_to_load_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToLoad(kw)')
end
- $storage_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$storage_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:ToGrid(kw)')
if $storage_to_grid_col.nil?
$storage_to_grid_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:ToGrid(kw)')
end
- $storage_soc = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Storage']['year_one_soc_series_pct']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$storage_soc_col = feature_report.timeseries_csv.column_names.index('REopt:Electricity:Storage:StateOfCharge(pct)')
if $storage_soc_col.nil?
$storage_soc_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:Electricity:Storage:StateOfCharge(pct)')
end
- $generator_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$generator_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:Total(kw)')
if $generator_total_col.nil?
$generator_total_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:Total(kw)')
end
- $generator_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$generator_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToBattery(kw)')
if $generator_to_battery_col.nil?
$generator_to_battery_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToBattery(kw)')
end
- $generator_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$generator_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToLoad(kw)')
if $generator_to_load_col.nil?
$generator_to_load_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToLoad(kw)')
end
- $generator_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Generator']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$generator_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Generator:ToGrid(kw)')
if $generator_to_grid_col.nil?
$generator_to_grid_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Generator:ToGrid(kw)')
end
@@ -357,43 +381,43 @@
$pv_to_load = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
$pv_to_grid = Matrix[[0] * (8760 * feature_report.timesteps_per_hour)]
reopt_output['outputs']['Scenario']['Site']['PV'].each_with_index do |pv, i|
if (pv['size_kw'] || 0) > 0
- $pv_total += Matrix[scale_timeseries(pv['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
- $pv_to_battery += Matrix[scale_timeseries(pv['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
- $pv_to_load += Matrix[scale_timeseries(pv['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
- $pv_to_grid += Matrix[scale_timeseries(pv['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)]
+ $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)]
+ $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)]
+ $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)]
+ $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)]
end
end
$pv_total = $pv_total.to_a[0]
$pv_to_battery = $pv_to_battery.to_a[0]
$pv_to_load = $pv_to_load.to_a[0]
$pv_to_grid = $pv_to_grid.to_a[0]
- $wind_total = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_power_production_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$wind_total_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:Total(kw)')
if $wind_total_col.nil?
$wind_total_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:Total(kw)')
end
- $wind_to_battery = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_battery_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$wind_to_battery_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToBattery(kw)')
if $wind_to_battery_col.nil?
$wind_to_battery_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToBattery(kw)')
end
- $wind_to_load = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_load_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$wind_to_load_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToLoad(kw)')
if $wind_to_load_col.nil?
$wind_to_load_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToLoad(kw)')
end
- $wind_to_grid = scale_timeseries(reopt_output['outputs']['Scenario']['Site']['Wind']['year_one_to_grid_series_kw']) || [0] * (8760 * feature_report.timesteps_per_hour)
+ $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)
$wind_to_grid_col = feature_report.timeseries_csv.column_names.index('REopt:ElectricityProduced:Wind:ToGrid(kw)')
if $wind_to_grid_col.nil?
$wind_to_grid_col = feature_report.timeseries_csv.column_names.length
feature_report.timeseries_csv.column_names.push('REopt:ElectricityProduced:Wind:ToGrid(kw)')
end