# Seasonal storage balance constraint

**URL:** <https://discourse.julialang.org/t/seasonal-storage-balance-constraint/87098>\
**Category:** Optimization (Mathematical)\
**Created:** [September 11, 2022, 8:39pm UTC](https://discourse.julialang.org/t/seasonal-storage-balance-constraint/87098 "2022-09-11T20:39:12Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mbah](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@mbah](https://discourse.julialang.org/u/mbah)\
**Post date:** [September 11, 2022, 8:39pm UTC](https://discourse.julialang.org/t/seasonal-storage-balance-constraint/87098/1 "2022-09-11T20:39:12Z")

</div>

Hello all,

I am trying to code up a seasonal storage balance constraint. The idea is to limit the total generation over a time range by a particular amount for each of the seasonal storage plants (see Table). I have tried to do this with the SSBalance constraint, without much success.  
See full error message when running the SSBalance constraint below.

```julia
using JuMP, DataFrames, Gurobi  

generators = DataFrame(index = ["SS_A", "SS_B"], 
                        node = ["zonea", "zoneb"],
                        cost = [0,0], g_max = [70,60], 
                        plant_type = ["SS","SS"])

```

```julia
SS = generators.index
T = convert(Array{Int64}, 1:6) #Time stamp
Test_Model = Model(Gurobi.Optimizer)

@variable(Test_Model, vSSTORAGE[T, ss in SS] >=0) #seasonal storage

#@constraint(Test_Model, SSGeneration[t in T, ss in SS], vSSTORAGE[t,ss] <= generators[findfirst(==(ss), SS), :].g_max) #generation constraint

@constraint(Test_Model, SSBalance[t in T, ss in SS], vSSTORAGE[1:3,"SS_A"] <= 100) #main problem

```

```julia
ERROR: Operation `sub_mul` between `JuMP.Containers.DenseAxisArray{VariableRef, 1, Tuple{Vector{Int64}}, Tuple{JuMP.Containers._AxisLookup{Dict{Int64, Int64}}}}` and `Int64` is not allowed. You should use broadcast.
Stacktrace:
  [1] error(s::String)
    @ Base .\error.jl:33
  [2] operate!!(#unused#::typeof(MutableArithmetics.sub_mul), x::JuMP.Containers.DenseAxisArray{VariableRef, 1, Tuple{Vector{Int64}}, Tuple{JuMP.Containers._AxisLookup{Dict{Int64, Int64}}}}, y::Int64) @ JuMP C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\sets.jl:96
  [3] macro expansion
    @ C:\Users\mbahe\.julia\packages\MutableArithmetics\Lnlkl\src\rewrite.jl:294 [inlined]
  [4] macro expansion
    @ C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\macros.jl:823 [inlined]
  [5] (::var"#19#20")(t::Int64, ss::String)
    @ Main C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\Containers\macro.jl:304
  [6] #39
    @ C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\Containers\container.jl:105 [inlined]
  [7] iterate
    @ .\generator.jl:47 [inlined]
  [8] collect(itr::Base.Generator{JuMP.Containers.VectorizedProductIterator{Tuple{Vector{Int64}, Vector{String}}}, JuMP.Containers.var"#39#40"{var"#19#20"}})
    @ Base .\array.jl:724
  [9] map(f::Function, A::JuMP.Containers.VectorizedProductIterator{Tuple{Vector{Int64}, Vector{String}}})
    @ Base .\abstractarray.jl:2896
 [10] container(f::Function, indices::JuMP.Containers.VectorizedProductIterator{Tuple{Vector{Int64}, Vector{String}}}, #unused#::Type{JuMP.Containers.DenseAxisArray})
    @ JuMP.Containers C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\Containers\container.jl:105
 [11] container(f::Function, indices::JuMP.Containers.VectorizedProductIterator{Tuple{Vector{Int64}, Vector{String}}})
    @ JuMP.Containers C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\Containers\container.jl:66
 [12] macro expansion
    @ C:\Users\mbahe\.julia\packages\JuMP\Y4piv\src\macros.jl:142 [inlined]
 [13] top-level scope
    @ c:\Users\mbahe\Desktop\PhD UNIBASEL\NUCLEAR PROJECT\ZEC MODELLING\JuliaDiscourse\seasonal_storage_test.jl:55

```

Any help on the constraint would be much appreciated.

Thanks

![seasonal_storage_table](https://global.discourse-cdn.com/julialang/original/3X/d/9/d9db47aad14a555c7b96a2271e6b59ea9547c69c.png)

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [September 11, 2022, 9:07pm UTC](https://discourse.julialang.org/t/seasonal-storage-balance-constraint/87098/2 "2022-09-11T21:07:58Z")

</div>

> @constraint(Test\_Model, SSBalance[t in T, ss in SS], vSSTORAGE[1:3,“SS\_A”] \<= 100)

There are multiple things wrong with this constraint. Why is it indexed over `T` and `SS`, when neither of them appear in the constraint?

This probably needs to be `@constraint(Test_Model, SSBalance, vSSTORAGE[1:3,"SS_A"] .<= 100)`. Note the `.<=` instead of `<=`.

Or, you might have meant:  
`@constraint(Test_Model, SSBalance[t in T, ss in SS], vSSTORAGE[t, ss] <= 100)`

But even better, would be to use `set_upper_bound.(vSSTORAGE[1:3, "SS_A"], 10)`

Edit: I just saw your table at the bottom. Do something like this:

```Julia
upper_bound = Dict()
for t in 1:3
    upper_bound[(t, "SS_A")] = 100
    upper_bound[(t, "SS_B")] = 150
end
for t in 4:6
    upper_bound[(t, "SS_A")] = 160
    upper_bound[(t, "SS_B")] = 200
end
@variable(Test_Model, 0 <= vSSTORAGE[t in T, ss in SS] <= upper_bound[(t, ss)])

```

---

<div class="post-metadata">

**Author:** ![mbah](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@mbah](https://discourse.julialang.org/u/mbah)\
**Post date:** [September 12, 2022, 7:08am UTC](https://discourse.julialang.org/t/seasonal-storage-balance-constraint/87098/3 "2022-09-12T07:08:37Z")

</div>

Thanks @odow for helpful codes. I used the last bit of code you suggested with the dictionary.

The code works, however the aggregate output for each plant does not obey the upper bound value I set. In fact the aggregate output for each plant exceeds the upper bound limit for each time block but remains in line with the installed capacity constraint (SSGeneration). Any suggestions on working around this?

Thanks

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [September 12, 2022, 7:11am UTC](https://discourse.julialang.org/t/seasonal-storage-balance-constraint/87098/4 "2022-09-12T07:11:58Z")

</div>

I don’t understand the question. Can you post the code you have and the solution you expect?
