Adding an attribute to Flow




I am trying to define a stability constraint to my model, as percentage of syncronous generation over the entire electricity production.
I have seen the example in the repository for the emission and fuel share limit and it is clear, but since I am defining my nodes through an excel file, I think it would be easier to add the attribute stability_factor to the Flows in order to characterize all the components I wish with the attribute stability_factor directly for the excel file, and define the overall limit (as implemented now for the emission limit).
How could I add an attribute to a Flow? Do you suggest a better alternative for my purpose?



It is possible to add an attribute to any Flow. Assuming that you have a working example with an energysytem:

energysystem.add(solph.Source(label='my_source', outputs={my_bus: solph.Flow(
    nominal_value=50, my_new_attr=45)}))

for f in energysystem.flows():
    print(getattr(energysystem.flows()[f], 'my_new_attr', None))

You should get a None for all flows, that do not have my_new_attr and the value (in my_flow it is 45) of all flows that do have this attribute.


Ok, thanks. Then the Source is passed to the solph.Model (with all the other components) keeping my_new_attr, is it correct?


Yes, this is correct.

If you want to be sure you can try the following.

model = solph.Model(energysystem)

for (i, o) in model.flows:
    if hasattr(model.flows[i, o], 'my_new_attr'):
        print(i, o, model.flows[i, o].my_new_attr)

You can use this code to find all flows, that have the my_new_attr.

In the emission constraint you can either pass a list of flows or you can use all flows that have the emission attribute. You could use something like this in your function as well.


That works, I tried also to implement the constraint defining a new function min_stability as:

def min_stability(om,flows=None,limit=None):
    if flows is None:
        flows = {}
        for (i, o) in om.flows:
            if hasattr(om.flows[i, o], 'stability factor'):
                flows[(i, o)] = om.flows[i, o]

        for (i, o) in flows:
            if not hasattr(flows[i, o], 'stability factor'):
                raise ValueError(('Flow with source: {0} and target: {1} '
                                 'has no attribute stability factor.').format(i.label, o.label))
    def stability_rule(m):                                                              
       return (sum(m.flow[i, o, t]*m.timeincrement[t]*m.flows[i, o].stability_factor
                for (i, o) in flows
                for t in m.TIMESTEPS) >= limit)
    om.min_stability = po.Constraint(rule=stability_rule)
    return om

but I get the error: Constructing component 'min_stability' from data=None failed:
    ValueError: Invalid constraint expression. The constraint expression
    resolved to a trivial Boolean (True) instead of a Pyomo object. Please
    modify your rule to return Constraint.Feasible instead of True.

I am trying to understand the reason of this error, but I don't find it


I got it…the attribute is written wrong…




I am trying to improve the code I wrote here in this topic concerning the stabilization share.
How can I add the constraint for each time step instead for the whole simulation horizon as it is now?



Normally it is better to open a new post for a new question.

I do not use additional constraints at the moment but it should work like this:

    def my_rule(m, t):                                                              
        return something(t)
    model.min_stability = po.Constraint(model.TIMESTEPS, rule=stability_rule)


We could solve it in Aalborg :wink:


@gabrielecassetti: Could you post your solution and mark it as solved?



yes, we could solve it in Aalborg!
The solution finally found is the following:

def stability_rule(m,t):
      lhs = sum(m.flow[i, o, t]*m.flows[i, o].stability_factor * m.timeincrement[t]
                for (i, o) in flows)
      rhs = limit[t]                                                          
       return  (lhs >= rhs)               
om.min_stability = po.Constraint(om.TIMESTEPS,rule=stability_rule)

where limit is a list.

Thanks again Cord!