Skip to content

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

Merged
FabianHofmann merged 17 commits into
mainfrom
docs/pypsa-modular-builds
Oct 2, 2026
Merged

FabianHofmann merged 17 commits into
mainfrom
docs/pypsa-modular-builds

Conversation

@FabianHofmann

@FabianHofmann FabianHofmann commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Prompt: Continue PyPSA parity for energy-models/mathspec: implement step 4 of the plan in tracking issue #783. Step 4 covers the parity items the language can already state. Run it as an ultracode workflow with at most 4 agents, one PR per group.

Note

The following content was generated by AI.

examples/pypsa.yaml now states {c}-n_mod and the modularity row for Line, Transformer, StorageUnit and Store, and builds both, for all seven components, only for a unit that stands in at least one snapshot. Rung 63 records it.

Part of #783 (step 4, group 1: modular builds). Stacks on #787, which stacks on #786.

Method, gate output, PyPSA cites, what is not done

What changed

  • Parameters Line_s_nom_mod, Transformer_s_nom_mod, StorageUnit_p_nom_mod, Store_e_nom_mod, over the component only (PyPSA refuses a module size that differs by scenario, consistency.py:1183-1185).
  • Variables Line_n_mod, Transformer_n_mod, StorageUnit_n_mod, Store_n_mod; rows Line_s_nom_modularity, Transformer_s_nom_modularity, StorageUnit_p_nom_modularity, Store_e_nom_modularity. Symbols in examples/symbols/pypsa.yaml.
  • All seven {c}_n_mod and {c}_{attr}_modularity blocks take count({c}_active, over=snapshot) > 0 in their where.
  • Rung 63 (rung_63_modular_branches_and_storage.py), its section in docs/examples/pypsa.md, and the rung 8 row note.
  • Test test_a_modular_build_counts_modules_only_where_the_unit_stands, parametrized over the seven components. On the parent tree all 7 cases fail (KeyError for the four new components, the old where for Generator, Link and Process); on this branch all 7 pass.
  • Fragments and generated pages regenerated with tools.pypsa_split and tools.gallery, not edited by hand.

PyPSA cites (master 02bdcbba)

  • variables.py:363-384: define_modular_variables, mod_i = c.extendables ∩ c.modulars ∩ c.active_assets at :379.
  • constraints.py:1824-1882: define_modular_constraints, the same index at :1864, row {c}-{attr}_modularity at :1880-1882.
  • optimize.py:801-804 and :830-834: both are called for every (component, attr) in the nominal lookup.
  • components/descriptors.py:151-169: active_assets is the static active flag, true in any scenario. It does not read build year or lifetime (get_active_assets with no period, :133-134).

Rung 63

The spine plus an east bus fed over a modular line (s_nom_mod=25) and a modular transformer (s_nom_mod=15), with a modular storage unit (p_nom_mod=15) and store (e_nom_mod=40). A modular extendable generator, link and process stand beside them with active=False. PyPSA builds n_mod and the modularity row for the four active components only, and none for the three inactive ones. PyPSA solves to 13927.0, 108 rows. With one module size set to zero at a time, PyPSA solves to: line 13882.0, transformer 13921.0, storage unit 13877.0, store 13873.0. So each module binds.

Gates

  • pixi run python -m tools.pypsa_split split examples/pypsa && pixi run python -m tools.gallery: regenerated.
  • uv run --script examples/references/pypsa/reference.py: only rung 63 was added to references.json; no other record changed. --check: every rung solves to its record.
  • pixi run lint: passes. pixi run ci: exit 0, 2633 passed, docs build No issues found, compiled 55 document(s).

Departures and what is not done

  • The file reads active_assets as "stands in at least one snapshot", and not as PyPSA's static flag. They differ only for a unit with active=True whose build year and lifetime miss every period. PyPSA builds n_mod and the row for that unit, and nothing else reads them. The file has no static active parameter, and this PR adds none.
  • {c}_{attr}_ext keeps no active restriction. PyPSA builds no {c}-{attr} column for a unit that is not active (variables.py:354). The file still declares it, priced at zero by {c}_capital_weight. That is the data-prep note in PyPSA parity with master: open points, new master changes and the PyPSA bugs found #783, not this group.
  • The changelog line and the #815 beside the rung 63 numbers came in a follow-up commit, after the PR number was known.
  • No new language feature was needed.

@FBumann FBumann added the docs Documentation pages, guides, reference and README label Oct 1, 2026
@read-the-docs-community

read-the-docs-community Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

@FabianHofmann
FabianHofmann force-pushed the docs/pypsa-fixed-modular branch from df7f835 to 34af2a0 Compare October 2, 2026 09:06
@FabianHofmann
FabianHofmann changed the base branch from docs/pypsa-fixed-modular to main October 2, 2026 09:11
…ilds

# Conflicts:
#	CHANGELOG.md
#	docs/examples/pypsa.md
#	docs/examples/pypsa/index.md
#	docs/examples/pypsa/link.md
#	examples/references/pypsa/references.json
#	tests/test_pypsa_references.py
@FabianHofmann
FabianHofmann merged commit 5297159 into main Oct 2, 2026
6 checks passed
FBumann pushed a commit that referenced this pull request Oct 2, 2026
…tum8xc

#808 and #815 add six sparse tables, marked missing: neutral:
Line_v_ang_max and Transformer_v_ang_max (no row by default), and the
module sizes of a storage unit, a store, a line and a transformer.

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

Labels

docs Documentation pages, guides, reference and README

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants