-
Notifications
You must be signed in to change notification settings - Fork 49
Implement Model a PQU diagram for reactive limits #3612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Fabrice Buscaylet <[email protected]>
added unit tests Signed-off-by: Fabrice Buscaylet <[email protected]>
Signed-off-by: Matthieu SAUR <[email protected]>
Signed-off-by: Matthieu SAUR <[email protected]>
Added lower and upper bounds for ReactiveCapabilityShapePolyhedron Added tests and fixed old ones Added javadocs Signed-off-by: Fabrice Buscaylet <[email protected]>
Added lower and upper bounds for ReactiveCapabilityShapePolyhedron Added tests and fixed old ones Added javadocs Signed-off-by: Fabrice Buscaylet <[email protected]>
Signed-off-by: Fabrice Buscaylet <[email protected]>
Signed-off-by: Fabrice Buscaylet <[email protected]>
added unit tests Signed-off-by: Fabrice Buscaylet <[email protected]>
Added lower and upper bounds for ReactiveCapabilityShapePolyhedron Added tests and fixed old ones Added javadocs Signed-off-by: Fabrice Buscaylet <[email protected]>
Added lower and upper bounds for ReactiveCapabilityShapePolyhedron Added tests and fixed old ones Added javadocs Signed-off-by: Fabrice Buscaylet <[email protected]>
Signed-off-by: Fabrice Buscaylet <[email protected]>
Signed-off-by: Fabrice Buscaylet <[email protected]>
…' into features/ReactiveCapabilityShape # Conflicts: # iidm/iidm-api/src/main/java/com/powsybl/iidm/network/ReactiveCapabilityShapePlane.java
Signed-off-by: Fabrice Buscaylet <[email protected]>
…into features/ReactiveCapabilityShape
Signed-off-by: Fabrice Buscaylet <[email protected]>
# Conflicts: # iidm/iidm-serde/src/main/resources/xsd/iidm_V1_15.xsd # iidm/iidm-serde/src/main/resources/xsd/iidm_equipment_V1_15.xsd # iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/AbstractIidmSerDeTest.java # iidm/iidm-serde/src/test/java/com/powsybl/iidm/serde/StaticVarCompensatorXmlTest.java
|
| /** | ||
| * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| * SPDX-License-Identifier: MPL-2.0 | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyright is wrong:
| /** | |
| * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| * SPDX-License-Identifier: MPL-2.0 | |
| */ | |
| /** | |
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| * SPDX-License-Identifier: MPL-2.0 | |
| */ |
| * *---*--+---------------* | | ||
| * | / | | | | | ||
| * |/ | . (P, Q, U) | | | ||
| * +---|--|---------------|--+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what these points represent
| double getMinQ(double p, double v); | ||
|
|
||
| /** | ||
| * Get the reactive power maximum value at a given active power and voltage values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * Get the reactive power maximum value at a given active power and voltage values. | |
| * Get the reactive power maximum value at a given active power and voltage values. |
| /** | ||
| * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| * SPDX-License-Identifier: MPL-2.0 | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyright is wrong:
| /** | |
| * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| * SPDX-License-Identifier: MPL-2.0 | |
| */ | |
| /* | |
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| * SPDX-License-Identifier: MPL-2.0 | |
| */ |
| * Add a reactive capability shape plane to the reactive capability shape | ||
| * @param alpha the alpha coefficient | ||
| * @param beta the beta coefficient | ||
| * @param gamma the gamme right hand side |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @param gamma the gamme right hand side | |
| * @param gamma the gamma right hand side |
| /** | ||
| * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| * SPDX-License-Identifier: MPL-2.0 | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyright is wrong:
| /** | |
| * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| * SPDX-License-Identifier: MPL-2.0 | |
| */ | |
| /* | |
| * Copyright (c) 2025, RTE (http://www.rte-france.com) | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| * SPDX-License-Identifier: MPL-2.0 | |
| */ |
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
|
||
| class ReactiveCapabilityShapeLimitsTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
author is missing
| @@ -0,0 +1,88 @@ | |||
| package com.powsybl.iidm.network.impl; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copyright is missing
| import org.junit.jupiter.api.Test; | ||
| import static org.junit.jupiter.api.Assertions.*; | ||
|
|
||
| class ReactiveCapabilityShapePlaneTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
author is missing
| @@ -0,0 +1,121 @@ | |||
| package com.powsybl.iidm.network.impl; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copyright is missing
|
|
||
| import static org.junit.jupiter.api.Assertions.*; | ||
|
|
||
| class ReactiveCapabilityShapePolyhedronTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
author is missing
| * - U (kV): Voltage (Vertical Axis) | ||
| * </pre> | ||
| * The bounding box represents the operational limits—the single convex polyhedron defined by your constraints (the listOfPlanes). | ||
| * The point (P, Q, U) represents a specific operating point that the isInside function is checking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentence about the (P, Q, U) point should be in the polyhedron javadoc as it is not directly in the ReactiveCapabilityShape object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or the isInside function could be added to this interface.
| * | ||
| * - P (MW): Active Power (Horizontal Axis) | ||
| * - Q (MVaR): Reactive Power (Depth Axis) | ||
| * - U (kV): Voltage (Vertical Axis) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is confusing to use U in the javadoc but V in the code. Should it not all be V?
| ReactiveCapabilityShape add(); | ||
|
|
||
| /** | ||
| * Add a reactive capability shape plane to the reactive capability shape |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would be good to reming the place equation here so that the alpha, beta and gamma coefficients are directly understood.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or in the param you could add what the coefficient refers to.
|
|
||
| /** | ||
| * Constructor | ||
| * @param polyhedron the reactive capacility shape polyhedron |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @param polyhedron the reactive capacility shape polyhedron | |
| * @param polyhedron the reactive capability shape polyhedron |
|
|
||
| /** | ||
| * Builder | ||
| * @param polyhedron the reactive capacility shape polyhedron |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @param polyhedron the reactive capacility shape polyhedron | |
| * @param polyhedron the reactive capability shape polyhedron |
| /** | ||
| * The inequaility types | ||
| */ | ||
| InequalityType inequalityType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be private no?
| sb.append("Q"); | ||
|
|
||
| // Append U term (alpha * U) | ||
| if (Math.abs(alpha) > EPSILON) { // Check if alpha is non-zero |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could create a new method to extract the common logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should either use v or u for variables
| * @return true if the point satisfies ALL plane constraints, false otherwise. | ||
| */ | ||
| public boolean isInside(final double p, final double q, final double u) { | ||
| boolean insideBounds = isInsideBounds(p, q, u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if not insideBounds, return false at the beginning of the method for clarity
| private void addBoundsConstraints(final Collection<LinearConstraint> constraints) { | ||
| // Check the bounds activities before adding them to the linear program | ||
| if (!Double.isNaN(this.minQ)) { | ||
| constraints.add(new LinearConstraint(new double[]{1.0, 0.0, 0.0}, Relationship.GEQ, this.minQ)); | ||
| } | ||
| if (!Double.isNaN(this.maxQ)) { | ||
| constraints.add(new LinearConstraint(new double[]{1.0, 0.0, 0.0}, Relationship.LEQ, this.maxQ)); | ||
| } | ||
| if (!Double.isNaN(this.minP)) { | ||
| constraints.add(new LinearConstraint(new double[]{0.0, 0.0, 1.0}, Relationship.GEQ, this.minP)); | ||
| } | ||
| if (!Double.isNaN(this.maxP)) { | ||
| constraints.add(new LinearConstraint(new double[]{0.0, 0.0, 1.0}, Relationship.LEQ, this.maxP)); | ||
| } | ||
| if (!Double.isNaN(this.minV)) { | ||
| constraints.add(new LinearConstraint(new double[]{0.0, 1.0, 0.0}, Relationship.GEQ, this.minV)); | ||
| } | ||
| if (!Double.isNaN(this.maxV)) { | ||
| constraints.add(new LinearConstraint(new double[]{0.0, 1.0, 0.0}, Relationship.LEQ, this.maxV)); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private void addBoundsConstraints(final Collection<LinearConstraint> constraints) { | |
| // Check the bounds activities before adding them to the linear program | |
| if (!Double.isNaN(this.minQ)) { | |
| constraints.add(new LinearConstraint(new double[]{1.0, 0.0, 0.0}, Relationship.GEQ, this.minQ)); | |
| } | |
| if (!Double.isNaN(this.maxQ)) { | |
| constraints.add(new LinearConstraint(new double[]{1.0, 0.0, 0.0}, Relationship.LEQ, this.maxQ)); | |
| } | |
| if (!Double.isNaN(this.minP)) { | |
| constraints.add(new LinearConstraint(new double[]{0.0, 0.0, 1.0}, Relationship.GEQ, this.minP)); | |
| } | |
| if (!Double.isNaN(this.maxP)) { | |
| constraints.add(new LinearConstraint(new double[]{0.0, 0.0, 1.0}, Relationship.LEQ, this.maxP)); | |
| } | |
| if (!Double.isNaN(this.minV)) { | |
| constraints.add(new LinearConstraint(new double[]{0.0, 1.0, 0.0}, Relationship.GEQ, this.minV)); | |
| } | |
| if (!Double.isNaN(this.maxV)) { | |
| constraints.add(new LinearConstraint(new double[]{0.0, 1.0, 0.0}, Relationship.LEQ, this.maxV)); | |
| } | |
| } | |
| private void addBoundsConstraints(final Collection<LinearConstraint> constraints) { | |
| addBoundConstraint(constraints, IDX_Q, this.minQ, Relationship.GEQ); | |
| addBoundConstraint(constraints, IDX_Q, this.maxQ, Relationship.LEQ); | |
| addBoundConstraint(constraints, IDX_P, this.minP, Relationship.GEQ); | |
| addBoundConstraint(constraints, IDX_P, this.maxP, Relationship.LEQ); | |
| addBoundConstraint(constraints, IDX_U, this.minU, Relationship.GEQ); | |
| addBoundConstraint(constraints, IDX_U, this.maxU, Relationship.LEQ); | |
| } | |
| private void addBoundConstraint(Collection<LinearConstraint> constraints, int variableIndex, double boundValue, Relationship relationship) { | |
| if (!Double.isNaN(boundValue)) { | |
| double[] coefficients = new double[3]; | |
| coefficients[variableIndex] = 1.0; | |
| constraints.add(new LinearConstraint(coefficients, relationship, boundValue)); | |
| } | |
| } |
| * This method permits to add active power bounds to the reactive limit implementation | ||
| * @param holder the reactive limit holder | ||
| */ | ||
| default void applyOwnerBounds(ReactiveLimitsHolder holder) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should not be part of the API and moved to impl
| @@ -0,0 +1,123 @@ | |||
| /** | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this one should be move to impl package, because I don't think it could be reused in the network store iidm impl.
It make sense to ReactiveCapabilityShapePolyhedron and ReactiveCapabilityShapePlane on API side as it is utility classes reusable in all IIDM implementations but I don't think it is the case for ReactiveCapabilityShapeImpl.
|
|
||
| @Override | ||
| public void applyOwnerBounds(ReactiveLimitsHolder holder) { | ||
| polyhedron.withActivePowerBounds(holder.getMinP(), holder.getMaxP()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with this approach is that if one change the minP and maxP of the generator for instance, the shape is not up-to date anymore. We probably need to store the holder ot an abstraction on it to always get the current value.



Please check if the PR fulfills these requirements
Does this PR already have an issue describing the problem?
Implement #3511
What kind of change does this PR introduce?
feature : Implement Model a PQU diagram for reactive limits
What is the current behavior?
#3511
What is the new behavior (if this is a feature change)?
Does this PR introduce a breaking change or deprecate an API?
If yes, please check if the following requirements are fulfilled
What changes might users need to make in their application due to this PR? (migration steps)
Other information: