diff --git a/src/constraints/load_balance.jl b/src/constraints/load_balance.jl index 057330e55..74121d500 100644 --- a/src/constraints/load_balance.jl +++ b/src/constraints/load_balance.jl @@ -50,6 +50,14 @@ function add_elec_load_balance_constraints(m, p; _n="") + m[Symbol("dvCurtail"*_n)][t, ts] for t in p.techs.elec) + p.s.electric_load.critical_loads_kw[ts] ) + """ + TODO: Do the following, unless a custom critical load series is uploaded?: + + sum(m[Symbol("dvCoolingProduction"*_n)][t, ts] / p.cooling_cop[t][ts] for t in setdiff(p.techs.cooling,p.techs.ghp)) * critical_load_fraction + + sum(m[Symbol("dvHeatingProduction"*_n)][t, q, ts] / p.heating_cop[t][ts] for q in p.heating_loads, t in p.techs.electric_heater) * critical_load_fraction + + p.s.electric_load.loads_kw[ts] * critical_load_fraction + - p.s.cooling_load.loads_kw_thermal[ts] / p.cooling_cop["ExistingChiller"][ts] * critical_load_fraction + + sum(p.ghp_electric_consumption_kw[g,ts] * m[Symbol("binGHP"*_n)][g] for g in p.ghp_options) * critical_load_fraction + """ else # load balancing constraint for off-grid runs @constraint(m, [ts in p.time_steps_without_grid], sum(p.production_factor[t,ts] * p.levelization_factor[t] * m[Symbol("dvRatedProduction"*_n)][t,ts] for t in p.techs.elec) diff --git a/src/results/electric_load.jl b/src/results/electric_load.jl index 457ef4abe..804633772 100644 --- a/src/results/electric_load.jl +++ b/src/results/electric_load.jl @@ -1,9 +1,15 @@ # REoptĀ®, Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/REopt.jl/blob/master/LICENSE. """ `ElectricLoad` results keys: -- `load_series_kw` # vector of BAU site load in every time step. Does not include electric load for any new heating or cooling techs. +- `bau_load_series_kw` # vector of BAU site load in every time step. Does not include electric load for any new heating or cooling techs. Does not adjust for critical load during modeled outages. +- `bau_existing_chiller_load_series_kw` # vector of BAU existing chiller electric load in every time step +- `chiller_load_series_kw` # vector of optimized chiller electric load in every time step +- `electric_heater_load_series_kw` # vector of optimized electric heater load in every time step +- `ghp_load_series_kw` # vector of optimized GHP electric load in every time step +- `load_series_kw` # vector of site electric load in the optimized case in every time step - `critical_load_series_kw` # vector of site critical load in every time step -- `annual_calculated_kwh` # sum of the `load_series_kw`. Does not include electric load for any new heating or cooling techs. +- `bau_annual_calculated_kwh` # sum of `bau_load_series_kw`. Does not include electric load for any new heating or cooling techs. +- `annual_calculated_kwh` # sum of `load_series_kw` - `annual_electric_load_with_thermal_conversions_kwh` # Total end-use electrical load, including electrified heating and cooling end-use load - `offgrid_load_met_series_kw` # vector of electric load met by generation techs, for off-grid scenarios only - `offgrid_load_met_fraction` # percentage of total electric load met on an annual basis, for off-grid scenarios only @@ -24,11 +30,33 @@ function add_electric_load_results(m::JuMP.AbstractModel, p::REoptInputs, d::Dic r = Dict{String, Any}() - r["load_series_kw"] = p.s.electric_load.loads_kw + # BAU Loads + # TODO: bau load series should have critical load spliced in during time_steps_without_grid + r["bau_load_series_kw"] = p.s.electric_load.loads_kw # includes bau_existing_chiller_electric_load_series_kw + r["bau_existing_chiller_load_series_kw"] = p.s.cooling_load.loads_kw_thermal ./ p.cooling_cop["ExistingChiller"] + r["bau_annual_calculated_kwh"] = round(sum(r["bau_load_series_kw"]) / p.s.settings.time_steps_per_hour, digits=2) + r["critical_load_series_kw"] = p.s.electric_load.critical_loads_kw - r["annual_calculated_kwh"] = round( - sum(r["load_series_kw"]) / p.s.settings.time_steps_per_hour, digits=2 - ) + + # Optimized loads + # dvCoolingProduction, dvHeatingProduction are not constrained in time_steps_without_grid + # ghp_electric_consumption_kw is not relevant (?) in time_steps_without_grid + r["chiller_load_series_kw"] = [ + sum(value(m[Symbol("dvCoolingProduction"*_n)][t, ts]) / p.cooling_cop[t][ts] for t in setdiff(p.techs.cooling, p.techs.ghp); init=0.0) + for ts in p.time_steps + ] + r["electric_heater_load_series_kw"] = [ + sum(value(m[Symbol("dvHeatingProduction"*_n)][t, q, ts]) / p.heating_cop[t][ts] for q in p.heating_loads, t in p.techs.electric_heater; init=0.0) + for ts in p.time_steps + ] + r["ghp_load_series_kw"] = [ + sum(p.ghp_electric_consumption_kw[g,ts] * value(m[Symbol("binGHP"*_n)][g]) for g in p.ghp_options; init=0.0) + for ts in p.time_steps + ] + # TODO: splice critical load series into bau loads during time_steps_without_grid? + # TODO: would need to update heating and cooling load reporting too + r["load_series_kw"] = r["bau_load_series_kw"] .- r["bau_existing_chiller_load_series_kw"] .+ r["chiller_load_series_kw"] .+ r["electric_heater_load_series_kw"] .+ r["ghp_load_series_kw"] + r["annual_calculated_kwh"] = round(sum(r["load_series_kw"]) / p.s.settings.time_steps_per_hour, digits=2) load_dict = get_load_metrics( r["load_series_kw"];