Skip to content

Carry a PLEXOS Constraint through the extensions sidecar - #19

Open
thomaschristopherking wants to merge 1 commit into
issue-116-plexos-expansion-and-yearsfrom
issue-116-plexos-constraints-sidecar
Open

Carry a PLEXOS Constraint through the extensions sidecar#19
thomaschristopherking wants to merge 1 commit into
issue-116-plexos-expansion-and-yearsfrom
issue-116-plexos-constraints-sidecar

Conversation

@thomaschristopherking

@thomaschristopherking thomaschristopherking commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

TL;DR

A PLEXOS Constraint holds a weighted sum over the objects it names to a right-hand side,
which is how a model states an energy budget, a running-hour cap, an RPS target and an
emission target. The AEMO 2024 ISP file carries 186 of them, and map_constraints reported
every one as not carried. Each Constraint the translator can read now reaches the extensions
sidecar.

Third of five for transition-zero/tz-infra-interop#116,
stacked on #18.

Files to review (6, +291 / -47):

File Why
interop/core/extensions.py (start here) ConstraintExtension, with the sense, the period and the weighted terms.
interop/plugins/shared/plexos_pypsa_translations/_constraints.py Reads a Constraint, and reports the ones it cannot.
interop/plugins/steps/pypsa_to_sienna_map_components.py Relays each record on, so the next hop still has it.
tests/features/plexos_to_pypsa/constraints.feature What a readable Constraint becomes, and what an unreadable one reports.

Why

A PyPSA GlobalConstraint limits one carrier over the whole horizon and cannot name a set of
components, so no shape of PLEXOS Constraint fits it. That is a real gap in the hub, and it
is not closable here. What was avoidable was losing the constraint entirely: the concept
survives a hop through PyPSA only if something carries it, and nothing did.

How

The sidecar record carries what a consumer needs to rebuild the constraint: the sense
(<=, ==, >=), the period its right-hand side applies over, the limit, and each term of
the weighted sum with the class its object belongs to and the property that weights it. PLEXOS
names that coefficient property per class (Generation Coefficient, Flow Coefficient and the
rest), so the record names it rather than assuming one.

pypsa-to-sienna relays each record into its own sidecar rather than reading it. A hop that
cannot apply a constraint must not be the hop that loses it.

Reviewer notes

  • Nothing applies these constraints. This PR makes them survive a hop, not take effect.
    The gap analysis still lists every one as unapplied, and part 5 reads the carbon caps out of
    these records for the Sienna portfolio.
  • A Constraint that cannot be read is still reported. One that states no right-hand side,
    or weights a class the reader does not know, becomes a NOT_MAPPED entry against the object
    that states it, and one warning names a few and counts the rest.

Tests

610 scenarios pass, and all 17 pre-commit hooks.

uv run pytest -q

Open workspace in Conductor

A PLEXOS `Constraint` holds a weighted sum over the objects it names to a
right-hand side, and that is how a model states an energy budget, a running-hour
cap, an RPS target and an emission target. The AEMO 2024 ISP file carries 186 of
them. `map_constraints` reported every one as not carried and the reading stopped
there, so nothing downstream could apply a constraint even in principle.

A PyPSA `GlobalConstraint` limits one carrier over the whole horizon and cannot
name a set of components, so no shape of `Constraint` fits it. The concept
survives a hop through PyPSA only in the sidecar, which now carries each
`Constraint` it can read: the sense, the period its right-hand side applies over,
the limit, and each term of the weighted sum with the class its object belongs to
and the property that weights it.

`pypsa-to-sienna` relays each record on, because a hop that cannot apply a
constraint must not be the hop that loses it.

Signed-off-by: Thomas C. King <thomas.k@transitionzero.org>
@thomaschristopherking
thomaschristopherking requested a review from a team as a code owner September 11, 2026 09:17
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 69bd6ec0-f2cb-4f72-a4fe-ce29b3df6b77

📥 Commits

Reviewing files that changed from the base of the PR and between 8f25bc9 and 44548a9.

📒 Files selected for processing (6)
  • docs/translation_mappings/translation-from-plexos-to-pypsa.md
  • interop/core/extensions.py
  • interop/plugins/shared/plexos_pypsa_translations/_constraints.py
  • interop/plugins/steps/plexos_to_pypsa/map_constraints.py
  • interop/plugins/steps/pypsa_to_sienna_map_components.py
  • tests/features/plexos_to_pypsa/constraints.feature

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant