PyPSA in 24 files#
PyPSA in one file is examples/pypsa.yaml, one spec of some
four thousand lines. This is the same spec as 24 files under
examples/pypsa/, one per topic, and merge gives the one file back: the
two have one canonical form.
Every fragment loads, prints and gets advice on its own. What it reads and does
not declare, it states under
given. A component that
puts something into a sum every component adds to, such as the bus balance or
the operating cost, names its share as an expression of its own and adds it
with a term.
One fragment declares each sum as an
empty sum, empty: true, so a
term always lands. A new component is one new file, and the network does
not change.
The split is written by tools/pypsa_split.py from the one file and checked
against it, so the two cannot drift. It is a proof of concept: a decision on
which of the two is the source comes after both land.
What each file says#
Three kinds of file. A component owns PyPSA's class of that name: its
dimension, its data, its columns, its rows, and its share of each sum. The
committable classes, Generator, Link and Process, are cut by feature into
a file each for the class, its commitment, its ramping and its maintenance,
and the three sets read alike because PyPSA's rows do. An owner declares
a sum as empty: true over its frame, and the row that reads it: the network
declares Bus_injection, power flow declares Cycle_angle_sum. Settings
holds what every topic reads, the weightings and the flags, and declares the
totals whose own readers, the cost, the carriers and the global constraints, a
model may leave out.
The sums#
The fragments#
| Fragment | Parameters | Variables | Constraints | Reads | Adds to |
|---|---|---|---|---|---|
| carrier | 2 | 0 | 1 | 1 | |
| cost | 1 | 3 | 2 | 3 | |
| generator | 23 | 3 | 11 | 16 | primary_energy, operational_limit, tech_capacity_expansion, scenario_opex, Carrier_additions, Bus_injection |
| generator_commitment | 10 | 3 | 20 | 17 | scenario_opex |
| generator_maintenance | 5 | 4 | 13 | 9 | |
| generator_ramping | 5 | 0 | 6 | 14 | |
| global_constraints | 3 | 0 | 15 | 6 | |
| line | 18 | 3 | 11 | 8 | transmission_volume_expansion, transmission_expansion_cost, tech_capacity_expansion, Carrier_additions, Bus_injection, Cycle_angle_sum |
| link | 23 | 3 | 9 | 14 | transmission_volume_expansion, transmission_expansion_cost, tech_capacity_expansion, scenario_opex, Carrier_additions, Bus_injection |
| link_commitment | 10 | 3 | 20 | 17 | scenario_opex |
| link_maintenance | 5 | 4 | 13 | 9 | |
| link_ramping | 5 | 0 | 6 | 14 | |
| load | 3 | 0 | 0 | 1 | Bus_injection |
| network | 0 | 0 | 1 | 0 | |
| power_flow | 0 | 0 | 1 | 0 | |
| process | 21 | 3 | 9 | 12 | tech_capacity_expansion, scenario_opex, Carrier_additions, Bus_injection |
| process_commitment | 10 | 3 | 20 | 17 | scenario_opex |
| process_maintenance | 5 | 4 | 13 | 9 | |
| process_ramping | 5 | 0 | 6 | 14 | |
| security | 2 | 0 | 8 | 10 | |
| settings | 9 | 0 | 0 | 0 | |
| storage_unit | 34 | 5 | 20 | 14 | primary_energy, operational_limit, tech_capacity_expansion, scenario_opex, Carrier_additions, Bus_injection |
| store | 27 | 3 | 10 | 14 | primary_energy, operational_limit, tech_capacity_expansion, scenario_opex, Carrier_additions, Bus_injection |
| transformer | 19 | 4 | 11 | 4 | Bus_injection, Cycle_angle_sum |
Leaving a file out#
A model may leave a component family out, or the cost, the carriers, the
global constraints or security, and what is left is a whole model: nothing
stays under given:. It may not leave the network or power flow out while a
component is in, because the component's terms would land on no name, and
merge says so.