Skip to content

Apply the new-format custom constraints in pypsa_build - #148

Open
nick-gorman wants to merge 3 commits into
mainfrom
apply-temporal-scope-custom-constraints
Open

nick-gorman wants to merge 3 commits into
mainfrom
apply-temporal-scope-custom-constraints

Conversation

@nick-gorman

@nick-gorman nick-gorman commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

The new-format custom constraints from the translator (#139) are scoped by
investment period and timeslice, e.g. a flow limit that only applies at QLD
peak demand in 2030. The existing _add_custom_constraints sums every term
over every snapshot, so it can't express that. This change adds
_add_custom_constraints_with_temporal_scope, which turns each RHS row into
one linopy constraint at the snapshots its investment period and timeslice
select.

It isn't wired into build_pypsa_network yet; that comes with the final
wiring PR, so there's no change in behaviour.

src/ispypsa/
├── pypsa_build/custom_constraints.py        ← new temporal-scope path
├── translator/timeslices.py                 ← no-snapshot warning now per investment period
└── validation/schemas/
    ├── ispypsa_tables/                      ← existing schemas, moved
    └── pypsa_friendly_tables/               ← new: contracts for this step's inputs
tests/test_model/test_custom_constraints_with_temporal_scope.py
CLAUDE.md                                    ← "investment period", never bare "period"

Design choices worth a look:

  • Blank timeslice is a fallback, per constraint. It covers the snapshots
    in its investment period that none of the same constraint's named
    timeslices cover.
  • Blank investment_period matches only blank. An LHS term joins only the
    RHS rows with its exact investment_period, not every investment period. The
    translator resolves all dated inputs to explicit investment periods, so
    blank only appears on the expansion limits.
  • Load terms are data, not variables. coefficient × p_set is added as a
    per-snapshot constant, which linopy moves to the RHS.
  • Storage p is net dispatch (p_dispatch − p_store), matching PLEXOS's
    paired battery Generation/Load coefficients.
  • Missing components aren't skipped. Unsupported (component, attribute)
    terms and constraints with no variable terms raise, rather than silently
    weakening the constraint.
  • Schema split. The schema folder is now ispypsa_tables (translator
    input) and pypsa_friendly_tables (pypsa_build input). Only the three
    tables this step reads are declared so far. Nothing loads the schemas yet,
    so the move is paths only.

🤖 Generated with Claude Code

The translator's new-format custom constraints are scoped by investment
period and timeslice, which the existing pypsa_build path can't express.
Adds the pypsa_build step that turns each RHS row into a linopy constraint
at the snapshots its period and timeslice select, with blank timeslices as
a per-constraint fallback and load terms as a per-snapshot RHS offset.

Also declares the contract for its input tables as schemas, splitting the
schema folder into ispypsa_tables (translator input) and
pypsa_friendly_tables (pypsa_build input). Not yet wired into
build_pypsa_network, so no production behaviour changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/ispypsa/pypsa_build/custom_constraints.py 93.49% <100.00%> (+13.49%) ⬆️
src/ispypsa/templater/existing_planned.py 100.00% <ø> (ø)
src/ispypsa/templater/new_entrants.py 100.00% <ø> (ø)
src/ispypsa/translator/timeslices.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

nick-gorman and others added 2 commits September 30, 2026 11:43
On its own, "period" reads as a snapshot or time window, which is easy to
confuse with the timeslice scoping these constraints also carry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bare "period" kept reading as a snapshot or time window in the custom
constraint docs, so the convention is written down for future changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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