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: export considering different nominal voltage #2571

Merged
merged 10 commits into from
May 22, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import com.powsybl.iidm.network.extensions.SlackTerminal;
import com.powsybl.iidm.network.util.HvdcUtils;
import com.powsybl.matpower.model.*;

import org.apache.commons.math3.complex.Complex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -200,20 +202,7 @@ private void createLines(Network network, MatpowerModel model, Context context)
for (Line l : network.getLines()) {
Terminal t1 = l.getTerminal1();
Terminal t2 = l.getTerminal2();
Bus bus1 = t1.getBusView().getBus();
Bus bus2 = t2.getBusView().getBus();
if (isConnectedToMainCc(bus1) && isConnectedToMainCc(bus2)) {
VoltageLevel vl2 = t2.getVoltageLevel();
MBranch mBranch = new MBranch();
mBranch.setFrom(context.mBusesNumbersByIds.get(bus1.getId()));
mBranch.setTo(context.mBusesNumbersByIds.get(bus2.getId()));
mBranch.setStatus(CONNECTED_STATUS);
double zb = vl2.getNominalV() * vl2.getNominalV() / BASE_MVA;
mBranch.setR(l.getR() / zb);
mBranch.setX(l.getX() / zb);
mBranch.setB((l.getB1() + l.getB2()) * zb);
model.addBranch(mBranch);
}
createMBranch(t1, t2, l.getR(), l.getX(), l.getB1(), l.getB2(), context).ifPresent(model::addBranch);
}
}

Expand Down Expand Up @@ -249,23 +238,54 @@ private void createTieLines(Network network, MatpowerModel model, Context contex
for (TieLine l : network.getTieLines()) {
Terminal t1 = l.getDanglingLine1().getTerminal();
Terminal t2 = l.getDanglingLine2().getTerminal();
Bus bus1 = t1.getBusView().getBus();
Bus bus2 = t2.getBusView().getBus();
if (isConnectedToMainCc(bus1) && isConnectedToMainCc(bus2)) {
VoltageLevel vl2 = t2.getVoltageLevel();
MBranch mBranch = new MBranch();
mBranch.setFrom(context.mBusesNumbersByIds.get(bus1.getId()));
mBranch.setTo(context.mBusesNumbersByIds.get(bus2.getId()));
mBranch.setStatus(CONNECTED_STATUS);
double zb = vl2.getNominalV() * vl2.getNominalV() / BASE_MVA;
mBranch.setR(l.getR() / zb);
mBranch.setX(l.getX() / zb);
mBranch.setB((l.getB1() + l.getB2()) * zb);
model.addBranch(mBranch);
}
createMBranch(t1, t2, l.getR(), l.getX(), l.getB1(), l.getB2(), context).ifPresent(model::addBranch);
}
}

private static Optional<MBranch> createMBranch(Terminal t1, Terminal t2, double r, double x, double b1, double b2, Context context) {
Bus bus1 = t1.getBusView().getBus();
Bus bus2 = t2.getBusView().getBus();
if (isConnectedToMainCc(bus1) && isConnectedToMainCc(bus2)) {
VoltageLevel vl1 = t1.getVoltageLevel();
VoltageLevel vl2 = t2.getVoltageLevel();
MBranch mBranch = new MBranch();
mBranch.setFrom(context.mBusesNumbersByIds.get(bus1.getId()));
mBranch.setTo(context.mBusesNumbersByIds.get(bus2.getId()));
mBranch.setStatus(CONNECTED_STATUS);

double rpu = impedanceToPerUnitForLine(r, vl1.getNominalV(), vl2.getNominalV(), BASE_MVA);
double xpu = impedanceToPerUnitForLine(x, vl1.getNominalV(), vl2.getNominalV(), BASE_MVA);
Complex ytr = impedanceToAdmittance(r, x);
double b1pu = admittanceEndToPerUnitForLine(ytr.getImaginary(), b1, vl1.getNominalV(), vl2.getNominalV(), BASE_MVA);
double b2pu = admittanceEndToPerUnitForLine(ytr.getImaginary(), b2, vl2.getNominalV(), vl1.getNominalV(), BASE_MVA);
mBranch.setR(rpu);
mBranch.setX(xpu);
mBranch.setB(b1pu + b2pu);
return Optional.of(mBranch);
} else {
return Optional.empty();
}
}

// 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 impedanceToPerUnitForLine(double impedance, double nominalVoltageAtEnd,
double nominalVoltageAtOtherEnd, double sBase) {
// this method handles also line with different nominal voltage at ends
return impedance * sBase / (nominalVoltageAtEnd * nominalVoltageAtOtherEnd);
}

private static double admittanceEndToPerUnitForLine(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 in engineering units
return (shuntAdmittanceAtEnd * nominalVoltageAtEnd * nominalVoltageAtEnd
+ (nominalVoltageAtEnd - nominalVoltageAtOtherEnd) * nominalVoltageAtEnd * transmissionAdmittance) / sBase;
}

private void createDanglingLineBranches(Network network, MatpowerModel model, Context context) {
for (DanglingLine dl : network.getDanglingLines(DanglingLineFilter.UNPAIRED)) {
Terminal t = dl.getTerminal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,33 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.ByteStreams;
import com.powsybl.cgmes.conformity.CgmesConformity1ModifiedCatalog;
import com.powsybl.commons.datasource.FileDataSource;
import com.powsybl.commons.datasource.MemDataSource;
import com.powsybl.commons.test.AbstractConverterTest;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.NetworkFactory;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import com.powsybl.iidm.network.test.FourSubstationsNodeBreakerFactory;
import com.powsybl.matpower.model.MatpowerModel;
import com.powsybl.matpower.model.MatpowerModelFactory;
import com.powsybl.matpower.model.MatpowerReader;
import com.powsybl.matpower.model.MatpowerWriter;

import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Properties;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
class MatpowerExporterTest {
class MatpowerExporterTest extends AbstractConverterTest {

private static void exportToMatAndCompareTo(Network network, String refJsonFile) throws IOException {
MemDataSource dataSource = new MemDataSource();
Expand Down Expand Up @@ -64,4 +72,19 @@ void testWithHvdcLines() throws IOException {
var network = FourSubstationsNodeBreakerFactory.create();
exportToMatAndCompareTo(network, "/fourSubstationFactory.json");
}

@Test
void testCase30ConsideringBaseVoltage() throws IOException {
MatpowerModel model = MatpowerModelFactory.create30();
model.setCaseName("ieee30-considering-base-voltage");
String caseId = model.getCaseName();
Path matFile = tmpDir.resolve(caseId + ".mat");
MatpowerWriter.write(model, matFile);

Properties properties = new Properties();
properties.put("matpower.import.ignore-base-voltage", false);
Network network = new MatpowerImporter().importData(new FileDataSource(tmpDir, caseId), NetworkFactory.findDefault(), properties);

exportToMatAndCompareTo(network, "/ieee30-considering-base-voltage.json");
}
}
6 changes: 3 additions & 3 deletions matpower/matpower-converter/src/test/resources/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@
"branches" : [ {
"from" : 5,
"to" : 4,
"r" : 0.0038222222222222225,
"r" : 0.003822222222222222,
"x" : 0.06755555555555556,
"b" : 0.021470821875,
"rateA" : 0.0,
Expand All @@ -245,9 +245,9 @@
}, {
"from" : 5,
"to" : 4,
"r" : 0.010277530864197531,
"r" : 0.010277530864197533,
"x" : 0.1402469135802469,
"b" : 0.010131024375,
"b" : 0.010131024374999999,
"rateA" : 0.0,
"rateB" : 0.0,
"rateC" : 0.0,
Expand Down
Loading