Skip to content

Commit

Permalink
Matpower: export considering different nominal voltage (#2571)
Browse files Browse the repository at this point in the history
Signed-off-by: José Antonio Marqués <marquesja@aia.es>
  • Loading branch information
marqueslanauja authored May 22, 2023
1 parent 7a2d983 commit 003ef7f
Show file tree
Hide file tree
Showing 5 changed files with 1,241 additions and 34 deletions.
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

0 comments on commit 003ef7f

Please sign in to comment.