fix: clamp s/p_nom_max in brownfield to prevent floating-point infeasibility#2115
Merged
lkstrp merged 4 commits intoPyPSA:masterfrom Mar 25, 2026
Merged
Conversation
…ibility When brownfield carries forward s_nom_opt from a previous horizon as s_nom_min, solver floating-point tolerance can make s_nom_min exceed s_nom_max by a tiny amount (e.g., 0.00013 MW on a 33,585 MW line). This creates an infeasible constraint that crashes the solver. Extends the fix from PRs PyPSA#840 and PyPSA#952 (which handle global transmission constraints) to also cover per-line s_nom_max and DC link p_nom_max.
fneum
approved these changes
Mar 18, 2026
When barrier solutions without crossover produce slightly imprecise p_nom_opt values, the already-retrofitted H2 pipeline capacity can marginally exceed the original pipe capacity. This makes remaining_capacity negative, setting p_nom_max < p_nom_min = 0, which causes infeasibility at the next planning horizon. Observed on 115-cluster myopic runs with BarConvTol=1e-4: H2 pipeline retrofitted ES2 7 -> FR2 1: p_nom_max = -0.000649 MW H2 pipeline retrofitted GB1 3 -> GB1 7: p_nom_max = -0.000169 MW Apply the same clip(lower=0) pattern used for AC lines and DC links.
auto-merge was automatically disabled
March 25, 2026 05:27
Head branch was pushed to by a user without write access
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes proposed in this Pull Request
In myopic optimisation,
add_brownfield()setss_nom_minandp_nom_minfor AC lines and DC links to the previoushorizon's
s_nom_opt/p_nom_opt. Due to solver floating-point tolerance, the optimised value can slightly exceeds_nom_max, creating a per-componentmin > maxinfeasibility.I ran into this on a 50-cluster, 6-horizon sector-coupled run where an AC line (DE2 → NL2) ended up with
s_nom_minexceeding
s_nom_maxby 0.00013 MW on a 33,585 MW line — enough to make the solver declare infeasibility.PRs #840 and #952 fixed the related aggregate case (total
s_nom_minhitting the global transmission expansionlimit). This PR adds the complementary per-component fix: clamping
s_nom_max/p_nom_maxto be at leasts_nom_min/p_nom_minright after the brownfield assignment.The pattern is consistent with the existing
update_p_nom_max()in_helpers.pyand the generator clamp inadd_existing_baseyear.py, both of which already handle the same class of issue for other component types.Checklist
pixi.toml(usingpixi add <dependency-name>).config/config.default.yaml.doc/configtables/*.csv.doc/release_notes.rstis added.