Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ghp-to-storage dispatch #391

Merged
merged 6 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ Classify the change according to the following categories:
### Deprecated
### Removed

## Develop 2024-05-09
### Changed
- Updated the GHP testset .json `./test/scenarios/ghp_inputs.json` to include a nominal HotThermalStorage and ColdThermalStorage system.
### Fixed
- Fixed a bug in which the model fails to build when both GHP and either Hot or Cold Thermal Storage are present.

## v. 0.46.0
### Added
- In `src/core/absorption_chiller.jl` struct, added field **heating_load_input** to the AbsorptionChiller struct
Expand Down
16 changes: 15 additions & 1 deletion src/constraints/storage_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function add_hot_thermal_storage_dispatch_constraints(m, p, b; _n="")
if !isempty(p.techs.chp)
if !isempty(p.techs.steam_turbine) && p.s.chp.can_supply_steam_turbine
@constraint(m, CHPTechProductionFlowCon[b in p.s.storage.types.hot, t in p.techs.chp, q in p.heating_loads, ts in p.time_steps],
m[Symbol("dvHeatToStorage"*_n)][b,tq,ts] + m[Symbol("dvProductionToWaste"*_n)][t,q,ts] + m[Symbol("dvThermalToSteamTurbine"*_n)][t,q,ts] <=
m[Symbol("dvHeatToStorage"*_n)][b,t,q,ts] + m[Symbol("dvProductionToWaste"*_n)][t,q,ts] + m[Symbol("dvThermalToSteamTurbine"*_n)][t,q,ts] <=
m[Symbol("dvHeatingProduction"*_n)][t,q,ts]
)
else
Expand Down Expand Up @@ -181,6 +181,13 @@ function add_hot_thermal_storage_dispatch_constraints(m, p, b; _n="")
sum(m[Symbol("dvHeatFromStorage"*_n)][b,q,ts] for q in p.heating_loads)
)

#Do not allow GHP to charge storage
if !isempty(p.techs.ghp)
for b in p.s.storage.types.hot, t in p.techs.ghp, q in p.heating_loads, ts in p.time_steps
fix(m[Symbol("dvHeatToStorage"*_n)][b,t,q,ts], 0.0, force=true)
end
end

end

function add_cold_thermal_storage_dispatch_constraints(m, p, b; _n="")
Expand All @@ -207,6 +214,13 @@ function add_cold_thermal_storage_dispatch_constraints(m, p, b; _n="")
m[Symbol("dvStoragePower"*_n)][b] >= m[Symbol("dvDischargeFromStorage"*_n)][b,ts] +
sum(m[Symbol("dvProductionToStorage"*_n)][b,t,ts] for t in p.techs.cooling)
)

#Do not allow GHP to charge storage
adfarth marked this conversation as resolved.
Show resolved Hide resolved
if !isempty(p.techs.ghp)
for b in p.s.storage.types.cold, t in p.techs.ghp, ts in p.time_steps
fix(m[Symbol("dvProductionToStorage"*_n)][b,t,ts], 0.0, force=true)
end
end
end

function add_storage_sum_constraints(m, p; _n="")
Expand Down
14 changes: 7 additions & 7 deletions src/core/reopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,19 +216,19 @@ function build_reopt!(m::JuMP.AbstractModel, p::REoptInputs)
elseif b in p.s.storage.types.hot
@constraint(m, [q in q in setdiff(p.heating_loads, p.heating_loads_served_by_tes[b]), ts in p.time_steps], m[:dvHeatFromStorage][b,q,ts] == 0)
if "DomesticHotWater" in p.heating_loads_served_by_tes[b]
@constraint(m, [t in setdiff(p.heating_techs, p.techs_can_serve_dhw), ts in p.time_steps], m[:dvHeatToStorage][b,"DomesticHotWater",ts] == 0)
@constraint(m, [t in setdiff(p.heating_techs, p.techs_can_serve_dhw), ts in p.time_steps], m[:dvHeatToStorage][b,t,"DomesticHotWater",ts] == 0)
else
@constraint(m, [t in p.heating_techs, ts in p.time_steps], m[:dvHeatToStorage][b,"DomesticHotWater",ts] == 0)
@constraint(m, [t in p.heating_techs, ts in p.time_steps], m[:dvHeatToStorage][b,t,"DomesticHotWater",ts] == 0)
end
if "SpaceHeating" in p.heating_loads_served_by_tes[b]
@constraint(m, [t in setdiff(p.heating_techs, p.techs_can_serve_space_heating), ts in p.time_steps], m[:dvHeatToStorage][b,"SpaceHeating",ts] == 0)
@constraint(m, [t in setdiff(p.heating_techs, p.techs_can_serve_space_heating), ts in p.time_steps], m[:dvHeatToStorage][b,t,"SpaceHeating",ts] == 0)
else
@constraint(m, [t in p.heating_techs, ts in p.time_steps], m[:dvHeatToStorage][b,"SpaceHeating",ts] == 0)
@constraint(m, [t in p.heating_techs, ts in p.time_steps], m[:dvHeatToStorage][b,t,"SpaceHeating",ts] == 0)
end
if "ProcessHeat" in p.heating_loads_served_by_tes[b]
@constraint(m, [t in setdiff(p.heating_techs, p.techs_can_serve_process_heat), ts in p.time_steps], m[:dvHeatToStorage][b,"ProcessHeat",ts] == 0)
@constraint(m, [t in setdiff(p.heating_techs, p.techs_can_serve_process_heat), ts in p.time_steps], m[:dvHeatToStorage][b,t,"ProcessHeat",ts] == 0)
else
@constraint(m, [t in p.heating_techs, ts in p.time_steps], m[:dvHeatToStorage][b,"ProcessHeat",ts] == 0)
@constraint(m, [t in p.heating_techs, ts in p.time_steps], m[:dvHeatToStorage][b,t,"ProcessHeat",ts] == 0)
end
end
else
Expand Down Expand Up @@ -584,7 +584,7 @@ function add_variables!(m::JuMP.AbstractModel, p::REoptInputs)
dvGridPurchase[p.time_steps, 1:p.s.electric_tariff.n_energy_tiers] >= 0 # Power from grid dispatched to meet electrical load [kW]
dvRatedProduction[p.techs.all, p.time_steps] >= 0 # Rated production of technology t [kW]
dvCurtail[p.techs.all, p.time_steps] >= 0 # [kW]
dvProductionToStorage[p.s.storage.types.all, p.techs.all, p.time_steps] >= 0 # Power from technology t used to charge storage system b [kW]
dvProductionToStorage[p.s.storage.types.all, union(p.techs.ghp,p.techs.all), p.time_steps] >= 0 # Power from technology t used to charge storage system b [kW]
adfarth marked this conversation as resolved.
Show resolved Hide resolved
dvDischargeFromStorage[p.s.storage.types.all, p.time_steps] >= 0 # Power discharged from storage system b [kW]
dvGridToStorage[p.s.storage.types.elec, p.time_steps] >= 0 # Electrical power delivered to storage by the grid [kW]
dvStoredEnergy[p.s.storage.types.all, 0:p.time_steps[end]] >= 0 # State of charge of storage system b
Expand Down
3 changes: 3 additions & 0 deletions src/core/steam_turbine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
can_wholesale::Bool = false
can_export_beyond_nem_limit::Bool = false
can_curtail::Bool = false
can_serve_dhw::Bool = true
can_serve_space_heating::Bool = true
can_serve_process_heat::Bool = true

macrs_option_years::Int = 0
macrs_bonus_fraction::Float64 = 0.0
Expand Down
10 changes: 10 additions & 0 deletions test/scenarios/ghp_inputs.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,15 @@
"ElectricStorage": {
"max_kw": 0.0,
"max_kwh": 0.0
},
"ColdThermalStorage": {
"min_gal": 10,
"max_gal": 10,
"thermal_decay_rate_fraction": 0.0
},
"HotThermalStorage": {
"min_gal": 10,
"max_gal": 10,
"thermal_decay_rate_fraction": 0.0
}
}
Loading