From 4ca4806f511a562f09609efb99c1b7dc54186a20 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 13:25:13 +0000 Subject: [PATCH 1/7] feat(spec): a spec written back out puts its given block first `given:` now follows `description:` on `Spec`, so `to_yaml()`, the canonical form and what `merge` and `override` return all write it before `dimensions:`. The key table in the language reference lists it first too. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019i7xNVeQzGJykmE9id6w51 --- docs/reference/language/file.md | 2 +- src/mathspec/spec.py | 4 ++-- tests/test_canonical.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/language/file.md b/docs/reference/language/file.md index d635d178..41c69153 100644 --- a/docs/reference/language/file.md +++ b/docs/reference/language/file.md @@ -10,11 +10,11 @@ A spec file is a YAML mapping with **twelve declaration keys**, plus | Key | | | ------------- | ------------------------------------------------------------------------------------------------- | +| `given` | what this file reads but does not build ([given](declarations.md#given)) | | `dimensions` | the axes ([dimensions](dimensions.md)) | | `relations` | named relations between dimensions ([relations](relations.md)) | | `parameters` | the data the spec expects ([declarations](declarations.md)) | | `variables` | what the solver decides | -| `given` | what this file reads but does not build ([given](declarations.md#given)) | | `constraints` | the rules those decisions obey | | `objective` | what is minimised or maximised | | `expressions` | named quantities, reusable in the math and readable after a solve ([named expressions](named.md)) | diff --git a/src/mathspec/spec.py b/src/mathspec/spec.py index 57fbd244..d8ca83aa 100644 --- a/src/mathspec/spec.py +++ b/src/mathspec/spec.py @@ -829,12 +829,12 @@ class is pydantic's, not a contract this package keeps. #: What the file as a whole is, in the same plain prose a declaration's #: ``description:`` takes. The typeset document opens with it. description: str | None = None + #: What this file reads and does not build ([`GivenBlock`][]). Empty in a file that stands alone. + given: GivenBlock = GivenBlock() dimensions: dict[str, DimensionBlock] = {} relations: dict[str, RelationBlock] = {} parameters: dict[str, ParameterBlock] = {} variables: dict[str, VariableBlock] = {} - #: What this file reads and does not build ([`GivenBlock`][]). Empty in a file that stands alone. - given: GivenBlock = GivenBlock() constraints: dict[str, ConstraintBlock] = {} objective: ObjectiveBlock | None = None expressions: dict[str, ExpressionBlock] = {} diff --git a/tests/test_canonical.py b/tests/test_canonical.py index 2b645f47..d168f0e4 100644 --- a/tests/test_canonical.py +++ b/tests/test_canonical.py @@ -141,11 +141,11 @@ def test_the_declarations_of_a_section_are_sorted_by_name(): SECTIONS = [ 'version', 'description', + 'given', 'dimensions', 'relations', 'parameters', 'variables', - 'given', 'constraints', 'objective', 'expressions', From 00fdb0dfb3da887e912640b034f00180d758d667 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 13:25:38 +0000 Subject: [PATCH 2/7] docs: add the changelog line for #818 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019i7xNVeQzGJykmE9id6w51 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41ee080c..9919a109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ request renames that heading to the version and the day, such as `## 0.1.0 (2026-10-01)`, and edits the section into the release notes. Merging it releases that version ([RELEASING.md](https://github.com/energy-models/mathspec/blob/main/RELEASING.md)). +## Upcoming version + +- feat(spec): a spec written back out puts its given block first ([#818](https://github.com/energy-models/mathspec/pull/818)) + ## 0.2.1 (2026-10-01) A spec can now be written as several files. [`merge`](https://mathspec.readthedocs.io/en/latest/howto/compose/) From e3ff7060bf40713609c6222ff48cd28d8596809b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 22:30:19 +0000 Subject: [PATCH 3/7] the reading page lists given in the canonical section order Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01CsaSWMofYqJiKmnSiPycV9 --- CHANGELOG.md | 2 +- docs/reference/reading.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db9b363a..13d1a5e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ it releases that version ([RELEASING.md](https://github.com/energy-models/mathsp ## Upcoming version -- feat(spec): a spec written back out puts its given block first ([#818](https://github.com/energy-models/mathspec/pull/818)) +- feat(spec)!: a spec written back out puts its given block first ([#818](https://github.com/energy-models/mathspec/pull/818)) - docs(pypsa): the pypsa page lists six more refusals and eight data-prep steps, and a capital cost says where fom_cost and overnight_cost enter ([#816](https://github.com/energy-models/mathspec/pull/816)) - docs(pypsa): a committable unit built in a later period starts from off, and the big M follows pypsa for an infinite build cap ([#817](https://github.com/energy-models/mathspec/pull/817)) - docs(pypsa): a line, a transformer, a storage unit and a store may be built in whole modules, and a unit that is not active counts no modules ([#815](https://github.com/energy-models/mathspec/pull/815)) diff --git a/docs/reference/reading.md b/docs/reference/reading.md index 53acc422..385954de 100644 --- a/docs/reference/reading.md +++ b/docs/reference/reading.md @@ -280,7 +280,7 @@ spec.to_yaml(canonical=True) == to_spec(spec.to_yaml(canonical=True)).to_yaml(ca ``` - **The sections come in one order**, whatever order the file wrote them in: - `version`, `description`, `dimensions`, `relations`, `parameters`, + `version`, `description`, `given`, `dimensions`, `relations`, `parameters`, `variables`, `constraints`, `objective`, `expressions`, `macros`, `piecewise`, `sos`, `assumptions`. The keys of a declaration also come in one order. From 15e1d8af633a470c1d2227259a41a9d9a803ac97 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 11:33:19 +0000 Subject: [PATCH 4/7] feat(spec)!: a spec written back out puts sos and piecewise after constraints, and macros before expressions The field order on Spec is the section order of to_dict, to_yaml and the canonical form. The order is now: given, dimensions, relations, parameters, variables, constraints, sos, piecewise, objective, macros, expressions, masks, assumptions. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LXkcLcoxVyLvgDfZgt2eUt --- docs/reference/language/file.md | 6 +++--- docs/reference/reading.md | 6 +++--- src/mathspec/spec.py | 6 +++--- tests/test_canonical.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/reference/language/file.md b/docs/reference/language/file.md index 5f835168..a70d9efb 100644 --- a/docs/reference/language/file.md +++ b/docs/reference/language/file.md @@ -16,12 +16,12 @@ A spec file is a YAML mapping with **thirteen declaration keys**, plus | `parameters` | the data the spec expects ([declarations](declarations.md)) | | `variables` | what the solver decides | | `constraints` | the rules those decisions obey | +| `sos` | special-ordered sets ([sos](piecewise.md#sos)) | +| `piecewise` | piecewise-linear curves ([piecewise](piecewise.md)) | | `objective` | what is minimised or maximised | +| `macros` | templates that take arguments ([macros](named.md#macros)) | | `expressions` | named quantities, reusable in the math and readable after a solve ([named expressions](named.md)) | | `masks` | named `where` predicates, read by name wherever a `where` string is ([masks](named.md#masks)) | -| `macros` | templates that take arguments ([macros](named.md#macros)) | -| `piecewise` | piecewise-linear curves ([piecewise](piecewise.md)) | -| `sos` | special-ordered sets ([sos](piecewise.md#sos)) | | `assumptions` | what the spec expects of its data ([assumptions](assumptions.md)) | A file with no `objective` is a **feasibility problem**: it asks whether the diff --git a/docs/reference/reading.md b/docs/reference/reading.md index 4296b026..8fba6149 100644 --- a/docs/reference/reading.md +++ b/docs/reference/reading.md @@ -291,9 +291,9 @@ spec.to_yaml(canonical=True) == to_spec(spec.to_yaml(canonical=True)).to_yaml(ca - **The sections come in one order**, whatever order the file wrote them in: `version`, `description`, `given`, `dimensions`, `relations`, `parameters`, - `variables`, `constraints`, `objective`, `expressions`, `macros`, - `piecewise`, `sos`, `assumptions`. The keys of a declaration also come in one - order. + `variables`, `constraints`, `sos`, `piecewise`, `objective`, `macros`, + `expressions`, `masks`, `assumptions`. The keys of a declaration also come in + one order. - **Declarations are sorted by name** within each section. - **Every expression is printed from its parsed tree**, so the spacing and the brackets are the printer's rather than the author's. diff --git a/src/mathspec/spec.py b/src/mathspec/spec.py index 60ee7d96..4b433d86 100644 --- a/src/mathspec/spec.py +++ b/src/mathspec/spec.py @@ -908,12 +908,12 @@ class is pydantic's, not a contract this package keeps. parameters: dict[str, ParameterBlock] = {} variables: dict[str, VariableBlock] = {} constraints: dict[str, ConstraintBlock] = {} + sos: dict[str, SosBlock] = {} + piecewise: dict[str, PiecewiseBlock] = {} objective: ObjectiveBlock | None = None + macros: dict[str, MacroBlock] = {} expressions: dict[str, ExpressionBlock] = {} masks: dict[str, MaskBlock] = {} - macros: dict[str, MacroBlock] = {} - piecewise: dict[str, PiecewiseBlock] = {} - sos: dict[str, SosBlock] = {} assumptions: dict[str, AssumptionBlock] = {} @cached_property diff --git a/tests/test_canonical.py b/tests/test_canonical.py index 092b5c26..195a0fd8 100644 --- a/tests/test_canonical.py +++ b/tests/test_canonical.py @@ -147,12 +147,12 @@ def test_the_declarations_of_a_section_are_sorted_by_name(): 'parameters', 'variables', 'constraints', + 'sos', + 'piecewise', 'objective', + 'macros', 'expressions', 'masks', - 'macros', - 'piecewise', - 'sos', 'assumptions', ] From c9fe66d99c72d520bafc4b6d320660a3277d1315 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 11:33:44 +0000 Subject: [PATCH 5/7] docs: add the changelog line for #848 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LXkcLcoxVyLvgDfZgt2eUt --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e785e48f..3d593229 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 +- feat(spec)!: a spec written back out puts sos and piecewise after constraints, and macros before expressions ([#848](https://github.com/energy-models/mathspec/pull/848)) - feat(spec)!: a spec written back out puts its given block first ([#818](https://github.com/energy-models/mathspec/pull/818)) - refactor(program)!: the node a use of a named expression stands as is `NamedExpression`, beside `NamedMask`, and `Named` is gone ([#822](https://github.com/energy-models/mathspec/pull/822)) - docs(pypsa): the pypsa spec names its repeated row conditions as masks, and its topic files read them under `given: masks:` ([#825](https://github.com/energy-models/mathspec/pull/825)) From 983cbe0acc6153f03bf3be30f8ddbdd0a33b2776 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 13:40:55 +0000 Subject: [PATCH 6/7] feat(spec)!: a spec written back out puts the objective before the constraints The sections now follow the typeset document: the objective comes before the rows it is subject to. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LXkcLcoxVyLvgDfZgt2eUt --- CHANGELOG.md | 2 +- docs/examples/library/composed.md | 2 +- docs/reference/language/file.md | 2 +- docs/reference/reading.md | 2 +- src/mathspec/spec.py | 2 +- tests/test_canonical.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d593229..a782b8a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ it releases that version ([RELEASING.md](https://github.com/energy-models/mathsp ## Upcoming version -- feat(spec)!: a spec written back out puts sos and piecewise after constraints, and macros before expressions ([#848](https://github.com/energy-models/mathspec/pull/848)) +- feat(spec)!: a spec written back out puts the objective before the constraints, sos and piecewise after them, and macros before expressions ([#848](https://github.com/energy-models/mathspec/pull/848)) - feat(spec)!: a spec written back out puts its given block first ([#818](https://github.com/energy-models/mathspec/pull/818)) - refactor(program)!: the node a use of a named expression stands as is `NamedExpression`, beside `NamedMask`, and `Named` is gone ([#822](https://github.com/energy-models/mathspec/pull/822)) - docs(pypsa): the pypsa spec names its repeated row conditions as masks, and its topic files read them under `given: masks:` ([#825](https://github.com/energy-models/mathspec/pull/825)) diff --git a/docs/examples/library/composed.md b/docs/examples/library/composed.md index 66c7d0b7..f368a5a7 100644 --- a/docs/examples/library/composed.md +++ b/docs/examples/library/composed.md @@ -75,6 +75,7 @@ variables: domain: continuous absence: undefined description: '`Generator-p` — what a generator produces in a snapshot' +objective: {sense: minimize, expression: total_cost} constraints: Bus_nodal_balance: dims: [snapshot, bus] @@ -90,7 +91,6 @@ constraints: expression: at(Port_p, by=Load_port[port]) == -Load_p_set description: 'what a load takes is what its port withdraws. No PyPSA row stands for this: PyPSA writes the load into the balance instead' -objective: {sense: minimize, expression: total_cost} expressions: Generator_cost: sum(Generator_p * Generator_marginal_cost) total_cost: diff --git a/docs/reference/language/file.md b/docs/reference/language/file.md index a70d9efb..fcc43de0 100644 --- a/docs/reference/language/file.md +++ b/docs/reference/language/file.md @@ -15,10 +15,10 @@ A spec file is a YAML mapping with **thirteen declaration keys**, plus | `relations` | named relations between dimensions ([relations](relations.md)) | | `parameters` | the data the spec expects ([declarations](declarations.md)) | | `variables` | what the solver decides | +| `objective` | what is minimised or maximised | | `constraints` | the rules those decisions obey | | `sos` | special-ordered sets ([sos](piecewise.md#sos)) | | `piecewise` | piecewise-linear curves ([piecewise](piecewise.md)) | -| `objective` | what is minimised or maximised | | `macros` | templates that take arguments ([macros](named.md#macros)) | | `expressions` | named quantities, reusable in the math and readable after a solve ([named expressions](named.md)) | | `masks` | named `where` predicates, read by name wherever a `where` string is ([masks](named.md#masks)) | diff --git a/docs/reference/reading.md b/docs/reference/reading.md index 8fba6149..6604c138 100644 --- a/docs/reference/reading.md +++ b/docs/reference/reading.md @@ -291,7 +291,7 @@ spec.to_yaml(canonical=True) == to_spec(spec.to_yaml(canonical=True)).to_yaml(ca - **The sections come in one order**, whatever order the file wrote them in: `version`, `description`, `given`, `dimensions`, `relations`, `parameters`, - `variables`, `constraints`, `sos`, `piecewise`, `objective`, `macros`, + `variables`, `objective`, `constraints`, `sos`, `piecewise`, `macros`, `expressions`, `masks`, `assumptions`. The keys of a declaration also come in one order. - **Declarations are sorted by name** within each section. diff --git a/src/mathspec/spec.py b/src/mathspec/spec.py index 4b433d86..bdb7062a 100644 --- a/src/mathspec/spec.py +++ b/src/mathspec/spec.py @@ -907,10 +907,10 @@ class is pydantic's, not a contract this package keeps. relations: dict[str, RelationBlock] = {} parameters: dict[str, ParameterBlock] = {} variables: dict[str, VariableBlock] = {} + objective: ObjectiveBlock | None = None constraints: dict[str, ConstraintBlock] = {} sos: dict[str, SosBlock] = {} piecewise: dict[str, PiecewiseBlock] = {} - objective: ObjectiveBlock | None = None macros: dict[str, MacroBlock] = {} expressions: dict[str, ExpressionBlock] = {} masks: dict[str, MaskBlock] = {} diff --git a/tests/test_canonical.py b/tests/test_canonical.py index 195a0fd8..f610b33b 100644 --- a/tests/test_canonical.py +++ b/tests/test_canonical.py @@ -146,10 +146,10 @@ def test_the_declarations_of_a_section_are_sorted_by_name(): 'relations', 'parameters', 'variables', + 'objective', 'constraints', 'sos', 'piecewise', - 'objective', 'macros', 'expressions', 'masks', From 0d37ff7516bee667c8bceef61cebf1e4aa5f76ec Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 13:58:35 +0000 Subject: [PATCH 7/7] feat(typesetting): the typeset document follows the section order of the file The legend lists Given first. Variable domains prints directly after Subject to, before Definitions and Masks. A special ordered set prints under Subject to, between the constraints and the curves. Assumptions stays last. The declared gallery pages print the domains after the constraints too. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LXkcLcoxVyLvgDfZgt2eUt --- CHANGELOG.md | 2 +- docs/examples/commitment.md | 16 +- docs/examples/library/composed.md | 46 +- docs/examples/library/generator.md | 26 +- docs/examples/library/load.md | 12 +- docs/examples/library/surface.md | 12 +- docs/examples/pypsa.md | 2236 +++++++++--------- docs/examples/pypsa/carrier.md | 12 +- docs/examples/pypsa/cost.md | 34 +- docs/examples/pypsa/generator.md | 84 +- docs/examples/pypsa/generator_commitment.md | 82 +- docs/examples/pypsa/generator_maintenance.md | 46 +- docs/examples/pypsa/generator_ramping.md | 38 +- docs/examples/pypsa/global_constraints.md | 22 +- docs/examples/pypsa/line.md | 80 +- docs/examples/pypsa/link.md | 82 +- docs/examples/pypsa/link_commitment.md | 82 +- docs/examples/pypsa/link_maintenance.md | 46 +- docs/examples/pypsa/link_ramping.md | 38 +- docs/examples/pypsa/load.md | 12 +- docs/examples/pypsa/network.md | 12 +- docs/examples/pypsa/power_flow.md | 12 +- docs/examples/pypsa/process.md | 78 +- docs/examples/pypsa/process_commitment.md | 82 +- docs/examples/pypsa/process_maintenance.md | 46 +- docs/examples/pypsa/process_ramping.md | 38 +- docs/examples/pypsa/security.md | 30 +- docs/examples/pypsa/settings.md | 26 +- docs/examples/pypsa/storage_unit.md | 114 +- docs/examples/pypsa/store.md | 90 +- docs/examples/pypsa/transformer.md | 68 +- docs/howto/see-an-expansion.md | 24 +- docs/reference/notation.md | 6 +- docs/reference/typeset.md | 6 + docs/several-files.md | 32 +- src/mathspec/typesetting/legend.py | 4 +- src/mathspec/typesetting/walk.py | 37 +- tests/typesetting/golden/latex.out | 36 +- tests/typesetting/golden/markdown.out | 112 +- tests/typesetting/golden/typst.out | 32 +- tests/typesetting/test_cases.py | 2 +- tools/gallery.py | 4 +- tools/notation.py | 4 +- 43 files changed, 1949 insertions(+), 1954 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f01ce5c4..0c39317b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ it releases that version ([RELEASING.md](https://github.com/energy-models/mathsp ## Upcoming version -- feat(spec)!: a spec written back out puts the objective before the constraints, sos and piecewise after them, and macros before expressions ([#848](https://github.com/energy-models/mathspec/pull/848)) +- feat!: a spec written back out and its typeset document follow one section order ([#848](https://github.com/energy-models/mathspec/pull/848)) - docs(pypsa): a delayed port under uneven snapshot weights is refused, where PyPSA counts weighted time ([#852](https://github.com/energy-models/mathspec/pull/852)) - docs: limits.md names that a count compares only against a whole-number literal ([#851](https://github.com/energy-models/mathspec/pull/851)) - docs: every spec in the docs and examples opens with its given block ([#813](https://github.com/energy-models/mathspec/pull/813)) diff --git a/docs/examples/commitment.md b/docs/examples/commitment.md index eb880a62..8df3a007 100644 --- a/docs/examples/commitment.md +++ b/docs/examples/commitment.md @@ -167,14 +167,6 @@ $`\mathrm{pos}(t)`$ denotes where index $`t`$ sits along its dimension's own ord \mathit{dispatch}_{t,g} - \mathit{dispatch}_{t \boxminus_{0} 1,g} \le \mathrm{ramp\_limit}_{g} \cdot \mathit{previous\_status}_{t,g} + \mathrm{start\_up\_limit}_{g} \cdot \left( 1 - \mathit{previous\_status}_{t,g} \right) \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -#### Definitions - -**`previous_status`** - -```math -\mathit{previous\_status}_{t,g} = \begin{cases} 1 & \text{if } \neg \mathrm{committable}_{g} \\ \mathrm{status}^{\mathrm{initial}}_{g} & \text{if } \mathrm{committable}_{g} \wedge \mathrm{pos}(t) = 0 \\ \mathit{status}_{t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} -``` - #### Variable domains **`dispatch`** @@ -189,6 +181,14 @@ $`\mathrm{pos}(t)`$ denotes where index $`t`$ sits along its dimension's own ord \mathit{status}_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` +#### Definitions + +**`previous_status`** + +```math +\mathit{previous\_status}_{t,g} = \begin{cases} 1 & \text{if } \neg \mathrm{committable}_{g} \\ \mathrm{status}^{\mathrm{initial}}_{g} & \text{if } \mathrm{committable}_{g} \wedge \mathrm{pos}(t) = 0 \\ \mathit{status}_{t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +``` + #### Assumptions **`output_floor_fits_under_the_cap`** diff --git a/docs/examples/library/composed.md b/docs/examples/library/composed.md index f44f18a4..a4d13f50 100644 --- a/docs/examples/library/composed.md +++ b/docs/examples/library/composed.md @@ -159,32 +159,32 @@ expressions: f_{t,\mathrm{Load\_port}(d)} = -\mathrm{load}_{t,d} \qquad \forall\, t \in \mathcal{T},\ d \in \mathcal{D} ``` - #### Definitions + #### Variable domains - **`Generator_cost`** + **`Port_p`** ```math - \mathit{Generator\_cost} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{c}_{g} + f_{t,j} \in \mathbb{R} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} ``` - **`total_cost`** + **`Generator_p`** ```math - \mathit{total\_cost} = \mathit{Generator\_cost} + 0 \le p_{t,g} \le \mathrm{p}^{\mathrm{nom}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` - #### Variable domains + #### Definitions - **`Port_p`** + **`Generator_cost`** ```math - f_{t,j} \in \mathbb{R} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} + \mathit{Generator\_cost} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{c}_{g} ``` - **`Generator_p`** + **`total_cost`** ```math - 0 \le p_{t,g} \le \mathrm{p}^{\mathrm{nom}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} + \mathit{total\_cost} = \mathit{Generator\_cost} ``` === "With commitment" @@ -281,37 +281,37 @@ expressions: p_{t,g} \ge \underline{\mathrm{p}}_{g} \cdot \mathrm{p}^{\mathrm{nom}}_{g} \cdot u_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` - #### Definitions + #### Variable domains - **`Generator_cost`** + **`Port_p`** ```math - \mathit{Generator\_cost} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{c}_{g} + f_{t,j} \in \mathbb{R} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} ``` - **`total_cost`** + **`Generator_p`** ```math - \mathit{total\_cost} = \mathit{Generator\_cost} + p_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` - #### Variable domains - - **`Port_p`** + **`Generator_status`** ```math - f_{t,j} \in \mathbb{R} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} + u_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` - **`Generator_p`** + #### Definitions + + **`Generator_cost`** ```math - p_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} + \mathit{Generator\_cost} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{c}_{g} ``` - **`Generator_status`** + **`total_cost`** ```math - u_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} + \mathit{total\_cost} = \mathit{Generator\_cost} ``` diff --git a/docs/examples/library/generator.md b/docs/examples/library/generator.md index 915359df..d4784c53 100644 --- a/docs/examples/library/generator.md +++ b/docs/examples/library/generator.md @@ -68,6 +68,13 @@ expressions: PyPSA's `Generator`, wired to a port rather than straight to a bus, and cut to what a dispatch spec needs: a fixed build, no availability profile, no ramp limits. +#### Given + +| Symbol | Meaning | +|---|---| +| $`f`$ | `Port_p` over $`\mathcal{T} \times \mathcal{J}`$ — the surface introduces this flow, and this file pins it at its own ports | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Generator_cost` to | + #### Sets | Symbol | Meaning | @@ -89,13 +96,6 @@ PyPSA's `Generator`, wired to a port rather than straight to a bus, and cut to w |---|---| | $`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 flow, and this file pins it at its own ports | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Generator_cost` to | - #### Definitions | Symbol | Meaning | @@ -110,19 +110,19 @@ PyPSA's `Generator`, wired to a port rather than straight to a bus, and cut to w f_{t,\mathrm{Generator\_port}(g)} = p_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -#### Definitions +#### Variable domains -**`Generator_cost`** +**`Generator_p`** ```math -\mathit{Generator\_cost} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{c}_{g} +0 \le p_{t,g} \le \mathrm{p}^{\mathrm{nom}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -#### Variable domains +#### Definitions -**`Generator_p`** +**`Generator_cost`** ```math -0 \le p_{t,g} \le \mathrm{p}^{\mathrm{nom}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{Generator\_cost} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{c}_{g} ``` diff --git a/docs/examples/library/load.md b/docs/examples/library/load.md index f946af52..90fc0dee 100644 --- a/docs/examples/library/load.md +++ b/docs/examples/library/load.md @@ -39,6 +39,12 @@ constraints: PyPSA's `Load`, wired to a port rather than straight to a bus. What it takes is data, so it decides nothing. +#### Given + +| Symbol | Meaning | +|---|---| +| $`f`$ | `Port_p` over $`\mathcal{T} \times \mathcal{J}`$ — the surface introduces this flow, and this file pins it at its own ports | + #### Sets | Symbol | Meaning | @@ -53,12 +59,6 @@ PyPSA's `Load`, wired to a port rather than straight to a bus. What it takes is |---|---| | $`\mathrm{load}`$ | `Load_p_set` over $`\mathcal{T} \times \mathcal{D}`$ — `Load-p_set` — what a load takes in a snapshot | -#### Given - -| Symbol | Meaning | -|---|---| -| $`f`$ | `Port_p` over $`\mathcal{T} \times \mathcal{J}`$ — the surface introduces this flow, and this file pins it at its own ports | - #### Subject to **`Load_withdrawal`** diff --git a/docs/examples/library/surface.md b/docs/examples/library/surface.md index 4fc11fc1..5e9dfca3 100644 --- a/docs/examples/library/surface.md +++ b/docs/examples/library/surface.md @@ -55,6 +55,12 @@ objective: The coupling surface every component in this library is written against: one flow per port, one balance per bus, and one cost to minimise. A component is wired to a port, the port to a bus, and the balance names no component class. A flow is positive where the port injects into its bus. A component that costs something adds its cost to `total_cost`. +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression another file defines — what running the system costs | + #### Sets | Symbol | Meaning | @@ -69,12 +75,6 @@ The coupling surface every component in this library is written against: one flo |---|---| | $`f`$ | `Port_p` over $`\mathcal{T} \times \mathcal{J}`$ — what a port puts into its bus in a snapshot, negative for a withdrawal | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression another file defines — what running the system costs | - #### Objective ```math diff --git a/docs/examples/pypsa.md b/docs/examples/pypsa.md index 6eba39db..98da2f46 100644 --- a/docs/examples/pypsa.md +++ b/docs/examples/pypsa.md @@ -10116,2023 +10116,2023 @@ CVaR_def: \theta + \frac{1}{1 - \alpha} \cdot \left( \sum_{\xi \in \Xi} \pi_{\xi} \cdot a_{\xi} \right) \le CVaR \qquad \text{where } \omega \text{ is defined} ``` -### `Generator_previous_status` +#### Variable domains -```yaml -Generator_previous_status: - description: >- - the commitment state a generator carries into a snapshot — off at the - first snapshot it stands in past the first of the horizon, as PyPSA - reads a status it did not build (`constraints.py:298`), and the state - carried over otherwise - dims: [scenario, snapshot, generator] - cases: - opening_late: { when: "position(snapshot) > 0 AND NOT shift(Generator_active, along=snapshot, offset=1)", expression: 0 } - otherwise: Generator_status_carried_over -``` +**`Generator_p`** ```math -\overleftarrow{u}_{\xi,t,g} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}_{t - 1,g} \\ \overleftarrow{u}^{\circ}_{\xi,t,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +p_{\xi,t,g} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}_{t,g} ``` -### `Generator_status_carried_over` +**`Link_p`** -```yaml -Generator_status_carried_over: - description: >- - the state a generator carries over into a snapshot — the state it brought - into the horizon at the first, the previous snapshot's after that - dims: [scenario, snapshot, generator] - cases: - opening: { when: "position(snapshot) == 0", expression: Generator_status_initial } - otherwise: shift(Generator_status, along=snapshot, offset=1) +```math +f_{\xi,t,l} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f}_{t,l} ``` +**`Process_p`** + ```math -\overleftarrow{u}^{\circ}_{\xi,t,g} = \begin{cases} \mathrm{u}^{0}_{\xi,g} & \text{if } \mathrm{pos}(t) = 0 \\ u_{\xi,t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +z_{\xi,t,j} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z}_{t,j} ``` -### `Generator_previous_p` +**`StorageUnit_p_dispatch`** -```yaml -Generator_previous_p: - description: >- - the output a generator carries into a snapshot — at the first, the - `p_init` it brought in where it came in running and nothing where it - came in off; the previous snapshot's after that - dims: [scenario, snapshot, generator] - cases: - opening: { when: "position(snapshot) == 0", expression: Generator_status_initial * Generator_p_init } - otherwise: shift(Generator_p, along=snapshot, offset=1) +```math +h^{+}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} ``` +**`StorageUnit_p_store`** + ```math -\overleftarrow{p}_{\xi,t,g} = \begin{cases} \mathrm{u}^{0}_{\xi,g} \cdot \mathrm{p}^{0}_{\xi,g} & \text{if } \mathrm{pos}(t) = 0 \\ p_{\xi,t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +h^{-}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} ``` -### `Generator_p_nom_effective` +**`StorageUnit_state_of_charge`** -```yaml -Generator_p_nom_effective: - description: the build a generator's limits are taken against — the chosen one where it is extendable, the given one otherwise - dims: [scenario, generator] - cases: - extendable: { when: Generator_p_nom_extendable, expression: Generator_p_nom_ext } - otherwise: Generator_p_nom +```math +\mathit{soc}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} ``` +**`StorageUnit_spill`** + ```math -\widetilde{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} = \begin{cases} P_{g} & \text{if } \mathrm{ext}_{g} \\ \mathrm{p}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} +0 \le \mathit{spill}_{\xi,t,s} \le \mathrm{inflow}_{\xi,t,s} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{inflow}_{\xi,t,s} > 0 \wedge \mathrm{on}^{h}_{t,s} ``` -### `Generator_ramp_up_rate` +**`Store_e`** -```yaml -Generator_ramp_up_rate: - description: >- - the ramp limit a unit's up row reads — PyPSA's `ramp_limit_up`, or the - full build where it has none, since a start-up ramp alone builds the row - dims: [scenario, snapshot, generator] - cases: - given: { when: Generator_ramp_limit_up, expression: Generator_ramp_limit_up } - otherwise: 1 +```math +e_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} ``` +**`Store_p`** + ```math -\widetilde{\mathrm{ru}}_{\xi,t,g} = \begin{cases} \mathrm{ru}_{\xi,t,g} & \text{if } \mathrm{ru}_{\xi,t,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +q_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} ``` -### `Generator_ramp_down_rate` +**`Generator_n_mod`** -```yaml -Generator_ramp_down_rate: - description: >- - the ramp limit a unit's down row reads — PyPSA's `ramp_limit_down`, or - the full build where it has none, since a shut-down ramp alone builds the row - dims: [scenario, snapshot, generator] - cases: - given: { when: Generator_ramp_limit_down, expression: Generator_ramp_limit_down } - otherwise: 1 +```math +N_{g} \ge 0, N_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}_{t,g} \} \rvert > 0 ``` +**`Generator_status`** + ```math -\widetilde{\mathrm{rd}}_{\xi,t,g} = \begin{cases} \mathrm{rd}_{\xi,t,g} & \text{if } \mathrm{rd}_{\xi,t,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +u_{\xi,t,g} \ge 0, u_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} ``` -### `Generator_start_up_rate` +**`Generator_start_up`** -```yaml -Generator_start_up_rate: - description: >- - the start-up ramp a unit's up row reads — PyPSA's `ramp_limit_start_up`, - or the full build where it has none - dims: [scenario, generator] - cases: - given: { when: Generator_ramp_limit_start_up, expression: Generator_ramp_limit_start_up } - otherwise: 1 +```math +\mathit{up}_{\xi,t,g} \ge 0, \mathit{up}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} ``` +**`Generator_shut_down`** + ```math -\widetilde{\mathrm{ru}}^{\mathrm{up}}_{\xi,g} = \begin{cases} \mathrm{ru}^{\mathrm{up}}_{\xi,g} & \text{if } \mathrm{ru}^{\mathrm{up}}_{\xi,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} +\mathit{dn}_{\xi,t,g} \ge 0, \mathit{dn}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} ``` -### `Generator_shut_down_rate` +**`Generator_maintenance`** -```yaml -Generator_shut_down_rate: - description: >- - the shut-down ramp a unit's down row reads — PyPSA's - `ramp_limit_shut_down`, or the full build where it has none - dims: [scenario, generator] - cases: - given: { when: Generator_ramp_limit_shut_down, expression: Generator_ramp_limit_shut_down } - otherwise: 1 +```math +0 \le \mu_{\xi,t,g} \le 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}_{t,g} ``` +**`Generator_maintenance_start`** + ```math -\widetilde{\mathrm{rd}}^{\mathrm{dn}}_{\xi,g} = \begin{cases} \mathrm{rd}^{\mathrm{dn}}_{\xi,g} & \text{if } \mathrm{rd}^{\mathrm{dn}}_{\xi,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} +\mu^{\mathrm{up}}_{\xi,t,g} \in \{0, 1\} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}_{t,g} ``` -### `Generator_p_nom_committed` +**`Generator_maintenance_capacity`** -```yaml -Generator_p_nom_committed: - description: >- - the build a committed unit's ramp rows are taken against — one module - where the build is extendable and modular, the given build otherwise - dims: [scenario, generator] - cases: - modular_build: { when: Generator_p_nom_extendable AND Generator_p_nom_mod > 0, expression: Generator_p_nom_mod } - otherwise: Generator_p_nom +```math +\mu^{\mathrm{nom}}_{\xi,t,g} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{mnt,ext}}_{t,g} ``` +**`Generator_maintenance_status`** + ```math -\widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} = \begin{cases} \mathrm{p}^{\mathrm{mod}}_{g} & \text{if } \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \\ \mathrm{p}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} +\mu^{u}_{\xi,t,g} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}^{\mathrm{com}}_{t,g} \wedge \neg \left( \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \right) ``` -### `Generator_ramp_up_allowance` +**`Link_n_mod`** -```yaml -Generator_ramp_up_allowance: - description: >- - how far a generator may raise output between two snapshots — its ramp - limit of the build while it stays on, plus its start-up ramp in the - snapshot it turns on - dims: [scenario, snapshot, generator] - cases: - committed: - when: Generator_committable - expression: >- - Generator_ramp_up_rate * Generator_p_nom_committed * Generator_previous_status - + Generator_start_up_rate * Generator_p_nom_committed - * (Generator_status - Generator_previous_status) - otherwise: Generator_ramp_up_rate * Generator_p_nom_effective +```math +N^{f}_{l} \ge 0, N^{f}_{l} \in \mathbb{Z} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{f}_{t,l} \} \rvert > 0 ``` +**`Link_status`** + ```math -\Delta^{+}_{\xi,t,g} = \begin{cases} \widetilde{\mathrm{ru}}_{\xi,t,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot \overleftarrow{u}_{\xi,t,g} + \widetilde{\mathrm{ru}}^{\mathrm{up}}_{\xi,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \overleftarrow{u}_{\xi,t,g} \right) & \text{if } \mathrm{com}_{g} \\ \widetilde{\mathrm{ru}}_{\xi,t,g} \cdot \widetilde{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +u^{f}_{\xi,t,l} \ge 0, u^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} ``` -### `Generator_ramp_down_allowance` +**`Link_start_up`** -```yaml -Generator_ramp_down_allowance: - description: >- - how far a generator may lower output between two snapshots — its ramp - limit of the build while it stays on, plus its shut-down ramp in the - snapshot it turns off - dims: [scenario, snapshot, generator] - cases: - committed: - when: Generator_committable - expression: >- - Generator_ramp_down_rate * Generator_p_nom_committed * Generator_status - + Generator_shut_down_rate * Generator_p_nom_committed - * (Generator_previous_status - Generator_status) - otherwise: Generator_ramp_down_rate * Generator_p_nom_effective +```math +\mathit{up}^{f}_{\xi,t,l} \ge 0, \mathit{up}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} ``` +**`Link_shut_down`** + ```math -\Delta^{-}_{\xi,t,g} = \begin{cases} \widetilde{\mathrm{rd}}_{\xi,t,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot u_{\xi,t,g} + \widetilde{\mathrm{rd}}^{\mathrm{dn}}_{\xi,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot \left( \overleftarrow{u}_{\xi,t,g} - u_{\xi,t,g} \right) & \text{if } \mathrm{com}_{g} \\ \widetilde{\mathrm{rd}}_{\xi,t,g} \cdot \widetilde{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{dn}^{f}_{\xi,t,l} \ge 0, \mathit{dn}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} ``` -### `Link_p_nom_effective` +**`Link_maintenance`** -```yaml -Link_p_nom_effective: - description: the build a link's limits are taken against — the chosen one where it is extendable, the given one otherwise - dims: [scenario, link] - cases: - extendable: { when: Link_p_nom_extendable, expression: Link_p_nom_ext } - otherwise: Link_p_nom +```math +0 \le \mu^{f}_{\xi,t,l} \le 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} ``` +**`Link_maintenance_start`** + ```math -\widetilde{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} = \begin{cases} F_{l} & \text{if } \mathrm{ext}^{f}_{l} \\ \mathrm{f}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} +\mu^{f,\mathrm{up}}_{\xi,t,l} \in \{0, 1\} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} ``` -### `Link_previous_status` +**`Link_maintenance_capacity`** -```yaml -Link_previous_status: - description: >- - the commitment state a link carries into a snapshot — off at the - first snapshot it stands in past the first of the horizon, as PyPSA - reads a status it did not build (`constraints.py:298`), and the state - carried over otherwise - dims: [scenario, snapshot, link] - cases: - opening_late: { when: "position(snapshot) > 0 AND NOT shift(Link_active, along=snapshot, offset=1)", expression: 0 } - otherwise: Link_status_carried_over +```math +\mu^{f,\mathrm{nom}}_{\xi,t,l} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{mnt,ext}}_{t,l} ``` +**`Link_maintenance_status`** + ```math -\overleftarrow{u}^{f}_{\xi,t,l} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{f}_{t - 1,l} \\ \overleftarrow{u}^{\circ f}_{\xi,t,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +\mu^{f,u}_{\xi,t,l} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f,\mathrm{com}}_{t,l} \wedge \neg \left( \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \right) ``` -### `Link_status_carried_over` +**`Process_n_mod`** -```yaml -Link_status_carried_over: - description: >- - the state a link carries over into a snapshot — the state it brought - into the horizon at the first, the previous snapshot's after that - dims: [scenario, snapshot, link] - cases: - opening: { when: "position(snapshot) == 0", expression: Link_status_initial } - otherwise: shift(Link_status, along=snapshot, offset=1) +```math +N^{z}_{j} \ge 0, N^{z}_{j} \in \mathbb{Z} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{z}_{t,j} \} \rvert > 0 ``` +**`Process_status`** + ```math -\overleftarrow{u}^{\circ f}_{\xi,t,l} = \begin{cases} \mathrm{u}^{f,0}_{\xi,l} & \text{if } \mathrm{pos}(t) = 0 \\ u^{f}_{\xi,t - 1,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +u^{z}_{\xi,t,j} \ge 0, u^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} ``` -### `Link_previous_p` +**`Process_start_up`** -```yaml -Link_previous_p: - description: >- - the flow a link carries into a snapshot — at the first, the - `p_init` it brought in where it came in running and nothing where it - came in off; the previous snapshot's after that - dims: [scenario, snapshot, link] - cases: - opening: { when: "position(snapshot) == 0", expression: Link_status_initial * Link_p_init } - otherwise: shift(Link_p, along=snapshot, offset=1) +```math +\mathit{up}^{z}_{\xi,t,j} \ge 0, \mathit{up}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} ``` +**`Process_shut_down`** + ```math -\overleftarrow{f}_{\xi,t,l} = \begin{cases} \mathrm{u}^{f,0}_{\xi,l} \cdot \mathrm{f}^{0}_{\xi,l} & \text{if } \mathrm{pos}(t) = 0 \\ f_{\xi,t - 1,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +\mathit{dn}^{z}_{\xi,t,j} \ge 0, \mathit{dn}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} ``` -### `Link_ramp_up_rate` +**`Process_maintenance`** -```yaml -Link_ramp_up_rate: - description: >- - the ramp limit a link's up row reads — PyPSA's `ramp_limit_up`, or the - full build where it has none, since a start-up ramp alone builds the row - dims: [scenario, snapshot, link] - cases: - given: { when: Link_ramp_limit_up, expression: Link_ramp_limit_up } - otherwise: 1 +```math +0 \le \mu^{z}_{\xi,t,j} \le 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} ``` +**`Process_maintenance_start`** + ```math -\widetilde{\mathrm{ru}}^{f}_{\xi,t,l} = \begin{cases} \mathrm{ru}^{f}_{\xi,t,l} & \text{if } \mathrm{ru}^{f}_{\xi,t,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +\mu^{z,\mathrm{up}}_{\xi,t,j} \in \{0, 1\} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} ``` -### `Link_ramp_down_rate` +**`Process_maintenance_capacity`** -```yaml -Link_ramp_down_rate: - description: >- - the ramp limit a link's down row reads — PyPSA's `ramp_limit_down`, or - the full build where it has none, since a shut-down ramp alone builds the row - dims: [scenario, snapshot, link] - cases: - given: { when: Link_ramp_limit_down, expression: Link_ramp_limit_down } - otherwise: 1 +```math +\mu^{z,\mathrm{nom}}_{\xi,t,j} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{mnt,ext}}_{t,j} ``` +**`Process_maintenance_status`** + ```math -\widetilde{\mathrm{rd}}^{f}_{\xi,t,l} = \begin{cases} \mathrm{rd}^{f}_{\xi,t,l} & \text{if } \mathrm{rd}^{f}_{\xi,t,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +\mu^{z,u}_{\xi,t,j} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z,\mathrm{com}}_{t,j} \wedge \neg \left( \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \right) ``` -### `Link_start_up_rate` +**`Line_s`** -```yaml -Link_start_up_rate: - description: >- - the start-up ramp a link's up row reads — PyPSA's `ramp_limit_start_up`, - or the full build where it has none - dims: [scenario, link] - cases: - given: { when: Link_ramp_limit_start_up, expression: Link_ramp_limit_start_up } - otherwise: 1 +```math +s_{\xi,t,k} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s}_{t,k} ``` +**`Line_loss`** + ```math -\widetilde{\mathrm{ru}}^{f,\mathrm{up}}_{\xi,l} = \begin{cases} \mathrm{ru}^{f,\mathrm{up}}_{\xi,l} & \text{if } \mathrm{ru}^{f,\mathrm{up}}_{\xi,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} +\ell_{\xi,t,k} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s,\mathrm{lossy}}_{t,k} ``` -### `Link_shut_down_rate` +**`Transformer_s`** -```yaml -Link_shut_down_rate: - description: >- - the shut-down ramp a link's down row reads — PyPSA's - `ramp_limit_shut_down`, or the full build where it has none - dims: [scenario, link] - cases: - given: { when: Link_ramp_limit_shut_down, expression: Link_ramp_limit_shut_down } - otherwise: 1 +```math +\sigma_{\xi,t,m} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma}_{t,m} ``` +**`Transformer_loss`** + ```math -\widetilde{\mathrm{rd}}^{f,\mathrm{dn}}_{\xi,l} = \begin{cases} \mathrm{rd}^{f,\mathrm{dn}}_{\xi,l} & \text{if } \mathrm{rd}^{f,\mathrm{dn}}_{\xi,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} +\ell^{\sigma}_{\xi,t,m} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} ``` -### `Link_p_nom_committed` +**`Transformer_phase_shift`** -```yaml -Link_p_nom_committed: - description: >- - the build a committed link's ramp rows are taken against — one module - where the build is extendable and modular, the given build otherwise - dims: [scenario, link] - cases: - modular_build: { when: Link_p_nom_extendable AND Link_p_nom_mod > 0, expression: Link_p_nom_mod } - otherwise: Link_p_nom +```math +\mathrm{Transformer\_phase\_shift\_min}_{m} \le \mathit{Transformer\_phase\_shift}_{\xi,t,m} \le \mathrm{Transformer\_phase\_shift\_max}_{m} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{Transformer\_phase\_shift\_varying}_{m} \wedge \mathrm{on}^{\sigma}_{t,m} ``` +**`Line_s_nom_ext`** + ```math -\widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} = \begin{cases} \mathrm{f}^{\mathrm{mod}}_{l} & \text{if } \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \\ \mathrm{f}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} +S_{k} \in \mathbb{R} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} ``` -### `Link_ramp_up_allowance` +**`Line_n_mod`** -```yaml -Link_ramp_up_allowance: - description: >- - how far a link may raise flow between two snapshots — its ramp - limit of the build while it stays on, plus its start-up ramp in the - snapshot it turns on - dims: [scenario, snapshot, link] - cases: - committed: - when: Link_committable - expression: >- - Link_ramp_up_rate * Link_p_nom_committed * Link_previous_status - + Link_start_up_rate * Link_p_nom_committed - * (Link_status - Link_previous_status) - otherwise: Link_ramp_up_rate * Link_p_nom_effective +```math +N^{s}_{k} \ge 0, N^{s}_{k} \in \mathbb{Z} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} \wedge \mathrm{s}^{\mathrm{mod}}_{k} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{s}_{t,k} \} \rvert > 0 ``` +**`Generator_p_nom_ext`** + ```math -\Delta^{f,+}_{\xi,t,l} = \begin{cases} \widetilde{\mathrm{ru}}^{f}_{\xi,t,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot \overleftarrow{u}^{f}_{\xi,t,l} + \widetilde{\mathrm{ru}}^{f,\mathrm{up}}_{\xi,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \overleftarrow{u}^{f}_{\xi,t,l} \right) & \text{if } \mathrm{com}^{f}_{l} \\ \widetilde{\mathrm{ru}}^{f}_{\xi,t,l} \cdot \widetilde{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +P_{g} \in \mathbb{R} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} ``` -### `Link_ramp_down_allowance` +**`Link_p_nom_ext`** -```yaml -Link_ramp_down_allowance: - description: >- - how far a link may lower flow between two snapshots — its ramp - limit of the build while it stays on, plus its shut-down ramp in the - snapshot it turns off - dims: [scenario, snapshot, link] - cases: - committed: - when: Link_committable - expression: >- - Link_ramp_down_rate * Link_p_nom_committed * Link_status - + Link_shut_down_rate * Link_p_nom_committed - * (Link_previous_status - Link_status) - otherwise: Link_ramp_down_rate * Link_p_nom_effective +```math +F_{l} \in \mathbb{R} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} ``` +**`Process_p_nom_ext`** + ```math -\Delta^{f,-}_{\xi,t,l} = \begin{cases} \widetilde{\mathrm{rd}}^{f}_{\xi,t,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot u^{f}_{\xi,t,l} + \widetilde{\mathrm{rd}}^{f,\mathrm{dn}}_{\xi,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot \left( \overleftarrow{u}^{f}_{\xi,t,l} - u^{f}_{\xi,t,l} \right) & \text{if } \mathrm{com}^{f}_{l} \\ \widetilde{\mathrm{rd}}^{f}_{\xi,t,l} \cdot \widetilde{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +Z_{j} \in \mathbb{R} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} ``` -### `Process_p_nom_effective` +**`Transformer_s_nom_ext`** -```yaml -Process_p_nom_effective: - description: the build a process's limits are taken against — the chosen one where it is extendable, the given one otherwise - dims: [scenario, process] - cases: - extendable: { when: Process_p_nom_extendable, expression: Process_p_nom_ext } - otherwise: Process_p_nom +```math +\Sigma_{m} \in \mathbb{R} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} ``` +**`Transformer_n_mod`** + ```math -\widetilde{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} = \begin{cases} Z_{j} & \text{if } \mathrm{ext}^{z}_{j} \\ \mathrm{z}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} +N^{\sigma}_{m} \ge 0, N^{\sigma}_{m} \in \mathbb{Z} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} \wedge \sigma^{\mathrm{mod}}_{m} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{\sigma}_{t,m} \} \rvert > 0 ``` -### `Process_previous_status` +**`StorageUnit_p_nom_ext`** -```yaml -Process_previous_status: - description: >- - the commitment state a process carries into a snapshot — off at the - first snapshot it stands in past the first of the horizon, as PyPSA - reads a status it did not build (`constraints.py:298`), and the state - carried over otherwise - dims: [scenario, snapshot, process] - cases: - opening_late: { when: "position(snapshot) > 0 AND NOT shift(Process_active, along=snapshot, offset=1)", expression: 0 } - otherwise: Process_status_carried_over +```math +H_{s} \in \mathbb{R} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} ``` +**`StorageUnit_n_mod`** + ```math -\overleftarrow{u}^{z}_{\xi,t,j} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{z}_{t - 1,j} \\ \overleftarrow{u}^{\circ z}_{\xi,t,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +N^{h}_{s} \ge 0, N^{h}_{s} \in \mathbb{Z} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} \wedge \mathrm{h}^{\mathrm{mod}}_{s} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{h}_{t,s} \} \rvert > 0 ``` -### `Process_status_carried_over` - -```yaml -Process_status_carried_over: - description: >- - the state a process carries over into a snapshot — the state it brought - into the horizon at the first, the previous snapshot's after that - dims: [scenario, snapshot, process] - cases: - opening: { when: "position(snapshot) == 0", expression: Process_status_initial } - otherwise: shift(Process_status, along=snapshot, offset=1) +**`Store_e_nom_ext`** + +```math +E_{v} \in \mathbb{R} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} ``` +**`Store_n_mod`** + ```math -\overleftarrow{u}^{\circ z}_{\xi,t,j} = \begin{cases} \mathrm{u}^{z,0}_{\xi,j} & \text{if } \mathrm{pos}(t) = 0 \\ u^{z}_{\xi,t - 1,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +N^{e}_{v} \ge 0, N^{e}_{v} \in \mathbb{Z} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} \wedge \mathrm{e}^{\mathrm{mod}}_{v} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{e}_{t,v} \} \rvert > 0 ``` -### `Process_previous_p` +**`CVaR_a`** -```yaml -Process_previous_p: - description: >- - the internal power a process carries into a snapshot — at the first, the - `p_init` it brought in where it came in running and nothing where it - came in off; the previous snapshot's after that - dims: [scenario, snapshot, process] - cases: - opening: { when: "position(snapshot) == 0", expression: Process_status_initial * Process_p_init } - otherwise: shift(Process_p, along=snapshot, offset=1) +```math +a_{\xi} \ge 0 \qquad \forall\, \xi \in \Xi \,:\, \omega \text{ is defined} ``` +**`CVaR_theta`** + ```math -\overleftarrow{z}_{\xi,t,j} = \begin{cases} \mathrm{u}^{z,0}_{\xi,j} \cdot \mathrm{z}^{0}_{\xi,j} & \text{if } \mathrm{pos}(t) = 0 \\ z_{\xi,t - 1,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +\theta \in \mathbb{R} \qquad \text{where } \omega \text{ is defined} ``` -### `Process_ramp_up_rate` +**`CVaR`** + +```math +CVaR \in \mathbb{R} \qquad \text{where } \omega \text{ is defined} +``` + +### `Generator_previous_status` ```yaml -Process_ramp_up_rate: +Generator_previous_status: description: >- - the ramp limit a process's up row reads — PyPSA's `ramp_limit_up`, or the - full build where it has none, since a start-up ramp alone builds the row - dims: [scenario, snapshot, process] + the commitment state a generator carries into a snapshot — off at the + first snapshot it stands in past the first of the horizon, as PyPSA + reads a status it did not build (`constraints.py:298`), and the state + carried over otherwise + dims: [scenario, snapshot, generator] cases: - given: { when: Process_ramp_limit_up, expression: Process_ramp_limit_up } - otherwise: 1 + opening_late: { when: "position(snapshot) > 0 AND NOT shift(Generator_active, along=snapshot, offset=1)", expression: 0 } + otherwise: Generator_status_carried_over ``` ```math -\widetilde{\mathrm{ru}}^{z}_{\xi,t,j} = \begin{cases} \mathrm{ru}^{z}_{\xi,t,j} & \text{if } \mathrm{ru}^{z}_{\xi,t,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +\overleftarrow{u}_{\xi,t,g} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}_{t - 1,g} \\ \overleftarrow{u}^{\circ}_{\xi,t,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `Process_ramp_down_rate` +### `Generator_status_carried_over` ```yaml -Process_ramp_down_rate: +Generator_status_carried_over: description: >- - the ramp limit a process's down row reads — PyPSA's `ramp_limit_down`, or - the full build where it has none, since a shut-down ramp alone builds the row - dims: [scenario, snapshot, process] + the state a generator carries over into a snapshot — the state it brought + into the horizon at the first, the previous snapshot's after that + dims: [scenario, snapshot, generator] cases: - given: { when: Process_ramp_limit_down, expression: Process_ramp_limit_down } - otherwise: 1 + opening: { when: "position(snapshot) == 0", expression: Generator_status_initial } + otherwise: shift(Generator_status, along=snapshot, offset=1) ``` ```math -\widetilde{\mathrm{rd}}^{z}_{\xi,t,j} = \begin{cases} \mathrm{rd}^{z}_{\xi,t,j} & \text{if } \mathrm{rd}^{z}_{\xi,t,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +\overleftarrow{u}^{\circ}_{\xi,t,g} = \begin{cases} \mathrm{u}^{0}_{\xi,g} & \text{if } \mathrm{pos}(t) = 0 \\ u_{\xi,t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `Process_start_up_rate` +### `Generator_previous_p` ```yaml -Process_start_up_rate: +Generator_previous_p: description: >- - the start-up ramp a process's up row reads — PyPSA's `ramp_limit_start_up`, - or the full build where it has none - dims: [scenario, process] + the output a generator carries into a snapshot — at the first, the + `p_init` it brought in where it came in running and nothing where it + came in off; the previous snapshot's after that + dims: [scenario, snapshot, generator] cases: - given: { when: Process_ramp_limit_start_up, expression: Process_ramp_limit_start_up } - otherwise: 1 + opening: { when: "position(snapshot) == 0", expression: Generator_status_initial * Generator_p_init } + otherwise: shift(Generator_p, along=snapshot, offset=1) ``` ```math -\widetilde{\mathrm{ru}}^{z,\mathrm{up}}_{\xi,j} = \begin{cases} \mathrm{ru}^{z,\mathrm{up}}_{\xi,j} & \text{if } \mathrm{ru}^{z,\mathrm{up}}_{\xi,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} +\overleftarrow{p}_{\xi,t,g} = \begin{cases} \mathrm{u}^{0}_{\xi,g} \cdot \mathrm{p}^{0}_{\xi,g} & \text{if } \mathrm{pos}(t) = 0 \\ p_{\xi,t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `Process_shut_down_rate` +### `Generator_p_nom_effective` ```yaml -Process_shut_down_rate: - description: >- - the shut-down ramp a process's down row reads — PyPSA's - `ramp_limit_shut_down`, or the full build where it has none - dims: [scenario, process] +Generator_p_nom_effective: + description: the build a generator's limits are taken against — the chosen one where it is extendable, the given one otherwise + dims: [scenario, generator] cases: - given: { when: Process_ramp_limit_shut_down, expression: Process_ramp_limit_shut_down } - otherwise: 1 + extendable: { when: Generator_p_nom_extendable, expression: Generator_p_nom_ext } + otherwise: Generator_p_nom ``` ```math -\widetilde{\mathrm{rd}}^{z,\mathrm{dn}}_{\xi,j} = \begin{cases} \mathrm{rd}^{z,\mathrm{dn}}_{\xi,j} & \text{if } \mathrm{rd}^{z,\mathrm{dn}}_{\xi,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} +\widetilde{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} = \begin{cases} P_{g} & \text{if } \mathrm{ext}_{g} \\ \mathrm{p}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} ``` -### `Process_p_nom_committed` +### `Generator_ramp_up_rate` ```yaml -Process_p_nom_committed: +Generator_ramp_up_rate: description: >- - the build a committed process's ramp rows are taken against — one module - where the build is extendable and modular, the given build otherwise - dims: [scenario, process] + the ramp limit a unit's up row reads — PyPSA's `ramp_limit_up`, or the + full build where it has none, since a start-up ramp alone builds the row + dims: [scenario, snapshot, generator] cases: - modular_build: { when: Process_p_nom_extendable AND Process_p_nom_mod > 0, expression: Process_p_nom_mod } - otherwise: Process_p_nom + given: { when: Generator_ramp_limit_up, expression: Generator_ramp_limit_up } + otherwise: 1 ``` ```math -\widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} = \begin{cases} \mathrm{z}^{\mathrm{mod}}_{j} & \text{if } \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \\ \mathrm{z}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} +\widetilde{\mathrm{ru}}_{\xi,t,g} = \begin{cases} \mathrm{ru}_{\xi,t,g} & \text{if } \mathrm{ru}_{\xi,t,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `Process_ramp_up_allowance` +### `Generator_ramp_down_rate` ```yaml -Process_ramp_up_allowance: +Generator_ramp_down_rate: description: >- - how far a process may raise internal power between two snapshots — its ramp - limit of the build while it stays on, plus its start-up ramp in the - snapshot it turns on - dims: [scenario, snapshot, process] + the ramp limit a unit's down row reads — PyPSA's `ramp_limit_down`, or + the full build where it has none, since a shut-down ramp alone builds the row + dims: [scenario, snapshot, generator] cases: - committed: - when: Process_committable - expression: >- - Process_ramp_up_rate * Process_p_nom_committed * Process_previous_status - + Process_start_up_rate * Process_p_nom_committed - * (Process_status - Process_previous_status) - otherwise: Process_ramp_up_rate * Process_p_nom_effective + given: { when: Generator_ramp_limit_down, expression: Generator_ramp_limit_down } + otherwise: 1 ``` ```math -\Delta^{z,+}_{\xi,t,j} = \begin{cases} \widetilde{\mathrm{ru}}^{z}_{\xi,t,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot \overleftarrow{u}^{z}_{\xi,t,j} + \widetilde{\mathrm{ru}}^{z,\mathrm{up}}_{\xi,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \overleftarrow{u}^{z}_{\xi,t,j} \right) & \text{if } \mathrm{com}^{z}_{j} \\ \widetilde{\mathrm{ru}}^{z}_{\xi,t,j} \cdot \widetilde{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +\widetilde{\mathrm{rd}}_{\xi,t,g} = \begin{cases} \mathrm{rd}_{\xi,t,g} & \text{if } \mathrm{rd}_{\xi,t,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `Process_ramp_down_allowance` +### `Generator_start_up_rate` ```yaml -Process_ramp_down_allowance: +Generator_start_up_rate: description: >- - how far a process may lower internal power between two snapshots — its ramp - limit of the build while it stays on, plus its shut-down ramp in the - snapshot it turns off - dims: [scenario, snapshot, process] + the start-up ramp a unit's up row reads — PyPSA's `ramp_limit_start_up`, + or the full build where it has none + dims: [scenario, generator] cases: - committed: - when: Process_committable - expression: >- - Process_ramp_down_rate * Process_p_nom_committed * Process_status - + Process_shut_down_rate * Process_p_nom_committed - * (Process_previous_status - Process_status) - otherwise: Process_ramp_down_rate * Process_p_nom_effective + given: { when: Generator_ramp_limit_start_up, expression: Generator_ramp_limit_start_up } + otherwise: 1 ``` ```math -\Delta^{z,-}_{\xi,t,j} = \begin{cases} \widetilde{\mathrm{rd}}^{z}_{\xi,t,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot u^{z}_{\xi,t,j} + \widetilde{\mathrm{rd}}^{z,\mathrm{dn}}_{\xi,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot \left( \overleftarrow{u}^{z}_{\xi,t,j} - u^{z}_{\xi,t,j} \right) & \text{if } \mathrm{com}^{z}_{j} \\ \widetilde{\mathrm{rd}}^{z}_{\xi,t,j} \cdot \widetilde{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +\widetilde{\mathrm{ru}}^{\mathrm{up}}_{\xi,g} = \begin{cases} \mathrm{ru}^{\mathrm{up}}_{\xi,g} & \text{if } \mathrm{ru}^{\mathrm{up}}_{\xi,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} ``` -### `StorageUnit_charge_carried_in` +### `Generator_shut_down_rate` ```yaml -StorageUnit_charge_carried_in: +Generator_shut_down_rate: description: >- - the charge a unit opens a snapshot with — at the first snapshot it - stands in, its last such snapshot's less standing loss where it is - cyclic and the given initial charge, which no standing loss has touched - yet, where it is not; the previous snapshot's less standing loss - otherwise. A unit built in a later period opens in that period, and a - cyclic one that retires closes on its own last snapshot. Per period, the - same holds with each investment period as the horizon - dims: [scenario, snapshot, storage_unit] + the shut-down ramp a unit's down row reads — PyPSA's + `ramp_limit_shut_down`, or the full build where it has none + dims: [scenario, generator] cases: - cyclic: - when: >- - StorageUnit_cyclic_state_of_charge AND NOT StorageUnit_cyclic_state_of_charge_per_period - AND NOT StorageUnit_state_of_charge_initial_per_period - AND (position(snapshot) == 0 OR StorageUnit_opens_late) - expression: >- - StorageUnit_retention - * shift(shift(StorageUnit_state_of_charge, along=snapshot, offset=1, edge='wrap'), along=snapshot, offset=StorageUnit_inactive_snapshots, edge='wrap') - opening: - when: >- - NOT StorageUnit_cyclic_state_of_charge AND NOT StorageUnit_cyclic_state_of_charge_per_period - AND NOT StorageUnit_state_of_charge_initial_per_period - AND (position(snapshot) == 0 OR StorageUnit_opens_late) - expression: StorageUnit_state_of_charge_initial - period_cyclic: - when: StorageUnit_cyclic_state_of_charge_per_period - expression: >- - StorageUnit_retention - * shift(StorageUnit_state_of_charge, along=snapshot, offset=1, edge='wrap', within=snapshot_period[period]) - period_opening: - when: >- - StorageUnit_state_of_charge_initial_per_period AND NOT StorageUnit_cyclic_state_of_charge_per_period - AND position(snapshot, within=snapshot_period[period]) == 0 - expression: StorageUnit_state_of_charge_initial - otherwise: StorageUnit_retention * shift(StorageUnit_state_of_charge, along=snapshot, offset=1) + given: { when: Generator_ramp_limit_shut_down, expression: Generator_ramp_limit_shut_down } + otherwise: 1 ``` ```math -\overleftarrow{\mathit{soc}}_{\xi,t,s} = \begin{cases} \rho_{\xi,t,s} \cdot \mathit{soc}_{\xi,\left( t \ominus \mathrm{idle} \right) \ominus 1,s} & \text{if } \mathrm{cyc}_{\xi,s} \wedge \neg \mathrm{cyc}^{y}_{\xi,s} \wedge \neg \mathrm{reset}_{\xi,s} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}_{t,s} \right) \\ \mathrm{soc}^{0}_{\xi,s} & \text{if } \neg \mathrm{cyc}_{\xi,s} \wedge \neg \mathrm{cyc}^{y}_{\xi,s} \wedge \neg \mathrm{reset}_{\xi,s} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}_{t,s} \right) \\ \rho_{\xi,t,s} \cdot \mathit{soc}_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} 1,s} & \text{if } \mathrm{cyc}^{y}_{\xi,s} \\ \mathrm{soc}^{0}_{\xi,s} & \text{if } \mathrm{reset}_{\xi,s} \wedge \neg \mathrm{cyc}^{y}_{\xi,s} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = 0 \\ \rho_{\xi,t,s} \cdot \mathit{soc}_{\xi,t - 1,s} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} +\widetilde{\mathrm{rd}}^{\mathrm{dn}}_{\xi,g} = \begin{cases} \mathrm{rd}^{\mathrm{dn}}_{\xi,g} & \text{if } \mathrm{rd}^{\mathrm{dn}}_{\xi,g} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} ``` -### `Store_energy_carried_in` +### `Generator_p_nom_committed` ```yaml -Store_energy_carried_in: +Generator_p_nom_committed: description: >- - the energy a store opens a snapshot with — at the first snapshot it - stands in, its last such snapshot's less standing loss where it is - cyclic and the given initial energy, which no standing loss has touched - yet, where it is not; the previous snapshot's less standing loss - otherwise. A store built in a later period opens in that period, and a - cyclic one that retires closes on its own last snapshot. Per period, the - same holds with each investment period as the horizon - dims: [scenario, snapshot, store] + the build a committed unit's ramp rows are taken against — one module + where the build is extendable and modular, the given build otherwise + dims: [scenario, generator] cases: - cyclic: - when: >- - Store_e_cyclic AND NOT Store_e_cyclic_per_period AND NOT Store_e_initial_per_period - AND (position(snapshot) == 0 OR Store_opens_late) - expression: >- - Store_retention - * shift(shift(Store_e, along=snapshot, offset=1, edge='wrap'), along=snapshot, offset=Store_inactive_snapshots, edge='wrap') - opening: - when: >- - NOT Store_e_cyclic AND NOT Store_e_cyclic_per_period AND NOT Store_e_initial_per_period - AND (position(snapshot) == 0 OR Store_opens_late) - expression: Store_e_initial - period_cyclic: - when: Store_e_cyclic_per_period - expression: Store_retention * shift(Store_e, along=snapshot, offset=1, edge='wrap', within=snapshot_period[period]) - period_opening: - when: Store_e_initial_per_period AND NOT Store_e_cyclic_per_period AND position(snapshot, within=snapshot_period[period]) == 0 - expression: Store_e_initial - otherwise: Store_retention * shift(Store_e, along=snapshot, offset=1) + modular_build: { when: Generator_p_nom_extendable AND Generator_p_nom_mod > 0, expression: Generator_p_nom_mod } + otherwise: Generator_p_nom ``` ```math -\overleftarrow{e}_{\xi,t,v} = \begin{cases} \rho^{e}_{\xi,t,v} \cdot e_{\xi,\left( t \ominus \mathrm{idle}^{e} \right) \ominus 1,v} & \text{if } \mathrm{cyc}^{e}_{\xi,v} \wedge \neg \mathrm{cyc}^{e,y}_{\xi,v} \wedge \neg \mathrm{reset}^{e}_{\xi,v} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}^{e}_{t,v} \right) \\ \mathrm{e}^{0}_{\xi,v} & \text{if } \neg \mathrm{cyc}^{e}_{\xi,v} \wedge \neg \mathrm{cyc}^{e,y}_{\xi,v} \wedge \neg \mathrm{reset}^{e}_{\xi,v} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}^{e}_{t,v} \right) \\ \rho^{e}_{\xi,t,v} \cdot e_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} 1,v} & \text{if } \mathrm{cyc}^{e,y}_{\xi,v} \\ \mathrm{e}^{0}_{\xi,v} & \text{if } \mathrm{reset}^{e}_{\xi,v} \wedge \neg \mathrm{cyc}^{e,y}_{\xi,v} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = 0 \\ \rho^{e}_{\xi,t,v} \cdot e_{\xi,t - 1,v} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} +\widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} = \begin{cases} \mathrm{p}^{\mathrm{mod}}_{g} & \text{if } \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \\ \mathrm{p}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ g \in \mathcal{G} ``` -### `Link_output_arrival` +### `Generator_ramp_up_allowance` ```yaml -Link_output_arrival: +Generator_ramp_up_allowance: description: >- - what a link delivers to an output port at a snapshot — its flow delayed - by the port's `delay` within its investment period, times the port's - efficiency at the snapshot the flow arrives; where the port is - `cyclic_delay` the delayed flow wraps from the period's end, and where it - is not the flow still in transit at the period's first snapshots is - lost. A port that does not delay (`delay` - zero) delivers its flow unshifted, cyclic or not - dims: [scenario, snapshot, link_output] + how far a generator may raise output between two snapshots — its ramp + limit of the build while it stays on, plus its start-up ramp in the + snapshot it turns on + dims: [scenario, snapshot, generator] cases: - wrapping: - when: Link_output_cyclic_delay - expression: shift(at(Link_p, by=Link_output_link[link]), along=snapshot, offset=Link_output_delay, edge='wrap', within=snapshot_period[period]) * Link_efficiency - otherwise: shift(at(Link_p, by=Link_output_link[link]), along=snapshot, offset=Link_output_delay, edge=0, within=snapshot_period[period]) * Link_efficiency + committed: + when: Generator_committable + expression: >- + Generator_ramp_up_rate * Generator_p_nom_committed * Generator_previous_status + + Generator_start_up_rate * Generator_p_nom_committed + * (Generator_status - Generator_previous_status) + otherwise: Generator_ramp_up_rate * Generator_p_nom_effective ``` ```math -\overrightarrow{f}_{\xi,t,o} = \begin{cases} f_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{f},\mathrm{Link\_output\_link}(o)} \cdot \eta_{\xi,t,o} & \text{if } \mathrm{cyc}^{f}_{o} \\ f_{\xi,t \boxminus_{0}^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{f},\mathrm{Link\_output\_link}(o)} \cdot \eta_{\xi,t,o} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ o \in \mathcal{O} +\Delta^{+}_{\xi,t,g} = \begin{cases} \widetilde{\mathrm{ru}}_{\xi,t,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot \overleftarrow{u}_{\xi,t,g} + \widetilde{\mathrm{ru}}^{\mathrm{up}}_{\xi,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot \left( u_{\xi,t,g} - \overleftarrow{u}_{\xi,t,g} \right) & \text{if } \mathrm{com}_{g} \\ \widetilde{\mathrm{ru}}_{\xi,t,g} \cdot \widetilde{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `Process_output_arrival` +### `Generator_ramp_down_allowance` ```yaml -Process_output_arrival: +Generator_ramp_down_allowance: description: >- - what a process transfers at a port at a snapshot — its internal power - delayed by the port's `delay` within its investment period, times the - port's rate at the snapshot the transfer arrives; where the port is - `cyclic_delay` the delayed transfer wraps from the period's end, and - where it is not the energy still in transit at the period's first - snapshots is lost. A port that does not - delay (`delay` zero) transfers at once, cyclic or not - dims: [scenario, snapshot, process_output] + how far a generator may lower output between two snapshots — its ramp + limit of the build while it stays on, plus its shut-down ramp in the + snapshot it turns off + dims: [scenario, snapshot, generator] cases: - wrapping: - when: Process_output_cyclic_delay - expression: shift(at(Process_p, by=Process_output_process[process]), along=snapshot, offset=Process_output_delay, edge='wrap', within=snapshot_period[period]) * Process_rate - otherwise: shift(at(Process_p, by=Process_output_process[process]), along=snapshot, offset=Process_output_delay, edge=0, within=snapshot_period[period]) * Process_rate + committed: + when: Generator_committable + expression: >- + Generator_ramp_down_rate * Generator_p_nom_committed * Generator_status + + Generator_shut_down_rate * Generator_p_nom_committed + * (Generator_previous_status - Generator_status) + otherwise: Generator_ramp_down_rate * Generator_p_nom_effective ``` ```math -\overrightarrow{z}_{\xi,t,r} = \begin{cases} z_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{z},\mathrm{Process\_output\_process}(r)} \cdot \alpha_{\xi,t,r} & \text{if } \mathrm{cyc}^{z}_{r} \\ z_{\xi,t \boxminus_{0}^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{z},\mathrm{Process\_output\_process}(r)} \cdot \alpha_{\xi,t,r} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ r \in \mathcal{R} +\Delta^{-}_{\xi,t,g} = \begin{cases} \widetilde{\mathrm{rd}}_{\xi,t,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot u_{\xi,t,g} + \widetilde{\mathrm{rd}}^{\mathrm{dn}}_{\xi,g} \cdot \widehat{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} \cdot \left( \overleftarrow{u}_{\xi,t,g} - u_{\xi,t,g} \right) & \text{if } \mathrm{com}_{g} \\ \widetilde{\mathrm{rd}}_{\xi,t,g} \cdot \widetilde{\mathrm{p}}^{\mathrm{nom}}_{\xi,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -### `GlobalConstraint_energy_weight` +### `Link_p_nom_effective` ```yaml -GlobalConstraint_energy_weight: - description: >- - what one unit of power at a snapshot counts for in a row — the - generator weighting times the years of the snapshot's period, where the - row counts the snapshot, and nothing where it does not - dims: [scenario, global_constraint, snapshot] +Link_p_nom_effective: + description: the build a link's limits are taken against — the chosen one where it is extendable, the given one otherwise + dims: [scenario, link] cases: - counted: - when: GlobalConstraint_counts_snapshot - expression: snapshot_weightings_generators * at(period_weight_years, by=snapshot_period[period]) - otherwise: 0 + extendable: { when: Link_p_nom_extendable, expression: Link_p_nom_ext } + otherwise: Link_p_nom ``` ```math -\mathit{w}^{\mathrm{gc}}_{\xi,i,t} = \begin{cases} \mathrm{w}^{\mathrm{gen}}_{t} \cdot \mathrm{w}^{\mathrm{yr}}_{\mathrm{snapshot\_period}(t)} & \text{if } \mathrm{in}_{\xi,i,t} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T} +\widetilde{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} = \begin{cases} F_{l} & \text{if } \mathrm{ext}^{f}_{l} \\ \mathrm{f}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} ``` -### `StorageUnit_last_counted_active` +### `Link_previous_status` ```yaml -StorageUnit_last_counted_active: +Link_previous_status: description: >- - one at the last snapshot a row counts where a unit stands, and zero - elsewhere — a unit that retires before the last counted snapshot closes - on its last active level, as PyPSA forward-fills the level over the - counted snapshots (`global_constraints.py:455-458`) - dims: [scenario, global_constraint, snapshot, storage_unit] + the commitment state a link carries into a snapshot — off at the + first snapshot it stands in past the first of the horizon, as PyPSA + reads a status it did not build (`constraints.py:298`), and the state + carried over otherwise + dims: [scenario, snapshot, link] cases: - last: - when: >- - GlobalConstraint_counts_snapshot AND StorageUnit_active - AND NOT shift(GlobalConstraint_counts_snapshot AND StorageUnit_active, along=snapshot, offset=-1) - expression: 1 - otherwise: 0 + opening_late: { when: "position(snapshot) > 0 AND NOT shift(Link_active, along=snapshot, offset=1)", expression: 0 } + otherwise: Link_status_carried_over ``` ```math -\mathit{last}^{h}_{\xi,i,t,s} = \begin{cases} 1 & \text{if } \mathrm{in}_{\xi,i,t} \wedge \mathrm{on}^{h}_{t,s} \wedge \neg \left( \mathrm{in}_{\xi,i,t + 1} \wedge \mathrm{on}^{h}_{t + 1,s} \right) \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ s \in \mathcal{S} +\overleftarrow{u}^{f}_{\xi,t,l} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{f}_{t - 1,l} \\ \overleftarrow{u}^{\circ f}_{\xi,t,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `StorageUnit_closing_weight` +### `Link_status_carried_over` ```yaml -StorageUnit_closing_weight: +Link_status_carried_over: description: >- - what the charge a unit holds at a snapshot counts for in a row as its - closing level — the years of the period at the last snapshot of each - counted period where the unit reopens per period, one at the last - counted snapshot it stands in where it does not, and nothing elsewhere - dims: [scenario, global_constraint, snapshot, storage_unit] + the state a link carries over into a snapshot — the state it brought + into the horizon at the first, the previous snapshot's after that + dims: [scenario, snapshot, link] cases: - per_period: - when: StorageUnit_state_of_charge_initial_per_period AND GlobalConstraint_counts_snapshot AND position(snapshot, within=snapshot_period[period]) == -1 - expression: at(period_weight_years, by=snapshot_period[period]) - carried_over: - when: NOT StorageUnit_state_of_charge_initial_per_period - expression: StorageUnit_last_counted_active - otherwise: 0 + opening: { when: "position(snapshot) == 0", expression: Link_status_initial } + otherwise: shift(Link_status, along=snapshot, offset=1) ``` ```math -\mathit{w}^{h}_{\xi,i,t,s} = \begin{cases} \mathrm{w}^{\mathrm{yr}}_{\mathrm{snapshot\_period}(t)} & \text{if } \mathrm{reset}_{\xi,s} \wedge \mathrm{in}_{\xi,i,t} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = \lvert \mathcal{T}_{\mathrm{snapshot\_period}(t)} \rvert - 1 \\ \mathit{last}^{h}_{\xi,i,t,s} & \text{if } \neg \mathrm{reset}_{\xi,s} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ s \in \mathcal{S} +\overleftarrow{u}^{\circ f}_{\xi,t,l} = \begin{cases} \mathrm{u}^{f,0}_{\xi,l} & \text{if } \mathrm{pos}(t) = 0 \\ u^{f}_{\xi,t - 1,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `Store_last_counted_active` +### `Link_previous_p` ```yaml -Store_last_counted_active: +Link_previous_p: description: >- - one at the last snapshot a row counts where a store stands, and zero - elsewhere — a store that retires before the last counted snapshot closes - on its last active level, as PyPSA forward-fills the level over the - counted snapshots (`global_constraints.py:507-510`) - dims: [scenario, global_constraint, snapshot, store] + the flow a link carries into a snapshot — at the first, the + `p_init` it brought in where it came in running and nothing where it + came in off; the previous snapshot's after that + dims: [scenario, snapshot, link] cases: - last: - when: >- - GlobalConstraint_counts_snapshot AND Store_active - AND NOT shift(GlobalConstraint_counts_snapshot AND Store_active, along=snapshot, offset=-1) - expression: 1 - otherwise: 0 + opening: { when: "position(snapshot) == 0", expression: Link_status_initial * Link_p_init } + otherwise: shift(Link_p, along=snapshot, offset=1) ``` ```math -\mathit{last}^{e}_{\xi,i,t,v} = \begin{cases} 1 & \text{if } \mathrm{in}_{\xi,i,t} \wedge \mathrm{on}^{e}_{t,v} \wedge \neg \left( \mathrm{in}_{\xi,i,t + 1} \wedge \mathrm{on}^{e}_{t + 1,v} \right) \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ v \in \mathcal{V} +\overleftarrow{f}_{\xi,t,l} = \begin{cases} \mathrm{u}^{f,0}_{\xi,l} \cdot \mathrm{f}^{0}_{\xi,l} & \text{if } \mathrm{pos}(t) = 0 \\ f_{\xi,t - 1,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `Store_closing_weight` +### `Link_ramp_up_rate` ```yaml -Store_closing_weight: +Link_ramp_up_rate: description: >- - what the energy a store holds at a snapshot counts for in a row as its - closing level — the years of the period at the last snapshot of each - counted period where the store reopens per period, one at the last - counted snapshot it stands in where it does not, and nothing elsewhere - dims: [scenario, global_constraint, snapshot, store] + the ramp limit a link's up row reads — PyPSA's `ramp_limit_up`, or the + full build where it has none, since a start-up ramp alone builds the row + dims: [scenario, snapshot, link] cases: - per_period: - when: Store_e_initial_per_period AND GlobalConstraint_counts_snapshot AND position(snapshot, within=snapshot_period[period]) == -1 - expression: at(period_weight_years, by=snapshot_period[period]) - carried_over: - when: NOT Store_e_initial_per_period - expression: Store_last_counted_active - otherwise: 0 + given: { when: Link_ramp_limit_up, expression: Link_ramp_limit_up } + otherwise: 1 ``` ```math -\mathit{w}^{e}_{\xi,i,t,v} = \begin{cases} \mathrm{w}^{\mathrm{yr}}_{\mathrm{snapshot\_period}(t)} & \text{if } \mathrm{reset}^{e}_{\xi,v} \wedge \mathrm{in}_{\xi,i,t} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = \lvert \mathcal{T}_{\mathrm{snapshot\_period}(t)} \rvert - 1 \\ \mathit{last}^{e}_{\xi,i,t,v} & \text{if } \neg \mathrm{reset}^{e}_{\xi,v} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ v \in \mathcal{V} +\widetilde{\mathrm{ru}}^{f}_{\xi,t,l} = \begin{cases} \mathrm{ru}^{f}_{\xi,t,l} & \text{if } \mathrm{ru}^{f}_{\xi,t,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `Generator_primary_energy` +### `Link_ramp_down_rate` ```yaml -Generator_primary_energy: - expression: >- - sum(sum((Generator_p * GlobalConstraint_energy_weight) * Generator_primary_energy_weight, over=snapshot), over=generator) +Link_ramp_down_rate: + description: >- + the ramp limit a link's down row reads — PyPSA's `ramp_limit_down`, or + the full build where it has none, since a shut-down ramp alone builds the row + dims: [scenario, snapshot, link] + cases: + given: { when: Link_ramp_limit_down, expression: Link_ramp_limit_down } + otherwise: 1 ``` ```math -\mathit{Generator\_primary\_energy}_{\xi,i} = \sum_{g \in \mathcal{G}} \sum_{t \in \mathcal{T}} p_{\xi,t,g} \cdot \mathit{w}^{\mathrm{gc}}_{\xi,i,t} \cdot \mathrm{a}_{\xi,i,t,g} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{rd}}^{f}_{\xi,t,l} = \begin{cases} \mathrm{rd}^{f}_{\xi,t,l} & \text{if } \mathrm{rd}^{f}_{\xi,t,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `StorageUnit_primary_energy` +### `Link_start_up_rate` ```yaml -StorageUnit_primary_energy: - expression: >- - -sum(sum((StorageUnit_state_of_charge * StorageUnit_closing_weight) * StorageUnit_primary_energy_weight, over=snapshot), over=storage_unit) +Link_start_up_rate: + description: >- + the start-up ramp a link's up row reads — PyPSA's `ramp_limit_start_up`, + or the full build where it has none + dims: [scenario, link] + cases: + given: { when: Link_ramp_limit_start_up, expression: Link_ramp_limit_start_up } + otherwise: 1 ``` ```math -\mathit{StorageUnit\_primary\_energy}_{\xi,i} = -\left( \sum_{s \in \mathcal{S}} \sum_{t \in \mathcal{T}} \mathit{soc}_{\xi,t,s} \cdot \mathit{w}^{h}_{\xi,i,t,s} \cdot \mathrm{a}^{h}_{\xi,i,s} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{ru}}^{f,\mathrm{up}}_{\xi,l} = \begin{cases} \mathrm{ru}^{f,\mathrm{up}}_{\xi,l} & \text{if } \mathrm{ru}^{f,\mathrm{up}}_{\xi,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} ``` -### `Store_primary_energy` +### `Link_shut_down_rate` ```yaml -Store_primary_energy: - expression: >- - -sum(sum((Store_e * Store_closing_weight) * Store_primary_energy_weight, over=snapshot), over=store) +Link_shut_down_rate: + description: >- + the shut-down ramp a link's down row reads — PyPSA's + `ramp_limit_shut_down`, or the full build where it has none + dims: [scenario, link] + cases: + given: { when: Link_ramp_limit_shut_down, expression: Link_ramp_limit_shut_down } + otherwise: 1 ``` ```math -\mathit{Store\_primary\_energy}_{\xi,i} = -\left( \sum_{v \in \mathcal{V}} \sum_{t \in \mathcal{T}} e_{\xi,t,v} \cdot \mathit{w}^{e}_{\xi,i,t,v} \cdot \mathrm{a}^{e}_{\xi,i,v} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{rd}}^{f,\mathrm{dn}}_{\xi,l} = \begin{cases} \mathrm{rd}^{f,\mathrm{dn}}_{\xi,l} & \text{if } \mathrm{rd}^{f,\mathrm{dn}}_{\xi,l} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} ``` -### `primary_energy` +### `Link_p_nom_committed` ```yaml -primary_energy: - dims: [scenario, global_constraint] - expression: Generator_primary_energy + StorageUnit_primary_energy + Store_primary_energy +Link_p_nom_committed: description: >- - what a `primary_energy` row totals — weighted generator energy over the - snapshots it counts, less the charge left in weighted storage at the - close; the initial charge it is compared against is folded into the - row's constant + the build a committed link's ramp rows are taken against — one module + where the build is extendable and modular, the given build otherwise + dims: [scenario, link] + cases: + modular_build: { when: Link_p_nom_extendable AND Link_p_nom_mod > 0, expression: Link_p_nom_mod } + otherwise: Link_p_nom ``` ```math -\mathit{primary\_energy}_{\xi,i} = \mathit{Generator\_primary\_energy}_{\xi,i} + \mathit{StorageUnit\_primary\_energy}_{\xi,i} + \mathit{Store\_primary\_energy}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} = \begin{cases} \mathrm{f}^{\mathrm{mod}}_{l} & \text{if } \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \\ \mathrm{f}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ l \in \mathcal{L} ``` -### `Generator_operational_limit` +### `Link_ramp_up_allowance` ```yaml -Generator_operational_limit: - expression: >- - sum(sum((Generator_p * GlobalConstraint_energy_weight) * Generator_operational_limit_weight, over=snapshot), over=generator) +Link_ramp_up_allowance: + description: >- + how far a link may raise flow between two snapshots — its ramp + limit of the build while it stays on, plus its start-up ramp in the + snapshot it turns on + dims: [scenario, snapshot, link] + cases: + committed: + when: Link_committable + expression: >- + Link_ramp_up_rate * Link_p_nom_committed * Link_previous_status + + Link_start_up_rate * Link_p_nom_committed + * (Link_status - Link_previous_status) + otherwise: Link_ramp_up_rate * Link_p_nom_effective ``` ```math -\mathit{Generator\_operational\_limit}_{\xi,i} = \sum_{g \in \mathcal{G}} \sum_{t \in \mathcal{T}} p_{\xi,t,g} \cdot \mathit{w}^{\mathrm{gc}}_{\xi,i,t} \cdot \mathrm{b}_{\xi,i,g} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\Delta^{f,+}_{\xi,t,l} = \begin{cases} \widetilde{\mathrm{ru}}^{f}_{\xi,t,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot \overleftarrow{u}^{f}_{\xi,t,l} + \widetilde{\mathrm{ru}}^{f,\mathrm{up}}_{\xi,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot \left( u^{f}_{\xi,t,l} - \overleftarrow{u}^{f}_{\xi,t,l} \right) & \text{if } \mathrm{com}^{f}_{l} \\ \widetilde{\mathrm{ru}}^{f}_{\xi,t,l} \cdot \widetilde{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `StorageUnit_operational_limit` +### `Link_ramp_down_allowance` ```yaml -StorageUnit_operational_limit: - expression: >- - -sum(sum((StorageUnit_state_of_charge * StorageUnit_closing_weight) * StorageUnit_operational_limit_weight, over=snapshot), over=storage_unit) +Link_ramp_down_allowance: + description: >- + how far a link may lower flow between two snapshots — its ramp + limit of the build while it stays on, plus its shut-down ramp in the + snapshot it turns off + dims: [scenario, snapshot, link] + cases: + committed: + when: Link_committable + expression: >- + Link_ramp_down_rate * Link_p_nom_committed * Link_status + + Link_shut_down_rate * Link_p_nom_committed + * (Link_previous_status - Link_status) + otherwise: Link_ramp_down_rate * Link_p_nom_effective ``` ```math -\mathit{StorageUnit\_operational\_limit}_{\xi,i} = -\left( \sum_{s \in \mathcal{S}} \sum_{t \in \mathcal{T}} \mathit{soc}_{\xi,t,s} \cdot \mathit{w}^{h}_{\xi,i,t,s} \cdot \mathrm{b}^{h}_{\xi,i,s} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\Delta^{f,-}_{\xi,t,l} = \begin{cases} \widetilde{\mathrm{rd}}^{f}_{\xi,t,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot u^{f}_{\xi,t,l} + \widetilde{\mathrm{rd}}^{f,\mathrm{dn}}_{\xi,l} \cdot \widehat{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} \cdot \left( \overleftarrow{u}^{f}_{\xi,t,l} - u^{f}_{\xi,t,l} \right) & \text{if } \mathrm{com}^{f}_{l} \\ \widetilde{\mathrm{rd}}^{f}_{\xi,t,l} \cdot \widetilde{\mathrm{f}}^{\mathrm{nom}}_{\xi,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -### `Store_operational_limit` +### `Process_p_nom_effective` ```yaml -Store_operational_limit: - expression: >- - -sum(sum((Store_e * Store_closing_weight) * Store_operational_limit_weight, over=snapshot), over=store) +Process_p_nom_effective: + description: the build a process's limits are taken against — the chosen one where it is extendable, the given one otherwise + dims: [scenario, process] + cases: + extendable: { when: Process_p_nom_extendable, expression: Process_p_nom_ext } + otherwise: Process_p_nom ``` ```math -\mathit{Store\_operational\_limit}_{\xi,i} = -\left( \sum_{v \in \mathcal{V}} \sum_{t \in \mathcal{T}} e_{\xi,t,v} \cdot \mathit{w}^{e}_{\xi,i,t,v} \cdot \mathrm{b}^{e}_{\xi,i,v} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} = \begin{cases} Z_{j} & \text{if } \mathrm{ext}^{z}_{j} \\ \mathrm{z}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} ``` -### `operational_limit` +### `Process_previous_status` ```yaml -operational_limit: - dims: [scenario, global_constraint] - expression: >- - Generator_operational_limit - + StorageUnit_operational_limit - + Store_operational_limit +Process_previous_status: description: >- - what an `operational_limit` row totals — the weighted energy its - generators deliver over the snapshots it counts, plus what its - non-cyclic storage draws down; the initial charge it draws from is - folded into the row's constant + the commitment state a process carries into a snapshot — off at the + first snapshot it stands in past the first of the horizon, as PyPSA + reads a status it did not build (`constraints.py:298`), and the state + carried over otherwise + dims: [scenario, snapshot, process] + cases: + opening_late: { when: "position(snapshot) > 0 AND NOT shift(Process_active, along=snapshot, offset=1)", expression: 0 } + otherwise: Process_status_carried_over ``` ```math -\mathit{operational\_limit}_{\xi,i} = \mathit{Generator\_operational\_limit}_{\xi,i} + \mathit{StorageUnit\_operational\_limit}_{\xi,i} + \mathit{Store\_operational\_limit}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\overleftarrow{u}^{z}_{\xi,t,j} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{z}_{t - 1,j} \\ \overleftarrow{u}^{\circ z}_{\xi,t,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `Line_transmission_volume_expansion` +### `Process_status_carried_over` ```yaml -Line_transmission_volume_expansion: - expression: sum(Line_s_nom_ext * Line_volume_weight, over=line) +Process_status_carried_over: + description: >- + the state a process carries over into a snapshot — the state it brought + into the horizon at the first, the previous snapshot's after that + dims: [scenario, snapshot, process] + cases: + opening: { when: "position(snapshot) == 0", expression: Process_status_initial } + otherwise: shift(Process_status, along=snapshot, offset=1) ``` ```math -\mathit{Line\_transmission\_volume\_expansion}_{\xi,i} = \sum_{k \in \mathcal{K}} S_{k} \cdot \mathrm{len}_{\xi,i,k} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\overleftarrow{u}^{\circ z}_{\xi,t,j} = \begin{cases} \mathrm{u}^{z,0}_{\xi,j} & \text{if } \mathrm{pos}(t) = 0 \\ u^{z}_{\xi,t - 1,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `Link_transmission_volume_expansion` +### `Process_previous_p` ```yaml -Link_transmission_volume_expansion: - expression: sum(Link_p_nom_ext * Link_volume_weight, over=link) +Process_previous_p: + description: >- + the internal power a process carries into a snapshot — at the first, the + `p_init` it brought in where it came in running and nothing where it + came in off; the previous snapshot's after that + dims: [scenario, snapshot, process] + cases: + opening: { when: "position(snapshot) == 0", expression: Process_status_initial * Process_p_init } + otherwise: shift(Process_p, along=snapshot, offset=1) ``` ```math -\mathit{Link\_transmission\_volume\_expansion}_{\xi,i} = \sum_{l \in \mathcal{L}} F_{l} \cdot \mathrm{len}^{f}_{\xi,i,l} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\overleftarrow{z}_{\xi,t,j} = \begin{cases} \mathrm{u}^{z,0}_{\xi,j} \cdot \mathrm{z}^{0}_{\xi,j} & \text{if } \mathrm{pos}(t) = 0 \\ z_{\xi,t - 1,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `transmission_volume_expansion` +### `Process_ramp_up_rate` ```yaml -transmission_volume_expansion: - dims: [scenario, global_constraint] - expression: Line_transmission_volume_expansion + Link_transmission_volume_expansion +Process_ramp_up_rate: description: >- - what a `transmission_volume_expansion_limit` row totals — length times - the chosen build of the row's branches + the ramp limit a process's up row reads — PyPSA's `ramp_limit_up`, or the + full build where it has none, since a start-up ramp alone builds the row + dims: [scenario, snapshot, process] + cases: + given: { when: Process_ramp_limit_up, expression: Process_ramp_limit_up } + otherwise: 1 ``` ```math -\mathit{transmission\_volume\_expansion}_{\xi,i} = \mathit{Line\_transmission\_volume\_expansion}_{\xi,i} + \mathit{Link\_transmission\_volume\_expansion}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{ru}}^{z}_{\xi,t,j} = \begin{cases} \mathrm{ru}^{z}_{\xi,t,j} & \text{if } \mathrm{ru}^{z}_{\xi,t,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `Line_transmission_expansion_cost` +### `Process_ramp_down_rate` ```yaml -Line_transmission_expansion_cost: - expression: sum(Line_s_nom_ext * Line_expansion_cost_weight, over=line) +Process_ramp_down_rate: + description: >- + the ramp limit a process's down row reads — PyPSA's `ramp_limit_down`, or + the full build where it has none, since a shut-down ramp alone builds the row + dims: [scenario, snapshot, process] + cases: + given: { when: Process_ramp_limit_down, expression: Process_ramp_limit_down } + otherwise: 1 ``` ```math -\mathit{Line\_transmission\_expansion\_cost}_{\xi,i} = \sum_{k \in \mathcal{K}} S_{k} \cdot \mathrm{cc}_{\xi,i,k} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{rd}}^{z}_{\xi,t,j} = \begin{cases} \mathrm{rd}^{z}_{\xi,t,j} & \text{if } \mathrm{rd}^{z}_{\xi,t,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `Link_transmission_expansion_cost` +### `Process_start_up_rate` ```yaml -Link_transmission_expansion_cost: - expression: sum(Link_p_nom_ext * Link_expansion_cost_weight, over=link) +Process_start_up_rate: + description: >- + the start-up ramp a process's up row reads — PyPSA's `ramp_limit_start_up`, + or the full build where it has none + dims: [scenario, process] + cases: + given: { when: Process_ramp_limit_start_up, expression: Process_ramp_limit_start_up } + otherwise: 1 ``` ```math -\mathit{Link\_transmission\_expansion\_cost}_{\xi,i} = \sum_{l \in \mathcal{L}} F_{l} \cdot \mathrm{cc}^{f}_{\xi,i,l} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{ru}}^{z,\mathrm{up}}_{\xi,j} = \begin{cases} \mathrm{ru}^{z,\mathrm{up}}_{\xi,j} & \text{if } \mathrm{ru}^{z,\mathrm{up}}_{\xi,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} ``` -### `transmission_expansion_cost` +### `Process_shut_down_rate` ```yaml -transmission_expansion_cost: - dims: [scenario, global_constraint] - expression: Line_transmission_expansion_cost + Link_transmission_expansion_cost +Process_shut_down_rate: description: >- - what a `transmission_expansion_cost_limit` row totals — capital cost - times the chosen build of the row's branches + the shut-down ramp a process's down row reads — PyPSA's + `ramp_limit_shut_down`, or the full build where it has none + dims: [scenario, process] + cases: + given: { when: Process_ramp_limit_shut_down, expression: Process_ramp_limit_shut_down } + otherwise: 1 ``` ```math -\mathit{transmission\_expansion\_cost}_{\xi,i} = \mathit{Line\_transmission\_expansion\_cost}_{\xi,i} + \mathit{Link\_transmission\_expansion\_cost}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} +\widetilde{\mathrm{rd}}^{z,\mathrm{dn}}_{\xi,j} = \begin{cases} \mathrm{rd}^{z,\mathrm{dn}}_{\xi,j} & \text{if } \mathrm{rd}^{z,\mathrm{dn}}_{\xi,j} \text{ is defined} \\ 1 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} ``` -### `Generator_tech_capacity_expansion` +### `Process_p_nom_committed` ```yaml -Generator_tech_capacity_expansion: - expression: sum(Generator_p_nom_ext * Generator_tech_capacity_weight, over=generator) +Process_p_nom_committed: + description: >- + the build a committed process's ramp rows are taken against — one module + where the build is extendable and modular, the given build otherwise + dims: [scenario, process] + cases: + modular_build: { when: Process_p_nom_extendable AND Process_p_nom_mod > 0, expression: Process_p_nom_mod } + otherwise: Process_p_nom ``` ```math -\mathit{Generator\_tech\_capacity\_expansion}_{i} = \sum_{g \in \mathcal{G}} P_{g} \cdot \mathrm{m}_{i,g} \qquad \forall\, i \in \mathcal{I} +\widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} = \begin{cases} \mathrm{z}^{\mathrm{mod}}_{j} & \text{if } \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \\ \mathrm{z}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ j \in \mathcal{J} ``` -### `Line_tech_capacity_expansion` +### `Process_ramp_up_allowance` ```yaml -Line_tech_capacity_expansion: - expression: sum(Line_s_nom_ext * Line_tech_capacity_weight, over=line) +Process_ramp_up_allowance: + description: >- + how far a process may raise internal power between two snapshots — its ramp + limit of the build while it stays on, plus its start-up ramp in the + snapshot it turns on + dims: [scenario, snapshot, process] + cases: + committed: + when: Process_committable + expression: >- + Process_ramp_up_rate * Process_p_nom_committed * Process_previous_status + + Process_start_up_rate * Process_p_nom_committed + * (Process_status - Process_previous_status) + otherwise: Process_ramp_up_rate * Process_p_nom_effective ``` ```math -\mathit{Line\_tech\_capacity\_expansion}_{i} = \sum_{k \in \mathcal{K}} S_{k} \cdot \mathrm{m}^{l}_{i,k} \qquad \forall\, i \in \mathcal{I} +\Delta^{z,+}_{\xi,t,j} = \begin{cases} \widetilde{\mathrm{ru}}^{z}_{\xi,t,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot \overleftarrow{u}^{z}_{\xi,t,j} + \widetilde{\mathrm{ru}}^{z,\mathrm{up}}_{\xi,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot \left( u^{z}_{\xi,t,j} - \overleftarrow{u}^{z}_{\xi,t,j} \right) & \text{if } \mathrm{com}^{z}_{j} \\ \widetilde{\mathrm{ru}}^{z}_{\xi,t,j} \cdot \widetilde{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `Link_tech_capacity_expansion` +### `Process_ramp_down_allowance` ```yaml -Link_tech_capacity_expansion: - expression: sum(Link_p_nom_ext * Link_tech_capacity_weight, over=link) +Process_ramp_down_allowance: + description: >- + how far a process may lower internal power between two snapshots — its ramp + limit of the build while it stays on, plus its shut-down ramp in the + snapshot it turns off + dims: [scenario, snapshot, process] + cases: + committed: + when: Process_committable + expression: >- + Process_ramp_down_rate * Process_p_nom_committed * Process_status + + Process_shut_down_rate * Process_p_nom_committed + * (Process_previous_status - Process_status) + otherwise: Process_ramp_down_rate * Process_p_nom_effective ``` ```math -\mathit{Link\_tech\_capacity\_expansion}_{i} = \sum_{l \in \mathcal{L}} F_{l} \cdot \mathrm{m}^{f}_{i,l} \qquad \forall\, i \in \mathcal{I} +\Delta^{z,-}_{\xi,t,j} = \begin{cases} \widetilde{\mathrm{rd}}^{z}_{\xi,t,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot u^{z}_{\xi,t,j} + \widetilde{\mathrm{rd}}^{z,\mathrm{dn}}_{\xi,j} \cdot \widehat{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} \cdot \left( \overleftarrow{u}^{z}_{\xi,t,j} - u^{z}_{\xi,t,j} \right) & \text{if } \mathrm{com}^{z}_{j} \\ \widetilde{\mathrm{rd}}^{z}_{\xi,t,j} \cdot \widetilde{\mathrm{z}}^{\mathrm{nom}}_{\xi,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -### `Process_tech_capacity_expansion` +### `StorageUnit_charge_carried_in` ```yaml -Process_tech_capacity_expansion: - expression: sum(Process_p_nom_ext * Process_tech_capacity_weight, over=process) +StorageUnit_charge_carried_in: + description: >- + the charge a unit opens a snapshot with — at the first snapshot it + stands in, its last such snapshot's less standing loss where it is + cyclic and the given initial charge, which no standing loss has touched + yet, where it is not; the previous snapshot's less standing loss + otherwise. A unit built in a later period opens in that period, and a + cyclic one that retires closes on its own last snapshot. Per period, the + same holds with each investment period as the horizon + dims: [scenario, snapshot, storage_unit] + cases: + cyclic: + when: >- + StorageUnit_cyclic_state_of_charge AND NOT StorageUnit_cyclic_state_of_charge_per_period + AND NOT StorageUnit_state_of_charge_initial_per_period + AND (position(snapshot) == 0 OR StorageUnit_opens_late) + expression: >- + StorageUnit_retention + * shift(shift(StorageUnit_state_of_charge, along=snapshot, offset=1, edge='wrap'), along=snapshot, offset=StorageUnit_inactive_snapshots, edge='wrap') + opening: + when: >- + NOT StorageUnit_cyclic_state_of_charge AND NOT StorageUnit_cyclic_state_of_charge_per_period + AND NOT StorageUnit_state_of_charge_initial_per_period + AND (position(snapshot) == 0 OR StorageUnit_opens_late) + expression: StorageUnit_state_of_charge_initial + period_cyclic: + when: StorageUnit_cyclic_state_of_charge_per_period + expression: >- + StorageUnit_retention + * shift(StorageUnit_state_of_charge, along=snapshot, offset=1, edge='wrap', within=snapshot_period[period]) + period_opening: + when: >- + StorageUnit_state_of_charge_initial_per_period AND NOT StorageUnit_cyclic_state_of_charge_per_period + AND position(snapshot, within=snapshot_period[period]) == 0 + expression: StorageUnit_state_of_charge_initial + otherwise: StorageUnit_retention * shift(StorageUnit_state_of_charge, along=snapshot, offset=1) ``` ```math -\mathit{Process\_tech\_capacity\_expansion}_{i} = \sum_{j \in \mathcal{J}} Z_{j} \cdot \mathrm{m}^{z}_{i,j} \qquad \forall\, i \in \mathcal{I} +\overleftarrow{\mathit{soc}}_{\xi,t,s} = \begin{cases} \rho_{\xi,t,s} \cdot \mathit{soc}_{\xi,\left( t \ominus \mathrm{idle} \right) \ominus 1,s} & \text{if } \mathrm{cyc}_{\xi,s} \wedge \neg \mathrm{cyc}^{y}_{\xi,s} \wedge \neg \mathrm{reset}_{\xi,s} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}_{t,s} \right) \\ \mathrm{soc}^{0}_{\xi,s} & \text{if } \neg \mathrm{cyc}_{\xi,s} \wedge \neg \mathrm{cyc}^{y}_{\xi,s} \wedge \neg \mathrm{reset}_{\xi,s} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}_{t,s} \right) \\ \rho_{\xi,t,s} \cdot \mathit{soc}_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} 1,s} & \text{if } \mathrm{cyc}^{y}_{\xi,s} \\ \mathrm{soc}^{0}_{\xi,s} & \text{if } \mathrm{reset}_{\xi,s} \wedge \neg \mathrm{cyc}^{y}_{\xi,s} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = 0 \\ \rho_{\xi,t,s} \cdot \mathit{soc}_{\xi,t - 1,s} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} ``` -### `StorageUnit_tech_capacity_expansion` +### `Store_energy_carried_in` ```yaml -StorageUnit_tech_capacity_expansion: - expression: sum(StorageUnit_p_nom_ext * StorageUnit_tech_capacity_weight, over=storage_unit) +Store_energy_carried_in: + description: >- + the energy a store opens a snapshot with — at the first snapshot it + stands in, its last such snapshot's less standing loss where it is + cyclic and the given initial energy, which no standing loss has touched + yet, where it is not; the previous snapshot's less standing loss + otherwise. A store built in a later period opens in that period, and a + cyclic one that retires closes on its own last snapshot. Per period, the + same holds with each investment period as the horizon + dims: [scenario, snapshot, store] + cases: + cyclic: + when: >- + Store_e_cyclic AND NOT Store_e_cyclic_per_period AND NOT Store_e_initial_per_period + AND (position(snapshot) == 0 OR Store_opens_late) + expression: >- + Store_retention + * shift(shift(Store_e, along=snapshot, offset=1, edge='wrap'), along=snapshot, offset=Store_inactive_snapshots, edge='wrap') + opening: + when: >- + NOT Store_e_cyclic AND NOT Store_e_cyclic_per_period AND NOT Store_e_initial_per_period + AND (position(snapshot) == 0 OR Store_opens_late) + expression: Store_e_initial + period_cyclic: + when: Store_e_cyclic_per_period + expression: Store_retention * shift(Store_e, along=snapshot, offset=1, edge='wrap', within=snapshot_period[period]) + period_opening: + when: Store_e_initial_per_period AND NOT Store_e_cyclic_per_period AND position(snapshot, within=snapshot_period[period]) == 0 + expression: Store_e_initial + otherwise: Store_retention * shift(Store_e, along=snapshot, offset=1) ``` ```math -\mathit{StorageUnit\_tech\_capacity\_expansion}_{i} = \sum_{s \in \mathcal{S}} H_{s} \cdot \mathrm{m}^{h}_{i,s} \qquad \forall\, i \in \mathcal{I} +\overleftarrow{e}_{\xi,t,v} = \begin{cases} \rho^{e}_{\xi,t,v} \cdot e_{\xi,\left( t \ominus \mathrm{idle}^{e} \right) \ominus 1,v} & \text{if } \mathrm{cyc}^{e}_{\xi,v} \wedge \neg \mathrm{cyc}^{e,y}_{\xi,v} \wedge \neg \mathrm{reset}^{e}_{\xi,v} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}^{e}_{t,v} \right) \\ \mathrm{e}^{0}_{\xi,v} & \text{if } \neg \mathrm{cyc}^{e}_{\xi,v} \wedge \neg \mathrm{cyc}^{e,y}_{\xi,v} \wedge \neg \mathrm{reset}^{e}_{\xi,v} \wedge \left( \mathrm{pos}(t) = 0 \vee \mathrm{open}^{e}_{t,v} \right) \\ \rho^{e}_{\xi,t,v} \cdot e_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} 1,v} & \text{if } \mathrm{cyc}^{e,y}_{\xi,v} \\ \mathrm{e}^{0}_{\xi,v} & \text{if } \mathrm{reset}^{e}_{\xi,v} \wedge \neg \mathrm{cyc}^{e,y}_{\xi,v} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = 0 \\ \rho^{e}_{\xi,t,v} \cdot e_{\xi,t - 1,v} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} ``` -### `Store_tech_capacity_expansion` +### `Link_output_arrival` ```yaml -Store_tech_capacity_expansion: - expression: sum(Store_e_nom_ext * Store_tech_capacity_weight, over=store) +Link_output_arrival: + description: >- + what a link delivers to an output port at a snapshot — its flow delayed + by the port's `delay` within its investment period, times the port's + efficiency at the snapshot the flow arrives; where the port is + `cyclic_delay` the delayed flow wraps from the period's end, and where it + is not the flow still in transit at the period's first snapshots is + lost. A port that does not delay (`delay` + zero) delivers its flow unshifted, cyclic or not + dims: [scenario, snapshot, link_output] + cases: + wrapping: + when: Link_output_cyclic_delay + expression: shift(at(Link_p, by=Link_output_link[link]), along=snapshot, offset=Link_output_delay, edge='wrap', within=snapshot_period[period]) * Link_efficiency + otherwise: shift(at(Link_p, by=Link_output_link[link]), along=snapshot, offset=Link_output_delay, edge=0, within=snapshot_period[period]) * Link_efficiency ``` ```math -\mathit{Store\_tech\_capacity\_expansion}_{i} = \sum_{v \in \mathcal{V}} E_{v} \cdot \mathrm{m}^{e}_{i,v} \qquad \forall\, i \in \mathcal{I} +\overrightarrow{f}_{\xi,t,o} = \begin{cases} f_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{f},\mathrm{Link\_output\_link}(o)} \cdot \eta_{\xi,t,o} & \text{if } \mathrm{cyc}^{f}_{o} \\ f_{\xi,t \boxminus_{0}^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{f},\mathrm{Link\_output\_link}(o)} \cdot \eta_{\xi,t,o} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ o \in \mathcal{O} ``` -### `tech_capacity_expansion` +### `Process_output_arrival` ```yaml -tech_capacity_expansion: - dims: [global_constraint] - expression: >- - Generator_tech_capacity_expansion - + Line_tech_capacity_expansion - + Link_tech_capacity_expansion - + Process_tech_capacity_expansion - + StorageUnit_tech_capacity_expansion - + Store_tech_capacity_expansion +Process_output_arrival: description: >- - what a `tech_capacity_expansion_limit` row totals — the chosen build of - the row's carrier-and-bus set + what a process transfers at a port at a snapshot — its internal power + delayed by the port's `delay` within its investment period, times the + port's rate at the snapshot the transfer arrives; where the port is + `cyclic_delay` the delayed transfer wraps from the period's end, and + where it is not the energy still in transit at the period's first + snapshots is lost. A port that does not + delay (`delay` zero) transfers at once, cyclic or not + dims: [scenario, snapshot, process_output] + cases: + wrapping: + when: Process_output_cyclic_delay + expression: shift(at(Process_p, by=Process_output_process[process]), along=snapshot, offset=Process_output_delay, edge='wrap', within=snapshot_period[period]) * Process_rate + otherwise: shift(at(Process_p, by=Process_output_process[process]), along=snapshot, offset=Process_output_delay, edge=0, within=snapshot_period[period]) * Process_rate ``` ```math -\mathit{tech\_capacity\_expansion}_{i} = \mathit{Generator\_tech\_capacity\_expansion}_{i} + \mathit{Line\_tech\_capacity\_expansion}_{i} + \mathit{Link\_tech\_capacity\_expansion}_{i} + \mathit{Process\_tech\_capacity\_expansion}_{i} + \mathit{StorageUnit\_tech\_capacity\_expansion}_{i} + \mathit{Store\_tech\_capacity\_expansion}_{i} \qquad \forall\, i \in \mathcal{I} +\overrightarrow{z}_{\xi,t,r} = \begin{cases} z_{\xi,t \ominus^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{z},\mathrm{Process\_output\_process}(r)} \cdot \alpha_{\xi,t,r} & \text{if } \mathrm{cyc}^{z}_{r} \\ z_{\xi,t \boxminus_{0}^{\mathrm{snapshot\_period}(t)} \mathrm{d}^{z},\mathrm{Process\_output\_process}(r)} \cdot \alpha_{\xi,t,r} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ r \in \mathcal{R} ``` -### `Generator_opex` +### `GlobalConstraint_energy_weight` ```yaml -Generator_opex: - expression: >- - sum(sum(((Generator_p * Generator_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=generator), over=snapshot) - + sum(sum((((Generator_p * Generator_p) * Generator_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=generator), over=snapshot) +GlobalConstraint_energy_weight: + description: >- + what one unit of power at a snapshot counts for in a row — the + generator weighting times the years of the snapshot's period, where the + row counts the snapshot, and nothing where it does not + dims: [scenario, global_constraint, snapshot] + cases: + counted: + when: GlobalConstraint_counts_snapshot + expression: snapshot_weightings_generators * at(period_weight_years, by=snapshot_period[period]) + otherwise: 0 ``` ```math -\mathit{Generator\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} p_{\xi,t,g} \cdot \mathrm{c}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} p_{\xi,t,g} \cdot p_{\xi,t,g} \cdot \mathrm{c}^{(2)}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi +\mathit{w}^{\mathrm{gc}}_{\xi,i,t} = \begin{cases} \mathrm{w}^{\mathrm{gen}}_{t} \cdot \mathrm{w}^{\mathrm{yr}}_{\mathrm{snapshot\_period}(t)} & \text{if } \mathrm{in}_{\xi,i,t} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T} ``` -### `Generator_commitment_opex` +### `StorageUnit_last_counted_active` ```yaml -Generator_commitment_opex: - expression: >- - sum(sum(((Generator_status * Generator_stand_by_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=generator), over=snapshot) - + sum(sum(Generator_start_up * Generator_start_up_cost, over=generator), over=snapshot) - + sum(sum(Generator_shut_down * Generator_shut_down_cost, over=generator), over=snapshot) +StorageUnit_last_counted_active: + description: >- + one at the last snapshot a row counts where a unit stands, and zero + elsewhere — a unit that retires before the last counted snapshot closes + on its last active level, as PyPSA forward-fills the level over the + counted snapshots (`global_constraints.py:455-458`) + dims: [scenario, global_constraint, snapshot, storage_unit] + cases: + last: + when: >- + GlobalConstraint_counts_snapshot AND StorageUnit_active + AND NOT shift(GlobalConstraint_counts_snapshot AND StorageUnit_active, along=snapshot, offset=-1) + expression: 1 + otherwise: 0 ``` ```math -\mathit{Generator\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} u_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{on}}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{up}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{up}}_{\xi,t,g} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{dn}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{dn}}_{\xi,t,g} \qquad \forall\, \xi \in \Xi +\mathit{last}^{h}_{\xi,i,t,s} = \begin{cases} 1 & \text{if } \mathrm{in}_{\xi,i,t} \wedge \mathrm{on}^{h}_{t,s} \wedge \neg \left( \mathrm{in}_{\xi,i,t + 1} \wedge \mathrm{on}^{h}_{t + 1,s} \right) \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ s \in \mathcal{S} ``` -### `Link_opex` +### `StorageUnit_closing_weight` ```yaml -Link_opex: - expression: >- - sum(sum(((Link_p * Link_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=link), over=snapshot) - + sum(sum((((Link_p * Link_p) * Link_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=link), over=snapshot) +StorageUnit_closing_weight: + description: >- + what the charge a unit holds at a snapshot counts for in a row as its + closing level — the years of the period at the last snapshot of each + counted period where the unit reopens per period, one at the last + counted snapshot it stands in where it does not, and nothing elsewhere + dims: [scenario, global_constraint, snapshot, storage_unit] + cases: + per_period: + when: StorageUnit_state_of_charge_initial_per_period AND GlobalConstraint_counts_snapshot AND position(snapshot, within=snapshot_period[period]) == -1 + expression: at(period_weight_years, by=snapshot_period[period]) + carried_over: + when: NOT StorageUnit_state_of_charge_initial_per_period + expression: StorageUnit_last_counted_active + otherwise: 0 ``` ```math -\mathit{Link\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} f_{\xi,t,l} \cdot \mathrm{c}^{f}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} f_{\xi,t,l} \cdot f_{\xi,t,l} \cdot \mathrm{c}^{f,(2)}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi +\mathit{w}^{h}_{\xi,i,t,s} = \begin{cases} \mathrm{w}^{\mathrm{yr}}_{\mathrm{snapshot\_period}(t)} & \text{if } \mathrm{reset}_{\xi,s} \wedge \mathrm{in}_{\xi,i,t} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = \lvert \mathcal{T}_{\mathrm{snapshot\_period}(t)} \rvert - 1 \\ \mathit{last}^{h}_{\xi,i,t,s} & \text{if } \neg \mathrm{reset}_{\xi,s} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ s \in \mathcal{S} ``` -### `Link_commitment_opex` +### `Store_last_counted_active` ```yaml -Link_commitment_opex: - expression: >- - sum(sum(((Link_status * Link_stand_by_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=link), over=snapshot) - + sum(sum(Link_start_up * Link_start_up_cost, over=link), over=snapshot) - + sum(sum(Link_shut_down * Link_shut_down_cost, over=link), over=snapshot) +Store_last_counted_active: + description: >- + one at the last snapshot a row counts where a store stands, and zero + elsewhere — a store that retires before the last counted snapshot closes + on its last active level, as PyPSA forward-fills the level over the + counted snapshots (`global_constraints.py:507-510`) + dims: [scenario, global_constraint, snapshot, store] + cases: + last: + when: >- + GlobalConstraint_counts_snapshot AND Store_active + AND NOT shift(GlobalConstraint_counts_snapshot AND Store_active, along=snapshot, offset=-1) + expression: 1 + otherwise: 0 ``` ```math -\mathit{Link\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} u^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{on}}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{up}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{up}}_{\xi,t,l} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{dn}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{dn}}_{\xi,t,l} \qquad \forall\, \xi \in \Xi +\mathit{last}^{e}_{\xi,i,t,v} = \begin{cases} 1 & \text{if } \mathrm{in}_{\xi,i,t} \wedge \mathrm{on}^{e}_{t,v} \wedge \neg \left( \mathrm{in}_{\xi,i,t + 1} \wedge \mathrm{on}^{e}_{t + 1,v} \right) \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ v \in \mathcal{V} ``` -### `Process_opex` +### `Store_closing_weight` ```yaml -Process_opex: - expression: >- - sum(sum(((Process_p * Process_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=process), over=snapshot) - + sum(sum((((Process_p * Process_p) * Process_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=process), over=snapshot) +Store_closing_weight: + description: >- + what the energy a store holds at a snapshot counts for in a row as its + closing level — the years of the period at the last snapshot of each + counted period where the store reopens per period, one at the last + counted snapshot it stands in where it does not, and nothing elsewhere + dims: [scenario, global_constraint, snapshot, store] + cases: + per_period: + when: Store_e_initial_per_period AND GlobalConstraint_counts_snapshot AND position(snapshot, within=snapshot_period[period]) == -1 + expression: at(period_weight_years, by=snapshot_period[period]) + carried_over: + when: NOT Store_e_initial_per_period + expression: Store_last_counted_active + otherwise: 0 ``` ```math -\mathit{Process\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} z_{\xi,t,j} \cdot \mathrm{c}^{z}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} z_{\xi,t,j} \cdot z_{\xi,t,j} \cdot \mathrm{c}^{z,(2)}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi +\mathit{w}^{e}_{\xi,i,t,v} = \begin{cases} \mathrm{w}^{\mathrm{yr}}_{\mathrm{snapshot\_period}(t)} & \text{if } \mathrm{reset}^{e}_{\xi,v} \wedge \mathrm{in}_{\xi,i,t} \wedge \mathrm{pos}_{\mathrm{snapshot\_period}(t)}(t) = \lvert \mathcal{T}_{\mathrm{snapshot\_period}(t)} \rvert - 1 \\ \mathit{last}^{e}_{\xi,i,t,v} & \text{if } \neg \mathrm{reset}^{e}_{\xi,v} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I},\ t \in \mathcal{T},\ v \in \mathcal{V} ``` -### `Process_commitment_opex` +### `Generator_primary_energy` ```yaml -Process_commitment_opex: +Generator_primary_energy: expression: >- - sum(sum(((Process_status * Process_stand_by_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=process), over=snapshot) - + sum(sum(Process_start_up * Process_start_up_cost, over=process), over=snapshot) - + sum(sum(Process_shut_down * Process_shut_down_cost, over=process), over=snapshot) + sum(sum((Generator_p * GlobalConstraint_energy_weight) * Generator_primary_energy_weight, over=snapshot), over=generator) ``` ```math -\mathit{Process\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} u^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{on}}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{up}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{up}}_{\xi,t,j} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{dn}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{dn}}_{\xi,t,j} \qquad \forall\, \xi \in \Xi +\mathit{Generator\_primary\_energy}_{\xi,i} = \sum_{g \in \mathcal{G}} \sum_{t \in \mathcal{T}} p_{\xi,t,g} \cdot \mathit{w}^{\mathrm{gc}}_{\xi,i,t} \cdot \mathrm{a}_{\xi,i,t,g} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `StorageUnit_opex` +### `StorageUnit_primary_energy` ```yaml -StorageUnit_opex: +StorageUnit_primary_energy: expression: >- - sum(sum(((StorageUnit_p_dispatch * StorageUnit_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) - + sum(sum((((StorageUnit_p_dispatch * StorageUnit_p_dispatch) * StorageUnit_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) - + sum(sum(((StorageUnit_state_of_charge * StorageUnit_marginal_cost_storage) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) - + sum(sum(((StorageUnit_spill * StorageUnit_spill_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) + -sum(sum((StorageUnit_state_of_charge * StorageUnit_closing_weight) * StorageUnit_primary_energy_weight, over=snapshot), over=storage_unit) ``` ```math -\mathit{StorageUnit\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} h^{+}_{\xi,t,s} \cdot \mathrm{c}^{h}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} h^{+}_{\xi,t,s} \cdot h^{+}_{\xi,t,s} \cdot \mathrm{c}^{h,(2)}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} \mathit{soc}_{\xi,t,s} \cdot \mathrm{c}^{\mathrm{soc}}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} \mathit{spill}_{\xi,t,s} \cdot \mathrm{c}^{\mathrm{spill}}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi +\mathit{StorageUnit\_primary\_energy}_{\xi,i} = -\left( \sum_{s \in \mathcal{S}} \sum_{t \in \mathcal{T}} \mathit{soc}_{\xi,t,s} \cdot \mathit{w}^{h}_{\xi,i,t,s} \cdot \mathrm{a}^{h}_{\xi,i,s} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Store_opex` +### `Store_primary_energy` ```yaml -Store_opex: +Store_primary_energy: expression: >- - sum(sum(((Store_p * Store_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=store), over=snapshot) - + sum(sum((((Store_p * Store_p) * Store_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=store), over=snapshot) - + sum(sum(((Store_e * Store_marginal_cost_storage) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=store), over=snapshot) + -sum(sum((Store_e * Store_closing_weight) * Store_primary_energy_weight, over=snapshot), over=store) ``` ```math -\mathit{Store\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{v \in \mathcal{V}} q_{\xi,t,v} \cdot \mathrm{c}^{q}_{\xi,t,v} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{v \in \mathcal{V}} q_{\xi,t,v} \cdot q_{\xi,t,v} \cdot \mathrm{c}^{q,(2)}_{\xi,t,v} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{v \in \mathcal{V}} e_{\xi,t,v} \cdot \mathrm{c}^{e}_{\xi,t,v} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi +\mathit{Store\_primary\_energy}_{\xi,i} = -\left( \sum_{v \in \mathcal{V}} \sum_{t \in \mathcal{T}} e_{\xi,t,v} \cdot \mathit{w}^{e}_{\xi,i,t,v} \cdot \mathrm{a}^{e}_{\xi,i,v} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `scenario_opex` +### `primary_energy` ```yaml -scenario_opex: - dims: [scenario] - expression: >- - Generator_opex - + Generator_commitment_opex - + Link_opex - + Link_commitment_opex - + Process_opex - + Process_commitment_opex - + StorageUnit_opex - + Store_opex +primary_energy: + dims: [scenario, global_constraint] + expression: Generator_primary_energy + StorageUnit_primary_energy + Store_primary_energy description: >- - what a future costs to run — every operating term, weighted by the - snapshot's hours and its period, before the scenario's own weight; a - start and a stop cost what they cost, unweighted, as PyPSA adds them - (`optimize.py:415-432`) -``` - -```math -\mathit{scenario\_opex}_{\xi} = \mathit{Generator\_opex}_{\xi} + \mathit{Generator\_commitment\_opex}_{\xi} + \mathit{Link\_opex}_{\xi} + \mathit{Link\_commitment\_opex}_{\xi} + \mathit{Process\_opex}_{\xi} + \mathit{Process\_commitment\_opex}_{\xi} + \mathit{StorageUnit\_opex}_{\xi} + \mathit{Store\_opex}_{\xi} \qquad \forall\, \xi \in \Xi -``` - -### `Generator_capex` - -```yaml -Generator_capex: - expression: sum(scenario_weight * Generator_p_nom_ext * Generator_capital_cost * Generator_capital_weight) + what a `primary_energy` row totals — weighted generator energy over the + snapshots it counts, less the charge left in weighted storage at the + close; the initial charge it is compared against is folded into the + row's constant ``` ```math -\mathit{Generator\_capex} = \sum_{\xi \in \Xi,\ g \in \mathcal{G}} \pi_{\xi} \cdot P_{g} \cdot \mathrm{c}^{\mathrm{cap}}_{\xi,g} \cdot \mathrm{W}_{g} +\mathit{primary\_energy}_{\xi,i} = \mathit{Generator\_primary\_energy}_{\xi,i} + \mathit{StorageUnit\_primary\_energy}_{\xi,i} + \mathit{Store\_primary\_energy}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Link_capex` +### `Generator_operational_limit` ```yaml -Link_capex: - expression: sum(scenario_weight * Link_p_nom_ext * Link_capital_cost * Link_capital_weight) +Generator_operational_limit: + expression: >- + sum(sum((Generator_p * GlobalConstraint_energy_weight) * Generator_operational_limit_weight, over=snapshot), over=generator) ``` ```math -\mathit{Link\_capex} = \sum_{\xi \in \Xi,\ l \in \mathcal{L}} \pi_{\xi} \cdot F_{l} \cdot \mathrm{c}^{\mathrm{cap},f}_{\xi,l} \cdot \mathrm{W}^{f}_{l} +\mathit{Generator\_operational\_limit}_{\xi,i} = \sum_{g \in \mathcal{G}} \sum_{t \in \mathcal{T}} p_{\xi,t,g} \cdot \mathit{w}^{\mathrm{gc}}_{\xi,i,t} \cdot \mathrm{b}_{\xi,i,g} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `StorageUnit_capex` +### `StorageUnit_operational_limit` ```yaml -StorageUnit_capex: - expression: sum(scenario_weight * StorageUnit_p_nom_ext * StorageUnit_capital_cost * StorageUnit_capital_weight) +StorageUnit_operational_limit: + expression: >- + -sum(sum((StorageUnit_state_of_charge * StorageUnit_closing_weight) * StorageUnit_operational_limit_weight, over=snapshot), over=storage_unit) ``` ```math -\mathit{StorageUnit\_capex} = \sum_{\xi \in \Xi,\ s \in \mathcal{S}} \pi_{\xi} \cdot H_{s} \cdot \mathrm{c}^{\mathrm{cap},h}_{\xi,s} \cdot \mathrm{W}^{h}_{s} +\mathit{StorageUnit\_operational\_limit}_{\xi,i} = -\left( \sum_{s \in \mathcal{S}} \sum_{t \in \mathcal{T}} \mathit{soc}_{\xi,t,s} \cdot \mathit{w}^{h}_{\xi,i,t,s} \cdot \mathrm{b}^{h}_{\xi,i,s} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Store_capex` +### `Store_operational_limit` -```yaml -Store_capex: - expression: sum(scenario_weight * Store_e_nom_ext * Store_capital_cost * Store_capital_weight) +```yaml +Store_operational_limit: + expression: >- + -sum(sum((Store_e * Store_closing_weight) * Store_operational_limit_weight, over=snapshot), over=store) ``` ```math -\mathit{Store\_capex} = \sum_{\xi \in \Xi,\ v \in \mathcal{V}} \pi_{\xi} \cdot E_{v} \cdot \mathrm{c}^{\mathrm{cap},e}_{\xi,v} \cdot \mathrm{W}^{e}_{v} +\mathit{Store\_operational\_limit}_{\xi,i} = -\left( \sum_{v \in \mathcal{V}} \sum_{t \in \mathcal{T}} e_{\xi,t,v} \cdot \mathit{w}^{e}_{\xi,i,t,v} \cdot \mathrm{b}^{e}_{\xi,i,v} \right) \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Line_capex` +### `operational_limit` ```yaml -Line_capex: - expression: sum(scenario_weight * Line_s_nom_ext * Line_capital_cost * Line_capital_weight) +operational_limit: + dims: [scenario, global_constraint] + expression: >- + Generator_operational_limit + + StorageUnit_operational_limit + + Store_operational_limit + description: >- + what an `operational_limit` row totals — the weighted energy its + generators deliver over the snapshots it counts, plus what its + non-cyclic storage draws down; the initial charge it draws from is + folded into the row's constant ``` ```math -\mathit{Line\_capex} = \sum_{\xi \in \Xi,\ k \in \mathcal{K}} \pi_{\xi} \cdot S_{k} \cdot \mathrm{c}^{\mathrm{cap},s}_{\xi,k} \cdot \mathrm{W}^{s}_{k} +\mathit{operational\_limit}_{\xi,i} = \mathit{Generator\_operational\_limit}_{\xi,i} + \mathit{StorageUnit\_operational\_limit}_{\xi,i} + \mathit{Store\_operational\_limit}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Process_capex` +### `Line_transmission_volume_expansion` ```yaml -Process_capex: - expression: sum(scenario_weight * Process_p_nom_ext * Process_capital_cost * Process_capital_weight) +Line_transmission_volume_expansion: + expression: sum(Line_s_nom_ext * Line_volume_weight, over=line) ``` ```math -\mathit{Process\_capex} = \sum_{\xi \in \Xi,\ j \in \mathcal{J}} \pi_{\xi} \cdot Z_{j} \cdot \mathrm{c}^{\mathrm{cap},z}_{\xi,j} \cdot \mathrm{W}^{z}_{j} +\mathit{Line\_transmission\_volume\_expansion}_{\xi,i} = \sum_{k \in \mathcal{K}} S_{k} \cdot \mathrm{len}_{\xi,i,k} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Transformer_capex` +### `Link_transmission_volume_expansion` ```yaml -Transformer_capex: - expression: sum(scenario_weight * Transformer_s_nom_ext * Transformer_capital_cost * Transformer_capital_weight) +Link_transmission_volume_expansion: + expression: sum(Link_p_nom_ext * Link_volume_weight, over=link) ``` ```math -\mathit{Transformer\_capex} = \sum_{\xi \in \Xi,\ m \in \mathcal{M}} \pi_{\xi} \cdot \Sigma_{m} \cdot \mathrm{c}^{\mathrm{cap},\sigma}_{\xi,m} \cdot \mathrm{W}^{\sigma}_{m} +\mathit{Link\_transmission\_volume\_expansion}_{\xi,i} = \sum_{l \in \mathcal{L}} F_{l} \cdot \mathrm{len}^{f}_{\xi,i,l} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `risk_weighted_opex` +### `transmission_volume_expansion` ```yaml -risk_weighted_opex: - expression: (1 - CVaR_omega) * sum(scenario_weight * scenario_opex, over=scenario) + CVaR_omega * CVaR +transmission_volume_expansion: + dims: [scenario, global_constraint] + expression: Line_transmission_volume_expansion + Link_transmission_volume_expansion + description: >- + what a `transmission_volume_expansion_limit` row totals — length times + the chosen build of the row's branches ``` ```math -\mathit{risk\_weighted\_opex} = \left( 1 - \omega \right) \cdot \left( \sum_{\xi \in \Xi} \pi_{\xi} \cdot \mathit{scenario\_opex}_{\xi} \right) + \omega \cdot CVaR +\mathit{transmission\_volume\_expansion}_{\xi,i} = \mathit{Line\_transmission\_volume\_expansion}_{\xi,i} + \mathit{Link\_transmission\_volume\_expansion}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `total_cost` +### `Line_transmission_expansion_cost` ```yaml -total_cost: - dims: [] - expression: >- - Generator_capex - + Link_capex - + StorageUnit_capex - + Store_capex - + Line_capex - + Process_capex - + Transformer_capex - + risk_weighted_opex - description: >- - what the system costs — capacity once per active period at its - expected cost over the scenarios, operation in expectation over the - scenarios, and a share of it at the tail +Line_transmission_expansion_cost: + expression: sum(Line_s_nom_ext * Line_expansion_cost_weight, over=line) ``` ```math -\mathit{total\_cost} = \mathit{Generator\_capex} + \mathit{Link\_capex} + \mathit{StorageUnit\_capex} + \mathit{Store\_capex} + \mathit{Line\_capex} + \mathit{Process\_capex} + \mathit{Transformer\_capex} + \mathit{risk\_weighted\_opex} +\mathit{Line\_transmission\_expansion\_cost}_{\xi,i} = \sum_{k \in \mathcal{K}} S_{k} \cdot \mathrm{cc}_{\xi,i,k} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Generator_additions` +### `Link_transmission_expansion_cost` ```yaml -Generator_additions: - expression: >- - sum(Generator_p_nom_ext * Generator_first_active, over=generator, by=Generator_carrier[carrier]) +Link_transmission_expansion_cost: + expression: sum(Link_p_nom_ext * Link_expansion_cost_weight, over=link) ``` ```math -\mathit{Generator\_additions}_{y,i} = \sum_{g \in \mathcal{G} \,:\, \mathrm{Generator\_carrier}(g) = i} P_{g} \cdot \mathrm{new}_{y,g} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{Link\_transmission\_expansion\_cost}_{\xi,i} = \sum_{l \in \mathcal{L}} F_{l} \cdot \mathrm{cc}^{f}_{\xi,i,l} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Line_additions` +### `transmission_expansion_cost` ```yaml -Line_additions: - expression: >- - sum(Line_s_nom_ext * Line_first_active, over=line, by=Line_carrier[carrier]) +transmission_expansion_cost: + dims: [scenario, global_constraint] + expression: Line_transmission_expansion_cost + Link_transmission_expansion_cost + description: >- + what a `transmission_expansion_cost_limit` row totals — capital cost + times the chosen build of the row's branches ``` ```math -\mathit{Line\_additions}_{y,i} = \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_carrier}(k) = i} S_{k} \cdot \mathrm{new}^{s}_{y,k} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{transmission\_expansion\_cost}_{\xi,i} = \mathit{Line\_transmission\_expansion\_cost}_{\xi,i} + \mathit{Link\_transmission\_expansion\_cost}_{\xi,i} \qquad \forall\, \xi \in \Xi,\ i \in \mathcal{I} ``` -### `Link_additions` +### `Generator_tech_capacity_expansion` ```yaml -Link_additions: - expression: >- - sum(Link_p_nom_ext * Link_first_active, over=link, by=Link_carrier[carrier]) +Generator_tech_capacity_expansion: + expression: sum(Generator_p_nom_ext * Generator_tech_capacity_weight, over=generator) ``` ```math -\mathit{Link\_additions}_{y,i} = \sum_{l \in \mathcal{L} \,:\, \mathrm{Link\_carrier}(l) = i} F_{l} \cdot \mathrm{new}^{f}_{y,l} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{Generator\_tech\_capacity\_expansion}_{i} = \sum_{g \in \mathcal{G}} P_{g} \cdot \mathrm{m}_{i,g} \qquad \forall\, i \in \mathcal{I} ``` -### `Process_additions` +### `Line_tech_capacity_expansion` ```yaml -Process_additions: - expression: >- - sum(Process_p_nom_ext * Process_first_active, over=process, by=Process_carrier[carrier]) +Line_tech_capacity_expansion: + expression: sum(Line_s_nom_ext * Line_tech_capacity_weight, over=line) ``` ```math -\mathit{Process\_additions}_{y,i} = \sum_{j \in \mathcal{J} \,:\, \mathrm{Process\_carrier}(j) = i} Z_{j} \cdot \mathrm{new}^{z}_{y,j} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{Line\_tech\_capacity\_expansion}_{i} = \sum_{k \in \mathcal{K}} S_{k} \cdot \mathrm{m}^{l}_{i,k} \qquad \forall\, i \in \mathcal{I} ``` -### `StorageUnit_additions` +### `Link_tech_capacity_expansion` ```yaml -StorageUnit_additions: - expression: >- - sum(StorageUnit_p_nom_ext * StorageUnit_first_active, over=storage_unit, by=StorageUnit_carrier[carrier]) +Link_tech_capacity_expansion: + expression: sum(Link_p_nom_ext * Link_tech_capacity_weight, over=link) ``` ```math -\mathit{StorageUnit\_additions}_{y,i} = \sum_{s \in \mathcal{S} \,:\, \mathrm{StorageUnit\_carrier}(s) = i} H_{s} \cdot \mathrm{new}^{h}_{y,s} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{Link\_tech\_capacity\_expansion}_{i} = \sum_{l \in \mathcal{L}} F_{l} \cdot \mathrm{m}^{f}_{i,l} \qquad \forall\, i \in \mathcal{I} ``` -### `Store_additions` +### `Process_tech_capacity_expansion` ```yaml -Store_additions: - expression: >- - sum(Store_e_nom_ext * Store_first_active, over=store, by=Store_carrier[carrier]) +Process_tech_capacity_expansion: + expression: sum(Process_p_nom_ext * Process_tech_capacity_weight, over=process) ``` ```math -\mathit{Store\_additions}_{y,i} = \sum_{v \in \mathcal{V} \,:\, \mathrm{Store\_carrier}(v) = i} E_{v} \cdot \mathrm{new}^{e}_{y,v} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{Process\_tech\_capacity\_expansion}_{i} = \sum_{j \in \mathcal{J}} Z_{j} \cdot \mathrm{m}^{z}_{i,j} \qquad \forall\, i \in \mathcal{I} ``` -### `Carrier_additions` +### `StorageUnit_tech_capacity_expansion` ```yaml -Carrier_additions: - dims: [period, carrier] - expression: >- - Generator_additions - + Line_additions - + Link_additions - + Process_additions - + StorageUnit_additions - + Store_additions - description: >- - what a carrier adds in a period — every extendable component of that - carrier, counting each build in the first period it stands in. Like - PyPSA, it sums only the components that carry a carrier attribute, so a - transformer, which has none, counts in no carrier +StorageUnit_tech_capacity_expansion: + expression: sum(StorageUnit_p_nom_ext * StorageUnit_tech_capacity_weight, over=storage_unit) ``` ```math -\mathit{Carrier\_additions}_{y,i} = \mathit{Generator\_additions}_{y,i} + \mathit{Line\_additions}_{y,i} + \mathit{Link\_additions}_{y,i} + \mathit{Process\_additions}_{y,i} + \mathit{StorageUnit\_additions}_{y,i} + \mathit{Store\_additions}_{y,i} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} +\mathit{StorageUnit\_tech\_capacity\_expansion}_{i} = \sum_{s \in \mathcal{S}} H_{s} \cdot \mathrm{m}^{h}_{i,s} \qquad \forall\, i \in \mathcal{I} ``` -### `Carrier_relative_growth` +### `Store_tech_capacity_expansion` ```yaml -Carrier_relative_growth: - description: >- - the share of the previous period's additions a carrier's growth limit - reads — PyPSA's `max_relative_growth` clipped at zero, so a negative - share adds nothing and never tightens the limit - dims: [carrier] - cases: - positive: { when: Carrier_max_relative_growth > 0, expression: Carrier_max_relative_growth } - otherwise: 0 +Store_tech_capacity_expansion: + expression: sum(Store_e_nom_ext * Store_tech_capacity_weight, over=store) ``` ```math -\mathrm{r}^{+}_{i} = \begin{cases} \mathrm{r}_{i} & \text{if } \mathrm{r}_{i} > 0 \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, i \in \mathcal{I} +\mathit{Store\_tech\_capacity\_expansion}_{i} = \sum_{v \in \mathcal{V}} E_{v} \cdot \mathrm{m}^{e}_{i,v} \qquad \forall\, i \in \mathcal{I} ``` -### `Load_demand` +### `tech_capacity_expansion` ```yaml -Load_demand: +tech_capacity_expansion: + dims: [global_constraint] + expression: >- + Generator_tech_capacity_expansion + + Line_tech_capacity_expansion + + Link_tech_capacity_expansion + + Process_tech_capacity_expansion + + StorageUnit_tech_capacity_expansion + + Store_tech_capacity_expansion description: >- - what a load draws from its bus's balance — its demand times its sign - where it is active, nothing where it is not, since PyPSA drops an - inactive load from the balance (`constraints.py:1513-1514`) - dims: [scenario, snapshot, load] - cases: - active: { when: Load_active, expression: Load_sign * Load_p_set } - otherwise: 0 + what a `tech_capacity_expansion_limit` row totals — the chosen build of + the row's carrier-and-bus set ``` ```math -\check{\mathrm{load}}_{\xi,t,d} = \begin{cases} \mathrm{sgn}^{\mathrm{load}}_{d} \cdot \mathrm{load}_{\xi,t,d} & \text{if } \mathrm{on}^{\mathrm{load}}_{d} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ d \in \mathcal{D} +\mathit{tech\_capacity\_expansion}_{i} = \mathit{Generator\_tech\_capacity\_expansion}_{i} + \mathit{Line\_tech\_capacity\_expansion}_{i} + \mathit{Link\_tech\_capacity\_expansion}_{i} + \mathit{Process\_tech\_capacity\_expansion}_{i} + \mathit{StorageUnit\_tech\_capacity\_expansion}_{i} + \mathit{Store\_tech\_capacity\_expansion}_{i} \qquad \forall\, i \in \mathcal{I} ``` -### `Line_s_monitored` +### `Generator_opex` ```yaml -Line_s_monitored: - description: >- - the flow a line's post-contingency rows read — its flow where it stands, - nothing where it does not, since PyPSA builds those rows for every - branch of the sub-network in every snapshot - dims: [scenario, snapshot, line] - cases: - standing: { when: Line_active, expression: Line_s } - otherwise: 0 +Generator_opex: + expression: >- + sum(sum(((Generator_p * Generator_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=generator), over=snapshot) + + sum(sum((((Generator_p * Generator_p) * Generator_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=generator), over=snapshot) ``` ```math -\check{s}_{\xi,t,k} = \begin{cases} s_{\xi,t,k} & \text{if } \mathrm{on}^{s}_{t,k} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} +\mathit{Generator\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} p_{\xi,t,g} \cdot \mathrm{c}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} p_{\xi,t,g} \cdot p_{\xi,t,g} \cdot \mathrm{c}^{(2)}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi ``` -### `Transformer_s_monitored` +### `Generator_commitment_opex` ```yaml -Transformer_s_monitored: - description: the flow a transformer's post-contingency rows read, as a line's - dims: [scenario, snapshot, transformer] - cases: - standing: { when: Transformer_active, expression: Transformer_s } - otherwise: 0 +Generator_commitment_opex: + expression: >- + sum(sum(((Generator_status * Generator_stand_by_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=generator), over=snapshot) + + sum(sum(Generator_start_up * Generator_start_up_cost, over=generator), over=snapshot) + + sum(sum(Generator_shut_down * Generator_shut_down_cost, over=generator), over=snapshot) ``` ```math -\check{\sigma}_{\xi,t,m} = \begin{cases} \sigma_{\xi,t,m} & \text{if } \mathrm{on}^{\sigma}_{t,m} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} +\mathit{Generator\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} u_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{on}}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{up}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{up}}_{\xi,t,g} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{dn}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{dn}}_{\xi,t,g} \qquad \forall\, \xi \in \Xi ``` -### `Outage_s` +### `Link_opex` ```yaml -Outage_s: - description: >- - the flow an outage takes off its branch — the outaged line's or - transformer's flow before it goes out - dims: [scenario, snapshot, outage] - cases: - line: { when: Outage_line, expression: "at(Line_s_monitored, by=Outage_line[line])" } - otherwise: at(Transformer_s_monitored, by=Outage_transformer[transformer]) +Link_opex: + expression: >- + sum(sum(((Link_p * Link_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=link), over=snapshot) + + sum(sum((((Link_p * Link_p) * Link_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=link), over=snapshot) ``` ```math -\hat{s}_{\xi,t,\kappa} = \begin{cases} \check{s}_{\xi,t,\mathrm{Outage\_line}(\kappa)} & \text{if } \mathrm{Outage\_line}(\kappa) \text{ is defined} \\ \check{\sigma}_{\xi,t,\mathrm{Outage\_transformer}(\kappa)} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ \kappa \in \mathcal{K}^{\mathrm{out}} +\mathit{Link\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} f_{\xi,t,l} \cdot \mathrm{c}^{f}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} f_{\xi,t,l} \cdot f_{\xi,t,l} \cdot \mathrm{c}^{f,(2)}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi ``` -### `Generator_injection` +### `Link_commitment_opex` ```yaml -Generator_injection: - expression: sum(Generator_sign * Generator_p, over=generator, by=Generator_bus[bus]) +Link_commitment_opex: + expression: >- + sum(sum(((Link_status * Link_stand_by_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=link), over=snapshot) + + sum(sum(Link_start_up * Link_start_up_cost, over=link), over=snapshot) + + sum(sum(Link_shut_down * Link_shut_down_cost, over=link), over=snapshot) ``` ```math -\mathit{Generator\_injection}_{\xi,t,n} = \sum_{g \in \mathcal{G} \,:\, \mathrm{Generator\_bus}(g) = n} \mathrm{sgn}_{g} \cdot p_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{Link\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} u^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{on}}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{up}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{up}}_{\xi,t,l} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{dn}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{dn}}_{\xi,t,l} \qquad \forall\, \xi \in \Xi ``` -### `Line_injection` +### `Process_opex` ```yaml -Line_injection: - expression: >- - -sum(Line_s, over=line, by=Line_bus0[bus]) - + sum(Line_s, over=line, by=Line_bus1[bus]) - - (0.5 * sum(Line_loss, over=line, by=Line_bus0[bus])) - - (0.5 * sum(Line_loss, over=line, by=Line_bus1[bus])) +Process_opex: + expression: >- + sum(sum(((Process_p * Process_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=process), over=snapshot) + + sum(sum((((Process_p * Process_p) * Process_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=process), over=snapshot) ``` ```math -\mathit{Line\_injection}_{\xi,t,n} = -\left( \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus0}(k) = n} s_{\xi,t,k} \right) + \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus1}(k) = n} s_{\xi,t,k} - 0.5 \cdot \left( \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus0}(k) = n} \ell_{\xi,t,k} \right) - 0.5 \cdot \left( \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus1}(k) = n} \ell_{\xi,t,k} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{Process\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} z_{\xi,t,j} \cdot \mathrm{c}^{z}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} z_{\xi,t,j} \cdot z_{\xi,t,j} \cdot \mathrm{c}^{z,(2)}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi ``` -### `Link_injection` +### `Process_commitment_opex` ```yaml -Link_injection: +Process_commitment_opex: expression: >- - -sum(Link_p, over=link, by=Link_bus0[bus]) - + sum(Link_output_arrival, over=link_output, by=Link_output_bus[bus]) + sum(sum(((Process_status * Process_stand_by_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=process), over=snapshot) + + sum(sum(Process_start_up * Process_start_up_cost, over=process), over=snapshot) + + sum(sum(Process_shut_down * Process_shut_down_cost, over=process), over=snapshot) ``` ```math -\mathit{Link\_injection}_{\xi,t,n} = -\left( \sum_{l \in \mathcal{L} \,:\, \mathrm{Link\_bus0}(l) = n} f_{\xi,t,l} \right) + \sum_{o \in \mathcal{O} \,:\, \mathrm{Link\_output\_bus}(o) = n} \overrightarrow{f}_{\xi,t,o} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{Process\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} u^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{on}}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{up}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{up}}_{\xi,t,j} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{dn}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{dn}}_{\xi,t,j} \qquad \forall\, \xi \in \Xi ``` -### `Load_injection` +### `StorageUnit_opex` ```yaml -Load_injection: sum(Load_demand, over=load, by=Load_bus[bus]) +StorageUnit_opex: + expression: >- + sum(sum(((StorageUnit_p_dispatch * StorageUnit_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) + + sum(sum((((StorageUnit_p_dispatch * StorageUnit_p_dispatch) * StorageUnit_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) + + sum(sum(((StorageUnit_state_of_charge * StorageUnit_marginal_cost_storage) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) + + sum(sum(((StorageUnit_spill * StorageUnit_spill_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=storage_unit), over=snapshot) ``` ```math -\mathrm{Load\_injection}_{\xi,t,n} = \sum_{d \in \mathcal{D} \,:\, \mathrm{Load\_bus}(d) = n} \check{\mathrm{load}}_{\xi,t,d} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{StorageUnit\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} h^{+}_{\xi,t,s} \cdot \mathrm{c}^{h}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} h^{+}_{\xi,t,s} \cdot h^{+}_{\xi,t,s} \cdot \mathrm{c}^{h,(2)}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} \mathit{soc}_{\xi,t,s} \cdot \mathrm{c}^{\mathrm{soc}}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{s \in \mathcal{S}} \mathit{spill}_{\xi,t,s} \cdot \mathrm{c}^{\mathrm{spill}}_{\xi,t,s} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi ``` -### `Process_injection` +### `Store_opex` ```yaml -Process_injection: +Store_opex: expression: >- - sum(Process_output_arrival, over=process_output, by=Process_output_bus[bus]) + sum(sum(((Store_p * Store_marginal_cost) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=store), over=snapshot) + + sum(sum((((Store_p * Store_p) * Store_marginal_cost_quadratic) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=store), over=snapshot) + + sum(sum(((Store_e * Store_marginal_cost_storage) * snapshot_weightings_objective) * at(period_weight_objective, by=snapshot_period[period]), over=store), over=snapshot) ``` ```math -\mathit{Process\_injection}_{\xi,t,n} = \sum_{r \in \mathcal{R} \,:\, \mathrm{Process\_output\_bus}(r) = n} \overrightarrow{z}_{\xi,t,r} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{Store\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{v \in \mathcal{V}} q_{\xi,t,v} \cdot \mathrm{c}^{q}_{\xi,t,v} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{v \in \mathcal{V}} q_{\xi,t,v} \cdot q_{\xi,t,v} \cdot \mathrm{c}^{q,(2)}_{\xi,t,v} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{v \in \mathcal{V}} e_{\xi,t,v} \cdot \mathrm{c}^{e}_{\xi,t,v} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} \qquad \forall\, \xi \in \Xi ``` -### `StorageUnit_injection` +### `scenario_opex` ```yaml -StorageUnit_injection: +scenario_opex: + dims: [scenario] expression: >- - sum(StorageUnit_sign * (StorageUnit_p_dispatch - StorageUnit_p_store), over=storage_unit, by=StorageUnit_bus[bus]) + Generator_opex + + Generator_commitment_opex + + Link_opex + + Link_commitment_opex + + Process_opex + + Process_commitment_opex + + StorageUnit_opex + + Store_opex + description: >- + what a future costs to run — every operating term, weighted by the + snapshot's hours and its period, before the scenario's own weight; a + start and a stop cost what they cost, unweighted, as PyPSA adds them + (`optimize.py:415-432`) ``` ```math -\mathit{StorageUnit\_injection}_{\xi,t,n} = \sum_{s \in \mathcal{S} \,:\, \mathrm{StorageUnit\_bus}(s) = n} \mathrm{sgn}^{h}_{s} \cdot \left( h^{+}_{\xi,t,s} - h^{-}_{\xi,t,s} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{scenario\_opex}_{\xi} = \mathit{Generator\_opex}_{\xi} + \mathit{Generator\_commitment\_opex}_{\xi} + \mathit{Link\_opex}_{\xi} + \mathit{Link\_commitment\_opex}_{\xi} + \mathit{Process\_opex}_{\xi} + \mathit{Process\_commitment\_opex}_{\xi} + \mathit{StorageUnit\_opex}_{\xi} + \mathit{Store\_opex}_{\xi} \qquad \forall\, \xi \in \Xi ``` -### `Store_injection` +### `Generator_capex` ```yaml -Store_injection: sum(Store_sign * Store_p, over=store, by=Store_bus[bus]) +Generator_capex: + expression: sum(scenario_weight * Generator_p_nom_ext * Generator_capital_cost * Generator_capital_weight) ``` ```math -\mathit{Store\_injection}_{\xi,t,n} = \sum_{v \in \mathcal{V} \,:\, \mathrm{Store\_bus}(v) = n} \mathrm{sgn}^{q}_{v} \cdot q_{\xi,t,v} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{Generator\_capex} = \sum_{\xi \in \Xi,\ g \in \mathcal{G}} \pi_{\xi} \cdot P_{g} \cdot \mathrm{c}^{\mathrm{cap}}_{\xi,g} \cdot \mathrm{W}_{g} ``` -### `Transformer_injection` +### `Link_capex` ```yaml -Transformer_injection: - expression: >- - -sum(Transformer_s, over=transformer, by=Transformer_bus0[bus]) - + sum(Transformer_s, over=transformer, by=Transformer_bus1[bus]) - - (0.5 * sum(Transformer_loss, over=transformer, by=Transformer_bus0[bus])) - - (0.5 * sum(Transformer_loss, over=transformer, by=Transformer_bus1[bus])) +Link_capex: + expression: sum(scenario_weight * Link_p_nom_ext * Link_capital_cost * Link_capital_weight) ``` ```math -\mathit{Transformer\_injection}_{\xi,t,n} = -\left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \sigma_{\xi,t,m} \right) + \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \sigma_{\xi,t,m} - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{Link\_capex} = \sum_{\xi \in \Xi,\ l \in \mathcal{L}} \pi_{\xi} \cdot F_{l} \cdot \mathrm{c}^{\mathrm{cap},f}_{\xi,l} \cdot \mathrm{W}^{f}_{l} ``` -### `Bus_injection` +### `StorageUnit_capex` ```yaml -Bus_injection: - dims: [scenario, snapshot, bus] - expression: >- - Generator_injection - + Line_injection - + Link_injection - + Load_injection - + Process_injection - + StorageUnit_injection - + Store_injection - + Transformer_injection - description: >- - what every component puts into a bus, less what it takes out of it; - PyPSA writes each term into the balance, and a load on its right-hand - side +StorageUnit_capex: + expression: sum(scenario_weight * StorageUnit_p_nom_ext * StorageUnit_capital_cost * StorageUnit_capital_weight) ``` ```math -\mathit{Bus\_injection}_{\xi,t,n} = \mathit{Generator\_injection}_{\xi,t,n} + \mathit{Line\_injection}_{\xi,t,n} + \mathit{Link\_injection}_{\xi,t,n} + \mathrm{Load\_injection}_{\xi,t,n} + \mathit{Process\_injection}_{\xi,t,n} + \mathit{StorageUnit\_injection}_{\xi,t,n} + \mathit{Store\_injection}_{\xi,t,n} + \mathit{Transformer\_injection}_{\xi,t,n} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathit{StorageUnit\_capex} = \sum_{\xi \in \Xi,\ s \in \mathcal{S}} \pi_{\xi} \cdot H_{s} \cdot \mathrm{c}^{\mathrm{cap},h}_{\xi,s} \cdot \mathrm{W}^{h}_{s} ``` -### `Line_angle_sum` +### `Store_capex` ```yaml -Line_angle_sum: sum(Line_s * at(Line_cycle_weight, by=snapshot_period[period]), over=line) +Store_capex: + expression: sum(scenario_weight * Store_e_nom_ext * Store_capital_cost * Store_capital_weight) ``` ```math -\mathit{Line\_angle\_sum}_{\xi,t,c} = \sum_{k \in \mathcal{K}} s_{\xi,t,k} \cdot \mathrm{x}_{\mathrm{snapshot\_period}(t),k,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} +\mathit{Store\_capex} = \sum_{\xi \in \Xi,\ v \in \mathcal{V}} \pi_{\xi} \cdot E_{v} \cdot \mathrm{c}^{\mathrm{cap},e}_{\xi,v} \cdot \mathrm{W}^{e}_{v} ``` -### `Transformer_angle_sum` +### `Line_capex` ```yaml -Transformer_angle_sum: - expression: >- - sum(Transformer_s * at(Transformer_cycle_weight, by=snapshot_period[period]), over=transformer) - + sum(Transformer_phase_shift_weight, over=transformer) - + sum(Transformer_phase_shift * at(Transformer_phase_shift_cycle_weight, by=snapshot_period[period]), over=transformer) +Line_capex: + expression: sum(scenario_weight * Line_s_nom_ext * Line_capital_cost * Line_capital_weight) ``` ```math -\mathit{Transformer\_angle\_sum}_{\xi,t,c} = \sum_{m \in \mathcal{M}} \sigma_{\xi,t,m} \cdot \mathrm{x}^{\sigma}_{\mathrm{snapshot\_period}(t),m,c} + \sum_{m \in \mathcal{M}} \vartheta_{t,m,c} + \sum_{m \in \mathcal{M}} \mathit{Transformer\_phase\_shift}_{\xi,t,m} \cdot \mathrm{Transformer\_phase\_shift\_cycle\_weight}_{\mathrm{snapshot\_period}(t),m,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} +\mathit{Line\_capex} = \sum_{\xi \in \Xi,\ k \in \mathcal{K}} \pi_{\xi} \cdot S_{k} \cdot \mathrm{c}^{\mathrm{cap},s}_{\xi,k} \cdot \mathrm{W}^{s}_{k} ``` -### `Cycle_angle_sum` +### `Process_capex` ```yaml -Cycle_angle_sum: - dims: [scenario, snapshot, cycle] - expression: Line_angle_sum + Transformer_angle_sum - description: >- - the voltage angle differences around a cycle: every branch flow times - its cycle weight, and every transformer phase shift +Process_capex: + expression: sum(scenario_weight * Process_p_nom_ext * Process_capital_cost * Process_capital_weight) ``` ```math -\mathit{Cycle\_angle\_sum}_{\xi,t,c} = \mathit{Line\_angle\_sum}_{\xi,t,c} + \mathit{Transformer\_angle\_sum}_{\xi,t,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} +\mathit{Process\_capex} = \sum_{\xi \in \Xi,\ j \in \mathcal{J}} \pi_{\xi} \cdot Z_{j} \cdot \mathrm{c}^{\mathrm{cap},z}_{\xi,j} \cdot \mathrm{W}^{z}_{j} ``` -#### Variable domains +### `Transformer_capex` -**`Generator_p`** +```yaml +Transformer_capex: + expression: sum(scenario_weight * Transformer_s_nom_ext * Transformer_capital_cost * Transformer_capital_weight) +``` ```math -p_{\xi,t,g} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}_{t,g} +\mathit{Transformer\_capex} = \sum_{\xi \in \Xi,\ m \in \mathcal{M}} \pi_{\xi} \cdot \Sigma_{m} \cdot \mathrm{c}^{\mathrm{cap},\sigma}_{\xi,m} \cdot \mathrm{W}^{\sigma}_{m} ``` -**`Link_p`** +### `risk_weighted_opex` -```math -f_{\xi,t,l} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f}_{t,l} +```yaml +risk_weighted_opex: + expression: (1 - CVaR_omega) * sum(scenario_weight * scenario_opex, over=scenario) + CVaR_omega * CVaR ``` -**`Process_p`** - ```math -z_{\xi,t,j} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z}_{t,j} +\mathit{risk\_weighted\_opex} = \left( 1 - \omega \right) \cdot \left( \sum_{\xi \in \Xi} \pi_{\xi} \cdot \mathit{scenario\_opex}_{\xi} \right) + \omega \cdot CVaR ``` -**`StorageUnit_p_dispatch`** +### `total_cost` -```math -h^{+}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} +```yaml +total_cost: + dims: [] + expression: >- + Generator_capex + + Link_capex + + StorageUnit_capex + + Store_capex + + Line_capex + + Process_capex + + Transformer_capex + + risk_weighted_opex + description: >- + what the system costs — capacity once per active period at its + expected cost over the scenarios, operation in expectation over the + scenarios, and a share of it at the tail ``` -**`StorageUnit_p_store`** - ```math -h^{-}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} +\mathit{total\_cost} = \mathit{Generator\_capex} + \mathit{Link\_capex} + \mathit{StorageUnit\_capex} + \mathit{Store\_capex} + \mathit{Line\_capex} + \mathit{Process\_capex} + \mathit{Transformer\_capex} + \mathit{risk\_weighted\_opex} ``` -**`StorageUnit_state_of_charge`** +### `Generator_additions` -```math -\mathit{soc}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} +```yaml +Generator_additions: + expression: >- + sum(Generator_p_nom_ext * Generator_first_active, over=generator, by=Generator_carrier[carrier]) ``` -**`StorageUnit_spill`** - ```math -0 \le \mathit{spill}_{\xi,t,s} \le \mathrm{inflow}_{\xi,t,s} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{inflow}_{\xi,t,s} > 0 \wedge \mathrm{on}^{h}_{t,s} +\mathit{Generator\_additions}_{y,i} = \sum_{g \in \mathcal{G} \,:\, \mathrm{Generator\_carrier}(g) = i} P_{g} \cdot \mathrm{new}_{y,g} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Store_e`** +### `Line_additions` -```math -e_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} +```yaml +Line_additions: + expression: >- + sum(Line_s_nom_ext * Line_first_active, over=line, by=Line_carrier[carrier]) ``` -**`Store_p`** - ```math -q_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} +\mathit{Line\_additions}_{y,i} = \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_carrier}(k) = i} S_{k} \cdot \mathrm{new}^{s}_{y,k} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Generator_n_mod`** +### `Link_additions` -```math -N_{g} \ge 0, N_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}_{t,g} \} \rvert > 0 +```yaml +Link_additions: + expression: >- + sum(Link_p_nom_ext * Link_first_active, over=link, by=Link_carrier[carrier]) ``` -**`Generator_status`** - ```math -u_{\xi,t,g} \ge 0, u_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} +\mathit{Link\_additions}_{y,i} = \sum_{l \in \mathcal{L} \,:\, \mathrm{Link\_carrier}(l) = i} F_{l} \cdot \mathrm{new}^{f}_{y,l} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Generator_start_up`** +### `Process_additions` -```math -\mathit{up}_{\xi,t,g} \ge 0, \mathit{up}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} +```yaml +Process_additions: + expression: >- + sum(Process_p_nom_ext * Process_first_active, over=process, by=Process_carrier[carrier]) ``` -**`Generator_shut_down`** - ```math -\mathit{dn}_{\xi,t,g} \ge 0, \mathit{dn}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} +\mathit{Process\_additions}_{y,i} = \sum_{j \in \mathcal{J} \,:\, \mathrm{Process\_carrier}(j) = i} Z_{j} \cdot \mathrm{new}^{z}_{y,j} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Generator_maintenance`** +### `StorageUnit_additions` -```math -0 \le \mu_{\xi,t,g} \le 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}_{t,g} +```yaml +StorageUnit_additions: + expression: >- + sum(StorageUnit_p_nom_ext * StorageUnit_first_active, over=storage_unit, by=StorageUnit_carrier[carrier]) ``` -**`Generator_maintenance_start`** - ```math -\mu^{\mathrm{up}}_{\xi,t,g} \in \{0, 1\} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}_{t,g} +\mathit{StorageUnit\_additions}_{y,i} = \sum_{s \in \mathcal{S} \,:\, \mathrm{StorageUnit\_carrier}(s) = i} H_{s} \cdot \mathrm{new}^{h}_{y,s} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Generator_maintenance_capacity`** +### `Store_additions` + +```yaml +Store_additions: + expression: >- + sum(Store_e_nom_ext * Store_first_active, over=store, by=Store_carrier[carrier]) +``` ```math -\mu^{\mathrm{nom}}_{\xi,t,g} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{mnt,ext}}_{t,g} +\mathit{Store\_additions}_{y,i} = \sum_{v \in \mathcal{V} \,:\, \mathrm{Store\_carrier}(v) = i} E_{v} \cdot \mathrm{new}^{e}_{y,v} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Generator_maintenance_status`** +### `Carrier_additions` -```math -\mu^{u}_{\xi,t,g} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}^{\mathrm{com}}_{t,g} \wedge \neg \left( \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \right) +```yaml +Carrier_additions: + dims: [period, carrier] + expression: >- + Generator_additions + + Line_additions + + Link_additions + + Process_additions + + StorageUnit_additions + + Store_additions + description: >- + what a carrier adds in a period — every extendable component of that + carrier, counting each build in the first period it stands in. Like + PyPSA, it sums only the components that carry a carrier attribute, so a + transformer, which has none, counts in no carrier ``` -**`Link_n_mod`** - ```math -N^{f}_{l} \ge 0, N^{f}_{l} \in \mathbb{Z} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{f}_{t,l} \} \rvert > 0 +\mathit{Carrier\_additions}_{y,i} = \mathit{Generator\_additions}_{y,i} + \mathit{Line\_additions}_{y,i} + \mathit{Link\_additions}_{y,i} + \mathit{Process\_additions}_{y,i} + \mathit{StorageUnit\_additions}_{y,i} + \mathit{Store\_additions}_{y,i} \qquad \forall\, y \in \mathcal{Y},\ i \in \mathcal{I} ``` -**`Link_status`** +### `Carrier_relative_growth` -```math -u^{f}_{\xi,t,l} \ge 0, u^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} +```yaml +Carrier_relative_growth: + description: >- + the share of the previous period's additions a carrier's growth limit + reads — PyPSA's `max_relative_growth` clipped at zero, so a negative + share adds nothing and never tightens the limit + dims: [carrier] + cases: + positive: { when: Carrier_max_relative_growth > 0, expression: Carrier_max_relative_growth } + otherwise: 0 ``` -**`Link_start_up`** - ```math -\mathit{up}^{f}_{\xi,t,l} \ge 0, \mathit{up}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} +\mathrm{r}^{+}_{i} = \begin{cases} \mathrm{r}_{i} & \text{if } \mathrm{r}_{i} > 0 \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, i \in \mathcal{I} ``` -**`Link_shut_down`** +### `Load_demand` -```math -\mathit{dn}^{f}_{\xi,t,l} \ge 0, \mathit{dn}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} +```yaml +Load_demand: + description: >- + what a load draws from its bus's balance — its demand times its sign + where it is active, nothing where it is not, since PyPSA drops an + inactive load from the balance (`constraints.py:1513-1514`) + dims: [scenario, snapshot, load] + cases: + active: { when: Load_active, expression: Load_sign * Load_p_set } + otherwise: 0 ``` -**`Link_maintenance`** - ```math -0 \le \mu^{f}_{\xi,t,l} \le 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +\check{\mathrm{load}}_{\xi,t,d} = \begin{cases} \mathrm{sgn}^{\mathrm{load}}_{d} \cdot \mathrm{load}_{\xi,t,d} & \text{if } \mathrm{on}^{\mathrm{load}}_{d} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ d \in \mathcal{D} ``` -**`Link_maintenance_start`** +### `Line_s_monitored` -```math -\mu^{f,\mathrm{up}}_{\xi,t,l} \in \{0, 1\} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} +```yaml +Line_s_monitored: + description: >- + the flow a line's post-contingency rows read — its flow where it stands, + nothing where it does not, since PyPSA builds those rows for every + branch of the sub-network in every snapshot + dims: [scenario, snapshot, line] + cases: + standing: { when: Line_active, expression: Line_s } + otherwise: 0 ``` -**`Link_maintenance_capacity`** - ```math -\mu^{f,\mathrm{nom}}_{\xi,t,l} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{mnt,ext}}_{t,l} +\check{s}_{\xi,t,k} = \begin{cases} s_{\xi,t,k} & \text{if } \mathrm{on}^{s}_{t,k} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} ``` -**`Link_maintenance_status`** +### `Transformer_s_monitored` -```math -\mu^{f,u}_{\xi,t,l} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f,\mathrm{com}}_{t,l} \wedge \neg \left( \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \right) +```yaml +Transformer_s_monitored: + description: the flow a transformer's post-contingency rows read, as a line's + dims: [scenario, snapshot, transformer] + cases: + standing: { when: Transformer_active, expression: Transformer_s } + otherwise: 0 ``` -**`Process_n_mod`** - ```math -N^{z}_{j} \ge 0, N^{z}_{j} \in \mathbb{Z} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{z}_{t,j} \} \rvert > 0 +\check{\sigma}_{\xi,t,m} = \begin{cases} \sigma_{\xi,t,m} & \text{if } \mathrm{on}^{\sigma}_{t,m} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} ``` -**`Process_status`** +### `Outage_s` -```math -u^{z}_{\xi,t,j} \ge 0, u^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} +```yaml +Outage_s: + description: >- + the flow an outage takes off its branch — the outaged line's or + transformer's flow before it goes out + dims: [scenario, snapshot, outage] + cases: + line: { when: Outage_line, expression: "at(Line_s_monitored, by=Outage_line[line])" } + otherwise: at(Transformer_s_monitored, by=Outage_transformer[transformer]) ``` -**`Process_start_up`** - ```math -\mathit{up}^{z}_{\xi,t,j} \ge 0, \mathit{up}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} +\hat{s}_{\xi,t,\kappa} = \begin{cases} \check{s}_{\xi,t,\mathrm{Outage\_line}(\kappa)} & \text{if } \mathrm{Outage\_line}(\kappa) \text{ is defined} \\ \check{\sigma}_{\xi,t,\mathrm{Outage\_transformer}(\kappa)} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ \kappa \in \mathcal{K}^{\mathrm{out}} ``` -**`Process_shut_down`** +### `Generator_injection` -```math -\mathit{dn}^{z}_{\xi,t,j} \ge 0, \mathit{dn}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} +```yaml +Generator_injection: + expression: sum(Generator_sign * Generator_p, over=generator, by=Generator_bus[bus]) ``` -**`Process_maintenance`** - ```math -0 \le \mu^{z}_{\xi,t,j} \le 1 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +\mathit{Generator\_injection}_{\xi,t,n} = \sum_{g \in \mathcal{G} \,:\, \mathrm{Generator\_bus}(g) = n} \mathrm{sgn}_{g} \cdot p_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Process_maintenance_start`** +### `Line_injection` -```math -\mu^{z,\mathrm{up}}_{\xi,t,j} \in \{0, 1\} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} +```yaml +Line_injection: + expression: >- + -sum(Line_s, over=line, by=Line_bus0[bus]) + + sum(Line_s, over=line, by=Line_bus1[bus]) + - (0.5 * sum(Line_loss, over=line, by=Line_bus0[bus])) + - (0.5 * sum(Line_loss, over=line, by=Line_bus1[bus])) ``` -**`Process_maintenance_capacity`** - ```math -\mu^{z,\mathrm{nom}}_{\xi,t,j} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{mnt,ext}}_{t,j} +\mathit{Line\_injection}_{\xi,t,n} = -\left( \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus0}(k) = n} s_{\xi,t,k} \right) + \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus1}(k) = n} s_{\xi,t,k} - 0.5 \cdot \left( \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus0}(k) = n} \ell_{\xi,t,k} \right) - 0.5 \cdot \left( \sum_{k \in \mathcal{K} \,:\, \mathrm{Line\_bus1}(k) = n} \ell_{\xi,t,k} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Process_maintenance_status`** +### `Link_injection` -```math -\mu^{z,u}_{\xi,t,j} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z,\mathrm{com}}_{t,j} \wedge \neg \left( \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \right) +```yaml +Link_injection: + expression: >- + -sum(Link_p, over=link, by=Link_bus0[bus]) + + sum(Link_output_arrival, over=link_output, by=Link_output_bus[bus]) ``` -**`Line_s`** - ```math -s_{\xi,t,k} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s}_{t,k} +\mathit{Link\_injection}_{\xi,t,n} = -\left( \sum_{l \in \mathcal{L} \,:\, \mathrm{Link\_bus0}(l) = n} f_{\xi,t,l} \right) + \sum_{o \in \mathcal{O} \,:\, \mathrm{Link\_output\_bus}(o) = n} \overrightarrow{f}_{\xi,t,o} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Line_loss`** +### `Load_injection` -```math -\ell_{\xi,t,k} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s,\mathrm{lossy}}_{t,k} +```yaml +Load_injection: sum(Load_demand, over=load, by=Load_bus[bus]) ``` -**`Transformer_s`** - ```math -\sigma_{\xi,t,m} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma}_{t,m} +\mathrm{Load\_injection}_{\xi,t,n} = \sum_{d \in \mathcal{D} \,:\, \mathrm{Load\_bus}(d) = n} \check{\mathrm{load}}_{\xi,t,d} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Transformer_loss`** +### `Process_injection` -```math -\ell^{\sigma}_{\xi,t,m} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} +```yaml +Process_injection: + expression: >- + sum(Process_output_arrival, over=process_output, by=Process_output_bus[bus]) ``` -**`Transformer_phase_shift`** - ```math -\mathrm{Transformer\_phase\_shift\_min}_{m} \le \mathit{Transformer\_phase\_shift}_{\xi,t,m} \le \mathrm{Transformer\_phase\_shift\_max}_{m} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{Transformer\_phase\_shift\_varying}_{m} \wedge \mathrm{on}^{\sigma}_{t,m} +\mathit{Process\_injection}_{\xi,t,n} = \sum_{r \in \mathcal{R} \,:\, \mathrm{Process\_output\_bus}(r) = n} \overrightarrow{z}_{\xi,t,r} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Line_s_nom_ext`** +### `StorageUnit_injection` -```math -S_{k} \in \mathbb{R} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} +```yaml +StorageUnit_injection: + expression: >- + sum(StorageUnit_sign * (StorageUnit_p_dispatch - StorageUnit_p_store), over=storage_unit, by=StorageUnit_bus[bus]) ``` -**`Line_n_mod`** - ```math -N^{s}_{k} \ge 0, N^{s}_{k} \in \mathbb{Z} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} \wedge \mathrm{s}^{\mathrm{mod}}_{k} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{s}_{t,k} \} \rvert > 0 +\mathit{StorageUnit\_injection}_{\xi,t,n} = \sum_{s \in \mathcal{S} \,:\, \mathrm{StorageUnit\_bus}(s) = n} \mathrm{sgn}^{h}_{s} \cdot \left( h^{+}_{\xi,t,s} - h^{-}_{\xi,t,s} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Generator_p_nom_ext`** +### `Store_injection` -```math -P_{g} \in \mathbb{R} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} +```yaml +Store_injection: sum(Store_sign * Store_p, over=store, by=Store_bus[bus]) ``` -**`Link_p_nom_ext`** - ```math -F_{l} \in \mathbb{R} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} +\mathit{Store\_injection}_{\xi,t,n} = \sum_{v \in \mathcal{V} \,:\, \mathrm{Store\_bus}(v) = n} \mathrm{sgn}^{q}_{v} \cdot q_{\xi,t,v} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Process_p_nom_ext`** +### `Transformer_injection` -```math -Z_{j} \in \mathbb{R} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} +```yaml +Transformer_injection: + expression: >- + -sum(Transformer_s, over=transformer, by=Transformer_bus0[bus]) + + sum(Transformer_s, over=transformer, by=Transformer_bus1[bus]) + - (0.5 * sum(Transformer_loss, over=transformer, by=Transformer_bus0[bus])) + - (0.5 * sum(Transformer_loss, over=transformer, by=Transformer_bus1[bus])) ``` -**`Transformer_s_nom_ext`** - ```math -\Sigma_{m} \in \mathbb{R} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} +\mathit{Transformer\_injection}_{\xi,t,n} = -\left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \sigma_{\xi,t,m} \right) + \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \sigma_{\xi,t,m} - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Transformer_n_mod`** +### `Bus_injection` -```math -N^{\sigma}_{m} \ge 0, N^{\sigma}_{m} \in \mathbb{Z} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} \wedge \sigma^{\mathrm{mod}}_{m} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{\sigma}_{t,m} \} \rvert > 0 +```yaml +Bus_injection: + dims: [scenario, snapshot, bus] + expression: >- + Generator_injection + + Line_injection + + Link_injection + + Load_injection + + Process_injection + + StorageUnit_injection + + Store_injection + + Transformer_injection + description: >- + what every component puts into a bus, less what it takes out of it; + PyPSA writes each term into the balance, and a load on its right-hand + side ``` -**`StorageUnit_p_nom_ext`** - ```math -H_{s} \in \mathbb{R} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} +\mathit{Bus\_injection}_{\xi,t,n} = \mathit{Generator\_injection}_{\xi,t,n} + \mathit{Line\_injection}_{\xi,t,n} + \mathit{Link\_injection}_{\xi,t,n} + \mathrm{Load\_injection}_{\xi,t,n} + \mathit{Process\_injection}_{\xi,t,n} + \mathit{StorageUnit\_injection}_{\xi,t,n} + \mathit{Store\_injection}_{\xi,t,n} + \mathit{Transformer\_injection}_{\xi,t,n} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`StorageUnit_n_mod`** +### `Line_angle_sum` -```math -N^{h}_{s} \ge 0, N^{h}_{s} \in \mathbb{Z} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} \wedge \mathrm{h}^{\mathrm{mod}}_{s} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{h}_{t,s} \} \rvert > 0 +```yaml +Line_angle_sum: sum(Line_s * at(Line_cycle_weight, by=snapshot_period[period]), over=line) ``` -**`Store_e_nom_ext`** - ```math -E_{v} \in \mathbb{R} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} +\mathit{Line\_angle\_sum}_{\xi,t,c} = \sum_{k \in \mathcal{K}} s_{\xi,t,k} \cdot \mathrm{x}_{\mathrm{snapshot\_period}(t),k,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} ``` -**`Store_n_mod`** +### `Transformer_angle_sum` -```math -N^{e}_{v} \ge 0, N^{e}_{v} \in \mathbb{Z} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} \wedge \mathrm{e}^{\mathrm{mod}}_{v} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{e}_{t,v} \} \rvert > 0 +```yaml +Transformer_angle_sum: + expression: >- + sum(Transformer_s * at(Transformer_cycle_weight, by=snapshot_period[period]), over=transformer) + + sum(Transformer_phase_shift_weight, over=transformer) + + sum(Transformer_phase_shift * at(Transformer_phase_shift_cycle_weight, by=snapshot_period[period]), over=transformer) ``` -**`CVaR_a`** - ```math -a_{\xi} \ge 0 \qquad \forall\, \xi \in \Xi \,:\, \omega \text{ is defined} +\mathit{Transformer\_angle\_sum}_{\xi,t,c} = \sum_{m \in \mathcal{M}} \sigma_{\xi,t,m} \cdot \mathrm{x}^{\sigma}_{\mathrm{snapshot\_period}(t),m,c} + \sum_{m \in \mathcal{M}} \vartheta_{t,m,c} + \sum_{m \in \mathcal{M}} \mathit{Transformer\_phase\_shift}_{\xi,t,m} \cdot \mathrm{Transformer\_phase\_shift\_cycle\_weight}_{\mathrm{snapshot\_period}(t),m,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} ``` -**`CVaR_theta`** +### `Cycle_angle_sum` -```math -\theta \in \mathbb{R} \qquad \text{where } \omega \text{ is defined} +```yaml +Cycle_angle_sum: + dims: [scenario, snapshot, cycle] + expression: Line_angle_sum + Transformer_angle_sum + description: >- + the voltage angle differences around a cycle: every branch flow times + its cycle weight, and every transformer phase shift ``` -**`CVaR`** - ```math -CVaR \in \mathbb{R} \qquad \text{where } \omega \text{ is defined} +\mathit{Cycle\_angle\_sum}_{\xi,t,c} = \mathit{Line\_angle\_sum}_{\xi,t,c} + \mathit{Transformer\_angle\_sum}_{\xi,t,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} ``` ### `Generator_maintenance_events_positive` diff --git a/docs/examples/pypsa/carrier.md b/docs/examples/pypsa/carrier.md index 69192a52..962ac27d 100644 --- a/docs/examples/pypsa/carrier.md +++ b/docs/examples/pypsa/carrier.md @@ -63,6 +63,12 @@ constraints: <= Carrier_max_growth ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression another file defines | + #### Sets | Symbol | Meaning | @@ -77,12 +83,6 @@ constraints: | $`\overline{\Delta}`$ | `Carrier_max_growth` over $`\mathcal{I}`$, `neutral` where the data has no row — most capacity of a carrier that may be added in a period; no value means no limit. The least over the scenarios, as PyPSA takes it (`global_constraints.py:227-231`), data prep. PyPSA reads it only under `multi_investment_periods` (`global_constraints.py:220-221`), so data prep feeds no value otherwise | | $`\mathrm{r}`$ | `Carrier_max_relative_growth` over $`\mathcal{I}`$ — share of the previous period's additions that may be added on top — the least over the scenarios, as PyPSA takes it, data prep | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression another file defines | - #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/cost.md b/docs/examples/pypsa/cost.md index 43acd888..de8bba90 100644 --- a/docs/examples/pypsa/cost.md +++ b/docs/examples/pypsa/cost.md @@ -64,6 +64,15 @@ constraints: expression: CVaR_theta + 1 / (1 - CVaR_alpha) * sum(scenario_weight * CVaR_a, over=scenario) <= CVaR ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression another file defines | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `risk_weighted_opex` to | + #### Sets | Symbol | Meaning | @@ -84,15 +93,6 @@ constraints: | $`\theta`$ | `CVaR_theta` (scalar), `neutral` where the mask leaves it out — `CVaR-theta` — where the tail starts, the value at risk | | $`CVaR`$ | `CVaR` (scalar), `neutral` where the mask leaves it out — `CVaR` — the tail's average cost, what the objective prices at `omega` | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression another file defines | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `risk_weighted_opex` to | - #### Definitions | Symbol | Meaning | @@ -113,14 +113,6 @@ a_{\xi} - \mathit{scenario\_opex}_{\xi} + \theta \ge 0 \qquad \forall\, \xi \in \theta + \frac{1}{1 - \alpha} \cdot \left( \sum_{\xi \in \Xi} \pi_{\xi} \cdot a_{\xi} \right) \le CVaR \qquad \text{where } \omega \text{ is defined} ``` -#### Definitions - -**`risk_weighted_opex`** - -```math -\mathit{risk\_weighted\_opex} = \left( 1 - \omega \right) \cdot \left( \sum_{\xi \in \Xi} \pi_{\xi} \cdot \mathit{scenario\_opex}_{\xi} \right) + \omega \cdot CVaR -``` - #### Variable domains **`CVaR_a`** @@ -140,4 +132,12 @@ a_{\xi} \ge 0 \qquad \forall\, \xi \in \Xi \,:\, \omega \text{ is defined} ```math CVaR \in \mathbb{R} \qquad \text{where } \omega \text{ is defined} ``` + +#### Definitions + +**`risk_weighted_opex`** + +```math +\mathit{risk\_weighted\_opex} = \left( 1 - \omega \right) \cdot \left( \sum_{\xi \in \Xi} \pi_{\xi} \cdot \mathit{scenario\_opex}_{\xi} \right) + \omega \cdot CVaR +``` diff --git a/docs/examples/pypsa/generator.md b/docs/examples/pypsa/generator.md index 4702cce7..64a128fe 100644 --- a/docs/examples/pypsa/generator.md +++ b/docs/examples/pypsa/generator.md @@ -303,6 +303,28 @@ assumptions: `CVaR_omega` row only where a risk preference is set ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{com}`$ | `Generator_committable` over $`\mathcal{G}`$, data another file declares | +| $`\gamma`$ | `Generator_maintenance_pu` over $`\Xi \times \mathcal{G}`$, data another file declares | +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | +| $`\mu`$ | `Generator_maintenance` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | +| $`\mu^{\mathrm{nom}}`$ | `Generator_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | +| $`\mathit{w}^{\mathrm{gc}}`$ | `GlobalConstraint_energy_weight` over $`\Xi \times \mathcal{L} \times \mathcal{T}`$, an expression another file defines | +| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{L}`$, an expression this file adds `Generator_primary_energy` to | +| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{L}`$, an expression this file adds `Generator_operational_limit` to | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{L}`$, an expression this file adds `Generator_tech_capacity_expansion` to | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Generator_opex` to | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Generator_capex` to | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Generator_additions` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Generator_injection` to | + #### Sets | Symbol | Meaning | @@ -351,28 +373,6 @@ assumptions: | $`N`$ | `Generator_n_mod` over $`\mathcal{G}`$ — `Generator-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | | $`P`$ | `Generator_p_nom_ext` over $`\mathcal{G}`$ — `Generator-p_nom` — nominal power where it is a decision; the parameter of the same PyPSA name carries the fixed regime | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{com}`$ | `Generator_committable` over $`\mathcal{G}`$, data another file declares | -| $`\gamma`$ | `Generator_maintenance_pu` over $`\Xi \times \mathcal{G}`$, data another file declares | -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | -| $`\mu`$ | `Generator_maintenance` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | -| $`\mu^{\mathrm{nom}}`$ | `Generator_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | -| $`\mathit{w}^{\mathrm{gc}}`$ | `GlobalConstraint_energy_weight` over $`\Xi \times \mathcal{L} \times \mathcal{T}`$, an expression another file defines | -| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{L}`$, an expression this file adds `Generator_primary_energy` to | -| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{L}`$, an expression this file adds `Generator_operational_limit` to | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{L}`$, an expression this file adds `Generator_tech_capacity_expansion` to | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Generator_opex` to | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Generator_capex` to | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Generator_additions` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Generator_injection` to | - #### Definitions | Symbol | Meaning | @@ -461,6 +461,26 @@ P_{g} = \mathrm{p}^{\mathrm{mod}}_{g} \cdot N_{g} \qquad \forall\, g \in \mathca p_{\xi,t,g} = \mathrm{p}^{\mathrm{set}}_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{p}^{\mathrm{set}}_{\xi,t,g} \text{ is defined} \wedge \mathrm{on}_{t,g} ``` +#### Variable domains + +**`Generator_p`** + +```math +p_{\xi,t,g} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}_{t,g} +``` + +**`Generator_n_mod`** + +```math +N_{g} \ge 0, N_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}_{t,g} \} \rvert > 0 +``` + +**`Generator_p_nom_ext`** + +```math +P_{g} \in \mathbb{R} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} +``` + #### Definitions **`Generator_p_nom_effective`** @@ -525,26 +545,6 @@ p_{\xi,t,g} = \mathrm{p}^{\mathrm{set}}_{\xi,t,g} \qquad \forall\, \xi \in \Xi,\ \mathrm{on}^{\mathrm{com}}_{t,g} \iff \mathrm{com}_{g} \wedge \mathrm{on}_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -#### Variable domains - -**`Generator_p`** - -```math -p_{\xi,t,g} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}_{t,g} -``` - -**`Generator_n_mod`** - -```math -N_{g} \ge 0, N_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}_{t,g} \} \rvert > 0 -``` - -**`Generator_p_nom_ext`** - -```math -P_{g} \in \mathbb{R} \qquad \forall\, g \in \mathcal{G} \,:\, \mathrm{ext}_{g} -``` - #### Assumptions **`Generator_marginal_cost_quadratic_without_risk_preference`** diff --git a/docs/examples/pypsa/generator_commitment.md b/docs/examples/pypsa/generator_commitment.md index e900ea4c..b3e36293 100644 --- a/docs/examples/pypsa/generator_commitment.md +++ b/docs/examples/pypsa/generator_commitment.md @@ -304,6 +304,29 @@ constraints: expression: Generator_shut_down <= Generator_n_mod ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{p}^{\mathrm{nom}}`$ | `Generator_p_nom` over $`\Xi \times \mathcal{G}`$, data another file declares | +| $`\mathrm{ext}`$ | `Generator_p_nom_extendable` over $`\mathcal{G}`$, data another file declares | +| $`\underline{\mathrm{p}}`$ | `Generator_p_min_pu` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, data another file declares | +| $`\overline{\mathrm{p}}`$ | `Generator_p_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, data another file declares | +| $`\mathrm{p}^{\mathrm{mod}}`$ | `Generator_p_nom_mod` over $`\mathcal{G}`$, data another file declares | +| $`\mathrm{N}^{\mathrm{fix}}`$ | `Generator_modules_installed` over $`\Xi \times \mathcal{G}`$, data another file declares | +| $`\mathrm{nonneg}`$ | `Generator_p_min_pu_nonneg` over $`\mathcal{G}`$, data another file declares | +| $`\gamma`$ | `Generator_maintenance_pu` over $`\Xi \times \mathcal{G}`$, data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{on}`$ | `Generator_active` over $`\mathcal{T} \times \mathcal{G}`$, data another file declares | +| $`p`$ | `Generator_p` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | +| $`N`$ | `Generator_n_mod` over $`\mathcal{G}`$ | +| $`\mu^{\mathrm{nom}}`$ | `Generator_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | +| $`\mu^{u}`$ | `Generator_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | +| $`P`$ | `Generator_p_nom_ext` over $`\mathcal{G}`$ | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Generator_commitment_opex` to | +| $`\mathrm{on}^{\mathrm{com}}`$ | `Generator_committed` over $`\mathcal{T} \times \mathcal{G}`$, a mask another file defines | + #### Sets | Symbol | Meaning | @@ -336,29 +359,6 @@ constraints: | $`\mathit{up}`$ | `Generator_start_up` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ — `Generator-start_up` — how much of a committable unit turns on this snapshot, capped as the status is | | $`\mathit{dn}`$ | `Generator_shut_down` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ — `Generator-shut_down` — how much of a committable unit turns off this snapshot, capped as the status is | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{p}^{\mathrm{nom}}`$ | `Generator_p_nom` over $`\Xi \times \mathcal{G}`$, data another file declares | -| $`\mathrm{ext}`$ | `Generator_p_nom_extendable` over $`\mathcal{G}`$, data another file declares | -| $`\underline{\mathrm{p}}`$ | `Generator_p_min_pu` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, data another file declares | -| $`\overline{\mathrm{p}}`$ | `Generator_p_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, data another file declares | -| $`\mathrm{p}^{\mathrm{mod}}`$ | `Generator_p_nom_mod` over $`\mathcal{G}`$, data another file declares | -| $`\mathrm{N}^{\mathrm{fix}}`$ | `Generator_modules_installed` over $`\Xi \times \mathcal{G}`$, data another file declares | -| $`\mathrm{nonneg}`$ | `Generator_p_min_pu_nonneg` over $`\mathcal{G}`$, data another file declares | -| $`\gamma`$ | `Generator_maintenance_pu` over $`\Xi \times \mathcal{G}`$, data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{on}`$ | `Generator_active` over $`\mathcal{T} \times \mathcal{G}`$, data another file declares | -| $`p`$ | `Generator_p` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | -| $`N`$ | `Generator_n_mod` over $`\mathcal{G}`$ | -| $`\mu^{\mathrm{nom}}`$ | `Generator_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | -| $`\mu^{u}`$ | `Generator_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | -| $`P`$ | `Generator_p_nom_ext` over $`\mathcal{G}`$ | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Generator_commitment_opex` to | -| $`\mathrm{on}^{\mathrm{com}}`$ | `Generator_committed` over $`\mathcal{T} \times \mathcal{G}`$, a mask another file defines | - #### Definitions | Symbol | Meaning | @@ -497,51 +497,51 @@ u_{\xi,t,g} \le N_{g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \ \mathit{dn}_{\xi,t,g} \le N_{g} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} \wedge \mathrm{ext}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 ``` -#### Definitions +#### Variable domains -**`Generator_previous_status`** +**`Generator_status`** ```math -\overleftarrow{u}_{\xi,t,g} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}_{t - 1,g} \\ \overleftarrow{u}^{\circ}_{\xi,t,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +u_{\xi,t,g} \ge 0, u_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} ``` -**`Generator_status_carried_over`** +**`Generator_start_up`** ```math -\overleftarrow{u}^{\circ}_{\xi,t,g} = \begin{cases} \mathrm{u}^{0}_{\xi,g} & \text{if } \mathrm{pos}(t) = 0 \\ u_{\xi,t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{up}_{\xi,t,g} \ge 0, \mathit{up}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} ``` -**`Generator_commitment_opex`** +**`Generator_shut_down`** ```math -\mathit{Generator\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} u_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{on}}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{up}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{up}}_{\xi,t,g} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{dn}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{dn}}_{\xi,t,g} \qquad \forall\, \xi \in \Xi +\mathit{dn}_{\xi,t,g} \ge 0, \mathit{dn}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} ``` -#### Masks +#### Definitions -**`Generator_com_ext`** +**`Generator_previous_status`** ```math -\mathrm{on}^{\mathrm{com,ext}}_{t,g} \iff \mathrm{com}_{g} \wedge \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\overleftarrow{u}_{\xi,t,g} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}_{t - 1,g} \\ \overleftarrow{u}^{\circ}_{\xi,t,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -#### Variable domains - -**`Generator_status`** +**`Generator_status_carried_over`** ```math -u_{\xi,t,g} \ge 0, u_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} +\overleftarrow{u}^{\circ}_{\xi,t,g} = \begin{cases} \mathrm{u}^{0}_{\xi,g} & \text{if } \mathrm{pos}(t) = 0 \\ u_{\xi,t - 1,g} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`Generator_start_up`** +**`Generator_commitment_opex`** ```math -\mathit{up}_{\xi,t,g} \ge 0, \mathit{up}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} +\mathit{Generator\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} u_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{on}}_{\xi,t,g} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{up}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{up}}_{\xi,t,g} + \sum_{t \in \mathcal{T}} \sum_{g \in \mathcal{G}} \mathit{dn}_{\xi,t,g} \cdot \mathrm{c}^{\mathrm{dn}}_{\xi,t,g} \qquad \forall\, \xi \in \Xi ``` -**`Generator_shut_down`** +#### Masks + +**`Generator_com_ext`** ```math -\mathit{dn}_{\xi,t,g} \ge 0, \mathit{dn}_{\xi,t,g} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{on}^{\mathrm{com}}_{t,g} +\mathrm{on}^{\mathrm{com,ext}}_{t,g} \iff \mathrm{com}_{g} \wedge \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` diff --git a/docs/examples/pypsa/generator_maintenance.md b/docs/examples/pypsa/generator_maintenance.md index 8e697399..03c36cb1 100644 --- a/docs/examples/pypsa/generator_maintenance.md +++ b/docs/examples/pypsa/generator_maintenance.md @@ -246,6 +246,21 @@ assumptions: (`constraints.py:504-507`) ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{ext}`$ | `Generator_p_nom_extendable` over $`\mathcal{G}`$, data another file declares | +| $`\mathrm{com}`$ | `Generator_committable` over $`\mathcal{G}`$, data another file declares | +| $`\mathrm{p}^{\mathrm{mod}}`$ | `Generator_p_nom_mod` over $`\mathcal{G}`$, data another file declares | +| $`\mathrm{on}`$ | `Generator_active` over $`\mathcal{T} \times \mathcal{G}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | +| $`\underline{\mathrm{p}}^{\mathrm{nom}}`$ | `Generator_p_nom_min` over $`\Xi \times \mathcal{G}`$, data another file declares | +| $`\overline{\mathrm{p}}^{\mathrm{nom}}`$ | `Generator_p_nom_max` over $`\Xi \times \mathcal{G}`$, data another file declares | +| $`u`$ | `Generator_status` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | +| $`P`$ | `Generator_p_nom_ext` over $`\mathcal{G}`$ | +| $`\mathrm{on}^{\mathrm{com}}`$ | `Generator_committed` over $`\mathcal{T} \times \mathcal{G}`$, a mask another file defines | + #### Sets | Symbol | Meaning | @@ -273,21 +288,6 @@ assumptions: | $`\mu^{\mathrm{nom}}`$ | `Generator_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, `neutral` where the mask leaves it out — `Generator-maintenance_capacity` — the chosen build while in maintenance, zero otherwise: the product the `maintcap` rows linearize | | $`\mu^{u}`$ | `Generator_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, `neutral` where the mask leaves it out — `Generator-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}`$ | `Generator_p_nom_extendable` over $`\mathcal{G}`$, data another file declares | -| $`\mathrm{com}`$ | `Generator_committable` over $`\mathcal{G}`$, data another file declares | -| $`\mathrm{p}^{\mathrm{mod}}`$ | `Generator_p_nom_mod` over $`\mathcal{G}`$, data another file declares | -| $`\mathrm{on}`$ | `Generator_active` over $`\mathcal{T} \times \mathcal{G}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | -| $`\underline{\mathrm{p}}^{\mathrm{nom}}`$ | `Generator_p_nom_min` over $`\Xi \times \mathcal{G}`$, data another file declares | -| $`\overline{\mathrm{p}}^{\mathrm{nom}}`$ | `Generator_p_nom_max` over $`\Xi \times \mathcal{G}`$, data another file declares | -| $`u`$ | `Generator_status` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$ | -| $`P`$ | `Generator_p_nom_ext` over $`\mathcal{G}`$ | -| $`\mathrm{on}^{\mathrm{com}}`$ | `Generator_committed` over $`\mathcal{T} \times \mathcal{G}`$, a mask another file defines | - #### Masks | Symbol | Meaning | @@ -374,14 +374,6 @@ assumptions: \mu^{u}_{\xi,t,g} \ge u_{\xi,t,g} - \frac{\overline{\mathrm{p}}^{\mathrm{nom}}_{\xi,g}}{\mathrm{p}^{\mathrm{mod}}_{g}} \cdot \left( 1 - \mu_{\xi,t,g} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}^{\mathrm{com}}_{t,g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 ``` -#### Masks - -**`Generator_maint_ext`** - -```math -\mathrm{on}^{\mathrm{mnt,ext}}_{t,g} \iff \mathrm{mnt}_{g} \wedge \mathrm{ext}_{g} \wedge \neg \left( \mathrm{com}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} -``` - #### Variable domains **`Generator_maintenance`** @@ -408,6 +400,14 @@ assumptions: \mu^{u}_{\xi,t,g} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{mnt}_{g} \wedge \mathrm{on}^{\mathrm{com}}_{t,g} \wedge \neg \left( \mathrm{ext}_{g} \wedge \neg \left( \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \right) ``` +#### Masks + +**`Generator_maint_ext`** + +```math +\mathrm{on}^{\mathrm{mnt,ext}}_{t,g} \iff \mathrm{mnt}_{g} \wedge \mathrm{ext}_{g} \wedge \neg \left( \mathrm{com}_{g} \wedge \mathrm{p}^{\mathrm{mod}}_{g} > 0 \right) \wedge \mathrm{on}_{t,g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +``` + #### Assumptions **`Generator_maintenance_events_positive`** diff --git a/docs/examples/pypsa/generator_ramping.md b/docs/examples/pypsa/generator_ramping.md index 1bcc65a2..e7331ea2 100644 --- a/docs/examples/pypsa/generator_ramping.md +++ b/docs/examples/pypsa/generator_ramping.md @@ -261,25 +261,6 @@ assumptions: spec does not state that row, so it refuses the data ``` -#### Sets - -| Symbol | Meaning | -|---|---| -| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | -| $`\mathcal{T}`$ | index $`t`$ — `snapshot` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — dispatch periods | -| $`\mathcal{G}`$ | index $`g`$ — `generator` — generating units, each on one bus | -| $`\mathcal{Y}`$ | index $`y`$ — `period` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — investment periods — PyPSA's `investment_periods` | - -#### Parameters - -| Symbol | Meaning | -|---|---| -| $`\mathrm{ru}`$ | `Generator_ramp_limit_up` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, `neutral` where the data has no row — most a generator may raise its output between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | -| $`\mathrm{rd}`$ | `Generator_ramp_limit_down` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, `neutral` where the data has no row — most a generator may lower its output between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | -| $`\mathrm{ru}^{\mathrm{up}}`$ | `Generator_ramp_limit_start_up` over $`\Xi \times \mathcal{G}`$, `neutral` where the data has no row — most output in the snapshot a unit starts, per unit of nominal power; no value means no limit | -| $`\mathrm{rd}^{\mathrm{dn}}`$ | `Generator_ramp_limit_shut_down` over $`\Xi \times \mathcal{G}`$, `neutral` where the data has no row — most output in the snapshot before a unit stops, per unit of nominal power; no value means no limit | -| $`\mathrm{p}^{0}`$ | `Generator_p_init` over $`\Xi \times \mathcal{G}`$, `neutral` where the data has no row — the output a unit brought into the horizon — PyPSA's `p_init`, read only where the unit came in running; no value means it is unknown, so the unit carries no ramp row at the first snapshot | - #### Given | Symbol | Meaning | @@ -300,6 +281,25 @@ assumptions: | $`\widehat{\mathrm{p}}^{\mathrm{nom}}`$ | `Generator_p_nom_committed` over $`\Xi \times \mathcal{G}`$, an expression another file defines | | $`\mathrm{on}^{\mathrm{com,ext}}`$ | `Generator_com_ext` over $`\mathcal{T} \times \mathcal{G}`$, a mask another file defines | +#### Sets + +| Symbol | Meaning | +|---|---| +| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | +| $`\mathcal{T}`$ | index $`t`$ — `snapshot` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — dispatch periods | +| $`\mathcal{G}`$ | index $`g`$ — `generator` — generating units, each on one bus | +| $`\mathcal{Y}`$ | index $`y`$ — `period` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — investment periods — PyPSA's `investment_periods` | + +#### Parameters + +| Symbol | Meaning | +|---|---| +| $`\mathrm{ru}`$ | `Generator_ramp_limit_up` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, `neutral` where the data has no row — most a generator may raise its output between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | +| $`\mathrm{rd}`$ | `Generator_ramp_limit_down` over $`\Xi \times \mathcal{T} \times \mathcal{G}`$, `neutral` where the data has no row — most a generator may lower its output between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | +| $`\mathrm{ru}^{\mathrm{up}}`$ | `Generator_ramp_limit_start_up` over $`\Xi \times \mathcal{G}`$, `neutral` where the data has no row — most output in the snapshot a unit starts, per unit of nominal power; no value means no limit | +| $`\mathrm{rd}^{\mathrm{dn}}`$ | `Generator_ramp_limit_shut_down` over $`\Xi \times \mathcal{G}`$, `neutral` where the data has no row — most output in the snapshot before a unit stops, per unit of nominal power; no value means no limit | +| $`\mathrm{p}^{0}`$ | `Generator_p_init` over $`\Xi \times \mathcal{G}`$, `neutral` where the data has no row — the output a unit brought into the horizon — PyPSA's `p_init`, read only where the unit came in running; no value means it is unknown, so the unit carries no ramp row at the first snapshot | + #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/global_constraints.md b/docs/examples/pypsa/global_constraints.md index c4bd0f48..b01abaac 100644 --- a/docs/examples/pypsa/global_constraints.md +++ b/docs/examples/pypsa/global_constraints.md @@ -139,6 +139,17 @@ assumptions: more than one scenario ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression another file defines | +| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression another file defines | +| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression another file defines | +| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression another file defines | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression another file defines | + #### Sets | Symbol | Meaning | @@ -154,17 +165,6 @@ assumptions: | $`\mathrm{sense}`$ | `GlobalConstraint_sense` over $`\Xi \times \mathcal{G}`$ — which way the row binds in each scenario — `<=`, `>=` or `==`; PyPSA reads a row's sense per scenario (`global_constraints.py:551`, `:749`, `:829`) | | $`\mathrm{K}`$ | `GlobalConstraint_constant` over $`\Xi \times \mathcal{G}`$ — the constant the total is held against; what a variable cannot carry — an initial charge, times its period's years for each counted period where the storage reopens per period, or a non-extendable build — is folded in here by data prep. PyPSA reads it per scenario (`global_constraints.py:552`, `:750`, `:829`) | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression another file defines | -| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression another file defines | -| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression another file defines | -| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression another file defines | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression another file defines | - #### Subject to **`GlobalConstraint_primary_energy_ub`** diff --git a/docs/examples/pypsa/line.md b/docs/examples/pypsa/line.md index 62ed4185..5d55aee2 100644 --- a/docs/examples/pypsa/line.md +++ b/docs/examples/pypsa/line.md @@ -342,6 +342,20 @@ constraints: expression: Line_loss - Line_loss_slope * Line_s >= Line_loss_offset ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\mathrm{lossy}`$ | `transmission_losses` (scalar), data another file declares | +| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Line_transmission_volume_expansion` to | +| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Line_transmission_expansion_cost` to | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Line_tech_capacity_expansion` to | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Line_capex` to | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Line_additions` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Line_injection` to | +| $`\mathit{Cycle\_angle\_sum}`$ | `Cycle_angle_sum` over $`\Xi \times \mathcal{T} \times \mathcal{C}`$, an expression this file adds `Line_angle_sum` to | + #### Sets | Symbol | Meaning | @@ -391,20 +405,6 @@ constraints: | $`S`$ | `Line_s_nom_ext` over $`\mathcal{K}`$ — `Line-s_nom` — nominal apparent power where it is a decision; the parameter of the same PyPSA name carries the fixed regime | | $`N^{s}`$ | `Line_n_mod` over $`\mathcal{K}`$ — `Line-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\mathrm{lossy}`$ | `transmission_losses` (scalar), data another file declares | -| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Line_transmission_volume_expansion` to | -| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Line_transmission_expansion_cost` to | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Line_tech_capacity_expansion` to | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Line_capex` to | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Line_additions` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Line_injection` to | -| $`\mathit{Cycle\_angle\_sum}`$ | `Cycle_angle_sum` over $`\Xi \times \mathcal{T} \times \mathcal{C}`$, an expression this file adds `Line_angle_sum` to | - #### Definitions | Symbol | Meaning | @@ -510,6 +510,32 @@ s_{\xi,t,k} \le \frac{\overline{\delta}_{\xi,k} \cdot \frac{3.141592653589793}{1 \ell_{\xi,t,k} - \mathrm{a}_{\xi,t,k,e} \cdot s_{\xi,t,k} \ge \mathrm{b}_{\xi,t,k,e} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K},\ e \in \mathcal{E} \,:\, \mathrm{on}^{s,\mathrm{lossy}}_{t,k} ``` +#### Variable domains + +**`Line_s`** + +```math +s_{\xi,t,k} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s}_{t,k} +``` + +**`Line_loss`** + +```math +\ell_{\xi,t,k} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s,\mathrm{lossy}}_{t,k} +``` + +**`Line_s_nom_ext`** + +```math +S_{k} \in \mathbb{R} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} +``` + +**`Line_n_mod`** + +```math +N^{s}_{k} \ge 0, N^{s}_{k} \in \mathbb{Z} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} \wedge \mathrm{s}^{\mathrm{mod}}_{k} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{s}_{t,k} \} \rvert > 0 +``` + #### Definitions **`Line_transmission_volume_expansion`** @@ -567,30 +593,4 @@ s_{\xi,t,k} \le \frac{\overline{\delta}_{\xi,k} \cdot \frac{3.141592653589793}{1 ```math \mathrm{on}^{s,\mathrm{lossy}}_{t,k} \iff \mathrm{lossy} \wedge \mathrm{on}^{s}_{t,k} \qquad \forall\, t \in \mathcal{T},\ k \in \mathcal{K} ``` - -#### Variable domains - -**`Line_s`** - -```math -s_{\xi,t,k} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s}_{t,k} -``` - -**`Line_loss`** - -```math -\ell_{\xi,t,k} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ k \in \mathcal{K} \,:\, \mathrm{on}^{s,\mathrm{lossy}}_{t,k} -``` - -**`Line_s_nom_ext`** - -```math -S_{k} \in \mathbb{R} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} -``` - -**`Line_n_mod`** - -```math -N^{s}_{k} \ge 0, N^{s}_{k} \in \mathbb{Z} \qquad \forall\, k \in \mathcal{K} \,:\, \mathrm{ext}^{s}_{k} \wedge \mathrm{s}^{\mathrm{mod}}_{k} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{s}_{t,k} \} \rvert > 0 -``` diff --git a/docs/examples/pypsa/link.md b/docs/examples/pypsa/link.md index 8a4942c1..ceecc701 100644 --- a/docs/examples/pypsa/link.md +++ b/docs/examples/pypsa/link.md @@ -356,6 +356,27 @@ assumptions: `CVaR_omega` row only where a risk preference is set ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{com}^{f}`$ | `Link_committable` over $`\mathcal{L}`$, data another file declares | +| $`\gamma^{f}`$ | `Link_maintenance_pu` over $`\Xi \times \mathcal{L}`$, data another file declares | +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | +| $`\mu^{f}`$ | `Link_maintenance` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | +| $`\mu^{f,\mathrm{nom}}`$ | `Link_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | +| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Link_transmission_volume_expansion` to | +| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Link_transmission_expansion_cost` to | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Link_tech_capacity_expansion` to | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Link_opex` to | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Link_capex` to | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Link_additions` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Link_injection` to | + #### Sets | Symbol | Meaning | @@ -405,27 +426,6 @@ assumptions: | $`N^{f}`$ | `Link_n_mod` over $`\mathcal{L}`$ — `Link-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | | $`F`$ | `Link_p_nom_ext` over $`\mathcal{L}`$ — `Link-p_nom` — nominal power where it is a decision; the parameter of the same PyPSA name carries the fixed regime | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{com}^{f}`$ | `Link_committable` over $`\mathcal{L}`$, data another file declares | -| $`\gamma^{f}`$ | `Link_maintenance_pu` over $`\Xi \times \mathcal{L}`$, data another file declares | -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | -| $`\mu^{f}`$ | `Link_maintenance` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | -| $`\mu^{f,\mathrm{nom}}`$ | `Link_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | -| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Link_transmission_volume_expansion` to | -| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Link_transmission_expansion_cost` to | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Link_tech_capacity_expansion` to | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Link_opex` to | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Link_capex` to | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Link_additions` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Link_injection` to | - #### Definitions | Symbol | Meaning | @@ -509,6 +509,26 @@ F_{l} = \mathrm{f}^{\mathrm{mod}}_{l} \cdot N^{f}_{l} \qquad \forall\, l \in \ma f_{\xi,t,l} = \mathrm{f}^{\mathrm{set}}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{f}^{\mathrm{set}}_{\xi,t,l} \text{ is defined} \wedge \mathrm{on}^{f}_{t,l} ``` +#### Variable domains + +**`Link_p`** + +```math +f_{\xi,t,l} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f}_{t,l} +``` + +**`Link_n_mod`** + +```math +N^{f}_{l} \ge 0, N^{f}_{l} \in \mathbb{Z} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{f}_{t,l} \} \rvert > 0 +``` + +**`Link_p_nom_ext`** + +```math +F_{l} \in \mathbb{R} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} +``` + #### Definitions **`Link_p_nom_effective`** @@ -579,26 +599,6 @@ f_{\xi,t,l} = \mathrm{f}^{\mathrm{set}}_{\xi,t,l} \qquad \forall\, \xi \in \Xi,\ \mathrm{on}^{f,\mathrm{com}}_{t,l} \iff \mathrm{com}^{f}_{l} \wedge \mathrm{on}^{f}_{t,l} \qquad \forall\, t \in \mathcal{T},\ l \in \mathcal{L} ``` -#### Variable domains - -**`Link_p`** - -```math -f_{\xi,t,l} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f}_{t,l} -``` - -**`Link_n_mod`** - -```math -N^{f}_{l} \ge 0, N^{f}_{l} \in \mathbb{Z} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{f}_{t,l} \} \rvert > 0 -``` - -**`Link_p_nom_ext`** - -```math -F_{l} \in \mathbb{R} \qquad \forall\, l \in \mathcal{L} \,:\, \mathrm{ext}^{f}_{l} -``` - #### Assumptions **`Link_output_delay_under_uniform_weighting`** diff --git a/docs/examples/pypsa/link_commitment.md b/docs/examples/pypsa/link_commitment.md index bcbcd27a..148c4a2b 100644 --- a/docs/examples/pypsa/link_commitment.md +++ b/docs/examples/pypsa/link_commitment.md @@ -304,6 +304,29 @@ constraints: expression: Link_shut_down <= Link_n_mod ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{f}^{\mathrm{nom}}`$ | `Link_p_nom` over $`\Xi \times \mathcal{L}`$, data another file declares | +| $`\mathrm{ext}^{f}`$ | `Link_p_nom_extendable` over $`\mathcal{L}`$, data another file declares | +| $`\underline{\mathrm{f}}`$ | `Link_p_min_pu` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, data another file declares | +| $`\overline{\mathrm{f}}`$ | `Link_p_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, data another file declares | +| $`\mathrm{f}^{\mathrm{mod}}`$ | `Link_p_nom_mod` over $`\mathcal{L}`$, data another file declares | +| $`\mathrm{N}^{f,\mathrm{fix}}`$ | `Link_modules_installed` over $`\Xi \times \mathcal{L}`$, data another file declares | +| $`\mathrm{nonneg}^{f}`$ | `Link_p_min_pu_nonneg` over $`\mathcal{L}`$, data another file declares | +| $`\gamma^{f}`$ | `Link_maintenance_pu` over $`\Xi \times \mathcal{L}`$, data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{on}^{f}`$ | `Link_active` over $`\mathcal{T} \times \mathcal{L}`$, data another file declares | +| $`f`$ | `Link_p` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | +| $`N^{f}`$ | `Link_n_mod` over $`\mathcal{L}`$ | +| $`\mu^{f,\mathrm{nom}}`$ | `Link_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | +| $`\mu^{f,u}`$ | `Link_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | +| $`F`$ | `Link_p_nom_ext` over $`\mathcal{L}`$ | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Link_commitment_opex` to | +| $`\mathrm{on}^{f,\mathrm{com}}`$ | `Link_committed` over $`\mathcal{T} \times \mathcal{L}`$, a mask another file defines | + #### Sets | Symbol | Meaning | @@ -336,29 +359,6 @@ constraints: | $`\mathit{up}^{f}`$ | `Link_start_up` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ — `Link-start_up` — how much of a committable link turns on this snapshot, capped as the status is | | $`\mathit{dn}^{f}`$ | `Link_shut_down` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ — `Link-shut_down` — how much of a committable link turns off this snapshot, capped as the status is | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{f}^{\mathrm{nom}}`$ | `Link_p_nom` over $`\Xi \times \mathcal{L}`$, data another file declares | -| $`\mathrm{ext}^{f}`$ | `Link_p_nom_extendable` over $`\mathcal{L}`$, data another file declares | -| $`\underline{\mathrm{f}}`$ | `Link_p_min_pu` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, data another file declares | -| $`\overline{\mathrm{f}}`$ | `Link_p_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, data another file declares | -| $`\mathrm{f}^{\mathrm{mod}}`$ | `Link_p_nom_mod` over $`\mathcal{L}`$, data another file declares | -| $`\mathrm{N}^{f,\mathrm{fix}}`$ | `Link_modules_installed` over $`\Xi \times \mathcal{L}`$, data another file declares | -| $`\mathrm{nonneg}^{f}`$ | `Link_p_min_pu_nonneg` over $`\mathcal{L}`$, data another file declares | -| $`\gamma^{f}`$ | `Link_maintenance_pu` over $`\Xi \times \mathcal{L}`$, data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{on}^{f}`$ | `Link_active` over $`\mathcal{T} \times \mathcal{L}`$, data another file declares | -| $`f`$ | `Link_p` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | -| $`N^{f}`$ | `Link_n_mod` over $`\mathcal{L}`$ | -| $`\mu^{f,\mathrm{nom}}`$ | `Link_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | -| $`\mu^{f,u}`$ | `Link_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | -| $`F`$ | `Link_p_nom_ext` over $`\mathcal{L}`$ | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Link_commitment_opex` to | -| $`\mathrm{on}^{f,\mathrm{com}}`$ | `Link_committed` over $`\mathcal{T} \times \mathcal{L}`$, a mask another file defines | - #### Definitions | Symbol | Meaning | @@ -497,51 +497,51 @@ u^{f}_{\xi,t,l} \le N^{f}_{l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ \mathit{dn}^{f}_{\xi,t,l} \le N^{f}_{l} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} \wedge \mathrm{ext}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 ``` -#### Definitions +#### Variable domains -**`Link_previous_status`** +**`Link_status`** ```math -\overleftarrow{u}^{f}_{\xi,t,l} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{f}_{t - 1,l} \\ \overleftarrow{u}^{\circ f}_{\xi,t,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +u^{f}_{\xi,t,l} \ge 0, u^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} ``` -**`Link_status_carried_over`** +**`Link_start_up`** ```math -\overleftarrow{u}^{\circ f}_{\xi,t,l} = \begin{cases} \mathrm{u}^{f,0}_{\xi,l} & \text{if } \mathrm{pos}(t) = 0 \\ u^{f}_{\xi,t - 1,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} +\mathit{up}^{f}_{\xi,t,l} \ge 0, \mathit{up}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} ``` -**`Link_commitment_opex`** +**`Link_shut_down`** ```math -\mathit{Link\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} u^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{on}}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{up}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{up}}_{\xi,t,l} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{dn}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{dn}}_{\xi,t,l} \qquad \forall\, \xi \in \Xi +\mathit{dn}^{f}_{\xi,t,l} \ge 0, \mathit{dn}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} ``` -#### Masks +#### Definitions -**`Link_com_ext`** +**`Link_previous_status`** ```math -\mathrm{on}^{f,\mathrm{com,ext}}_{t,l} \iff \mathrm{com}^{f}_{l} \wedge \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} \qquad \forall\, t \in \mathcal{T},\ l \in \mathcal{L} +\overleftarrow{u}^{f}_{\xi,t,l} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{f}_{t - 1,l} \\ \overleftarrow{u}^{\circ f}_{\xi,t,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -#### Variable domains - -**`Link_status`** +**`Link_status_carried_over`** ```math -u^{f}_{\xi,t,l} \ge 0, u^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} +\overleftarrow{u}^{\circ f}_{\xi,t,l} = \begin{cases} \mathrm{u}^{f,0}_{\xi,l} & \text{if } \mathrm{pos}(t) = 0 \\ u^{f}_{\xi,t - 1,l} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} ``` -**`Link_start_up`** +**`Link_commitment_opex`** ```math -\mathit{up}^{f}_{\xi,t,l} \ge 0, \mathit{up}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} +\mathit{Link\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} u^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{on}}_{\xi,t,l} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{up}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{up}}_{\xi,t,l} + \sum_{t \in \mathcal{T}} \sum_{l \in \mathcal{L}} \mathit{dn}^{f}_{\xi,t,l} \cdot \mathrm{c}^{f,\mathrm{dn}}_{\xi,t,l} \qquad \forall\, \xi \in \Xi ``` -**`Link_shut_down`** +#### Masks + +**`Link_com_ext`** ```math -\mathit{dn}^{f}_{\xi,t,l} \ge 0, \mathit{dn}^{f}_{\xi,t,l} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{on}^{f,\mathrm{com}}_{t,l} +\mathrm{on}^{f,\mathrm{com,ext}}_{t,l} \iff \mathrm{com}^{f}_{l} \wedge \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} \qquad \forall\, t \in \mathcal{T},\ l \in \mathcal{L} ``` diff --git a/docs/examples/pypsa/link_maintenance.md b/docs/examples/pypsa/link_maintenance.md index eb82a02e..4656995f 100644 --- a/docs/examples/pypsa/link_maintenance.md +++ b/docs/examples/pypsa/link_maintenance.md @@ -243,6 +243,21 @@ assumptions: (`constraints.py:504-507`) ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{ext}^{f}`$ | `Link_p_nom_extendable` over $`\mathcal{L}`$, data another file declares | +| $`\mathrm{com}^{f}`$ | `Link_committable` over $`\mathcal{L}`$, data another file declares | +| $`\mathrm{f}^{\mathrm{mod}}`$ | `Link_p_nom_mod` over $`\mathcal{L}`$, data another file declares | +| $`\mathrm{on}^{f}`$ | `Link_active` over $`\mathcal{T} \times \mathcal{L}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | +| $`\underline{\mathrm{f}}^{\mathrm{nom}}`$ | `Link_p_nom_min` over $`\Xi \times \mathcal{L}`$, data another file declares | +| $`\overline{\mathrm{f}}^{\mathrm{nom}}`$ | `Link_p_nom_max` over $`\Xi \times \mathcal{L}`$, data another file declares | +| $`u^{f}`$ | `Link_status` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | +| $`F`$ | `Link_p_nom_ext` over $`\mathcal{L}`$ | +| $`\mathrm{on}^{f,\mathrm{com}}`$ | `Link_committed` over $`\mathcal{T} \times \mathcal{L}`$, a mask another file defines | + #### Sets | Symbol | Meaning | @@ -270,21 +285,6 @@ assumptions: | $`\mu^{f,\mathrm{nom}}`$ | `Link_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, `neutral` where the mask leaves it out — `Link-maintenance_capacity` — the chosen build while in maintenance, zero otherwise: the product the `maintcap` rows linearize | | $`\mu^{f,u}`$ | `Link_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, `neutral` where the mask leaves it out — `Link-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}^{f}`$ | `Link_p_nom_extendable` over $`\mathcal{L}`$, data another file declares | -| $`\mathrm{com}^{f}`$ | `Link_committable` over $`\mathcal{L}`$, data another file declares | -| $`\mathrm{f}^{\mathrm{mod}}`$ | `Link_p_nom_mod` over $`\mathcal{L}`$, data another file declares | -| $`\mathrm{on}^{f}`$ | `Link_active` over $`\mathcal{T} \times \mathcal{L}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | -| $`\underline{\mathrm{f}}^{\mathrm{nom}}`$ | `Link_p_nom_min` over $`\Xi \times \mathcal{L}`$, data another file declares | -| $`\overline{\mathrm{f}}^{\mathrm{nom}}`$ | `Link_p_nom_max` over $`\Xi \times \mathcal{L}`$, data another file declares | -| $`u^{f}`$ | `Link_status` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$ | -| $`F`$ | `Link_p_nom_ext` over $`\mathcal{L}`$ | -| $`\mathrm{on}^{f,\mathrm{com}}`$ | `Link_committed` over $`\mathcal{T} \times \mathcal{L}`$, a mask another file defines | - #### Masks | Symbol | Meaning | @@ -371,14 +371,6 @@ assumptions: \mu^{f,u}_{\xi,t,l} \ge u^{f}_{\xi,t,l} - \frac{\overline{\mathrm{f}}^{\mathrm{nom}}_{\xi,l}}{\mathrm{f}^{\mathrm{mod}}_{l}} \cdot \left( 1 - \mu^{f}_{\xi,t,l} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f,\mathrm{com}}_{t,l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 ``` -#### Masks - -**`Link_maint_ext`** - -```math -\mathrm{on}^{f,\mathrm{mnt,ext}}_{t,l} \iff \mathrm{mnt}^{f}_{l} \wedge \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{com}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} \qquad \forall\, t \in \mathcal{T},\ l \in \mathcal{L} -``` - #### Variable domains **`Link_maintenance`** @@ -405,6 +397,14 @@ assumptions: \mu^{f,u}_{\xi,t,l} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ l \in \mathcal{L} \,:\, \mathrm{mnt}^{f}_{l} \wedge \mathrm{on}^{f,\mathrm{com}}_{t,l} \wedge \neg \left( \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \right) ``` +#### Masks + +**`Link_maint_ext`** + +```math +\mathrm{on}^{f,\mathrm{mnt,ext}}_{t,l} \iff \mathrm{mnt}^{f}_{l} \wedge \mathrm{ext}^{f}_{l} \wedge \neg \left( \mathrm{com}^{f}_{l} \wedge \mathrm{f}^{\mathrm{mod}}_{l} > 0 \right) \wedge \mathrm{on}^{f}_{t,l} \qquad \forall\, t \in \mathcal{T},\ l \in \mathcal{L} +``` + #### Assumptions **`Link_maintenance_events_positive`** diff --git a/docs/examples/pypsa/link_ramping.md b/docs/examples/pypsa/link_ramping.md index 44274eb3..1706abf1 100644 --- a/docs/examples/pypsa/link_ramping.md +++ b/docs/examples/pypsa/link_ramping.md @@ -249,25 +249,6 @@ assumptions: spec does not state that row, so it refuses the data ``` -#### Sets - -| Symbol | Meaning | -|---|---| -| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | -| $`\mathcal{T}`$ | index $`t`$ — `snapshot` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — dispatch periods | -| $`\mathcal{L}`$ | index $`l`$ — `link` — controllable connections, each from one bus to the buses it delivers to | -| $`\mathcal{Y}`$ | index $`y`$ — `period` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — investment periods — PyPSA's `investment_periods` | - -#### Parameters - -| Symbol | Meaning | -|---|---| -| $`\mathrm{ru}^{f}`$ | `Link_ramp_limit_up` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, `neutral` where the data has no row — most a link may raise its flow between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | -| $`\mathrm{rd}^{f}`$ | `Link_ramp_limit_down` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, `neutral` where the data has no row — most a link may lower its flow between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | -| $`\mathrm{ru}^{f,\mathrm{up}}`$ | `Link_ramp_limit_start_up` over $`\Xi \times \mathcal{L}`$, `neutral` where the data has no row — most flow in the snapshot a link starts, per unit of nominal power; no value means no limit | -| $`\mathrm{rd}^{f,\mathrm{dn}}`$ | `Link_ramp_limit_shut_down` over $`\Xi \times \mathcal{L}`$, `neutral` where the data has no row — most flow in the snapshot before a link stops, per unit of nominal power; no value means no limit | -| $`\mathrm{f}^{0}`$ | `Link_p_init` over $`\Xi \times \mathcal{L}`$, `neutral` where the data has no row — the flow a link brought into the horizon — PyPSA's `p_init`, read only where the link came in running; no value means it is unknown, so the link carries no ramp row at the first snapshot | - #### Given | Symbol | Meaning | @@ -288,6 +269,25 @@ assumptions: | $`\widehat{\mathrm{f}}^{\mathrm{nom}}`$ | `Link_p_nom_committed` over $`\Xi \times \mathcal{L}`$, an expression another file defines | | $`\mathrm{on}^{f,\mathrm{com,ext}}`$ | `Link_com_ext` over $`\mathcal{T} \times \mathcal{L}`$, a mask another file defines | +#### Sets + +| Symbol | Meaning | +|---|---| +| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | +| $`\mathcal{T}`$ | index $`t`$ — `snapshot` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — dispatch periods | +| $`\mathcal{L}`$ | index $`l`$ — `link` — controllable connections, each from one bus to the buses it delivers to | +| $`\mathcal{Y}`$ | index $`y`$ — `period` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — investment periods — PyPSA's `investment_periods` | + +#### Parameters + +| Symbol | Meaning | +|---|---| +| $`\mathrm{ru}^{f}`$ | `Link_ramp_limit_up` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, `neutral` where the data has no row — most a link may raise its flow between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | +| $`\mathrm{rd}^{f}`$ | `Link_ramp_limit_down` over $`\Xi \times \mathcal{T} \times \mathcal{L}`$, `neutral` where the data has no row — most a link may lower its flow between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | +| $`\mathrm{ru}^{f,\mathrm{up}}`$ | `Link_ramp_limit_start_up` over $`\Xi \times \mathcal{L}`$, `neutral` where the data has no row — most flow in the snapshot a link starts, per unit of nominal power; no value means no limit | +| $`\mathrm{rd}^{f,\mathrm{dn}}`$ | `Link_ramp_limit_shut_down` over $`\Xi \times \mathcal{L}`$, `neutral` where the data has no row — most flow in the snapshot before a link stops, per unit of nominal power; no value means no limit | +| $`\mathrm{f}^{0}`$ | `Link_p_init` over $`\Xi \times \mathcal{L}`$, `neutral` where the data has no row — the flow a link brought into the horizon — PyPSA's `p_init`, read only where the link came in running; no value means it is unknown, so the link carries no ramp row at the first snapshot | + #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/load.md b/docs/examples/pypsa/load.md index e94172bb..7dcd61f4 100644 --- a/docs/examples/pypsa/load.md +++ b/docs/examples/pypsa/load.md @@ -64,6 +64,12 @@ expressions: adds_to: Bus_injection ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Load_injection` to | + #### Sets | Symbol | Meaning | @@ -81,12 +87,6 @@ expressions: | $`\mathrm{sgn}^{\mathrm{load}}`$ | `Load_sign` over $`\mathcal{D}`$ — the sign a load's demand enters its bus's balance with — PyPSA's `sign`, `-1` unless given, `1` for a load that feeds its bus. PyPSA refuses one that differs by scenario (`constants.py:43`) | | $`\mathrm{on}^{\mathrm{load}}`$ | `Load_active` over $`\mathcal{D}`$ — whether a load stands in the model — PyPSA's `active`. A load has no build year and no lifetime, so the flag holds in every snapshot. PyPSA refuses one that differs by scenario (`constants.py:51`) | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Load_injection` to | - #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/network.md b/docs/examples/pypsa/network.md index ea0647a4..7529fba0 100644 --- a/docs/examples/pypsa/network.md +++ b/docs/examples/pypsa/network.md @@ -45,19 +45,19 @@ constraints: expression: Bus_injection == 0 ``` -#### Sets +#### Given | Symbol | Meaning | |---|---| -| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | -| $`\mathcal{T}`$ | index $`t`$ — `snapshot` — dispatch periods | -| $`\mathcal{N}`$ | index $`n`$ — `bus` — network nodes | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression another file defines — what every component puts into a bus, less what it takes out of it; PyPSA writes each term into the balance, and a load on its right-hand side | -#### Given +#### Sets | Symbol | Meaning | |---|---| -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression another file defines — what every component puts into a bus, less what it takes out of it; PyPSA writes each term into the balance, and a load on its right-hand side | +| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | +| $`\mathcal{T}`$ | index $`t`$ — `snapshot` — dispatch periods | +| $`\mathcal{N}`$ | index $`n`$ — `bus` — network nodes | #### Subject to diff --git a/docs/examples/pypsa/power_flow.md b/docs/examples/pypsa/power_flow.md index 16c3624d..faa3e357 100644 --- a/docs/examples/pypsa/power_flow.md +++ b/docs/examples/pypsa/power_flow.md @@ -47,19 +47,19 @@ constraints: expression: Cycle_angle_sum == 0 ``` -#### Sets +#### Given | Symbol | Meaning | |---|---| -| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | -| $`\mathcal{T}`$ | index $`t`$ — `snapshot` — dispatch periods | -| $`\mathcal{C}`$ | index $`c`$ — `cycle` — independent cycles of the passive network graph — the cycle basis, data prep. Each period has its own basis, of the branches that stand in it; a label is a position in that period's basis, so one label names a different cycle in another period | +| $`\mathit{Cycle\_angle\_sum}`$ | `Cycle_angle_sum` over $`\Xi \times \mathcal{T} \times \mathcal{C}`$, an expression another file defines — the voltage angle differences around a cycle: every branch flow times its cycle weight, and every transformer phase shift | -#### Given +#### Sets | Symbol | Meaning | |---|---| -| $`\mathit{Cycle\_angle\_sum}`$ | `Cycle_angle_sum` over $`\Xi \times \mathcal{T} \times \mathcal{C}`$, an expression another file defines — the voltage angle differences around a cycle: every branch flow times its cycle weight, and every transformer phase shift | +| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | +| $`\mathcal{T}`$ | index $`t`$ — `snapshot` — dispatch periods | +| $`\mathcal{C}`$ | index $`c`$ — `cycle` — independent cycles of the passive network graph — the cycle basis, data prep. Each period has its own basis, of the branches that stand in it; a label is a position in that period's basis, so one label names a different cycle in another period | #### Subject to diff --git a/docs/examples/pypsa/process.md b/docs/examples/pypsa/process.md index 89748d1e..04a36eef 100644 --- a/docs/examples/pypsa/process.md +++ b/docs/examples/pypsa/process.md @@ -320,6 +320,25 @@ assumptions: `CVaR_omega` row only where a risk preference is set ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{com}^{z}`$ | `Process_committable` over $`\mathcal{J}`$, data another file declares | +| $`\gamma^{z}`$ | `Process_maintenance_pu` over $`\Xi \times \mathcal{J}`$, data another file declares | +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | +| $`\mu^{z}`$ | `Process_maintenance` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | +| $`\mu^{z,\mathrm{nom}}`$ | `Process_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Process_tech_capacity_expansion` to | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Process_opex` to | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Process_capex` to | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Process_additions` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Process_injection` to | + #### Sets | Symbol | Meaning | @@ -367,25 +386,6 @@ assumptions: | $`N^{z}`$ | `Process_n_mod` over $`\mathcal{J}`$ — `Process-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | | $`Z`$ | `Process_p_nom_ext` over $`\mathcal{J}`$ — `Process-p_nom` — nominal internal power where it is a decision; the parameter of the same PyPSA name carries the fixed regime | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{com}^{z}`$ | `Process_committable` over $`\mathcal{J}`$, data another file declares | -| $`\gamma^{z}`$ | `Process_maintenance_pu` over $`\Xi \times \mathcal{J}`$, data another file declares | -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{gen}}`$ | `snapshot_weightings_generators` over $`\mathcal{T}`$, data another file declares | -| $`\mu^{z}`$ | `Process_maintenance` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | -| $`\mu^{z,\mathrm{nom}}`$ | `Process_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Process_tech_capacity_expansion` to | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Process_opex` to | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Process_capex` to | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Process_additions` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Process_injection` to | - #### Definitions | Symbol | Meaning | @@ -467,6 +467,26 @@ Z_{j} = \mathrm{z}^{\mathrm{mod}}_{j} \cdot N^{z}_{j} \qquad \forall\, j \in \ma z_{\xi,t,j} = \mathrm{z}^{\mathrm{set}}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{z}^{\mathrm{set}}_{\xi,t,j} \text{ is defined} \wedge \mathrm{on}^{z}_{t,j} ``` +#### Variable domains + +**`Process_p`** + +```math +z_{\xi,t,j} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z}_{t,j} +``` + +**`Process_n_mod`** + +```math +N^{z}_{j} \ge 0, N^{z}_{j} \in \mathbb{Z} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{z}_{t,j} \} \rvert > 0 +``` + +**`Process_p_nom_ext`** + +```math +Z_{j} \in \mathbb{R} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} +``` + #### Definitions **`Process_p_nom_effective`** @@ -525,26 +545,6 @@ z_{\xi,t,j} = \mathrm{z}^{\mathrm{set}}_{\xi,t,j} \qquad \forall\, \xi \in \Xi,\ \mathrm{on}^{z,\mathrm{com}}_{t,j} \iff \mathrm{com}^{z}_{j} \wedge \mathrm{on}^{z}_{t,j} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} ``` -#### Variable domains - -**`Process_p`** - -```math -z_{\xi,t,j} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z}_{t,j} -``` - -**`Process_n_mod`** - -```math -N^{z}_{j} \ge 0, N^{z}_{j} \in \mathbb{Z} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{z}_{t,j} \} \rvert > 0 -``` - -**`Process_p_nom_ext`** - -```math -Z_{j} \in \mathbb{R} \qquad \forall\, j \in \mathcal{J} \,:\, \mathrm{ext}^{z}_{j} -``` - #### Assumptions **`Process_output_delay_under_uniform_weighting`** diff --git a/docs/examples/pypsa/process_commitment.md b/docs/examples/pypsa/process_commitment.md index 685a6eb8..223065d1 100644 --- a/docs/examples/pypsa/process_commitment.md +++ b/docs/examples/pypsa/process_commitment.md @@ -304,6 +304,29 @@ constraints: expression: Process_shut_down <= Process_n_mod ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{z}^{\mathrm{nom}}`$ | `Process_p_nom` over $`\Xi \times \mathcal{J}`$, data another file declares | +| $`\mathrm{ext}^{z}`$ | `Process_p_nom_extendable` over $`\mathcal{J}`$, data another file declares | +| $`\underline{\mathrm{z}}`$ | `Process_p_min_pu` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, data another file declares | +| $`\overline{\mathrm{z}}`$ | `Process_p_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, data another file declares | +| $`\mathrm{z}^{\mathrm{mod}}`$ | `Process_p_nom_mod` over $`\mathcal{J}`$, data another file declares | +| $`\mathrm{N}^{z,\mathrm{fix}}`$ | `Process_modules_installed` over $`\Xi \times \mathcal{J}`$, data another file declares | +| $`\mathrm{nonneg}^{z}`$ | `Process_p_min_pu_nonneg` over $`\mathcal{J}`$, data another file declares | +| $`\gamma^{z}`$ | `Process_maintenance_pu` over $`\Xi \times \mathcal{J}`$, data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{on}^{z}`$ | `Process_active` over $`\mathcal{T} \times \mathcal{J}`$, data another file declares | +| $`z`$ | `Process_p` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | +| $`N^{z}`$ | `Process_n_mod` over $`\mathcal{J}`$ | +| $`\mu^{z,\mathrm{nom}}`$ | `Process_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | +| $`\mu^{z,u}`$ | `Process_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | +| $`Z`$ | `Process_p_nom_ext` over $`\mathcal{J}`$ | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Process_commitment_opex` to | +| $`\mathrm{on}^{z,\mathrm{com}}`$ | `Process_committed` over $`\mathcal{T} \times \mathcal{J}`$, a mask another file defines | + #### Sets | Symbol | Meaning | @@ -336,29 +359,6 @@ constraints: | $`\mathit{up}^{z}`$ | `Process_start_up` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ — `Process-start_up` — how much of a committable process turns on this snapshot, capped as the status is | | $`\mathit{dn}^{z}`$ | `Process_shut_down` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ — `Process-shut_down` — how much of a committable process turns off this snapshot, capped as the status is | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{z}^{\mathrm{nom}}`$ | `Process_p_nom` over $`\Xi \times \mathcal{J}`$, data another file declares | -| $`\mathrm{ext}^{z}`$ | `Process_p_nom_extendable` over $`\mathcal{J}`$, data another file declares | -| $`\underline{\mathrm{z}}`$ | `Process_p_min_pu` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, data another file declares | -| $`\overline{\mathrm{z}}`$ | `Process_p_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, data another file declares | -| $`\mathrm{z}^{\mathrm{mod}}`$ | `Process_p_nom_mod` over $`\mathcal{J}`$, data another file declares | -| $`\mathrm{N}^{z,\mathrm{fix}}`$ | `Process_modules_installed` over $`\Xi \times \mathcal{J}`$, data another file declares | -| $`\mathrm{nonneg}^{z}`$ | `Process_p_min_pu_nonneg` over $`\mathcal{J}`$, data another file declares | -| $`\gamma^{z}`$ | `Process_maintenance_pu` over $`\Xi \times \mathcal{J}`$, data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{on}^{z}`$ | `Process_active` over $`\mathcal{T} \times \mathcal{J}`$, data another file declares | -| $`z`$ | `Process_p` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | -| $`N^{z}`$ | `Process_n_mod` over $`\mathcal{J}`$ | -| $`\mu^{z,\mathrm{nom}}`$ | `Process_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | -| $`\mu^{z,u}`$ | `Process_maintenance_status` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$ | -| $`Z`$ | `Process_p_nom_ext` over $`\mathcal{J}`$ | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Process_commitment_opex` to | -| $`\mathrm{on}^{z,\mathrm{com}}`$ | `Process_committed` over $`\mathcal{T} \times \mathcal{J}`$, a mask another file defines | - #### Definitions | Symbol | Meaning | @@ -497,51 +497,51 @@ u^{z}_{\xi,t,j} \le N^{z}_{j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ \mathit{dn}^{z}_{\xi,t,j} \le N^{z}_{j} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} \wedge \mathrm{ext}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 ``` -#### Definitions +#### Variable domains -**`Process_previous_status`** +**`Process_status`** ```math -\overleftarrow{u}^{z}_{\xi,t,j} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{z}_{t - 1,j} \\ \overleftarrow{u}^{\circ z}_{\xi,t,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +u^{z}_{\xi,t,j} \ge 0, u^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} ``` -**`Process_status_carried_over`** +**`Process_start_up`** ```math -\overleftarrow{u}^{\circ z}_{\xi,t,j} = \begin{cases} \mathrm{u}^{z,0}_{\xi,j} & \text{if } \mathrm{pos}(t) = 0 \\ u^{z}_{\xi,t - 1,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} +\mathit{up}^{z}_{\xi,t,j} \ge 0, \mathit{up}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} ``` -**`Process_commitment_opex`** +**`Process_shut_down`** ```math -\mathit{Process\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} u^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{on}}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{up}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{up}}_{\xi,t,j} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{dn}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{dn}}_{\xi,t,j} \qquad \forall\, \xi \in \Xi +\mathit{dn}^{z}_{\xi,t,j} \ge 0, \mathit{dn}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} ``` -#### Masks +#### Definitions -**`Process_com_ext`** +**`Process_previous_status`** ```math -\mathrm{on}^{z,\mathrm{com,ext}}_{t,j} \iff \mathrm{com}^{z}_{j} \wedge \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} +\overleftarrow{u}^{z}_{\xi,t,j} = \begin{cases} 0 & \text{if } \mathrm{pos}(t) > 0 \wedge \neg \mathrm{on}^{z}_{t - 1,j} \\ \overleftarrow{u}^{\circ z}_{\xi,t,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -#### Variable domains - -**`Process_status`** +**`Process_status_carried_over`** ```math -u^{z}_{\xi,t,j} \ge 0, u^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} +\overleftarrow{u}^{\circ z}_{\xi,t,j} = \begin{cases} \mathrm{u}^{z,0}_{\xi,j} & \text{if } \mathrm{pos}(t) = 0 \\ u^{z}_{\xi,t - 1,j} & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} ``` -**`Process_start_up`** +**`Process_commitment_opex`** ```math -\mathit{up}^{z}_{\xi,t,j} \ge 0, \mathit{up}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} +\mathit{Process\_commitment\_opex}_{\xi} = \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} u^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{on}}_{\xi,t,j} \cdot \mathrm{w}_{t} \cdot \mathrm{w}^{y}_{\mathrm{snapshot\_period}(t)} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{up}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{up}}_{\xi,t,j} + \sum_{t \in \mathcal{T}} \sum_{j \in \mathcal{J}} \mathit{dn}^{z}_{\xi,t,j} \cdot \mathrm{c}^{z,\mathrm{dn}}_{\xi,t,j} \qquad \forall\, \xi \in \Xi ``` -**`Process_shut_down`** +#### Masks + +**`Process_com_ext`** ```math -\mathit{dn}^{z}_{\xi,t,j} \ge 0, \mathit{dn}^{z}_{\xi,t,j} \in \mathbb{Z} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{on}^{z,\mathrm{com}}_{t,j} +\mathrm{on}^{z,\mathrm{com,ext}}_{t,j} \iff \mathrm{com}^{z}_{j} \wedge \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} ``` diff --git a/docs/examples/pypsa/process_maintenance.md b/docs/examples/pypsa/process_maintenance.md index 0fcf3a85..7242e595 100644 --- a/docs/examples/pypsa/process_maintenance.md +++ b/docs/examples/pypsa/process_maintenance.md @@ -246,6 +246,21 @@ assumptions: (`constraints.py:504-507`) ``` +#### 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}`$ | +| $`\mathrm{on}^{z,\mathrm{com}}`$ | `Process_committed` over $`\mathcal{T} \times \mathcal{J}`$, a mask another file defines | + #### Sets | Symbol | Meaning | @@ -273,21 +288,6 @@ assumptions: | $`\mu^{z,\mathrm{nom}}`$ | `Process_maintenance_capacity` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, `neutral` where the mask leaves it out — `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}`$, `neutral` where the mask leaves it out — `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}`$ | -| $`\mathrm{on}^{z,\mathrm{com}}`$ | `Process_committed` over $`\mathcal{T} \times \mathcal{J}`$, a mask another file defines | - #### Masks | Symbol | Meaning | @@ -374,14 +374,6 @@ assumptions: \mu^{z,u}_{\xi,t,j} \ge u^{z}_{\xi,t,j} - \frac{\overline{\mathrm{z}}^{\mathrm{nom}}_{\xi,j}}{\mathrm{z}^{\mathrm{mod}}_{j}} \cdot \left( 1 - \mu^{z}_{\xi,t,j} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z,\mathrm{com}}_{t,j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 ``` -#### Masks - -**`Process_maint_ext`** - -```math -\mathrm{on}^{z,\mathrm{mnt,ext}}_{t,j} \iff \mathrm{mnt}^{z}_{j} \wedge \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{com}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} -``` - #### Variable domains **`Process_maintenance`** @@ -408,6 +400,14 @@ assumptions: \mu^{z,u}_{\xi,t,j} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ j \in \mathcal{J} \,:\, \mathrm{mnt}^{z}_{j} \wedge \mathrm{on}^{z,\mathrm{com}}_{t,j} \wedge \neg \left( \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \right) ``` +#### Masks + +**`Process_maint_ext`** + +```math +\mathrm{on}^{z,\mathrm{mnt,ext}}_{t,j} \iff \mathrm{mnt}^{z}_{j} \wedge \mathrm{ext}^{z}_{j} \wedge \neg \left( \mathrm{com}^{z}_{j} \wedge \mathrm{z}^{\mathrm{mod}}_{j} > 0 \right) \wedge \mathrm{on}^{z}_{t,j} \qquad \forall\, t \in \mathcal{T},\ j \in \mathcal{J} +``` + #### Assumptions **`Process_maintenance_events_positive`** diff --git a/docs/examples/pypsa/process_ramping.md b/docs/examples/pypsa/process_ramping.md index 46cc03ca..6b833ed2 100644 --- a/docs/examples/pypsa/process_ramping.md +++ b/docs/examples/pypsa/process_ramping.md @@ -255,25 +255,6 @@ assumptions: spec does not state that row, so it refuses the data ``` -#### Sets - -| Symbol | Meaning | -|---|---| -| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | -| $`\mathcal{T}`$ | index $`t`$ — `snapshot` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — dispatch periods | -| $`\mathcal{J}`$ | index $`j`$ — `process` — generalized multi-port converters, each with an internal power that every port draws or delivers at its own rate | -| $`\mathcal{Y}`$ | index $`y`$ — `period` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — investment periods — PyPSA's `investment_periods` | - -#### Parameters - -| Symbol | Meaning | -|---|---| -| $`\mathrm{ru}^{z}`$ | `Process_ramp_limit_up` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, `neutral` where the data has no row — most a process may raise its internal power between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | -| $`\mathrm{rd}^{z}`$ | `Process_ramp_limit_down` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, `neutral` where the data has no row — most a process may lower its internal power between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | -| $`\mathrm{ru}^{z,\mathrm{up}}`$ | `Process_ramp_limit_start_up` over $`\Xi \times \mathcal{J}`$, `neutral` where the data has no row — most internal power in the snapshot a process starts, per unit of nominal power; no value means no limit | -| $`\mathrm{rd}^{z,\mathrm{dn}}`$ | `Process_ramp_limit_shut_down` over $`\Xi \times \mathcal{J}`$, `neutral` where the data has no row — most internal power in the snapshot before a process stops, per unit of nominal power; no value means no limit | -| $`\mathrm{z}^{0}`$ | `Process_p_init` over $`\Xi \times \mathcal{J}`$, `neutral` where the data has no row — the internal power a process brought into the horizon — PyPSA's `p_init`, read only where the process came in running; no value means it is unknown, so the process carries no ramp row at the first snapshot | - #### Given | Symbol | Meaning | @@ -294,6 +275,25 @@ assumptions: | $`\widehat{\mathrm{z}}^{\mathrm{nom}}`$ | `Process_p_nom_committed` over $`\Xi \times \mathcal{J}`$, an expression another file defines | | $`\mathrm{on}^{z,\mathrm{com,ext}}`$ | `Process_com_ext` over $`\mathcal{T} \times \mathcal{J}`$, a mask another file defines | +#### Sets + +| Symbol | Meaning | +|---|---| +| $`\Xi`$ | index $`\xi`$ — `scenario` — the futures dispatch is chosen in, each with a weight | +| $`\mathcal{T}`$ | index $`t`$ — `snapshot` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — dispatch periods | +| $`\mathcal{J}`$ | index $`j`$ — `process` — generalized multi-port converters, each with an internal power that every port draws or delivers at its own rate | +| $`\mathcal{Y}`$ | index $`y`$ — `period` with $`\mathrm{snapshot\_period}: \mathcal{T} \to \mathcal{Y}`$ — investment periods — PyPSA's `investment_periods` | + +#### Parameters + +| Symbol | Meaning | +|---|---| +| $`\mathrm{ru}^{z}`$ | `Process_ramp_limit_up` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, `neutral` where the data has no row — most a process may raise its internal power between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | +| $`\mathrm{rd}^{z}`$ | `Process_ramp_limit_down` over $`\Xi \times \mathcal{T} \times \mathcal{J}`$, `neutral` where the data has no row — most a process may lower its internal power between snapshots, per unit of nominal power; no value means no limit — read at the later of the two snapshots, so the limit may change over time | +| $`\mathrm{ru}^{z,\mathrm{up}}`$ | `Process_ramp_limit_start_up` over $`\Xi \times \mathcal{J}`$, `neutral` where the data has no row — most internal power in the snapshot a process starts, per unit of nominal power; no value means no limit | +| $`\mathrm{rd}^{z,\mathrm{dn}}`$ | `Process_ramp_limit_shut_down` over $`\Xi \times \mathcal{J}`$, `neutral` where the data has no row — most internal power in the snapshot before a process stops, per unit of nominal power; no value means no limit | +| $`\mathrm{z}^{0}`$ | `Process_p_init` over $`\Xi \times \mathcal{J}`$, `neutral` where the data has no row — the internal power a process brought into the horizon — PyPSA's `p_init`, read only where the process came in running; no value means it is unknown, so the process carries no ramp row at the first snapshot | + #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/security.md b/docs/examples/pypsa/security.md index f0eff530..d9358a51 100644 --- a/docs/examples/pypsa/security.md +++ b/docs/examples/pypsa/security.md @@ -187,6 +187,21 @@ constraints: expression: Transformer_s_monitored + at(Transformer_BODF, by=snapshot_period[period]) * Outage_s <= Transformer_s_max_pu * Transformer_s_nom_ext ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{s}^{\mathrm{nom}}`$ | `Line_s_nom` over $`\Xi \times \mathcal{K}`$, data another file declares | +| $`\mathrm{ext}^{s}`$ | `Line_s_nom_extendable` over $`\mathcal{K}`$, data another file declares | +| $`\overline{\mathrm{s}}`$ | `Line_s_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{K}`$, data another file declares | +| $`\sigma^{\mathrm{nom}}`$ | `Transformer_s_nom` over $`\Xi \times \mathcal{M}`$, data another file declares | +| $`\mathrm{ext}^{\sigma}`$ | `Transformer_s_nom_extendable` over $`\mathcal{M}`$, data another file declares | +| $`\overline{\sigma}`$ | `Transformer_s_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{M}`$, data another file declares | +| $`S`$ | `Line_s_nom_ext` over $`\mathcal{K}`$ | +| $`\Sigma`$ | `Transformer_s_nom_ext` over $`\mathcal{M}`$ | +| $`\check{s}`$ | `Line_s_monitored` over $`\Xi \times \mathcal{T} \times \mathcal{K}`$, an expression another file defines | +| $`\check{\sigma}`$ | `Transformer_s_monitored` over $`\Xi \times \mathcal{T} \times \mathcal{M}`$, an expression another file defines | + #### Sets | Symbol | Meaning | @@ -205,21 +220,6 @@ constraints: | $`\beta`$ | `Line_BODF` over $`\mathcal{Y} \times \mathcal{K} \times \mathcal{K}^{\mathrm{out}}`$, `neutral` where the data has no row — the share of an outaged branch's flow a line takes on when that branch goes out — PyPSA's `BODF`, from the PTDF of the sub-network the period's active branches form, data prep; a row only where the line and the outage are active in the period and share a sub-network, -1 at the outaged line itself. The same in every scenario: PyPSA takes the factors of the first scenario (`abstract.py:534`) | | $`\beta^{\sigma}`$ | `Transformer_BODF` over $`\mathcal{Y} \times \mathcal{M} \times \mathcal{K}^{\mathrm{out}}`$, `neutral` where the data has no row — the share of an outaged branch's flow a transformer takes on when that branch goes out, as a line's; a row only where the transformer and the outage are active in the period and share a sub-network | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{s}^{\mathrm{nom}}`$ | `Line_s_nom` over $`\Xi \times \mathcal{K}`$, data another file declares | -| $`\mathrm{ext}^{s}`$ | `Line_s_nom_extendable` over $`\mathcal{K}`$, data another file declares | -| $`\overline{\mathrm{s}}`$ | `Line_s_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{K}`$, data another file declares | -| $`\sigma^{\mathrm{nom}}`$ | `Transformer_s_nom` over $`\Xi \times \mathcal{M}`$, data another file declares | -| $`\mathrm{ext}^{\sigma}`$ | `Transformer_s_nom_extendable` over $`\mathcal{M}`$, data another file declares | -| $`\overline{\sigma}`$ | `Transformer_s_max_pu` over $`\Xi \times \mathcal{T} \times \mathcal{M}`$, data another file declares | -| $`S`$ | `Line_s_nom_ext` over $`\mathcal{K}`$ | -| $`\Sigma`$ | `Transformer_s_nom_ext` over $`\mathcal{M}`$ | -| $`\check{s}`$ | `Line_s_monitored` over $`\Xi \times \mathcal{T} \times \mathcal{K}`$, an expression another file defines | -| $`\check{\sigma}`$ | `Transformer_s_monitored` over $`\Xi \times \mathcal{T} \times \mathcal{M}`$, an expression another file defines | - #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/settings.md b/docs/examples/pypsa/settings.md index 0cbbf587..17366c58 100644 --- a/docs/examples/pypsa/settings.md +++ b/docs/examples/pypsa/settings.md @@ -154,6 +154,19 @@ objective: expression: total_cost ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what a `primary_energy` row totals — weighted generator energy over the snapshots it counts, less the charge left in weighted storage at the close; the initial charge it is compared against is folded into the row's constant | +| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what an `operational_limit` row totals — the weighted energy its generators deliver over the snapshots it counts, plus what its non-cyclic storage draws down; the initial charge it draws from is folded into the row's constant | +| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what a `transmission_volume_expansion_limit` row totals — length times the chosen build of the row's branches | +| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what a `transmission_expansion_cost_limit` row totals — capital cost times the chosen build of the row's branches | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression another file defines — what a `tech_capacity_expansion_limit` row totals — the chosen build of the row's carrier-and-bus set | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression another file defines — what a future costs to run — every operating term, weighted by the snapshot's hours and its period, before the scenario's own weight; a start and a stop cost what they cost, unweighted, as PyPSA adds them (`optimize.py:415-432`) | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression another file defines — what the system costs — capacity once per active period at its expected cost over the scenarios, operation in expectation over the scenarios, and a share of it at the tail | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression another file defines — what a carrier adds in a period — every extendable component of that carrier, counting each build in the first period it stands in. Like PyPSA, it sums only the components that carry a carrier attribute, so a transformer, which has none, counts in no carrier | + #### Sets | Symbol | Meaning | @@ -178,19 +191,6 @@ objective: | $`\mathrm{lossy}`$ | `transmission_losses` (scalar) — whether the network dissipates transmission losses — PyPSA's `transmission_losses` read as a flag; its mode, tangents or secants, only decides how data prep fills the `segment` axis, the rows are the same; false with no segments is a lossless run. A security-constrained run over a network with passive branches builds no loss: PyPSA does not hand the keyword to `create_model` (`abstract.py:528-532`) but to the solver (`:548`), so data prep feeds false there | | $`\mathrm{in}`$ | `GlobalConstraint_counts_snapshot` over $`\Xi \times \mathcal{G} \times \mathcal{T}`$, `neutral` where the data has no row — whether a row counts a snapshot in a scenario — PyPSA's `investment_period`: every snapshot where the row names none, and only that period's where it names one, data prep. A row that names a period the run does not model has no label here, as PyPSA skips it (`global_constraints.py:372`); PyPSA reads the column only under `multi_investment_periods`, and fails on a row that names a period without it (`global_constraints.py:364-369`) | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what a `primary_energy` row totals — weighted generator energy over the snapshots it counts, less the charge left in weighted storage at the close; the initial charge it is compared against is folded into the row's constant | -| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what an `operational_limit` row totals — the weighted energy its generators deliver over the snapshots it counts, plus what its non-cyclic storage draws down; the initial charge it draws from is folded into the row's constant | -| $`\mathit{transmission\_volume\_expansion}`$ | `transmission_volume_expansion` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what a `transmission_volume_expansion_limit` row totals — length times the chosen build of the row's branches | -| $`\mathit{transmission\_expansion\_cost}`$ | `transmission_expansion_cost` over $`\Xi \times \mathcal{G}`$, an expression another file defines — what a `transmission_expansion_cost_limit` row totals — capital cost times the chosen build of the row's branches | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression another file defines — what a `tech_capacity_expansion_limit` row totals — the chosen build of the row's carrier-and-bus set | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression another file defines — what a future costs to run — every operating term, weighted by the snapshot's hours and its period, before the scenario's own weight; a start and a stop cost what they cost, unweighted, as PyPSA adds them (`optimize.py:415-432`) | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression another file defines — what the system costs — capacity once per active period at its expected cost over the scenarios, operation in expectation over the scenarios, and a share of it at the tail | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression another file defines — what a carrier adds in a period — every extendable component of that carrier, counting each build in the first period it stands in. Like PyPSA, it sums only the components that carry a carrier attribute, so a transformer, which has none, counts in no carrier | - #### Definitions | Symbol | Meaning | diff --git a/docs/examples/pypsa/storage_unit.md b/docs/examples/pypsa/storage_unit.md index 77b6fdc5..cdab489e 100644 --- a/docs/examples/pypsa/storage_unit.md +++ b/docs/examples/pypsa/storage_unit.md @@ -528,6 +528,25 @@ assumptions: `CVaR_omega` row only where a risk preference is set ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{yr}}`$ | `period_weight_years` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{sto}}`$ | `snapshot_weightings_stores` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{in}`$ | `GlobalConstraint_counts_snapshot` over $`\Xi \times \mathcal{G} \times \mathcal{T}`$, data another file declares | +| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression this file adds `StorageUnit_primary_energy` to | +| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression this file adds `StorageUnit_operational_limit` to | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `StorageUnit_tech_capacity_expansion` to | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `StorageUnit_opex` to | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `StorageUnit_capex` to | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `StorageUnit_additions` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `StorageUnit_injection` to | + #### Sets | Symbol | Meaning | @@ -591,25 +610,6 @@ assumptions: | $`H`$ | `StorageUnit_p_nom_ext` over $`\mathcal{S}`$ — `StorageUnit-p_nom` — nominal power where it is a decision; the parameter of the same PyPSA name carries the fixed regime | | $`N^{h}`$ | `StorageUnit_n_mod` over $`\mathcal{S}`$ — `StorageUnit-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{yr}}`$ | `period_weight_years` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{sto}}`$ | `snapshot_weightings_stores` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{in}`$ | `GlobalConstraint_counts_snapshot` over $`\Xi \times \mathcal{G} \times \mathcal{T}`$, data another file declares | -| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression this file adds `StorageUnit_primary_energy` to | -| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression this file adds `StorageUnit_operational_limit` to | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `StorageUnit_tech_capacity_expansion` to | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `StorageUnit_opex` to | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `StorageUnit_capex` to | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `StorageUnit_additions` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `StorageUnit_injection` to | - #### Definitions | Symbol | Meaning | @@ -770,6 +770,44 @@ h^{-}_{\xi,t,s} = \mathrm{h}^{-,\mathrm{set}}_{\xi,t,s} \qquad \forall\, \xi \in \mathit{soc}_{\xi,t,s} = \mathrm{soc}^{\mathrm{set}}_{\xi,t,s} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{soc}^{\mathrm{set}}_{\xi,t,s} \text{ is defined} \wedge \mathrm{on}^{h}_{t,s} ``` +#### Variable domains + +**`StorageUnit_p_dispatch`** + +```math +h^{+}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} +``` + +**`StorageUnit_p_store`** + +```math +h^{-}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} +``` + +**`StorageUnit_state_of_charge`** + +```math +\mathit{soc}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} +``` + +**`StorageUnit_spill`** + +```math +0 \le \mathit{spill}_{\xi,t,s} \le \mathrm{inflow}_{\xi,t,s} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{inflow}_{\xi,t,s} > 0 \wedge \mathrm{on}^{h}_{t,s} +``` + +**`StorageUnit_p_nom_ext`** + +```math +H_{s} \in \mathbb{R} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} +``` + +**`StorageUnit_n_mod`** + +```math +N^{h}_{s} \ge 0, N^{h}_{s} \in \mathbb{Z} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} \wedge \mathrm{h}^{\mathrm{mod}}_{s} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{h}_{t,s} \} \rvert > 0 +``` + #### Definitions **`StorageUnit_charge_carried_in`** @@ -846,44 +884,6 @@ h^{-}_{\xi,t,s} = \mathrm{h}^{-,\mathrm{set}}_{\xi,t,s} \qquad \forall\, \xi \in \mathrm{on}^{h,\mathrm{ext}}_{t,s} \iff \mathrm{ext}^{h}_{s} \wedge \mathrm{on}^{h}_{t,s} \qquad \forall\, t \in \mathcal{T},\ s \in \mathcal{S} ``` -#### Variable domains - -**`StorageUnit_p_dispatch`** - -```math -h^{+}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} -``` - -**`StorageUnit_p_store`** - -```math -h^{-}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} -``` - -**`StorageUnit_state_of_charge`** - -```math -\mathit{soc}_{\xi,t,s} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{on}^{h}_{t,s} -``` - -**`StorageUnit_spill`** - -```math -0 \le \mathit{spill}_{\xi,t,s} \le \mathrm{inflow}_{\xi,t,s} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ s \in \mathcal{S} \,:\, \mathrm{inflow}_{\xi,t,s} > 0 \wedge \mathrm{on}^{h}_{t,s} -``` - -**`StorageUnit_p_nom_ext`** - -```math -H_{s} \in \mathbb{R} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} -``` - -**`StorageUnit_n_mod`** - -```math -N^{h}_{s} \ge 0, N^{h}_{s} \in \mathbb{Z} \qquad \forall\, s \in \mathcal{S} \,:\, \mathrm{ext}^{h}_{s} \wedge \mathrm{h}^{\mathrm{mod}}_{s} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{h}_{t,s} \} \rvert > 0 -``` - #### Assumptions **`StorageUnit_stands_in_one_run`** diff --git a/docs/examples/pypsa/store.md b/docs/examples/pypsa/store.md index e6cb2a7f..f2b56309 100644 --- a/docs/examples/pypsa/store.md +++ b/docs/examples/pypsa/store.md @@ -411,6 +411,25 @@ assumptions: `CVaR_omega` row only where a risk preference is set ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | +| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{yr}}`$ | `period_weight_years` over $`\mathcal{Y}`$, data another file declares | +| $`\mathrm{w}^{\mathrm{sto}}`$ | `snapshot_weightings_stores` over $`\mathcal{T}`$, data another file declares | +| $`\mathrm{in}`$ | `GlobalConstraint_counts_snapshot` over $`\Xi \times \mathcal{G} \times \mathcal{T}`$, data another file declares | +| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Store_primary_energy` to | +| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Store_operational_limit` to | +| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Store_tech_capacity_expansion` to | +| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Store_opex` to | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Store_capex` to | +| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Store_additions` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Store_injection` to | + #### Sets | Symbol | Meaning | @@ -465,25 +484,6 @@ assumptions: | $`E`$ | `Store_e_nom_ext` over $`\mathcal{V}`$ — `Store-e_nom` — nominal capacity where it is a decision; the parameter of the same PyPSA name carries the fixed regime | | $`N^{e}`$ | `Store_n_mod` over $`\mathcal{V}`$ — `Store-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\mathrm{w}`$ | `snapshot_weightings_objective` over $`\mathcal{T}`$, data another file declares | -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\omega`$ | `CVaR_omega` (scalar), data another file declares | -| $`\mathrm{w}^{y}`$ | `period_weight_objective` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{yr}}`$ | `period_weight_years` over $`\mathcal{Y}`$, data another file declares | -| $`\mathrm{w}^{\mathrm{sto}}`$ | `snapshot_weightings_stores` over $`\mathcal{T}`$, data another file declares | -| $`\mathrm{in}`$ | `GlobalConstraint_counts_snapshot` over $`\Xi \times \mathcal{G} \times \mathcal{T}`$, data another file declares | -| $`\mathit{primary\_energy}`$ | `primary_energy` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Store_primary_energy` to | -| $`\mathit{operational\_limit}`$ | `operational_limit` over $`\Xi \times \mathcal{G}`$, an expression this file adds `Store_operational_limit` to | -| $`\mathit{tech\_capacity\_expansion}`$ | `tech_capacity_expansion` over $`\mathcal{G}`$, an expression this file adds `Store_tech_capacity_expansion` to | -| $`\mathit{scenario\_opex}`$ | `scenario_opex` over $`\Xi`$, an expression this file adds `Store_opex` to | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Store_capex` to | -| $`\mathit{Carrier\_additions}`$ | `Carrier_additions` over $`\mathcal{Y} \times \mathcal{I}`$, an expression this file adds `Store_additions` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Store_injection` to | - #### Definitions | Symbol | Meaning | @@ -577,6 +577,32 @@ e_{\xi,t,v} = \mathrm{e}^{\mathrm{set}}_{\xi,t,v} \qquad \forall\, \xi \in \Xi,\ q_{\xi,t,v} = \mathrm{q}^{\mathrm{set}}_{\xi,t,v} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{q}^{\mathrm{set}}_{\xi,t,v} \text{ is defined} \wedge \mathrm{on}^{e}_{t,v} ``` +#### Variable domains + +**`Store_e`** + +```math +e_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} +``` + +**`Store_p`** + +```math +q_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} +``` + +**`Store_e_nom_ext`** + +```math +E_{v} \in \mathbb{R} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} +``` + +**`Store_n_mod`** + +```math +N^{e}_{v} \ge 0, N^{e}_{v} \in \mathbb{Z} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} \wedge \mathrm{e}^{\mathrm{mod}}_{v} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{e}_{t,v} \} \rvert > 0 +``` + #### Definitions **`Store_energy_carried_in`** @@ -639,32 +665,6 @@ q_{\xi,t,v} = \mathrm{q}^{\mathrm{set}}_{\xi,t,v} \qquad \forall\, \xi \in \Xi,\ \mathit{Store\_injection}_{\xi,t,n} = \sum_{v \in \mathcal{V} \,:\, \mathrm{Store\_bus}(v) = n} \mathrm{sgn}^{q}_{v} \cdot q_{\xi,t,v} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -#### Variable domains - -**`Store_e`** - -```math -e_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} -``` - -**`Store_p`** - -```math -q_{\xi,t,v} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ v \in \mathcal{V} \,:\, \mathrm{on}^{e}_{t,v} -``` - -**`Store_e_nom_ext`** - -```math -E_{v} \in \mathbb{R} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} -``` - -**`Store_n_mod`** - -```math -N^{e}_{v} \ge 0, N^{e}_{v} \in \mathbb{Z} \qquad \forall\, v \in \mathcal{V} \,:\, \mathrm{ext}^{e}_{v} \wedge \mathrm{e}^{\mathrm{mod}}_{v} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{e}_{t,v} \} \rvert > 0 -``` - #### Assumptions **`Store_stands_in_one_run`** diff --git a/docs/examples/pypsa/transformer.md b/docs/examples/pypsa/transformer.md index 26c999a5..a9814d2a 100644 --- a/docs/examples/pypsa/transformer.md +++ b/docs/examples/pypsa/transformer.md @@ -359,6 +359,16 @@ constraints: expression: Transformer_loss - Transformer_loss_slope * Transformer_s >= Transformer_loss_offset ``` +#### Given + +| Symbol | Meaning | +|---|---| +| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | +| $`\mathrm{lossy}`$ | `transmission_losses` (scalar), data another file declares | +| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Transformer_capex` to | +| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Transformer_injection` to | +| $`\mathit{Cycle\_angle\_sum}`$ | `Cycle_angle_sum` over $`\Xi \times \mathcal{T} \times \mathcal{C}`$, an expression this file adds `Transformer_angle_sum` to | + #### Sets | Symbol | Meaning | @@ -409,16 +419,6 @@ constraints: | $`\Sigma`$ | `Transformer_s_nom_ext` over $`\mathcal{M}`$ — `Transformer-s_nom` — nominal apparent power where it is a decision; the parameter of the same PyPSA name carries the fixed regime | | $`N^{\sigma}`$ | `Transformer_n_mod` over $`\mathcal{M}`$ — `Transformer-n_mod` — how many modules of an extendable modular build; none for a build that stands in no snapshot | -#### Given - -| Symbol | Meaning | -|---|---| -| $`\pi`$ | `scenario_weight` over $`\Xi`$, data another file declares | -| $`\mathrm{lossy}`$ | `transmission_losses` (scalar), data another file declares | -| $`\mathit{total\_cost}`$ | `total_cost` (scalar), an expression this file adds `Transformer_capex` to | -| $`\mathit{Bus\_injection}`$ | `Bus_injection` over $`\Xi \times \mathcal{T} \times \mathcal{N}`$, an expression this file adds `Transformer_injection` to | -| $`\mathit{Cycle\_angle\_sum}`$ | `Cycle_angle_sum` over $`\Xi \times \mathcal{T} \times \mathcal{C}`$, an expression this file adds `Transformer_angle_sum` to | - #### Definitions | Symbol | Meaning | @@ -534,69 +534,69 @@ Upright is what the data supplies — a parameter such as $`\mathrm{Transformer\ \ell^{\sigma}_{\xi,t,m} - \mathrm{a}^{\sigma}_{\xi,t,m,s} \cdot \sigma_{\xi,t,m} \ge \mathrm{b}^{\sigma}_{\xi,t,m,s} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M},\ s \in \mathcal{S} \,:\, \mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} ``` -#### Definitions +#### Variable domains -**`Transformer_capex`** +**`Transformer_s`** ```math -\mathit{Transformer\_capex} = \sum_{\xi \in \Xi,\ m \in \mathcal{M}} \pi_{\xi} \cdot \Sigma_{m} \cdot \mathrm{c}^{\mathrm{cap},\sigma}_{\xi,m} \cdot \mathrm{W}^{\sigma}_{m} +\sigma_{\xi,t,m} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma}_{t,m} ``` -**`Transformer_s_monitored`** +**`Transformer_loss`** ```math -\check{\sigma}_{\xi,t,m} = \begin{cases} \sigma_{\xi,t,m} & \text{if } \mathrm{on}^{\sigma}_{t,m} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} +\ell^{\sigma}_{\xi,t,m} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} ``` -**`Transformer_injection`** +**`Transformer_phase_shift`** ```math -\mathit{Transformer\_injection}_{\xi,t,n} = -\left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \sigma_{\xi,t,m} \right) + \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \sigma_{\xi,t,m} - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} +\mathrm{Transformer\_phase\_shift\_min}_{m} \le \mathit{Transformer\_phase\_shift}_{\xi,t,m} \le \mathrm{Transformer\_phase\_shift\_max}_{m} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{Transformer\_phase\_shift\_varying}_{m} \wedge \mathrm{on}^{\sigma}_{t,m} ``` -**`Transformer_angle_sum`** +**`Transformer_s_nom_ext`** ```math -\mathit{Transformer\_angle\_sum}_{\xi,t,c} = \sum_{m \in \mathcal{M}} \sigma_{\xi,t,m} \cdot \mathrm{x}^{\sigma}_{\mathrm{snapshot\_period}(t),m,c} + \sum_{m \in \mathcal{M}} \vartheta_{t,m,c} + \sum_{m \in \mathcal{M}} \mathit{Transformer\_phase\_shift}_{\xi,t,m} \cdot \mathrm{Transformer\_phase\_shift\_cycle\_weight}_{\mathrm{snapshot\_period}(t),m,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} +\Sigma_{m} \in \mathbb{R} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} ``` -#### Masks - -**`Transformer_lossy`** +**`Transformer_n_mod`** ```math -\mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} \iff \mathrm{lossy} \wedge \mathrm{on}^{\sigma}_{t,m} \qquad \forall\, t \in \mathcal{T},\ m \in \mathcal{M} +N^{\sigma}_{m} \ge 0, N^{\sigma}_{m} \in \mathbb{Z} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} \wedge \sigma^{\mathrm{mod}}_{m} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{\sigma}_{t,m} \} \rvert > 0 ``` -#### Variable domains +#### Definitions -**`Transformer_s`** +**`Transformer_capex`** ```math -\sigma_{\xi,t,m} \in \mathbb{R} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma}_{t,m} +\mathit{Transformer\_capex} = \sum_{\xi \in \Xi,\ m \in \mathcal{M}} \pi_{\xi} \cdot \Sigma_{m} \cdot \mathrm{c}^{\mathrm{cap},\sigma}_{\xi,m} \cdot \mathrm{W}^{\sigma}_{m} ``` -**`Transformer_loss`** +**`Transformer_s_monitored`** ```math -\ell^{\sigma}_{\xi,t,m} \ge 0 \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} +\check{\sigma}_{\xi,t,m} = \begin{cases} \sigma_{\xi,t,m} & \text{if } \mathrm{on}^{\sigma}_{t,m} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} ``` -**`Transformer_phase_shift`** +**`Transformer_injection`** ```math -\mathrm{Transformer\_phase\_shift\_min}_{m} \le \mathit{Transformer\_phase\_shift}_{\xi,t,m} \le \mathrm{Transformer\_phase\_shift\_max}_{m} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ m \in \mathcal{M} \,:\, \mathrm{Transformer\_phase\_shift\_varying}_{m} \wedge \mathrm{on}^{\sigma}_{t,m} +\mathit{Transformer\_injection}_{\xi,t,n} = -\left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \sigma_{\xi,t,m} \right) + \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \sigma_{\xi,t,m} - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus0}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) - 0.5 \cdot \left( \sum_{m \in \mathcal{M} \,:\, \mathrm{Transformer\_bus1}(m) = n} \ell^{\sigma}_{\xi,t,m} \right) \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ n \in \mathcal{N} ``` -**`Transformer_s_nom_ext`** +**`Transformer_angle_sum`** ```math -\Sigma_{m} \in \mathbb{R} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} +\mathit{Transformer\_angle\_sum}_{\xi,t,c} = \sum_{m \in \mathcal{M}} \sigma_{\xi,t,m} \cdot \mathrm{x}^{\sigma}_{\mathrm{snapshot\_period}(t),m,c} + \sum_{m \in \mathcal{M}} \vartheta_{t,m,c} + \sum_{m \in \mathcal{M}} \mathit{Transformer\_phase\_shift}_{\xi,t,m} \cdot \mathrm{Transformer\_phase\_shift\_cycle\_weight}_{\mathrm{snapshot\_period}(t),m,c} \qquad \forall\, \xi \in \Xi,\ t \in \mathcal{T},\ c \in \mathcal{C} ``` -**`Transformer_n_mod`** +#### Masks + +**`Transformer_lossy`** ```math -N^{\sigma}_{m} \ge 0, N^{\sigma}_{m} \in \mathbb{Z} \qquad \forall\, m \in \mathcal{M} \,:\, \mathrm{ext}^{\sigma}_{m} \wedge \sigma^{\mathrm{mod}}_{m} > 0 \wedge \lvert \{ t \in \mathcal{T} \,:\, \mathrm{on}^{\sigma}_{t,m} \} \rvert > 0 +\mathrm{on}^{\sigma,\mathrm{lossy}}_{t,m} \iff \mathrm{lossy} \wedge \mathrm{on}^{\sigma}_{t,m} \qquad \forall\, t \in \mathcal{T},\ m \in \mathcal{M} ``` diff --git a/docs/howto/see-an-expansion.md b/docs/howto/see-an-expansion.md index 0112ce25..9541ac50 100644 --- a/docs/howto/see-an-expansion.md +++ b/docs/howto/see-an-expansion.md @@ -64,18 +64,20 @@ names each row the expansion adds. === "Math" - _Variable domains_ + _Subject to_ - **`p`** + **`pick`** ```math - 0 \le p_{g} \le 10 \qquad \forall\, g \in \mathcal{G} + \left( p_{g} \right)_{g \in \mathcal{G}} \in \mathrm{SOS}1 ``` - **`pick`** + _Variable domains_ + + **`p`** ```math - \left( p_{g} \right)_{g \in \mathcal{G}} \in \mathrm{SOS}1 + 0 \le p_{g} \le 10 \qquad \forall\, g \in \mathcal{G} ``` === "`expand()`" @@ -272,6 +274,12 @@ the set out too. y = \sum_{b \in \mathcal{B}} \mathit{curve\_lam}_{b} \cdot \mathrm{y}^{\mathrm{bp}}_{b} ``` + **`curve`** + + ```math + \left( \mathit{curve\_lam}_{b} \right)_{b \in \mathcal{B}} \in \mathrm{SOS}2 + ``` + _Variable domains_ **`x`** @@ -292,12 +300,6 @@ the set out too. 0 \le \mathit{curve\_lam}_{b} \le 1 \qquad \forall\, b \in \mathcal{B} ``` - **`curve`** - - ```math - \left( \mathit{curve\_lam}_{b} \right)_{b \in \mathcal{B}} \in \mathrm{SOS}2 - ``` - _Assumptions_ **`curve_complete`** diff --git a/docs/reference/notation.md b/docs/reference/notation.md index aa687e27..79f83f8a 100644 --- a/docs/reference/notation.md +++ b/docs/reference/notation.md @@ -1143,11 +1143,11 @@ Written out by `spec.expand()`: ``` ```math -0 \le \lambda_{t,g,b} \le 1 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G},\ b \in \mathcal{B} +\left( \lambda_{t,g,b} \right)_{b \in \mathcal{B}} \in \mathrm{SOS}2 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` ```math -\left( \lambda_{t,g,b} \right)_{b \in \mathcal{B}} \in \mathrm{SOS}2 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +0 \le \lambda_{t,g,b} \le 1 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G},\ b \in \mathcal{B} ``` ```math @@ -1273,7 +1273,7 @@ Written out by `spec.expand()`: ### Special ordered sets -A set prints beside the variable it restricts, because it restricts that variable rather than adding a row of its own. Under it are the rows it is written out as. +A set prints under Subject to, after the constraints and before the curves, because a solver holds it as a constraint. Under it are the rows it is written out as. #### Special ordered set of type 2 diff --git a/docs/reference/typeset.md b/docs/reference/typeset.md index a6451a33..853e14ad 100644 --- a/docs/reference/typeset.md +++ b/docs/reference/typeset.md @@ -44,6 +44,12 @@ a flag. The [Python API](api.md#typesetting) gives each signature. `-o FILE` writes to a file instead of stdout. - The spec's `description:` opens the document. +- The legend lists Given, Sets, Parameters, Variables, Definitions and Masks. + The math follows under Objective, Subject to, Variable domains, Definitions, + Masks and Assumptions. Under Subject to, the constraints come first, then the + special ordered sets, then the curves. Each part keeps the order of the + file's sections. The one exception is Variable domains, which prints after + the rows. - A `piecewise:` block prints as one line: the curve it states, over the frame it states one curve per coordinate of. To print its rows, print [`spec.expand()`](spec.md#mathspec.spec.Spec.expand) or pass `--expand` diff --git a/docs/several-files.md b/docs/several-files.md index 9e6da335..8f5fac64 100644 --- a/docs/several-files.md +++ b/docs/several-files.md @@ -133,6 +133,14 @@ feasibility problem: A generator fleet, each unit on one bus. + #### Variable domains + + **`dispatch`** + + ```math + 0 \le \mathit{dispatch}_{t,g} \le \mathrm{capacity}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} + ``` + #### Definitions **`generation`** @@ -147,14 +155,6 @@ feasibility problem: \mathit{generation}^{\mathrm{cost}} = \sum_{t \in \mathcal{T},\ g \in \mathcal{G}} \mathit{dispatch}_{t,g} \cdot \mathrm{cost}_{g} ``` - #### Variable domains - - **`dispatch`** - - ```math - 0 \le \mathit{dispatch}_{t,g} \le \mathrm{capacity}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} - ``` - ## The loads Make a file `loads.yaml`. Its term, `consumption`, takes the demand out of the @@ -234,6 +234,14 @@ print(ms.to_markdown(spec, legend=False)) \mathit{injection}_{t,b} = 0 \qquad \forall\, t \in \mathcal{T},\ b \in \mathcal{B} ``` + #### Variable domains + + **`dispatch`** + + ```math + 0 \le \mathit{dispatch}_{t,g} \le \mathrm{capacity}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} + ``` + #### Definitions **`generation`** @@ -266,14 +274,6 @@ print(ms.to_markdown(spec, legend=False)) \mathit{total\_cost} = \mathit{generation}^{\mathrm{cost}} ``` - #### Variable domains - - **`dispatch`** - - ```math - 0 \le \mathit{dispatch}_{t,g} \le \mathrm{capacity}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} - ``` - ## Add a component Make a file `imports.yaml`. It adds a term, `purchase`, to the injection and a diff --git a/src/mathspec/typesetting/legend.py b/src/mathspec/typesetting/legend.py index 861c7367..9c75c13a 100644 --- a/src/mathspec/typesetting/legend.py +++ b/src/mathspec/typesetting/legend.py @@ -142,7 +142,7 @@ def _op(self, name: OperatorName) -> str: return self.format.operators[name] def glossaries(self, noticed: Noticed, defined: Iterable[str]) -> list[tuple[str, list[Entry]]]: - """The sets, parameters, variables, given declarations, definitions and masks, each with its symbol, its dims and its description. + """The given declarations, sets, parameters, variables, definitions and masks, each with its symbol, its dims and its description. *defined* names the expressions that print under their own symbol, so a legend row stands exactly where a symbol does. @@ -226,10 +226,10 @@ def glossaries(self, noticed: Noticed, defined: Iterable[str]) -> list[tuple[str for m, block in program.masks.items() ] groups = ( + ('Given', given), ('Sets', sets), ('Parameters', parameters), ('Variables', variables), - ('Given', given), ('Definitions', definitions), ('Masks', masks), ) diff --git a/src/mathspec/typesetting/walk.py b/src/mathspec/typesetting/walk.py index 69f55b6d..b1aaf582 100644 --- a/src/mathspec/typesetting/walk.py +++ b/src/mathspec/typesetting/walk.py @@ -64,7 +64,7 @@ from collections.abc import Iterable, Mapping from mathspec._expression_parser import BinaryOperator - from mathspec.program import PiecewiseDeclaration, Program, SosDeclaration + from mathspec.program import PiecewiseDeclaration, Program from mathspec.typesetting.format import Format from mathspec.typesetting.symbols import Symbols @@ -659,9 +659,9 @@ def equations(self) -> list[tuple[str, list[Line]]]: return [ ('Objective', self._objective()), ('Subject to', self._constraints()), + ('Variable domains', [self._variable(name) for name in self.program.variables]), ('Definitions', self._definitions()), ('Masks', [self.mask(name) for name in self.program.masks]), - ('Variable domains', self._variables()), ('Assumptions', self._assumptions()), ] @@ -679,14 +679,15 @@ def _objective(self) -> list[Line]: return [Line(label='', left=sense, right=self._expression(objective.expression, self._context()))] def _constraints(self) -> list[Line]: - """Every constraint, then every curve. + """Every constraint, then every set, then every curve: the order of the file's sections. - A ``piecewise:`` block restricts what its link expressions may be - together, which is what a row does, so it prints here rather than among - the domains — where a set prints, being a property of one variable. + A ``sos:`` block restricts which members of a family may be nonzero at + once, and a ``piecewise:`` block what its link expressions may be + together. A solver holds both as constraints, so both print here. """ return [ *(self._constraint(name) for name in self.program.constraints), + *(self._sos(key) for key in self.program.sos), *(self._piecewise(name) for name in self.program.piecewise), ] @@ -811,22 +812,6 @@ def _arms(self, node: Cases, ctx: _Context) -> list[tuple[str, str]]: def _arm_condition(self, when: Mask, ctx: _Context) -> str: return f'{self.format.prose("if ")} {self._predicate(when.root, ctx, need=_WHERE_PRECEDENCE["and"])}' - def _variables(self) -> list[Line]: - """One line per variable, and one more for a set the variable carries. - - A ``sos:`` block restricts the *domain* — which members of a family may - be nonzero at once — so it prints under this heading, beside the - variable it is a property of, rather than among the constraints, where - it would read as a row a solver holds. - """ - sets = {block.variable: (key, block) for key, block in self.program.sos.items()} - lines = [] - for name, block in self.program.variables.items(): - lines.append(self._variable(name)) - if name in sets: - lines.append(self._sos(name, *sets[name], self._context(frame=block.dims))) - return lines - def _variable(self, name: str) -> Line: block = self.program.variables[name] ctx = self._context(frame=block.dims) @@ -851,10 +836,12 @@ def _variable(self, name: str) -> Line: right = f'{right}, {symbol} {self._op("in")} {self._op("integers")}' return Line(label=name, left=left, right=right, condition=condition) - def _sos(self, name: str, key: str, block: SosDeclaration, ctx: _Context) -> Line: + def _sos(self, key: str) -> Line: """The variable's family along the set's dim, as one member of the SOS set, quantified over the other dims.""" - dims = self.program.variables[name].dims - family = self.format.parenthesise(ctx.indexed(self.symbols.name[name], list(dims))) + block = self.program.sos[key] + dims = self.program.variables[block.variable].dims + ctx = self._context(frame=dims) + family = self.format.parenthesise(ctx.indexed(self.symbols.name[block.variable], list(dims))) return Line( label=key, left=self.format.subscript(family, [self._membership(block.along)]), diff --git a/tests/typesetting/golden/latex.out b/tests/typesetting/golden/latex.out index f5b0bbae..6580b917 100644 --- a/tests/typesetting/golden/latex.out +++ b/tests/typesetting/golden/latex.out @@ -143,6 +143,7 @@ \text{zoned} && \theta_{b} & \le \mathrm{budget} && \forall\, b \in \mathcal{B} \,:\, \mathrm{zone\_cap}_{\mathrm{zone\_of}(b)} \text{ is defined} \\ \text{capped} && p_{t,g} & \le \mathrm{p}^{\mathrm{max}}_{g} && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{spend}^{\mathrm{cap}}_{g} > 0 \vee \neg \mathrm{is\_flexible}_{g} \\ \text{masked} && p_{t,g} & \le \mathrm{p}^{\mathrm{max}}_{g} && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{priced\_dispatch}_{g} \wedge \mathrm{pos}(t) > 0 \\ +\text{adjacent} && \left( \mathit{weight}_{t,g} \right)_{g \in \mathcal{G}} & \in \mathrm{SOS}2 && \forall\, t \in \mathcal{T} \\ \text{fuel\_curve} && \left( p_{t,g},\ \mathit{fuel}_{t,g},\ \mathit{heat}_{t,g} \right) & \in \mathit{on}_{t,g} \cdot \mathrm{pwl}_{a \in \mathcal{A}}(\mathrm{bp\_x}_{g,a},\ \mathrm{bp\_y}_{g,a},\ \mathrm{bp\_heat}_{g,a}) && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ \text{cost\_curve} && \mathit{op\_cost}_{t,g} & \ge \begin{cases} \mathit{warm}_{t,g} & \text{if } \mathrm{is\_flexible}_{g} \\ 1 & \text{otherwise} \end{cases} \cdot \mathrm{pwl}_{a \in \mathcal{A} \,:\, \mathrm{bp\_run}_{g,a}}(\mathrm{bp\_x}_{g,a},\ \mathrm{bp\_y}_{g,a})(p_{t,g}) && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ \text{hull\_curve} && \left( p_{t,g},\ \mathit{fuel}_{t,g} \right) & \in \mathrm{conv}_{a \in \mathcal{A}}(\mathrm{bp\_x}_{g,a},\ \mathrm{bp\_heat}_{g,a}) && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ @@ -150,23 +151,6 @@ \text{ramp\_curve} && \mathit{heat}_{t,g} & \le \mathrm{pwl}_{a \in \mathcal{A}}(\mathrm{bp\_x}_{g,a},\ \mathrm{bp\_heat}_{g,a})(p_{t,g}) && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \end{align} -\paragraph{Definitions} -\begin{align} -\text{spend\_cap} && \mathrm{spend}^{\mathrm{cap}}_{g} & = \mathrm{cost}_{g} \cdot 2 && \forall\, g \in \mathcal{G} \\ -\text{spend} && \mathit{spend}_{t} & = \sum_{g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g} && \forall\, t \in \mathcal{T} \\ -\text{rating} && \mathrm{rating}_{g,t} & = \mathrm{eta}_{g} \cdot \mathrm{p}^{\mathrm{max}}_{g} && \forall\, g \in \mathcal{G},\ t \in \mathcal{T} \\ -\text{lcoe} && \mathit{lcoe} & = \frac{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g}}{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g}} \\ -\text{net} && \mathit{net}_{t} & = -\mathit{spill}_{t} + \mathit{slack}_{t} && \forall\, t \in \mathcal{T} \\ -\text{marginal\_price} && \mathit{marginal\_price}_{t,b} & = \lambda_{\mathrm{balance},t,b} && \forall\, t \in \mathcal{T},\ b \in \mathcal{B} \\ -\text{startup\_cost} && \mathrm{startup\_cost}_{t,g} & = \begin{cases} \mathrm{cost}_{g} & \text{if } \mathrm{pos}(t) = 0 \\ \mathrm{cost}_{g} \cdot 2 & \text{if } \mathrm{pos}(t) > 0 \wedge \mathrm{season\_of}(t) = \text{'}\mathrm{winter}\text{'} \\ 0 & \text{otherwise} \end{cases} && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} -\end{align} - -\paragraph{Masks} -\begin{align} -\text{dispatchable} && \mathrm{dispatchable}_{g} & \iff \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} && \forall\, g \in \mathcal{G} \\ -\text{priced\_dispatch} && \mathrm{priced\_dispatch}_{g} & \iff \mathrm{dispatchable}_{g} \wedge \mathrm{spend}^{\mathrm{cap}}_{g} > 0 && \forall\, g \in \mathcal{G} -\end{align} - \paragraph{Variable domains} \begin{align} \text{p} && \mathrm{p}^{\mathrm{min}}_{g} \le p_{t,g} & \le \mathrm{p}^{\mathrm{max}}_{g} && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} \vee \mathrm{p}^{\mathrm{min}}_{g} > 0 \\ @@ -179,13 +163,29 @@ \text{reserve} && \mathit{reserve} & \ge 0 \\ \text{headroom} && \mathit{headroom} & \ge 0 && \text{where } \mathrm{budget} \text{ is defined} \\ \text{weight} && 0 \le \mathit{weight}_{t,g} & \le 1 && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ -\text{adjacent} && \left( \mathit{weight}_{t,g} \right)_{g \in \mathcal{G}} & \in \mathrm{SOS}2 && \forall\, t \in \mathcal{T} \\ \text{fuel} && \mathit{fuel}_{t,g} & \ge 0 && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ \text{heat} && \mathit{heat}_{t,g} & \ge 0 && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ \text{op\_cost} && \mathit{op\_cost}_{t,g} & \ge 0 && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \\ \text{warm} && \mathit{warm}_{t,g} & \in \{0, 1\} && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{is\_flexible}_{g} \end{align} +\paragraph{Definitions} +\begin{align} +\text{spend\_cap} && \mathrm{spend}^{\mathrm{cap}}_{g} & = \mathrm{cost}_{g} \cdot 2 && \forall\, g \in \mathcal{G} \\ +\text{spend} && \mathit{spend}_{t} & = \sum_{g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g} && \forall\, t \in \mathcal{T} \\ +\text{rating} && \mathrm{rating}_{g,t} & = \mathrm{eta}_{g} \cdot \mathrm{p}^{\mathrm{max}}_{g} && \forall\, g \in \mathcal{G},\ t \in \mathcal{T} \\ +\text{lcoe} && \mathit{lcoe} & = \frac{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g}}{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g}} \\ +\text{net} && \mathit{net}_{t} & = -\mathit{spill}_{t} + \mathit{slack}_{t} && \forall\, t \in \mathcal{T} \\ +\text{marginal\_price} && \mathit{marginal\_price}_{t,b} & = \lambda_{\mathrm{balance},t,b} && \forall\, t \in \mathcal{T},\ b \in \mathcal{B} \\ +\text{startup\_cost} && \mathrm{startup\_cost}_{t,g} & = \begin{cases} \mathrm{cost}_{g} & \text{if } \mathrm{pos}(t) = 0 \\ \mathrm{cost}_{g} \cdot 2 & \text{if } \mathrm{pos}(t) > 0 \wedge \mathrm{season\_of}(t) = \text{'}\mathrm{winter}\text{'} \\ 0 & \text{otherwise} \end{cases} && \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\end{align} + +\paragraph{Masks} +\begin{align} +\text{dispatchable} && \mathrm{dispatchable}_{g} & \iff \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} && \forall\, g \in \mathcal{G} \\ +\text{priced\_dispatch} && \mathrm{priced\_dispatch}_{g} & \iff \mathrm{dispatchable}_{g} \wedge \mathrm{spend}^{\mathrm{cap}}_{g} > 0 && \forall\, g \in \mathcal{G} +\end{align} + \paragraph{Assumptions} \begin{align} \text{bounds\_do\_not\_cross} && \mathrm{p}^{\mathrm{min}}_{g} & \le \mathrm{p}^{\mathrm{max}}_{g} && \forall\, g \in \mathcal{G} \\ diff --git a/tests/typesetting/golden/markdown.out b/tests/typesetting/golden/markdown.out index 64a4e157..f7200daf 100644 --- a/tests/typesetting/golden/markdown.out +++ b/tests/typesetting/golden/markdown.out @@ -389,6 +389,12 @@ p_{t,g} \le \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, t \in \mathcal{T},\ g p_{t,g} \le \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{priced\_dispatch}_{g} \wedge \mathrm{pos}(t) > 0 ``` +**`adjacent`** + +```math +\left( \mathit{weight}_{t,g} \right)_{g \in \mathcal{G}} \in \mathrm{SOS}2 \qquad \forall\, t \in \mathcal{T} +``` + **`fuel_curve`** ```math @@ -419,154 +425,148 @@ p_{t,g} \le \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \mathit{heat}_{t,g} \le \mathrm{pwl}_{a \in \mathcal{A}}(\mathrm{bp\_x}_{g,a},\ \mathrm{bp\_heat}_{g,a})(p_{t,g}) \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -#### Definitions +#### Variable domains -**`spend_cap`** +**`p`** ```math -\mathrm{spend}^{\mathrm{cap}}_{g} = \mathrm{cost}_{g} \cdot 2 \qquad \forall\, g \in \mathcal{G} +\mathrm{p}^{\mathrm{min}}_{g} \le p_{t,g} \le \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} \vee \mathrm{p}^{\mathrm{min}}_{g} > 0 ``` -**`spend`** +**`spill`** ```math -\mathit{spend}_{t} = \sum_{g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g} \qquad \forall\, t \in \mathcal{T} +\mathit{spill}_{t} \ge 0 \qquad \forall\, t \in \mathcal{T} ``` -**`rating`** +**`slack`** ```math -\mathrm{rating}_{g,t} = \mathrm{eta}_{g} \cdot \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, g \in \mathcal{G},\ t \in \mathcal{T} +\mathit{slack}_{t} \le 100 \qquad \forall\, t \in \mathcal{T} ``` -**`lcoe`** +**`theta`** ```math -\mathit{lcoe} = \frac{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g}}{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g}} +\theta_{b} \in \mathbb{R} \qquad \forall\, b \in \mathcal{B} ``` -**`net`** +**`on`** ```math -\mathit{net}_{t} = -\mathit{spill}_{t} + \mathit{slack}_{t} \qquad \forall\, t \in \mathcal{T} +\mathit{on}_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`marginal_price`** +**`units`** ```math -\mathit{marginal\_price}_{t,b} = \lambda_{\mathrm{balance},t,b} \qquad \forall\, t \in \mathcal{T},\ b \in \mathcal{B} +0 \le \mathit{units}_{g} \le 10, \mathit{units}_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} ``` -**`startup_cost`** +**`spare`** ```math -\mathrm{startup\_cost}_{t,g} = \begin{cases} \mathrm{cost}_{g} & \text{if } \mathrm{pos}(t) = 0 \\ \mathrm{cost}_{g} \cdot 2 & \text{if } \mathrm{pos}(t) > 0 \wedge \mathrm{season\_of}(t) = \text{'}\mathrm{winter}\text{'} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{spare}_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} ``` -#### Masks - -**`dispatchable`** +**`reserve`** ```math -\mathrm{dispatchable}_{g} \iff \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} \qquad \forall\, g \in \mathcal{G} +\mathit{reserve} \ge 0 ``` -**`priced_dispatch`** +**`headroom`** ```math -\mathrm{priced\_dispatch}_{g} \iff \mathrm{dispatchable}_{g} \wedge \mathrm{spend}^{\mathrm{cap}}_{g} > 0 \qquad \forall\, g \in \mathcal{G} +\mathit{headroom} \ge 0 \qquad \text{where } \mathrm{budget} \text{ is defined} ``` -#### Variable domains - -**`p`** +**`weight`** ```math -\mathrm{p}^{\mathrm{min}}_{g} \le p_{t,g} \le \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} \vee \mathrm{p}^{\mathrm{min}}_{g} > 0 +0 \le \mathit{weight}_{t,g} \le 1 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`spill`** +**`fuel`** ```math -\mathit{spill}_{t} \ge 0 \qquad \forall\, t \in \mathcal{T} +\mathit{fuel}_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`slack`** +**`heat`** ```math -\mathit{slack}_{t} \le 100 \qquad \forall\, t \in \mathcal{T} +\mathit{heat}_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`theta`** +**`op_cost`** ```math -\theta_{b} \in \mathbb{R} \qquad \forall\, b \in \mathcal{B} +\mathit{op\_cost}_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`on`** +**`warm`** ```math -\mathit{on}_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{warm}_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{is\_flexible}_{g} ``` -**`units`** - -```math -0 \le \mathit{units}_{g} \le 10, \mathit{units}_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} -``` +#### Definitions -**`spare`** +**`spend_cap`** ```math -\mathit{spare}_{g} \in \mathbb{Z} \qquad \forall\, g \in \mathcal{G} +\mathrm{spend}^{\mathrm{cap}}_{g} = \mathrm{cost}_{g} \cdot 2 \qquad \forall\, g \in \mathcal{G} ``` -**`reserve`** +**`spend`** ```math -\mathit{reserve} \ge 0 +\mathit{spend}_{t} = \sum_{g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g} \qquad \forall\, t \in \mathcal{T} ``` -**`headroom`** +**`rating`** ```math -\mathit{headroom} \ge 0 \qquad \text{where } \mathrm{budget} \text{ is defined} +\mathrm{rating}_{g,t} = \mathrm{eta}_{g} \cdot \mathrm{p}^{\mathrm{max}}_{g} \qquad \forall\, g \in \mathcal{G},\ t \in \mathcal{T} ``` -**`weight`** +**`lcoe`** ```math -0 \le \mathit{weight}_{t,g} \le 1 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{lcoe} = \frac{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \cdot \mathrm{cost}_{g}}{\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g}} ``` -**`adjacent`** +**`net`** ```math -\left( \mathit{weight}_{t,g} \right)_{g \in \mathcal{G}} \in \mathrm{SOS}2 \qquad \forall\, t \in \mathcal{T} +\mathit{net}_{t} = -\mathit{spill}_{t} + \mathit{slack}_{t} \qquad \forall\, t \in \mathcal{T} ``` -**`fuel`** +**`marginal_price`** ```math -\mathit{fuel}_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathit{marginal\_price}_{t,b} = \lambda_{\mathrm{balance},t,b} \qquad \forall\, t \in \mathcal{T},\ b \in \mathcal{B} ``` -**`heat`** +**`startup_cost`** ```math -\mathit{heat}_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathrm{startup\_cost}_{t,g} = \begin{cases} \mathrm{cost}_{g} & \text{if } \mathrm{pos}(t) = 0 \\ \mathrm{cost}_{g} \cdot 2 & \text{if } \mathrm{pos}(t) > 0 \wedge \mathrm{season\_of}(t) = \text{'}\mathrm{winter}\text{'} \\ 0 & \text{otherwise} \end{cases} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} ``` -**`op_cost`** +#### Masks + +**`dispatchable`** ```math -\mathit{op\_cost}_{t,g} \ge 0 \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} +\mathrm{dispatchable}_{g} \iff \mathrm{p}^{\mathrm{max}}_{g} > 0 \wedge \neg \mathrm{is\_flexible}_{g} \qquad \forall\, g \in \mathcal{G} ``` -**`warm`** +**`priced_dispatch`** ```math -\mathit{warm}_{t,g} \in \{0, 1\} \qquad \forall\, t \in \mathcal{T},\ g \in \mathcal{G} \,:\, \mathrm{is\_flexible}_{g} +\mathrm{priced\_dispatch}_{g} \iff \mathrm{dispatchable}_{g} \wedge \mathrm{spend}^{\mathrm{cap}}_{g} > 0 \qquad \forall\, g \in \mathcal{G} ``` #### Assumptions diff --git a/tests/typesetting/golden/typst.out b/tests/typesetting/golden/typst.out index 93f3eb4a..73f01cd0 100644 --- a/tests/typesetting/golden/typst.out +++ b/tests/typesetting/golden/typst.out @@ -128,27 +128,13 @@ $ upright("budgeted") & italic("spend")_(t) & <= upright("budget") & forall t in upright("zoned") & theta_(b) & <= upright("budget") & forall b in cal(B) colon upright("zone_cap")_(upright("zone_of")(b)) upright(" is defined") \ upright("capped") & p_(t,g) & <= upright("p")^(upright("max"))_(g) & forall t in cal(T), g in cal(G) colon upright("spend")^(upright("cap"))_(g) > 0 or not upright("is_flexible")_(g) \ upright("masked") & p_(t,g) & <= upright("p")^(upright("max"))_(g) & forall t in cal(T), g in cal(G) colon upright("priced_dispatch")_(g) and upright("pos")(t) > 0 \ + upright("adjacent") & (italic("weight")_(t,g))_(g in cal(G)) & in upright("SOS")2 & forall t in cal(T) \ upright("fuel_curve") & (p_(t,g), italic("fuel")_(t,g), italic("heat")_(t,g)) & in italic("on")_(t,g) dot upright("pwl")_(a in cal(A))(upright("bp_x")_(g,a), upright("bp_y")_(g,a), upright("bp_heat")_(g,a)) & forall t in cal(T), g in cal(G) \ upright("cost_curve") & italic("op_cost")_(t,g) & >= cases(italic("warm")_(t,g) & upright("if ") upright("is_flexible")_(g), 1 & upright("otherwise")) dot upright("pwl")_(a in cal(A) colon upright("bp_run")_(g,a))(upright("bp_x")_(g,a), upright("bp_y")_(g,a))(p_(t,g)) & forall t in cal(T), g in cal(G) \ upright("hull_curve") & (p_(t,g), italic("fuel")_(t,g)) & in upright("conv")_(a in cal(A))(upright("bp_x")_(g,a), upright("bp_heat")_(g,a)) & forall t in cal(T), g in cal(G) \ upright("lp_curve") & italic("fuel")_(t,g) & >= upright("pwl")_(a in cal(A) colon upright("bp_x")_(g,a) upright(" is defined"))(upright("bp_x")_(g,a), upright("bp_y")_(g,a))(p_(t,g)) & forall t in cal(T), g in cal(G) \ upright("ramp_curve") & italic("heat")_(t,g) & <= upright("pwl")_(a in cal(A))(upright("bp_x")_(g,a), upright("bp_heat")_(g,a))(p_(t,g)) & forall t in cal(T), g in cal(G) $ -== Definitions -#set math.equation(numbering: "(1)") -$ upright("spend_cap") & upright("spend")^(upright("cap"))_(g) & = upright("cost")_(g) dot 2 & forall g in cal(G) \ - upright("spend") & italic("spend")_(t) & = sum_(g in cal(G)) p_(t,g) dot upright("cost")_(g) & forall t in cal(T) \ - upright("rating") & upright("rating")_(g,t) & = upright("eta")_(g) dot upright("p")^(upright("max"))_(g) & forall g in cal(G), t in cal(T) \ - upright("lcoe") & italic("lcoe") & = frac(sum_(t in cal(T), g in cal(G)) p_(t,g) dot upright("cost")_(g), sum_(t in cal(T), g in cal(G)) p_(t,g)) \ - upright("net") & italic("net")_(t) & = -italic("spill")_(t) + italic("slack")_(t) & forall t in cal(T) \ - upright("marginal_price") & italic("marginal_price")_(t,b) & = lambda_(upright("balance"),t,b) & forall t in cal(T), b in cal(B) \ - upright("startup_cost") & upright("startup_cost")_(t,g) & = cases(upright("cost")_(g) & upright("if ") upright("pos")(t) = 0, upright("cost")_(g) dot 2 & upright("if ") upright("pos")(t) > 0 and upright("season_of")(t) = upright("'winter'"), 0 & upright("otherwise")) & forall t in cal(T), g in cal(G) $ - -== Masks -#set math.equation(numbering: "(1)") -$ upright("dispatchable") & upright("dispatchable")_(g) & arrow.l.r.double.long upright("p")^(upright("max"))_(g) > 0 and not upright("is_flexible")_(g) & forall g in cal(G) \ - upright("priced_dispatch") & upright("priced_dispatch")_(g) & arrow.l.r.double.long upright("dispatchable")_(g) and upright("spend")^(upright("cap"))_(g) > 0 & forall g in cal(G) $ - == Variable domains #set math.equation(numbering: "(1)") $ upright("p") & upright("p")^(upright("min"))_(g) <= p_(t,g) & <= upright("p")^(upright("max"))_(g) & forall t in cal(T), g in cal(G) colon upright("p")^(upright("max"))_(g) > 0 and not upright("is_flexible")_(g) or upright("p")^(upright("min"))_(g) > 0 \ @@ -161,12 +147,26 @@ $ upright("p") & upright("p")^(upright("min"))_(g) <= p_(t,g) & <= upright("p")^ upright("reserve") & italic("reserve") & >= 0 \ upright("headroom") & italic("headroom") & >= 0 & upright("where ") upright("budget") upright(" is defined") \ upright("weight") & 0 <= italic("weight")_(t,g) & <= 1 & forall t in cal(T), g in cal(G) \ - upright("adjacent") & (italic("weight")_(t,g))_(g in cal(G)) & in upright("SOS")2 & forall t in cal(T) \ upright("fuel") & italic("fuel")_(t,g) & >= 0 & forall t in cal(T), g in cal(G) \ upright("heat") & italic("heat")_(t,g) & >= 0 & forall t in cal(T), g in cal(G) \ upright("op_cost") & italic("op_cost")_(t,g) & >= 0 & forall t in cal(T), g in cal(G) \ upright("warm") & italic("warm")_(t,g) & in {0, 1} & forall t in cal(T), g in cal(G) colon upright("is_flexible")_(g) $ +== Definitions +#set math.equation(numbering: "(1)") +$ upright("spend_cap") & upright("spend")^(upright("cap"))_(g) & = upright("cost")_(g) dot 2 & forall g in cal(G) \ + upright("spend") & italic("spend")_(t) & = sum_(g in cal(G)) p_(t,g) dot upright("cost")_(g) & forall t in cal(T) \ + upright("rating") & upright("rating")_(g,t) & = upright("eta")_(g) dot upright("p")^(upright("max"))_(g) & forall g in cal(G), t in cal(T) \ + upright("lcoe") & italic("lcoe") & = frac(sum_(t in cal(T), g in cal(G)) p_(t,g) dot upright("cost")_(g), sum_(t in cal(T), g in cal(G)) p_(t,g)) \ + upright("net") & italic("net")_(t) & = -italic("spill")_(t) + italic("slack")_(t) & forall t in cal(T) \ + upright("marginal_price") & italic("marginal_price")_(t,b) & = lambda_(upright("balance"),t,b) & forall t in cal(T), b in cal(B) \ + upright("startup_cost") & upright("startup_cost")_(t,g) & = cases(upright("cost")_(g) & upright("if ") upright("pos")(t) = 0, upright("cost")_(g) dot 2 & upright("if ") upright("pos")(t) > 0 and upright("season_of")(t) = upright("'winter'"), 0 & upright("otherwise")) & forall t in cal(T), g in cal(G) $ + +== Masks +#set math.equation(numbering: "(1)") +$ upright("dispatchable") & upright("dispatchable")_(g) & arrow.l.r.double.long upright("p")^(upright("max"))_(g) > 0 and not upright("is_flexible")_(g) & forall g in cal(G) \ + upright("priced_dispatch") & upright("priced_dispatch")_(g) & arrow.l.r.double.long upright("dispatchable")_(g) and upright("spend")^(upright("cap"))_(g) > 0 & forall g in cal(G) $ + == Assumptions #set math.equation(numbering: "(1)") $ upright("bounds_do_not_cross") & upright("p")^(upright("min"))_(g) & <= upright("p")^(upright("max"))_(g) & forall g in cal(G) \ diff --git a/tests/typesetting/test_cases.py b/tests/typesetting/test_cases.py index d37a09be..8f9d8af0 100644 --- a/tests/typesetting/test_cases.py +++ b/tests/typesetting/test_cases.py @@ -158,6 +158,6 @@ def test_the_definitions_print_in_declaration_order(): """ declared = ['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot'] tex = to_latex(varied(CASED, **{f'expressions.{n}': BY_REGION for n in declared}), legend=False) - section = tex[tex.index('Definitions') : tex.index('Variable domains')] + section = tex[tex.index('Definitions') :] labels = re.findall(r'^\\text\{(\w+)\} &&', section, flags=re.MULTILINE) assert labels == ['headroom', *declared], "declaration order, the file's own" diff --git a/tools/gallery.py b/tools/gallery.py index 12ee6019..2138c908 100644 --- a/tools/gallery.py +++ b/tools/gallery.py @@ -261,7 +261,7 @@ def _stands_for(name: str, description: str | None) -> str: def declared_block(path: Path) -> str: - """The legend, the objective, then every constraint and every named expression as YAML beside its equation.""" + """The legend, the objective, every constraint, the domains, then every named expression as YAML beside its equation.""" text = without_header(path) model = to_spec(path) page = to_markdown(model, symbols=sidecar_for(path), numbered=False) @@ -283,11 +283,11 @@ def declared_block(path: Path) -> str: f'```yaml\n{declaration(text, "constraints", name)}\n```\n\n' f'{printed}' ) + parts.append(domains) parts.extend( f'### `{name}`\n\n```yaml\n{declaration(text, "expressions", name)}\n```\n\n{definition[name]}' for name in model.expressions ) - parts.append(domains) parts.extend( f'### `{name}`\n\n```yaml\n{declaration(text, "assumptions", name)}\n```\n\n{assumption[name]}' for name in model.assumptions diff --git a/tools/notation.py b/tools/notation.py index 2d15d25e..b238b30b 100644 --- a/tools/notation.py +++ b/tools/notation.py @@ -335,8 +335,8 @@ def block() -> str: continue if family == 'Special ordered sets': parts.append( - 'A set prints beside the variable it restricts, because it restricts that variable rather than ' - 'adding a row of its own. Under it are the rows it is written out as.' + 'A set prints under Subject to, after the constraints and before the curves, because a solver ' + 'holds it as a constraint. Under it are the rows it is written out as.' ) parts += [ f'{_row(found[name], heading, printed)}\n\n{_written_out(name, written)}'