Unit Commitment

UC tries to schedule generation to meet the system load for the next several hours at lowest cost. UC adds a dimension of time to the ED problem, with the additional choice of turning generators on or off. The classic text is Wood & Wollenburg.

The problem

mintgCg(P t,g)+C su(g)(u t,g)

System Message: ERROR/3 (/home/docs/sites/readthedocs.org/checkouts/readthedocs.org/user_builds/minpower/checkouts/v1.1.2/doc/unit-commitment.rst, line 22)

Syntax error: "\;"

\mathrm{s.t.} \; P_{\min (g)} \leq P_{t,g} \leq P_{\max (g)}  \; \forall  \; t,g  \; \mathrm{where}  \; u_{t,g}=1

System Message: ERROR/3 (/home/docs/sites/readthedocs.org/checkouts/readthedocs.org/user_builds/minpower/checkouts/v1.1.2/doc/unit-commitment.rst, line 24)

Syntax error: "\;"

\mathrm{s.t.} \; \sum_g P_{t,g}= P_{\mathrm{load}(t)}  \; \forall  \; t

System Message: ERROR/3 (/home/docs/sites/readthedocs.org/checkouts/readthedocs.org/user_builds/minpower/checkouts/v1.1.2/doc/unit-commitment.rst, line 26)

Syntax error: "\;"

\mathrm{s.t.} \; P_{\mathrm{ramp min} (g)} \leq P_{t,g}-P_{t-1,g} \leq P_{\mathrm{ramp max} (g)}    \; \forall  \; t,g

In this mathematical formulation generators are indexed by g and time is indexed by t. P t,g is a generator’s power output at time t and u t,g is its operation status (on/off). Cg() is the generator’s production cost function and C su(g)() is its startup/shutdown cost. The objective is to minimize the total cost. The constraints are:

  • each generator must be within its real power limits
  • total power generated must equal the power consumed by the load
  • each generator must be within its real power ramping limits
  • each generator must be within its up/down time limits

Note

The last constraint is not shown in the formulation above due to complexity. It requires keeping track of how many hours a generator has been on/off. For the actual formulation in use, see powersystems.Generator.constraints().

The basics

Let’s say you have made a folder called mycommitment and put the information about your problem in the folder. Then if you run the script:

from minpower import solve
solve.directory('mycommitment/')

You get a plot:

./_static/demos/commitment/commitment.png

This figure has two plots that share the same time axis. The top plot shows the price of energy for the system. The bottom plot shows the energy that each generator produces.

Note

For only a few generators, results.Solution_UC.vizualization() displays a stack plot showing power for each generator. For more generators, the display is grouped by kind (so that all the coal plants as one color, all the wind as another color, ...).

For this example we have two generators, one named cheap (which produces energy for $45/MWh) and one named expensive (which produces energy for $150/MWh). Obviously we only turn on the expensive generator after we can’t use the cheaper any more (its limit is 100MW for this example). So as the load goes up and over 100MW, the expensive generator is committed.

But why doesn’t the expensive generator turn back off at 6:00, when the load goes back down? It can’t turn off that quickly - it has a minimum up time of 2hrs and a minimum output of 20MW. But why does the price go back down? It’s complicated [1].

The data from the graph is also output in spreadsheet form:

times,prices,status: expensive,power: expensive,status: cheap,power: cheap,load power: small
2011-10-09 01:00:00,45.0,0.0,0.0,1.0,10.0,10
2011-10-09 02:00:00,45.0,0.0,0.0,1.0,10.0,10
2011-10-09 03:00:00,45.0,0.0,0.0,1.0,45.0,45
2011-10-09 04:00:00,45.0,0.0,0.0,1.0,90.0,90
2011-10-09 05:00:00,150.0,1.0,50.0,1.0,100.0,150
2011-10-09 06:00:00,45.0,1.0,5.0,1.0,85.0,90
2011-10-09 07:00:00,45.0,0.0,0.0,1.0,45.0,45
2011-10-09 08:00:00,45.0,0.0,0.0,1.0,10.0,10
2011-10-09 09:00:00,45.0,0.0,0.0,1.0,10.0,10

Unlike ED and OPF results, this spreadsheet is not particularly easy to read. It is meant more for machines than for humans. The spreadsheet gives status and energy output for each generator, along with the system energy price, for each time.

These outputs are saved in the mycommitment folder as commitment.png and commitment.csv.

What’s actually going on?

It’s easy once you get the hang of it. minpower will:
  1. read in your files (see get_data)
  2. set up an optimization problem (see solve.create_problem())
  3. send it off to a solver (see optimization.solve())
  4. show you the results (see results.Solution_UC)

minpower just looks for the files in the mycommitment directory that describe the generators and load.

Tell it the specifics of your problem by editing the generator file (generators.csv):

name,cost curve equation,min up time,P max,P min,startup cost
expensive,150P,2,500,5,0
cheap,45P,0,100,0,0

Note

Cost curves don’t have to be linear. See an example of polynomial cost curves in the ED example or see the documentation in bidding.parsePolynomial().

the initial generator state file (initial.csv):

name,P,status,hours in status
expensive,0,0,10
cheap,10,1,10

the loads file (loads.csv):

name,schedule filename
small,small-changing-load.csv 

Note

You specify each changing load by a schedule file. You can also have loads with fixed power values, which are specified by P. For UC, all loads are summed together to get the system load.

and in this case we just have one schedule file (small-changing-load.csv):

"time","P"
"1:00","10"
"2:00","10"
"3:00","45"
"4:00","90"
"5:00","150"
"6:00","90"
"7:00","45"
"8:00","10"
"9:00","10"

Note

For more information about what options you can specify in each spreadsheet see: Data Input.

Footnotes

[1]Generators at their limits can’t set the price. In the real world the monetary differences are dealt with via a system called “side payments”. In the example above a side payment of $105/MWh would be made to the more expensive generator for its second hour to make sure that it recovers its cost of operating for that hour.

Project Versions

Table Of Contents

Previous topic

Data Input

Next topic

Data Input

This Page