Skip to content
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

Matpower importer: Support lines with different nominal voltage at both ends #2493

Merged
merged 9 commits into from
Mar 20, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
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 org.joda.time.DateTime;
import org.slf4j.Logger;
Expand Down Expand Up @@ -358,6 +360,17 @@ private static void createBranches(MatpowerModel model, ContainersMapping contai
branch = newTwt;
LOGGER.trace("Created TwoWindingsTransformer {} {} {}", newTwt.getId(), bus1Id, bus2Id);
} 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)
Expand All @@ -367,12 +380,12 @@ private static void createBranches(MatpowerModel model, ContainersMapping contai
.setBus2(connectedBus2)
.setConnectableBus2(bus2Id)
.setVoltageLevel2(voltageLevel2Id)
.setR(mBranch.getR() * zb)
.setX(mBranch.getX() * zb)
.setG1(0)
.setB1(mBranch.getB() / zb / 2)
.setG2(0)
.setB2(mBranch.getB() / zb / 2)
.setR(r)
.setX(x)
.setG1(g1)
.setB1(b1)
.setG2(g2)
.setB2(b2)
.add();
LOGGER.trace("Created line {} {} {}", branch.getId(), bus1Id, bus2Id);
}
Expand All @@ -387,6 +400,24 @@ private static void createBranches(MatpowerModel model, ContainersMapping contai
}
}

// 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();
}

private static double impedanceToEngineeringUnitsForLine(double impedance, double nominalVoltageAtEnd,
double nominalVoltageAtOtherEnd, double sBase) {
// this method handles also line with different nominal voltage at ends
return impedance * nominalVoltageAtEnd * nominalVoltageAtOtherEnd / sBase;
}

private static double admittanceEndToEngineeringUnitsForLine(double transmissionAdmittance, double shuntAdmittanceAtEnd,
double nominalVoltageAtEnd, double nominalVoltageAtOtherEnd, double sBase) {
// this method handles also line with different nominal voltage at ends
// note that ytr is already in engineering units
return shuntAdmittanceAtEnd * sBase / (nominalVoltageAtEnd * nominalVoltageAtEnd) - (1 - nominalVoltageAtOtherEnd / nominalVoltageAtEnd) * transmissionAdmittance;
}

@Override
public boolean exists(ReadOnlyDataSource dataSource) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.time.Month;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Properties;

import static com.powsybl.commons.test.ComparisonUtils.compareTxt;
import static org.junit.jupiter.api.Assertions.*;
Expand Down Expand Up @@ -114,6 +115,16 @@ void testCase30() throws IOException {
testCase(MatpowerModelFactory.create30());
}

@Test
void testCase30ConsideringBaseVoltage() throws IOException {
MatpowerModel model = MatpowerModelFactory.create30();
model.setCaseName("ieee30-considering-base-voltage");

Properties properties = new Properties();
properties.put("matpower.import.ignore-base-voltage", false);
testCase(model, properties);
}

@Test
void testCase57() throws IOException {
testCase(MatpowerModelFactory.create57());
Expand All @@ -140,11 +151,15 @@ void testNonexistentCase() {
}

private void testCase(MatpowerModel model) throws IOException {
testCase(model, null);
}

private void testCase(MatpowerModel model, Properties properties) throws IOException {
String caseId = model.getCaseName();
Path matFile = tmpDir.resolve(caseId + ".mat");
MatpowerWriter.write(model, matFile);

Network network = new MatpowerImporter().importData(new FileDataSource(tmpDir, caseId), NetworkFactory.findDefault(), null);
Network network = new MatpowerImporter().importData(new FileDataSource(tmpDir, caseId), NetworkFactory.findDefault(), properties);
testNetwork(network, caseId);
}

Expand Down
Loading