Skip to content

Commit

Permalink
Debug hydrogen components
Browse files Browse the repository at this point in the history
  • Loading branch information
lixiangk1 committed Jul 25, 2023
1 parent 0c33d70 commit bc3d152
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 33 deletions.
5 changes: 5 additions & 0 deletions src/REopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ include("core/wind.jl")
include("core/energy_storage/storage.jl")
include("core/energy_storage/electric_storage.jl")
include("core/energy_storage/thermal_storage.jl")
include("core/energy_storage/hydrogen_storage_LP.jl")
include("core/energy_storage/hydrogen_storage_HP.jl")
include("core/electrolyzer.jl")
include("core/compressor.jl")
include("core/generator.jl")
include("core/doe_commercial_reference_building_loads.jl")
include("core/electric_load.jl")
Expand Down Expand Up @@ -179,6 +183,7 @@ include("constraints/ghp_constraints.jl")
include("constraints/steam_turbine_constraints.jl")
include("constraints/renewable_energy_constraints.jl")
include("constraints/emissions_constraints.jl")
include("constraints/hydrogen_constraints.jl")

include("mpc/structs.jl")
include("mpc/scenario.jl")
Expand Down
6 changes: 3 additions & 3 deletions src/constraints/hydrogen_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function add_compressor_constraints(m, p; _n="")
@constraint(m, [ts in p.time_steps],
sum(p.production_factor[t, ts] * p.levelization_factor[t] * m[Symbol("dvRatedProduction"*_n)][t,ts] for t in p.techs.compressor)
==
sum(m[Symbol("dvProductionToStorage"*_n)][b,ts] for b in p.s.storage.types.hydrogen_hp)
sum(m[Symbol("dvProductionToStorage"*_n)][b,t,ts] for b in p.s.storage.types.hydrogen_hp, t in p.techs.elec)
)
@constraint(m, [ts in p.time_steps_with_grid],
sum(p.s.compressor.efficiency_kwh_per_kg * p.production_factor[t, ts] * p.levelization_factor[t] *
Expand All @@ -64,11 +64,11 @@ end
function add_electrolyzer_constraints(m, p; _n="")

##Constraint: Compressor takes hydrogen from LP storage to charge HP storage while consuming electricity
if !isempty(t in p.techs.electrolyzer)
if !isempty(p.techs.electrolyzer)
@constraint(m, [ts in p.time_steps],
sum(p.production_factor[t, ts] * p.levelization_factor[t] * m[Symbol("dvRatedProduction"*_n)][t,ts] for t in p.techs.electrolyzer)
==
sum(m[Symbol("dvProductionToStorage"*_n)][b,ts] for b in p.s.storage.types.hydrogen_lp)
sum(m[Symbol("dvProductionToStorage"*_n)][b,t,ts] for b in p.s.storage.types.hydrogen_lp, t in p.techs.elec)
)
@constraint(m, [ts in p.time_steps_with_grid],
sum(p.s.electrolyzer.efficiency_kwh_per_kg * p.production_factor[t, ts] * p.levelization_factor[t] *
Expand Down
23 changes: 23 additions & 0 deletions src/constraints/storage_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,29 @@ function add_storage_size_constraints(m, p, b; _n="")
)
end

function add_hydrogen_storage_size_constraints(m, p, b; _n="")
# TODO add formal types for storage (i.e. "b")

# Constraint (4b)-1: Lower bound on Storage Energy Capacity
@constraint(m,
m[Symbol("dvStorageEnergy"*_n)][b] >= p.s.storage.attr[b].min_kg
)

# Constraint (4b)-2: Upper bound on Storage Energy Capacity
@constraint(m,
m[Symbol("dvStorageEnergy"*_n)][b] <= p.s.storage.attr[b].max_kg
)

# # Constraint (4c)-1: Lower bound on Storage Power Capacity
# @constraint(m,
# m[Symbol("dvStoragePower"*_n)][b] >= p.s.storage.attr[b].min_kw
# )

# # Constraint (4c)-2: Upper bound on Storage Power Capacity
# @constraint(m,
# m[Symbol("dvStoragePower"*_n)][b] <= p.s.storage.attr[b].max_kw
# )
end

function add_general_storage_dispatch_constraints(m, p, b; _n="")
# Constraint (4a): initial state of charge
Expand Down
4 changes: 2 additions & 2 deletions src/core/energy_storage/hydrogen_storage_HP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Base.@kwdef struct HydrogenStorageHPDefaults
soc_min_fraction::Float64 = 0.05
soc_init_fraction::Float64 = 0.5
installed_cost_per_kg::Real = 1500.0
replace_cost_per_kg:Real = 1000.0
replace_cost_per_kg::Real = 1000.0
replacement_year::Int = 25
macrs_option_years::Int = 7
macrs_bonus_fraction::Float64 = 0.8
Expand Down Expand Up @@ -112,7 +112,7 @@ struct HydrogenStorageHP <: AbstractHydrogenStorage
s.soc_min_fraction,
s.soc_init_fraction,
s.installed_cost_per_kg,
replace_cost_per_kg,
s.replace_cost_per_kg,
s.replacement_year,
s.macrs_option_years,
s.macrs_bonus_fraction,
Expand Down
6 changes: 3 additions & 3 deletions src/core/energy_storage/hydrogen_storage_LP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@
"""
Base.@kwdef struct HydrogenStorageLPDefaults
min_kg::Real = 0.0
max_kg::Real = 1.0e9
max_kg::Real = 1.0e6
soc_min_fraction::Float64 = 0.05
soc_init_fraction::Float64 = 0.5
installed_cost_per_kg::Real = 1500.0
replace_cost_per_kg:Real = 1000.0
replace_cost_per_kg::Real = 1000.0
replacement_year::Int = 25
macrs_option_years::Int = 7
macrs_bonus_fraction::Float64 = 0.8
Expand Down Expand Up @@ -112,7 +112,7 @@ struct HydrogenStorageLP <: AbstractHydrogenStorage
s.soc_min_fraction,
s.soc_init_fraction,
s.installed_cost_per_kg,
replace_cost_per_kg,
s.replace_cost_per_kg,
s.replacement_year,
s.macrs_option_years,
s.macrs_bonus_fraction,
Expand Down
42 changes: 28 additions & 14 deletions src/core/energy_storage/storage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ mutable struct StorageTypes
hydrogen::Vector{String}
hydrogen_lp::Vector{String}
hydrogen_hp::Vector{String}
nonhydrogen::Vector{String}

function StorageTypes()
new(
Expand All @@ -81,16 +82,16 @@ mutable struct StorageTypes
hydrogen_storage = String[]
hydrogen_lp_storage = String[]
hydrogen_hp_storage = String[]

non_hydrogen_storage = String[]

for (k,v) in d
if v.max_kw > 0.0 && v.max_kwh > 0.0

push!(all_storage, k)
if typeof(v) <: AbstractHydrogenStorage

if v.max_kg > 0.0

if typeof(v) <: AbstractElectricStorage
push!(elec_storage, k)
push!(all_storage, k)

elseif typeof(v) <: AbstractHydrogenStorage
if occursin("LP", k)
push!(hydrogen_lp_storage, k)
elseif occursin("HP", k)
Expand All @@ -99,14 +100,26 @@ mutable struct StorageTypes
throw(@error("Hydrogen Storage not labeled as LP or HP."))
end

elseif typeof(v) <: ThermalStorage
if occursin("Hot", k)
push!(hot_storage, k)
elseif occursin("Cold", k)
push!(cold_storage, k)
else
throw(@error("Thermal Storage not labeled as Hot or Cold."))
end
else
if v.max_kw > 0.0 && v.max_kwh > 0.0

push!(all_storage, k)
push!(non_hydrogen_storage, k)

if typeof(v) <: AbstractElectricStorage
push!(elec_storage, k)

elseif typeof(v) <: ThermalStorage
if occursin("Hot", k)
push!(hot_storage, k)
elseif occursin("Cold", k)
push!(cold_storage, k)
else
throw(@error("Thermal Storage not labeled as Hot or Cold."))
end
end

end
end
end
Expand All @@ -122,7 +135,8 @@ mutable struct StorageTypes
cold_storage,
hydrogen_storage,
hydrogen_lp_storage,
hydrogen_hp_storage
hydrogen_hp_storage,
non_hydrogen_storage
)
end
end
Expand Down
29 changes: 23 additions & 6 deletions src/core/reopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,25 @@ function build_reopt!(m::JuMP.AbstractModel, p::REoptInputs)
end

for b in p.s.storage.types.all
if p.s.storage.attr[b].max_kw == 0 || p.s.storage.attr[b].max_kwh == 0

if b in p.s.storage.types.hydrogen
if p.s.storage.attr[b].max_kg == 0
@constraint(m, [ts in p.time_steps], m[:dvStoredEnergy][b, ts] == 0)
@constraint(m, m[:dvStorageEnergy][b] == 0)
@constraint(m, [ts in p.time_steps], m[:dvDischargeFromStorage][b, ts] == 0)
@constraint(m, [ts in p.time_steps], m[:dvGridToStorage][b, ts] == 0)
@constraint(m, [t in p.techs.elec, ts in p.time_steps_with_grid],
m[:dvProductionToStorage][b, t, ts] == 0)
else
add_hydrogen_storage_size_constraints(m, p, b)
add_general_storage_dispatch_constraints(m, p, b)
if b in p.s.storage.types.hydrogen_lp
add_lp_hydrogen_storage_dispatch_constraints(m, p, b)
elseif b in p.s.storage.types.hydrogen_hp
add_hp_hydrogen_storage_dispatch_constraints(m, p, b)
end
end
elseif p.s.storage.attr[b].max_kw == 0 || p.s.storage.attr[b].max_kwh == 0
@constraint(m, [ts in p.time_steps], m[:dvStoredEnergy][b, ts] == 0)
@constraint(m, m[:dvStorageEnergy][b] == 0)
@constraint(m, [ts in p.time_steps], m[:dvDischargeFromStorage][b, ts] == 0)
Expand All @@ -251,10 +269,6 @@ function build_reopt!(m::JuMP.AbstractModel, p::REoptInputs)
add_hot_thermal_storage_dispatch_constraints(m, p, b)
elseif b in p.s.storage.types.cold
add_cold_thermal_storage_dispatch_constraints(m, p, b)
elseif b in p.s.storage.types.hydrogen_lp
add_lp_hydrogen_storage_dispatch_constraints(m, p, b)
elseif b in p.s.storage.types.hydrogen_hp
add_hp_hydrogen_storage_dispatch_constraints(m, p, b)
else
throw(@error("Invalid storage does not fall in a thermal or electrical set"))
end
Expand All @@ -263,6 +277,8 @@ function build_reopt!(m::JuMP.AbstractModel, p::REoptInputs)

if any(max_kw->max_kw > 0, (p.s.storage.attr[b].max_kw for b in p.s.storage.types.elec))
add_storage_sum_constraints(m, p)
elseif any(max_kg->max_kg > 0, (p.s.storage.attr[b].max_kg for b in p.s.storage.types.hydrogen))
add_storage_sum_constraints(m, p)
end

add_production_constraints(m, p)
Expand Down Expand Up @@ -394,7 +410,8 @@ function build_reopt!(m::JuMP.AbstractModel, p::REoptInputs)

@expression(m, TotalStorageCapCosts, p.third_party_factor * (
sum( p.s.storage.attr[b].net_present_cost_per_kw * m[:dvStoragePower][b] for b in p.s.storage.types.elec) +
sum( p.s.storage.attr[b].net_present_cost_per_kwh * m[:dvStorageEnergy][b] for b in p.s.storage.types.all )
sum( p.s.storage.attr[b].net_present_cost_per_kwh * m[:dvStorageEnergy][b] for b in p.s.storage.types.nonhydrogen) +
sum( p.s.storage.attr[b].net_present_cost_per_kg * m[:dvStorageEnergy][b] for b in p.s.storage.types.hydrogen)
))

@expression(m, TotalPerUnitSizeOMCosts, p.third_party_factor * p.pwf_om *
Expand Down
16 changes: 15 additions & 1 deletion src/core/scenario.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct Scenario <: AbstractScenario
space_heating_thermal_load_reduction_with_ghp_kw::Union{Vector{Float64}, Nothing}
cooling_thermal_load_reduction_with_ghp_kw::Union{Vector{Float64}, Nothing}
steam_turbine::Union{SteamTurbine, Nothing}
electrolyzer::Union{Electrolyzer, Nothing}
compressor::Union{Compressor, Nothing}
end

"""
Expand Down Expand Up @@ -237,6 +239,16 @@ function Scenario(d::Dict; flex_hvac_from_json=false)
)
end

electrolyzer = nothing
compressor = nothing
if haskey(d, "Electrolyzer")
electrolyzer = Electrolyzer(; dictkeys_tosymbols(d["Electrolyzer"])...)
end

if haskey(d, "Compressor")
compressor = Compressor(; dictkeys_tosymbols(d["Compressor"])...)
end

max_heat_demand_kw = 0.0
if haskey(d, "DomesticHotWaterLoad") && !haskey(d, "FlexibleHVAC")
add_doe_reference_names_from_elec_to_thermal_loads(d["ElectricLoad"], d["DomesticHotWaterLoad"])
Expand Down Expand Up @@ -596,7 +608,9 @@ function Scenario(d::Dict; flex_hvac_from_json=false)
ghp_option_list,
space_heating_thermal_load_reduction_with_ghp_kw,
cooling_thermal_load_reduction_with_ghp_kw,
steam_turbine
steam_turbine,
electrolyzer,
compressor
)
end

Expand Down
6 changes: 3 additions & 3 deletions src/core/techs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,14 @@ function Techs(s::Scenario)
thermal_techs = union(heating_techs, boiler_techs, chp_techs, cooling_techs)
fuel_burning_techs = union(gentechs, boiler_techs, chp_techs)

if s.electrolyzer.max_kw > 0
if !isnothing(s.electrolyzer)
push!(all_techs, "Electrolyzer")
push!(electrolyzer_techs, "Electrolyzer")
end

if s.compressor.max_kw > 0
if !isnothing(s.compressor)
push!(all_techs, "Compressor")
push!(electrolyzer_techs, "Compressor")
push!(compressor_techs, "Compressor")
end

Techs(
Expand Down
2 changes: 1 addition & 1 deletion src/core/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ function dictkeys_tosymbols(d::Dict)
for (k, v) in d
# handling array type conversions for API inputs and JSON
if k in [
"loads_kw", "critical_loads_kw",
"loads_kw", "critical_loads_kw", "loads_kg",
"thermal_loads_ton",
"fuel_loads_mmbtu_per_hour",
"monthly_totals_kwh",
Expand Down

0 comments on commit bc3d152

Please sign in to comment.