Adding a variable to pyomo in oemof

Hi everyone,

I’m currently implementing peak shaving in an oemof model.
For this I add a max_power variable for each month within the simulation horizon.
For each timestep I add a constraint to limit the sum of the flows from the grid into my system (there are several grid sources due to different energy markets) to the corresponding max_power variable.
The max_power variables afterwards are multiplied with cost_per_watt and added to the objective function. So far everything works well (at least it seems to work as the objective of the optimizer changes in a reasonable way if the feature is activated).

model.CustomConstraints.PEAK_SHAVING.max_power_set = po.Set(initialize=range(1, 1 + len(monthly_indices)))
    model.CustomConstraints.PEAK_SHAVING.max_power_indexed = po.Var(model.CustomConstraints.PEAK_SHAVING.max_power_set, within=po.NonNegativeReals)

Unfortunately, I struggle with the result processing part of oemof as oemof tries to restructure all results of the optimizer into a (start_component, end_component) logic, which fails for my max_power variables.

  File "C:\Users\user\AppData\Local\anaconda3\envsoemof_env\Lib\site-packages\oemof\solph\processing.py", line 162, in set_result_index
    df_dict[k].index = result_index
    ^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Local\anaconda3\envsoemof_env\Lib\site-packages\pandas\core\generic.py", line 6307, in __setattr__
    return object.__setattr__(self, name, value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "properties.pyx", line 69, in pandas._libs.properties.AxisProperty.__set__
  File "C:\Users\user\AppData\Local\anaconda3\envsoemof_env\Lib\site-packages\pandas\core\generic.py", line 813, in _set_axis
    self._mgr.set_axis(axis, labels)
  File "C:\Users\user\AppData\Local\anaconda3\envsoemof_env\Lib\site-packages\pandas\core\internals\managers.py", line 239, in set_axis
    self._validate_set_axis(axis, new_labels)
  File "C:\Users\user\AppData\Local\anaconda3\envsoemof_env\Lib\site-packages\pandas\core\internals\base.py", line 98, in _validate_set_axis
    raise ValueError(
ValueError: Length mismatch: Expected axis has 3 elements, new values have 961 elements

I think the definition of the variables is not the way you’re supposed to do this in oemof.
How can I add a set of new variables to the model after the pyomo model is generated by oemof in a way that oemof can deal with the result?

Thanks for your ideas!

Best regards
Brian

(Btw: I don’t want to add grid components for every month to keep the model simple)

Hi @briand,

If you want to reduce peak power on a monthly interval, there might be a simpler approach. You might want to consider it if time coding is more expensive than (slightly) inefficient code:

grid = {month: Bus(f"electricity_{month}") for month in months}
local = Bus(
    "electricity_local",
    inputs={grid[month] : Flow(
        nominal_value=Investment(...),
        max=[1 if check_month(time_step) else 0 for time_steps],
    )}
)
energy_system.add(grid.values, local)

(Sorry for the non-answer. Result processing is really lacking some love at the moment, so I rather wanted to sketch something that will be valid for longer.)

Hi @pschoen,
thanks for this approach. I think the solution you suggested works well for my use case.

Best regards
Brian