From 1ff7a31a86ae0888889f0fc9420498931ba2d995 Mon Sep 17 00:00:00 2001 From: lixiangk1 <72464565+lixiangk1@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:12:43 -0600 Subject: [PATCH] Update thermal decay variables to match electric storage self-discharge --- src/constraints/storage_constraints.jl | 12 ++++++---- src/core/energy_storage/thermal_storage.jl | 24 ++++++++++++------- test/scenarios/ghp_inputs.json | 4 ++-- .../heat_cool_energy_balance_inputs.json | 4 ++-- test/scenarios/re_emissions_with_thermal.json | 2 +- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/constraints/storage_constraints.jl b/src/constraints/storage_constraints.jl index 1a38ab58e..6af7232ea 100644 --- a/src/constraints/storage_constraints.jl +++ b/src/constraints/storage_constraints.jl @@ -111,11 +111,12 @@ function add_hot_thermal_storage_dispatch_constraints(m, p, b; _n="") @constraint(m, [b in p.s.storage.types.hot, ts in p.time_steps], m[Symbol("dvStoredEnergy"*_n)][b,ts] == m[Symbol("dvStoredEnergy"*_n)][b,ts-1] + (1/p.s.settings.time_steps_per_hour) * ( p.s.storage.attr[b].charge_efficiency * sum(m[Symbol("dvHeatToStorage"*_n)][b,t,q,ts] for t in union(p.techs.heating, p.techs.chp), q in p.heating_loads) - - sum(m[Symbol("dvHeatFromStorage"*_n)][b,q,ts] for q in p.heating_loads) / p.s.storage.attr[b].discharge_efficiency - - p.s.storage.attr[b].thermal_decay_rate_fraction * m[Symbol("dvStorageEnergy"*_n)][b] + sum(m[Symbol("dvHeatFromStorage"*_n)][b,q,ts] for q in p.heating_loads) / p.s.storage.attr[b].discharge_efficiency ) + - (p.s.storage.attr[b].soc_based_per_ts_thermal_decay_fraction * m[Symbol("dvStoredEnergy"*_n)][b, ts]) + - (p.s.storage.attr[b].capacity_based_per_ts_thermal_decay_fraction * m[Symbol("dvStorageEnergy"*_n)][b]) ) - + #Constraint (4n)-1: Dispatch to and from thermal storage is no greater than power capacity @constraint(m, [b in p.s.storage.types.hot, ts in p.time_steps], m[Symbol("dvStoragePower"*_n)][b] >= @@ -154,9 +155,10 @@ function add_cold_thermal_storage_dispatch_constraints(m, p, b; _n="") @constraint(m, ColdTESInventoryCon[b in p.s.storage.types.cold, ts in p.time_steps], m[Symbol("dvStoredEnergy"*_n)][b,ts] == m[Symbol("dvStoredEnergy"*_n)][b,ts-1] + (1/p.s.settings.time_steps_per_hour) * ( sum(p.s.storage.attr[b].charge_efficiency * m[Symbol("dvProductionToStorage"*_n)][b,t,ts] for t in p.techs.cooling) - - m[Symbol("dvDischargeFromStorage"*_n)][b,ts]/p.s.storage.attr[b].discharge_efficiency - - p.s.storage.attr[b].thermal_decay_rate_fraction * m[Symbol("dvStorageEnergy"*_n)][b] + m[Symbol("dvDischargeFromStorage"*_n)][b,ts]/p.s.storage.attr[b].discharge_efficiency ) + - (p.s.storage.attr[b].soc_based_per_ts_thermal_decay_fraction * m[Symbol("dvStoredEnergy"*_n)][b, ts]) + - (p.s.storage.attr[b].capacity_based_per_ts_thermal_decay_fraction * m[Symbol("dvStorageEnergy"*_n)][b]) ) #Constraint (4n)-2: Dispatch to and from thermal storage is no greater than power capacity diff --git a/src/core/energy_storage/thermal_storage.jl b/src/core/energy_storage/thermal_storage.jl index 41ffb6aff..a0703578f 100644 --- a/src/core/energy_storage/thermal_storage.jl +++ b/src/core/energy_storage/thermal_storage.jl @@ -15,7 +15,8 @@ Cold thermal energy storage sytem; specifically, a chilled water system used to soc_min_fraction::Float64 = 0.1 # Minimum allowable TES thermal state of charge soc_init_fraction::Float64 = 0.5 # TES thermal state of charge at first hour of optimization installed_cost_per_gal::Float64 = 1.50 # Thermal energy-based cost of TES (e.g. volume of the tank) - thermal_decay_rate_fraction::Float64 = 0.0004 # Thermal loss (gain) rate as a fraction of energy storage capacity, per hour (frac*energy_capacity/hr = kw_thermal) + soc_based_per_ts_thermal_decay_fraction = 0.0 # Thermal loss (gain) rate as a fraction of energy storage capacity per timestep (frac*energy_capacity = kw_thermal); the provided default is for an hourly thermal loss/gain + capacity_based_per_ts_thermal_decay_fraction = 0.0004 # Thermal loss (gain) rate as a fraction of the energy storaged in each timestep (frac*energy_stored = kw_thermal) om_cost_per_gal::Float64 = 0.0 # Yearly fixed O&M cost dependent on storage energy size macrs_option_years::Int = 7 macrs_bonus_fraction::Float64 = 0.6 @@ -33,7 +34,8 @@ Base.@kwdef struct ColdThermalStorageDefaults <: AbstractThermalStorageDefaults soc_min_fraction::Float64 = 0.1 soc_init_fraction::Float64 = 0.5 installed_cost_per_gal::Float64 = 1.50 - thermal_decay_rate_fraction::Float64 = 0.0004 + soc_based_per_ts_thermal_decay_fraction::Float64 = 0.0 + capacity_based_per_ts_thermal_decay_fraction::Float64 = 0.0004 om_cost_per_gal::Float64 = 0.0 macrs_option_years::Int = 7 macrs_bonus_fraction::Float64 = 0.6 @@ -55,7 +57,8 @@ end soc_min_fraction::Float64 = 0.1 soc_init_fraction::Float64 = 0.5 installed_cost_per_gal::Float64 = 1.50 - thermal_decay_rate_fraction::Float64 = 0.0004 + soc_based_per_ts_thermal_decay_fraction = 0.0 + capacity_based_per_ts_thermal_decay_fraction = 0.0004 om_cost_per_gal::Float64 = 0.0 macrs_option_years::Int = 7 macrs_bonus_fraction::Float64 = 0.6 @@ -76,7 +79,8 @@ Base.@kwdef struct HotThermalStorageDefaults <: AbstractThermalStorageDefaults soc_min_fraction::Float64 = 0.1 soc_init_fraction::Float64 = 0.5 installed_cost_per_gal::Float64 = 1.50 - thermal_decay_rate_fraction::Float64 = 0.0004 + soc_based_per_ts_thermal_decay_fraction::Float64 = 0.0 + capacity_based_per_ts_thermal_decay_fraction::Float64 = 0.0004 om_cost_per_gal::Float64 = 0.0 macrs_option_years::Int = 7 macrs_bonus_fraction::Float64 = 0.6 @@ -105,7 +109,8 @@ struct ColdThermalStorage <: AbstractThermalStorage soc_min_fraction::Float64 soc_init_fraction::Float64 installed_cost_per_gal::Float64 - thermal_decay_rate_fraction::Float64 + soc_based_per_ts_thermal_decay_fraction::Float64 + capacity_based_per_ts_thermal_decay_fraction::Float64 om_cost_per_gal::Float64 macrs_option_years::Int macrs_bonus_fraction::Float64 @@ -154,7 +159,8 @@ struct ColdThermalStorage <: AbstractThermalStorage s.soc_min_fraction, s.soc_init_fraction, s.installed_cost_per_gal, - s.thermal_decay_rate_fraction, + s.soc_based_per_ts_thermal_decay_fraction, + s.capacity_based_per_ts_thermal_decay_fraction, s.om_cost_per_gal, s.macrs_option_years, s.macrs_bonus_fraction, @@ -188,7 +194,8 @@ struct HotThermalStorage <: AbstractThermalStorage soc_min_fraction::Float64 soc_init_fraction::Float64 installed_cost_per_gal::Float64 - thermal_decay_rate_fraction::Float64 + soc_based_per_ts_thermal_decay_fraction::Float64 + capacity_based_per_ts_thermal_decay_fraction::Float64 om_cost_per_gal::Float64 macrs_option_years::Int macrs_bonus_fraction::Float64 @@ -240,7 +247,8 @@ struct HotThermalStorage <: AbstractThermalStorage s.soc_min_fraction, s.soc_init_fraction, s.installed_cost_per_gal, - s.thermal_decay_rate_fraction, + s.soc_based_per_ts_thermal_decay_fraction, + s.capacity_based_per_ts_thermal_decay_fraction, s.om_cost_per_gal, s.macrs_option_years, s.macrs_bonus_fraction, diff --git a/test/scenarios/ghp_inputs.json b/test/scenarios/ghp_inputs.json index 43b816527..abd01faad 100644 --- a/test/scenarios/ghp_inputs.json +++ b/test/scenarios/ghp_inputs.json @@ -59,11 +59,11 @@ "ColdThermalStorage": { "min_gal": 10, "max_gal": 10, - "thermal_decay_rate_fraction": 0.0 + "capacity_based_per_ts_thermal_decay_fraction": 0.0 }, "HotThermalStorage": { "min_gal": 10, "max_gal": 10, - "thermal_decay_rate_fraction": 0.0 + "capacity_based_per_ts_thermal_decay_fraction": 0.0 } } \ No newline at end of file diff --git a/test/scenarios/heat_cool_energy_balance_inputs.json b/test/scenarios/heat_cool_energy_balance_inputs.json index 6d8af917e..30aecc394 100644 --- a/test/scenarios/heat_cool_energy_balance_inputs.json +++ b/test/scenarios/heat_cool_energy_balance_inputs.json @@ -74,13 +74,13 @@ "min_gal": 20000.0, "max_gal": 20000.0, "internal_efficiency_fraction": 0.97, - "thermal_decay_rate_fraction": 0.004 + "capacity_based_per_ts_thermal_decay_fraction": 0.004 }, "ColdThermalStorage":{ "min_gal": 30000.0, "max_gal": 30000.0, "internal_efficiency_fraction": 0.97, - "thermal_decay_rate_fraction": 0.004, + "capacity_based_per_ts_thermal_decay_fraction": 0.004, "soc_init_fraction": 0.1 }, "AbsorptionChiller": { diff --git a/test/scenarios/re_emissions_with_thermal.json b/test/scenarios/re_emissions_with_thermal.json index fbc0346f1..747f1792e 100644 --- a/test/scenarios/re_emissions_with_thermal.json +++ b/test/scenarios/re_emissions_with_thermal.json @@ -79,7 +79,7 @@ "soc_min_fraction": 0.1 , "soc_init_fraction": 0.5 , "installed_cost_per_gal": 3.0 , - "thermal_decay_rate_fraction": 0.004 , + "capacity_based_per_ts_thermal_decay_fraction": 0.004 , "om_cost_per_gal": 0.0 , "macrs_option_years": 0 , "macrs_bonus_fraction": 0.0