From 577099b179272b67ec2d83ae52303bfcd7b789bf Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 16 Dec 2022 14:06:33 -0700 Subject: [PATCH 01/29] initial commit of name changes --- src/core/reopt_inputs.jl | 3 +- src/core/utils.jl | 2 +- src/outagesim/backup_reliability.jl | 12 +- src/outagesim/outage_simulator.jl | 10 +- src/results/absorption_chiller.jl | 27 ++--- src/results/boiler.jl | 36 +++--- src/results/chp.jl | 48 ++++---- src/results/electric_storage.jl | 14 +-- src/results/electric_utility.jl | 40 +++---- src/results/existing_boiler.jl | 28 ++--- src/results/existing_chiller.jl | 18 +-- src/results/generator.jl | 26 ++--- src/results/pv.jl | 39 ++++--- src/results/results.jl | 36 +++--- src/results/site.jl | 34 +++--- src/results/steam_turbine.jl | 40 +++---- src/results/thermal_storage.jl | 24 ++-- src/results/wind.jl | 36 +++--- test/runtests.jl | 6 +- test/test_with_cplex.jl | 4 +- test/test_with_xpress.jl | 172 ++++++++++++++-------------- 21 files changed, 330 insertions(+), 325 deletions(-) diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index 74e3dba57..22bf8475c 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -190,6 +190,7 @@ function REoptInputs(s::AbstractScenario) months = 1:12 levelization_factor, pwf_e, pwf_om, pwf_fuel, pwf_emissions_cost, pwf_grid_emissions, third_party_factor, pwf_offtaker, pwf_owner = setup_present_worth_factors(s, techs) + print("\nlevelization_factor: ", levelization_factor) # the following hardcoded values for levelization_factor matches the public REopt API value # and makes the test values match. # the REopt code herein uses the Desktop method for levelization_factor, which is more accurate @@ -197,7 +198,7 @@ function REoptInputs(s::AbstractScenario) # levelization_factor = Dict("PV" => 0.9539) # levelization_factor = Dict("ground" => 0.942238, "roof_east" => 0.942238, "roof_west" => 0.942238) # levelization_factor["PV"] = 0.9539 - # levelization_factor["Generator"] = 1.0 + # levelization_factor["Generator"] = 1.0 # TODO: does it make sense to default this to 1 while the calculation involves discount and escalation rates? time_steps_with_grid, time_steps_without_grid, = setup_electric_utility_inputs(s) ghp_options, require_ghp_purchase, ghp_heating_thermal_load_served_kw, diff --git a/src/core/utils.jl b/src/core/utils.jl index ae633687e..1366d1df6 100644 --- a/src/core/utils.jl +++ b/src/core/utils.jl @@ -70,7 +70,7 @@ function annuity_escalation(analysis_period::Int, rate_escalation::Real, rate_di end -function levelization_factor(years::Int, rate_escalation::Real, rate_discount::Real, +function levelization_factor(years::Int, rate_escalation::Real, rate_discount::Real, # TODO: should this account for escalation and discount rates? rate_degradation::Real) #= NOTE: levelization_factor for an electricity producing tech is the ratio of: diff --git a/src/outagesim/backup_reliability.jl b/src/outagesim/backup_reliability.jl index a163ce36c..f1f94e3ca 100644 --- a/src/outagesim/backup_reliability.jl +++ b/src/outagesim/backup_reliability.jl @@ -447,7 +447,7 @@ function backup_reliability_inputs(d::Dict, p::REoptInputs; r::Dict = Dict())::D critical_loads_kw = p.s.electric_load.critical_loads_kw if "CHP" in keys(d) - chp_generation = get(d["CHP"], "year_one_electric_production_series_kw", zero_array) + chp_generation = get(d["CHP"], "electric_production_series_kw", zero_array) critical_loads_kw .-= chp_generation end @@ -456,10 +456,10 @@ function backup_reliability_inputs(d::Dict, p::REoptInputs; r::Dict = Dict())::D pv_kw_ac_hourly = zero_array if "PV" in keys(d) pv_kw_ac_hourly = ( - get(d["PV"], "year_one_to_battery_series_kw", zero_array) - + get(d["PV"], "year_one_curtailed_production_series_kw", zero_array) - + get(d["PV"], "year_one_to_load_series_kw", zero_array) - + get(d["PV"], "year_one_to_grid_series_kw", zero_array) + get(d["PV"], "production_to_battery_series_kw", zero_array) + + get(d["PV"], "production_curtailed_series_kw", zero_array) + + get(d["PV"], "production_to_load_series_kw", zero_array) + + get(d["PV"], "production_to_grid_series_kw", zero_array) ) end if microgrid_only && !Bool(get(d, "PV_upgraded", false)) @@ -477,7 +477,7 @@ function backup_reliability_inputs(d::Dict, p::REoptInputs; r::Dict = Dict())::D batt_kwh = get(d["Storage"], "size_kwh", 0) batt_kw = get(d["Storage"], "size_kw", 0) - init_soc = get(d["Storage"], "year_one_soc_series_fraction", []) + init_soc = get(d["Storage"], "soc_series_fraction", []) if microgrid_only && !Bool(get(d, "storage_upgraded", false)) batt_kwh = 0 diff --git a/src/outagesim/outage_simulator.jl b/src/outagesim/outage_simulator.jl index 9498f3741..7c1bee304 100644 --- a/src/outagesim/outage_simulator.jl +++ b/src/outagesim/outage_simulator.jl @@ -259,10 +259,10 @@ function simulate_outages(d::Dict, p::REoptInputs; microgrid_only::Bool=false) pv_kw_ac_hourly = zeros(length(p.time_steps)) if "PV" in keys(d) pv_kw_ac_hourly = ( - get(d["PV"], "year_one_to_battery_series_kw", zeros(length(p.time_steps))) - + get(d["PV"], "year_one_curtailed_production_series_kw", zeros(length(p.time_steps))) - + get(d["PV"], "year_one_to_load_series_kw", zeros(length(p.time_steps))) - + get(d["PV"], "year_one_to_grid_series_kw", zeros(length(p.time_steps))) + get(d["PV"], "production_to_battery_series_kw", zeros(length(p.time_steps))) + + get(d["PV"], "production_curtailed_series_kw", zeros(length(p.time_steps))) + + get(d["PV"], "production_to_load_series_kw", zeros(length(p.time_steps))) + + get(d["PV"], "production_to_grid_series_kw", zeros(length(p.time_steps))) ) end if microgrid_only && !Bool(get(d["Outages"], "PV_upgraded", false)) @@ -275,7 +275,7 @@ function simulate_outages(d::Dict, p::REoptInputs; microgrid_only::Bool=false) if "ElectricStorage" in keys(d) batt_kwh = get(d["ElectricStorage"], "size_kwh", 0) batt_kw = get(d["ElectricStorage"], "size_kw", 0) - init_soc = get(d["ElectricStorage"], "year_one_soc_series_fraction", zeros(length(p.time_steps))) + init_soc = get(d["ElectricStorage"], "soc_series_fraction", zeros(length(p.time_steps))) end if microgrid_only && !Bool(get(d["Outages"], "storage_upgraded", false)) batt_kwh = 0 diff --git a/src/results/absorption_chiller.jl b/src/results/absorption_chiller.jl index 5af6ffdff..443202483 100644 --- a/src/results/absorption_chiller.jl +++ b/src/results/absorption_chiller.jl @@ -31,12 +31,13 @@ `AbsorptionChiller` results keys: - `size_kw` Power capacity size of the absorption chiller system [kW] - `size_ton` -- `year_one_to_tes_series_ton` -- `year_one_thermal_consumption_series` -- `year_one_thermal_consumption_kwh` -- `year_one_thermal_production_tonhour` -- `year_one_electric_consumption_series` -- `year_one_electric_consumption_kwh` +- `production_to_tes_series_ton` +- `production_to_load_series_ton` +- `thermal_consumption_series_mmbtu_per_hour` +- `annual_thermal_consumption_mmbtu` +- `annual_thermal_production_tonhour` +- `electric_consumption_series_kw` +- `annual_electric_consumption_kwh` """ function add_absorption_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `AbsorptionChiller` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -53,29 +54,29 @@ function add_absorption_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d r["size_ton"] = r["size_kw"] / KWH_THERMAL_PER_TONHOUR @expression(m, ABSORPCHLtoTESKW[ts in p.time_steps], sum(m[:dvProductionToStorage][b,t,ts] for b in p.s.storage.types.cold, t in p.techs.absorption_chiller)) - r["year_one_to_tes_series_ton"] = round.(value.(ABSORPCHLtoTESKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) + r["production_to_tes_series_ton"] = round.(value.(ABSORPCHLtoTESKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) @expression(m, ABSORPCHLtoLoadKW[ts in p.time_steps], sum(m[:dvThermalProduction][t,ts] for t in p.techs.absorption_chiller) - ABSORPCHLtoTESKW[ts]) - r["year_one_to_load_series_ton"] = round.(value.(ABSORPCHLtoLoadKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) + r["production_to_load_series_ton"] = round.(value.(ABSORPCHLtoLoadKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) @expression(m, ABSORPCHLThermalConsumptionSeriesKW[ts in p.time_steps], sum(m[:dvThermalProduction][t,ts] / p.thermal_cop[t] for t in p.techs.absorption_chiller)) - r["year_one_thermal_consumption_series_mmbtu_per_hour"] = round.(value.(ABSORPCHLThermalConsumptionSeriesKW) ./ KWH_PER_MMBTU, digits=5) + r["thermal_consumption_series_mmbtu_per_hour"] = round.(value.(ABSORPCHLThermalConsumptionSeriesKW) ./ KWH_PER_MMBTU, digits=5) @expression(m, Year1ABSORPCHLThermalConsumptionKWH, p.hours_per_time_step * sum(m[:dvThermalProduction][t,ts] / p.thermal_cop[t] for t in p.techs.absorption_chiller, ts in p.time_steps)) - r["year_one_thermal_consumption_mmbtu"] = round(value(Year1ABSORPCHLThermalConsumptionKWH) / KWH_PER_MMBTU, digits=5) + r["annual_thermal_consumption_mmbtu"] = round(value(Year1ABSORPCHLThermalConsumptionKWH) / KWH_PER_MMBTU, digits=5) @expression(m, Year1ABSORPCHLThermalProdKWH, p.hours_per_time_step * sum(m[:dvThermalProduction][t, ts] for t in p.techs.absorption_chiller, ts in p.time_steps)) - r["year_one_thermal_production_tonhour"] = round(value(Year1ABSORPCHLThermalProdKWH) / KWH_THERMAL_PER_TONHOUR, digits=5) + r["annual_thermal_production_tonhour"] = round(value(Year1ABSORPCHLThermalProdKWH) / KWH_THERMAL_PER_TONHOUR, digits=5) @expression(m, ABSORPCHLElectricConsumptionSeries[ts in p.time_steps], sum(m[:dvThermalProduction][t,ts] / p.cop[t] for t in p.techs.absorption_chiller) ) - r["year_one_electric_consumption_series_kw"] = round.(value.(ABSORPCHLElectricConsumptionSeries), digits=3) + r["electric_consumption_series_kw"] = round.(value.(ABSORPCHLElectricConsumptionSeries), digits=3) @expression(m, Year1ABSORPCHLElectricConsumption, p.hours_per_time_step * sum(m[:dvThermalProduction][t,ts] / p.cop[t] for t in p.techs.absorption_chiller, ts in p.time_steps)) - r["year_one_electric_consumption_kwh"] = round(value(Year1ABSORPCHLElectricConsumption), digits=3) + r["annual_electric_consumption_kwh"] = round(value(Year1ABSORPCHLElectricConsumption), digits=3) d["AbsorptionChiller"] = r nothing diff --git a/src/results/boiler.jl b/src/results/boiler.jl index 462a7ce26..fc2f6c9e7 100644 --- a/src/results/boiler.jl +++ b/src/results/boiler.jl @@ -30,28 +30,28 @@ """ `Boiler` results keys: - `size_mmbtu_per_hour` # Thermal production capacity size of the Boiler [MMBtu/hr] -- `year_one_fuel_consumption_series_mmbtu_per_hour` # Fuel consumption series [MMBtu] -- `year_one_fuel_consumption_mmbtu` # Fuel consumed in a year [MMBtu] -- `year_one_thermal_production_series_mmbtu_per_hour` # Thermal energy production series [MMBtu/hr] -- `year_one_thermal_production_mmbtu` # Thermal energy produced in a year [MMBtu] -- `year_one_thermal_to_tes_series_mmbtu_per_hour` # Thermal power production to HotThermalStorage series [MMBtu/hr] -- `year_one_thermal_to_steamturbine_series_mmbtu_per_hour` # Thermal power production to SteamTurbine series [MMBtu/hr] -- `year_one_thermal_to_load_series_mmbtu_per_hour` # Thermal power production to serve the heating load series [MMBtu/hr] -- `lifecycle_fuel_cost` # Life cycle fuel cost [\$] -- `year_one_fuel_cost` # Year one fuel cost [\$] +- `fuel_consumption_series_mmbtu_per_hour` # Fuel consumption series [MMBtu/hr] +- `annual_fuel_consumption_mmbtu` # Fuel consumed in a year [MMBtu] +- `thermal_production_series_mmbtu_per_hour` # Thermal energy production series [MMBtu/hr] +- `annual_thermal_production_mmbtu` # Thermal energy produced in a year [MMBtu] +- `thermal_to_tes_series_mmbtu_per_hour` # Thermal power production to HotThermalStorage series [MMBtu/hr] +- `thermal_to_steamturbine_series_mmbtu_per_hour` # Thermal power production to SteamTurbine series [MMBtu/hr] +- `thermal_to_load_series_mmbtu_per_hour` # Thermal power production to serve the heating load series [MMBtu/hr] +- `lifecycle_fuel_cost_after_tax` # Life cycle fuel cost [\$] +- `year_one_fuel_cost_before_tax` # Year one fuel cost [\$] - `lifecycle_per_unit_prod_om_costs` # Life cycle production-based O&M cost [\$] """ function add_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() r["size_mmbtu_per_hour"] = round(value(m[Symbol("dvSize"*_n)]["Boiler"]) / KWH_PER_MMBTU, digits=3) - r["year_one_fuel_consumption_series_mmbtu_per_hour"] = + r["fuel_consumption_series_mmbtu_per_hour"] = round.(value.(m[:dvFuelUsage]["Boiler", ts] for ts in p.time_steps) / KWH_PER_MMBTU, digits=3) - r["year_one_fuel_consumption_mmbtu"] = round(sum(r["year_one_fuel_consumption_series_mmbtu_per_hour"]), digits=3) + r["annual_fuel_consumption_mmbtu"] = round(sum(r["fuel_consumption_series_mmbtu_per_hour"]), digits=3) - r["year_one_thermal_production_series_mmbtu_per_hour"] = + r["thermal_production_series_mmbtu_per_hour"] = round.(value.(m[:dvThermalProduction]["Boiler", ts] for ts in p.time_steps) / KWH_PER_MMBTU, digits=5) - r["year_one_thermal_production_mmbtu"] = round(sum(r["year_one_thermal_production_series_mmbtu_per_hour"]), digits=3) + r["annual_thermal_production_mmbtu"] = round(sum(r["thermal_production_series_mmbtu_per_hour"]), digits=3) if !isempty(p.s.storage.types.hot) @expression(m, BoilerToHotTESKW[ts in p.time_steps], @@ -60,25 +60,25 @@ function add_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n=" else BoilerToHotTESKW = zeros(length(p.time_steps)) end - r["year_one_thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) + r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) if !isempty(p.techs.steam_turbine) && p.s.boiler.can_supply_steam_turbine @expression(m, BoilerToSteamTurbine[ts in p.time_steps], m[:dvThermalToSteamTurbine]["Boiler",ts]) else BoilerToSteamTurbine = zeros(length(p.time_steps)) end - r["year_one_thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(BoilerToSteamTurbine), digits=3) + r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(BoilerToSteamTurbine), digits=3) BoilerToLoad = @expression(m, [ts in p.time_steps], m[:dvThermalProduction]["Boiler", ts] - BoilerToHotTESKW[ts] - BoilerToSteamTurbine[ts] ) - r["year_one_thermal_to_load_series_mmbtu_per_hour"] = round.(value.(BoilerToLoad / KWH_PER_MMBTU), digits=3) + r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(BoilerToLoad / KWH_PER_MMBTU), digits=3) lifecycle_fuel_cost = p.pwf_fuel["Boiler"] * value( sum(m[:dvFuelUsage]["Boiler", ts] * p.fuel_cost_per_kwh["Boiler"][ts] for ts in p.time_steps) ) - r["lifecycle_fuel_cost"] = round(lifecycle_fuel_cost * (1 - p.s.financial.offtaker_tax_rate_fraction), digits=3) - r["year_one_fuel_cost"] = round(lifecycle_fuel_cost / p.pwf_fuel["Boiler"], digits=3) + r["lifecycle_fuel_cost_after_tax"] = round(lifecycle_fuel_cost * (1 - p.s.financial.offtaker_tax_rate_fraction), digits=3) + r["year_one_fuel_cost_before_tax"] = round(lifecycle_fuel_cost / p.pwf_fuel["Boiler"], digits=3) r["lifecycle_per_unit_prod_om_costs"] = round(value(m[:TotalBoilerPerUnitProdOMCosts]), digits=3) diff --git a/src/results/chp.jl b/src/results/chp.jl index dfb4b3618..b68cf9ad6 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -31,20 +31,20 @@ `CHP` results keys: - `size_kw` Power capacity size of the CHP system [kW] - `size_supplemental_firing_kw` Power capacity of CHP supplementary firing system [kW] -- `year_one_fuel_used_mmbtu` Fuel consumed in year one [MMBtu] -- `year_one_electric_energy_produced_kwh` Electric energy produced in year one [kWh] -- `year_one_thermal_energy_produced_mmbtu` Thermal energy produced in year one [MMBtu] -- `year_one_electric_production_series_kw` Electric power production time-series array [kW] -- `year_one_to_grid_series_kw` Electric power exported time-series array [kW] -- `year_one_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] -- `year_one_to_load_series_kw` Electric power to serve the electric load time-series array [kW] -- `year_one_thermal_to_tes_series_mmbtu_per_hour` Thermal power to TES time-series array [MMBtu/hr] +- `annual_fuel_consumption_mmbtu` Fuel consumed in year one [MMBtu] +- `annual_electric_production_kwh` Electric energy produced in year one [kWh] +- `annual_thermal_production_mmbtu` Thermal energy produced in year one [MMBtu] +- `electric_production_series_kw` Electric power production time-series array [kW] +- `electric_to_grid_series_kw` Electric power exported time-series array [kW] +- `electric_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] +- `electric_to_load_series_kw` Electric power to serve the electric load time-series array [kW] +- `thermal_to_tes_series_mmbtu_per_hour` Thermal power to TES time-series array [MMBtu/hr] - `year_one_thermal_to_waste_series_mmbtu_per_hour` Thermal power wasted/unused/vented time-series array [MMBtu/hr] -- `year_one_thermal_to_load_series_mmbtu_per_hour` Thermal power to serve the heating load time-series array [MMBtu/hr] -- `year_one_thermal_to_steamturbine_series_mmbtu_per_hour` Thermal (steam) power to steam turbine time-series array [MMBtu/hr] -- `year_one_chp_fuel_cost_before_tax` Cost of fuel consumed by the CHP system in year one [\$] +- `thermal_to_load_series_mmbtu_per_hour` Thermal power to serve the heating load time-series array [MMBtu/hr] +- `thermal_to_steamturbine_series_mmbtu_per_hour` Thermal (steam) power to steam turbine time-series array [MMBtu/hr] +- `year_one_fuel_cost_before_tax` Cost of fuel consumed by the CHP system in year one [\$] - `lifecycle_chp_fuel_cost_after_tax` Present value of cost of fuel consumed by the CHP system, after tax [\$] -- `year_one_chp_standby_cost_before_tax` CHP standby charges in year one [\$] +- `year_one_standby_cost_before_tax` CHP standby charges in year one [\$] - `lifecycle_chp_standby_cost_after_tax` Present value of all CHP standby charges, after tax. """ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") @@ -54,20 +54,20 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r["size_kw"] = value(sum(m[Symbol("dvSize"*_n)][t] for t in p.techs.chp)) r["size_supplemental_firing_kw"] = value(sum(m[Symbol("dvSupplementaryFiringSize"*_n)][t] for t in p.techs.chp)) @expression(m, CHPFuelUsedKWH, sum(m[Symbol("dvFuelUsage"*_n)][t, ts] for t in p.techs.chp, ts in p.time_steps)) - r["year_one_fuel_used_mmbtu"] = round(value(CHPFuelUsedKWH) / KWH_PER_MMBTU, digits=3) + r["annual_fuel_consumption_mmbtu"] = round(value(CHPFuelUsedKWH) / KWH_PER_MMBTU, digits=3) @expression(m, Year1CHPElecProd, p.hours_per_time_step * sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for t in p.techs.chp, ts in p.time_steps)) - r["year_one_electric_energy_produced_kwh"] = round(value(Year1CHPElecProd), digits=3) + r["annual_electric_production_kwh"] = round(value(Year1CHPElecProd), digits=3) @expression(m, Year1CHPThermalProdKWH, p.hours_per_time_step * sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] - m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp, ts in p.time_steps)) - r["year_one_thermal_energy_produced_mmbtu"] = round(value(Year1CHPThermalProdKWH) / KWH_PER_MMBTU, digits=3) + r["annual_thermal_production_mmbtu"] = round(value(Year1CHPThermalProdKWH) / KWH_PER_MMBTU, digits=3) @expression(m, CHPElecProdTotal[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for t in p.techs.chp)) - r["year_one_electric_production_series_kw"] = round.(value.(CHPElecProdTotal), digits=3) + r["electric_production_series_kw"] = round.(value.(CHPElecProdTotal), digits=3) # Electric dispatch breakdown if !isempty(p.s.electric_tariff.export_bins) @expression(m, CHPtoGrid[ts in p.time_steps], sum(m[Symbol("dvProductionToGrid"*_n)][t,u,ts] @@ -75,18 +75,18 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else CHPtoGrid = zeros(length(p.time_steps)) end - r["year_one_to_grid_series_kw"] = round.(value.(CHPtoGrid), digits=3) + r["electric_to_grid_series_kw"] = round.(value.(CHPtoGrid), digits=3) if !isempty(p.s.storage.types.elec) @expression(m, CHPtoBatt[ts in p.time_steps], sum(m[Symbol("dvProductionToStorage"*_n)]["ElectricStorage",t,ts] for t in p.techs.chp)) else CHPtoBatt = zeros(length(p.time_steps)) end - r["year_one_to_battery_series_kw"] = round.(value.(CHPtoBatt), digits=3) + r["electric_to_battery_series_kw"] = round.(value.(CHPtoBatt), digits=3) @expression(m, CHPtoLoad[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] for t in p.techs.chp) - CHPtoBatt[ts] - CHPtoGrid[ts]) - r["year_one_to_load_series_kw"] = round.(value.(CHPtoLoad), digits=3) + r["electric_to_load_series_kw"] = round.(value.(CHPtoLoad), digits=3) # Thermal dispatch breakdown if !isempty(p.s.storage.types.hot) @expression(m, CHPtoHotTES[ts in p.time_steps], @@ -94,7 +94,7 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else CHPtoHotTES = zeros(length(p.time_steps)) end - r["year_one_thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(CHPtoHotTES / KWH_PER_MMBTU), digits=5) + r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(CHPtoHotTES / KWH_PER_MMBTU), digits=5) @expression(m, CHPThermalToWasteKW[ts in p.time_steps], sum(m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) r["year_one_thermal_to_waste_series_mmbtu_per_hour"] = round.(value.(CHPThermalToWasteKW) / KWH_PER_MMBTU, digits=5) @@ -103,15 +103,15 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else CHPToSteamTurbineKW = zeros(length(p.time_steps)) end - r["year_one_thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(CHPToSteamTurbineKW) / KWH_PER_MMBTU, digits=5) + r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(CHPToSteamTurbineKW) / KWH_PER_MMBTU, digits=5) @expression(m, CHPThermalToLoadKW[ts in p.time_steps], sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] for t in p.techs.chp) - CHPtoHotTES[ts] - CHPToSteamTurbineKW[ts] - CHPThermalToWasteKW[ts]) - r["year_one_thermal_to_load_series_mmbtu_per_hour"] = round.(value.(CHPThermalToLoadKW) / KWH_PER_MMBTU, digits=5) - r["year_one_chp_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) + r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(CHPThermalToLoadKW) / KWH_PER_MMBTU, digits=5) + r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) r["lifecycle_chp_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) #Standby charges and hourly O&M - r["year_one_chp_standby_cost_before_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) / p.pwf_e, digits=0) + r["year_one_standby_cost_before_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) / p.pwf_e, digits=0) r["lifecycle_chp_standby_cost_after_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) * p.s.financial.offtaker_tax_rate_fraction, digits=0) diff --git a/src/results/electric_storage.jl b/src/results/electric_storage.jl index 8636f6bae..54f6011d2 100644 --- a/src/results/electric_storage.jl +++ b/src/results/electric_storage.jl @@ -31,10 +31,10 @@ `ElectricStorage` results keys: - `size_kw` Optimal inverter capacity - `size_kwh` Optimal storage capacity -- `year_one_soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year -- `year_one_to_load_series_kw` Vector of power used to meet load over the first year +- `soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year +- `storage_to_load_series_kw` Vector of power used to meet load over the first year - `initial_capital_cost` Upfront capital cost for storage and inverter -# The following results are reported if storage degradation is modeled +# The following results are reported if storage degradation is modeled: - `state_of_health` - `maintenance_cost` - `replacement_month` @@ -49,10 +49,10 @@ function add_electric_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d:: if r["size_kwh"] != 0 soc = (m[Symbol("dvStoredEnergy"*_n)][b, ts] for ts in p.time_steps) - r["year_one_soc_series_fraction"] = round.(value.(soc) ./ r["size_kwh"], digits=3) + r["soc_series_fraction"] = round.(value.(soc) ./ r["size_kwh"], digits=3) discharge = (m[Symbol("dvDischargeFromStorage"*_n)][b, ts] for ts in p.time_steps) - r["year_one_to_load_series_kw"] = round.(value.(discharge), digits=3) + r["storage_to_load_series_kw"] = round.(value.(discharge), digits=3) r["initial_capital_cost"] = r["size_kwh"] * p.s.storage.attr[b].installed_cost_per_kwh + r["size_kw"] * p.s.storage.attr[b].installed_cost_per_kw @@ -67,8 +67,8 @@ function add_electric_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d:: end end else - r["year_one_soc_series_fraction"] = [] - r["year_one_to_load_series_kw"] = [] + r["soc_series_fraction"] = [] + r["storage_to_load_series_kw"] = [] end d[b] = r diff --git a/src/results/electric_utility.jl b/src/results/electric_utility.jl index d0dcfa26e..f94d51685 100644 --- a/src/results/electric_utility.jl +++ b/src/results/electric_utility.jl @@ -29,19 +29,19 @@ # ********************************************************************************* """ `ElectricUtility` results keys: -- `year_one_energy_supplied_kwh` Total energy supplied from the grid in year one. -- `year_one_to_load_series_kw` Vector of power drawn from the grid to serve load in year one. -- `year_one_to_battery_series_kw` Vector of power drawn from the grid to charge the battery in year one. -- `year_one_emissions_tonnes_CO2` -- `year_one_emissions_tonnes_NOx` -- `year_one_emissions_tonnes_SO2` -- `year_one_emissions_tonnes_PM25` -- `lifecycle_emissions_tonnes_CO2` -- `lifecycle_emissions_tonnes_NOx` -- `lifecycle_emissions_tonnes_SO2` -- `lifecycle_emissions_tonnes_PM25` -- `emissions_region` -- `distance_to_emissions_region_meters` +- `annual_energy_supplied_kwh` Total energy supplied from the grid in year one. +- `production_to_load_series_kw` Vector of power drawn from the grid to serve load in year one. +- `production_to_battery_series_kw` Vector of power drawn from the grid to charge the battery in year one. +- `annual_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_emissions_tonnes_PM25` # Total tons of PM2.5 emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `lifecycle_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `lifecycle_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `lifecycle_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `lifecycle_emissions_tonnes_PM25` # Total tons of PM2.5 emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `emissions_region` # EPA AVERT region of the site (populated if default emissions values are used). +- `distance_to_emissions_region_meters` """ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, d::Dict; _n="") # Adds the `ElectricUtility` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -51,7 +51,7 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, Year1UtilityEnergy = p.hours_per_time_step * sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for ts in p.time_steps, tier in p.s.electric_tariff.n_energy_tiers) - r["year_one_energy_supplied_kwh"] = round(value(Year1UtilityEnergy), digits=2) + r["annual_energy_supplied_kwh"] = round(value(Year1UtilityEnergy), digits=2) if !isempty(p.s.storage.types.elec) GridToLoad = (sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in p.s.electric_tariff.n_energy_tiers) @@ -65,14 +65,14 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, GridToBatt = zeros(length(p.time_steps)) end - r["year_one_to_load_series_kw"] = round.(value.(GridToLoad), digits=3) - r["year_one_to_battery_series_kw"] = round.(value.(GridToBatt), digits=3) + r["production_to_load_series_kw"] = round.(value.(GridToLoad), digits=3) + r["production_to_battery_series_kw"] = round.(value.(GridToBatt), digits=3) if _n=="" #only output emissions results if not a multinode model - r["year_one_emissions_tonnes_CO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_CO2]*TONNE_PER_LB), digits=2) - r["year_one_emissions_tonnes_NOx"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_NOx]*TONNE_PER_LB), digits=2) - r["year_one_emissions_tonnes_SO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_SO2]*TONNE_PER_LB), digits=2) - r["year_one_emissions_tonnes_PM25"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_PM25]*TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_CO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_CO2]*TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_NOx"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_NOx]*TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_SO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_SO2]*TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_PM25"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_PM25]*TONNE_PER_LB), digits=2) r["lifecycle_emissions_tonnes_CO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_CO2]*TONNE_PER_LB*p.pwf_grid_emissions["CO2"]), digits=2) r["lifecycle_emissions_tonnes_NOx"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_NOx]*TONNE_PER_LB*p.pwf_grid_emissions["NOx"]), digits=2) r["lifecycle_emissions_tonnes_SO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_SO2]*TONNE_PER_LB*p.pwf_grid_emissions["SO2"]), digits=2) diff --git a/src/results/existing_boiler.jl b/src/results/existing_boiler.jl index eb0d221ad..2354692e2 100644 --- a/src/results/existing_boiler.jl +++ b/src/results/existing_boiler.jl @@ -29,26 +29,26 @@ # ********************************************************************************* """ `ExistingBoiler` results keys: -- `year_one_fuel_consumption_series_mmbtu_per_hour` -- `year_one_fuel_consumption_mmbtu` -- `year_one_thermal_production_series_mmbtu_per_hour` -- `year_one_thermal_production_mmbtu` -- `year_one_thermal_to_tes_series_mmbtu_per_hour` -- `year_one_thermal_to_steamturbine_series_mmbtu_per_hour` -- `year_one_thermal_to_load_series_mmbtu_per_hour` +- `fuel_consumption_series_mmbtu_per_hour` +- `annual_fuel_consumption_mmbtu` +- `thermal_production_series_mmbtu_per_hour` +- `annual_thermal_production_mmbtu` +- `thermal_to_tes_series_mmbtu_per_hour` +- `thermal_to_steamturbine_series_mmbtu_per_hour` +- `thermal_to_load_series_mmbtu_per_hour` - `lifecycle_fuel_cost_after_tax` - `year_one_fuel_cost_before_tax` """ function add_existing_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() - r["year_one_fuel_consumption_series_mmbtu_per_hour"] = + r["fuel_consumption_series_mmbtu_per_hour"] = round.(value.(m[:dvFuelUsage]["ExistingBoiler", ts] for ts in p.time_steps) ./ KWH_PER_MMBTU, digits=5) - r["year_one_fuel_consumption_mmbtu"] = round(sum(r["year_one_fuel_consumption_series_mmbtu_per_hour"]), digits=5) + r["annual_fuel_consumption_mmbtu"] = round(sum(r["fuel_consumption_series_mmbtu_per_hour"]), digits=5) - r["year_one_thermal_production_series_mmbtu_per_hour"] = + r["thermal_production_series_mmbtu_per_hour"] = round.(value.(m[:dvThermalProduction]["ExistingBoiler", ts] for ts in p.time_steps) ./ KWH_PER_MMBTU, digits=5) - r["year_one_thermal_production_mmbtu"] = round(sum(r["year_one_thermal_production_series_mmbtu_per_hour"]), digits=5) + r["annual_thermal_production_mmbtu"] = round(sum(r["thermal_production_series_mmbtu_per_hour"]), digits=5) if !isempty(p.s.storage.types.hot) @expression(m, BoilerToHotTESKW[ts in p.time_steps], @@ -57,20 +57,20 @@ function add_existing_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::D else BoilerToHotTESKW = zeros(length(p.time_steps)) end - r["year_one_thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) + r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) if !isempty(p.techs.steam_turbine) && p.s.existing_boiler.can_supply_steam_turbine @expression(m, BoilerToSteamTurbineKW[ts in p.time_steps], m[:dvThermalToSteamTurbine]["ExistingBoiler",ts]) else @expression(m, BoilerToSteamTurbineKW[ts in p.time_steps], 0.0) end - r["year_one_thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(BoilerToSteamTurbineKW) ./ KWH_PER_MMBTU, digits=5) + r["thermal_to_steamturbine_series_mmbtu_per_hour"] = round.(value.(BoilerToSteamTurbineKW) ./ KWH_PER_MMBTU, digits=5) BoilerToLoadKW = @expression(m, [ts in p.time_steps], m[:dvThermalProduction]["ExistingBoiler",ts] - BoilerToHotTESKW[ts] - BoilerToSteamTurbineKW[ts] ) - r["year_one_thermal_to_load_series_mmbtu_per_hour"] = round.(value.(BoilerToLoadKW ./ KWH_PER_MMBTU), digits=5) + r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(BoilerToLoadKW ./ KWH_PER_MMBTU), digits=5) m[:TotalExistingBoilerFuelCosts] = @expression(m, p.pwf_fuel["ExistingBoiler"] * sum(m[:dvFuelUsage]["ExistingBoiler", ts] * p.fuel_cost_per_kwh["ExistingBoiler"][ts] for ts in p.time_steps) diff --git a/src/results/existing_chiller.jl b/src/results/existing_chiller.jl index 2b2e5d5ab..bdf1c5570 100644 --- a/src/results/existing_chiller.jl +++ b/src/results/existing_chiller.jl @@ -29,11 +29,11 @@ # ********************************************************************************* """ `ExistingChiller` results keys: -- `year_one_to_tes_series_ton` -- `year_one_to_load_series_ton` +- `production_to_tes_series_ton` +- `production_to_load_series_ton` - `year_one_electric_consumption_series` -- `year_one_electric_consumption_kwh` -- `year_one_thermal_production_tonhour` +- `annual_electric_consumption_kwh` +- `annual_thermal_production_tonhour` """ function add_existing_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() @@ -41,30 +41,30 @@ function add_existing_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d:: @expression(m, ELECCHLtoTES[ts in p.time_steps], sum(m[:dvProductionToStorage][b,"ExistingChiller",ts] for b in p.s.storage.types.cold) ) - r["year_one_to_tes_series_ton"] = round.(value.(ELECCHLtoTES / KWH_THERMAL_PER_TONHOUR), digits=3) + r["production_to_tes_series_ton"] = round.(value.(ELECCHLtoTES / KWH_THERMAL_PER_TONHOUR), digits=3) @expression(m, ELECCHLtoLoad[ts in p.time_steps], sum(m[:dvThermalProduction]["ExistingChiller", ts]) - ELECCHLtoTES[ts] ) - r["year_one_to_load_series_ton"] = round.(value.(ELECCHLtoLoad / KWH_THERMAL_PER_TONHOUR).data, digits=3) + r["production_to_load_series_ton"] = round.(value.(ELECCHLtoLoad / KWH_THERMAL_PER_TONHOUR).data, digits=3) @expression(m, ELECCHLElecConsumptionSeries[ts in p.time_steps], sum(m[:dvThermalProduction]["ExistingChiller", ts] / p.cop["ExistingChiller"]) ) - r["year_one_electric_consumption_series_kw"] = round.(value.(ELECCHLElecConsumptionSeries).data, digits=3) + r["electric_consumption_series_kw"] = round.(value.(ELECCHLElecConsumptionSeries).data, digits=3) @expression(m, Year1ELECCHLElecConsumption, p.hours_per_time_step * sum(m[:dvThermalProduction]["ExistingChiller", ts] / p.cop["ExistingChiller"] for ts in p.time_steps) ) - r["year_one_electric_consumption_kwh"] = round(value(Year1ELECCHLElecConsumption), digits=3) + r["annual_electric_consumption_kwh"] = round(value(Year1ELECCHLElecConsumption), digits=3) @expression(m, Year1ELECCHLThermalProd, p.hours_per_time_step * sum(m[:dvThermalProduction]["ExistingChiller", ts] for ts in p.time_steps) ) - r["year_one_thermal_production_tonhour"] = round(value(Year1ELECCHLThermalProd / KWH_THERMAL_PER_TONHOUR), digits=3) + r["annual_thermal_production_tonhour"] = round(value(Year1ELECCHLThermalProd / KWH_THERMAL_PER_TONHOUR), digits=3) d["ExistingChiller"] = r nothing diff --git a/src/results/generator.jl b/src/results/generator.jl index a8747e0a0..d817629fb 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -31,17 +31,17 @@ `Generator` results keys: - `size_kw` Optimal generator capacity - `lifecycle_fixed_om_cost_after_tax` Lifecycle fixed operations and maintenance cost in present value, after tax -- `year_one_fixed_om_cost__before_tax` fixed operations and maintenance cost over the first year, before considering tax benefits +- `year_one_fixed_om_cost_before_tax` fixed operations and maintenance cost over the first year, before considering tax benefits - `lifecycle_variable_om_cost_after_tax` Lifecycle variable operations and maintenance cost in present value, after tax - `year_one_variable_om_cost_before_tax` variable operations and maintenance cost over the first year, before considering tax benefits - `lifecycle_fuel_cost_after_tax` Lifecycle fuel cost in present value, after tax - `year_one_fuel_cost_before_tax` Fuel cost over the first year, before considering tax benefits -- `average_annual_fuel_used_gal` Gallons of fuel used in each year -- `year_one_to_battery_series_kw` Vector of power sent to battery in year one -- `year_one_to_grid_series_kw` Vector of power sent to grid in year one -- `year_one_to_load_series_kw` Vector of power sent to load in year one +- `annual_fuel_consumption_gal` Gallons of fuel used in each year +- `production_to_battery_series_kw` Vector of power sent to battery in year one +- `production_to_grid_series_kw` Vector of power sent to grid in year one +- `production_to_load_series_kw` Vector of power sent to load in year one - `year_one_energy_produced_kwh` Total energy produced in year one -- `average_annual_energy_produced_kwh` Average annual energy produced over analysis period +- `annual_energy_produced_kwh` Average annual energy produced over analysis period """ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `Generator` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -69,22 +69,22 @@ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ else generatorToBatt = zeros(length(p.time_steps)) end - r["year_one_to_battery_series_kw"] = round.(value.(generatorToBatt), digits=3) + r["production_to_battery_series_kw"] = round.(value.(generatorToBatt), digits=3) generatorToGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for t in p.techs.gen, u in p.export_bins_by_tech[t]) ) - r["year_one_to_grid_series_kw"] = round.(value.(generatorToGrid), digits=3) + r["production_to_grid_series_kw"] = round.(value.(generatorToGrid), digits=3) generatorToLoad = @expression(m, [ts in p.time_steps], sum(m[:dvRatedProduction][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] for t in p.techs.gen) - generatorToBatt[ts] - generatorToGrid[ts] ) - r["year_one_to_load_series_kw"] = round.(value.(generatorToLoad), digits=3) + r["production_to_load_series_kw"] = round.(value.(generatorToLoad), digits=3) GeneratorFuelUsed = @expression(m, sum(m[:dvFuelUsage][t, ts] for t in p.techs.gen, ts in p.time_steps) / KWH_PER_GAL_DIESEL) - r["average_annual_fuel_used_gal"] = round(value(GeneratorFuelUsed), digits=2) + r["annual_fuel_consumption_gal"] = round(value(GeneratorFuelUsed), digits=2) Year1GenProd = @expression(m, p.hours_per_time_step * sum(m[:dvRatedProduction][t,ts] * p.production_factor[t, ts] @@ -96,7 +96,7 @@ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ p.levelization_factor[t] for t in p.techs.gen, ts in p.time_steps) ) - r["average_annual_energy_produced_kwh"] = round(value(AverageGenProd), digits=0) + r["annual_energy_produced_kwh"] = round(value(AverageGenProd), digits=0) d["Generator"] = r nothing @@ -109,7 +109,7 @@ MPC `Generator` results keys: - `to_battery_series_kw` - `to_grid_series_kw` - `to_load_series_kw` -- `average_annual_fuel_used_gal` +- `annual_fuel_consumption_gal` - `energy_produced_kwh` """ function add_generator_results(m::JuMP.AbstractModel, p::MPCInputs, d::Dict; _n="") @@ -139,7 +139,7 @@ function add_generator_results(m::JuMP.AbstractModel, p::MPCInputs, d::Dict; _n= r["to_load_series_kw"] = round.(value.(generatorToLoad), digits=3).data GeneratorFuelUsed = @expression(m, sum(m[:dvFuelUsage][t, ts] for t in p.techs.gen, ts in p.time_steps) / KWH_PER_GAL_DIESEL) - r["average_annual_fuel_used_gal"] = round(value(GeneratorFuelUsed), digits=2) + r["annual_fuel_consumption_gal"] = round(value(GeneratorFuelUsed), digits=2) Year1GenProd = @expression(m, p.hours_per_time_step * sum(m[:dvRatedProduction][t,ts] * p.production_factor[t, ts] diff --git a/src/results/pv.jl b/src/results/pv.jl index c0e6d3e2c..63c80ea15 100644 --- a/src/results/pv.jl +++ b/src/results/pv.jl @@ -32,17 +32,20 @@ - `size_kw` Optimal PV capacity - `lifecycle_om_cost_after_tax` Lifecycle operations and maintenance cost in present value, after tax - `year_one_energy_produced_kwh` Energy produced over the first year -- `average_annual_energy_produced_kwh` Average annual energy produced when accounting for degradation +- `annual_energy_produced_kwh` Average annual energy produced when accounting for degradation - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system -- `year_one_to_load_series_kw` Vector of power used to meet load over the first year -- `year_one_to_battery_series_kw` Vector of power used to charge the battery over the first year -- `year_one_to_grid_series_kw` Vector of power exported to the grid over the first year -- `year_one_curtailed_production_series_kw` Vector of power curtailed over the first year -- `average_annual_energy_exported_kwh` Average annual energy exported to the grid +- `production_to_load_series_kw` Vector of power used to meet load over the first year +- `production_to_battery_series_kw` Vector of power used to charge the battery over the first year +- `production_to_grid_series_kw` Vector of power exported to the grid over the first year +- `production_curtailed_series_kw` Vector of power curtailed over the first year +- `annual_energy_exported_kwh` Average annual energy exported to the grid !!! warn The key(s) used to access PV outputs in the results dictionary is determined by the `PV.name` value to allow for modeling multiple PV options. (The default `PV.name` is "PV".) +!!! note "Existing PV" + All outputs account for any existing PV. E.g., `size_kw` includes existing capacity and the REopt-recommended additional capacity. + """ function add_pv_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `PV` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -58,30 +61,30 @@ function add_pv_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else PVtoBatt = repeat([0], length(p.time_steps)) end - r["year_one_to_battery_series_kw"] = round.(value.(PVtoBatt), digits=3) + r["production_to_battery_series_kw"] = round.(value.(PVtoBatt), digits=3) - r["year_one_to_grid_series_kw"] = zeros(size(r["year_one_to_battery_series_kw"])) - r["average_annual_energy_exported_kwh"] = 0.0 + r["production_to_grid_series_kw"] = zeros(size(r["production_to_battery_series_kw"])) + r["annual_energy_exported_kwh"] = 0.0 if !isempty(p.s.electric_tariff.export_bins) PVtoGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for u in p.export_bins_by_tech[t])) - r["year_one_to_grid_series_kw"] = round.(value.(PVtoGrid), digits=3).data + r["production_to_grid_series_kw"] = round.(value.(PVtoGrid), digits=3).data - r["average_annual_energy_exported_kwh"] = round( - sum(r["year_one_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) + r["annual_energy_exported_kwh"] = round( + sum(r["production_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) end PVtoCUR = (m[Symbol("dvCurtail"*_n)][t, ts] for ts in p.time_steps) - r["year_one_curtailed_production_series_kw"] = round.(value.(PVtoCUR), digits=3) + r["production_curtailed_series_kw"] = round.(value.(PVtoCUR), digits=3) PVtoLoad = (m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] - - r["year_one_curtailed_production_series_kw"][ts] - - r["year_one_to_grid_series_kw"][ts] - - r["year_one_to_battery_series_kw"][ts] for ts in p.time_steps + - r["production_curtailed_series_kw"][ts] + - r["production_to_grid_series_kw"][ts] + - r["production_to_battery_series_kw"][ts] for ts in p.time_steps ) - r["year_one_to_load_series_kw"] = round.(value.(PVtoLoad), digits=3) + r["production_to_load_series_kw"] = round.(value.(PVtoLoad), digits=3) Year1PvProd = (sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for ts in p.time_steps) * p.hours_per_time_step) r["year_one_energy_produced_kwh"] = round(value(Year1PvProd), digits=0) - r["average_annual_energy_produced_kwh"] = round(r["year_one_energy_produced_kwh"] * p.levelization_factor[t], digits=2) + r["annual_energy_produced_kwh"] = round(r["year_one_energy_produced_kwh"] * p.levelization_factor[t], digits=2) PVPerUnitSizeOMCosts = p.om_cost_per_kw[t] * p.pwf_om * m[Symbol("dvSize"*_n)][t] r["lifecycle_om_cost_after_tax"] = round(value(PVPerUnitSizeOMCosts) * (1 - p.s.financial.owner_tax_rate_fraction), digits=0) r["lcoe_per_kwh"] = calculate_lcoe(p, r, get_pv_by_name(t, p.s.pvs)) diff --git a/src/results/results.jl b/src/results/results.jl index 321188490..3ddbebe9a 100644 --- a/src/results/results.jl +++ b/src/results/results.jl @@ -155,20 +155,20 @@ function combine_results(p::REoptInputs, bau::Dict, opt::Dict, bau_scenario::BAU ("ElectricTariff", "year_one_export_benefit_before_tax"), ("ElectricTariff", "year_one_coincident_peak_cost_before_tax"), ("ElectricTariff", "lifecycle_coincident_peak_cost_after_tax"), - ("ElectricUtility", "year_one_to_load_series_kw"), - ("ElectricUtility", "year_one_energy_supplied_kwh"), - ("ElectricUtility", "year_one_emissions_tonnes_CO2"), - ("ElectricUtility", "year_one_emissions_tonnes_NOx"), - ("ElectricUtility", "year_one_emissions_tonnes_NOx"), - ("ElectricUtility", "year_one_emissions_tonnes_PM25"), + ("ElectricUtility", "production_to_load_series_kw"), + ("ElectricUtility", "annual_energy_supplied_kwh"), + ("ElectricUtility", "annual_emissions_tonnes_CO2"), + ("ElectricUtility", "annual_emissions_tonnes_NOx"), + ("ElectricUtility", "annual_emissions_tonnes_NOx"), + ("ElectricUtility", "annual_emissions_tonnes_PM25"), ("ElectricUtility", "lifecycle_emissions_tonnes_CO2"), ("ElectricUtility", "lifecycle_emissions_tonnes_NOx"), ("ElectricUtility", "lifecycle_emissions_tonnes_SO2"), ("ElectricUtility", "lifecycle_emissions_tonnes_PM25"), - ("PV", "average_annual_energy_produced_kwh"), + ("PV", "annual_energy_produced_kwh"), ("PV", "year_one_energy_produced_kwh"), ("PV", "lifecycle_om_cost_after_tax"), - ("Generator", "average_annual_fuel_used_gal"), + ("Generator", "annual_fuel_consumption_gal"), ("Generator", "lifecycle_fixed_om_cost_after_tax"), ("Generator", "lifecycle_variable_om_cost_after_tax"), ("Generator", "lifecycle_fuel_cost_after_tax"), @@ -180,14 +180,14 @@ function combine_results(p::REoptInputs, bau::Dict, opt::Dict, bau_scenario::BAU ("Site", "annual_renewable_electricity_kwh"), ("Site", "renewable_electricity_fraction"), ("Site", "total_renewable_energy_fraction"), - ("Site", "year_one_emissions_tonnes_CO2"), - ("Site", "year_one_emissions_tonnes_NOx"), - ("Site", "year_one_emissions_tonnes_SO2"), - ("Site", "year_one_emissions_tonnes_PM25"), - ("Site", "year_one_emissions_from_fuelburn_tonnes_CO2"), - ("Site", "year_one_emissions_from_fuelburn_tonnes_NOx"), - ("Site", "year_one_emissions_from_fuelburn_tonnes_SO2"), - ("Site", "year_one_emissions_from_fuelburn_tonnes_PM25"), + ("Site", "annual_emissions_tonnes_CO2"), + ("Site", "annual_emissions_tonnes_NOx"), + ("Site", "annual_emissions_tonnes_SO2"), + ("Site", "annual_emissions_tonnes_PM25"), + ("Site", "annual_emissions_from_fuelburn_tonnes_CO2"), + ("Site", "annual_emissions_from_fuelburn_tonnes_NOx"), + ("Site", "annual_emissions_from_fuelburn_tonnes_SO2"), + ("Site", "annual_emissions_from_fuelburn_tonnes_PM25"), ("Site", "year_one_emissions_from_elec_grid_tonnes_CO2"), ("Site", "year_one_emissions_from_elec_grid_tonnes_NOx"), ("Site", "year_one_emissions_from_elec_grid_tonnes_SO2"), @@ -242,9 +242,9 @@ function combine_results(p::REoptInputs, bau::Dict, opt::Dict, bau_scenario::BAU # (back-calculating using the equation for m[:Lifecycle_Emissions_Cost_CO2] in "add_lifecycle_emissions_calcs" in emissions_constraints.jl) if npv_without_modeled_climate_costs < 0 # if the system is not cost effective (NPV < 0) without considering any cost of CO2 breakeven_cost_denominator = p.pwf_emissions_cost["CO2_grid"] * ( - bau["ElectricUtility"]["year_one_emissions_tonnes_CO2"] - opt["ElectricUtility"]["year_one_emissions_tonnes_CO2"] + bau["ElectricUtility"]["annual_emissions_tonnes_CO2"] - opt["ElectricUtility"]["annual_emissions_tonnes_CO2"] ) + p.pwf_emissions_cost["CO2_onsite"] * ( - bau["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2"] - opt["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2"] + bau["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] - opt["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] ) if breakeven_cost_denominator != 0.0 opt["Financial"]["breakeven_cost_of_emissions_reduction_per_tonnes_CO2"] = -1 * npv_without_modeled_climate_costs / breakeven_cost_denominator diff --git a/src/results/site.jl b/src/results/site.jl index b76eeaf21..5efa815f9 100644 --- a/src/results/site.jl +++ b/src/results/site.jl @@ -36,14 +36,14 @@ Site results: - `annual_renewable_electricity_kwh` - `renewable_electricity_fraction` - `total_renewable_energy_fraction` -- `year_one_emissions_tonnes_CO2` -- `year_one_emissions_tonnes_NOx` -- `year_one_emissions_tonnes_SO2` -- `year_one_emissions_tonnes_PM25` -- `year_one_emissions_from_fuelburn_tonnes_CO2` -- `year_one_emissions_from_fuelburn_tonnes_NOx` -- `year_one_emissions_from_fuelburn_tonnes_SO2` -- `year_one_emissions_from_fuelburn_tonnes_PM25` +- `annual_emissions_tonnes_CO2` +- `annual_emissions_tonnes_NOx` +- `annual_emissions_tonnes_SO2` +- `annual_emissions_tonnes_PM25` +- `annual_emissions_from_fuelburn_tonnes_CO2` +- `annual_emissions_from_fuelburn_tonnes_NOx` +- `annual_emissions_from_fuelburn_tonnes_SO2` +- `annual_emissions_from_fuelburn_tonnes_PM25` - `lifecycle_emissions_tonnes_CO2` - `lifecycle_emissions_tonnes_NOx` - `lifecycle_emissions_tonnes_SO2` @@ -69,15 +69,15 @@ function add_site_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r["total_renewable_energy_fraction"] = round(value(m[:AnnualRETotkWh])/value(m[:AnnualTotkWh]), digits=6) # Year 1 Emissions results at Site level - r["year_one_emissions_tonnes_CO2"] = round(value(m[:EmissionsYr1_Total_LbsCO2] * TONNE_PER_LB), digits=2) - r["year_one_emissions_tonnes_NOx"] = round(value(m[:EmissionsYr1_Total_LbsNOx] * TONNE_PER_LB), digits=2) - r["year_one_emissions_tonnes_SO2"] = round(value(m[:EmissionsYr1_Total_LbsSO2] * TONNE_PER_LB), digits=2) - r["year_one_emissions_tonnes_PM25"] = round(value(m[:EmissionsYr1_Total_LbsPM25] * TONNE_PER_LB), digits=2) - - r["year_one_emissions_from_fuelburn_tonnes_CO2"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_CO2] * TONNE_PER_LB), digits=2) - r["year_one_emissions_from_fuelburn_tonnes_NOx"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_NOx] * TONNE_PER_LB), digits=2) - r["year_one_emissions_from_fuelburn_tonnes_SO2"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_SO2] * TONNE_PER_LB), digits=2) - r["year_one_emissions_from_fuelburn_tonnes_PM25"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_PM25] * TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_CO2"] = round(value(m[:EmissionsYr1_Total_LbsCO2] * TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_NOx"] = round(value(m[:EmissionsYr1_Total_LbsNOx] * TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_SO2"] = round(value(m[:EmissionsYr1_Total_LbsSO2] * TONNE_PER_LB), digits=2) + r["annual_emissions_tonnes_PM25"] = round(value(m[:EmissionsYr1_Total_LbsPM25] * TONNE_PER_LB), digits=2) + + r["annual_emissions_from_fuelburn_tonnes_CO2"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_CO2] * TONNE_PER_LB), digits=2) + r["annual_emissions_from_fuelburn_tonnes_NOx"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_NOx] * TONNE_PER_LB), digits=2) + r["annual_emissions_from_fuelburn_tonnes_SO2"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_SO2] * TONNE_PER_LB), digits=2) + r["annual_emissions_from_fuelburn_tonnes_PM25"] = round(value(m[:yr1_emissions_onsite_fuel_lbs_PM25] * TONNE_PER_LB), digits=2) # Lifecycle emissions results at Site level if !isnothing(p.s.site.bau_emissions_lb_CO2_per_year) diff --git a/src/results/steam_turbine.jl b/src/results/steam_turbine.jl index 2b8fb2965..5ad527f62 100644 --- a/src/results/steam_turbine.jl +++ b/src/results/steam_turbine.jl @@ -30,16 +30,16 @@ """ `SteamTurbine` results keys: - `size_kw` Power capacity size [kW] -- `year_one_thermal_consumption_mmbtu` Thermal (steam) consumption [MMBtu] -- `year_one_electric_energy_produced_kwh` Electric energy produced in a year [kWh] -- `year_one_thermal_energy_produced_mmbtu` Thermal energy produced in a year [MMBtu] -- `year_one_thermal_consumption_series_mmbtu_per_hour` Thermal (steam) energy consumption series [MMBtu/hr] -- `year_one_electric_production_series_kw` Electric power production series [kW] -- `year_one_electric_to_grid_series_kw` Electric power exported to grid series [kW] -- `year_one_electric_to_battery_series_kw` Electric power to charge the battery series [kW] -- `year_one_electric_to_load_series_kw` Electric power to serve load series [kW] -- `year_one_thermal_to_tes_series_mmbtu_per_hour` Thermal production to charge the HotThermalStorage series [MMBtu/hr] -- `year_one_thermal_to_load_series_mmbtu_per_hour` Thermal production to serve the heating load SERVICES [MMBtu/hr] +- `annual_thermal_consumption_mmbtu` Thermal (steam) consumption [MMBtu] +- `annual_electric_production_kwh` Electric energy produced in a year [kWh] +- `annual_thermal_production_mmbtu` Thermal energy produced in a year [MMBtu] +- `thermal_consumption_series_mmbtu_per_hour` Thermal (steam) energy consumption series [MMBtu/hr] +- `electric_production_series_kw` Electric power production series [kW] +- `electric_to_grid_series_kw` Electric power exported to grid series [kW] +- `electric_to_battery_series_kw` Electric power to charge the battery series [kW] +- `electric_to_load_series_kw` Electric power to serve load series [kW] +- `thermal_to_tes_series_mmbtu_per_hour` Thermal production to charge the HotThermalStorage series [MMBtu/hr] +- `thermal_to_load_series_mmbtu_per_hour` Thermal production to serve the heating load SERVICES [MMBtu/hr] """ function add_steam_turbine_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") @@ -51,48 +51,48 @@ function add_steam_turbine_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dic r["size_kw"] = round(value(sum(m[Symbol("dvSize"*_n)][t] for t in p.techs.steam_turbine)), digits=3) @expression(m, Year1SteamTurbineThermalConsumptionKWH, p.hours_per_time_step * sum(m[Symbol("dvThermalToSteamTurbine"*_n)][tst,ts] for tst in p.techs.can_supply_steam_turbine, ts in p.time_steps)) - r["year_one_thermal_consumption_mmbtu"] = round(value(Year1SteamTurbineThermalConsumptionKWH) / KWH_PER_MMBTU, digits=5) + r["annual_thermal_consumption_mmbtu"] = round(value(Year1SteamTurbineThermalConsumptionKWH) / KWH_PER_MMBTU, digits=5) @expression(m, Year1SteamTurbineElecProd, p.hours_per_time_step * sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for t in p.techs.steam_turbine, ts in p.time_steps)) - r["year_one_electric_energy_produced_kwh"] = round(value(Year1SteamTurbineElecProd), digits=3) + r["annual_electric_production_kwh"] = round(value(Year1SteamTurbineElecProd), digits=3) @expression(m, Year1SteamTurbineThermalProdKWH, p.hours_per_time_step * sum(m[Symbol("dvThermalProduction"*_n)][t,ts] for t in p.techs.steam_turbine, ts in p.time_steps)) - r["year_one_thermal_energy_produced_mmbtu"] = round(value(Year1SteamTurbineThermalProdKWH) / KWH_PER_MMBTU, digits=5) + r["annual_thermal_production_mmbtu"] = round(value(Year1SteamTurbineThermalProdKWH) / KWH_PER_MMBTU, digits=5) @expression(m, SteamTurbineThermalConsumptionKW[ts in p.time_steps], sum(m[Symbol("dvThermalToSteamTurbine"*_n)][tst,ts] for tst in p.techs.can_supply_steam_turbine)) - r["year_one_thermal_consumption_series_mmbtu_per_hour"] = round.(value.(SteamTurbineThermalConsumptionKW) ./ KWH_PER_MMBTU, digits=5) + r["thermal_consumption_series_mmbtu_per_hour"] = round.(value.(SteamTurbineThermalConsumptionKW) ./ KWH_PER_MMBTU, digits=5) @expression(m, SteamTurbineElecProdTotal[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for t in p.techs.steam_turbine)) - r["year_one_electric_production_series_kw"] = round.(value.(SteamTurbineElecProdTotal), digits=3) + r["electric_production_series_kw"] = round.(value.(SteamTurbineElecProdTotal), digits=3) if !isempty(p.s.electric_tariff.export_bins) @expression(m, SteamTurbinetoGrid[ts in p.time_steps], sum(m[Symbol("dvProductionToGrid"*_n)][t, u, ts] for t in p.techs.steam_turbine, u in p.export_bins_by_tech[t])) else SteamTurbinetoGrid = zeros(length(p.time_steps)) end - r["year_one_electric_to_grid_series_kw"] = round.(value.(SteamTurbinetoGrid), digits=3) + r["electric_to_grid_series_kw"] = round.(value.(SteamTurbinetoGrid), digits=3) if !isempty(p.s.storage.types.elec) @expression(m, SteamTurbinetoBatt[ts in p.time_steps], sum(m[Symbol("dvProductionToStorage"*_n)]["ElectricStorage",t,ts] for t in p.techs.steam_turbine)) else SteamTurbinetoBatt = zeros(length(p.time_steps)) end - r["year_one_electric_to_battery_series_kw"] = round.(value.(SteamTurbinetoBatt), digits=3) + r["electric_to_battery_series_kw"] = round.(value.(SteamTurbinetoBatt), digits=3) @expression(m, SteamTurbinetoLoad[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] for t in p.techs.steam_turbine) - SteamTurbinetoBatt[ts] - SteamTurbinetoGrid[ts]) - r["year_one_electric_to_load_series_kw"] = round.(value.(SteamTurbinetoLoad), digits=3) + r["electric_to_load_series_kw"] = round.(value.(SteamTurbinetoLoad), digits=3) if !isempty(p.s.storage.types.hot) @expression(m, SteamTurbinetoHotTESKW[ts in p.time_steps], sum(m[Symbol("dvProductionToStorage"*_n)]["HotThermalStorage",t,ts] for t in p.techs.steam_turbine)) else SteamTurbinetoHotTESKW = zeros(length(p.time_steps)) end - r["year_one_thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(SteamTurbinetoHotTESKW) ./ KWH_PER_MMBTU, digits=5) + r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(SteamTurbinetoHotTESKW) ./ KWH_PER_MMBTU, digits=5) @expression(m, SteamTurbineThermalToLoadKW[ts in p.time_steps], sum(m[Symbol("dvThermalProduction"*_n)][t,ts] for t in p.techs.steam_turbine) - SteamTurbinetoHotTESKW[ts]) - r["year_one_thermal_to_load_series_mmbtu_per_hour"] = round.(value.(SteamTurbineThermalToLoadKW) ./ KWH_PER_MMBTU, digits=5) + r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(SteamTurbineThermalToLoadKW) ./ KWH_PER_MMBTU, digits=5) d["SteamTurbine"] = r nothing end \ No newline at end of file diff --git a/src/results/thermal_storage.jl b/src/results/thermal_storage.jl index 775c91ced..fbe82dba6 100644 --- a/src/results/thermal_storage.jl +++ b/src/results/thermal_storage.jl @@ -30,8 +30,8 @@ """ `HotThermalStorage` results keys: - `size_gal` Optimal TES capacity, by volume [gal] -- `year_one_soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year [-] -- `year_one_to_load_series_mmbtu_per_hour` Vector of power used to meet load over the first year [MMBTU/hr] +- `soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year [-] +- `storage_to_load_series_mmbtu_per_hour` Vector of power used to meet load over the first year [MMBTU/hr] """ function add_hot_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict, b::String; _n="") # Adds the `HotThermalStorage` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -48,13 +48,13 @@ function add_hot_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict, if size_kwh != 0 soc = (m[Symbol("dvStoredEnergy"*_n)][b, ts] for ts in p.time_steps) - r["year_one_soc_series_fraction"] = round.(value.(soc) ./ size_kwh, digits=3) + r["soc_series_fraction"] = round.(value.(soc) ./ size_kwh, digits=3) discharge = (m[Symbol("dvDischargeFromStorage"*_n)][b, ts] for ts in p.time_steps) - r["year_one_to_load_series_mmbtu_per_hour"] = round.(value.(discharge) / KWH_PER_MMBTU, digits=7) + r["storage_to_load_series_mmbtu_per_hour"] = round.(value.(discharge) / KWH_PER_MMBTU, digits=7) else - r["year_one_soc_series_fraction"] = [] - r["year_one_to_load_series_mmbtu_per_hour"] = [] + r["soc_series_fraction"] = [] + r["storage_to_load_series_mmbtu_per_hour"] = [] end d[b] = r @@ -82,8 +82,8 @@ end """ `ColdThermalStorage` results: - `size_gal` Optimal TES capacity, by volume [gal] -- `year_one_soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year [-] -- `year_one_to_load_series_ton` Vector of power used to meet load over the first year [ton] +- `soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year [-] +- `production_to_load_series_ton` Vector of power used to meet load over the first year [ton] """ function add_cold_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict, b::String; _n="") #= @@ -102,13 +102,13 @@ function add_cold_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict if size_kwh != 0 soc = (m[Symbol("dvStoredEnergy"*_n)][b, ts] for ts in p.time_steps) - r["year_one_soc_series_fraction"] = round.(value.(soc) ./ size_kwh, digits=3) + r["soc_series_fraction"] = round.(value.(soc) ./ size_kwh, digits=3) discharge = (m[Symbol("dvDischargeFromStorage"*_n)][b, ts] for ts in p.time_steps) - r["year_one_to_load_series_ton"] = round.(value.(discharge) / KWH_THERMAL_PER_TONHOUR, digits=7) + r["production_to_load_series_ton"] = round.(value.(discharge) / KWH_THERMAL_PER_TONHOUR, digits=7) else - r["year_one_soc_series_fraction"] = [] - r["year_one_to_load_series_ton"] = [] + r["soc_series_fraction"] = [] + r["production_to_load_series_ton"] = [] end d[b] = r diff --git a/src/results/wind.jl b/src/results/wind.jl index c28c3bc75..4e90b18b7 100644 --- a/src/results/wind.jl +++ b/src/results/wind.jl @@ -32,14 +32,14 @@ - `size_kw` Optimal Wind capacity - `lifecycle_om_cost_after_tax` Lifecycle operations and maintenance cost in present value, after tax - `year_one_om_cost_before_tax` Operations and maintenance cost in the first year, before tax benefits -- `year_one_to_battery_series_kw` Vector of power used to charge the battery over the first year -- `year_one_to_grid_series_kw` Vector of power exported to the grid over the first year -- `average_annual_energy_exported_kwh` Average annual energy exported to the grid -- `year_one_to_load_series_kw` Vector of power used to meet load over the first year +- `production_to_battery_series_kw` Vector of power used to charge the battery over the first year +- `production_to_grid_series_kw` Vector of power exported to the grid over the first year +- `annual_energy_exported_kwh` Average annual energy exported to the grid +- `production_to_load_series_kw` Vector of power used to meet load over the first year - `year_one_energy_produced_kwh` Energy produced over the first year -- `average_annual_energy_produced_kwh` Average annual energy produced when accounting for degradation +- `annual_energy_produced_kwh` Average annual energy produced when accounting for degradation - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system -- `year_one_curtailed_production_series_kw` Vector of power curtailed over the first year +- `production_curtailed_series_kw` Vector of power curtailed over the first year """ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `Wind` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -59,35 +59,35 @@ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else WindToStorage = zeros(length(p.time_steps)) end - r["year_one_to_battery_series_kw"] = round.(value.(WindToStorage), digits=3) + r["production_to_battery_series_kw"] = round.(value.(WindToStorage), digits=3) - r["average_annual_energy_exported_kwh"] = 0.0 + r["annual_energy_exported_kwh"] = 0.0 if !isempty(p.s.electric_tariff.export_bins) WindToGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for u in p.export_bins_by_tech[t])) - r["year_one_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3).data - r["average_annual_energy_exported_kwh"] = round( - sum(r["year_one_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) + r["production_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3).data + r["annual_energy_exported_kwh"] = round( + sum(r["production_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) else WindToGrid = zeros(length(p.time_steps)) end - r["year_one_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3) + r["production_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3) WindToCUR = (m[Symbol("dvCurtail"*_n)][t, ts] for ts in p.time_steps) - r["year_one_curtailed_production_series_kw"] = round.(value.(WindToCUR), digits=3) + r["production_curtailed_series_kw"] = round.(value.(WindToCUR), digits=3) TotalHourlyWindProd = value.(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for ts in p.time_steps) WindToLoad =(TotalHourlyWindProd[ts] - - r["year_one_to_battery_series_kw"][ts] - - r["year_one_to_grid_series_kw"][ts] - - r["year_one_curtailed_production_series_kw"][ts] for ts in p.time_steps + - r["production_to_battery_series_kw"][ts] + - r["production_to_grid_series_kw"][ts] + - r["production_curtailed_series_kw"][ts] for ts in p.time_steps ) - r["year_one_to_load_series_kw"] = round.(value.(WindToLoad), digits=3) + r["production_to_load_series_kw"] = round.(value.(WindToLoad), digits=3) Year1WindProd = (sum(TotalHourlyWindProd) * p.hours_per_time_step) r["year_one_energy_produced_kwh"] = round(value(Year1WindProd), digits=0) - r["average_annual_energy_produced_kwh"] = r["year_one_energy_produced_kwh"] * p.levelization_factor[t] + r["annual_energy_produced_kwh"] = r["year_one_energy_produced_kwh"] * p.levelization_factor[t] r["lcoe_per_kwh"] = calculate_lcoe(p, r, p.s.wind) d[t] = r diff --git a/test/runtests.jl b/test/runtests.jl index 4a7296009..5e0a87d00 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -79,7 +79,7 @@ else # run HiGHS tests @test results["PV"]["size_kw"] ≈ 70.3084 atol=0.01 @test results["Financial"]["lcc"] ≈ 430747.0 rtol=1e-5 # with levelization_factor hack the LCC is within 5e-5 of REopt API LCC - @test all(x == 0.0 for x in results["PV"]["year_one_to_load_series_kw"][1:744]) + @test all(x == 0.0 for x in results["PV"]["production_to_load_series_kw"][1:744]) end @testset "Blended tariff" begin @@ -109,8 +109,8 @@ else # run HiGHS tests ) results = run_reopt(model, "./scenarios/generator.json") @test results["Generator"]["size_kw"] ≈ 8.13 atol=0.01 - @test (sum(results["Generator"]["year_one_to_load_series_kw"][i] for i in 1:9) + - sum(results["Generator"]["year_one_to_load_series_kw"][i] for i in 13:8760)) == 0 + @test (sum(results["Generator"]["production_to_load_series_kw"][i] for i in 1:9) + + sum(results["Generator"]["production_to_load_series_kw"][i] for i in 13:8760)) == 0 p = REoptInputs("./scenarios/generator.json") simresults = simulate_outages(results, p) @test simresults["resilience_hours_max"] == 11 diff --git a/test/test_with_cplex.jl b/test/test_with_cplex.jl index d908b4d6c..30edbc150 100644 --- a/test/test_with_cplex.jl +++ b/test/test_with_cplex.jl @@ -49,8 +49,8 @@ check to make sure that PV does NOT export unless the site load is met first for inputs = REoptInputs(s) results = run_reopt(model, inputs) - @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["year_one_to_load_series_kw"][1:744]) - if results["PV"]["year_one_to_grid_series_kw"][i] > 0) + @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["production_to_load_series_kw"][1:744]) + if results["PV"]["production_to_grid_series_kw"][i] > 0) end diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index c012cebf0..653aed2e4 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -37,7 +37,7 @@ Random.seed!(42) # for test consistency, random prices used in FlexibleHVAC tes m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0)) results = run_reopt(m, "./scenarios/thermal_load.json") - @test round(results["ExistingBoiler"]["year_one_fuel_consumption_mmbtu"], digits=0) ≈ 2904 + @test round(results["ExistingBoiler"]["annual_fuel_consumption_mmbtu"], digits=0) ≈ 2904 # Hourly fuel load inputs with addressable_load_fraction are served as expected data = JSON.parsefile("./scenarios/thermal_load.json") @@ -49,7 +49,7 @@ Random.seed!(42) # for test consistency, random prices used in FlexibleHVAC tes inputs = REoptInputs(s) m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0)) results = run_reopt(m, inputs) - @test round(results["ExistingBoiler"]["year_one_fuel_consumption_mmbtu"], digits=0) ≈ 8760 * (0.5 * 0.6 + 0.5 * 0.8) + @test round(results["ExistingBoiler"]["annual_fuel_consumption_mmbtu"], digits=0) ≈ 8760 * (0.5 * 0.6 + 0.5 * 0.8) # Monthly fuel load input with addressable_load_fraction is processed to expected thermal load data = JSON.parsefile("./scenarios/thermal_load.json") @@ -183,10 +183,10 @@ end results = run_reopt(m, inputs) tot_elec_load = results["ElectricLoad"]["load_series_kw"] - chp_total_elec_prod = results["CHP"]["year_one_electric_production_series_kw"] - chp_to_load = results["CHP"]["year_one_to_load_series_kw"] - chp_export = results["CHP"]["year_one_to_grid_series_kw"] - cooling_elec_consumption = results["ExistingChiller"]["year_one_electric_consumption_series_kw"] + chp_total_elec_prod = results["CHP"]["electric_production_series_kw"] + chp_to_load = results["CHP"]["electric_to_load_series_kw"] + chp_export = results["CHP"]["electric_to_grid_series_kw"] + cooling_elec_consumption = results["ExistingChiller"]["electric_consumption_series_kw"] # The values compared to the expected values @test sum([(chp_to_load[i] - tot_elec_load[i]*data["ElectricLoad"]["critical_load_fraction"]) for i in outage_start:outage_end]) ≈ 0.0 atol=0.001 @@ -218,8 +218,8 @@ end results = run_reopt(m1, inputs) @test results["CHP"]["size_kw"] == 800 @test results["CHP"]["size_supplemental_firing_kw"] == 0 - @test results["CHP"]["year_one_electric_energy_produced_kwh"] ≈ 800*8760 rtol=1e-5 - @test results["CHP"]["year_one_thermal_energy_produced_mmbtu"] ≈ 800*(0.4418/0.3573)*8760/293.07107 rtol=1e-5 + @test results["CHP"]["annual_electric_production_kwh"] ≈ 800*8760 rtol=1e-5 + @test results["CHP"]["annual_thermal_production_mmbtu"] ≈ 800*(0.4418/0.3573)*8760/293.07107 rtol=1e-5 @test results["ElectricTariff"]["lifecycle_demand_cost_after_tax"] == 0 @test results["HeatingLoad"]["annual_calculated_total_heating_thermal_load_mmbtu"] == 12.0 * 8760 * REopt.EXISTING_BOILER_EFFICIENCY @test results["HeatingLoad"]["annual_calculated_dhw_thermal_load_mmbtu"] == 6.0 * 8760 * REopt.EXISTING_BOILER_EFFICIENCY @@ -234,7 +234,7 @@ end inputs = REoptInputs(s) results = run_reopt(m2, inputs) @test results["CHP"]["size_supplemental_firing_kw"] ≈ 278.73 atol=0.1 - @test results["CHP"]["year_one_thermal_energy_produced_mmbtu"] ≈ 138624 rtol=1e-5 + @test results["CHP"]["annual_thermal_production_mmbtu"] ≈ 138624 rtol=1e-5 @test results["ElectricTariff"]["lifecycle_demand_cost_after_tax"] ≈ 5212.7 rtol=1e-5 end end @@ -416,8 +416,8 @@ check to make sure that PV does NOT export unless the site load is met first for inputs = REoptInputs(s) results = run_reopt(model, inputs) - @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["year_one_to_load_series_kw"][1:744]) - if results["PV"]["year_one_to_grid_series_kw"][i] > 0) + @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["production_to_load_series_kw"][1:744]) + if results["PV"]["production_to_grid_series_kw"][i] > 0) end @testset "Solar and ElectricStorage w/BAU and degradation" begin @@ -439,11 +439,11 @@ end # compare avg soc with and without degradation, # using default augmentation battery maintenance strategy - avg_soc_no_degr = sum(results["ElectricStorage"]["year_one_soc_series_fraction"]) / 8760 + avg_soc_no_degr = sum(results["ElectricStorage"]["soc_series_fraction"]) / 8760 d["ElectricStorage"]["model_degradation"] = true m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0)) r_degr = run_reopt(m, d) - avg_soc_degr = sum(r_degr["ElectricStorage"]["year_one_soc_series_fraction"]) / 8760 + avg_soc_degr = sum(r_degr["ElectricStorage"]["soc_series_fraction"]) / 8760 @test avg_soc_no_degr > avg_soc_degr # test the replacement strategy @@ -464,7 +464,7 @@ end m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0)) set_optimizer_attribute(m, "MIPRELSTOP", 0.01) r = run_reopt(m, d) - @test round(sum(r["ElectricStorage"]["year_one_soc_series_fraction"]), digits=2) / 8760 >= 0.72 + @test round(sum(r["ElectricStorage"]["soc_series_fraction"]), digits=2) / 8760 >= 0.72 end @testset "Outage with Generator, outage simulator, BAU critical load outputs" begin @@ -473,8 +473,8 @@ end p = REoptInputs("./scenarios/generator.json") results = run_reopt([m1,m2], p) @test results["Generator"]["size_kw"] ≈ 8.13 atol=0.01 - @test (sum(results["Generator"]["year_one_to_load_series_kw"][i] for i in 1:9) + - sum(results["Generator"]["year_one_to_load_series_kw"][i] for i in 13:8760)) == 0 + @test (sum(results["Generator"]["production_to_load_series_kw"][i] for i in 1:9) + + sum(results["Generator"]["production_to_load_series_kw"][i] for i in 13:8760)) == 0 @test results["ElectricLoad"]["bau_critical_load_met"] == false @test results["ElectricLoad"]["bau_critical_load_met_time_steps"] == 0 @@ -674,11 +674,11 @@ end @test roof_east["size_kw"] ≈ 4 atol=0.1 @test ground_pv["lifecycle_om_cost_after_tax_bau"] ≈ 782.0 atol=0.1 @test roof_west["lifecycle_om_cost_after_tax_bau"] ≈ 782.0 atol=0.1 - @test ground_pv["average_annual_energy_produced_kwh_bau"] ≈ 8844.19 atol=0.1 - @test roof_west["average_annual_energy_produced_kwh_bau"] ≈ 7440.1 atol=0.1 - @test ground_pv["average_annual_energy_produced_kwh"] ≈ 26533.54 atol=0.1 - @test roof_west["average_annual_energy_produced_kwh"] ≈ 10416.52 atol=0.1 - @test roof_east["average_annual_energy_produced_kwh"] ≈ 6482.37 atol=0.1 + @test ground_pv["annual_energy_produced_kwh_bau"] ≈ 8844.19 atol=0.1 + @test roof_west["annual_energy_produced_kwh_bau"] ≈ 7440.1 atol=0.1 + @test ground_pv["annual_energy_produced_kwh"] ≈ 26533.54 atol=0.1 + @test roof_west["annual_energy_produced_kwh"] ≈ 10416.52 atol=0.1 + @test roof_east["annual_energy_produced_kwh"] ≈ 6482.37 atol=0.1 end @testset "Thermal Energy Storage + Absorption Chiller" begin @@ -733,14 +733,14 @@ end r = run_reopt(model, p) #dispatch to load should be 10kW every other period = 4,380 * 10 - @test sum(r["HotThermalStorage"]["year_one_to_load_series_mmbtu_per_hour"]) ≈ 149.45 atol=0.1 - @test sum(r["ColdThermalStorage"]["year_one_to_load_series_ton"]) ≈ 12454.33 atol=0.1 + @test sum(r["HotThermalStorage"]["storage_to_load_series_mmbtu_per_hour"]) ≈ 149.45 atol=0.1 + @test sum(r["ColdThermalStorage"]["production_to_load_series_ton"]) ≈ 12454.33 atol=0.1 #size should be just over 10kW in gallons, accounting for efficiency losses and min SOC @test r["HotThermalStorage"]["size_gal"] ≈ 227.89 atol=0.1 @test r["ColdThermalStorage"]["size_gal"] ≈ 379.82 atol=0.1 #No production from existing chiller, only absorption chiller, which is sized at ~5kW to manage electric demand charge & capital cost. - @test r["ExistingChiller"]["year_one_thermal_production_tonhour"] ≈ 0.0 atol=0.1 - @test r["AbsorptionChiller"]["year_one_thermal_production_tonhour"] ≈ 12464.15 atol=0.1 + @test r["ExistingChiller"]["annual_thermal_production_tonhour"] ≈ 0.0 atol=0.1 + @test r["AbsorptionChiller"]["annual_thermal_production_tonhour"] ≈ 12464.15 atol=0.1 @test r["AbsorptionChiller"]["size_ton"] ≈ 2.846 atol=0.01 end @@ -779,13 +779,13 @@ end boiler_fuel_consumption_total_mod_efficiency = boiler_thermal_load_mmbtu_total / inputs.s.existing_boiler.efficiency # Cooling outputs - cooling_elecchl_tons_to_load_series = results["ExistingChiller"]["year_one_to_load_series_ton"] - cooling_elecchl_tons_to_tes_series = results["ExistingChiller"]["year_one_to_tes_series_ton"] - cooling_absorpchl_tons_to_load_series = results["AbsorptionChiller"]["year_one_to_load_series_ton"] - cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["year_one_to_tes_series_ton"] + cooling_elecchl_tons_to_load_series = results["ExistingChiller"]["production_to_load_series_ton"] + cooling_elecchl_tons_to_tes_series = results["ExistingChiller"]["production_to_tes_series_ton"] + cooling_absorpchl_tons_to_load_series = results["AbsorptionChiller"]["production_to_load_series_ton"] + cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["production_to_tes_series_ton"] cooling_tonhour_to_load_tech_total = sum(cooling_elecchl_tons_to_load_series) + sum(cooling_absorpchl_tons_to_load_series) cooling_tonhour_to_tes_total = sum(cooling_elecchl_tons_to_tes_series) + sum(cooling_absorpchl_tons_to_tes_series) - cooling_tes_tons_to_load_series = results["ColdThermalStorage"]["year_one_to_load_series_ton"] + cooling_tes_tons_to_load_series = results["ColdThermalStorage"]["production_to_load_series_ton"] cooling_extra_from_tes_losses = cooling_tonhour_to_tes_total - sum(cooling_tes_tons_to_load_series) tes_effic_with_decay = sum(cooling_tes_tons_to_load_series) / cooling_tonhour_to_tes_total cooling_total_prod_from_techs = cooling_tonhour_to_load_tech_total + cooling_tonhour_to_tes_total @@ -794,7 +794,7 @@ end # Absorption Chiller electric consumption addition absorpchl_total_cooling_produced_series_ton = cooling_absorpchl_tons_to_load_series .+ cooling_absorpchl_tons_to_tes_series absorpchl_total_cooling_produced_ton_hour = sum(absorpchl_total_cooling_produced_series_ton) - absorpchl_electric_consumption_total_kwh = results["AbsorptionChiller"]["year_one_electric_consumption_kwh"] + absorpchl_electric_consumption_total_kwh = results["AbsorptionChiller"]["annual_electric_consumption_kwh"] absorpchl_cop_elec = s.absorption_chiller.cop_electric # Check if sum of electric and absorption chillers equals cooling thermal total @@ -803,15 +803,15 @@ end @test round(absorpchl_electric_consumption_total_kwh, digits=0) ≈ absorpchl_total_cooling_produced_ton_hour * REopt.KWH_THERMAL_PER_TONHOUR / absorpchl_cop_elec atol=1.0 # Heating outputs - boiler_fuel_consumption_calculated = results["ExistingBoiler"]["year_one_fuel_consumption_mmbtu"] - boiler_thermal_series = results["ExistingBoiler"]["year_one_thermal_production_series_mmbtu_per_hour"] - boiler_to_load_series = results["ExistingBoiler"]["year_one_thermal_to_load_series_mmbtu_per_hour"] - boiler_thermal_to_tes_series = results["ExistingBoiler"]["year_one_thermal_to_tes_series_mmbtu_per_hour"] - chp_thermal_to_load_series = results["CHP"]["year_one_thermal_to_load_series_mmbtu_per_hour"] - chp_thermal_to_tes_series = results["CHP"]["year_one_thermal_to_tes_series_mmbtu_per_hour"] + boiler_fuel_consumption_calculated = results["ExistingBoiler"]["annual_fuel_consumption_mmbtu"] + boiler_thermal_series = results["ExistingBoiler"]["thermal_production_series_mmbtu_per_hour"] + boiler_to_load_series = results["ExistingBoiler"]["thermal_to_load_series_mmbtu_per_hour"] + boiler_thermal_to_tes_series = results["ExistingBoiler"]["thermal_to_tes_series_mmbtu_per_hour"] + chp_thermal_to_load_series = results["CHP"]["thermal_to_load_series_mmbtu_per_hour"] + chp_thermal_to_tes_series = results["CHP"]["thermal_to_tes_series_mmbtu_per_hour"] chp_thermal_to_waste_series = results["CHP"]["year_one_thermal_to_waste_series_mmbtu_per_hour"] - absorpchl_thermal_series = results["AbsorptionChiller"]["year_one_thermal_consumption_series_mmbtu_per_hour"] - hot_tes_mmbtu_per_hour_to_load_series = results["HotThermalStorage"]["year_one_to_load_series_mmbtu_per_hour"] + absorpchl_thermal_series = results["AbsorptionChiller"]["thermal_consumption_series_mmbtu_per_hour"] + hot_tes_mmbtu_per_hour_to_load_series = results["HotThermalStorage"]["storage_to_load_series_mmbtu_per_hour"] tes_inflows = sum(chp_thermal_to_tes_series) + sum(boiler_thermal_to_tes_series) total_chp_production = sum(chp_thermal_to_load_series) + sum(chp_thermal_to_waste_series) + sum(chp_thermal_to_tes_series) tes_outflows = sum(hot_tes_mmbtu_per_hour_to_load_series) @@ -823,8 +823,8 @@ end @test round(total_thermal_mmbtu_calculated, digits=0) ≈ total_thermal_expected atol=8.0 # Test CHP["cooling_thermal_factor"] = 0.8, AbsorptionChiller["cop_thermal"] = 0.7 (from inputs .json) - absorpchl_heat_in_kwh = results["AbsorptionChiller"]["year_one_thermal_consumption_mmbtu"] * REopt.KWH_PER_MMBTU - absorpchl_cool_out_kwh = results["AbsorptionChiller"]["year_one_thermal_production_tonhour"] * REopt.KWH_THERMAL_PER_TONHOUR + absorpchl_heat_in_kwh = results["AbsorptionChiller"]["annual_thermal_consumption_mmbtu"] * REopt.KWH_PER_MMBTU + absorpchl_cool_out_kwh = results["AbsorptionChiller"]["annual_thermal_production_tonhour"] * REopt.KWH_THERMAL_PER_TONHOUR absorpchl_cop = absorpchl_cool_out_kwh / absorpchl_heat_in_kwh @test round(absorpchl_cop, digits=5) ≈ 0.8*0.7 rtol=1e-4 @@ -1027,8 +1027,8 @@ end # BAU boiler loads load_thermal_mmbtu_bau = sum(s.space_heating_load.loads_kw + s.dhw_load.loads_kw) / REopt.KWH_PER_MMBTU - existing_boiler_mmbtu = sum(results["ExistingBoiler"]["year_one_thermal_production_series_mmbtu_per_hour"]) - boiler_thermal_mmbtu = sum(results["Boiler"]["year_one_thermal_production_series_mmbtu_per_hour"]) + existing_boiler_mmbtu = sum(results["ExistingBoiler"]["thermal_production_series_mmbtu_per_hour"]) + boiler_thermal_mmbtu = sum(results["Boiler"]["thermal_production_series_mmbtu_per_hour"]) # Used monthly fuel cost for ExistingBoiler and Boiler, where ExistingBoiler has lower fuel cost only # in February (28 days), so expect ExistingBoiler to serve the flat/constant load 28 days of the year @@ -1055,7 +1055,7 @@ end @test scen.financial.microgrid_upgrade_cost_fraction ≈ 0 # Test outputs - @test r["ElectricUtility"]["year_one_energy_supplied_kwh"] ≈ 0 # no interaction with grid + @test r["ElectricUtility"]["annual_energy_supplied_kwh"] ≈ 0 # no interaction with grid @test r["Financial"]["lifecycle_offgrid_other_capital_costs"] ≈ 2617.092 atol=0.01 # Check straight line depreciation calc @test sum(r["ElectricLoad"]["offgrid_annual_oper_res_provided_series_kwh"]) >= sum(r["ElectricLoad"]["offgrid_annual_oper_res_required_series_kwh"]) # OR provided >= required @test r["ElectricLoad"]["offgrid_load_met_fraction"] >= scen.electric_load.min_load_met_annual_fraction @@ -1077,8 +1077,8 @@ end r = run_reopt(m, post) # Test generator outputs - @test r["Generator"]["average_annual_fuel_used_gal"] ≈ 7.52 # 99 kWh * 0.076 gal/kWh - @test r["Generator"]["average_annual_energy_produced_kwh"] ≈ 99.0 + @test r["Generator"]["annual_fuel_consumption_gal"] ≈ 7.52 # 99 kWh * 0.076 gal/kWh + @test r["Generator"]["annual_energy_produced_kwh"] ≈ 99.0 @test r["Generator"]["year_one_fuel_cost_before_tax"] ≈ 22.57 @test r["Generator"]["lifecycle_fuel_cost_after_tax"] ≈ 205.35 @test r["Financial"]["initial_capital_costs"] ≈ 100*(700) @@ -1120,7 +1120,7 @@ end f["lifecycle_outage_cost"] + f["lifecycle_MG_upgrade_and_fuel_cost"] - f["lifecycle_production_incentive_after_tax"] ≈ f["lcc"] atol=1.0 - windOR = sum(results["Wind"]["year_one_to_load_series_kw"] * post["Wind"]["operating_reserve_required_fraction"]) + windOR = sum(results["Wind"]["production_to_load_series_kw"] * post["Wind"]["operating_reserve_required_fraction"]) loadOR = sum(post["ElectricLoad"]["loads_kw"] * scen.electric_load.operating_reserve_required_fraction) @test sum(results["ElectricLoad"]["offgrid_annual_oper_res_required_series_kwh"]) ≈ loadOR + windOR atol=1.0 @@ -1185,7 +1185,7 @@ end @test round(heating_served_mmbtu, digits=1) ≈ expected_heating_served_mmbtu atol=1.0 # Boiler serves all of the DHW load, no DHW thermal reduction due to GHP retrofit - boiler_served_mmbtu = sum(results["ExistingBoiler"]["year_one_thermal_production_series_mmbtu_per_hour"]) + boiler_served_mmbtu = sum(results["ExistingBoiler"]["thermal_production_series_mmbtu_per_hour"]) expected_boiler_served_mmbtu = 3000 * 0.8 # (fuel_mmbtu * boiler_effic) @test round(boiler_served_mmbtu, digits=1) ≈ expected_boiler_served_mmbtu atol=1.0 @@ -1251,11 +1251,11 @@ end ER_fraction_diff = abs(ER_fraction_calced_out-ER_fraction_out) @test ER_fraction_diff ≈ 0.0 atol=1e-2 end - year_one_emissions_tonnes_CO2_out = results["Site"]["year_one_emissions_tonnes_CO2"] - yr1_fuel_emissions_tonnes_CO2_out = results["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2"] - yr1_grid_emissions_tonnes_CO2_out = results["ElectricUtility"]["year_one_emissions_tonnes_CO2"] + annual_emissions_tonnes_CO2_out = results["Site"]["annual_emissions_tonnes_CO2"] + yr1_fuel_emissions_tonnes_CO2_out = results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] + yr1_grid_emissions_tonnes_CO2_out = results["ElectricUtility"]["annual_emissions_tonnes_CO2"] yr1_total_emissions_calced_tonnes_CO2 = yr1_fuel_emissions_tonnes_CO2_out + yr1_grid_emissions_tonnes_CO2_out - @test year_one_emissions_tonnes_CO2_out ≈ yr1_total_emissions_calced_tonnes_CO2 atol=1e-1 + @test annual_emissions_tonnes_CO2_out ≈ yr1_total_emissions_calced_tonnes_CO2 atol=1e-1 if haskey(results["Financial"],"breakeven_cost_of_emissions_reduction_per_tonnes_CO2") @test results["Financial"]["breakeven_cost_of_emissions_reduction_per_tonnes_CO2"] >= 0.0 end @@ -1274,18 +1274,18 @@ end @test results["Site"]["total_renewable_energy_fraction_bau"] ≈ 0.14495 atol=1e-4 @test results["Site"]["lifecycle_emissions_reduction_CO2_fraction"] ≈ 0.61865 atol=1e-4 @test results["Financial"]["breakeven_cost_of_emissions_reduction_per_tonnes_CO2"] ≈ 283.5 atol=1 - @test results["Site"]["year_one_emissions_tonnes_CO2"] ≈ 11.36 atol=1e-2 - @test results["Site"]["year_one_emissions_tonnes_CO2_bau"] ≈ 32.16 atol=1e-2 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2"] ≈ 6.96 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2_bau"] ≈ 0.0 + @test results["Site"]["annual_emissions_tonnes_CO2"] ≈ 11.36 atol=1e-2 + @test results["Site"]["annual_emissions_tonnes_CO2_bau"] ≈ 32.16 atol=1e-2 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] ≈ 6.96 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2_bau"] ≈ 0.0 @test results["Financial"]["lifecycle_emissions_cost_climate"] ≈ 7752.46 atol=1 @test results["Financial"]["lifecycle_emissions_cost_climate_bau"] ≈ 20514.15 atol=1e-1 @test results["Site"]["lifecycle_emissions_tonnes_CO2"] ≈ 217.19 @test results["Site"]["lifecycle_emissions_tonnes_CO2_bau"] ≈ 569.53 @test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2"] ≈ 139.18 @test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2_bau"] ≈ 0.0 - @test results["ElectricUtility"]["year_one_emissions_tonnes_CO2"] ≈ 4.41 - @test results["ElectricUtility"]["year_one_emissions_tonnes_CO2_bau"] ≈ 32.16 + @test results["ElectricUtility"]["annual_emissions_tonnes_CO2"] ≈ 4.41 + @test results["ElectricUtility"]["annual_emissions_tonnes_CO2_bau"] ≈ 32.16 @test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2"] ≈ 78.01 @test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2_bau"] ≈ 569.53 elseif i == 2 @@ -1308,18 +1308,18 @@ end # CO2 emissions - totals ≈ from grid, from fuelburn, ER, $/tCO2 breakeven @test results["Site"]["lifecycle_emissions_reduction_CO2_fraction"] ≈ 0.8 atol=1e-3 # 0.8 @test results["Financial"]["breakeven_cost_of_emissions_reduction_per_tonnes_CO2"] ≈ 351.24 atol=1e-1 - @test results["Site"]["year_one_emissions_tonnes_CO2"] ≈ 14.2 atol=1 - @test results["Site"]["year_one_emissions_tonnes_CO2_bau"] ≈ 70.99 atol=1 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2"] ≈ 0.0 atol=1 # 0.0 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2_bau"] ≈ 0.0 atol=1 # 0.0 + @test results["Site"]["annual_emissions_tonnes_CO2"] ≈ 14.2 atol=1 + @test results["Site"]["annual_emissions_tonnes_CO2_bau"] ≈ 70.99 atol=1 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] ≈ 0.0 atol=1 # 0.0 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2_bau"] ≈ 0.0 atol=1 # 0.0 @test results["Financial"]["lifecycle_emissions_cost_climate"] ≈ 9056.43 atol=1 @test results["Financial"]["lifecycle_emissions_cost_climate_bau"] ≈ 45282.17 atol=1 @test results["Site"]["lifecycle_emissions_tonnes_CO2"] ≈ 251.43 atol=1 @test results["Site"]["lifecycle_emissions_tonnes_CO2_bau"] ≈ 1257.16 atol=1 @test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2"] ≈ 0.0 atol=1 # 0.0 @test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2_bau"] ≈ 0.0 atol=1 # 0.0 - @test results["ElectricUtility"]["year_one_emissions_tonnes_CO2"] ≈ 14.2 atol=1 - @test results["ElectricUtility"]["year_one_emissions_tonnes_CO2_bau"] ≈ 70.99 atol=1 + @test results["ElectricUtility"]["annual_emissions_tonnes_CO2"] ≈ 14.2 atol=1 + @test results["ElectricUtility"]["annual_emissions_tonnes_CO2_bau"] ≈ 70.99 atol=1 @test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2"] ≈ 251.43 atol=1 @test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2_bau"] ≈ 1257.16 atol=1 @@ -1346,22 +1346,22 @@ end @test results["AbsorptionChiller"]["size_ton"] ≈ 400.0 atol=1e-1 @test results["HotThermalStorage"]["size_gal"] ≈ 50000 atol=1e1 @test results["ColdThermalStorage"]["size_gal"] ≈ 30000 atol=1e1 - yr1_nat_gas_mmbtu = results["ExistingBoiler"]["year_one_fuel_consumption_mmbtu"] + results["CHP"]["year_one_fuel_used_mmbtu"] + yr1_nat_gas_mmbtu = results["ExistingBoiler"]["annual_fuel_consumption_mmbtu"] + results["CHP"]["annual_fuel_consumption_mmbtu"] nat_gas_emissions_lb_per_mmbtu = Dict("CO2"=>116.9, "NOx"=>0.09139, "SO2"=>0.000578592, "PM25"=>0.007328833) TONNE_PER_LB = 1/2204.62 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_CO2"] ≈ nat_gas_emissions_lb_per_mmbtu["CO2"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_NOx"] ≈ nat_gas_emissions_lb_per_mmbtu["NOx"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1e-2 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_SO2"] ≈ nat_gas_emissions_lb_per_mmbtu["SO2"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1e-2 - @test results["Site"]["year_one_emissions_from_fuelburn_tonnes_PM25"] ≈ nat_gas_emissions_lb_per_mmbtu["PM25"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1e-2 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] ≈ nat_gas_emissions_lb_per_mmbtu["CO2"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_NOx"] ≈ nat_gas_emissions_lb_per_mmbtu["NOx"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1e-2 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_SO2"] ≈ nat_gas_emissions_lb_per_mmbtu["SO2"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1e-2 + @test results["Site"]["annual_emissions_from_fuelburn_tonnes_PM25"] ≈ nat_gas_emissions_lb_per_mmbtu["PM25"] * yr1_nat_gas_mmbtu * TONNE_PER_LB atol=1e-2 @test results["Site"]["lifecycle_emissions_tonnes_CO2"] ≈ results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2"] + results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2"] atol=1 @test results["Site"]["lifecycle_emissions_tonnes_NOx"] ≈ results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_NOx"] + results["ElectricUtility"]["lifecycle_emissions_tonnes_NOx"] atol=0.1 @test results["Site"]["lifecycle_emissions_tonnes_SO2"] ≈ results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_SO2"] + results["ElectricUtility"]["lifecycle_emissions_tonnes_SO2"] atol=1e-2 @test results["Site"]["lifecycle_emissions_tonnes_PM25"] ≈ results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_PM25"] + results["ElectricUtility"]["lifecycle_emissions_tonnes_PM25"] atol=1.5e-2 - @test results["Site"]["annual_renewable_electricity_kwh"] ≈ results["PV"]["average_annual_energy_produced_kwh"] + inputs["CHP"]["fuel_renewable_energy_fraction"] * results["CHP"]["year_one_electric_energy_produced_kwh"] atol=1 + @test results["Site"]["annual_renewable_electricity_kwh"] ≈ results["PV"]["annual_energy_produced_kwh"] + inputs["CHP"]["fuel_renewable_energy_fraction"] * results["CHP"]["annual_electric_production_kwh"] atol=1 @test results["Site"]["renewable_electricity_fraction"] ≈ results["Site"]["annual_renewable_electricity_kwh"] / results["ElectricLoad"]["annual_calculated_kwh"] atol=1e-6#0.044285 atol=1e-4 KWH_PER_MMBTU = 293.07107 - annual_RE_kwh = inputs["CHP"]["fuel_renewable_energy_fraction"] * results["CHP"]["year_one_thermal_energy_produced_mmbtu"] * KWH_PER_MMBTU + results["Site"]["annual_renewable_electricity_kwh"] - annual_heat_kwh = (results["CHP"]["year_one_thermal_energy_produced_mmbtu"] + results["ExistingBoiler"]["year_one_thermal_production_mmbtu"]) * KWH_PER_MMBTU + annual_RE_kwh = inputs["CHP"]["fuel_renewable_energy_fraction"] * results["CHP"]["annual_thermal_production_mmbtu"] * KWH_PER_MMBTU + results["Site"]["annual_renewable_electricity_kwh"] + annual_heat_kwh = (results["CHP"]["annual_thermal_production_mmbtu"] + results["ExistingBoiler"]["annual_thermal_production_mmbtu"]) * KWH_PER_MMBTU @test results["Site"]["total_renewable_energy_fraction"] ≈ annual_RE_kwh / (annual_heat_kwh + results["ElectricLoad"]["annual_calculated_kwh"]) atol=1e-6 end end @@ -1400,30 +1400,30 @@ end @test results["Financial"]["lcc"] ≈ 189359280.0 rtol=0.001 @test results["Financial"]["npv"] ≈ 8085233.0 rtol=0.01 @test results["SteamTurbine"]["size_kw"] ≈ 2616.418 atol=1.0 - @test results["SteamTurbine"]["year_one_thermal_consumption_mmbtu"] ≈ 1000557.6 rtol=0.001 - @test results["SteamTurbine"]["year_one_electric_energy_produced_kwh"] ≈ 18970374.6 rtol=0.001 - @test results["SteamTurbine"]["year_one_thermal_energy_produced_mmbtu"] ≈ 924045.1 rtol=0.001 + @test results["SteamTurbine"]["annual_thermal_consumption_mmbtu"] ≈ 1000557.6 rtol=0.001 + @test results["SteamTurbine"]["annual_electric_production_kwh"] ≈ 18970374.6 rtol=0.001 + @test results["SteamTurbine"]["annual_thermal_production_mmbtu"] ≈ 924045.1 rtol=0.001 # BAU boiler loads load_boiler_fuel = (s.space_heating_load.loads_kw + s.dhw_load.loads_kw) ./ REopt.KWH_PER_MMBTU ./ s.existing_boiler.efficiency load_boiler_thermal = load_boiler_fuel * s.existing_boiler.efficiency # ExistingBoiler and SteamTurbine production - boiler_to_load = results["ExistingBoiler"]["year_one_thermal_to_load_series_mmbtu_per_hour"] - boiler_to_st = results["ExistingBoiler"]["year_one_thermal_to_steamturbine_series_mmbtu_per_hour"] + boiler_to_load = results["ExistingBoiler"]["thermal_to_load_series_mmbtu_per_hour"] + boiler_to_st = results["ExistingBoiler"]["thermal_to_steamturbine_series_mmbtu_per_hour"] boiler_total = boiler_to_load + boiler_to_st - st_to_load = results["SteamTurbine"]["year_one_thermal_to_load_series_mmbtu_per_hour"] + st_to_load = results["SteamTurbine"]["thermal_to_load_series_mmbtu_per_hour"] # Fuel/thermal **consumption** - boiler_fuel = results["ExistingBoiler"]["year_one_fuel_consumption_series_mmbtu_per_hour"] - steamturbine_thermal_in = results["SteamTurbine"]["year_one_thermal_consumption_series_mmbtu_per_hour"] + boiler_fuel = results["ExistingBoiler"]["fuel_consumption_series_mmbtu_per_hour"] + steamturbine_thermal_in = results["SteamTurbine"]["thermal_consumption_series_mmbtu_per_hour"] # Check that all thermal supply to load meets the BAU load thermal_to_load = sum(boiler_to_load) + sum(st_to_load) @test thermal_to_load ≈ sum(load_boiler_thermal) atol=1.0 # Check the net electric efficiency of Boiler->SteamTurbine (electric out/fuel in) with the expected value from the Fact Sheet - steamturbine_electric = results["SteamTurbine"]["year_one_electric_production_series_kw"] + steamturbine_electric = results["SteamTurbine"]["electric_production_series_kw"] net_electric_efficiency = sum(steamturbine_electric) / (sum(boiler_fuel) * REopt.KWH_PER_MMBTU) @test net_electric_efficiency ≈ 0.052 atol=0.005 @@ -1503,17 +1503,17 @@ end end end # Hot TES is the other thermal supply - hottes_to_load = results["HotThermalStorage"]["year_one_to_load_series_mmbtu_per_hour"] + hottes_to_load = results["HotThermalStorage"]["storage_to_load_series_mmbtu_per_hour"] # BAU boiler loads load_boiler_fuel = s.space_heating_load.loads_kw / input_data["ExistingBoiler"]["efficiency"] ./ REopt.KWH_PER_MMBTU load_boiler_thermal = load_boiler_fuel .* REopt.EXISTING_BOILER_EFFICIENCY # Fuel/thermal **consumption** - boiler_fuel = results["ExistingBoiler"]["year_one_fuel_consumption_series_mmbtu_per_hour"] - chp_fuel_total = results["CHP"]["year_one_fuel_used_mmbtu"] - steamturbine_thermal_in = results["SteamTurbine"]["year_one_thermal_consumption_series_mmbtu_per_hour"] - absorptionchiller_thermal_in = results["AbsorptionChiller"]["year_one_thermal_consumption_series_mmbtu_per_hour"] + boiler_fuel = results["ExistingBoiler"]["fuel_consumption_series_mmbtu_per_hour"] + chp_fuel_total = results["CHP"]["annual_fuel_consumption_mmbtu"] + steamturbine_thermal_in = results["SteamTurbine"]["thermal_consumption_series_mmbtu_per_hour"] + absorptionchiller_thermal_in = results["AbsorptionChiller"]["thermal_consumption_series_mmbtu_per_hour"] # Check that all thermal supply to load meets the BAU load plus AbsorptionChiller load which is not explicitly tracked alltechs_thermal_to_load_total = sum([sum(tech_to_thermal_load[tech]["load"]) for tech in thermal_techs]) + sum(hottes_to_load) From fde7c6b8b65562d9011e503b9a8af75c32adec3b Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 16 Dec 2022 16:41:49 -0700 Subject: [PATCH 02/29] Update test_with_xpress.jl --- test/test_with_xpress.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index 653aed2e4..ac9b55a81 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -809,7 +809,7 @@ end boiler_thermal_to_tes_series = results["ExistingBoiler"]["thermal_to_tes_series_mmbtu_per_hour"] chp_thermal_to_load_series = results["CHP"]["thermal_to_load_series_mmbtu_per_hour"] chp_thermal_to_tes_series = results["CHP"]["thermal_to_tes_series_mmbtu_per_hour"] - chp_thermal_to_waste_series = results["CHP"]["year_one_thermal_to_waste_series_mmbtu_per_hour"] + chp_thermal_to_waste_series = results["CHP"]["thermal_curtailed_series_mmbtu_per_hour"] absorpchl_thermal_series = results["AbsorptionChiller"]["thermal_consumption_series_mmbtu_per_hour"] hot_tes_mmbtu_per_hour_to_load_series = results["HotThermalStorage"]["storage_to_load_series_mmbtu_per_hour"] tes_inflows = sum(chp_thermal_to_tes_series) + sum(boiler_thermal_to_tes_series) @@ -1498,7 +1498,11 @@ end if (tech == "SteamTurbine" && load == "steamturbine") || (load == "waste" && tech != "CHP") tech_to_thermal_load[tech][load] = [0.0] * 8760 else - tech_to_thermal_load[tech][load] = results[tech]["year_one_thermal_to_"*load*"_series_mmbtu_per_hour"] + if load == "waste" + tech_to_thermal_load[tech][load] = results[tech]["thermal_curtailed_series_mmbtu_per_hour"] + else + tech_to_thermal_load[tech][load] = results[tech]["thermal_to_"*load*"_series_mmbtu_per_hour"] + end end end end From 7e647cb52cf89728720af56f83d44ed4f8a224c3 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 16 Dec 2022 16:41:57 -0700 Subject: [PATCH 03/29] Update chp.jl --- src/results/chp.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index b68cf9ad6..360af8477 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -39,7 +39,7 @@ - `electric_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] - `electric_to_load_series_kw` Electric power to serve the electric load time-series array [kW] - `thermal_to_tes_series_mmbtu_per_hour` Thermal power to TES time-series array [MMBtu/hr] -- `year_one_thermal_to_waste_series_mmbtu_per_hour` Thermal power wasted/unused/vented time-series array [MMBtu/hr] +- `thermal_curtailed_series_mmbtu_per_hour` Thermal power wasted/unused/vented time-series array [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` Thermal power to serve the heating load time-series array [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` Thermal (steam) power to steam turbine time-series array [MMBtu/hr] - `year_one_fuel_cost_before_tax` Cost of fuel consumed by the CHP system in year one [\$] @@ -97,7 +97,7 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(CHPtoHotTES / KWH_PER_MMBTU), digits=5) @expression(m, CHPThermalToWasteKW[ts in p.time_steps], sum(m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) - r["year_one_thermal_to_waste_series_mmbtu_per_hour"] = round.(value.(CHPThermalToWasteKW) / KWH_PER_MMBTU, digits=5) + r["thermal_curtailed_series_mmbtu_per_hour"] = round.(value.(CHPThermalToWasteKW) / KWH_PER_MMBTU, digits=5) if !isempty(p.techs.steam_turbine) && p.s.chp.can_supply_steam_turbine @expression(m, CHPToSteamTurbineKW[ts in p.time_steps], sum(m[Symbol("dvThermalToSteamTurbine"*_n)][t,ts] for t in p.techs.chp)) else From cb632fca979a5ce1c2ad8d77a4fe4ff329fc8de1 Mon Sep 17 00:00:00 2001 From: adfarth Date: Mon, 19 Dec 2022 17:12:29 -0500 Subject: [PATCH 04/29] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 128fd0222..a107fc59b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,11 @@ Classify the change according to the following categories: ### Deprecated ### Removed +## Develop - 2022-12-19 +### Changed +- Major name change overall for outputs/results. Changed energy-related outputs with "year_one" in name to "annual" to reflect that they are actually average annual output values. Changed any "average_annual" naming to "annual" to simplify. +### Added +- TODO: Added **thermal_production_series_mmbtu_per_hour** to CHP results. ## v0.23.0 ### Added - Add **REoptLogger** type of global logger with a standard out to the console and to a dictionary From 6b92072c3a33eb20ed1110d0aa5a6129917fec36 Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 21 Dec 2022 17:41:53 -0500 Subject: [PATCH 05/29] add average annual help text --- src/core/chp.jl | 2 +- src/results/absorption_chiller.jl | 13 +++++++++---- src/results/boiler.jl | 5 +++++ src/results/chp.jl | 10 +++++++++- src/results/electric_load.jl | 5 +++++ src/results/electric_storage.jl | 5 +++++ src/results/electric_utility.jl | 21 +++++++++++++-------- src/results/existing_boiler.jl | 5 +++++ src/results/existing_chiller.jl | 5 +++++ src/results/financial.jl | 7 ++++++- src/results/generator.jl | 5 +++++ src/results/ghp.jl | 2 +- src/results/heating_cooling_load.jl | 5 +++++ src/results/pv.jl | 4 ++++ src/results/site.jl | 5 +++++ src/results/steam_turbine.jl | 4 ++++ src/results/thermal_storage.jl | 5 +++++ src/results/wind.jl | 16 ++++++++++------ 18 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/core/chp.jl b/src/core/chp.jl index 4df3a2115..d23a20db8 100644 --- a/src/core/chp.jl +++ b/src/core/chp.jl @@ -91,7 +91,7 @@ prime_movers = ["recip_engine", "micro_turbine", "combustion_turbine", "fuel_cel emissions_factor_lb_PM25_per_mmbtu::Float64 = FUEL_DEFAULTS["emissions_factor_lb_PM25_per_mmbtu"][fuel_type] ``` -!!! note defaults and "Required inputs" +!!! note "Defaults and required inputs" See the `get_chp_defaults_prime_mover_size_class()` function docstring for details on the logic of choosing the type of CHP that is modeled If no information is provided, the default `prime_mover` is `recip_engine` and the `size_class` is 1 which represents the widest range of sizes available. diff --git a/src/results/absorption_chiller.jl b/src/results/absorption_chiller.jl index 443202483..d1b0bf904 100644 --- a/src/results/absorption_chiller.jl +++ b/src/results/absorption_chiller.jl @@ -29,15 +29,20 @@ # ********************************************************************************* """ `AbsorptionChiller` results keys: -- `size_kw` Power capacity size of the absorption chiller system [kW] -- `size_ton` -- `production_to_tes_series_ton` -- `production_to_load_series_ton` +- `size_kw` # Optimal power capacity size of the absorption chiller system [kW] +- `size_ton` +- `production_to_tes_series_ton` +- `production_to_load_series_ton` - `thermal_consumption_series_mmbtu_per_hour` - `annual_thermal_consumption_mmbtu` - `annual_thermal_production_tonhour` - `electric_consumption_series_kw` - `annual_electric_consumption_kwh` + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_absorption_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `AbsorptionChiller` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/boiler.jl b/src/results/boiler.jl index fc2f6c9e7..b6e84b701 100644 --- a/src/results/boiler.jl +++ b/src/results/boiler.jl @@ -40,6 +40,11 @@ - `lifecycle_fuel_cost_after_tax` # Life cycle fuel cost [\$] - `year_one_fuel_cost_before_tax` # Year one fuel cost [\$] - `lifecycle_per_unit_prod_om_costs` # Life cycle production-based O&M cost [\$] + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") diff --git a/src/results/chp.jl b/src/results/chp.jl index 360af8477..5cfb23929 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -46,6 +46,11 @@ - `lifecycle_chp_fuel_cost_after_tax` Present value of cost of fuel consumed by the CHP system, after tax [\$] - `year_one_standby_cost_before_tax` CHP standby charges in year one [\$] - `lifecycle_chp_standby_cost_after_tax` Present value of all CHP standby charges, after tax. + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `CHP` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. @@ -108,7 +113,10 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] for t in p.techs.chp) - CHPtoHotTES[ts] - CHPToSteamTurbineKW[ts] - CHPThermalToWasteKW[ts]) r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(CHPThermalToLoadKW) / KWH_PER_MMBTU, digits=5) - r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) + + # TODO add thermal_production_series_mmbtu_per_hour + + r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) r["lifecycle_chp_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) #Standby charges and hourly O&M r["year_one_standby_cost_before_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) / p.pwf_e, digits=0) diff --git a/src/results/electric_load.jl b/src/results/electric_load.jl index b38b09351..61a9e0a66 100644 --- a/src/results/electric_load.jl +++ b/src/results/electric_load.jl @@ -36,6 +36,11 @@ - `offgrid_load_met_fraction` percentage of total electric load met on an annual basis, for off-grid scenarios only - `offgrid_annual_oper_res_required_series_kwh` , total operating reserves required (for load and techs) on an annual basis, for off-grid scenarios only - `offgrid_annual_oper_res_provided_series_kwh` , total operating reserves provided on an annual basis, for off-grid scenarios only + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_electric_load_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `ElectricLoad` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/electric_storage.jl b/src/results/electric_storage.jl index 54f6011d2..60c5b6bc8 100644 --- a/src/results/electric_storage.jl +++ b/src/results/electric_storage.jl @@ -38,6 +38,11 @@ - `state_of_health` - `maintenance_cost` - `replacement_month` + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_electric_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict, b::String; _n="") # Adds the `Storage` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/electric_utility.jl b/src/results/electric_utility.jl index f94d51685..4d4a412b8 100644 --- a/src/results/electric_utility.jl +++ b/src/results/electric_utility.jl @@ -29,19 +29,24 @@ # ********************************************************************************* """ `ElectricUtility` results keys: -- `annual_energy_supplied_kwh` Total energy supplied from the grid in year one. -- `production_to_load_series_kw` Vector of power drawn from the grid to serve load in year one. -- `production_to_battery_series_kw` Vector of power drawn from the grid to charge the battery in year one. -- `annual_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. -- `annual_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. -- `annual_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. -- `annual_emissions_tonnes_PM25` # Total tons of PM2.5 emissions associated with the site's grid-purchased electricity in year one. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_energy_supplied_kwh` Total energy supplied from the grid in an average year. +- `production_to_load_series_kw` Vector of power drawn from the grid to serve load. +- `production_to_battery_series_kw` Vector of power drawn from the grid to charge the battery. +- `annual_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. +- `annual_emissions_tonnes_PM25` # Total tons of PM2.5 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `lifecycle_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `lifecycle_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `lifecycle_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `lifecycle_emissions_tonnes_PM25` # Total tons of PM2.5 emissions associated with the site's grid-purchased electricity over the analysis period. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `emissions_region` # EPA AVERT region of the site (populated if default emissions values are used). -- `distance_to_emissions_region_meters` +- `distance_to_emissions_region_meters` + +!!! note "'Series' and 'Annual' energy and emissions outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy and emissions outputs averaged over the analysis period. + """ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, d::Dict; _n="") # Adds the `ElectricUtility` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/existing_boiler.jl b/src/results/existing_boiler.jl index 2354692e2..32b08e001 100644 --- a/src/results/existing_boiler.jl +++ b/src/results/existing_boiler.jl @@ -38,6 +38,11 @@ - `thermal_to_load_series_mmbtu_per_hour` - `lifecycle_fuel_cost_after_tax` - `year_one_fuel_cost_before_tax` + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_existing_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() diff --git a/src/results/existing_chiller.jl b/src/results/existing_chiller.jl index bdf1c5570..0472e8752 100644 --- a/src/results/existing_chiller.jl +++ b/src/results/existing_chiller.jl @@ -34,6 +34,11 @@ - `year_one_electric_consumption_series` - `annual_electric_consumption_kwh` - `annual_thermal_production_tonhour` + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_existing_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() diff --git a/src/results/financial.jl b/src/results/financial.jl index b15574cf6..e14b02a54 100644 --- a/src/results/financial.jl +++ b/src/results/financial.jl @@ -57,7 +57,12 @@ - `lifecycle_emissions_cost_health` LCC component if Settings input include_health_in_objective is true. Present value of NOx, SO2, and PM2.5 emissions cost over the analysis period. calculated in combine_results function if BAU scenario is run: - - `breakeven_cost_of_emissions_reduction_per_tonnes_CO2` +- `breakeven_cost_of_emissions_reduction_per_tonnes_CO2` + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_financial_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Float64}() diff --git a/src/results/generator.jl b/src/results/generator.jl index d817629fb..abd43957c 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -42,6 +42,11 @@ - `production_to_load_series_kw` Vector of power sent to load in year one - `year_one_energy_produced_kwh` Total energy produced in year one - `annual_energy_produced_kwh` Average annual energy produced over analysis period + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `Generator` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/ghp.jl b/src/results/ghp.jl index 2f4f46595..c6e30f0f7 100644 --- a/src/results/ghp.jl +++ b/src/results/ghp.jl @@ -33,7 +33,7 @@ Adds the `GHP` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. Note: the node number is an empty string if evaluating a single `Site`. -CHP results: +GHP results: - `ghp_option_chosen` Option chosen for GHP (0 = none) -- With ghp_option_chosen >=1, all data about the GHP system can be achieved by s.ghp_option_list[ghp_option_chosen] - `heating_thermal_load_reduction_with_ghp_kw` diff --git a/src/results/heating_cooling_load.jl b/src/results/heating_cooling_load.jl index 344dfa904..6bab629b9 100644 --- a/src/results/heating_cooling_load.jl +++ b/src/results/heating_cooling_load.jl @@ -31,6 +31,11 @@ `CoolingLoad` results keys: - `load_series_ton` vector of site cooling load in every time step - `annual_calculated_tonhour` sum of the `load_series_ton` + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_cooling_load_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `ElectricLoad` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/pv.jl b/src/results/pv.jl index 63c80ea15..114b64349 100644 --- a/src/results/pv.jl +++ b/src/results/pv.jl @@ -46,6 +46,10 @@ !!! note "Existing PV" All outputs account for any existing PV. E.g., `size_kw` includes existing capacity and the REopt-recommended additional capacity. +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_pv_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `PV` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/site.jl b/src/results/site.jl index 5efa815f9..b254cf36d 100644 --- a/src/results/site.jl +++ b/src/results/site.jl @@ -56,6 +56,11 @@ Site results: calculated in combine_results function if BAU scenario is run: - `lifecycle_emissions_reduction_CO2_fraction` +!!! note "'Series' and 'Annual' energy and emissions outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy and emissions outputs averaged over the analysis period. + + """ function add_site_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() diff --git a/src/results/steam_turbine.jl b/src/results/steam_turbine.jl index 5ad527f62..13210039b 100644 --- a/src/results/steam_turbine.jl +++ b/src/results/steam_turbine.jl @@ -41,6 +41,10 @@ - `thermal_to_tes_series_mmbtu_per_hour` Thermal production to charge the HotThermalStorage series [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` Thermal production to serve the heating load SERVICES [MMBtu/hr] +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_steam_turbine_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `SteamTurbine` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/thermal_storage.jl b/src/results/thermal_storage.jl index fbe82dba6..843bf873e 100644 --- a/src/results/thermal_storage.jl +++ b/src/results/thermal_storage.jl @@ -32,6 +32,11 @@ - `size_gal` Optimal TES capacity, by volume [gal] - `soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year [-] - `storage_to_load_series_mmbtu_per_hour` Vector of power used to meet load over the first year [MMBTU/hr] + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. + """ function add_hot_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict, b::String; _n="") # Adds the `HotThermalStorage` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/wind.jl b/src/results/wind.jl index 4e90b18b7..dd1512444 100644 --- a/src/results/wind.jl +++ b/src/results/wind.jl @@ -29,17 +29,21 @@ # ********************************************************************************* """ `Wind` results keys: -- `size_kw` Optimal Wind capacity +- `size_kw` Optimal Wind capacity [kW] - `lifecycle_om_cost_after_tax` Lifecycle operations and maintenance cost in present value, after tax - `year_one_om_cost_before_tax` Operations and maintenance cost in the first year, before tax benefits -- `production_to_battery_series_kw` Vector of power used to charge the battery over the first year -- `production_to_grid_series_kw` Vector of power exported to the grid over the first year +- `production_to_battery_series_kw` Vector of power used to charge the battery over an average year +- `production_to_grid_series_kw` Vector of power exported to the grid over an average year - `annual_energy_exported_kwh` Average annual energy exported to the grid -- `production_to_load_series_kw` Vector of power used to meet load over the first year -- `year_one_energy_produced_kwh` Energy produced over the first year +- `production_to_load_series_kw` Vector of power used to meet load over an average year +- `year_one_energy_produced_kwh` Energy produced over an average year - `annual_energy_produced_kwh` Average annual energy produced when accounting for degradation - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system -- `production_curtailed_series_kw` Vector of power curtailed over the first year +- `production_curtailed_series_kw` Vector of power curtailed over an average year + +!!! note "'Series' and 'Annual' energy outputs are average annual" + REopt performs load balances using average annual production values for technologies that include degradation. + Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. """ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `Wind` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. From 06fb36f7ee6846af53b052ec0240e13c26742269 Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 21 Dec 2022 17:55:04 -0500 Subject: [PATCH 06/29] add thermal_production_series_mmbtu_per_hour to CHP --- src/results/chp.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index 5cfb23929..7ed4ac489 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -33,7 +33,7 @@ - `size_supplemental_firing_kw` Power capacity of CHP supplementary firing system [kW] - `annual_fuel_consumption_mmbtu` Fuel consumed in year one [MMBtu] - `annual_electric_production_kwh` Electric energy produced in year one [kWh] -- `annual_thermal_production_mmbtu` Thermal energy produced in year one [MMBtu] +- `annual_thermal_production_mmbtu` Thermal energy produced in year one (not including waste heat) [MMBtu] - `electric_production_series_kw` Electric power production time-series array [kW] - `electric_to_grid_series_kw` Electric power exported time-series array [kW] - `electric_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] @@ -46,6 +46,7 @@ - `lifecycle_chp_fuel_cost_after_tax` Present value of cost of fuel consumed by the CHP system, after tax [\$] - `year_one_standby_cost_before_tax` CHP standby charges in year one [\$] - `lifecycle_chp_standby_cost_after_tax` Present value of all CHP standby charges, after tax. +- `thermal_production_series_mmbtu_per_hour` !!! note "'Series' and 'Annual' energy outputs are average annual" REopt performs load balances using average annual production values for technologies that include degradation. @@ -114,7 +115,10 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") for t in p.techs.chp) - CHPtoHotTES[ts] - CHPToSteamTurbineKW[ts] - CHPThermalToWasteKW[ts]) r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(CHPThermalToLoadKW) / KWH_PER_MMBTU, digits=5) - # TODO add thermal_production_series_mmbtu_per_hour + @expression(m, CHPThermalProdKW[ts in p.time_steps], + sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] - + m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) + r["thermal_production_series_mmbtu_per_hour"] = round.(value.(CHPThermalProdKW) / KWH_PER_MMBTU, digits=5) r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) r["lifecycle_chp_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) From f4fb41a8d87352db693d7fe5023b5e29dfd15725 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 22 Dec 2022 10:06:31 -0500 Subject: [PATCH 07/29] add question --- src/results/generator.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/results/generator.jl b/src/results/generator.jl index abd43957c..70b19ae6b 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -40,7 +40,7 @@ - `production_to_battery_series_kw` Vector of power sent to battery in year one - `production_to_grid_series_kw` Vector of power sent to grid in year one - `production_to_load_series_kw` Vector of power sent to load in year one -- `year_one_energy_produced_kwh` Total energy produced in year one +- `year_one_energy_produced_kwh` Total energy produced in year one # TODO: Remove? - `annual_energy_produced_kwh` Average annual energy produced over analysis period !!! note "'Series' and 'Annual' energy outputs are average annual" From 462f806618bc472d5ebd077f300861c0f302b4a7 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 22 Dec 2022 10:14:42 -0500 Subject: [PATCH 08/29] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a107fc59b..114659abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ Classify the change according to the following categories: ### Changed - Major name change overall for outputs/results. Changed energy-related outputs with "year_one" in name to "annual" to reflect that they are actually average annual output values. Changed any "average_annual" naming to "annual" to simplify. ### Added -- TODO: Added **thermal_production_series_mmbtu_per_hour** to CHP results. +- Added **thermal_production_series_mmbtu_per_hour** to CHP results. ## v0.23.0 ### Added - Add **REoptLogger** type of global logger with a standard out to the console and to a dictionary From 0451443327b70bb93a3f80ebf53099c0d0d0cdb8 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 22 Dec 2022 10:19:42 -0500 Subject: [PATCH 09/29] remove comment --- src/core/reopt_inputs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index 75a1772df..de6cce79b 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -198,7 +198,7 @@ function REoptInputs(s::AbstractScenario) # levelization_factor = Dict("PV" => 0.9539) # levelization_factor = Dict("ground" => 0.942238, "roof_east" => 0.942238, "roof_west" => 0.942238) # levelization_factor["PV"] = 0.9539 - # levelization_factor["Generator"] = 1.0 # TODO: does it make sense to default this to 1 while the calculation involves discount and escalation rates? + # levelization_factor["Generator"] = 1.0 time_steps_with_grid, time_steps_without_grid, = setup_electric_utility_inputs(s) ghp_options, require_ghp_purchase, ghp_heating_thermal_load_served_kw, From 3188592e10e98f03116454d9e1024bae4736bdad Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 22 Dec 2022 10:21:21 -0500 Subject: [PATCH 10/29] remove print and comments --- src/core/reopt_inputs.jl | 1 - src/core/utils.jl | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index de6cce79b..e3fbf96d1 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -190,7 +190,6 @@ function REoptInputs(s::AbstractScenario) months = 1:12 levelization_factor, pwf_e, pwf_om, pwf_fuel, pwf_emissions_cost, pwf_grid_emissions, third_party_factor, pwf_offtaker, pwf_owner = setup_present_worth_factors(s, techs) - print("\nlevelization_factor: ", levelization_factor) # the following hardcoded values for levelization_factor matches the public REopt API value # and makes the test values match. # the REopt code herein uses the Desktop method for levelization_factor, which is more accurate diff --git a/src/core/utils.jl b/src/core/utils.jl index f0d09eadd..341ef3813 100644 --- a/src/core/utils.jl +++ b/src/core/utils.jl @@ -70,8 +70,7 @@ function annuity_escalation(analysis_period::Int, rate_escalation::Real, rate_di end -function levelization_factor(years::Int, rate_escalation::Real, rate_discount::Real, # TODO: should this account for escalation and discount rates? - rate_degradation::Real) +function levelization_factor(years::Int, rate_escalation::Real, rate_discount::Real, rate_degradation::Real) #= NOTE: levelization_factor for an electricity producing tech is the ratio of: - an annuity with an escalation rate equal to the electricity cost escalation rate, starting year 1, From 03e8dc8a28e5adc926b48da383e777f0f49bc152 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 22 Dec 2022 11:30:16 -0500 Subject: [PATCH 11/29] Update absorption_chiller.jl help text --- src/core/absorption_chiller.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/absorption_chiller.jl b/src/core/absorption_chiller.jl index 8af91f4b5..8819304f7 100644 --- a/src/core/absorption_chiller.jl +++ b/src/core/absorption_chiller.jl @@ -38,7 +38,6 @@ installed_cost_per_ton::Union{Float64, Nothing} = nothing om_cost_per_ton::Union{Float64, Nothing} = nothing - #Optional min_ton::Float64 = 0.0, max_ton::Float64 = BIG_NUMBER, @@ -50,11 +49,13 @@ ``` !!! note "Required inputs" - To model AbsorptionChiller, you must provide at least one of the following: (i) `thermal_consumption_hot_water_or_steam` from $(HOT_WATER_OR_STEAM), (ii) - (ii), `chp_prime_mover` from $(PRIME_MOVERS),or (iii) all of the "custom inputs" defined below. - If prime_mover is provided, any missing value from the "custom inputs" will be populated from data/absorption_chiller/defaults.json, - based on the `thermal_consumption_hot_water_or_steam` or `prime_mover`. boiler_type is "steam" if `prime_mover` is "combustion_turbine" - and is "hot_water" for all other `prime_mover` types. + To model AbsorptionChiller, you must provide at least one of the following: + (i) `thermal_consumption_hot_water_or_steam` from $(HOT_WATER_OR_STEAM), + (ii) `chp_prime_mover` from $(PRIME_MOVERS), or + (iii) all of the "custom inputs" defined below. + If `chp_prime_mover` is provided, any missing value from the "custom inputs" will be populated from data/absorption_chiller/defaults.json, + based on the `thermal_consumption_hot_water_or_steam` or `chp_prime_mover`. + `boiler_type` is "steam" if `prime_mover` is "combustion_turbine" and is "hot_water" for all other `chp_prime_mover` types. """ Base.@kwdef mutable struct AbsorptionChiller <: AbstractThermalTech thermal_consumption_hot_water_or_steam::Union{String, Nothing} = nothing From c0fcd8cbe2e1600c3624c43a354d5dda96656df8 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 22 Dec 2022 11:52:59 -0500 Subject: [PATCH 12/29] Update chp.jl text --- src/results/chp.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index 7ed4ac489..5f50b11c4 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -31,9 +31,9 @@ `CHP` results keys: - `size_kw` Power capacity size of the CHP system [kW] - `size_supplemental_firing_kw` Power capacity of CHP supplementary firing system [kW] -- `annual_fuel_consumption_mmbtu` Fuel consumed in year one [MMBtu] -- `annual_electric_production_kwh` Electric energy produced in year one [kWh] -- `annual_thermal_production_mmbtu` Thermal energy produced in year one (not including waste heat) [MMBtu] +- `annual_fuel_consumption_mmbtu` Fuel consumed in a year [MMBtu] +- `annual_electric_production_kwh` Electric energy produced in a year [kWh] +- `annual_thermal_production_mmbtu` Thermal energy produced in a year (not including waste heat) [MMBtu] - `electric_production_series_kw` Electric power production time-series array [kW] - `electric_to_grid_series_kw` Electric power exported time-series array [kW] - `electric_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] From a5f9a2005fe7e44fbc13f5cc9f07c4a7ea2be1b2 Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 28 Dec 2022 15:06:55 -0500 Subject: [PATCH 13/29] remove _chp from cost outputs --- src/results/chp.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index 5f50b11c4..1ed5a2d01 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -43,9 +43,9 @@ - `thermal_to_load_series_mmbtu_per_hour` Thermal power to serve the heating load time-series array [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` Thermal (steam) power to steam turbine time-series array [MMBtu/hr] - `year_one_fuel_cost_before_tax` Cost of fuel consumed by the CHP system in year one [\$] -- `lifecycle_chp_fuel_cost_after_tax` Present value of cost of fuel consumed by the CHP system, after tax [\$] +- `lifecycle_fuel_cost_after_tax` Present value of cost of fuel consumed by the CHP system, after tax [\$] - `year_one_standby_cost_before_tax` CHP standby charges in year one [\$] -- `lifecycle_chp_standby_cost_after_tax` Present value of all CHP standby charges, after tax. +- `lifecycle_standby_cost_after_tax` Present value of all CHP standby charges, after tax. - `thermal_production_series_mmbtu_per_hour` !!! note "'Series' and 'Annual' energy outputs are average annual" @@ -121,10 +121,10 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r["thermal_production_series_mmbtu_per_hour"] = round.(value.(CHPThermalProdKW) / KWH_PER_MMBTU, digits=5) r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) - r["lifecycle_chp_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) + r["lifecycle_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) #Standby charges and hourly O&M r["year_one_standby_cost_before_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) / p.pwf_e, digits=0) - r["lifecycle_chp_standby_cost_after_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) * p.s.financial.offtaker_tax_rate_fraction, digits=0) + r["lifecycle_standby_cost_after_tax"] = round(value(m[Symbol("TotalCHPStandbyCharges")]) * p.s.financial.offtaker_tax_rate_fraction, digits=0) d["CHP"] = r From 9c3f0bf5840b677a44ff8d1ceedcc8d2fbf887d4 Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 28 Dec 2022 16:04:41 -0500 Subject: [PATCH 14/29] Update thermal_storage.jl --- src/results/thermal_storage.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/results/thermal_storage.jl b/src/results/thermal_storage.jl index 843bf873e..c99c13092 100644 --- a/src/results/thermal_storage.jl +++ b/src/results/thermal_storage.jl @@ -88,7 +88,7 @@ end `ColdThermalStorage` results: - `size_gal` Optimal TES capacity, by volume [gal] - `soc_series_fraction` Vector of normalized (0-1) state of charge values over the first year [-] -- `production_to_load_series_ton` Vector of power used to meet load over the first year [ton] +- `storage_to_load_series_ton` Vector of power used to meet load over the first year [ton] """ function add_cold_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict, b::String; _n="") #= @@ -110,10 +110,10 @@ function add_cold_storage_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict r["soc_series_fraction"] = round.(value.(soc) ./ size_kwh, digits=3) discharge = (m[Symbol("dvDischargeFromStorage"*_n)][b, ts] for ts in p.time_steps) - r["production_to_load_series_ton"] = round.(value.(discharge) / KWH_THERMAL_PER_TONHOUR, digits=7) + r["storage_to_load_series_ton"] = round.(value.(discharge) / KWH_THERMAL_PER_TONHOUR, digits=7) else r["soc_series_fraction"] = [] - r["production_to_load_series_ton"] = [] + r["storage_to_load_series_ton"] = [] end d[b] = r From a802bc11ca6a19bb871f378696d386c12a9b6544 Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 28 Dec 2022 16:27:33 -0500 Subject: [PATCH 15/29] Update test_with_xpress.jl ColdThermalStorage output --- test/test_with_xpress.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index a44fd1556..3a6734985 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -734,7 +734,7 @@ end #dispatch to load should be 10kW every other period = 4,380 * 10 @test sum(r["HotThermalStorage"]["storage_to_load_series_mmbtu_per_hour"]) ≈ 149.45 atol=0.1 - @test sum(r["ColdThermalStorage"]["production_to_load_series_ton"]) ≈ 12454.33 atol=0.1 + @test sum(r["ColdThermalStorage"]["storage_to_load_series_ton"]) ≈ 12454.33 atol=0.1 #size should be just over 10kW in gallons, accounting for efficiency losses and min SOC @test r["HotThermalStorage"]["size_gal"] ≈ 227.89 atol=0.1 @test r["ColdThermalStorage"]["size_gal"] ≈ 379.82 atol=0.1 @@ -785,7 +785,7 @@ end cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["production_to_tes_series_ton"] cooling_tonhour_to_load_tech_total = sum(cooling_elecchl_tons_to_load_series) + sum(cooling_absorpchl_tons_to_load_series) cooling_tonhour_to_tes_total = sum(cooling_elecchl_tons_to_tes_series) + sum(cooling_absorpchl_tons_to_tes_series) - cooling_tes_tons_to_load_series = results["ColdThermalStorage"]["production_to_load_series_ton"] + cooling_tes_tons_to_load_series = results["ColdThermalStorage"]["storage_to_load_series_ton"] cooling_extra_from_tes_losses = cooling_tonhour_to_tes_total - sum(cooling_tes_tons_to_load_series) tes_effic_with_decay = sum(cooling_tes_tons_to_load_series) / cooling_tonhour_to_tes_total cooling_total_prod_from_techs = cooling_tonhour_to_load_tech_total + cooling_tonhour_to_tes_total From fd6b018279541a5308b9bc4e65008cf6cda7bdb2 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 12:31:43 -0500 Subject: [PATCH 16/29] rmv redundant eqn in chp.jl --- src/results/chp.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index 1ed5a2d01..838a6720a 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -65,12 +65,15 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") p.hours_per_time_step * sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for t in p.techs.chp, ts in p.time_steps)) r["annual_electric_production_kwh"] = round(value(Year1CHPElecProd), digits=3) - @expression(m, Year1CHPThermalProdKWH, - p.hours_per_time_step * sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + - m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] - - m[Symbol("dvProductionToWaste"*_n)][t,ts] - for t in p.techs.chp, ts in p.time_steps)) - r["annual_thermal_production_mmbtu"] = round(value(Year1CHPThermalProdKWH) / KWH_PER_MMBTU, digits=3) + + @expression(m, CHPThermalProdKW[ts in p.time_steps], + sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] - + m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) + + r["thermal_production_series_mmbtu_per_hour"] = round.(value.(CHPThermalProdKW) / KWH_PER_MMBTU, digits=5) + + r["annual_thermal_production_mmbtu"] = round(p.hours_per_time_step * sum(r["thermal_production_series_mmbtu_per_hour"]), digits=3) + @expression(m, CHPElecProdTotal[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for t in p.techs.chp)) r["electric_production_series_kw"] = round.(value.(CHPElecProdTotal), digits=3) @@ -118,7 +121,6 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") @expression(m, CHPThermalProdKW[ts in p.time_steps], sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] - m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) - r["thermal_production_series_mmbtu_per_hour"] = round.(value.(CHPThermalProdKW) / KWH_PER_MMBTU, digits=5) r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) r["lifecycle_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) From e4e4f6e32741f673adae16e8b7fe4e2444ef3dda Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:01:00 -0500 Subject: [PATCH 17/29] Update chp.jl --- src/results/chp.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index 838a6720a..c916934db 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -117,11 +117,6 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] for t in p.techs.chp) - CHPtoHotTES[ts] - CHPToSteamTurbineKW[ts] - CHPThermalToWasteKW[ts]) r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(CHPThermalToLoadKW) / KWH_PER_MMBTU, digits=5) - - @expression(m, CHPThermalProdKW[ts in p.time_steps], - sum(m[Symbol("dvThermalProduction"*_n)][t,ts] + m[Symbol("dvSupplementaryThermalProduction"*_n)][t,ts] - - m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) - r["year_one_fuel_cost_before_tax"] = round(value(m[:TotalCHPFuelCosts] / p.pwf_fuel["CHP"]), digits=3) r["lifecycle_fuel_cost_after_tax"] = round(value(m[:TotalCHPFuelCosts]) * p.s.financial.offtaker_tax_rate_fraction, digits=3) #Standby charges and hourly O&M From e7ddf15556aec27be5cef340e54f4042a6ac6ad4 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:06:42 -0500 Subject: [PATCH 18/29] remove year1 energy output for wind and generator --- src/results/generator.jl | 6 ------ src/results/wind.jl | 8 +++----- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/results/generator.jl b/src/results/generator.jl index 70b19ae6b..2e1c09234 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -40,7 +40,6 @@ - `production_to_battery_series_kw` Vector of power sent to battery in year one - `production_to_grid_series_kw` Vector of power sent to grid in year one - `production_to_load_series_kw` Vector of power sent to load in year one -- `year_one_energy_produced_kwh` Total energy produced in year one # TODO: Remove? - `annual_energy_produced_kwh` Average annual energy produced over analysis period !!! note "'Series' and 'Annual' energy outputs are average annual" @@ -91,11 +90,6 @@ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ GeneratorFuelUsed = @expression(m, sum(m[:dvFuelUsage][t, ts] for t in p.techs.gen, ts in p.time_steps) / KWH_PER_GAL_DIESEL) r["annual_fuel_consumption_gal"] = round(value(GeneratorFuelUsed), digits=2) - Year1GenProd = @expression(m, - p.hours_per_time_step * sum(m[:dvRatedProduction][t,ts] * p.production_factor[t, ts] - for t in p.techs.gen, ts in p.time_steps) - ) - r["year_one_energy_produced_kwh"] = round(value(Year1GenProd), digits=0) AverageGenProd = @expression(m, p.hours_per_time_step * sum(m[:dvRatedProduction][t,ts] * p.production_factor[t, ts] * p.levelization_factor[t] diff --git a/src/results/wind.jl b/src/results/wind.jl index dd1512444..961dffc5e 100644 --- a/src/results/wind.jl +++ b/src/results/wind.jl @@ -36,8 +36,7 @@ - `production_to_grid_series_kw` Vector of power exported to the grid over an average year - `annual_energy_exported_kwh` Average annual energy exported to the grid - `production_to_load_series_kw` Vector of power used to meet load over an average year -- `year_one_energy_produced_kwh` Energy produced over an average year -- `annual_energy_produced_kwh` Average annual energy produced when accounting for degradation +- `annual_energy_produced_kwh` Average annual energy produced - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system - `production_curtailed_series_kw` Vector of power curtailed over an average year @@ -89,9 +88,8 @@ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") ) r["production_to_load_series_kw"] = round.(value.(WindToLoad), digits=3) - Year1WindProd = (sum(TotalHourlyWindProd) * p.hours_per_time_step) - r["year_one_energy_produced_kwh"] = round(value(Year1WindProd), digits=0) - r["annual_energy_produced_kwh"] = r["year_one_energy_produced_kwh"] * p.levelization_factor[t] + AvgWindProd = (sum(TotalHourlyWindProd) * p.hours_per_time_step) * p.levelization_factor[t] + r["annual_energy_produced_kwh"] = r["year_one_energy_produced_kwh"] round(value(AvgWindProd), digits=0) r["lcoe_per_kwh"] = calculate_lcoe(p, r, p.s.wind) d[t] = r From 3b4ab7f2fce7601780372b4193f41e927eaab0e6 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:12:20 -0500 Subject: [PATCH 19/29] Update wind.jl --- src/results/wind.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/results/wind.jl b/src/results/wind.jl index 961dffc5e..03468821b 100644 --- a/src/results/wind.jl +++ b/src/results/wind.jl @@ -89,7 +89,7 @@ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r["production_to_load_series_kw"] = round.(value.(WindToLoad), digits=3) AvgWindProd = (sum(TotalHourlyWindProd) * p.hours_per_time_step) * p.levelization_factor[t] - r["annual_energy_produced_kwh"] = r["year_one_energy_produced_kwh"] round(value(AvgWindProd), digits=0) + r["annual_energy_produced_kwh"] = round(value(AvgWindProd), digits=0) r["lcoe_per_kwh"] = calculate_lcoe(p, r, p.s.wind) d[t] = r From 584011cb61e815de8155f3db50852bdef698bfa2 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:19:19 -0500 Subject: [PATCH 20/29] production -> thermal for abs and exst chiller --- src/results/absorption_chiller.jl | 8 ++++---- src/results/existing_chiller.jl | 8 ++++---- test/test_with_xpress.jl | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/results/absorption_chiller.jl b/src/results/absorption_chiller.jl index d1b0bf904..de8cfa209 100644 --- a/src/results/absorption_chiller.jl +++ b/src/results/absorption_chiller.jl @@ -31,8 +31,8 @@ `AbsorptionChiller` results keys: - `size_kw` # Optimal power capacity size of the absorption chiller system [kW] - `size_ton` -- `production_to_tes_series_ton` -- `production_to_load_series_ton` +- `thermal_to_tes_series_ton` +- `thermal_to_load_series_ton` - `thermal_consumption_series_mmbtu_per_hour` - `annual_thermal_consumption_mmbtu` - `annual_thermal_production_tonhour` @@ -59,11 +59,11 @@ function add_absorption_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d r["size_ton"] = r["size_kw"] / KWH_THERMAL_PER_TONHOUR @expression(m, ABSORPCHLtoTESKW[ts in p.time_steps], sum(m[:dvProductionToStorage][b,t,ts] for b in p.s.storage.types.cold, t in p.techs.absorption_chiller)) - r["production_to_tes_series_ton"] = round.(value.(ABSORPCHLtoTESKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) + r["thermal_to_tes_series_ton"] = round.(value.(ABSORPCHLtoTESKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) @expression(m, ABSORPCHLtoLoadKW[ts in p.time_steps], sum(m[:dvThermalProduction][t,ts] for t in p.techs.absorption_chiller) - ABSORPCHLtoTESKW[ts]) - r["production_to_load_series_ton"] = round.(value.(ABSORPCHLtoLoadKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) + r["thermal_to_load_series_ton"] = round.(value.(ABSORPCHLtoLoadKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) @expression(m, ABSORPCHLThermalConsumptionSeriesKW[ts in p.time_steps], sum(m[:dvThermalProduction][t,ts] / p.thermal_cop[t] for t in p.techs.absorption_chiller)) r["thermal_consumption_series_mmbtu_per_hour"] = round.(value.(ABSORPCHLThermalConsumptionSeriesKW) ./ KWH_PER_MMBTU, digits=5) diff --git a/src/results/existing_chiller.jl b/src/results/existing_chiller.jl index 0472e8752..74e95d145 100644 --- a/src/results/existing_chiller.jl +++ b/src/results/existing_chiller.jl @@ -29,8 +29,8 @@ # ********************************************************************************* """ `ExistingChiller` results keys: -- `production_to_tes_series_ton` -- `production_to_load_series_ton` +- `thermal_to_tes_series_ton` +- `thermal_to_load_series_ton` - `year_one_electric_consumption_series` - `annual_electric_consumption_kwh` - `annual_thermal_production_tonhour` @@ -46,13 +46,13 @@ function add_existing_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d:: @expression(m, ELECCHLtoTES[ts in p.time_steps], sum(m[:dvProductionToStorage][b,"ExistingChiller",ts] for b in p.s.storage.types.cold) ) - r["production_to_tes_series_ton"] = round.(value.(ELECCHLtoTES / KWH_THERMAL_PER_TONHOUR), digits=3) + r["thermal_to_tes_series_ton"] = round.(value.(ELECCHLtoTES / KWH_THERMAL_PER_TONHOUR), digits=3) @expression(m, ELECCHLtoLoad[ts in p.time_steps], sum(m[:dvThermalProduction]["ExistingChiller", ts]) - ELECCHLtoTES[ts] ) - r["production_to_load_series_ton"] = round.(value.(ELECCHLtoLoad / KWH_THERMAL_PER_TONHOUR).data, digits=3) + r["thermal_to_load_series_ton"] = round.(value.(ELECCHLtoLoad / KWH_THERMAL_PER_TONHOUR).data, digits=3) @expression(m, ELECCHLElecConsumptionSeries[ts in p.time_steps], sum(m[:dvThermalProduction]["ExistingChiller", ts] / p.cop["ExistingChiller"]) diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index 3a6734985..d5274d565 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -779,10 +779,10 @@ end boiler_fuel_consumption_total_mod_efficiency = boiler_thermal_load_mmbtu_total / inputs.s.existing_boiler.efficiency # Cooling outputs - cooling_elecchl_tons_to_load_series = results["ExistingChiller"]["production_to_load_series_ton"] - cooling_elecchl_tons_to_tes_series = results["ExistingChiller"]["production_to_tes_series_ton"] - cooling_absorpchl_tons_to_load_series = results["AbsorptionChiller"]["production_to_load_series_ton"] - cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["production_to_tes_series_ton"] + cooling_elecchl_tons_to_load_series = results["ExistingChiller"]["thermal_to_load_series_ton"] + cooling_elecchl_tons_to_tes_series = results["ExistingChiller"]["thermal_to_tes_series_ton"] + cooling_absorpchl_tons_to_load_series = results["AbsorptionChiller"]["thermal_to_load_series_ton"] + cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["thermal_to_tes_series_ton"] cooling_tonhour_to_load_tech_total = sum(cooling_elecchl_tons_to_load_series) + sum(cooling_absorpchl_tons_to_load_series) cooling_tonhour_to_tes_total = sum(cooling_elecchl_tons_to_tes_series) + sum(cooling_absorpchl_tons_to_tes_series) cooling_tes_tons_to_load_series = results["ColdThermalStorage"]["storage_to_load_series_ton"] From 3b168907b7af57305c1ba42bff800e9dcfd3b485 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:24:12 -0500 Subject: [PATCH 21/29] production_ --> electric_ --- src/outagesim/backup_reliability.jl | 8 ++++---- src/outagesim/outage_simulator.jl | 8 ++++---- src/results/electric_utility.jl | 8 ++++---- src/results/generator.jl | 12 ++++++------ src/results/pv.jl | 26 +++++++++++++------------- src/results/results.jl | 2 +- src/results/wind.jl | 26 +++++++++++++------------- test/runtests.jl | 6 +++--- test/test_with_cplex.jl | 4 ++-- test/test_with_xpress.jl | 10 +++++----- 10 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/outagesim/backup_reliability.jl b/src/outagesim/backup_reliability.jl index f1f94e3ca..dc33fe105 100644 --- a/src/outagesim/backup_reliability.jl +++ b/src/outagesim/backup_reliability.jl @@ -456,10 +456,10 @@ function backup_reliability_inputs(d::Dict, p::REoptInputs; r::Dict = Dict())::D pv_kw_ac_hourly = zero_array if "PV" in keys(d) pv_kw_ac_hourly = ( - get(d["PV"], "production_to_battery_series_kw", zero_array) - + get(d["PV"], "production_curtailed_series_kw", zero_array) - + get(d["PV"], "production_to_load_series_kw", zero_array) - + get(d["PV"], "production_to_grid_series_kw", zero_array) + get(d["PV"], "electric_to_battery_series_kw", zero_array) + + get(d["PV"], "electric_curtailed_series_kw", zero_array) + + get(d["PV"], "electric_to_load_series_kw", zero_array) + + get(d["PV"], "electric_to_grid_series_kw", zero_array) ) end if microgrid_only && !Bool(get(d, "PV_upgraded", false)) diff --git a/src/outagesim/outage_simulator.jl b/src/outagesim/outage_simulator.jl index 7c1bee304..9475da3fd 100644 --- a/src/outagesim/outage_simulator.jl +++ b/src/outagesim/outage_simulator.jl @@ -259,10 +259,10 @@ function simulate_outages(d::Dict, p::REoptInputs; microgrid_only::Bool=false) pv_kw_ac_hourly = zeros(length(p.time_steps)) if "PV" in keys(d) pv_kw_ac_hourly = ( - get(d["PV"], "production_to_battery_series_kw", zeros(length(p.time_steps))) - + get(d["PV"], "production_curtailed_series_kw", zeros(length(p.time_steps))) - + get(d["PV"], "production_to_load_series_kw", zeros(length(p.time_steps))) - + get(d["PV"], "production_to_grid_series_kw", zeros(length(p.time_steps))) + get(d["PV"], "electric_to_battery_series_kw", zeros(length(p.time_steps))) + + get(d["PV"], "electric_curtailed_series_kw", zeros(length(p.time_steps))) + + get(d["PV"], "electric_to_load_series_kw", zeros(length(p.time_steps))) + + get(d["PV"], "electric_to_grid_series_kw", zeros(length(p.time_steps))) ) end if microgrid_only && !Bool(get(d["Outages"], "PV_upgraded", false)) diff --git a/src/results/electric_utility.jl b/src/results/electric_utility.jl index 4d4a412b8..fa1d5e0d9 100644 --- a/src/results/electric_utility.jl +++ b/src/results/electric_utility.jl @@ -30,8 +30,8 @@ """ `ElectricUtility` results keys: - `annual_energy_supplied_kwh` Total energy supplied from the grid in an average year. -- `production_to_load_series_kw` Vector of power drawn from the grid to serve load. -- `production_to_battery_series_kw` Vector of power drawn from the grid to charge the battery. +- `electric_to_load_series_kw` Vector of power drawn from the grid to serve load. +- `electric_to_battery_series_kw` Vector of power drawn from the grid to charge the battery. - `annual_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `annual_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `annual_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. @@ -70,8 +70,8 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, GridToBatt = zeros(length(p.time_steps)) end - r["production_to_load_series_kw"] = round.(value.(GridToLoad), digits=3) - r["production_to_battery_series_kw"] = round.(value.(GridToBatt), digits=3) + r["electric_to_load_series_kw"] = round.(value.(GridToLoad), digits=3) + r["electric_to_battery_series_kw"] = round.(value.(GridToBatt), digits=3) if _n=="" #only output emissions results if not a multinode model r["annual_emissions_tonnes_CO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_CO2]*TONNE_PER_LB), digits=2) diff --git a/src/results/generator.jl b/src/results/generator.jl index 2e1c09234..4c0ff5a00 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -37,9 +37,9 @@ - `lifecycle_fuel_cost_after_tax` Lifecycle fuel cost in present value, after tax - `year_one_fuel_cost_before_tax` Fuel cost over the first year, before considering tax benefits - `annual_fuel_consumption_gal` Gallons of fuel used in each year -- `production_to_battery_series_kw` Vector of power sent to battery in year one -- `production_to_grid_series_kw` Vector of power sent to grid in year one -- `production_to_load_series_kw` Vector of power sent to load in year one +- `electric_to_battery_series_kw` Vector of power sent to battery in year one +- `electric_to_grid_series_kw` Vector of power sent to grid in year one +- `electric_to_load_series_kw` Vector of power sent to load in year one - `annual_energy_produced_kwh` Average annual energy produced over analysis period !!! note "'Series' and 'Annual' energy outputs are average annual" @@ -73,19 +73,19 @@ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ else generatorToBatt = zeros(length(p.time_steps)) end - r["production_to_battery_series_kw"] = round.(value.(generatorToBatt), digits=3) + r["electric_to_battery_series_kw"] = round.(value.(generatorToBatt), digits=3) generatorToGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for t in p.techs.gen, u in p.export_bins_by_tech[t]) ) - r["production_to_grid_series_kw"] = round.(value.(generatorToGrid), digits=3) + r["electric_to_grid_series_kw"] = round.(value.(generatorToGrid), digits=3) generatorToLoad = @expression(m, [ts in p.time_steps], sum(m[:dvRatedProduction][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] for t in p.techs.gen) - generatorToBatt[ts] - generatorToGrid[ts] ) - r["production_to_load_series_kw"] = round.(value.(generatorToLoad), digits=3) + r["electric_to_load_series_kw"] = round.(value.(generatorToLoad), digits=3) GeneratorFuelUsed = @expression(m, sum(m[:dvFuelUsage][t, ts] for t in p.techs.gen, ts in p.time_steps) / KWH_PER_GAL_DIESEL) r["annual_fuel_consumption_gal"] = round(value(GeneratorFuelUsed), digits=2) diff --git a/src/results/pv.jl b/src/results/pv.jl index 114b64349..5c991c45a 100644 --- a/src/results/pv.jl +++ b/src/results/pv.jl @@ -34,10 +34,10 @@ - `year_one_energy_produced_kwh` Energy produced over the first year - `annual_energy_produced_kwh` Average annual energy produced when accounting for degradation - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system -- `production_to_load_series_kw` Vector of power used to meet load over the first year -- `production_to_battery_series_kw` Vector of power used to charge the battery over the first year -- `production_to_grid_series_kw` Vector of power exported to the grid over the first year -- `production_curtailed_series_kw` Vector of power curtailed over the first year +- `electric_to_load_series_kw` Vector of power used to meet load over the first year +- `electric_to_battery_series_kw` Vector of power used to charge the battery over the first year +- `electric_to_grid_series_kw` Vector of power exported to the grid over the first year +- `electric_curtailed_series_kw` Vector of power curtailed over the first year - `annual_energy_exported_kwh` Average annual energy exported to the grid !!! warn @@ -65,27 +65,27 @@ function add_pv_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else PVtoBatt = repeat([0], length(p.time_steps)) end - r["production_to_battery_series_kw"] = round.(value.(PVtoBatt), digits=3) + r["electric_to_battery_series_kw"] = round.(value.(PVtoBatt), digits=3) - r["production_to_grid_series_kw"] = zeros(size(r["production_to_battery_series_kw"])) + r["electric_to_grid_series_kw"] = zeros(size(r["electric_to_battery_series_kw"])) r["annual_energy_exported_kwh"] = 0.0 if !isempty(p.s.electric_tariff.export_bins) PVtoGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for u in p.export_bins_by_tech[t])) - r["production_to_grid_series_kw"] = round.(value.(PVtoGrid), digits=3).data + r["electric_to_grid_series_kw"] = round.(value.(PVtoGrid), digits=3).data r["annual_energy_exported_kwh"] = round( - sum(r["production_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) + sum(r["electric_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) end PVtoCUR = (m[Symbol("dvCurtail"*_n)][t, ts] for ts in p.time_steps) - r["production_curtailed_series_kw"] = round.(value.(PVtoCUR), digits=3) + r["electric_curtailed_series_kw"] = round.(value.(PVtoCUR), digits=3) PVtoLoad = (m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] - - r["production_curtailed_series_kw"][ts] - - r["production_to_grid_series_kw"][ts] - - r["production_to_battery_series_kw"][ts] for ts in p.time_steps + - r["electric_curtailed_series_kw"][ts] + - r["electric_to_grid_series_kw"][ts] + - r["electric_to_battery_series_kw"][ts] for ts in p.time_steps ) - r["production_to_load_series_kw"] = round.(value.(PVtoLoad), digits=3) + r["electric_to_load_series_kw"] = round.(value.(PVtoLoad), digits=3) Year1PvProd = (sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for ts in p.time_steps) * p.hours_per_time_step) r["year_one_energy_produced_kwh"] = round(value(Year1PvProd), digits=0) r["annual_energy_produced_kwh"] = round(r["year_one_energy_produced_kwh"] * p.levelization_factor[t], digits=2) diff --git a/src/results/results.jl b/src/results/results.jl index 3ddbebe9a..004bd7b8e 100644 --- a/src/results/results.jl +++ b/src/results/results.jl @@ -155,7 +155,7 @@ function combine_results(p::REoptInputs, bau::Dict, opt::Dict, bau_scenario::BAU ("ElectricTariff", "year_one_export_benefit_before_tax"), ("ElectricTariff", "year_one_coincident_peak_cost_before_tax"), ("ElectricTariff", "lifecycle_coincident_peak_cost_after_tax"), - ("ElectricUtility", "production_to_load_series_kw"), + ("ElectricUtility", "electric_to_load_series_kw"), ("ElectricUtility", "annual_energy_supplied_kwh"), ("ElectricUtility", "annual_emissions_tonnes_CO2"), ("ElectricUtility", "annual_emissions_tonnes_NOx"), diff --git a/src/results/wind.jl b/src/results/wind.jl index 03468821b..29da05838 100644 --- a/src/results/wind.jl +++ b/src/results/wind.jl @@ -32,13 +32,13 @@ - `size_kw` Optimal Wind capacity [kW] - `lifecycle_om_cost_after_tax` Lifecycle operations and maintenance cost in present value, after tax - `year_one_om_cost_before_tax` Operations and maintenance cost in the first year, before tax benefits -- `production_to_battery_series_kw` Vector of power used to charge the battery over an average year -- `production_to_grid_series_kw` Vector of power exported to the grid over an average year +- `electric_to_battery_series_kw` Vector of power used to charge the battery over an average year +- `electric_to_grid_series_kw` Vector of power exported to the grid over an average year - `annual_energy_exported_kwh` Average annual energy exported to the grid -- `production_to_load_series_kw` Vector of power used to meet load over an average year +- `electric_to_load_series_kw` Vector of power used to meet load over an average year - `annual_energy_produced_kwh` Average annual energy produced - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system -- `production_curtailed_series_kw` Vector of power curtailed over an average year +- `electric_curtailed_series_kw` Vector of power curtailed over an average year !!! note "'Series' and 'Annual' energy outputs are average annual" REopt performs load balances using average annual production values for technologies that include degradation. @@ -62,31 +62,31 @@ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else WindToStorage = zeros(length(p.time_steps)) end - r["production_to_battery_series_kw"] = round.(value.(WindToStorage), digits=3) + r["electric_to_battery_series_kw"] = round.(value.(WindToStorage), digits=3) r["annual_energy_exported_kwh"] = 0.0 if !isempty(p.s.electric_tariff.export_bins) WindToGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for u in p.export_bins_by_tech[t])) - r["production_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3).data + r["electric_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3).data r["annual_energy_exported_kwh"] = round( - sum(r["production_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) + sum(r["electric_to_grid_series_kw"]) * p.hours_per_time_step, digits=0) else WindToGrid = zeros(length(p.time_steps)) end - r["production_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3) + r["electric_to_grid_series_kw"] = round.(value.(WindToGrid), digits=3) WindToCUR = (m[Symbol("dvCurtail"*_n)][t, ts] for ts in p.time_steps) - r["production_curtailed_series_kw"] = round.(value.(WindToCUR), digits=3) + r["electric_curtailed_series_kw"] = round.(value.(WindToCUR), digits=3) TotalHourlyWindProd = value.(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for ts in p.time_steps) WindToLoad =(TotalHourlyWindProd[ts] - - r["production_to_battery_series_kw"][ts] - - r["production_to_grid_series_kw"][ts] - - r["production_curtailed_series_kw"][ts] for ts in p.time_steps + - r["electric_to_battery_series_kw"][ts] + - r["electric_to_grid_series_kw"][ts] + - r["electric_curtailed_series_kw"][ts] for ts in p.time_steps ) - r["production_to_load_series_kw"] = round.(value.(WindToLoad), digits=3) + r["electric_to_load_series_kw"] = round.(value.(WindToLoad), digits=3) AvgWindProd = (sum(TotalHourlyWindProd) * p.hours_per_time_step) * p.levelization_factor[t] r["annual_energy_produced_kwh"] = round(value(AvgWindProd), digits=0) diff --git a/test/runtests.jl b/test/runtests.jl index 5e0a87d00..58f8172af 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -79,7 +79,7 @@ else # run HiGHS tests @test results["PV"]["size_kw"] ≈ 70.3084 atol=0.01 @test results["Financial"]["lcc"] ≈ 430747.0 rtol=1e-5 # with levelization_factor hack the LCC is within 5e-5 of REopt API LCC - @test all(x == 0.0 for x in results["PV"]["production_to_load_series_kw"][1:744]) + @test all(x == 0.0 for x in results["PV"]["electric_to_load_series_kw"][1:744]) end @testset "Blended tariff" begin @@ -109,8 +109,8 @@ else # run HiGHS tests ) results = run_reopt(model, "./scenarios/generator.json") @test results["Generator"]["size_kw"] ≈ 8.13 atol=0.01 - @test (sum(results["Generator"]["production_to_load_series_kw"][i] for i in 1:9) + - sum(results["Generator"]["production_to_load_series_kw"][i] for i in 13:8760)) == 0 + @test (sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 1:9) + + sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 13:8760)) == 0 p = REoptInputs("./scenarios/generator.json") simresults = simulate_outages(results, p) @test simresults["resilience_hours_max"] == 11 diff --git a/test/test_with_cplex.jl b/test/test_with_cplex.jl index 30edbc150..ebd5dc0db 100644 --- a/test/test_with_cplex.jl +++ b/test/test_with_cplex.jl @@ -49,8 +49,8 @@ check to make sure that PV does NOT export unless the site load is met first for inputs = REoptInputs(s) results = run_reopt(model, inputs) - @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["production_to_load_series_kw"][1:744]) - if results["PV"]["production_to_grid_series_kw"][i] > 0) + @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["electric_to_load_series_kw"][1:744]) + if results["PV"]["electric_to_grid_series_kw"][i] > 0) end diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index d5274d565..5f5115dd1 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -416,8 +416,8 @@ check to make sure that PV does NOT export unless the site load is met first for inputs = REoptInputs(s) results = run_reopt(model, inputs) - @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["production_to_load_series_kw"][1:744]) - if results["PV"]["production_to_grid_series_kw"][i] > 0) + @test all(x == 0.0 for (i,x) in enumerate(results["ElectricUtility"]["electric_to_load_series_kw"][1:744]) + if results["PV"]["electric_to_grid_series_kw"][i] > 0) end @testset "Solar and ElectricStorage w/BAU and degradation" begin @@ -473,8 +473,8 @@ end p = REoptInputs("./scenarios/generator.json") results = run_reopt([m1,m2], p) @test results["Generator"]["size_kw"] ≈ 8.13 atol=0.01 - @test (sum(results["Generator"]["production_to_load_series_kw"][i] for i in 1:9) + - sum(results["Generator"]["production_to_load_series_kw"][i] for i in 13:8760)) == 0 + @test (sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 1:9) + + sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 13:8760)) == 0 @test results["ElectricLoad"]["bau_critical_load_met"] == false @test results["ElectricLoad"]["bau_critical_load_met_time_steps"] == 0 @@ -1120,7 +1120,7 @@ end f["lifecycle_outage_cost"] + f["lifecycle_MG_upgrade_and_fuel_cost"] - f["lifecycle_production_incentive_after_tax"] ≈ f["lcc"] atol=1.0 - windOR = sum(results["Wind"]["production_to_load_series_kw"] * post["Wind"]["operating_reserve_required_fraction"]) + windOR = sum(results["Wind"]["electric_to_load_series_kw"] * post["Wind"]["operating_reserve_required_fraction"]) loadOR = sum(post["ElectricLoad"]["loads_kw"] * scen.electric_load.operating_reserve_required_fraction) @test sum(results["ElectricLoad"]["offgrid_annual_oper_res_required_series_kwh"]) ≈ loadOR + windOR atol=1.0 From 04ff39f3136e284d06fb169fbf6294ad9fb8cafc Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:26:50 -0500 Subject: [PATCH 22/29] remove note --- src/results/absorption_chiller.jl | 4 ---- src/results/existing_chiller.jl | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/results/absorption_chiller.jl b/src/results/absorption_chiller.jl index de8cfa209..094f6f851 100644 --- a/src/results/absorption_chiller.jl +++ b/src/results/absorption_chiller.jl @@ -39,10 +39,6 @@ - `electric_consumption_series_kw` - `annual_electric_consumption_kwh` -!!! note "'Series' and 'Annual' energy outputs are average annual" - REopt performs load balances using average annual production values for technologies that include degradation. - Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. - """ function add_absorption_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") # Adds the `AbsorptionChiller` results to the dictionary passed back from `run_reopt` using the solved model `m` and the `REoptInputs` for node `_n`. diff --git a/src/results/existing_chiller.jl b/src/results/existing_chiller.jl index 74e95d145..e2cf9e5f2 100644 --- a/src/results/existing_chiller.jl +++ b/src/results/existing_chiller.jl @@ -35,10 +35,6 @@ - `annual_electric_consumption_kwh` - `annual_thermal_production_tonhour` -!!! note "'Series' and 'Annual' energy outputs are average annual" - REopt performs load balances using average annual production values for technologies that include degradation. - Therefore, all timeseries (`_series`) and `annual_` results should be interpretted as energy outputs averaged over the analysis period. - """ function add_existing_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") r = Dict{String, Any}() From ef7ea75531c6aa882513c7ad382507f9dbc9e9b4 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:33:43 -0500 Subject: [PATCH 23/29] waste heat --> curtailed thermal --- src/results/chp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/results/chp.jl b/src/results/chp.jl index c916934db..56d074ef7 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -33,7 +33,7 @@ - `size_supplemental_firing_kw` Power capacity of CHP supplementary firing system [kW] - `annual_fuel_consumption_mmbtu` Fuel consumed in a year [MMBtu] - `annual_electric_production_kwh` Electric energy produced in a year [kWh] -- `annual_thermal_production_mmbtu` Thermal energy produced in a year (not including waste heat) [MMBtu] +- `annual_thermal_production_mmbtu` Thermal energy produced in a year (not including curtailed thermal) [MMBtu] - `electric_production_series_kw` Electric power production time-series array [kW] - `electric_to_grid_series_kw` Electric power exported time-series array [kW] - `electric_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] From 5f0f0eac62d26ee0af5efc1046910f3c4913747a Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:49:06 -0500 Subject: [PATCH 24/29] make storage outputs consistent --- src/outagesim/backup_reliability.jl | 2 +- src/outagesim/outage_simulator.jl | 2 +- src/results/absorption_chiller.jl | 4 ++-- src/results/boiler.jl | 4 ++-- src/results/chp.jl | 8 ++++---- src/results/electric_utility.jl | 4 ++-- src/results/existing_boiler.jl | 4 ++-- src/results/existing_chiller.jl | 4 ++-- src/results/generator.jl | 4 ++-- src/results/pv.jl | 8 ++++---- src/results/steam_turbine.jl | 8 ++++---- src/results/wind.jl | 6 +++--- test/test_with_xpress.jl | 8 ++++---- 13 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/outagesim/backup_reliability.jl b/src/outagesim/backup_reliability.jl index dc33fe105..48d58f7cc 100644 --- a/src/outagesim/backup_reliability.jl +++ b/src/outagesim/backup_reliability.jl @@ -456,7 +456,7 @@ function backup_reliability_inputs(d::Dict, p::REoptInputs; r::Dict = Dict())::D pv_kw_ac_hourly = zero_array if "PV" in keys(d) pv_kw_ac_hourly = ( - get(d["PV"], "electric_to_battery_series_kw", zero_array) + get(d["PV"], "electric_to_storage_series_kw", zero_array) + get(d["PV"], "electric_curtailed_series_kw", zero_array) + get(d["PV"], "electric_to_load_series_kw", zero_array) + get(d["PV"], "electric_to_grid_series_kw", zero_array) diff --git a/src/outagesim/outage_simulator.jl b/src/outagesim/outage_simulator.jl index 9475da3fd..713595c18 100644 --- a/src/outagesim/outage_simulator.jl +++ b/src/outagesim/outage_simulator.jl @@ -259,7 +259,7 @@ function simulate_outages(d::Dict, p::REoptInputs; microgrid_only::Bool=false) pv_kw_ac_hourly = zeros(length(p.time_steps)) if "PV" in keys(d) pv_kw_ac_hourly = ( - get(d["PV"], "electric_to_battery_series_kw", zeros(length(p.time_steps))) + get(d["PV"], "electric_to_storage_series_kw", zeros(length(p.time_steps))) + get(d["PV"], "electric_curtailed_series_kw", zeros(length(p.time_steps))) + get(d["PV"], "electric_to_load_series_kw", zeros(length(p.time_steps))) + get(d["PV"], "electric_to_grid_series_kw", zeros(length(p.time_steps))) diff --git a/src/results/absorption_chiller.jl b/src/results/absorption_chiller.jl index 094f6f851..66b1fccc9 100644 --- a/src/results/absorption_chiller.jl +++ b/src/results/absorption_chiller.jl @@ -31,7 +31,7 @@ `AbsorptionChiller` results keys: - `size_kw` # Optimal power capacity size of the absorption chiller system [kW] - `size_ton` -- `thermal_to_tes_series_ton` +- `thermal_to_storage_series_ton` - `thermal_to_load_series_ton` - `thermal_consumption_series_mmbtu_per_hour` - `annual_thermal_consumption_mmbtu` @@ -55,7 +55,7 @@ function add_absorption_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d r["size_ton"] = r["size_kw"] / KWH_THERMAL_PER_TONHOUR @expression(m, ABSORPCHLtoTESKW[ts in p.time_steps], sum(m[:dvProductionToStorage][b,t,ts] for b in p.s.storage.types.cold, t in p.techs.absorption_chiller)) - r["thermal_to_tes_series_ton"] = round.(value.(ABSORPCHLtoTESKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) + r["thermal_to_storage_series_ton"] = round.(value.(ABSORPCHLtoTESKW) ./ KWH_THERMAL_PER_TONHOUR, digits=5) @expression(m, ABSORPCHLtoLoadKW[ts in p.time_steps], sum(m[:dvThermalProduction][t,ts] for t in p.techs.absorption_chiller) - ABSORPCHLtoTESKW[ts]) diff --git a/src/results/boiler.jl b/src/results/boiler.jl index b6e84b701..c353c7371 100644 --- a/src/results/boiler.jl +++ b/src/results/boiler.jl @@ -34,7 +34,7 @@ - `annual_fuel_consumption_mmbtu` # Fuel consumed in a year [MMBtu] - `thermal_production_series_mmbtu_per_hour` # Thermal energy production series [MMBtu/hr] - `annual_thermal_production_mmbtu` # Thermal energy produced in a year [MMBtu] -- `thermal_to_tes_series_mmbtu_per_hour` # Thermal power production to HotThermalStorage series [MMBtu/hr] +- `thermal_to_storage_series_mmbtu_per_hour` # Thermal power production to HotThermalStorage series [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` # Thermal power production to SteamTurbine series [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` # Thermal power production to serve the heating load series [MMBtu/hr] - `lifecycle_fuel_cost_after_tax` # Life cycle fuel cost [\$] @@ -65,7 +65,7 @@ function add_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n=" else BoilerToHotTESKW = zeros(length(p.time_steps)) end - r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) + r["thermal_to_storage_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) if !isempty(p.techs.steam_turbine) && p.s.boiler.can_supply_steam_turbine @expression(m, BoilerToSteamTurbine[ts in p.time_steps], m[:dvThermalToSteamTurbine]["Boiler",ts]) diff --git a/src/results/chp.jl b/src/results/chp.jl index 56d074ef7..9bef621f3 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -36,9 +36,9 @@ - `annual_thermal_production_mmbtu` Thermal energy produced in a year (not including curtailed thermal) [MMBtu] - `electric_production_series_kw` Electric power production time-series array [kW] - `electric_to_grid_series_kw` Electric power exported time-series array [kW] -- `electric_to_battery_series_kw` Electric power to charge the battery storage time-series array [kW] +- `electric_to_storage_series_kw` Electric power to charge the battery storage time-series array [kW] - `electric_to_load_series_kw` Electric power to serve the electric load time-series array [kW] -- `thermal_to_tes_series_mmbtu_per_hour` Thermal power to TES time-series array [MMBtu/hr] +- `thermal_to_storage_series_mmbtu_per_hour` Thermal power to TES time-series array [MMBtu/hr] - `thermal_curtailed_series_mmbtu_per_hour` Thermal power wasted/unused/vented time-series array [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` Thermal power to serve the heating load time-series array [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` Thermal (steam) power to steam turbine time-series array [MMBtu/hr] @@ -91,7 +91,7 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else CHPtoBatt = zeros(length(p.time_steps)) end - r["electric_to_battery_series_kw"] = round.(value.(CHPtoBatt), digits=3) + r["electric_to_storage_series_kw"] = round.(value.(CHPtoBatt), digits=3) @expression(m, CHPtoLoad[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] for t in p.techs.chp) - CHPtoBatt[ts] - CHPtoGrid[ts]) @@ -103,7 +103,7 @@ function add_chp_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else CHPtoHotTES = zeros(length(p.time_steps)) end - r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(CHPtoHotTES / KWH_PER_MMBTU), digits=5) + r["thermal_to_storage_series_mmbtu_per_hour"] = round.(value.(CHPtoHotTES / KWH_PER_MMBTU), digits=5) @expression(m, CHPThermalToWasteKW[ts in p.time_steps], sum(m[Symbol("dvProductionToWaste"*_n)][t,ts] for t in p.techs.chp)) r["thermal_curtailed_series_mmbtu_per_hour"] = round.(value.(CHPThermalToWasteKW) / KWH_PER_MMBTU, digits=5) diff --git a/src/results/electric_utility.jl b/src/results/electric_utility.jl index fa1d5e0d9..236b6193f 100644 --- a/src/results/electric_utility.jl +++ b/src/results/electric_utility.jl @@ -31,7 +31,7 @@ `ElectricUtility` results keys: - `annual_energy_supplied_kwh` Total energy supplied from the grid in an average year. - `electric_to_load_series_kw` Vector of power drawn from the grid to serve load. -- `electric_to_battery_series_kw` Vector of power drawn from the grid to charge the battery. +- `electric_to_storage_series_kw` Vector of power drawn from the grid to charge the battery. - `annual_emissions_tonnes_CO2` # Total tons of CO2 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `annual_emissions_tonnes_NOx` # Total tons of NOx emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. - `annual_emissions_tonnes_SO2` # Total tons of SO2 emissions associated with the site's grid-purchased electricity in an average year. If include_exported_elec_emissions_in_total is False, this value only reflects grid purchaes. Otherwise, it accounts for emissions offset from any export to the grid. @@ -71,7 +71,7 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, end r["electric_to_load_series_kw"] = round.(value.(GridToLoad), digits=3) - r["electric_to_battery_series_kw"] = round.(value.(GridToBatt), digits=3) + r["electric_to_storage_series_kw"] = round.(value.(GridToBatt), digits=3) if _n=="" #only output emissions results if not a multinode model r["annual_emissions_tonnes_CO2"] = round(value(m[:yr1_emissions_from_elec_grid_net_if_selected_lbs_CO2]*TONNE_PER_LB), digits=2) diff --git a/src/results/existing_boiler.jl b/src/results/existing_boiler.jl index 32b08e001..bcc50f469 100644 --- a/src/results/existing_boiler.jl +++ b/src/results/existing_boiler.jl @@ -33,7 +33,7 @@ - `annual_fuel_consumption_mmbtu` - `thermal_production_series_mmbtu_per_hour` - `annual_thermal_production_mmbtu` -- `thermal_to_tes_series_mmbtu_per_hour` +- `thermal_to_storage_series_mmbtu_per_hour` - `thermal_to_steamturbine_series_mmbtu_per_hour` - `thermal_to_load_series_mmbtu_per_hour` - `lifecycle_fuel_cost_after_tax` @@ -62,7 +62,7 @@ function add_existing_boiler_results(m::JuMP.AbstractModel, p::REoptInputs, d::D else BoilerToHotTESKW = zeros(length(p.time_steps)) end - r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) + r["thermal_to_storage_series_mmbtu_per_hour"] = round.(value.(BoilerToHotTESKW / KWH_PER_MMBTU), digits=3) if !isempty(p.techs.steam_turbine) && p.s.existing_boiler.can_supply_steam_turbine @expression(m, BoilerToSteamTurbineKW[ts in p.time_steps], m[:dvThermalToSteamTurbine]["ExistingBoiler",ts]) diff --git a/src/results/existing_chiller.jl b/src/results/existing_chiller.jl index e2cf9e5f2..366c5fce8 100644 --- a/src/results/existing_chiller.jl +++ b/src/results/existing_chiller.jl @@ -29,7 +29,7 @@ # ********************************************************************************* """ `ExistingChiller` results keys: -- `thermal_to_tes_series_ton` +- `thermal_to_storage_series_ton` - `thermal_to_load_series_ton` - `year_one_electric_consumption_series` - `annual_electric_consumption_kwh` @@ -42,7 +42,7 @@ function add_existing_chiller_results(m::JuMP.AbstractModel, p::REoptInputs, d:: @expression(m, ELECCHLtoTES[ts in p.time_steps], sum(m[:dvProductionToStorage][b,"ExistingChiller",ts] for b in p.s.storage.types.cold) ) - r["thermal_to_tes_series_ton"] = round.(value.(ELECCHLtoTES / KWH_THERMAL_PER_TONHOUR), digits=3) + r["thermal_to_storage_series_ton"] = round.(value.(ELECCHLtoTES / KWH_THERMAL_PER_TONHOUR), digits=3) @expression(m, ELECCHLtoLoad[ts in p.time_steps], sum(m[:dvThermalProduction]["ExistingChiller", ts]) diff --git a/src/results/generator.jl b/src/results/generator.jl index 4c0ff5a00..151704be5 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -37,7 +37,7 @@ - `lifecycle_fuel_cost_after_tax` Lifecycle fuel cost in present value, after tax - `year_one_fuel_cost_before_tax` Fuel cost over the first year, before considering tax benefits - `annual_fuel_consumption_gal` Gallons of fuel used in each year -- `electric_to_battery_series_kw` Vector of power sent to battery in year one +- `electric_to_storage_series_kw` Vector of power sent to battery in year one - `electric_to_grid_series_kw` Vector of power sent to grid in year one - `electric_to_load_series_kw` Vector of power sent to load in year one - `annual_energy_produced_kwh` Average annual energy produced over analysis period @@ -73,7 +73,7 @@ function add_generator_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _ else generatorToBatt = zeros(length(p.time_steps)) end - r["electric_to_battery_series_kw"] = round.(value.(generatorToBatt), digits=3) + r["electric_to_storage_series_kw"] = round.(value.(generatorToBatt), digits=3) generatorToGrid = @expression(m, [ts in p.time_steps], sum(m[:dvProductionToGrid][t, u, ts] for t in p.techs.gen, u in p.export_bins_by_tech[t]) diff --git a/src/results/pv.jl b/src/results/pv.jl index 5c991c45a..d5b775398 100644 --- a/src/results/pv.jl +++ b/src/results/pv.jl @@ -35,7 +35,7 @@ - `annual_energy_produced_kwh` Average annual energy produced when accounting for degradation - `lcoe_per_kwh` Levelized Cost of Energy produced by the PV system - `electric_to_load_series_kw` Vector of power used to meet load over the first year -- `electric_to_battery_series_kw` Vector of power used to charge the battery over the first year +- `electric_to_storage_series_kw` Vector of power used to charge the battery over the first year - `electric_to_grid_series_kw` Vector of power exported to the grid over the first year - `electric_curtailed_series_kw` Vector of power curtailed over the first year - `annual_energy_exported_kwh` Average annual energy exported to the grid @@ -65,9 +65,9 @@ function add_pv_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else PVtoBatt = repeat([0], length(p.time_steps)) end - r["electric_to_battery_series_kw"] = round.(value.(PVtoBatt), digits=3) + r["electric_to_storage_series_kw"] = round.(value.(PVtoBatt), digits=3) - r["electric_to_grid_series_kw"] = zeros(size(r["electric_to_battery_series_kw"])) + r["electric_to_grid_series_kw"] = zeros(size(r["electric_to_storage_series_kw"])) r["annual_energy_exported_kwh"] = 0.0 if !isempty(p.s.electric_tariff.export_bins) PVtoGrid = @expression(m, [ts in p.time_steps], @@ -83,7 +83,7 @@ function add_pv_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") PVtoLoad = (m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] * p.levelization_factor[t] - r["electric_curtailed_series_kw"][ts] - r["electric_to_grid_series_kw"][ts] - - r["electric_to_battery_series_kw"][ts] for ts in p.time_steps + - r["electric_to_storage_series_kw"][ts] for ts in p.time_steps ) r["electric_to_load_series_kw"] = round.(value.(PVtoLoad), digits=3) Year1PvProd = (sum(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for ts in p.time_steps) * p.hours_per_time_step) diff --git a/src/results/steam_turbine.jl b/src/results/steam_turbine.jl index 13210039b..68886e45f 100644 --- a/src/results/steam_turbine.jl +++ b/src/results/steam_turbine.jl @@ -36,9 +36,9 @@ - `thermal_consumption_series_mmbtu_per_hour` Thermal (steam) energy consumption series [MMBtu/hr] - `electric_production_series_kw` Electric power production series [kW] - `electric_to_grid_series_kw` Electric power exported to grid series [kW] -- `electric_to_battery_series_kw` Electric power to charge the battery series [kW] +- `electric_to_storage_series_kw` Electric power to charge the battery series [kW] - `electric_to_load_series_kw` Electric power to serve load series [kW] -- `thermal_to_tes_series_mmbtu_per_hour` Thermal production to charge the HotThermalStorage series [MMBtu/hr] +- `thermal_to_storage_series_mmbtu_per_hour` Thermal production to charge the HotThermalStorage series [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` Thermal production to serve the heating load SERVICES [MMBtu/hr] !!! note "'Series' and 'Annual' energy outputs are average annual" @@ -82,7 +82,7 @@ function add_steam_turbine_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dic else SteamTurbinetoBatt = zeros(length(p.time_steps)) end - r["electric_to_battery_series_kw"] = round.(value.(SteamTurbinetoBatt), digits=3) + r["electric_to_storage_series_kw"] = round.(value.(SteamTurbinetoBatt), digits=3) @expression(m, SteamTurbinetoLoad[ts in p.time_steps], sum(m[Symbol("dvRatedProduction"*_n)][t, ts] * p.production_factor[t, ts] for t in p.techs.steam_turbine) - SteamTurbinetoBatt[ts] - SteamTurbinetoGrid[ts]) @@ -93,7 +93,7 @@ function add_steam_turbine_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dic else SteamTurbinetoHotTESKW = zeros(length(p.time_steps)) end - r["thermal_to_tes_series_mmbtu_per_hour"] = round.(value.(SteamTurbinetoHotTESKW) ./ KWH_PER_MMBTU, digits=5) + r["thermal_to_storage_series_mmbtu_per_hour"] = round.(value.(SteamTurbinetoHotTESKW) ./ KWH_PER_MMBTU, digits=5) @expression(m, SteamTurbineThermalToLoadKW[ts in p.time_steps], sum(m[Symbol("dvThermalProduction"*_n)][t,ts] for t in p.techs.steam_turbine) - SteamTurbinetoHotTESKW[ts]) r["thermal_to_load_series_mmbtu_per_hour"] = round.(value.(SteamTurbineThermalToLoadKW) ./ KWH_PER_MMBTU, digits=5) diff --git a/src/results/wind.jl b/src/results/wind.jl index 29da05838..74c1820f6 100644 --- a/src/results/wind.jl +++ b/src/results/wind.jl @@ -32,7 +32,7 @@ - `size_kw` Optimal Wind capacity [kW] - `lifecycle_om_cost_after_tax` Lifecycle operations and maintenance cost in present value, after tax - `year_one_om_cost_before_tax` Operations and maintenance cost in the first year, before tax benefits -- `electric_to_battery_series_kw` Vector of power used to charge the battery over an average year +- `electric_to_storage_series_kw` Vector of power used to charge the battery over an average year - `electric_to_grid_series_kw` Vector of power exported to the grid over an average year - `annual_energy_exported_kwh` Average annual energy exported to the grid - `electric_to_load_series_kw` Vector of power used to meet load over an average year @@ -62,7 +62,7 @@ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") else WindToStorage = zeros(length(p.time_steps)) end - r["electric_to_battery_series_kw"] = round.(value.(WindToStorage), digits=3) + r["electric_to_storage_series_kw"] = round.(value.(WindToStorage), digits=3) r["annual_energy_exported_kwh"] = 0.0 if !isempty(p.s.electric_tariff.export_bins) @@ -82,7 +82,7 @@ function add_wind_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dict; _n="") TotalHourlyWindProd = value.(m[Symbol("dvRatedProduction"*_n)][t,ts] * p.production_factor[t, ts] for ts in p.time_steps) WindToLoad =(TotalHourlyWindProd[ts] - - r["electric_to_battery_series_kw"][ts] + - r["electric_to_storage_series_kw"][ts] - r["electric_to_grid_series_kw"][ts] - r["electric_curtailed_series_kw"][ts] for ts in p.time_steps ) diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index 5f5115dd1..ebd9b5a79 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -780,9 +780,9 @@ end # Cooling outputs cooling_elecchl_tons_to_load_series = results["ExistingChiller"]["thermal_to_load_series_ton"] - cooling_elecchl_tons_to_tes_series = results["ExistingChiller"]["thermal_to_tes_series_ton"] + cooling_elecchl_tons_to_tes_series = results["ExistingChiller"]["thermal_to_storage_series_ton"] cooling_absorpchl_tons_to_load_series = results["AbsorptionChiller"]["thermal_to_load_series_ton"] - cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["thermal_to_tes_series_ton"] + cooling_absorpchl_tons_to_tes_series = results["AbsorptionChiller"]["thermal_to_storage_series_ton"] cooling_tonhour_to_load_tech_total = sum(cooling_elecchl_tons_to_load_series) + sum(cooling_absorpchl_tons_to_load_series) cooling_tonhour_to_tes_total = sum(cooling_elecchl_tons_to_tes_series) + sum(cooling_absorpchl_tons_to_tes_series) cooling_tes_tons_to_load_series = results["ColdThermalStorage"]["storage_to_load_series_ton"] @@ -806,9 +806,9 @@ end boiler_fuel_consumption_calculated = results["ExistingBoiler"]["annual_fuel_consumption_mmbtu"] boiler_thermal_series = results["ExistingBoiler"]["thermal_production_series_mmbtu_per_hour"] boiler_to_load_series = results["ExistingBoiler"]["thermal_to_load_series_mmbtu_per_hour"] - boiler_thermal_to_tes_series = results["ExistingBoiler"]["thermal_to_tes_series_mmbtu_per_hour"] + boiler_thermal_to_tes_series = results["ExistingBoiler"]["thermal_to_storage_series_mmbtu_per_hour"] chp_thermal_to_load_series = results["CHP"]["thermal_to_load_series_mmbtu_per_hour"] - chp_thermal_to_tes_series = results["CHP"]["thermal_to_tes_series_mmbtu_per_hour"] + chp_thermal_to_tes_series = results["CHP"]["thermal_to_storage_series_mmbtu_per_hour"] chp_thermal_to_waste_series = results["CHP"]["thermal_curtailed_series_mmbtu_per_hour"] absorpchl_thermal_series = results["AbsorptionChiller"]["thermal_consumption_series_mmbtu_per_hour"] hot_tes_mmbtu_per_hour_to_load_series = results["HotThermalStorage"]["storage_to_load_series_mmbtu_per_hour"] From ea35e45fb08623b40b12659ce9bbeb05127c6b71 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 13:57:58 -0500 Subject: [PATCH 25/29] Clarify some storage comments --- src/results/absorption_chiller.jl | 4 ++-- src/results/boiler.jl | 2 +- src/results/chp.jl | 2 +- src/results/existing_boiler.jl | 2 +- src/results/existing_chiller.jl | 4 ++-- src/results/generator.jl | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/results/absorption_chiller.jl b/src/results/absorption_chiller.jl index 66b1fccc9..601df09a0 100644 --- a/src/results/absorption_chiller.jl +++ b/src/results/absorption_chiller.jl @@ -31,8 +31,8 @@ `AbsorptionChiller` results keys: - `size_kw` # Optimal power capacity size of the absorption chiller system [kW] - `size_ton` -- `thermal_to_storage_series_ton` -- `thermal_to_load_series_ton` +- `thermal_to_storage_series_ton` # Thermal production to ColdThermalStorage +- `thermal_to_load_series_ton` # Thermal production to cooling load - `thermal_consumption_series_mmbtu_per_hour` - `annual_thermal_consumption_mmbtu` - `annual_thermal_production_tonhour` diff --git a/src/results/boiler.jl b/src/results/boiler.jl index c353c7371..e15660211 100644 --- a/src/results/boiler.jl +++ b/src/results/boiler.jl @@ -34,7 +34,7 @@ - `annual_fuel_consumption_mmbtu` # Fuel consumed in a year [MMBtu] - `thermal_production_series_mmbtu_per_hour` # Thermal energy production series [MMBtu/hr] - `annual_thermal_production_mmbtu` # Thermal energy produced in a year [MMBtu] -- `thermal_to_storage_series_mmbtu_per_hour` # Thermal power production to HotThermalStorage series [MMBtu/hr] +- `thermal_to_storage_series_mmbtu_per_hour` # Thermal power production to TES (HotThermalStorage) series [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` # Thermal power production to SteamTurbine series [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` # Thermal power production to serve the heating load series [MMBtu/hr] - `lifecycle_fuel_cost_after_tax` # Life cycle fuel cost [\$] diff --git a/src/results/chp.jl b/src/results/chp.jl index 9bef621f3..007185c6a 100644 --- a/src/results/chp.jl +++ b/src/results/chp.jl @@ -38,7 +38,7 @@ - `electric_to_grid_series_kw` Electric power exported time-series array [kW] - `electric_to_storage_series_kw` Electric power to charge the battery storage time-series array [kW] - `electric_to_load_series_kw` Electric power to serve the electric load time-series array [kW] -- `thermal_to_storage_series_mmbtu_per_hour` Thermal power to TES time-series array [MMBtu/hr] +- `thermal_to_storage_series_mmbtu_per_hour` Thermal power to TES (HotThermalStorage) time-series array [MMBtu/hr] - `thermal_curtailed_series_mmbtu_per_hour` Thermal power wasted/unused/vented time-series array [MMBtu/hr] - `thermal_to_load_series_mmbtu_per_hour` Thermal power to serve the heating load time-series array [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` Thermal (steam) power to steam turbine time-series array [MMBtu/hr] diff --git a/src/results/existing_boiler.jl b/src/results/existing_boiler.jl index bcc50f469..de5b11310 100644 --- a/src/results/existing_boiler.jl +++ b/src/results/existing_boiler.jl @@ -33,7 +33,7 @@ - `annual_fuel_consumption_mmbtu` - `thermal_production_series_mmbtu_per_hour` - `annual_thermal_production_mmbtu` -- `thermal_to_storage_series_mmbtu_per_hour` +- `thermal_to_storage_series_mmbtu_per_hour` # Thermal power production to TES (HotThermalStorage) series [MMBtu/hr] - `thermal_to_steamturbine_series_mmbtu_per_hour` - `thermal_to_load_series_mmbtu_per_hour` - `lifecycle_fuel_cost_after_tax` diff --git a/src/results/existing_chiller.jl b/src/results/existing_chiller.jl index 366c5fce8..0d4ef7b35 100644 --- a/src/results/existing_chiller.jl +++ b/src/results/existing_chiller.jl @@ -29,8 +29,8 @@ # ********************************************************************************* """ `ExistingChiller` results keys: -- `thermal_to_storage_series_ton` -- `thermal_to_load_series_ton` +- `thermal_to_storage_series_ton` # Thermal production to ColdThermalStorage +- `thermal_to_load_series_ton` # Thermal production to cooling load - `year_one_electric_consumption_series` - `annual_electric_consumption_kwh` - `annual_thermal_production_tonhour` diff --git a/src/results/generator.jl b/src/results/generator.jl index 151704be5..f1c24f120 100644 --- a/src/results/generator.jl +++ b/src/results/generator.jl @@ -37,9 +37,9 @@ - `lifecycle_fuel_cost_after_tax` Lifecycle fuel cost in present value, after tax - `year_one_fuel_cost_before_tax` Fuel cost over the first year, before considering tax benefits - `annual_fuel_consumption_gal` Gallons of fuel used in each year -- `electric_to_storage_series_kw` Vector of power sent to battery in year one -- `electric_to_grid_series_kw` Vector of power sent to grid in year one -- `electric_to_load_series_kw` Vector of power sent to load in year one +- `electric_to_storage_series_kw` Vector of power sent to battery in an average year +- `electric_to_grid_series_kw` Vector of power sent to grid in an average year +- `electric_to_load_series_kw` Vector of power sent to load in an average year - `annual_energy_produced_kwh` Average annual energy produced over analysis period !!! note "'Series' and 'Annual' energy outputs are average annual" From 23e082cd6b6e40b4460e2b72d198b240335df4b6 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 14:03:09 -0500 Subject: [PATCH 26/29] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 114659abe..79edc0ff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,9 +25,11 @@ Classify the change according to the following categories: ## Develop - 2022-12-19 ### Changed -- Major name change overall for outputs/results. Changed energy-related outputs with "year_one" in name to "annual" to reflect that they are actually average annual output values. Changed any "average_annual" naming to "annual" to simplify. +- Major name change overall for outputs/results. Changed energy-related outputs with "year_one" in name to "annual" to reflect that they are actually average annual output values. Changed any "average_annual" naming to "annual" to simplify. Changed `to_tes` and `to_battery` outputs to `to_storage` for consistency ### Added - Added **thermal_production_series_mmbtu_per_hour** to CHP results. +### Removed +- Removed `Wind` and `Generator` outputs `year_one_energy_produced_kwh` since these techs do not include degradation ## v0.23.0 ### Added - Add **REoptLogger** type of global logger with a standard out to the console and to a dictionary From 55e026e6b85bfc03eef285628e2f6ed5ad296a28 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 30 Dec 2022 14:27:58 -0500 Subject: [PATCH 27/29] Update test_with_xpress.jl --- test/test_with_xpress.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index ebd9b5a79..6d318f9ea 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -1490,7 +1490,7 @@ end results = run_reopt(m, inputs) thermal_techs = ["ExistingBoiler", "CHP", "SteamTurbine"] - thermal_loads = ["load", "tes", "steamturbine", "waste"] # We don't track AbsorptionChiller thermal consumption by tech + thermal_loads = ["load", "storage", "steamturbine", "waste"] # We don't track AbsorptionChiller thermal consumption by tech tech_to_thermal_load = Dict{Any, Any}() for tech in thermal_techs tech_to_thermal_load[tech] = Dict{Any, Any}() From 200cb3a7dcdba69503e4e9bd28e6c1883c11ced6 Mon Sep 17 00:00:00 2001 From: Bill Becker Date: Fri, 30 Dec 2022 14:24:34 -0700 Subject: [PATCH 28/29] Update AbsorptionChiller docstring to reflect actual behavior --- src/core/absorption_chiller.jl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/core/absorption_chiller.jl b/src/core/absorption_chiller.jl index 8819304f7..6dcf4e4bb 100644 --- a/src/core/absorption_chiller.jl +++ b/src/core/absorption_chiller.jl @@ -31,14 +31,12 @@ """ `AbsorptionChiller` is an optional REopt input with the following keys and default values: ```julia - thermal_consumption_hot_water_or_steam::Union{String, Nothing} = nothing - chp_prime_mover::String = "" + thermal_consumption_hot_water_or_steam::Union{String, Nothing} = nothing # Defaults to "hot_water" if chp_prime_mover or boiler_type are not provided + chp_prime_mover::String = "" # Informs thermal_consumption_hot_water_or_steam if not provided - #Required if neither "thermal_consumption_hot_water_or_steam" nor "chp_prime_mover" nor an ExistingBoiler included in inputs: + # Defaults for fields below are dependent on thermal_consumption_hot_water_or_steam and max cooling load installed_cost_per_ton::Union{Float64, Nothing} = nothing om_cost_per_ton::Union{Float64, Nothing} = nothing - - #Optional min_ton::Float64 = 0.0, max_ton::Float64 = BIG_NUMBER, cop_thermal::Union{Float64, Nothing} = nothing, @@ -48,12 +46,12 @@ macrs_bonus_fraction::Float64 = 0 ``` -!!! note "Required inputs" - To model AbsorptionChiller, you must provide at least one of the following: +!!! Note + To model AbsorptionChiller, there is logic which informs defaults for costs and COP: (i) `thermal_consumption_hot_water_or_steam` from $(HOT_WATER_OR_STEAM), (ii) `chp_prime_mover` from $(PRIME_MOVERS), or - (iii) all of the "custom inputs" defined below. - If `chp_prime_mover` is provided, any missing value from the "custom inputs" will be populated from data/absorption_chiller/defaults.json, + (iii) if (i) and (ii) are not provided, the default `thermal_consumption_hot_water_or_steam` is `hot_water` + The defaults for costs and COP will be populated from data/absorption_chiller/defaults.json, based on the `thermal_consumption_hot_water_or_steam` or `chp_prime_mover`. `boiler_type` is "steam" if `prime_mover` is "combustion_turbine" and is "hot_water" for all other `chp_prime_mover` types. """ From 018d85a66f359b336d9700ff7099a7ffdd25b63f Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 6 Jan 2023 09:48:24 -0700 Subject: [PATCH 29/29] Update CHANGELOG and Project.toml --- CHANGELOG.md | 4 ++-- Project.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79edc0ff7..e26b1b306 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,13 +23,13 @@ Classify the change according to the following categories: ### Deprecated ### Removed -## Develop - 2022-12-19 +## v0.24.0 ### Changed - Major name change overall for outputs/results. Changed energy-related outputs with "year_one" in name to "annual" to reflect that they are actually average annual output values. Changed any "average_annual" naming to "annual" to simplify. Changed `to_tes` and `to_battery` outputs to `to_storage` for consistency ### Added - Added **thermal_production_series_mmbtu_per_hour** to CHP results. ### Removed -- Removed `Wind` and `Generator` outputs `year_one_energy_produced_kwh` since these techs do not include degradation +- Removed `Wind` and `Generator` outputs **year_one_energy_produced_kwh** since these techs do not include degradation ## v0.23.0 ### Added - Add **REoptLogger** type of global logger with a standard out to the console and to a dictionary diff --git a/Project.toml b/Project.toml index bcdd8a152..7ebfdf882 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "REopt" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" authors = ["Nick Laws", "Hallie Dunham ", "Bill Becker ", "Bhavesh Rathod ", "Alex Zolan ", "Amanda Farthing "] -version = "0.23.0" +version = "0.24.0" [deps] ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"