Generators#
PyPSA's Generator, as one fragment. It owns its dimension, its relation into
port, its parameters, its column and its cost, and it reads Port_p from
the surface under
given_variables.
Generator_port stands where PyPSA writes Generator_bus.
The constraint is what makes the library composable:
at(Port_p, by=Generator_port) pins the flow at this component's own port
rather than adding a term to the balance, so the balance never grows.
The file is cut to what a dispatch model needs. A fixed build, no availability profile and no ramp limits are three declarations PyPSA carries and this one does not; the PyPSA rungs are where they are stated in full.
This file loads and prints on its own, which is why the math below it is here.
What it cannot do is name a column nothing introduces: merged with the surface,
Port_p is one declaration again.
description: >-
PyPSA's `Generator`, wired to a port rather than straight to a bus, and cut
to what a dispatch model needs: a fixed build, no availability profile, no
ramp limits.
dimensions:
snapshot: { dtype: datetime, description: dispatch periods }
port: { dtype: str, description: "the connections components make, one label per connection" }
generator: { dtype: str, description: "generating units, each on one port" }
relations:
Generator_port: { key: generator, value: port }
given_variables:
Port_p:
dims: [snapshot, port]
description: the surface introduces this column, and this file only writes into it
parameters:
Generator_p_nom: { dims: [generator], description: nominal power }
Generator_marginal_cost: { dims: [generator], description: cost of one unit of output }
variables:
Generator_p:
dims: [snapshot, generator]
bounds: { lower: 0, upper: Generator_p_nom }
description: "`Generator-p` — what a generator produces in a snapshot"
constraints:
Generator_injection:
description: >-
what a generator produces is what its port injects. No PyPSA row stands
for this: PyPSA writes the generator into the balance instead
dims: [snapshot, generator]
expression: at(Port_p, by=Generator_port) == Generator_p
objective:
sense: minimize
expression: sum(Generator_p * Generator_marginal_cost)
PyPSA's Generator, wired to a port rather than straight to a bus, and cut to what a dispatch model needs: a fixed build, no availability profile, no ramp limits.
Sets#
| Symbol | Meaning |
|---|---|
| \(\mathcal{T}\) | index \(t\) — snapshot — dispatch periods |
| \(\mathcal{J}\) | index \(j\) — port with \(\mathrm{Generator\_port}: \mathcal{G} \to \mathcal{J}\) — the connections components make, one label per connection |
| \(\mathcal{G}\) | index \(g\) — generator with \(\mathrm{Generator\_port}: \mathcal{G} \to \mathcal{J}\) — generating units, each on one port |
Parameters#
| Symbol | Meaning |
|---|---|
| \(\mathrm{p}^{\mathrm{nom}}\) | Generator_p_nom over \(\mathcal{G}\) — nominal power |
| \(\mathrm{c}\) | Generator_marginal_cost over \(\mathcal{G}\) — cost of one unit of output |
Variables#
| Symbol | Meaning |
|---|---|
| \(p\) | Generator_p over \(\mathcal{T} \times \mathcal{G}\) — Generator-p — what a generator produces in a snapshot |
Given#
| Symbol | Meaning |
|---|---|
| \(f\) | Port_p over \(\mathcal{T} \times \mathcal{J}\) — the surface introduces this column, and this file only writes into it |
Objective#
Subject to#
Generator_injection
Variable domains#
Generator_p