Skip to content

docs(pypsa): the pypsa spec is also 24 topic files that merge back to it, each component adding its share of a sum by name - #736

Merged
FBumann merged 89 commits into
mainfrom
docs/pypsa-fragments
Sep 28, 2026
Merged

FBumann merged 89 commits into
mainfrom
docs/pypsa-fragments

Conversation

@FBumann

@FBumann FBumann commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Prompt: "Now, let's try to port the large pypsa docs pr over / In a separate branch / To test the design". Later: "Can we improve/simplify the pypsa proof? Does it read well? Can it be looked at nivcely in the docs?", and "should we then combine 736 and 740 into one PR?" — "Yes".

Note

The following content was generated by AI.

examples/pypsa.yaml is also 24 topic files that merge back to it in one canonical form. One fragment declares each of the nine sums as empty: true, and each component adds its share by name. Each fragment has a page.

This PR now carries #740, which is closed. It also merges #620 and #717, so the diff carries both. Based on main at b82076c (#742, #759).

What a fragment says, the check, the pages, gates, what was not done

What a fragment says

# network.yaml owns the sum
expressions:
  Bus_injection:
    dims: [scenario, snapshot, bus]
    empty: true
    description: …
constraints:
  Bus_nodal_balance: { dims: [scenario, snapshot, bus], expression: Bus_injection == 0 }

# load.yaml adds its share
given:
  expressions:
    Bus_injection: { dims: [scenario, snapshot, bus], term: Load_injection }
expressions:
  Load_injection: sum(Load_demand, by=Load_bus, over=load, into=bus)
  • Owners. network owns Bus_injection, and power_flow owns Cycle_angle_sum. settings owns the seven totals whose readers (cost, carrier, global_constraints) a model may leave out. The file that was core.yaml is now settings.yaml.
  • The one file names its terms. In pypsa.yaml, each of the nine sums is its terms by name over a declared frame, 40 terms in all. So the merged fragments and the one file have one canonical form.
  • A missing owner is refused. Leaving out an owner while a contributor stays in is refused as "no fragment declares it". Leaving out a component leaves a whole model.

The check

python -m tools.pypsa_split check examples/pypsa loads each fragment alone, merges them, and compares the canonical form with the one file. The tool is 419 lines, down from 578, because it reads the sums and terms off the file. split is the bridge until you decide which side is the source.

Pages

docs/examples/pypsa/index.md has two generated tables: each sum with its owner and its terms, and each fragment with what it declares, reads and adds to. Each of the 24 fragments has a generated page. The three owner pages print each sum as symbol = ⋯. The pages sit under "Proofs of concept" as "PyPSA in 24 files", and tests/test_docs.py keeps them current.

How #740 was merged in

Gates

Pixi cannot be installed in this container. In a Python 3.12 venv, on d69d0d8:

pytest -n auto                                   2560 passed
ruff check . / ruff format --check .             clean
pyrefly check                                    0 errors
typos, prettier --check                          clean
python -m tools.pypsa_split check examples/pypsa 24/24 load alone, one canonical form
python -m tools.gallery --check                  34 page(s) current
zensical build --strict                          one warning: the docs.python.org inventory, blocked by the proxy (main has the same)

Not run: compile-tex, the PyPSA reference solves, reuse lint, zizmor, taplo.

Not done

🤖 Generated with Claude Code

https://claude.ai/code/session_01CQxVP5uX2V4rpvJNPhbyR2

…period classes

Fold pypsa_stochastic and pypsa_multi_period into examples/pypsa.yaml; retire
the sibling pages, symbols and example files. Add the rung 14 and rung 15
sections to the gallery page, and guard the plain-run collapse to the standard
model with a frozen shape fixture.
Add the Process component (a generalized multi-port converter, superset of
Link) and the full-depth Transformer (a passive branch like Line, with tap
ratio and a fixed phase shift in the KVL cycle) to examples/pypsa.yaml, with
symbols, the regenerated gallery, rung 17 and rung 18 reference networks and
oracles, and the collapse guard extended to the new standard names.
rung_19 records the secant-mode triangle solved through the pinned pypsa,
objective 10840.93, the same 150 rows as the tangent rung. The two loss-cut
blocks now stand for both their tangent and secant PyPSA names, matched by a
gallery helper that reads every backticked name before the dash.
A phase-shifting transformer's angle becomes a per-snapshot decision where
phase_shift_min < phase_shift_max, bounded by them and entering the KVL cycle
sum in place of the fixed constant; a plain run keeps the shift fixed and
collapses byte-for-byte. rung_20 records the phase-shifter triangle solved
through the pinned pypsa, objective 16455.0.
A transformer carries its own loss under transmission_losses, as a line does:
the loss counted against its rating, its cap, its tangent or secant cuts and half
of it at either bus. A plain run collapses byte-for-byte. rung_22 and rung_23
record the transformer triangle in both modes, objectives 10643.48 and 10822.00.
…s off

Generator_com_status_must_stay_down mirrors the must-stay-up block over a
data-prep mask, status fixed to zero; PyPSA names the row
Generator-com-status-min_down_time_must_stay_up. rung_24 records a cheap unit
held off for two snapshots, objective 9007.5.
Link gains the status, start-up and shut-down variables, the committable,
big-M and modular p bounds, transitions, up and down times, both must-stay
rules, the committed ramp rows, n_mod and its costs, mirroring Generator.
rung_25 records five committable links, objective 14013.0.
…tment

Process gains the same unit commitment blocks as Link, over its internal
power. rung_26 restates rung 25's links as processes drawing a quarter more
than they deliver, objective 15956.125.
…nd a start-up ramp alone

A committable extendable modular unit takes the ordinary ramp rows against
one module, not the big-M rows. A start-up or shut-down ramp alone builds
the row, and a missing limit reads as the full build. rung_27 (45469.5) and
rung_28 (83283.0) record both for Generator, Link and Process.
…h file

Reverts 5109686. The commit is kept on docs/pypsa-mga and waits for #571.
claude and others added 9 commits September 25, 2026 21:52
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1F2gprjeiGPnvDaWjZwBB
…ant-clarke-y58rek

# Conflicts:
#	CHANGELOG.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1F2gprjeiGPnvDaWjZwBB
…e carries the one description written for it (#743)
# Conflicts:
#	.prettierignore
#	CHANGELOG.md
#	src/mathspec/composition.py
#	src/mathspec/program.py
#	src/mathspec/resolution.py
#	src/mathspec/spec.py
#	src/mathspec/typesetting/walk.py
#	tests/fixtures.py
#	tests/test_dimensions.py
@FabianHofmann
FabianHofmann marked this pull request as ready for review September 28, 2026 12:31
Brings #742, #743, #756 and #759. Only CHANGELOG.md conflicted, and it keeps
both sides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQxVP5uX2V4rpvJNPhbyR2
#740 gives each of the nine sums one owning fragment, names the terms in
`pypsa.yaml`, simplifies the splitter and adds a page per fragment. The
language, typesetter and their tests keep main's side, which holds #742 and
#759 as merged. The PyPSA files take #740's side, the splitter writes
`empty: true` on each owner block, and the fragments and pages are
regenerated from `pypsa.yaml`, which keeps #717's per-snapshot coefficients.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQxVP5uX2V4rpvJNPhbyR2
…n earlier #742

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQxVP5uX2V4rpvJNPhbyR2
@FBumann
FBumann merged commit 22cdebd into main Sep 28, 2026
8 checks passed
FBumann pushed a commit that referenced this pull request Sep 28, 2026
…nalysis-features-zy7x4n-convexity-advice

examples/pypsa_quadratic.yaml is folded into examples/pypsa.yaml on main
(#736), so the assumption this branch added to it goes with the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CvcU9JRnsinc9e9syvVcHS
FBumann pushed a commit that referenced this pull request Sep 28, 2026
…claude/mathspec-analysis-features-zy7x4n-fix

examples/pypsa.yaml now carries the multi-period and stochastic classes
(#736): Link_n_mod and Process_n_mod are capacity decisions like
Generator_n_mod, and the CVaR columns span every snapshot by design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CvcU9JRnsinc9e9syvVcHS
FBumann pushed a commit that referenced this pull request Sep 29, 2026
…s0zjwf

main split pypsa_stochastic into the pypsa spec and its topic files
(#736, #620). The CVaR divisor change moves to examples/pypsa.yaml and
its symbols; the topic files and gallery pages are regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019C9UKzzVdzrcoK3sPrnean
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: composition Assembling a model from files, and fixing a decision docs Documentation pages, guides, reference and README

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants