Skip to content

Commit c012a93

Browse files
committed
feat(solver): Scaling P, Q slack variables and tests with jacobienne
Signed-off-by: Yoann Anezin <[email protected]> Signed-off-by: Yoann Anezin <[email protected]>
1 parent 1d9e4d5 commit c012a93

File tree

10 files changed

+349
-865
lines changed

10 files changed

+349
-865
lines changed

src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroLoadFlowParameters.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
/**
1414
* @author Jeanne Archambault {@literal <jeanne.archambault at artelys.com>}
1515
* @author Martin Debouté {@literal <martin.deboute at artelys.com>}
16+
* @author Amine Makhen {@literal <amine.makhen at artelys.com>}
1617
*/
1718
public class KnitroLoadFlowParameters extends AbstractExtension<LoadFlowParameters> {
1819

src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolverFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
/**
2626
* @author Pierre Arvy {@literal <pierre.arvy at artelys.com>}
2727
* @author Martin Debouté {@literal <martin.deboute at artelys.com>}
28+
* @author Amine Makhen {@literal <amine.makhen at artelys.com>}
2829
*/
2930
@AutoService(AcSolverFactory.class)
3031
public class KnitroSolverFactory implements AcSolverFactory {

src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolverParameters.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
* SPDX-License-Identifier: MPL-2.0
77
*/
8+
89
package com.powsybl.openloadflow.knitro.solver;
910

10-
import com.artelys.knitro.api.KNConstants;
1111
import com.powsybl.openloadflow.ac.solver.AcSolverParameters;
1212
import com.powsybl.openloadflow.ac.solver.LineSearchStateVectorScaling;
1313
import com.powsybl.openloadflow.ac.solver.MaxVoltageChangeStateVectorScaling;
@@ -25,8 +25,8 @@ public class KnitroSolverParameters implements AcSolverParameters {
2525
public static final int DEFAULT_GRADIENT_COMPUTATION_MODE = 1; // Specifies how the Jacobian matrix is computed
2626
public static final int DEFAULT_GRADIENT_USER_ROUTINE = 2; // If the user chooses to pass the exact Jacobian to knitro, specifies the sparsity pattern for the Jacobian matrix.
2727
public static final int DEFAULT_HESSIAN_COMPUTATION_MODE = 6; // Specifies how the Hessian matrix is computed. 6 means that the Hessian is approximated using the L-BFGS method, which is a quasi-Newton method.
28-
public static final double DEFAULT_LOWER_VOLTAGE_BOUND = 0; // Lower bound for voltage magnitude
29-
public static final double DEFAULT_UPPER_VOLTAGE_BOUND = 5; // Upper bound for voltage magnitude
28+
public static final double DEFAULT_LOWER_VOLTAGE_BOUND = 0.5; // Lower bound for voltage magnitude
29+
public static final double DEFAULT_UPPER_VOLTAGE_BOUND = 2; // Upper bound for voltage magnitude
3030
public static final int DEFAULT_MAX_ITERATIONS = 200;
3131
public static final double DEFAULT_STOPPING_CRITERIA = Math.pow(10, -6);
3232
public static final StateVectorScalingMode DEFAULT_STATE_VECTOR_SCALING_MODE = StateVectorScalingMode.NONE;

src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolverReacLim.java

Lines changed: 63 additions & 98 deletions
Large diffs are not rendered by default.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Copyright (c) 2025, Artelys (http://www.artelys.com/)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
9+
package com.powsybl.openloadflow.knitro.solver;
10+
11+
import com.powsybl.iidm.network.Network;
12+
import com.powsybl.iidm.network.*;
13+
import com.powsybl.loadflow.LoadFlow;
14+
import com.powsybl.loadflow.LoadFlowParameters;
15+
import com.powsybl.loadflow.LoadFlowResult;
16+
import com.powsybl.openloadflow.OpenLoadFlowParameters;
17+
18+
import java.util.*;
19+
20+
21+
import static org.ejml.UtilEjml.assertTrue;
22+
23+
/**
24+
* @author Pierre Arvy {@literal <pierre.arvy at artelys.com>}
25+
* @author Yoann Anezin {@literal <yoann.anezin at artelys.com>}
26+
*/
27+
public class ReacLimitsTestsUtils {
28+
private static final double DEFAULT_TOLERANCE = 1e-3;
29+
30+
public ArrayList<Integer> countAndSwitch(Network network, HashMap<String,Double> listMinQ, HashMap<String,Double> listMaxQ) throws Exception {
31+
int nmbSwitchQmin = 0;
32+
int nmbSwitchQmax = 0;
33+
int previousNmbBusPV = 0;
34+
ArrayList<Integer> switches = new ArrayList<>();
35+
for (Generator g : network.getGenerators()) {
36+
ArrayList<String> busVisited = new ArrayList<>();
37+
if (g.isVoltageRegulatorOn() && !busVisited.contains(g.getId())) {
38+
busVisited.add(g.getId());
39+
previousNmbBusPV += 1;
40+
}
41+
Terminal t = g.getTerminal();
42+
double v = t.getBusView().getBus().getV();
43+
if (g.isVoltageRegulatorOn()) {
44+
double Qming = g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP());
45+
double Qmaxg = g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP());
46+
if (!(v + DEFAULT_TOLERANCE > g.getTargetV() && v - DEFAULT_TOLERANCE < g.getTargetV())) {
47+
if (-t.getQ() + DEFAULT_TOLERANCE > Qming &&
48+
-t.getQ() - DEFAULT_TOLERANCE < Qming) {
49+
nmbSwitchQmin++;
50+
assertTrue(v > g.getTargetV(), "V below its target on Qmin switch of bus "
51+
+ t.getBusView().getBus().getId() + ". Current generator checked : " + g.getId());
52+
g.setTargetQ(listMinQ.get(g.getId()));
53+
} else if (-t.getQ() + DEFAULT_TOLERANCE > Qmaxg &&
54+
-t.getQ() - DEFAULT_TOLERANCE < Qmaxg) {
55+
nmbSwitchQmax++;
56+
assertTrue(v < g.getTargetV(), "V above its target on a Qmax switch of bus "
57+
+ t.getBusView().getBus().getId() + ". Current generator checked : " + g.getId());
58+
g.setTargetQ(listMaxQ.get(g.getId()));
59+
} else {
60+
throw new Exception("Value of Q not matching Qmin nor Qmax on the switch of bus "
61+
+ t.getBusView().getBus().getId() + ". Current generator checked : " + g.getId());
62+
}
63+
g.setVoltageRegulatorOn(false);
64+
65+
}
66+
}
67+
}
68+
switches.add(nmbSwitchQmin);
69+
switches.add(nmbSwitchQmax);
70+
switches.add(previousNmbBusPV);
71+
return switches;
72+
}
73+
74+
public void verifNewtonRaphson (Network network, LoadFlowParameters parameters, LoadFlow.Runner loadFlowRunner, int nbreIter) {
75+
OpenLoadFlowParameters.get(parameters).setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.NONE);
76+
parameters.setVoltageInitMode(LoadFlowParameters.VoltageInitMode.PREVIOUS_VALUES);
77+
OpenLoadFlowParameters.get(parameters).setMaxNewtonRaphsonIterations(nbreIter)
78+
.setReportedFeatures(Collections.singleton(OpenLoadFlowParameters.ReportedFeatures.NEWTON_RAPHSON_LOAD_FLOW));
79+
OpenLoadFlowParameters.get(parameters).setAcSolverType("NEWTON_RAPHSON");
80+
LoadFlowResult result = loadFlowRunner.run(network, parameters);
81+
assertTrue(result.isFullyConverged());
82+
}
83+
84+
public void checkSwitches(Network network, HashMap<String,Double> listMinQ, HashMap<String,Double> listMaxQ) {
85+
try {
86+
ArrayList<Integer> switches = countAndSwitch(network, listMinQ, listMaxQ);
87+
assertTrue(switches.get(2) > switches.get(1) + switches.get(0),
88+
"No control on any voltage magnitude : all buses switched");
89+
System.out.println(switches.get(0) + " switches to PQ with Q = Qlow and " + switches.get(1) + " with Q = Qup");
90+
} catch (Exception e) {
91+
throw new RuntimeException(e);
92+
}
93+
}
94+
}

src/main/java/com/powsybl/openloadflow/knitro/solver/ResilientKnitroSolver.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ public class ResilientKnitroSolver extends AbstractAcSolver {
4545

4646
// Penalty weights in the objective function
4747
private final double wK = 1.0;
48-
private final double wP = 100.0;
49-
private final double wQ = 50.0;
50-
private final double wV = 1.0;
48+
private final double wP = 1.0;
49+
private final double wQ = 1.0;
50+
private final double wV = 100.0;
5151

5252
// Lambda
53-
private final double lambda = 2.0;
53+
private final double lambda = 3.0;
5454

5555
// Number of Load Flows (LF) variables in the system
5656
private final int numLFVariables;
@@ -557,6 +557,9 @@ private ResilientKnitroProblem(
557557
// Initialize slack variables (≥ 0, initial value = 0)
558558
for (int i = slackStartIndex; i < numTotalVariables; i++) {
559559
lowerBounds.set(i, 0.0);
560+
// if (i >= slackVStartIndex) {
561+
// upperBounds.set(i, 0.0);
562+
// }
560563
}
561564

562565
// Set bounds for voltage variables based on Knitro parameters

0 commit comments

Comments
 (0)