listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ int numbreLimReacAdded = fixReacLim(network, listMinQ, listMaxQ);
+
+ knitroWritter.write("[" + LocalDateTime.now() + "]", false);
+ knitroWritter.write(numbreLimReacAdded + " bus pour lesquels les limites réactif ont été ajoutées", true);
+ logsWriting(knitroLoadFlowParameters, knitroWritter);
+ switch (perturbProcess) {
+ case "ActivePowerGlobal":
+ ReacLimitsTestsUtils.applyActivePowerPerturbation(network, perturbValue);
+ knitroWritter.write("Perturbed by global loads' increasement (All multiplied by " +
+ perturbValue * 100 + "% of total load)", true);
+ break;
+ case "ActivePowerLocal":
+ PerturbationFactory.applyActivePowerPerturbation(network,
+ PerturbationFactory.getActivePowerPerturbation(network), perturbValue);
+ knitroWritter.write("Perturbed by uniq big load (" + perturbValue * 100 + "% of total load)", true);
+ break;
+ case "ReactivePower":
+ PerturbationFactory.applyReactivePowerPerturbation(network,
+ PerturbationFactory.getReactivePowerPerturbation(network), perturbValue);
+ knitroWritter.write("Perturbed by power injection by the shunt (Target Q = " + perturbValue + ")", true);
+ break;
+ case "None":
+ knitroWritter.write("No Pertubations", true);
+ break;
+ default:
+ knitroWritter.write("No Pertubations, you have miswritten the pertubation's instruction", true);
+ break;
+ }
+
+ // solve and check
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ long end = System.nanoTime();
+ knitroWritter.write("Durée du test : " + (end - start) * 1e-9 + " secondes", true);
+ knitroWritter.write("Nombre d'itérations : " + result.getComponentResults().get(0).getIterationCount(), true);
+ knitroWritter.write("Status à l'arrivée : " + result.getComponentResults().get(0).getStatus().name(), true);
+ }
+
+ @BeforeEach
+ void setUp() {
+ loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new SparseMatrixFactory()));
+ parameters = new LoadFlowParameters().setUseReactiveLimits(true)
+ .setDistributedSlack(false);
+ KnitroLoadFlowParameters knitroLoadFlowParameters = new KnitroLoadFlowParameters(); // set gradient computation mode
+ knitroLoadFlowParameters.setGradientComputationMode(1);
+ knitroLoadFlowParameters.setMaxIterations(2000);
+ knitroLoadFlowParameters.setKnitroSolverType(KnitroSolverParameters.KnitroSolverType.REACTIVLIMITS);
+ parameters.addExtension(KnitroLoadFlowParameters.class, knitroLoadFlowParameters);
+ //parameters.setVoltageInitMode(LoadFlowParameters.VoltageInitMode.DC_VALUES);
+ //OpenLoadFlowParameters.create(parameters).setAcSolverType("NEWTON_RAPHSON");
+// OpenLoadFlowParameters.create(parameters).setAcSolverType(KnitroSolverFactory.NAME);
+ OpenLoadFlowParameters.get(parameters).setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE);
+
+ }
+
+ /**
+ *
+ * G1 LD2 G3
+ * | L12 | L23 |
+ * | ------- | ------- |
+ * B1 B2 B3
+ *
+ */
+ @Test
+ public void createNetworkWithT2wtActivePower() {
+
+ Network network = Network.create("yoann-n", "test");
+
+ Substation substation1 = network.newSubstation()
+ .setId("SUBSTATION1")
+ .setCountry(Country.FR)
+ .add();
+ VoltageLevel vl1 = substation1.newVoltageLevel()
+ .setId("VL_1")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl1.getBusBreakerView().newBus()
+ .setId("BUS_1")
+ .add();
+ Generator g1 = vl1.newGenerator()
+ .setId("GEN_1")
+ .setBus("BUS_1")
+ .setMinP(0.0)
+ .setMaxP(140)
+ .setTargetP(25)
+ .setTargetV(135)
+ .setVoltageRegulatorOn(true)
+ .add();
+ g1.newMinMaxReactiveLimits().setMinQ(-30000.0).setMaxQ(30000.0).add();
+
+ Substation substation = network.newSubstation()
+ .setId("SUBSTATION")
+ .setCountry(Country.FR)
+ .add();
+ VoltageLevel vl2 = substation.newVoltageLevel()
+ .setId("VL_2")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl2.getBusBreakerView().newBus()
+ .setId("BUS_2")
+ .add();
+ vl2.newLoad()
+ .setId("LOAD_2")
+ .setBus("BUS_2")
+ .setP0(35)
+ .setQ0(20)
+ .add();
+
+ VoltageLevel vl3 = substation.newVoltageLevel()
+ .setId("VL_3")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl3.getBusBreakerView().newBus()
+ .setId("BUS_3")
+ .add();
+ Generator g3 = vl3.newGenerator()
+ .setId("GEN_3")
+ .setBus("BUS_3")
+ .setMinP(0.0)
+ .setMaxP(140)
+ .setTargetP(15)
+ .setTargetV(130)
+ .setVoltageRegulatorOn(true)
+ .add();
+ g3.newMinMaxReactiveLimits().setMinQ(-3000.0).setMaxQ(3000.0).add();
+
+ network.newLine()
+ .setId("LINE_12")
+ .setBus1("BUS_1")
+ .setBus2("BUS_2")
+ .setR(1.05)
+ .setX(10.0)
+ .setG1(0.0000005)
+ .add();
+ network.newLine()
+ .setId("LINE_23")
+ .setBus1("BUS_2")
+ .setBus2("BUS_3")
+ .setR(1.05)
+ .setX(10.0)
+ .setG1(0.0000005)
+ .add();
+
+ OpenLoadFlowParameters.get(parameters)
+// .setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE)
+ .setSlackBusSelectionMode(SlackBusSelectionMode.NAME)
+ .setSlackBusId("VL_1_0");
+
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_3bus_Active_Power_Perturbation.txt";
+ testprocess(logFile, network, "ActivePowerLocal", 40.0);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ /**
+ *
+ * G1 LD2 G3
+ * | L12 | L23 |
+ * | ------- | ------- |
+ * B1 B2 B3
+ *
+ */
+ @Test
+ public void createNetworkWithT2wtReactivePower() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+
+ Network network = Network.create("yoann-n", "test");
+
+ Substation substation1 = network.newSubstation()
+ .setId("SUBSTATION1")
+ .setCountry(Country.FR)
+ .add();
+ VoltageLevel vl1 = substation1.newVoltageLevel()
+ .setId("VL_1")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl1.getBusBreakerView().newBus()
+ .setId("BUS_1")
+ .add();
+ Generator g1 = vl1.newGenerator()
+ .setId("GEN_1")
+ .setBus("BUS_1")
+ .setMinP(0.0)
+ .setMaxP(140)
+ .setTargetP(25)
+ .setTargetV(135)
+ .setVoltageRegulatorOn(true)
+ .add();
+ g1.newMinMaxReactiveLimits().setMinQ(-3000.0).setMaxQ(3000.0).add();
+ listMinQ.put(g1.getId(), -3000.0);
+ listMaxQ.put(g1.getId(), 3000.0);
+
+ Substation substation = network.newSubstation()
+ .setId("SUBSTATION")
+ .setCountry(Country.FR)
+ .add();
+ VoltageLevel vl2 = substation.newVoltageLevel()
+ .setId("VL_2")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl2.getBusBreakerView().newBus()
+ .setId("BUS_2")
+ .add();
+ vl2.newLoad()
+ .setId("LOAD_2")
+ .setBus("BUS_2")
+ .setP0(35)
+ .setQ0(20)
+ .add();
+
+ VoltageLevel vl3 = substation.newVoltageLevel()
+ .setId("VL_3")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl3.getBusBreakerView().newBus()
+ .setId("BUS_3")
+ .add();
+ Generator g3 = vl3.newGenerator()
+ .setId("GEN_3")
+ .setBus("BUS_3")
+ .setMinP(0.0)
+ .setMaxP(140)
+ .setTargetP(15)
+ .setTargetV(130)
+ .setVoltageRegulatorOn(true)
+ .add();
+ g3.newMinMaxReactiveLimits().setMinQ(-3000.0).setMaxQ(3000.0).add();
+ listMinQ.put(g3.getId(), -3000.0);
+ listMaxQ.put(g3.getId(), 3000.0);
+
+ network.newLine()
+ .setId("LINE_12")
+ .setBus1("BUS_1")
+ .setBus2("BUS_2")
+ .setR(1.05)
+ .setX(10.0)
+ .setG1(0.0000005)
+ .add();
+ network.newLine()
+ .setId("LINE_23")
+ .setBus1("BUS_2")
+ .setBus2("BUS_3")
+ .setR(1.05)
+ .setX(10.0)
+ .setG1(0.0000005)
+ .add();
+ network.getVoltageLevel("VL_1").newShuntCompensator()
+ .setId("SC")
+ .setBus("BUS_1")
+ .setConnectableBus("BUS_1")
+ .setSectionCount(1)
+ .newLinearModel()
+ .setBPerSection(3.25 * Math.pow(10, -3))
+ .setMaximumSectionCount(1)
+ .add()
+ .add();
+
+ OpenLoadFlowParameters.get(parameters)
+// .setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE)
+ .setSlackBusSelectionMode(SlackBusSelectionMode.NAME)
+ .setSlackBusId("VL_1_0");
+
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_3bus_Reactive_Power_Perturbation.txt";
+ testprocess(logFile, network, "ReactivePower", 1E10);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ /**
+ *
+ * G1 LD2 G3
+ * | L12 | L23 |
+ * | ------- | ------- |
+ * B1 B2 B3
+ *
+ */
+ @Test
+ public void createNetworkWithT2wtVoltage() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = Network.create("yoann-n", "test");
+
+ Substation substation1 = network.newSubstation()
+ .setId("SUBSTATION1")
+ .setCountry(Country.FR)
+ .add();
+ VoltageLevel vl1 = substation1.newVoltageLevel()
+ .setId("VL_1")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl1.getBusBreakerView().newBus()
+ .setId("BUS_1")
+ .add();
+ Generator g1 = vl1.newGenerator()
+ .setId("GEN_1")
+ .setBus("BUS_1")
+ .setMinP(0.0)
+ .setMaxP(140)
+ .setTargetP(25)
+ .setTargetV(135)
+ .setVoltageRegulatorOn(true)
+ .add();
+ g1.newMinMaxReactiveLimits().setMinQ(-3000.0).setMaxQ(3000.0).add();
+
+ Substation substation = network.newSubstation()
+ .setId("SUBSTATION")
+ .setCountry(Country.FR)
+ .add();
+ VoltageLevel vl2 = substation.newVoltageLevel()
+ .setId("VL_2")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl2.getBusBreakerView().newBus()
+ .setId("BUS_2")
+ .add();
+ vl2.newLoad()
+ .setId("LOAD_2")
+ .setBus("BUS_2")
+ .setP0(35)
+ .setQ0(20)
+ .add();
+
+ VoltageLevel vl3 = substation.newVoltageLevel()
+ .setId("VL_3")
+ .setNominalV(132.0)
+ .setLowVoltageLimit(118.8)
+ .setHighVoltageLimit(145.2)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vl3.getBusBreakerView().newBus()
+ .setId("BUS_3")
+ .add();
+ Generator g3 = vl3.newGenerator()
+ .setId("GEN_3")
+ .setBus("BUS_3")
+ .setMinP(0.0)
+ .setMaxP(140)
+ .setTargetP(15)
+ .setTargetV(130)
+ .setVoltageRegulatorOn(true)
+ .add();
+ g3.newMinMaxReactiveLimits().setMinQ(-3000.0).setMaxQ(3000.0).add();
+
+ network.newLine()
+ .setId("LINE_12")
+ .setBus1("BUS_1")
+ .setBus2("BUS_2")
+ .setR(1.05)
+ .setX(10.0)
+ .setG1(0.0000005)
+ .add();
+ network.newLine()
+ .setId("LINE_23")
+ .setBus1("BUS_2")
+ .setBus2("BUS_3")
+ .setR(1.05)
+ .setX(10.0)
+ .setG1(0.0000005)
+ .add();
+
+ OpenLoadFlowParameters.get(parameters)
+// .setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE)
+ .setSlackBusSelectionMode(SlackBusSelectionMode.NAME)
+ .setVoltageRemoteControl(false)
+ .setSlackBusId("VL_1_0");
+
+ // Line Characteristics in per-unit
+ double rPU = 0.0;
+ double xPU = 1e-5;
+ // Voltage Mismatch
+ double alpha = 0.75;
+ PerturbationFactory.VoltagePerturbation perturbation = PerturbationFactory.getVoltagePerturbation(network);
+ System.out.println(perturbation);
+ PerturbationFactory.applyVoltagePerturbation(network, perturbation, rPU, xPU, alpha);
+
+ fixReacLim(network, listMinQ, listMaxQ);
+// OpenLoadFlowParameters.get(parameters).setAcSolverType("NEWTON_RAPHSON");
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee14ActivePowerPerturbed() {
+ String perturbation = "ActivePowerLocal";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee14_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create14();
+ testprocess(logFile, network, perturbation, 1.2);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee30ActivePowerPerturbed() {
+ String perturbation = "ActivePowerLocal";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee30_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create30();
+ testprocess(logFile, network, perturbation, 1.2);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee30ReactivePowerPerturbed() {
+ String perturbation = "ReactivePower";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee30_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create30();
+ testprocess(logFile, network, perturbation, 1E11);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee30VoltagePerturbed() {
+ // set up network
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create30();
+ fixReacLim(network, listMinQ, listMaxQ);
+
+ // Line Characteristics in per-unit
+ double rPU = 0.0;
+ double xPU = 1e-5;
+ // Voltage Mismatch
+ double alpha = 0.95;
+ PerturbationFactory.VoltagePerturbation perturbation = PerturbationFactory.getVoltagePerturbation(network);
+ PerturbationFactory.applyVoltagePerturbation(network, perturbation, rPU, xPU, alpha);
+
+ // solve and check
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee118ActivePowerPerturbed() {
+ String perturbation = "ActivePowerLocal";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee118_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create118();
+ testprocess(logFile, network, perturbation, 1.2);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee118ReactivePowerPerturbed() {
+ String perturbation = "ReactivePower";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee118_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create118();
+ testprocess(logFile, network, perturbation, 1E10);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee118VoltagePerturbed() {
+ // set up network
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create118();
+ fixReacLim(network, listMinQ, listMaxQ);
+
+ // Line Characteristics in per-unit
+ double rPU = 0.0;
+ double xPU = 1e-5;
+ // Voltage Mismatch
+ double alpha = 0.95;
+ PerturbationFactory.VoltagePerturbation perturbation = PerturbationFactory.getVoltagePerturbation(network);
+ PerturbationFactory.applyVoltagePerturbation(network, perturbation, rPU, xPU, alpha);
+
+ // solve and check
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee300ActivePowerPerturbed() {
+ String perturbation = "ActivePowerGlobal";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee300_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create300();
+ testprocess(logFile, network, perturbation, 1.2);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ public void ieee300ReactivePowerPerturbed() {
+ String perturbation = "ReactivePower";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_ieee300_" + perturbation + ".txt";
+ Network network = IeeeCdfNetworkFactory.create300();
+ testprocess(logFile, network, perturbation, 1E11);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ void testxiidm1888ActivePowerOneLoadPerturbed() throws IOException {
+ String perturbation = "ActivePowerLocal";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_Rte1888_" + perturbation + ".txt";
+ Network network = Network.read("D:\\Documents\\Réseaux\\rte1888.xiidm");
+ testprocess(logFile, network, perturbation, 1.2);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 20);
+ }
+
+ @Test
+ void testxiidm6515() throws IOException {
+ String perturbation = "None";
+ logFile = "D:\\Documents\\Logs_Tests\\Logs_Rte6515_" + perturbation + ".txt";
+ Network network = Network.read("D:\\Documents\\Réseaux\\rte6515.xiidm");
+ testprocess(logFile, network, perturbation, 1.2);
+ }
+}
diff --git a/src/test/java/com/powsybl/openloadflow/knitro/solver/ReactiveNoJacobienneTest.java b/src/test/java/com/powsybl/openloadflow/knitro/solver/ReactiveNoJacobienneTest.java
new file mode 100644
index 0000000..064acdb
--- /dev/null
+++ b/src/test/java/com/powsybl/openloadflow/knitro/solver/ReactiveNoJacobienneTest.java
@@ -0,0 +1,438 @@
+/**
+ * Copyright (c) 2025, Artelys (http://www.artelys.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
+ */
+
+package com.powsybl.openloadflow.knitro.solver;
+
+import com.powsybl.iidm.network.Network;
+import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory;
+import com.powsybl.iidm.network.*;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
+import com.powsybl.loadflow.LoadFlow;
+import com.powsybl.loadflow.LoadFlowParameters;
+import com.powsybl.loadflow.LoadFlowResult;
+import com.powsybl.math.matrix.DenseMatrixFactory;
+import com.powsybl.openloadflow.OpenLoadFlowParameters;
+import com.powsybl.openloadflow.OpenLoadFlowProvider;
+import com.powsybl.openloadflow.network.EurostagFactory;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+import static com.powsybl.openloadflow.util.LoadFlowAssert.assertReactivePowerEquals;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author Pierre Arvy {@literal }
+ * @author Yoann Anezin {@literal }
+ */
+public class ReactiveNoJacobienneTest {
+ private static final double DEFAULT_TOLERANCE = 1e-2;
+ private LoadFlow.Runner loadFlowRunner;
+ private LoadFlowParameters parameters;
+
+ @BeforeEach
+ void setUp() {
+ loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory()));
+ parameters = new LoadFlowParameters().setUseReactiveLimits(true)
+ .setDistributedSlack(false);
+ KnitroLoadFlowParameters knitroLoadFlowParameters = new KnitroLoadFlowParameters(); // set gradient computation mode
+ knitroLoadFlowParameters.setGradientComputationMode(2);
+ knitroLoadFlowParameters.setMaxIterations(300);
+ knitroLoadFlowParameters.setKnitroSolverType(KnitroSolverParameters.KnitroSolverType.REACTIVLIMITS);
+ parameters.addExtension(KnitroLoadFlowParameters.class, knitroLoadFlowParameters);
+ //parameters.setVoltageInitMode(LoadFlowParameters.VoltageInitMode.DC_VALUES);
+ OpenLoadFlowParameters.create(parameters).setAcSolverType(KnitroSolverFactory.NAME);
+ OpenLoadFlowParameters.get(parameters).setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE);
+ }
+
+ @Test
+ void testReacLimEurostagQlow() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(250)
+ .setMaxQ(300)
+ .add();
+ listMinQ.put(gen2.getId(), 250.0);
+ listMaxQ.put(gen2.getId(), 300.0);
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+// assertReactivePowerEquals(-8.094, gen.getTerminal());
+ assertReactivePowerEquals(-250, gen2.getTerminal()); // GEN is correctly limited to 250 MVar
+ assertReactivePowerEquals(250, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimEurostagQup() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(100)
+ .add();
+ listMinQ.put(gen2.getId(), 0.0);
+ listMaxQ.put(gen2.getId(), 100.0);
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+// assertReactivePowerEquals(-164.315, gen.getTerminal());
+// assertReactivePowerEquals(-100, gen2.getTerminal()); // GEN is correctly limited to 100 MVar
+// assertReactivePowerEquals(100, ngen2Nhv1.getTerminal1());
+// assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimEurostagQupWithLoad() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(100)
+ .add();
+ listMinQ.put(gen2.getId(), 0.0);
+ listMaxQ.put(gen2.getId(), 100.0);
+ Load load2 = vlgen2.newLoad()
+ .setId("LOAD2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setP0(0.0)
+ .setQ0(30.0)
+ .add();
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+ //assertReactivePowerEquals(-196.263, gen.getTerminal());
+ assertReactivePowerEquals(-100, gen2.getTerminal()); // GEN is correctly limited to 100 MVar
+ assertReactivePowerEquals(70, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimEurostagQupWithGen() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(100)
+ .add();
+ listMinQ.put(gen2.getId(), 0.0);
+ listMaxQ.put(gen2.getId(), 100.0);
+ Generator gen2Bis = vlgen2.newGenerator()
+ .setId("GEN2BIS")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(50)
+ .add();
+ gen2Bis.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(40)
+ .add();
+ listMinQ.put(gen2Bis.getId(), 0.0);
+ listMaxQ.put(gen2Bis.getId(), 40.0);
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+ assertReactivePowerEquals(-122.735, gen.getTerminal());
+ assertReactivePowerEquals(-100, gen2.getTerminal()); // GEN is correctly limited to 100 MVar
+ assertReactivePowerEquals(140.0, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee14() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create14();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee30() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create30();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee118() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create118();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee300() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create300();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+}
diff --git a/src/test/java/com/powsybl/openloadflow/knitro/solver/ReactiveWithJacobienneTest.java b/src/test/java/com/powsybl/openloadflow/knitro/solver/ReactiveWithJacobienneTest.java
new file mode 100644
index 0000000..1e4cea0
--- /dev/null
+++ b/src/test/java/com/powsybl/openloadflow/knitro/solver/ReactiveWithJacobienneTest.java
@@ -0,0 +1,456 @@
+/**
+ * Copyright (c) 2025, Artelys (http://www.artelys.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
+ */
+package com.powsybl.openloadflow.knitro.solver;
+
+import com.powsybl.iidm.network.Network;
+import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory;
+import com.powsybl.iidm.network.*;
+import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
+import com.powsybl.loadflow.LoadFlow;
+import com.powsybl.loadflow.LoadFlowParameters;
+import com.powsybl.loadflow.LoadFlowResult;
+import com.powsybl.math.matrix.SparseMatrixFactory;
+import com.powsybl.openloadflow.OpenLoadFlowParameters;
+import com.powsybl.openloadflow.OpenLoadFlowProvider;
+import com.powsybl.openloadflow.network.EurostagFactory;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+
+import static com.powsybl.openloadflow.util.LoadFlowAssert.assertReactivePowerEquals;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author Pierre Arvy {@literal }
+ * @author Yoann Anezin {@literal }
+ */
+public class ReactiveWithJacobienneTest {
+ private static final double DEFAULT_TOLERANCE = 1e-3;
+ private LoadFlow.Runner loadFlowRunner;
+ private LoadFlowParameters parameters;
+
+ @BeforeEach
+ void setUp() {
+ loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new SparseMatrixFactory()));
+ parameters = new LoadFlowParameters().setUseReactiveLimits(true)
+ .setDistributedSlack(false);
+ KnitroLoadFlowParameters knitroLoadFlowParameters = new KnitroLoadFlowParameters(); // set gradient computation mode
+ knitroLoadFlowParameters.setGradientComputationMode(1);
+ knitroLoadFlowParameters.setMaxIterations(300);
+ knitroLoadFlowParameters.setKnitroSolverType(KnitroSolverParameters.KnitroSolverType.REACTIVLIMITS);
+ parameters.addExtension(KnitroLoadFlowParameters.class, knitroLoadFlowParameters);
+ //parameters.setVoltageInitMode(LoadFlowParameters.VoltageInitMode.DC_VALUES);
+ //OpenLoadFlowParameters.create(parameters).setAcSolverType("NEWTON_RAPHSON");
+ OpenLoadFlowParameters.create(parameters).setAcSolverType(KnitroSolverFactory.NAME);
+ OpenLoadFlowParameters.get(parameters).setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE);
+ }
+
+ @Test
+ void testReacLimEurostagQlow() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(250)
+ .setMaxQ(300)
+ .add();
+ listMinQ.put(gen2.getId(), 250.0);
+ listMaxQ.put(gen2.getId(), 300.0);
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+ //assertReactivePowerEquals(-8.094, gen.getTerminal());
+ assertReactivePowerEquals(-250, gen2.getTerminal()); // GEN is correctly limited to 250 MVar
+ assertReactivePowerEquals(250, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimEurostagQup() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(100)
+ .add();
+ listMinQ.put(gen2.getId(), 0.0);
+ listMaxQ.put(gen2.getId(), 100.0);
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+
+ parameters.setUseReactiveLimits(true);
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+ assertReactivePowerEquals(-164.3169, gen.getTerminal());
+ assertReactivePowerEquals(-100, gen2.getTerminal()); // GEN is correctly limited to 100 MVar
+ assertReactivePowerEquals(100, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimEurostagQupWithLoad() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(100)
+ .add();
+ listMinQ.put(gen2.getId(), 0.0);
+ listMaxQ.put(gen2.getId(), 100.0);
+ Load load2 = vlgen2.newLoad()
+ .setId("LOAD2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setP0(0.0)
+ .setQ0(30.0)
+ .add();
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+ assertReactivePowerEquals(-196.264, gen.getTerminal());
+ assertReactivePowerEquals(-100, gen2.getTerminal()); // GEN is correctly limited to 100 MVar
+ assertReactivePowerEquals(70, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimEurostagQupWithGen() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ Network network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
+
+ // access to already created equipments
+ Load load = network.getLoad("LOAD");
+
+ VoltageLevel vlgen = network.getVoltageLevel("VLGEN");
+ TwoWindingsTransformer nhv2Nload = network.getTwoWindingsTransformer("NHV2_NLOAD");
+ Generator gen = network.getGenerator("GEN");
+ Substation p1 = network.getSubstation("P1");
+
+ // reduce GEN reactive range
+ gen.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(280)
+ .add();
+ listMinQ.put(gen.getId(), -280.0);
+ listMaxQ.put(gen.getId(), 280.0);
+
+ // create a new generator GEN2
+ VoltageLevel vlgen2 = p1.newVoltageLevel()
+ .setId("VLGEN2")
+ .setNominalV(24.0)
+ .setTopologyKind(TopologyKind.BUS_BREAKER)
+ .add();
+ vlgen2.getBusBreakerView().newBus()
+ .setId("NGEN2")
+ .add();
+ Generator gen2 = vlgen2.newGenerator()
+ .setId("GEN2")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(100)
+ .add();
+ gen2.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(100)
+ .add();
+ listMinQ.put(gen2.getId(), 0.0);
+ listMaxQ.put(gen2.getId(), 100.0);
+ Generator gen2Bis = vlgen2.newGenerator()
+ .setId("GEN2BIS")
+ .setBus("NGEN2")
+ .setConnectableBus("NGEN2")
+ .setMinP(-9999.99)
+ .setMaxP(9999.99)
+ .setVoltageRegulatorOn(true)
+ .setTargetV(24.5)
+ .setTargetP(50)
+ .add();
+ gen2Bis.newMinMaxReactiveLimits()
+ .setMinQ(0)
+ .setMaxQ(40)
+ .add();
+ listMinQ.put(gen2Bis.getId(), 0.0);
+ listMaxQ.put(gen2Bis.getId(), 40.0);
+ int zb380 = 380 * 380 / 100;
+ TwoWindingsTransformer ngen2Nhv1 = p1.newTwoWindingsTransformer()
+ .setId("NGEN2_NHV1")
+ .setBus1("NGEN2")
+ .setConnectableBus1("NGEN2")
+ .setRatedU1(24.0)
+ .setBus2("NHV1")
+ .setConnectableBus2("NHV1")
+ .setRatedU2(400.0)
+ .setR(0.24 / 1800 * zb380)
+ .setX(Math.sqrt(10 * 10 - 0.24 * 0.24) / 1800 * zb380)
+ .add();
+
+ // fix active power balance
+ load.setP0(699.838);
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged());
+ //assertReactivePowerEquals(-122.715, gen.getTerminal());
+ assertReactivePowerEquals(-100, gen2.getTerminal()); // GEN is correctly limited to 100 MVar
+ assertReactivePowerEquals(140.0, ngen2Nhv1.getTerminal1());
+ assertReactivePowerEquals(-200, nhv2Nload.getTerminal2());
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee14() { /* Unfeasible Point */
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create14();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee30() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create30();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee118() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create118();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testReacLimIeee300() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = IeeeCdfNetworkFactory.create300();
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTerminal().getBusView().getBus().getP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTerminal().getBusView().getBus().getP()));
+ }
+ }
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+
+ @Test
+ void testxiidm() {
+ HashMap listMinQ = new HashMap<>();
+ HashMap listMaxQ = new HashMap<>();
+ parameters.setUseReactiveLimits(true);
+ Network network = Network.read("D:\\Documents\\Réseaux\\rte1888.xiidm");
+ LoadFlowResult result = loadFlowRunner.run(network, parameters);
+ assertTrue(result.isFullyConverged(), "Not Fully Converged");
+ for (var g : network.getGenerators()) {
+ if (g.getReactiveLimits().getMinQ(g.getTargetP()) > -1.7976931348623157E308) {
+ listMinQ.put(g.getId(), g.getReactiveLimits().getMinQ(g.getTargetP()));
+ listMaxQ.put(g.getId(), g.getReactiveLimits().getMaxQ(g.getTargetP()));
+ }
+ }
+ ReacLimitsTestsUtils.checkSwitches(network, listMinQ, listMaxQ);
+ ReacLimitsTestsUtils.verifNewtonRaphson(network, parameters, loadFlowRunner, 0);
+ }
+}
diff --git a/src/test/java/com/powsybl/openloadflow/knitro/solver/ResilientAcLoadFlowPerturbationTest.java b/src/test/java/com/powsybl/openloadflow/knitro/solver/ResilientAcLoadFlowPerturbationTest.java
index 44bd7a4..8ec0ac8 100644
--- a/src/test/java/com/powsybl/openloadflow/knitro/solver/ResilientAcLoadFlowPerturbationTest.java
+++ b/src/test/java/com/powsybl/openloadflow/knitro/solver/ResilientAcLoadFlowPerturbationTest.java
@@ -54,7 +54,8 @@ void setUp() {
private void configureSolver(String solver) {
OpenLoadFlowParameters.create(parameters)
.setSlackBusSelectionMode(SlackBusSelectionMode.MOST_MESHED)
- .setAcSolverType(solver);
+ .setAcSolverType(solver)
+ .setVoltageInitModeOverride(OpenLoadFlowParameters.VoltageInitModeOverride.FULL_VOLTAGE);
if (RKN.equals(solver)) {
KnitroLoadFlowParameters knitroParams = new KnitroLoadFlowParameters();
@@ -124,7 +125,7 @@ void testVoltagePerturbationOnVariousI3ENetworks(NetworkPair pair) {
double rPU = 0.0;
double xPU = 1e-5;
// Voltage Mismatch
- double alpha = 0.95;
+ double alpha = 1.0;
voltagePerturbationTest(rknNetwork, nrNetwork, baseFilename, rPU, xPU, alpha);
}
@@ -204,7 +205,6 @@ void testActivePowerPerturbationOnVariousI3ENetworks(NetworkPair pair) {
// Final perturbed load's percentage
double alpha = 0.10;
-
activePowerPerturbationTest(rknNetwork, nrNetwork, baseFilename, alpha);
}
diff --git a/src/test/java/com/powsybl/openloadflow/knitro/solver/utils/TempoTest.java b/src/test/java/com/powsybl/openloadflow/knitro/solver/utils/TempoTest.java
new file mode 100644
index 0000000..73190ae
--- /dev/null
+++ b/src/test/java/com/powsybl/openloadflow/knitro/solver/utils/TempoTest.java
@@ -0,0 +1,101 @@
+package com.powsybl.openloadflow.knitro.solver.utils;
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * This example demonstrates how to use Knitro to solve the following
+ * simple mathematical program with equilibrium/complementarity
+ * constraints (MPEC/MPCC).
+ *
+ * min (x0 - 5)^2 + (2 x1 + 1)^2
+ * s.t. -1.5 x0 + 2 x1 + x2 - 0.5 x3 + x4 = 2
+ * x2 complements (3 x0 - x1 - 3)
+ * x3 complements (-x0 + 0.5 x1 + 4)
+ * x4 complements (-x0 - x1 + 7)
+ * x0, x1, x2, x3, x4 >= 0
+ *
+ * The complementarity constraints must be converted so that one
+ * nonnegative variable complements another nonnegative variable.
+ *
+ * min (x0 - 5)^2 + (2 x1 + 1)^2
+ * s.t. -1.5 x0 + 2 x1 + x2 - 0.5 x3 + x4 = 2 (c0)
+ * 3 x0 - x1 - 3 - x5 = 0 (c1)
+ * -x0 + 0.5 x1 + 4 - x6 = 0 (c2)
+ * -x0 - x1 + 7 - x7 = 0 (c3)
+ * x2 complements x5
+ * x3 complements x6
+ * x4 complements x7
+ * x0, x1, x2, x3, x4, x5, x6, x7 >= 0
+ *
+ * The solution is (1, 0, 3.5, 0, 0, 0, 3, 6), with objective value 17.
+ *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+import com.artelys.knitro.api.*;
+
+import java.util.Arrays;
+
+public final class TempoTest {
+
+ private TempoTest() {
+ throw new UnsupportedOperationException();
+ }
+
+ private static class ProblemMPEC1 extends KNProblem {
+ public ProblemMPEC1() throws KNException {
+ super(8, 4);
+
+ // Variables
+ setVarLoBnds(Arrays.asList(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+ setXInitial(Arrays.asList(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+
+ // Constraints
+ setConEqBnds(Arrays.asList(2.0, 3.0, -4.0, -7.0));
+ setCompConstraintsTypes(Arrays.asList(KNConstants.KN_CCTYPE_VARVAR, KNConstants.KN_CCTYPE_VARVAR, KNConstants.KN_CCTYPE_VARVAR));
+ // x2 x3 and x4 complements respectively x5, x6 and x7
+ setCompConstraintsParts(Arrays.asList(2, 3, 4), Arrays.asList(5, 6, 7));
+
+ // Objective structure
+ /* Note that the objective (x0 - 5)^2 + (2 x1 + 1)^2 when
+ * expanded becomes:
+ * x0^2 + 4 x1^2 - 10 x0 + 4 x1 + 26 */
+ /* Add quadratic coefficients for the objective */
+ setObjectiveQuadraticPart(Arrays.asList(0, 1), Arrays.asList(0, 1), Arrays.asList(1.0, 4.0));
+ /* Add linear coefficients for the objective */
+ setObjectiveLinearPart(Arrays.asList(0, 1), Arrays.asList(-10.0, 4.0));
+ /* Add constant to the objective */
+ setObjConstPart(26.0);
+
+ // Constraints Strucutres
+ /* c0 */
+ addConstraintLinearPart(0, Arrays.asList(0, 1, 2, 3, 4), Arrays.asList(-1.5, 2.0, 1.0, -0.5, 1.0));
+ /* c1 */
+ addConstraintLinearPart(1, Arrays.asList(0, 1, 5), Arrays.asList(3.0, -1.0, -1.0));
+ /* c2 */
+ addConstraintLinearPart(2, Arrays.asList(0, 1, 6), Arrays.asList(-1.0, 0.5, -1.0));
+ /* c3 */
+ addConstraintLinearPart(3, Arrays.asList(0, 1, 7), Arrays.asList(-1.0, -1.0, -1.0));
+ }
+ }
+
+ public static void main(String[] args) throws KNException {
+ // Create a problem instance.
+ ProblemMPEC1 instance = new ProblemMPEC1();
+ // Create a solver
+ try (KNSolver solver = new KNSolver(instance)) {
+
+ solver.initProblem();
+ solver.solve();
+
+ KNSolution solution = solver.getSolution();
+
+ System.out.print("\n\n");
+ System.out.format("Knitro converged with final status = %d%n", solution.getStatus());
+ System.out.format(" optimal objective value = %f%n", solution.getObjValue());
+ System.out.format(" optimal primal values x0=%f%n", solution.getX().get(0));
+ System.out.format(" x1=%f%n", solution.getX().get(1));
+ System.out.format(" x2=%f complements x5=%f%n", solution.getX().get(2), solution.getX().get(5));
+ System.out.format(" x3=%f complements x6=%f%n", solution.getX().get(3), solution.getX().get(6));
+ System.out.format(" x4=%f complements x7=%f%n", solution.getX().get(4), solution.getX().get(7));
+ System.out.format(" feasibility violation = %f%n", solver.getAbsFeasError());
+ System.out.format(" KKT optimality violation = %f%n", solver.getAbsOptError());
+ }
+ }
+}
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
index 5416126..9e9e36f 100644
--- a/src/test/resources/logback-test.xml
+++ b/src/test/resources/logback-test.xml
@@ -13,7 +13,22 @@
%-5p %d{HH:mm:ss.SSS} %-20C{1} | %m%n
-
+
+
+ D:/Documents/La_Doc/logrte1888.log
+
+
+ D:/Documents/La_Doc/logrte1888.%d{yyyy-MM-dd}.log
+ 30
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
+
+
+
+
+