Processes, the maintenance#
One of the 24 fragments of examples/pypsa.yaml: PyPSA's Process, the maintenance rows. It reads Process_active, Process_committable, Process_p_nom_ext, Process_p_nom_extendable, Process_p_nom_max, Process_p_nom_min and 3 more under given.
dimensions:
scenario:
description: the futures dispatch is chosen in, each with a weight
snapshot:
description: dispatch periods
dtype: datetime
process:
description: generalized multi-port converters, each with an internal power that every port draws or delivers at its own rate
relations:
Process_maintenance_cover:
description: >-
the snapshots a maintenance event covers, by the snapshot it starts in —
in a scenario, the start and the snapshots after it, until their
generator weightings reach that scenario's `maintenance_duration`, data prep; no
rows for a process that is
not maintainable
key: { scenario: scenario, process: process, start: snapshot, covered: snapshot }
parameters:
Process_maintainable:
description: >-
whether a process must be taken off for maintenance within the horizon — in
any scenario, as PyPSA takes the union over them (`components.py:1016-1019`)
dims: [process]
dtype: bool
Process_maintenance_pu:
description: the share of the build a maintenance event takes off
dims: [scenario, process]
Process_maintenance_events:
description: how many maintenance events the horizon holds
dims: [scenario, process]
dtype: int
Process_maintenance_duration:
description: >-
the hours of generator weightings one maintenance event covers —
PyPSA's `maintenance_duration`; no value where the process is not
maintainable. No row reads it: data prep turns it into
`Process_maintenance_cover` and `Process_maintenance_start_blocked`, and the
assumptions hold it to the horizon
dims: [scenario, process]
Process_maintenance_start_blocked:
description: >-
true where no maintenance event may start, because the snapshots it
would cover run past the end of the horizon or into one the process does
not stand in — PyPSA's `active & ~valid`, from `maintenance_duration`
and the generator weightings, data prep
dims: [scenario, snapshot, process]
dtype: bool
variables:
Process_maintenance:
description: >-
`Process-maintenance` — whether a maintainable process is in maintenance:
continuous, and one exactly where an event covers the snapshot
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_active
absence: zero
bounds:
lower: 0
upper: 1
Process_maintenance_start:
description: "`Process-maintenance_start` — whether a maintenance event starts in this snapshot"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_active
absence: zero
domain: binary
Process_maintenance_capacity:
description: >-
`Process-maintenance_capacity` — the chosen build while in maintenance, zero
otherwise: the product the `maintcap` rows linearize
dims: [scenario, snapshot, process]
where: >-
Process_maintainable AND Process_p_nom_extendable
AND NOT (Process_committable AND Process_p_nom_mod > 0) AND Process_active
absence: zero
bounds:
lower: 0
Process_maintenance_status:
description: >-
`Process-maintenance_status` — the status while in maintenance, zero
otherwise: the product the `maint-status` rows linearize, so a unit in
maintenance may also be off
dims: [scenario, snapshot, process]
where: >-
Process_maintainable AND Process_committable
AND NOT (Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0)) AND Process_active
absence: zero
bounds:
lower: 0
given:
parameters:
Process_p_nom_extendable: { dims: [process], dtype: bool }
Process_p_nom_min: { dims: [scenario, process] }
Process_p_nom_max: { dims: [scenario, process] }
Process_committable: { dims: [process], dtype: bool }
Process_p_nom_mod: { dims: [process] }
Process_active: { dims: [snapshot, process], dtype: bool }
snapshot_weightings_generators: { dims: [snapshot] }
variables:
Process_status: { dims: [scenario, snapshot, process], domain: integer }
Process_p_nom_ext: { dims: [process] }
constraints:
Process_maint_event_count:
description: "`Process-maint-event-count` — a maintainable process holds its number of maintenance events over the horizon"
dims: [scenario, process]
where: Process_maintainable
expression: sum(Process_maintenance_start, over=snapshot) == Process_maintenance_events
Process_maint_window:
description: >-
`Process-maint-window` — a process is in maintenance exactly where an event it
started covers the snapshot; two events do not overlap, since the
maintenance status is at most one
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_active
expression: Process_maintenance == sum(Process_maintenance_start, by=Process_maintenance_cover, over=start, into=covered)
Process_maint_start_horizon:
description: "`Process-maint-start-horizon` — no event starts where it could not run its whole duration"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_active AND Process_maintenance_start_blocked
expression: Process_maintenance_start == 0
Process_maintcap_upper:
description: >-
`Process-maintcap_upper` — the build taken off is at most the chosen build in
maintenance, and at most the build less its floor out of it
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_p_nom_extendable AND NOT (Process_committable AND Process_p_nom_mod > 0) AND Process_active
expression: Process_maintenance_capacity <= Process_p_nom_ext - Process_p_nom_min * (1 - Process_maintenance)
Process_maintcap_upper_nommax:
description: "`Process-maintcap_upper_nommax` — out of maintenance, no build is taken off"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_p_nom_extendable AND NOT (Process_committable AND Process_p_nom_mod > 0) AND Process_active
expression: Process_maintenance_capacity <= Process_p_nom_max * Process_maintenance
Process_maintcap_lower_nommax:
description: "`Process-maintcap_lower_nommax` — in maintenance, the whole chosen build is taken off"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_p_nom_extendable AND NOT (Process_committable AND Process_p_nom_mod > 0) AND Process_active
expression: Process_maintenance_capacity >= Process_p_nom_ext - Process_p_nom_max * (1 - Process_maintenance)
Process_maintcap_lower_nommin:
description: "`Process-maintcap_lower_nommin` — in maintenance, at least the floor of the build is taken off"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_p_nom_extendable AND NOT (Process_committable AND Process_p_nom_mod > 0) AND Process_active AND Process_p_nom_min > 0
expression: Process_maintenance_capacity >= Process_p_nom_min * Process_maintenance
Process_maint_status_le_status:
description: "`Process-maint-status-le-status` — the status in maintenance is at most the status"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND Process_active
expression: Process_maintenance_status <= Process_status
Process_maint_status_le_maint:
description: "`Process-maint-status-le-maint` — out of maintenance, the status in maintenance is zero"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND Process_active
expression: Process_maintenance_status <= Process_maintenance
Process_maint_status_lb:
description: "`Process-maint-status-lb` — on and in maintenance, the status in maintenance is one"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND Process_active
expression: Process_maintenance_status >= Process_status + Process_maintenance - 1
Process_maint_modstatus_le_status:
description: "`Process-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_committable AND Process_p_nom_mod > 0 AND Process_active
expression: Process_maintenance_status <= Process_status
Process_maint_modstatus_le_maint:
description: >-
`Process-maint-modstatus-le-maint` — out of maintenance, no module is on in
maintenance; in it, at most the modules the build cap holds
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_committable AND Process_p_nom_mod > 0 AND Process_active
expression: Process_maintenance_status <= Process_p_nom_max / Process_p_nom_mod * Process_maintenance
Process_maint_modstatus_lb:
description: "`Process-maint-modstatus-lb` — in maintenance, every module on is on in maintenance"
dims: [scenario, snapshot, process]
where: Process_maintainable AND Process_committable AND Process_p_nom_mod > 0 AND Process_active
expression: Process_maintenance_status >= Process_status - Process_p_nom_max / Process_p_nom_mod * (1 - Process_maintenance)
assumptions:
Process_maintenance_events_positive:
holds: "Process_maintenance_events > 0"
where: "Process_maintainable"
description: >-
a maintainable process with no event schedules no maintenance —
PyPSA refuses it (`consistency.py:1516`)
Process_maintenance_duration_positive:
holds: "Process_maintenance_duration > 0"
where: "Process_maintainable"
description: >-
an event that covers no hours is no maintenance window — PyPSA
refuses it (`consistency.py:1506`)
Process_maintenance_duration_fits_the_horizon:
holds: "Process_maintenance_duration <= sum(snapshot_weightings_generators, over=snapshot)"
where: "Process_maintainable"
description: >-
one event longer than the horizon, in generator weightings, blocks
every start and makes the event count infeasible — PyPSA refuses it
(`consistency.py:1527`)
Process_maintenance_events_fit_the_horizon:
holds: "Process_maintenance_duration * Process_maintenance_events <= sum(snapshot_weightings_generators, over=snapshot)"
where: "Process_maintainable"
description: >-
the events together longer than the horizon, in generator
weightings, cannot all be scheduled — PyPSA refuses it
(`consistency.py:1539`)
Process_maintenance_build_cap_is_finite:
holds: "Process_p_nom_max < inf"
where: "Process_maintainable AND Process_p_nom_extendable"
description: >-
the `maintcap` rows hold the chosen build in maintenance against
`p_nom_max`, so an infinite cap is an infinite coefficient — PyPSA
refuses it (`consistency.py:1551`)
Process_maintenance_module_count_is_finite:
holds: "Process_p_nom_max < inf"
where: "Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND Process_p_nom_mod > 0"
description: >-
the `maint-modstatus` rows bound the modules on in maintenance by
`p_nom_max / p_nom_mod`, so an infinite cap is an infinite
coefficient. PyPSA does not check it, and HiGHS refuses the model
(`constraints.py:500-503`)
Sets#
| Symbol | Meaning |
|---|---|
| \(\Xi\) | index \(\xi\) — scenario with \(\mathrm{Process\_maintenance\_cover} \subseteq \Xi \times \mathcal{J} \times \mathcal{T} \times \mathcal{T}\) — the futures dispatch is chosen in, each with a weight |
| \(\mathcal{T}\) | index \(t\) — snapshot with \(\mathrm{Process\_maintenance\_cover} \subseteq \Xi \times \mathcal{J} \times \mathcal{T} \times \mathcal{T}\) — dispatch periods |
| \(\mathcal{J}\) | index \(j\) — process with \(\mathrm{Process\_maintenance\_cover} \subseteq \Xi \times \mathcal{J} \times \mathcal{T} \times \mathcal{T}\) — generalized multi-port converters, each with an internal power that every port draws or delivers at its own rate |
Parameters#
| Symbol | Meaning |
|---|---|
| \(\mathrm{mnt}^{z}\) | Process_maintainable over \(\mathcal{J}\) — whether a process must be taken off for maintenance within the horizon — in any scenario, as PyPSA takes the union over them (components.py:1016-1019) |
| \(\gamma^{z}\) | Process_maintenance_pu over \(\Xi \times \mathcal{J}\) — the share of the build a maintenance event takes off |
| \(\mathrm{n}^{z,\mathrm{mnt}}\) | Process_maintenance_events over \(\Xi \times \mathcal{J}\) — how many maintenance events the horizon holds |
| \(\tau^{z,\mathrm{mnt}}\) | Process_maintenance_duration over \(\Xi \times \mathcal{J}\) — the hours of generator weightings one maintenance event covers — PyPSA's maintenance_duration; no value where the process is not maintainable. No row reads it: data prep turns it into Process_maintenance_cover and Process_maintenance_start_blocked, and the assumptions hold it to the horizon |
| \(\mathrm{blk}^{z}\) | Process_maintenance_start_blocked over \(\Xi \times \mathcal{T} \times \mathcal{J}\) — true where no maintenance event may start, because the snapshots it would cover run past the end of the horizon or into one the process does not stand in — PyPSA's active & ~valid, from maintenance_duration and the generator weightings, data prep |
Variables#
| Symbol | Meaning |
|---|---|
| \(\mu^{z}\) | Process_maintenance over \(\Xi \times \mathcal{T} \times \mathcal{J}\) — Process-maintenance — whether a maintainable process is in maintenance: continuous, and one exactly where an event covers the snapshot |
| \(\mu^{z,\mathrm{up}}\) | Process_maintenance_start over \(\Xi \times \mathcal{T} \times \mathcal{J}\) — Process-maintenance_start — whether a maintenance event starts in this snapshot |
| \(\mu^{z,\mathrm{nom}}\) | Process_maintenance_capacity over \(\Xi \times \mathcal{T} \times \mathcal{J}\) — Process-maintenance_capacity — the chosen build while in maintenance, zero otherwise: the product the maintcap rows linearize |
| \(\mu^{z,u}\) | Process_maintenance_status over \(\Xi \times \mathcal{T} \times \mathcal{J}\) — Process-maintenance_status — the status while in maintenance, zero otherwise: the product the maint-status rows linearize, so a unit in maintenance may also be off |
Given#
| Symbol | Meaning |
|---|---|
| \(\mathrm{ext}^{z}\) | Process_p_nom_extendable over \(\mathcal{J}\), data another file declares |
| \(\underline{\mathrm{z}}^{\mathrm{nom}}\) | Process_p_nom_min over \(\Xi \times \mathcal{J}\), data another file declares |
| \(\overline{\mathrm{z}}^{\mathrm{nom}}\) | Process_p_nom_max over \(\Xi \times \mathcal{J}\), data another file declares |
| \(\mathrm{com}^{z}\) | Process_committable over \(\mathcal{J}\), data another file declares |
| \(\mathrm{z}^{\mathrm{mod}}\) | Process_p_nom_mod over \(\mathcal{J}\), data another file declares |
| \(\mathrm{on}^{z}\) | Process_active over \(\mathcal{T} \times \mathcal{J}\), data another file declares |
| \(\mathrm{w}^{\mathrm{gen}}\) | snapshot_weightings_generators over \(\mathcal{T}\), data another file declares |
| \(u^{z}\) | Process_status over \(\Xi \times \mathcal{T} \times \mathcal{J}\) |
| \(Z\) | Process_p_nom_ext over \(\mathcal{J}\) |
Subject to#
Process_maint_event_count
Process_maint_window
Process_maint_start_horizon
Process_maintcap_upper
Process_maintcap_upper_nommax
Process_maintcap_lower_nommax
Process_maintcap_lower_nommin
Process_maint_status_le_status
Process_maint_status_le_maint
Process_maint_status_lb
Process_maint_modstatus_le_status
Process_maint_modstatus_le_maint
Process_maint_modstatus_lb
Variable domains#
Process_maintenance
Process_maintenance_start
Process_maintenance_capacity
Process_maintenance_status
Assumptions#
Process_maintenance_events_positive
Process_maintenance_duration_positive
Process_maintenance_duration_fits_the_horizon
Process_maintenance_events_fit_the_horizon
Process_maintenance_build_cap_is_finite
Process_maintenance_module_count_is_finite