A curve that is not convex#
The same dispatch model, with a curve that bends both ways. Nothing about the
objective now keeps the weights on one segment, so the method builds the
restriction out of binaries. adjacency is the default, and this is what it
costs.
Compare the math with the convex page. A second variable
appears, cost_curve_seg, one binary per segment. Two rows come with it:
cost_curve_pick picks exactly one segment, and cost_curve_adjacency holds
each weight under the segments it borders. The link rows and the convexity row
are unchanged.
description: >-
The same least-cost dispatch as `piecewise.yaml`, with a cost curve that is
not convex. The weights need binaries to hold them on one segment, which is
what the default method builds.
dimensions:
snapshot:
description: dispatch periods
dtype: int
generator:
description: dispatchable units
dtype: str
bp:
description: breakpoints of the cost curve
dtype: int
parameters:
capacity:
description: maximum dispatch
dims: [generator]
load:
description: demand to be met
dims: [snapshot]
bp_x:
description: breakpoint dispatch levels, one curve per generator
dims: [generator, bp]
bp_y:
description: cost at each breakpoint, one curve per generator
dims: [generator, bp]
variables:
dispatch:
description: dispatched power
dims: [snapshot, generator]
bounds:
lower: 0
upper: capacity
op_cost:
description: operating cost, piecewise-linear in dispatch
dims: [snapshot, generator]
bounds:
lower: 0
piecewise:
cost_curve:
description: >-
cost read off the generator's curve. The curve bends both ways, so
nothing but the restriction keeps the weights on one segment: a binary
per segment picks the one they may sit on
along: bp
dims: [snapshot, generator]
links:
dispatch: [dispatch, bp_x]
op_cost: [op_cost, bp_y]
method: adjacency
constraints:
balance:
dims: [snapshot]
expression: sum(dispatch, over=generator) == load
objective:
sense: minimize
description: total operating cost, taken off the curves rather than from a marginal rate
expression: sum(op_cost)
The same least-cost dispatch as piecewise.yaml, with a cost curve that is not convex. The weights need binaries to hold them on one segment, which is what the default method builds.
Sets#
| Symbol | Meaning |
|---|---|
| \(\mathcal{T}\) | index \(t\) — snapshot — dispatch periods |
| \(\mathcal{G}\) | index \(g\) — generator — dispatchable units |
| \(\mathcal{B}\) | index \(b\) — bp — breakpoints of the cost curve |
Parameters#
| Symbol | Meaning |
|---|---|
| \(\mathrm{capacity}\) | capacity over \(\mathcal{G}\) — maximum dispatch |
| \(\mathrm{load}\) | load over \(\mathcal{T}\) — demand to be met |
| \(\mathrm{x}\) | bp_x over \(\mathcal{G} \times \mathcal{B}\) — breakpoint dispatch levels, one curve per generator |
| \(\mathrm{y}\) | bp_y over \(\mathcal{G} \times \mathcal{B}\) — cost at each breakpoint, one curve per generator |
Variables#
| Symbol | Meaning |
|---|---|
| \(\mathit{dispatch}\) | dispatch over \(\mathcal{T} \times \mathcal{G}\) — dispatched power |
| \(\mathit{op\_cost}\) | op_cost over \(\mathcal{T} \times \mathcal{G}\) — operating cost, piecewise-linear in dispatch |
Upright is what the data supplies — a parameter such as \(\mathrm{capacity}\), a coordinate map, a label — and italic is what the solver chooses, such as \(\mathit{dispatch}\). An index is italic too, being what a quantifier chooses, and a set is script.
Objective#
Subject to#
balance
cost_curve
Variable domains#
dispatch
op_cost
Assumptions#
cost_curve_complete