Skip to content

Commit

Permalink
Merge branch 'develop' into boiler-series-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
hdunham committed Oct 30, 2024
2 parents 827353b + 88b9499 commit 907fd4f
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Classify the change according to the following categories:
### Fixed
- When setting **thermal_production_series_mmbtu_per_hour** output in **ExistingBoiler**, sum over heating loads instead of time steps

## Develop - 2024-10-11
### Added
- Add new **ElectricStorage** parameters **max_duration_hours** and **min_duration_hours** to bound the energy duration of battery storage

## Develop degradation-cleanup
### Added
- Battery residual value if choosing replacement strategy for degradation
Expand Down
13 changes: 13 additions & 0 deletions src/constraints/storage_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ function add_storage_size_constraints(m, p, b; _n="")
@constraint(m,
m[Symbol("dvStoragePower"*_n)][b] <= p.s.storage.attr[b].max_kw
)

# Constraint (4c)-3: Limit on ElectricStorage Energy Capacity based on Duration Hours
if p.s.storage.attr[b] isa ElectricStorage
@constraint(m,
m[Symbol("dvStorageEnergy"*_n)][b] <= m[Symbol("dvStoragePower"*_n)][b] * p.s.storage.attr[b].max_duration_hours
)

@constraint(m,
m[Symbol("dvStorageEnergy"*_n)][b] >= m[Symbol("dvStoragePower"*_n)][b] * p.s.storage.attr[b].min_duration_hours
)
end


end


Expand Down
14 changes: 13 additions & 1 deletion src/core/energy_storage/electric_storage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ end
model_degradation::Bool = false
degradation::Dict = Dict()
minimum_avg_soc_fraction::Float64 = 0.0
min_duration_hours::Real = 0.0 # Minimum amount of time storage can discharge at its rated power capacity
max_duration_hours::Real = 100000.0 # Maximum amount of time storage can discharge at its rated power capacity (ratio of ElectricStorage size_kwh to size_kw)
```
"""
Base.@kwdef struct ElectricStorageDefaults
Expand Down Expand Up @@ -218,6 +220,8 @@ Base.@kwdef struct ElectricStorageDefaults
model_degradation::Bool = false
degradation::Dict = Dict()
minimum_avg_soc_fraction::Float64 = 0.0
min_duration_hours::Real = 0.0
max_duration_hours::Real = 100000.0
end


Expand Down Expand Up @@ -259,6 +263,8 @@ struct ElectricStorage <: AbstractElectricStorage
model_degradation::Bool
degradation::Degradation
minimum_avg_soc_fraction::Float64
min_duration_hours::Real
max_duration_hours::Real

function ElectricStorage(d::Dict, f::Financial)
s = ElectricStorageDefaults(;d...)
Expand All @@ -282,6 +288,10 @@ struct ElectricStorage <: AbstractElectricStorage
# replace_cost_per_kw is unchanged here.
end

if s.min_duration_hours > s.max_duration_hours
throw(@error("ElectricStorage min_duration_hours must be less than max_duration_hours."))
end

net_present_cost_per_kw = effective_cost(;
itc_basis = s.installed_cost_per_kw,
replacement_cost = s.inverter_replacement_year >= f.analysis_years ? 0.0 : replace_cost_per_kw,
Expand Down Expand Up @@ -345,7 +355,9 @@ struct ElectricStorage <: AbstractElectricStorage
net_present_cost_per_kwh,
s.model_degradation,
degr,
s.minimum_avg_soc_fraction
s.minimum_avg_soc_fraction,
s.min_duration_hours,
s.max_duration_hours
)
end
end
14 changes: 14 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2910,5 +2910,19 @@ else # run HiGHS tests
@test length(r["Messages"]["errors"]) > 0
@test length(r["Messages"]["warnings"]) > 0
end

@testset "Storage Duration" begin
## Battery storage
d = JSON.parsefile("scenarios/pv_storage.json")
d["ElectricStorage"]["min_duration_hours"] = 8
d["ElectricStorage"]["max_duration_hours"] = 8
s = Scenario(d)
inputs = REoptInputs(s)
m = Model(optimizer_with_attributes(HiGHS.Optimizer, "output_flag" => false, "log_to_console" => false))
r = run_reopt(m, inputs)
# Test battery size_kwh = size_hw * duration
@test r["ElectricStorage"]["size_kw"]*8 - r["ElectricStorage"]["size_kwh"] 0.0 atol = 0.1

end
end
end

0 comments on commit 907fd4f

Please sign in to comment.