From f8c0a4f73751ea69d19ccc8545c32c16a235e3cc Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 17 Dec 2024 13:39:37 +0100 Subject: [PATCH 1/2] Fix case9241pegase.mat import Signed-off-by: Geoffroy Jamgotchian --- .../matpower/converter/MatpowerImporter.java | 5 +- .../converter/MatpowerImporterTest.java | 5 + ...ieee14-phase-shifter-zero-ratio-issue.json | 594 ++++++++++++++++++ ...eee14-phase-shifter-zero-ratio-issue.xiidm | 139 ++++ .../matpower/model/MatpowerModelFactory.java | 2 +- 5 files changed, 743 insertions(+), 2 deletions(-) create mode 100644 matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.json create mode 100644 matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.xiidm diff --git a/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java b/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java index e8d0ff1c719..ad20e9b538b 100644 --- a/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java +++ b/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java @@ -354,6 +354,9 @@ private static void createBranches(MatpowerModel model, ContainersMapping contai Branch branch; if (isTransformer(model, mBranch)) { + // we might have a matpower branch with a phase shift and a 0 ratio (0 in matpower just means undefined) + // we need to create an IIDM transformer but we just in that case fix the ratio to 1 + double ratio = mBranch.getRatio() == 0 ? 1 : mBranch.getRatio(); TwoWindingsTransformer newTwt = voltageLevel2.getSubstation() .orElseThrow(() -> new PowsyblException("Substation null! Transformer must be within a substation")) .newTwoWindingsTransformer() @@ -365,7 +368,7 @@ private static void createBranches(MatpowerModel model, ContainersMapping contai .setBus2(connectedBus2) .setConnectableBus2(bus2Id) .setVoltageLevel2(voltageLevel2Id) - .setRatedU1(voltageLevel1.getNominalV() * mBranch.getRatio()) + .setRatedU1(voltageLevel1.getNominalV() * ratio) .setRatedU2(voltageLevel2.getNominalV()) .setR(mBranch.getR() * zb) .setX(mBranch.getX() * zb) diff --git a/matpower/matpower-converter/src/test/java/com/powsybl/matpower/converter/MatpowerImporterTest.java b/matpower/matpower-converter/src/test/java/com/powsybl/matpower/converter/MatpowerImporterTest.java index 7218ca727cb..7a1c77bd388 100644 --- a/matpower/matpower-converter/src/test/java/com/powsybl/matpower/converter/MatpowerImporterTest.java +++ b/matpower/matpower-converter/src/test/java/com/powsybl/matpower/converter/MatpowerImporterTest.java @@ -95,6 +95,11 @@ void testCase14WithPhaseShifter() throws IOException { testCase(MatpowerModelFactory.create14WithPhaseShifter()); } + @Test + void testCase14WithPhaseShifterZeroRatioIssue() throws IOException { + testCase(MatpowerModelFactory.readModelJsonFromResources("ieee14-phase-shifter-zero-ratio-issue.json")); + } + @Test void testCase14WithPhaseShifterSolved() throws IOException { testCaseSolved(MatpowerModelFactory.create14WithPhaseShifter()); diff --git a/matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.json b/matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.json new file mode 100644 index 00000000000..06ea26a1ac8 --- /dev/null +++ b/matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.json @@ -0,0 +1,594 @@ +{ + "caseName" : "ieee14-phase-shifter-zero-ratio-issue", + "baseMva" : 100.0, + "version" : "2", + "buses" : [ { + "number" : 1, + "type" : "REF", + "realPowerDemand" : 0.0, + "reactivePowerDemand" : 0.0, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.06, + "voltageAngle" : 0.0, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 2, + "type" : "PV", + "realPowerDemand" : 21.7, + "reactivePowerDemand" : 12.7, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0449999999999997, + "voltageAngle" : -5.000328510465844, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 3, + "type" : "PV", + "realPowerDemand" : 94.2, + "reactivePowerDemand" : 19.0, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.01, + "voltageAngle" : -12.78892335601888, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 4, + "type" : "PQ", + "realPowerDemand" : 47.8, + "reactivePowerDemand" : -3.9, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0173494845822744, + "voltageAngle" : -10.412306262257337, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 5, + "type" : "PQ", + "realPowerDemand" : 7.6, + "reactivePowerDemand" : 1.6, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0200789534978287, + "voltageAngle" : -8.724093100611777, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 6, + "type" : "PV", + "realPowerDemand" : 11.2, + "reactivePowerDemand" : 7.5, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.07, + "voltageAngle" : -13.22467775771849, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 7, + "type" : "PQ", + "realPowerDemand" : 0.0, + "reactivePowerDemand" : 0.0, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.061731342223832, + "voltageAngle" : -10.185085117783457, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 8, + "type" : "PV", + "realPowerDemand" : 0.0, + "reactivePowerDemand" : 0.0, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.09, + "voltageAngle" : -10.185085117783467, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 9, + "type" : "PQ", + "realPowerDemand" : 29.5, + "reactivePowerDemand" : 16.6, + "shuntConductance" : 0.0, + "shuntSusceptance" : 19.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0582629220284285, + "voltageAngle" : -12.65099581261227, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 10, + "type" : "PQ", + "realPowerDemand" : 9.0, + "reactivePowerDemand" : 5.8, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0531461836881817, + "voltageAngle" : -13.035710471997398, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 11, + "type" : "PQ", + "realPowerDemand" : 3.5, + "reactivePowerDemand" : 1.8, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0582558695370825, + "voltageAngle" : -13.25292235374066, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 12, + "type" : "PQ", + "realPowerDemand" : 6.1, + "reactivePowerDemand" : 1.6, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0551462766263606, + "voltageAngle" : -13.988186540628082, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 13, + "type" : "PQ", + "realPowerDemand" : 13.5, + "reactivePowerDemand" : 5.8, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.0509495051495474, + "voltageAngle" : -13.97721516091526, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + }, { + "number" : 14, + "type" : "PQ", + "realPowerDemand" : 14.9, + "reactivePowerDemand" : 5.0, + "shuntConductance" : 0.0, + "shuntSusceptance" : 0.0, + "areaNumber" : 1, + "voltageMagnitude" : 1.037140277380203, + "voltageAngle" : -14.223902738389041, + "baseVoltage" : 0.0, + "lossZone" : 1, + "maximumVoltageMagnitude" : 1.06, + "minimumVoltageMagnitude" : 0.94 + } ], + "generators" : [ { + "number" : 1, + "realPowerOutput" : 232.49989569603508, + "reactivePowerOutput" : -16.899907154008424, + "maximumReactivePowerOutput" : 10.0, + "minimumReactivePowerOutput" : 0.0, + "voltageMagnitudeSetpoint" : 1.06, + "totalMbase" : 100.0, + "status" : 1, + "maximumRealPowerOutput" : 332.4, + "minimumRealPowerOutput" : 0.0, + "pc1" : 0.0, + "pc2" : 0.0, + "qc1Min" : 0.0, + "qc1Max" : 0.0, + "qc2Min" : 0.0, + "qc2Max" : 0.0, + "rampAgc" : 0.0, + "rampTenMinutes" : 0.0, + "rampThirtyMinutes" : 0.0, + "rampQ" : 0.0, + "apf" : 0.0 + }, { + "number" : 2, + "realPowerOutput" : 40.0, + "reactivePowerOutput" : 43.58509011714705, + "maximumReactivePowerOutput" : 50.0, + "minimumReactivePowerOutput" : -40.0, + "voltageMagnitudeSetpoint" : 1.045, + "totalMbase" : 100.0, + "status" : 1, + "maximumRealPowerOutput" : 140.0, + "minimumRealPowerOutput" : 0.0, + "pc1" : 0.0, + "pc2" : 0.0, + "qc1Min" : 0.0, + "qc1Max" : 0.0, + "qc2Min" : 0.0, + "qc2Max" : 0.0, + "rampAgc" : 0.0, + "rampTenMinutes" : 0.0, + "rampThirtyMinutes" : 0.0, + "rampQ" : 0.0, + "apf" : 0.0 + }, { + "number" : 3, + "realPowerOutput" : 0.0, + "reactivePowerOutput" : 25.247205918340796, + "maximumReactivePowerOutput" : 40.0, + "minimumReactivePowerOutput" : 0.0, + "voltageMagnitudeSetpoint" : 1.01, + "totalMbase" : 100.0, + "status" : 1, + "maximumRealPowerOutput" : 100.0, + "minimumRealPowerOutput" : 0.0, + "pc1" : 0.0, + "pc2" : 0.0, + "qc1Min" : 0.0, + "qc1Max" : 0.0, + "qc2Min" : 0.0, + "qc2Max" : 0.0, + "rampAgc" : 0.0, + "rampTenMinutes" : 0.0, + "rampThirtyMinutes" : 0.0, + "rampQ" : 0.0, + "apf" : 0.0 + }, { + "number" : 6, + "realPowerOutput" : 0.0, + "reactivePowerOutput" : 14.270293690387987, + "maximumReactivePowerOutput" : 24.0, + "minimumReactivePowerOutput" : -6.0, + "voltageMagnitudeSetpoint" : 1.07, + "totalMbase" : 100.0, + "status" : 1, + "maximumRealPowerOutput" : 100.0, + "minimumRealPowerOutput" : 0.0, + "pc1" : 0.0, + "pc2" : 0.0, + "qc1Min" : 0.0, + "qc1Max" : 0.0, + "qc2Min" : 0.0, + "qc2Max" : 0.0, + "rampAgc" : 0.0, + "rampTenMinutes" : 0.0, + "rampThirtyMinutes" : 0.0, + "rampQ" : 0.0, + "apf" : 0.0 + }, { + "number" : 8, + "realPowerOutput" : 0.0, + "reactivePowerOutput" : 17.49238545332004, + "maximumReactivePowerOutput" : 24.0, + "minimumReactivePowerOutput" : -6.0, + "voltageMagnitudeSetpoint" : 1.09, + "totalMbase" : 100.0, + "status" : 1, + "maximumRealPowerOutput" : 100.0, + "minimumRealPowerOutput" : 0.0, + "pc1" : 0.0, + "pc2" : 0.0, + "qc1Min" : 0.0, + "qc1Max" : 0.0, + "qc2Min" : 0.0, + "qc2Max" : 0.0, + "rampAgc" : 0.0, + "rampTenMinutes" : 0.0, + "rampThirtyMinutes" : 0.0, + "rampQ" : 0.0, + "apf" : 0.0 + } ], + "branches" : [ { + "from" : 1, + "to" : 2, + "r" : 0.01938, + "x" : 0.05917, + "b" : 0.0528, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 1, + "to" : 5, + "r" : 0.05403, + "x" : 0.22304, + "b" : 0.0492, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 2, + "to" : 3, + "r" : 0.04699, + "x" : 0.19797, + "b" : 0.0438, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 2, + "to" : 4, + "r" : 0.05811, + "x" : 0.17632, + "b" : 0.034, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 2, + "to" : 5, + "r" : 0.05695, + "x" : 0.17388, + "b" : 0.0346, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 3, + "to" : 4, + "r" : 0.06701, + "x" : 0.17103, + "b" : 0.0128, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 4, + "to" : 5, + "r" : 0.01335, + "x" : 0.04211, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 4, + "to" : 7, + "r" : 0.0, + "x" : 0.20912, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : -5.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 4, + "to" : 9, + "r" : 0.0, + "x" : 0.55618, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.969, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 5, + "to" : 6, + "r" : 0.0, + "x" : 0.25202, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.932, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 6, + "to" : 11, + "r" : 0.09498, + "x" : 0.1989, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 6, + "to" : 12, + "r" : 0.12291, + "x" : 0.25581, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 6, + "to" : 13, + "r" : 0.06615, + "x" : 0.13027, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 7, + "to" : 8, + "r" : 0.0, + "x" : 0.17615, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 7, + "to" : 9, + "r" : 0.0, + "x" : 0.11001, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 9, + "to" : 10, + "r" : 0.03181, + "x" : 0.0845, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 9, + "to" : 14, + "r" : 0.12711, + "x" : 0.27038, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 10, + "to" : 11, + "r" : 0.08205, + "x" : 0.19207, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 12, + "to" : 13, + "r" : 0.22092, + "x" : 0.19988, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + }, { + "from" : 13, + "to" : 14, + "r" : 0.17093, + "x" : 0.34802, + "b" : 0.0, + "rateA" : 0.0, + "rateB" : 0.0, + "rateC" : 0.0, + "ratio" : 0.0, + "phaseShiftAngle" : 0.0, + "status" : 1.0, + "angMin" : -360.0, + "angMax" : 360.0 + } ] +} \ No newline at end of file diff --git a/matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.xiidm b/matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.xiidm new file mode 100644 index 00000000000..c03a80e4a3e --- /dev/null +++ b/matpower/matpower-converter/src/test/resources/ieee14-phase-shifter-zero-ratio-issue.xiidm @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/matpower/matpower-model/src/main/java/com/powsybl/matpower/model/MatpowerModelFactory.java b/matpower/matpower-model/src/main/java/com/powsybl/matpower/model/MatpowerModelFactory.java index 0b75311bcf5..752ca3da566 100644 --- a/matpower/matpower-model/src/main/java/com/powsybl/matpower/model/MatpowerModelFactory.java +++ b/matpower/matpower-model/src/main/java/com/powsybl/matpower/model/MatpowerModelFactory.java @@ -31,7 +31,7 @@ private static MatpowerModel readModelJsonFromResources(ObjectMapper mapper, Str return model; } - private static MatpowerModel readModelJsonFromResources(String fileName) { + public static MatpowerModel readModelJsonFromResources(String fileName) { return readModelJsonFromResources(new ObjectMapper(), fileName); } From f6bfb67518d0c9aabdfd378a929aad728e2d3c80 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 17 Dec 2024 14:07:43 +0100 Subject: [PATCH 2/2] Fix Sonar issue Signed-off-by: Geoffroy Jamgotchian --- .../matpower/converter/MatpowerImporter.java | 160 ++++++++++-------- 1 file changed, 89 insertions(+), 71 deletions(-) diff --git a/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java b/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java index ad20e9b538b..2e33b27134d 100644 --- a/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java +++ b/matpower/matpower-converter/src/main/java/com/powsybl/matpower/converter/MatpowerImporter.java @@ -16,15 +16,12 @@ import com.powsybl.commons.parameters.Parameter; import com.powsybl.commons.parameters.ParameterDefaultValueConfig; import com.powsybl.commons.parameters.ParameterType; -import com.powsybl.iidm.network.Importer; import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.SlackTerminal; import com.powsybl.iidm.network.util.ContainersMapping; import com.powsybl.matpower.model.*; - import org.apache.commons.math3.complex.Complex; import org.jgrapht.alg.util.Pair; -import java.time.ZonedDateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +29,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; +import java.time.ZonedDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -341,84 +339,20 @@ private static void createApparentPowerLimits(MBranch mBranch, ApparentPowerLimi private static void createBranches(MatpowerModel model, ContainersMapping containerMapping, Network network, Context context) { for (MBranch mBranch : model.getBranches()) { - String bus1Id = getId(BUS_PREFIX, mBranch.getFrom()); - String bus2Id = getId(BUS_PREFIX, mBranch.getTo()); + String connectableBus1 = getId(BUS_PREFIX, mBranch.getFrom()); + String connectableBus2 = getId(BUS_PREFIX, mBranch.getTo()); String voltageLevel1Id = containerMapping.getVoltageLevelId(mBranch.getFrom()); String voltageLevel2Id = containerMapping.getVoltageLevelId(mBranch.getTo()); VoltageLevel voltageLevel1 = network.getVoltageLevel(voltageLevel1Id); VoltageLevel voltageLevel2 = network.getVoltageLevel(voltageLevel2Id); double zb = voltageLevel2.getNominalV() * voltageLevel2.getNominalV() / context.getBaseMva(); boolean isInService = isInService(mBranch); - String connectedBus1 = isInService ? bus1Id : null; - String connectedBus2 = isInService ? bus2Id : null; Branch branch; if (isTransformer(model, mBranch)) { - // we might have a matpower branch with a phase shift and a 0 ratio (0 in matpower just means undefined) - // we need to create an IIDM transformer but we just in that case fix the ratio to 1 - double ratio = mBranch.getRatio() == 0 ? 1 : mBranch.getRatio(); - TwoWindingsTransformer newTwt = voltageLevel2.getSubstation() - .orElseThrow(() -> new PowsyblException("Substation null! Transformer must be within a substation")) - .newTwoWindingsTransformer() - .setId(getId(TRANSFORMER_PREFIX, mBranch.getFrom(), mBranch.getTo())) - .setEnsureIdUnicity(true) - .setBus1(connectedBus1) - .setConnectableBus1(bus1Id) - .setVoltageLevel1(voltageLevel1Id) - .setBus2(connectedBus2) - .setConnectableBus2(bus2Id) - .setVoltageLevel2(voltageLevel2Id) - .setRatedU1(voltageLevel1.getNominalV() * ratio) - .setRatedU2(voltageLevel2.getNominalV()) - .setR(mBranch.getR() * zb) - .setX(mBranch.getX() * zb) - .setG(0) - .setB(mBranch.getB() / zb) - .add(); - if (mBranch.getPhaseShiftAngle() != 0) { - newTwt.newPhaseTapChanger() - .setTapPosition(0) - .beginStep() - .setRho(1) - .setAlpha(-mBranch.getPhaseShiftAngle()) - .setR(0) - .setX(0) - .setG(0) - .setB(0) - .endStep() - .add(); - } - branch = newTwt; - LOGGER.trace("Created TwoWindingsTransformer {} {} {}", newTwt.getId(), bus1Id, bus2Id); + branch = createTransformer(mBranch, voltageLevel1, connectableBus1, voltageLevel2, connectableBus2, isInService, zb); } else { - double nominalV1 = voltageLevel1.getNominalV(); - double nominalV2 = voltageLevel2.getNominalV(); - double sBase = context.getBaseMva(); - double r = impedanceToEngineeringUnitsForLine(mBranch.getR(), nominalV1, nominalV2, sBase); - double x = impedanceToEngineeringUnitsForLine(mBranch.getX(), nominalV1, nominalV2, sBase); - Complex ytr = impedanceToAdmittance(r, x); - double g1 = admittanceEndToEngineeringUnitsForLine(ytr.getReal(), 0.0, nominalV1, nominalV2, sBase); - double b1 = admittanceEndToEngineeringUnitsForLine(ytr.getImaginary(), mBranch.getB() * 0.5, nominalV1, nominalV2, sBase); - double g2 = admittanceEndToEngineeringUnitsForLine(ytr.getReal(), 0.0, nominalV2, nominalV1, sBase); - double b2 = admittanceEndToEngineeringUnitsForLine(ytr.getImaginary(), mBranch.getB() * 0.5, nominalV2, nominalV1, sBase); - - branch = network.newLine() - .setId(getId(LINE_PREFIX, mBranch.getFrom(), mBranch.getTo())) - .setEnsureIdUnicity(true) - .setBus1(connectedBus1) - .setConnectableBus1(bus1Id) - .setVoltageLevel1(voltageLevel1Id) - .setBus2(connectedBus2) - .setConnectableBus2(bus2Id) - .setVoltageLevel2(voltageLevel2Id) - .setR(r) - .setX(x) - .setG1(g1) - .setB1(b1) - .setG2(g2) - .setB2(b2) - .add(); - LOGGER.trace("Created line {} {} {}", branch.getId(), bus1Id, bus2Id); + branch = createLine(network, context, mBranch, voltageLevel1, connectableBus1, voltageLevel2, connectableBus2, isInService); } if (mBranch.getRateA() != 0) { // we create the apparent power limit arbitrary on both sides @@ -431,6 +365,90 @@ private static void createBranches(MatpowerModel model, ContainersMapping contai } } + private static Branch createLine(Network network, Context context, MBranch mBranch, + VoltageLevel voltageLevel1, String connectableBus1, + VoltageLevel voltageLevel2, String connectableBus2, + boolean isInService) { + Branch branch; + String bus1 = isInService ? connectableBus1 : null; + String bus2 = isInService ? connectableBus2 : null; + double nominalV1 = voltageLevel1.getNominalV(); + double nominalV2 = voltageLevel2.getNominalV(); + double sBase = context.getBaseMva(); + double r = impedanceToEngineeringUnitsForLine(mBranch.getR(), nominalV1, nominalV2, sBase); + double x = impedanceToEngineeringUnitsForLine(mBranch.getX(), nominalV1, nominalV2, sBase); + Complex ytr = impedanceToAdmittance(r, x); + double g1 = admittanceEndToEngineeringUnitsForLine(ytr.getReal(), 0.0, nominalV1, nominalV2, sBase); + double b1 = admittanceEndToEngineeringUnitsForLine(ytr.getImaginary(), mBranch.getB() * 0.5, nominalV1, nominalV2, sBase); + double g2 = admittanceEndToEngineeringUnitsForLine(ytr.getReal(), 0.0, nominalV2, nominalV1, sBase); + double b2 = admittanceEndToEngineeringUnitsForLine(ytr.getImaginary(), mBranch.getB() * 0.5, nominalV2, nominalV1, sBase); + + branch = network.newLine() + .setId(getId(LINE_PREFIX, mBranch.getFrom(), mBranch.getTo())) + .setEnsureIdUnicity(true) + .setBus1(bus1) + .setConnectableBus1(connectableBus1) + .setVoltageLevel1(voltageLevel1.getId()) + .setBus2(bus2) + .setConnectableBus2(connectableBus2) + .setVoltageLevel2(voltageLevel2.getId()) + .setR(r) + .setX(x) + .setG1(g1) + .setB1(b1) + .setG2(g2) + .setB2(b2) + .add(); + LOGGER.trace("Created line {} {} {}", branch.getId(), bus1, bus2); + return branch; + } + + private static Branch createTransformer(MBranch mBranch, + VoltageLevel voltageLevel1, String connectableBus1, + VoltageLevel voltageLevel2, String connectableBus2, + boolean isInService, double zb) { + Branch branch; + String bus1 = isInService ? connectableBus1 : null; + String bus2 = isInService ? connectableBus2 : null; + // we might have a matpower branch with a phase shift and a 0 ratio (0 in matpower just means undefined) + // we need to create an IIDM transformer but we just in that case fix the ratio to 1 + double ratio = mBranch.getRatio() == 0 ? 1 : mBranch.getRatio(); + TwoWindingsTransformer newTwt = voltageLevel2.getSubstation() + .orElseThrow(() -> new PowsyblException("Substation null! Transformer must be within a substation")) + .newTwoWindingsTransformer() + .setId(getId(TRANSFORMER_PREFIX, mBranch.getFrom(), mBranch.getTo())) + .setEnsureIdUnicity(true) + .setBus1(bus1) + .setConnectableBus1(connectableBus1) + .setVoltageLevel1(voltageLevel1.getId()) + .setBus2(bus2) + .setConnectableBus2(connectableBus2) + .setVoltageLevel2(voltageLevel2.getId()) + .setRatedU1(voltageLevel1.getNominalV() * ratio) + .setRatedU2(voltageLevel2.getNominalV()) + .setR(mBranch.getR() * zb) + .setX(mBranch.getX() * zb) + .setG(0) + .setB(mBranch.getB() / zb) + .add(); + if (mBranch.getPhaseShiftAngle() != 0) { + newTwt.newPhaseTapChanger() + .setTapPosition(0) + .beginStep() + .setRho(1) + .setAlpha(-mBranch.getPhaseShiftAngle()) + .setR(0) + .setX(0) + .setG(0) + .setB(0) + .endStep() + .add(); + } + branch = newTwt; + LOGGER.trace("Created TwoWindingsTransformer {} {} {}", newTwt.getId(), bus1, bus2); + return branch; + } + // avoid NaN when r and x, both are 0.0 private static Complex impedanceToAdmittance(double r, double x) { return r == 0.0 && x == 0.0 ? new Complex(0.0, 0.0) : new Complex(r, x).reciprocal();