From 38bffcc82b6c5f4e81238adee89812c733bad903 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 29 Sep 2026 13:53:11 +0200 Subject: [PATCH 1/3] docs(pypsa): a fixed modular committable unit gets only its per-module commitment rows, as in pypsa master --- docs/examples/pypsa.md | 66 ++++++++++---------- docs/examples/pypsa/generator_commitment.md | 8 +-- docs/examples/pypsa/generator_maintenance.md | 12 ++-- docs/examples/pypsa/link_commitment.md | 8 +-- docs/examples/pypsa/link_maintenance.md | 12 ++-- docs/examples/pypsa/process_commitment.md | 8 +-- docs/examples/pypsa/process_maintenance.md | 12 ++-- examples/pypsa.yaml | 30 ++++----- examples/pypsa/generator_commitment.yaml | 4 +- examples/pypsa/generator_maintenance.yaml | 6 +- examples/pypsa/link_commitment.yaml | 4 +- examples/pypsa/link_maintenance.yaml | 6 +- examples/pypsa/process_commitment.yaml | 4 +- examples/pypsa/process_maintenance.yaml | 6 +- tests/test_pypsa_references.py | 29 +++++++++ 15 files changed, 122 insertions(+), 93 deletions(-) diff --git a/docs/examples/pypsa.md b/docs/examples/pypsa.md index d119f141..48196461 100644 --- a/docs/examples/pypsa.md +++ b/docs/examples/pypsa.md @@ -611,7 +611,7 @@ def build(): | PyPSA | status | note | | -------------------------------------------- | ------ | ------------------------------------------------------------- | | [`{c}-status`, `-start_up`, `-shut_down`](#variable-domains) | done | Generator; Link in rung 25, Process in rung 26 | -| [`{c}-com-p-lower/upper`](#generator-com-p-lower) | done | | +| [`{c}-com-p-lower/upper`](#generator-com-p-lower) | done | not for a modular build, which takes `com-mod-p-*` (PyPSA/PyPSA#1901) | | [`{c}-*-p-fixed-upper`](#generator-status-p-fixed-upper) | done | status, start and stop each at most one, as explicit rows | | [`{c}-com-transition-start-up/shut-down`](#generator-com-transition-start-up) | done | the state carried into a snapshot is a cased quantity, so the first snapshot needs no block of its own | | [`{c}-com-up-time`, `-down-time`](#generator-com-up-time) | done | `sum_back(window=min_up_time)` | @@ -687,7 +687,7 @@ def build(): | [`{c}-n_mod`, `{c}-p_nom_modularity`](#generator-p_nom_modularity) | done | | | [`{c}-*-p_nom-variable-upper`](#generator-status-p_nom-variable-upper) | done | a modular unit is on only where a module is built | | [`{c}-*-p-fixed-upper`, modular](#generator-status-p-fixed-upper) | done | the cap is the build's whole count of modules, `p_nom / p_nom_mod` in data prep, see X1; rung 8's `array` fixes one (#123) | -| [`{c}-com-mod-p-lower/upper`](#generator-com-mod-p-lower) | done | one module's share, times the status — a fixed build too, beside its ordinary `com-p-*` rows | +| [`{c}-com-mod-p-lower/upper`](#generator-com-mod-p-lower) | done | one module's share, times the status — a fixed build too, in place of the `com-p-*` rows (PyPSA/PyPSA#1901) | | [`{c}-com-ext-p-*` (big-M)](#generator-com-ext-p-upper-cap) | done | a cap row beside a big-M row; `M` is the build cap at full availability, data prep | | [`{c}-com-ext-p-lower-nonneg`](#generator-com-ext-p-lower-nonneg) | done | `(p_min_pu >= 0).all()` is prep | | [`{c}-p-ramp_limit_*-bigM`](#generator-p-ramp_limit_up-run-bigm) | done | run and start rows up, run and shut rows down; the output carried in is a cased quantity, so each is one block. A modular build takes the ordinary rows against one module instead, rung 27 | @@ -2839,7 +2839,7 @@ With the same network and no `maintainable`, PyPSA solves to `5370.0`. | PyPSA | status | note | | --- | --- | --- | | [`Generator-maintenance_status`](#variable-domains), and the `Link` and `Process` ones | done | | -| [`Generator-maint-status-*`](#generator-maint-status-le-status), [`-maint-modstatus-*`](#generator-maint-modstatus-le-status), and the `Link` and `Process` ones | done | a fixed build's status, and a modular build's module count | +| [`Generator-maint-status-*`](#generator-maint-status-le-status), [`-maint-modstatus-*`](#generator-maint-modstatus-le-status), and the `Link` and `Process` ones | done | `maint-status` for a fixed build that is not modular, `maint-modstatus` for a modular build, fixed or not (PyPSA/PyPSA#1901) | | [`Generator-com-p-*`](#generator-com-p-lower), [`-com-mod-p-*`](#generator-com-mod-p-lower), [`-com-ext-p-lower`](#generator-com-ext-p-lower), [`-com-ext-p-upper-cap`](#generator-com-ext-p-upper-cap), and the `Link` and `Process` ones, in maintenance | done | | @@ -5824,12 +5824,12 @@ StorageUnit_fix_state_of_charge_upper: Generator_com_p_lower: description: "`Generator-com-p-lower` — a committed unit outputs at least its minimum; off, at least nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p >= Generator_p_min_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) ``` ```math -p_{\xi,t,g} \ge \underline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +p_{\xi,t,g} \ge \underline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` ### `Generator-com-p-upper` @@ -5840,12 +5840,12 @@ p_{\xi,t,g} \ge \underline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}} Generator_com_p_upper: description: "`Generator-com-p-upper` — a committed unit outputs at most what is available; off, at most nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p <= Generator_p_max_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) ``` ```math -p_{\xi,t,g} \le \overline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +p_{\xi,t,g} \le \overline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` ### `Generator-com-transition-start-up` @@ -6414,12 +6414,12 @@ Generator_maintcap_lower_nommin: Generator_maint_status_le_status: description: "`Generator-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_status ``` ```math -\mu^{u}_{\xi,t,g} \le u_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +\mu^{u}_{\xi,t,g} \le u_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` ### `Generator-maint-status-le-maint` @@ -6430,12 +6430,12 @@ Generator_maint_status_le_status: Generator_maint_status_le_maint: description: "`Generator-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_maintenance ``` ```math -\mu^{u}_{\xi,t,g} \le \mu_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +\mu^{u}_{\xi,t,g} \le \mu_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` ### `Generator-maint-status-lb` @@ -6446,12 +6446,12 @@ Generator_maint_status_le_maint: Generator_maint_status_lb: description: "`Generator-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status >= Generator_status + Generator_maintenance - 1 ``` ```math -\mu^{u}_{\xi,t,g} \ge u_{\xi,t,g} + \mu_{\xi,t,g} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +\mu^{u}_{\xi,t,g} \ge u_{\xi,t,g} + \mu_{\xi,t,g} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` ### `Generator-maint-modstatus-le-status` @@ -6512,12 +6512,12 @@ Generator_maint_modstatus_lb: Link_com_p_lower: description: "`Link-com-p-lower` — a committed link flows at least its minimum; off, at least nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p >= Link_p_min_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) ``` ```math -f_{\xi,t,l} \ge \underline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +f_{\xi,t,l} \ge \underline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` ### `Link-com-p-upper` @@ -6528,12 +6528,12 @@ f_{\xi,t,l} \ge \underline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}} Link_com_p_upper: description: "`Link-com-p-upper` — a committed link flows at most what is available; off, at most nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p <= Link_p_max_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) ``` ```math -f_{\xi,t,l} \le \overline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +f_{\xi,t,l} \le \overline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` ### `Link-com-transition-start-up` @@ -7102,12 +7102,12 @@ Link_maintcap_lower_nommin: Link_maint_status_le_status: description: "`Link-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_status ``` ```math -\mu^{f,u}_{\xi,t,l} \le u^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\mu^{f,u}_{\xi,t,l} \le u^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` ### `Link-maint-status-le-maint` @@ -7118,12 +7118,12 @@ Link_maint_status_le_status: Link_maint_status_le_maint: description: "`Link-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_maintenance ``` ```math -\mu^{f,u}_{\xi,t,l} \le \mu^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\mu^{f,u}_{\xi,t,l} \le \mu^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` ### `Link-maint-status-lb` @@ -7134,12 +7134,12 @@ Link_maint_status_le_maint: Link_maint_status_lb: description: "`Link-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status >= Link_status + Link_maintenance - 1 ``` ```math -\mu^{f,u}_{\xi,t,l} \ge u^{f}_{\xi,t,l} + \mu^{f}_{\xi,t,l} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\mu^{f,u}_{\xi,t,l} \ge u^{f}_{\xi,t,l} + \mu^{f}_{\xi,t,l} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` ### `Link-maint-modstatus-le-status` @@ -7200,12 +7200,12 @@ Link_maint_modstatus_lb: Process_com_p_lower: description: "`Process-com-p-lower` — a committed process runs at least its minimum; off, at least nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p >= Process_p_min_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) ``` ```math -z_{\xi,t,j} \ge \underline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +z_{\xi,t,j} \ge \underline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` ### `Process-com-p-upper` @@ -7216,12 +7216,12 @@ z_{\xi,t,j} \ge \underline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}} Process_com_p_upper: description: "`Process-com-p-upper` — a committed process runs at most what is available; off, at most nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p <= Process_p_max_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) ``` ```math -z_{\xi,t,j} \le \overline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +z_{\xi,t,j} \le \overline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` ### `Process-com-transition-start-up` @@ -7790,12 +7790,12 @@ Process_maintcap_lower_nommin: 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_maintenance_status <= Process_status ``` ```math -\mu^{z,u}_{\xi,t,j} \le u^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mu^{z,u}_{\xi,t,j} \le u^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` ### `Process-maint-status-le-maint` @@ -7806,12 +7806,12 @@ Process_maint_status_le_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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_maintenance_status <= Process_maintenance ``` ```math -\mu^{z,u}_{\xi,t,j} \le \mu^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mu^{z,u}_{\xi,t,j} \le \mu^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` ### `Process-maint-status-lb` @@ -7822,12 +7822,12 @@ Process_maint_status_le_maint: 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_maintenance_status >= Process_status + Process_maintenance - 1 ``` ```math -\mu^{z,u}_{\xi,t,j} \ge u^{z}_{\xi,t,j} + \mu^{z}_{\xi,t,j} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mu^{z,u}_{\xi,t,j} \ge u^{z}_{\xi,t,j} + \mu^{z}_{\xi,t,j} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` ### `Process-maint-modstatus-le-status` diff --git a/docs/examples/pypsa/generator_commitment.md b/docs/examples/pypsa/generator_commitment.md index 2384d6f3..e5a497d8 100644 --- a/docs/examples/pypsa/generator_commitment.md +++ b/docs/examples/pypsa/generator_commitment.md @@ -139,12 +139,12 @@ constraints: Generator_com_p_lower: description: "`Generator-com-p-lower` — a committed unit outputs at least its minimum; off, at least nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p >= Generator_p_min_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) Generator_com_p_upper: description: "`Generator-com-p-upper` — a committed unit outputs at most what is available; off, at most nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p <= Generator_p_max_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) Generator_com_transition_start_up: description: "`Generator-com-transition-start-up` — turning on is a start, counted against the state the unit carried into the snapshot" @@ -339,13 +339,13 @@ $`\mathrm{pos}(t)`$ denotes where index $`t`$ sits along its dimension's own ord **`Generator_com_p_lower`** ```math -p_{\xi,t,g} \ge \underline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +p_{\xi,t,g} \ge \underline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` **`Generator_com_p_upper`** ```math -p_{\xi,t,g} \le \overline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +p_{\xi,t,g} \le \overline{\mathrm{p}}_{\xi,t,g} \cdot \mathrm{p}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \gamma_{\xi,g} \cdot \mu^{u}_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` **`Generator_com_transition_start_up`** diff --git a/docs/examples/pypsa/generator_maintenance.md b/docs/examples/pypsa/generator_maintenance.md index de416877..69552618 100644 --- a/docs/examples/pypsa/generator_maintenance.md +++ b/docs/examples/pypsa/generator_maintenance.md @@ -157,17 +157,17 @@ constraints: Generator_maint_status_le_status: description: "`Generator-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_status Generator_maint_status_le_maint: description: "`Generator-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_maintenance Generator_maint_status_lb: description: "`Generator-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status >= Generator_status + Generator_maintenance - 1 Generator_maint_modstatus_le_status: description: "`Generator-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on" @@ -319,19 +319,19 @@ assumptions: **`Generator_maint_status_le_status`** ```math -\mu^{u}_{\xi,t,g} \le u_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +\mu^{u}_{\xi,t,g} \le u_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` **`Generator_maint_status_le_maint`** ```math -\mu^{u}_{\xi,t,g} \le \mu_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +\mu^{u}_{\xi,t,g} \le \mu_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` **`Generator_maint_status_lb`** ```math -\mu^{u}_{\xi,t,g} \ge u_{\xi,t,g} + \mu_{\xi,t,g} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \mathrm{on}_{t,g} +\mu^{u}_{\xi,t,g} \ge u_{\xi,t,g} + \mu_{\xi,t,g} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{com}_{g} \wedge \neg \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} ``` **`Generator_maint_modstatus_le_status`** diff --git a/docs/examples/pypsa/link_commitment.md b/docs/examples/pypsa/link_commitment.md index 0f76a073..e32fce23 100644 --- a/docs/examples/pypsa/link_commitment.md +++ b/docs/examples/pypsa/link_commitment.md @@ -139,12 +139,12 @@ constraints: Link_com_p_lower: description: "`Link-com-p-lower` — a committed link flows at least its minimum; off, at least nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p >= Link_p_min_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) Link_com_p_upper: description: "`Link-com-p-upper` — a committed link flows at most what is available; off, at most nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p <= Link_p_max_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) Link_com_transition_start_up: description: "`Link-com-transition-start-up` — turning on is a start, counted against the state the link carried into the snapshot" @@ -339,13 +339,13 @@ $`\mathrm{pos}(t)`$ denotes where index $`t`$ sits along its dimension's own ord **`Link_com_p_lower`** ```math -f_{\xi,t,l} \ge \underline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +f_{\xi,t,l} \ge \underline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` **`Link_com_p_upper`** ```math -f_{\xi,t,l} \le \overline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +f_{\xi,t,l} \le \overline{\mathrm{f}}_{\xi,t,l} \cdot \mathrm{f}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \gamma^{f}_{\xi,l} \cdot \mu^{f,u}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` **`Link_com_transition_start_up`** diff --git a/docs/examples/pypsa/link_maintenance.md b/docs/examples/pypsa/link_maintenance.md index d8b5ed3d..4d08cab0 100644 --- a/docs/examples/pypsa/link_maintenance.md +++ b/docs/examples/pypsa/link_maintenance.md @@ -157,17 +157,17 @@ constraints: Link_maint_status_le_status: description: "`Link-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_status Link_maint_status_le_maint: description: "`Link-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_maintenance Link_maint_status_lb: description: "`Link-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status >= Link_status + Link_maintenance - 1 Link_maint_modstatus_le_status: description: "`Link-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on" @@ -319,19 +319,19 @@ assumptions: **`Link_maint_status_le_status`** ```math -\mu^{f,u}_{\xi,t,l} \le u^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\mu^{f,u}_{\xi,t,l} \le u^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` **`Link_maint_status_le_maint`** ```math -\mu^{f,u}_{\xi,t,l} \le \mu^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\mu^{f,u}_{\xi,t,l} \le \mu^{f}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` **`Link_maint_status_lb`** ```math -\mu^{f,u}_{\xi,t,l} \ge u^{f}_{\xi,t,l} + \mu^{f}_{\xi,t,l} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\mu^{f,u}_{\xi,t,l} \ge u^{f}_{\xi,t,l} + \mu^{f}_{\xi,t,l} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{com}^{f}_{l} \wedge \neg \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} ``` **`Link_maint_modstatus_le_status`** diff --git a/docs/examples/pypsa/process_commitment.md b/docs/examples/pypsa/process_commitment.md index f2087dc2..93878ab1 100644 --- a/docs/examples/pypsa/process_commitment.md +++ b/docs/examples/pypsa/process_commitment.md @@ -139,12 +139,12 @@ constraints: Process_com_p_lower: description: "`Process-com-p-lower` — a committed process runs at least its minimum; off, at least nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p >= Process_p_min_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) Process_com_p_upper: description: "`Process-com-p-upper` — a committed process runs at most what is available; off, at most nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p <= Process_p_max_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) Process_com_transition_start_up: description: "`Process-com-transition-start-up` — turning on is a start, counted against the state the process carried into the snapshot" @@ -339,13 +339,13 @@ $`\mathrm{pos}(t)`$ denotes where index $`t`$ sits along its dimension's own ord **`Process_com_p_lower`** ```math -z_{\xi,t,j} \ge \underline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +z_{\xi,t,j} \ge \underline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` **`Process_com_p_upper`** ```math -z_{\xi,t,j} \le \overline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +z_{\xi,t,j} \le \overline{\mathrm{z}}_{\xi,t,j} \cdot \mathrm{z}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \gamma^{z}_{\xi,j} \cdot \mu^{z,u}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` **`Process_com_transition_start_up`** diff --git a/docs/examples/pypsa/process_maintenance.md b/docs/examples/pypsa/process_maintenance.md index 0c223e1b..a420a8ca 100644 --- a/docs/examples/pypsa/process_maintenance.md +++ b/docs/examples/pypsa/process_maintenance.md @@ -157,17 +157,17 @@ constraints: 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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" @@ -319,19 +319,19 @@ assumptions: **`Process_maint_status_le_status`** ```math -\mu^{z,u}_{\xi,t,j} \le u^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mu^{z,u}_{\xi,t,j} \le u^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` **`Process_maint_status_le_maint`** ```math -\mu^{z,u}_{\xi,t,j} \le \mu^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mu^{z,u}_{\xi,t,j} \le \mu^{z}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` **`Process_maint_status_lb`** ```math -\mu^{z,u}_{\xi,t,j} \ge u^{z}_{\xi,t,j} + \mu^{z}_{\xi,t,j} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mu^{z,u}_{\xi,t,j} \ge u^{z}_{\xi,t,j} + \mu^{z}_{\xi,t,j} - 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{com}^{z}_{j} \wedge \neg \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} ``` **`Process_maint_modstatus_le_status`** diff --git a/examples/pypsa.yaml b/examples/pypsa.yaml index 98ed8b5d..8f10bd0c 100644 --- a/examples/pypsa.yaml +++ b/examples/pypsa.yaml @@ -2511,12 +2511,12 @@ constraints: Generator_com_p_lower: description: "`Generator-com-p-lower` — a committed unit outputs at least its minimum; off, at least nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p >= Generator_p_min_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) Generator_com_p_upper: description: "`Generator-com-p-upper` — a committed unit outputs at most what is available; off, at most nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p <= Generator_p_max_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) Generator_com_transition_start_up: description: "`Generator-com-transition-start-up` — turning on is a start, counted against the state the unit carried into the snapshot" @@ -2749,17 +2749,17 @@ constraints: Generator_maint_status_le_status: description: "`Generator-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_status Generator_maint_status_le_maint: description: "`Generator-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_maintenance Generator_maint_status_lb: description: "`Generator-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status >= Generator_status + Generator_maintenance - 1 Generator_maint_modstatus_le_status: description: "`Generator-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on" @@ -2781,12 +2781,12 @@ constraints: Link_com_p_lower: description: "`Link-com-p-lower` — a committed link flows at least its minimum; off, at least nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p >= Link_p_min_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) Link_com_p_upper: description: "`Link-com-p-upper` — a committed link flows at most what is available; off, at most nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p <= Link_p_max_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) Link_com_transition_start_up: description: "`Link-com-transition-start-up` — turning on is a start, counted against the state the link carried into the snapshot" @@ -3019,17 +3019,17 @@ constraints: Link_maint_status_le_status: description: "`Link-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_status Link_maint_status_le_maint: description: "`Link-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_maintenance Link_maint_status_lb: description: "`Link-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status >= Link_status + Link_maintenance - 1 Link_maint_modstatus_le_status: description: "`Link-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on" @@ -3051,12 +3051,12 @@ constraints: Process_com_p_lower: description: "`Process-com-p-lower` — a committed process runs at least its minimum; off, at least nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p >= Process_p_min_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) Process_com_p_upper: description: "`Process-com-p-upper` — a committed process runs at most what is available; off, at most nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p <= Process_p_max_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) Process_com_transition_start_up: description: "`Process-com-transition-start-up` — turning on is a start, counted against the state the process carried into the snapshot" @@ -3289,17 +3289,17 @@ constraints: 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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" diff --git a/examples/pypsa/generator_commitment.yaml b/examples/pypsa/generator_commitment.yaml index 8551031e..e12358e1 100644 --- a/examples/pypsa/generator_commitment.yaml +++ b/examples/pypsa/generator_commitment.yaml @@ -132,12 +132,12 @@ constraints: Generator_com_p_lower: description: "`Generator-com-p-lower` — a committed unit outputs at least its minimum; off, at least nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p >= Generator_p_min_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) Generator_com_p_upper: description: "`Generator-com-p-upper` — a committed unit outputs at most what is available; off, at most nothing" dims: [scenario, snapshot, generator] - where: Generator_committable AND not Generator_p_nom_extendable AND Generator_active + where: Generator_committable AND not Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_p <= Generator_p_max_pu * Generator_p_nom * (Generator_status - Generator_maintenance_pu * Generator_maintenance_status) Generator_com_transition_start_up: description: "`Generator-com-transition-start-up` — turning on is a start, counted against the state the unit carried into the snapshot" diff --git a/examples/pypsa/generator_maintenance.yaml b/examples/pypsa/generator_maintenance.yaml index 1f8ca404..0c5bc6e5 100644 --- a/examples/pypsa/generator_maintenance.yaml +++ b/examples/pypsa/generator_maintenance.yaml @@ -150,17 +150,17 @@ constraints: Generator_maint_status_le_status: description: "`Generator-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_status Generator_maint_status_le_maint: description: "`Generator-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status <= Generator_maintenance Generator_maint_status_lb: description: "`Generator-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, generator] - where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND Generator_active + where: Generator_maintainable AND Generator_committable AND NOT Generator_p_nom_extendable AND NOT (Generator_p_nom_mod > 0) AND Generator_active expression: Generator_maintenance_status >= Generator_status + Generator_maintenance - 1 Generator_maint_modstatus_le_status: description: "`Generator-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on" diff --git a/examples/pypsa/link_commitment.yaml b/examples/pypsa/link_commitment.yaml index 9c5cea68..b333f22f 100644 --- a/examples/pypsa/link_commitment.yaml +++ b/examples/pypsa/link_commitment.yaml @@ -132,12 +132,12 @@ constraints: Link_com_p_lower: description: "`Link-com-p-lower` — a committed link flows at least its minimum; off, at least nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p >= Link_p_min_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) Link_com_p_upper: description: "`Link-com-p-upper` — a committed link flows at most what is available; off, at most nothing" dims: [scenario, snapshot, link] - where: Link_committable AND not Link_p_nom_extendable AND Link_active + where: Link_committable AND not Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_p <= Link_p_max_pu * Link_p_nom * (Link_status - Link_maintenance_pu * Link_maintenance_status) Link_com_transition_start_up: description: "`Link-com-transition-start-up` — turning on is a start, counted against the state the link carried into the snapshot" diff --git a/examples/pypsa/link_maintenance.yaml b/examples/pypsa/link_maintenance.yaml index e81eefbf..fd4daa19 100644 --- a/examples/pypsa/link_maintenance.yaml +++ b/examples/pypsa/link_maintenance.yaml @@ -150,17 +150,17 @@ constraints: Link_maint_status_le_status: description: "`Link-maint-status-le-status` — the status in maintenance is at most the status" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_status Link_maint_status_le_maint: description: "`Link-maint-status-le-maint` — out of maintenance, the status in maintenance is zero" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status <= Link_maintenance Link_maint_status_lb: description: "`Link-maint-status-lb` — on and in maintenance, the status in maintenance is one" dims: [scenario, snapshot, link] - where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND Link_active + where: Link_maintainable AND Link_committable AND NOT Link_p_nom_extendable AND NOT (Link_p_nom_mod > 0) AND Link_active expression: Link_maintenance_status >= Link_status + Link_maintenance - 1 Link_maint_modstatus_le_status: description: "`Link-maint-modstatus-le-status` — the modules on in maintenance are at most the modules on" diff --git a/examples/pypsa/process_commitment.yaml b/examples/pypsa/process_commitment.yaml index 79c1a12d..15190282 100644 --- a/examples/pypsa/process_commitment.yaml +++ b/examples/pypsa/process_commitment.yaml @@ -132,12 +132,12 @@ constraints: Process_com_p_lower: description: "`Process-com-p-lower` — a committed process runs at least its minimum; off, at least nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p >= Process_p_min_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) Process_com_p_upper: description: "`Process-com-p-upper` — a committed process runs at most what is available; off, at most nothing" dims: [scenario, snapshot, process] - where: Process_committable AND not Process_p_nom_extendable AND Process_active + where: Process_committable AND not Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) AND Process_active expression: Process_p <= Process_p_max_pu * Process_p_nom * (Process_status - Process_maintenance_pu * Process_maintenance_status) Process_com_transition_start_up: description: "`Process-com-transition-start-up` — turning on is a start, counted against the state the process carried into the snapshot" diff --git a/examples/pypsa/process_maintenance.yaml b/examples/pypsa/process_maintenance.yaml index 2f1b9de8..594968b1 100644 --- a/examples/pypsa/process_maintenance.yaml +++ b/examples/pypsa/process_maintenance.yaml @@ -150,17 +150,17 @@ constraints: 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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 + where: Process_maintainable AND Process_committable AND NOT Process_p_nom_extendable AND NOT (Process_p_nom_mod > 0) 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" diff --git a/tests/test_pypsa_references.py b/tests/test_pypsa_references.py index bc076779..c69bbbed 100644 --- a/tests/test_pypsa_references.py +++ b/tests/test_pypsa_references.py @@ -156,6 +156,35 @@ def test_every_declared_row_is_built_by_some_reference(): assert not unbuilt, f'no reference network builds these declared rows — extend a fixture: {sorted(unbuilt)}' +def _admits(where: str, component: str, unit: dict[str, object]) -> bool: + """Whether a `where` over one component's own columns holds for a unit with those column values.""" + text = re.sub(rf'\b{component}_(\w+)', lambda column: repr(unit[column.group(1)]), where) + return eval(re.sub(r'\bNOT\b', 'not', text, flags=re.IGNORECASE).replace(' AND ', ' and ')) + + +@pytest.mark.parametrize('component', ['Generator', 'Link', 'Process']) +def test_a_fixed_modular_committable_unit_gets_only_its_per_module_commitment_rows(component: str): + """PyPSA/PyPSA#1901: the file built `com-p-*` and `maint-status-*` for rung 8's `array`, which PyPSA master does not. + + Those rows scale `p_nom` by a status that counts modules, which held rungs + 25 and 26 above PyPSA's objective. + """ + unit = {'committable': True, 'p_nom_extendable': False, 'p_nom_mod': 5.0, 'maintainable': True, 'active': True} + families = ('com_p_', 'com_mod_p_', 'maint_status_', 'maint_modstatus_') + admitted = { + name.removeprefix(f'{component}_') + for name, block in BASE.constraints.items() + if name.removeprefix(f'{component}_').startswith(families) and _admits(block.where, component, unit) + } + assert admitted == { + 'com_mod_p_lower', + 'com_mod_p_upper', + 'maint_modstatus_le_status', + 'maint_modstatus_le_maint', + 'maint_modstatus_lb', + }, 'a fixed modular committable unit gets the per-module rows and no whole-unit ones' + + def test_the_spine_weightings_are_generic(): """At weighting 1.0 a missing hours factor builds the identical matrix and passes every gate.""" sys.path.insert(0, str(REFERENCES)) From 726556db997a4c8b4020d9807b803b2d0ca565d9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 29 Sep 2026 14:00:36 +0200 Subject: [PATCH 2/3] docs(pypsa): add the changelog line --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a20d8af2..0e566f2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ it releases that version ([RELEASING.md](https://github.com/energy-models/mathsp ## Upcoming version +- docs(pypsa): a fixed modular committable unit gets only its per-module commitment rows, as in pypsa master ([#787](https://github.com/energy-models/mathspec/pull/787)) - docs(pypsa): the pypsa references are recorded against pypsa master ([#786](https://github.com/energy-models/mathspec/pull/786)) ## 0.2.1 (2026-10-01) From 34af2a073f6fa3ecf9caffced79e92dc1d96b53b Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 29 Sep 2026 15:09:09 +0200 Subject: [PATCH 3/3] test(pypsa): read the masks with the exclusivity evaluator, not eval --- tests/test_pypsa_references.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/test_pypsa_references.py b/tests/test_pypsa_references.py index c69bbbed..f2142622 100644 --- a/tests/test_pypsa_references.py +++ b/tests/test_pypsa_references.py @@ -14,13 +14,18 @@ import math import re import sys +from typing import TYPE_CHECKING import pytest from mathspec import to_spec +from mathspec.exclusivity import Subject, _evaluate, _Grid, _subject_of from tools import gallery from tools.gallery import DECLARED, RECORDED, REFERENCES, _names_for, _stands_for +if TYPE_CHECKING: + from mathspec.program import Mask + RUNGS = sorted(path.stem for path in REFERENCES.glob('rung_*.py')) SCRIPT = REFERENCES / 'reference.py' PAGE_TEXTS = [(gallery.PAGES / page).read_text() for page in DECLARED] @@ -156,10 +161,10 @@ def test_every_declared_row_is_built_by_some_reference(): assert not unbuilt, f'no reference network builds these declared rows — extend a fixture: {sorted(unbuilt)}' -def _admits(where: str, component: str, unit: dict[str, object]) -> bool: - """Whether a `where` over one component's own columns holds for a unit with those column values.""" - text = re.sub(rf'\b{component}_(\w+)', lambda column: repr(unit[column.group(1)]), where) - return eval(re.sub(r'\bNOT\b', 'not', text, flags=re.IGNORECASE).replace(' AND ', ' and ')) +def _admits(mask: Mask, component: str, unit: dict[str, bool | float]) -> bool: + """Whether a mask over one component's own parameters holds for a unit with those values, read by the exclusivity check.""" + cell = {Subject('param', f'{component}_{name}'): value for name, value in unit.items()} + return _evaluate(mask.root, cell, _Grid({}, {id(atom): _subject_of(atom) for atom in mask.atoms})) @pytest.mark.parametrize('component', ['Generator', 'Link', 'Process']) @@ -173,7 +178,7 @@ def test_a_fixed_modular_committable_unit_gets_only_its_per_module_commitment_ro families = ('com_p_', 'com_mod_p_', 'maint_status_', 'maint_modstatus_') admitted = { name.removeprefix(f'{component}_') - for name, block in BASE.constraints.items() + for name, block in BASE.program.constraints.items() if name.removeprefix(f'{component}_').startswith(families) and _admits(block.where, component, unit) } assert admitted == {