Skip to content

PV node: Support voltage-regulator Q limits and PV→PQ switching - #1452

Merged
nitbharambe merged 22 commits into
PowerGridModel:mainfrom
scud-soptim:feature/q_limit_handling_1236
Aug 11, 2026
Merged

PV node: Support voltage-regulator Q limits and PV→PQ switching #1452
nitbharambe merged 22 commits into
PowerGridModel:mainfrom
scud-soptim:feature/q_limit_handling_1236

Conversation

@scud-soptim

Copy link
Copy Markdown
Contributor

Implements #1236

Summary

This PR adds reactive-power limit handling for voltage-regulated nodes in Newton-Raphson power-flow calculations.

An active voltage_regulator now models the regulated node as a PV node by enforcing the configured voltage magnitude u_ref. If the reactive power required to maintain this voltage violates q_min or q_max, the regulated object is clamped to the violated limit and the effective node type is switched from PV to PQ.

The PR also exposes the effective node type in steady-state node output and documents the voltage-regulator behavior, including PV→PQ switching and reactive-power allocation when multiple regulators are connected to the same node.

Main changes

  • Add effective bus_type to steady-state node output.

    • 0: PQ
    • 1: PV
    • 2: Source/Slack
  • Extend voltage-regulator steady-state output with a limit indicator.

    • -1: lower reactive-power limit q_min reached
    • 0: no limit violation
    • 1: upper reactive-power limit q_max reached
  • Implement PV-node handling in Newton-Raphson power flow for active voltage regulators.

  • Implement PV→PQ switching when the required reactive power violates configured Q limits.

  • Clamp the regulated object to the violated Q limit after switching to PQ.

  • Propagate final bus type and Q-limit status to steady-state output.

  • Add and update tests for voltage-regulator Q-limit behavior, PV→PQ switching, batch updates, and output metadata.

  • Update user documentation for voltage-regulator behavior and power-flow algorithm details.

Reactive-power allocation with multiple voltage regulators

When multiple active voltage regulators are connected to the same node, they jointly regulate the same node voltage. The required reactive power is initially distributed equally over the active regulated objects. If one regulator reaches its individual q_min or q_max, it is clamped at that limit and removed from the remaining allocation. The unallocated reactive power is redistributed over the remaining regulators until all required reactive power has been allocated or all available regulators have reached a limit.

For asymmetric calculations, limit checks use the total three-phase reactive power. The phase distribution follows the available phase proportions where possible; if no usable phase proportion is available, the value is distributed equally over the three phases.

Documentation updates

The documentation now describes:

  • voltage-regulator PV-node behavior;
  • PV→PQ switching on reactive-power limit violation;
  • the meaning of node.bus_type;
  • the meaning of voltage_regulator.limit_violated;
  • reactive-power allocation for multiple voltage regulators at the same node;
  • the fact that voltage-controlled buses are supported through active voltage_regulator components in Newton-Raphson power flow.

Testing

Added and updated tests cover:

  • node output metadata for bus_type;
  • voltage-regulator output metadata for limit_violated;
  • Newton-Raphson PV-node handling;
  • PV→PQ switching on lower and upper Q-limit violations;
  • multiple voltage regulators at the same node;
  • batch calculation scenarios with voltage-regulator updates;
  • reference power-flow test data for the new PV→PQ switching case.

Notes for reviewers

  • The implementation is limited to Newton-Raphson power flow.
  • This PR does not change the public input model beyond the voltage-regulator Q-limit behavior already represented by q_min and q_max.
  • The reactive-power value is reported on the regulated load/generator output. The voltage_regulator output only reports the limit status.
  • If this PR fully resolves issue [FEATURE] Q limit handling for PV nodes #1236, the PR description can be changed from Related to #1236 to Closes #1236.

@figueroa1395 figueroa1395 added documentation Improvements or additions to documentation feature New feature or request improvement Improvement on internal implementation labels Jun 26, 2026
@figueroa1395

Copy link
Copy Markdown
Member

Hello @scud-soptim and @frie-soptim,

Thank you once more for your contribution!

Since this is a large and very involved PR, I'll give some initial comments:

  • We will start now the reviewing progress, but it will take us some time. Please be patient.
  • We'll address any question/comment presented during the review process itself.
  • As usual, feel free to ping us at any point in time if there is any urgency or you need help.

Additionally, we notice that this PR only includes the Q-limit handling and not yet the voltage-setpoint controller as described in #1236. We agree with this decision. Let's keep the scope of this PR strictly to the Q-limit handling and leave the voltage-setpoint controller for a follow up discussion. That said, I'll add a few additional remarks about this in the issue itself.

@figueroa1395 figueroa1395 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scud-soptim , @frie-soptim As always, great job!

Some additional comments:

  • CI is broken, but it's just minor stuff.
  • I see merge conflicts due to a recently merged documentation PR. Let us know if you want us to help resolving those.
  • There's some TODOs in power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/common_solver_functions.hpp, I agree that those should be implemented.
  • The logic looks good, no comment yet about that part.
  • The rest of the review will follow tomorrow :)

Comment thread docs/algorithms/pf-algorithms.md Outdated
Comment thread code_generation/data/attribute_classes/output.json Outdated
Comment thread docs/user_manual/components.md Outdated
Comment thread docs/user_manual/components.md
Comment thread power_grid_model_c/power_grid_model/include/power_grid_model/main_core/output.hpp Outdated

@figueroa1395 figueroa1395 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some additional comments

Comment thread tests/cpp_unit_tests/component/test_voltage_regulator.cpp
Comment thread tests/data/power_flow/pv-node/pv-node-pq-switching/README.md

@figueroa1395 figueroa1395 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be continued. I'm almost done now :)

Comment thread power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp Outdated
Comment thread power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp Outdated
@scud-soptim

Copy link
Copy Markdown
Contributor Author

Hi, we'll answer your questions when Frie returns from vacation.

@figueroa1395 figueroa1395 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double checking, but is there any additional validation needed on the python side? Say anything regarding the q-limits for instance? What would happen if q_min is set to 1 and q_max to -1 by mistake? I imagine this should be catched by both the validator and a hard error thrown?

Can you add some unit testing handling sym and asym regulated loads on a node? one violating limits, both violating limits, and both not violating limits?

I think I should be done with the overall review. If I have anything else to comment on, I'll mention it once Frie is back so this doesn't grow even more.

Comment thread tests/cpp_unit_tests/math_solver/test_math_solver_pf_newton_raphson.cpp Outdated
Comment thread tests/cpp_unit_tests/math_solver/test_math_solver_pf_newton_raphson.cpp Outdated
Comment thread tests/cpp_unit_tests/math_solver/test_math_solver_pf_newton_raphson.cpp Outdated
Comment thread tests/cpp_unit_tests/math_solver/test_math_solver_pf_newton_raphson.cpp Outdated
@figueroa1395

figueroa1395 commented Jul 14, 2026

Copy link
Copy Markdown
Member

Hello @scud-soptim and @frie-soptim,

Once small remark for when you return. We have enabled mandatory cryptographic signing for the PGM-org. Could you please amend your commits and either ssh or gpg sign them? This is additional to DCO signing which was already in place.

This was announced during the last community meeting, where @scud-soptim was present.

frie-soptim and others added 11 commits July 24, 2026 11:37
- add bus_type to node output
- implement feature in newton_raphson solver
- implmentet iterative equal distribution of Q at the end
  - try distributing equally
  - if individual regulator limit is violated, then save unallocated
    amount and distribute again in next iteration

Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Signed-off-by: SCUD-SOPTIM <udo.schmitz@soptim.de>
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
`cache_run` needed in Newton Raphson PF solver to determine that in case
of batching the max deviation should not be artificially set to infinity
(to trigger q limit checking) and then run into a IterationDiverge error,
because with cache_run also max_iter is set to 1

Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
- cache relevant IDs of voltage_regualtors and load_gens initially
- simplify distribution by iterating over cached regulators, instead of
  iterating over load_gens and looking up regulators over and over again
- check for unallocated power after distribution and throw
  (should be purely technical, cases where distribution actually not possible
  are handled in another function)

Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
- refactor q limit check triggering by using countdown variable, that starts
  limit check at iteration N, or earlier if solver converger before that
- split bus type and bus limit determination from settung reference voltage for PV buses
- remove noop call for function finalize_result() in non-NR solver
- use enum values for limit violations

Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
- mark node that it required recalculation after limit violation
- in setup of jacobian only calculate row for marked buses

Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
… load_gens

- specified_q on regulated load_gens should have no effect on the solution
- however, the initial linear solver considered it and calculated "wrong" start
  values for voltage. For PV buses, this voltage was replaced by the reference
  voltage of the regulator, but for PQ buses the "wrong" voltages remained
- this can lead to larger mismatches in the first iterations and thus to a potential
  limit violation and a bus switch to PQ.
- solution is to ignore specified_q values for regulated load_gens for the linear
  solver

Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
@frie-soptim
frie-soptim force-pushed the feature/q_limit_handling_1236 branch from 8efbef8 to 153af49 Compare July 24, 2026 12:28
@frie-soptim

Copy link
Copy Markdown
Contributor

Hello @scud-soptim and @frie-soptim,

Once small remark for when you return. We have enabled mandatory cryptographic signing for the PGM-org. Could you please amend your commits and either ssh or gpg sign them? This is additional to DCO signing which was already in place.

This was announced during the last community meeting, where @scud-soptim was present.

@figueroa1395 I have pushed some new commits and rebased the branch on current main, in order to sign the older commits too. If you had checked out the branch before, then you will have to update it now.

@figueroa1395

Copy link
Copy Markdown
Member

@figueroa1395 I have pushed some new commits and rebased the branch on current main, in order to sign the older commits too. If you had checked out the branch before, then you will have to update it now.

@frie-soptim Thanks for the heads up. I'll review the new updated PR next week + resolve any outdated comments that are no longer relevant.

In addition, I've enabled the CI to run.

@mgovers mgovers changed the title Support voltage-regulator Q limits and PV→PQ switching PV node: Support voltage-regulator Q limits and PV→PQ switching Jul 27, 2026
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Comment thread tests/data/power_flow/pv-node/pv-node-load-gen-const-i-y/sym_output.json Outdated
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
Signed-off-by: Eduard Fried <eduard.fried@soptim.de>
…ath_solver/newton_raphson_pf_solver.hpp

Co-authored-by: Santiago Figueroa Manrique <22895394+figueroa1395@users.noreply.github.com>
Signed-off-by: Eduard Fried <146418093+frie-soptim@users.noreply.github.com>
@frie-soptim

Copy link
Copy Markdown
Contributor

@figueroa1395 I believe I have addressed all comments or issues in my last commits. At the end, I also removed the the experimental feature check for Q limits.

I don't think I have the option to resolve any discussions, you will have to do it yourself.

If there are still any issues regarding naming or location of functions, feel free to change it as you see fit.

@figueroa1395

Copy link
Copy Markdown
Member

@figueroa1395 I believe I have addressed all comments or issues in my last commits. At the end, I also removed the the experimental feature check for Q limits.

I don't think I have the option to resolve any discussions, you will have to do it yourself.

If there are still any issues regarding naming or location of functions, feel free to change it as you see fit.

Hello @frie-soptim,

Thank you for addressing everything. You did an awesome job! This contribution is great as is. Whatever minor things we find after a final overall review, we can address, you already did all the heavy lifting. We'll then take it from here, but the credits go to you of course!

We'll PING you before we merge it so you are aware, it shouldn't be too long from now.

nitbharambe and others added 5 commits August 7, 2026 13:30
Signed-off-by: Nitish Bharambe <78108900+nitbharambe@users.noreply.github.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Signed-off-by: Nitish Bharambe <nitish.bharambe@alliander.com>
Updated the description of the 'limit_violated' field to reflect correct values for limit violations.

Signed-off-by: Nitish Bharambe <78108900+nitbharambe@users.noreply.github.com>
@nitbharambe

nitbharambe commented Aug 10, 2026

Copy link
Copy Markdown
Member

I see the asymmetric power flow has a bug in it so i re-enabled the experimental flag only on asym power flow + q limits.
(In short: I see a factor of 3 being the issue. We would need some extra logic to determine whether regulator is being applied on a sym or asym type of loadgen. Edit: I see the base needs to be divided 3).
We shall cover this in a new PR while this one can be merged.

nitbharambe
nitbharambe previously approved these changes Aug 10, 2026
@nitbharambe

nitbharambe commented Aug 10, 2026

Copy link
Copy Markdown
Member

Things to be covered in new PR:

Signed-off-by: Nitish Bharambe <78108900+nitbharambe@users.noreply.github.com>
@nitbharambe
nitbharambe added this pull request to the merge queue Aug 11, 2026
Merged via the queue into PowerGridModel:main with commit 4e6d8fb Aug 11, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation feature New feature or request improvement Improvement on internal implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants