Unit commitment in electric power systems: solving a mixed-integer non-linear optimization problem
Unit commitment (UC) in electric power systems is a (hard-to-solve) mixed-integer non-linear optimization problem. UC aims at scheduling the generation units such that they satisfy the demand at every time instant while minimizing the overall cost (or maximizing the welfare). On top of that, a large number of constraints must be respected, e.g. capability limits of generation units. To consider the grid model, there are basically three options available: single bus approximation (ignore grid model), DC load flow approximation, or full AC model.
In this article, I use the single bus approximation where the grid model is ignored. That means, it is assumed that the grid does not constrain the solution of the UC problem. In other words, it is assumed that the grid can serve all loads, provided the UC solution where only demand and generation are matched, without accounting for losses and grid constraints. However, the optimization includes the min./max. power and ramp-rate constraints of the generators as well as their cost-functions.
Optimization environment – GEKKO
The optimization is implemented in Python using the GEKKO optimization suite. See below how to install it in your Python environment:
#install GEKKO pip install gekko
GEKKO is a great environment for optimization because it provides a high-level abstraction for optimization problems. The objective function and constraints can be formulated by using prior defined constants, parameters, and variables. GEKKO is also interfaced with a solver (called APOPT) for mixed-integer non-linear optimization problems, which is a precondition to solve the UC problem.
Unit commitment problem
In this section, I will elaborate on the implemented unit commitment problem. As mentioned before, the unit commitment can follow different objectives.
Here, the total costs of the generation units over the whole time horizon shall be minimized. It is important to mention that the status of the unit (ON or OFF) must be considered in the objective function. The complete objective function is shown below.
- cn … (€/h) cost function of unit n
- pn(t) … (MW) active power of unit n at time t
- STATn … (integer variable) defining the operation status of unit n at time t: 0 = OFF, 1 = ON
The sum of active power from the generation units must be equal to the load at every time instant. Here it is also important to consider the status of the unit, i.e. whether the unit is in-service or out-of-service.
- L(t) … (MW) load at time instant t
Each unit has a minimum and maximum power limit which needs to be respected. The setpoint must be within these limits at all times.
- Pn,min/Pn,max … (MW) minimum/maximum power limit of unit n
Each unit has a maximum ramp rate which limits the change of power from one to the next time instant. I assume that the ramp-up and the ramp-down limit are the same. If desired, different ramp-up/ramp-down limits could be implemented easily by using two different parameters for the ramp-up and ramp-down limit.
- -Pn,Rmax/Pn,Rmax … (MW/h) ramp-down/ramp-up limit of unit n
Important: the (absolute) ramp limit must be larger or equal to the minimum power capability of the unit. Otherwise, the unit can’t be switched ON or OFF as the delta between two time instances is larger than the maximum ramp rate.
Example – solve the unit commitment problem for three generation units
Now, let’s apply the above formulation and solve the unit commitment problem for three generation units over a time horizon of 24 hours.
All three units have different parameters in terms of the cost function, min./max. power and ramp constraints. The most important cornerstones are:
- G1 is the most expensive
- G3 is the cheapest
- G1 has smallest power capability
- G3 has the largest power capability
- Ramp rate is equal to max. power, i.e. the ramp rate does not constrain
The cost function of the units is implemented as a quadratic function as shown below:
The table below summarizes the parameters of all units:
|max. up/down ramp|
|cost function (a0/a1/a2)|
|G1||100||250||± 250||500 / 9 / 0.002|
|G2||120||300||± 300||300 / 7 / 0.0015|
|G3||150||450||± 450||100 / 5 / 0.001|
The hourly load (to be satisfied) is given for a time period of 24 hours. Now we need to find the solution to satisfy the demand for each hour while minimizing the overall costs. In this example, only costs that stem from the generation units, according to their cost functions, are considered.
The screenshot below shows how the parameters and the load are defined in Python:
So let’s discuss the results that are shown in the plot below. The upper subplot shows the contribution of each unit to meet the demand. The lower subplot shows the individual contributions of each unit and also the mismatch, i.e. where the demand cannot be satisfied by the units.
It can be seen that the priority of the generators is according to their costs, the cheapest first and then the more expensive ones. There is one exception at hour 16, where G1 is used instead of G3. This is because G3 has a minimum capability of 150 MW but the load is 100 MW and, therefore, can only be satisfied by G1 which has a minimum capability of 100 MW.
During hours 4-6, the demand can’t be met as the load is higher (1200 MW) than the available generation capacity (1000 MW). This means a mismatch of 200 MW as shown in both subplots.
Similarly, during hours 17-19, the load is lower than the minimum power capacity of all units and, therefore, can’t be met, leading to a mismatch of 99 MW.
The total generation costs of the 24-hour-period amount to 111.3 k€ as shown at the top left of the plot.
Solution time of the implemented code
In a real application, the unit commitment problem must be solved for many more units than in the above example, and for different time horizons. That’s why I analyzed how long it takes to solve the problem with different numbers of units for different time horizons. This should give an estimation of the expected solution time for a specific problem.
For this analysis, only the linear part of the cost function was used. This was mainly done to reduce the overall calculation time of the analysis (still it was running for almost 24 hours). If you also use the quadratic part, the solution time significantly increases compared to the linear cost function. All relevant calculation parameters, i.e. min./max. power, ramp rate, cost function, and load have been varied randomly. For each number of units and timesteps, ten different combinations (with different parameters) were calculated. All calculations were carried out on a laptop with an i7-CPU and 8 GB of RAM.
The plot below shows the results of the calculation time for different numbers of units and timesteps (ts). The calculation time increases more with the number of time steps than with the number of units. That means, for larger time horizons the calculation time increases significantly.
If this was interesting, you might also like the following: An energy storage model to analyze the energy arbitrage potential in a day-ahead electricity market.
More insights to follow in the next article.
Btw: If you are interested in publishing an article on The Smart Insights? Find more information here!