johnwolf1987
johnwolf1987

Reputation: 11379

How to set a constraint depending on previous set index

I am writing an energy optimization model using Pyomo. In this model I have a constraint which updates the charge level of an energy storage at every time-step using the charge level in the previous time-step (simplified equation):

Storage_level[t] = Storage_level[t-1] + Charge [t] - Discharge [t]

And there is an additional constraint for the initial period:

Storage_level[1] = 0

When I run the problem, I don't get any useful result and the output window just displays the constraint bounds, such as:

ev_soc_max : Size=24
    Key : Lower : Body : Upper
      1 :  None : None :   0.0
      2 :  None : None :   0.0
      3 :  None : None :   0.0
      4 :  None : None :   0.0
      5 :  None : None :   0.0
      ...

and I also get this error for some variables:

ERROR: evaluating object as numeric value: p_bat_ch[1]
        (object: <class 'pyomo.core.base.var._GeneralVarData'>)
    No value for uninitialized NumericValue object p_bat_ch[1]

I suspect that the problem is related to the definition of the storage constraints.

This is how I coded it in Pyomo (I came to this result by combining different examples which I found here and there on the internet):

def bat_soc_ini_rule(model, t):
    if t == 1:
        return model.e_bat_t[t] == 0.
    else:
        return Constraint.Skip
model.bat_soc_ini = Constraint(model.T, rule = bat_soc_ini_rule)

def bat_soc_rule(model, t):
    if t >= 2:
        return model.e_bat_t[t] == model.eta_bat_cal * model.e_bat_t[t-1] + model.eta_bat_ch * model.p_bat_ch[t] - model.eta_bat_dis**-1 * model.p_bat_dis[t]
    else:
        return Constraint.Skip
model.bat_soc = Constraint(model.T, rule = bat_soc_rule)

I should also state that I declared the model.T set using model.T = RangeSet(24) and the variables are declared as follows: model.e_bat_t = Var(model.T, within = NonNegativeReals)

One last point: I am using GLPK as a solver.

My questions are:

  1. How should I declare a constraint which calls a previous member of the set? Am I doing it right?

  2. How should I set a constraint on only part of a set (e.g. for the initialization constraint)?

  3. Am I right in thinking that the error comes from the incorrect definition of this constraint? If not, do you have any idea where the problem could come from?

Upvotes: 1

Views: 1372

Answers (1)

oakca
oakca

Reputation: 1568

Well, I am working with urbs atm and following code comes from it.

This is the constraint rule you are looking for storage[t] = storage[t-1] + in - out

# storage content in timestep [t] == storage content[t-1] * (1-discharge)
# + newly stored energy * input efficiency
# - retrieved energy / output efficiency
def def_storage_state_rule(m, t, sit, sto, com):
    return (m.e_sto_con[t, sit, sto, com] ==
            m.e_sto_con[t-1, sit, sto, com] *
            (1 - m.storage_dict['discharge'][(sit, sto, com)]) ** m.dt.value +
            m.e_sto_in[t, sit, sto, com] *
            m.storage_dict['eff-in'][(sit, sto, com)] -
            m.e_sto_out[t, sit, sto, com] /
            m.storage_dict['eff-out'][(sit, sto, com)])

And for setting the init value they have something like following:

# initialization of storage content in first timestep t[1]
# forced minimun  storage content in final timestep t[len(m.t)]
# content[t=1] == storage capacity * fraction <= content[t=final]
def res_initial_and_final_storage_state_rule(m, t, sit, sto, com):
    if t == m.t[1]:  # first timestep (Pyomo uses 1-based indexing)
        return (m.e_sto_con[t, sit, sto, com] ==
                m.cap_sto_c[sit, sto, com] *
                m.storage_dict['init'][(sit, sto, com)])
    elif t == m.t[len(m.t)]:  # last timestep
        return (m.e_sto_con[t, sit, sto, com] >=
                m.cap_sto_c[sit, sto, com] *
                m.storage_dict['init'][(sit, sto, com)])
    else:
        return pyomo.Constraint.Skip

I hope this example helps you. You can use it change it or adapt it in your code-

Upvotes: 1

Related Questions