Adding custom expression to objective function to add demand charges

91 views
Skip to first unread message

Nestor Andres Sepulveda

unread,
Mar 30, 2022, 11:03:53 AM3/30/22
to pypsa
Hi All,

would love the input of this community on the following. A colleague is building a capacity expansion model with some assets offsite and some assets on-site. The idea is to add a capacity charge term to the objective function, so a few question of the community:
  1. what would be the best way to create an auxiliary variable for every month in the planning horizon to track the maximum electricity coming from  off-site sources (I know Max is non-linear and we have a formulation to linearize it via a set of constraints) so the Q is more about where and how to create these set of auxiliary variables
  2. how can we add an additional term to the objective that multiplies the auxiliary variable  by a monthly demand charge (parameter)
apologies if this seems stupidly simple, I am a Julia/JuMP guy trying to help a friend.

Best,
Nestor

Fabian Hofmann

unread,
Apr 7, 2022, 3:00:01 AM4/7/22
to pypsa
Hey Nestor, 

sorry it took so long for me to answer...

Adding custom variables is possible via the argument `extra_functionality` which is passed to the `lopf`. This argument needs to be a function as shown in this example (https://pypsa.readthedocs.io/en/latest/examples/lopf_with_pyomo_False.html) and is called after the definition of the default optimization problem. I assume you use the setting `pyomo=False` in the lopf (which is faster and more memory-efficient). 

Then, 
- the function for adding variables is called  `pypsa.linopt.define_variables`, have a look at its docstring for further information. 
- the function for adding terms to the objective function is called `pypsa.linopt.write_objective` which takes a linear expression as argument created with function `pypsa.linopt.linexpr`. Per default this function adds terms to the existing objective function. If you want to overwrite the whole objective functions, you have to call n.lopf(pyomo=False, skip_objective=True, extra_functionality=extra_functionality) in the beginning. 

Note, both things have to be called in the passed extra_functionality.

The optimization framework will in the future change to make things more user-friendly and flexible using the package linopy (https://github.com/PyPSA/linopy)

Hope that helps!

Best, 
Fabian  Hofmann
Reply all
Reply to author
Forward
0 new messages