Seasonal storage balance constraint

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.

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"])
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

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

@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:

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)])
1 Like

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

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