PsseImporterTest.java
/**
* Copyright (c) 2020, RTE (http://www.rte-france.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.psse.converter;
import com.powsybl.commons.datasource.ReadOnlyDataSource;
import com.powsybl.commons.datasource.ResourceDataSource;
import com.powsybl.commons.datasource.ResourceSet;
import com.powsybl.commons.test.AbstractSerDeTest;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.impl.NetworkFactoryImpl;
import com.powsybl.iidm.serde.NetworkSerDe;
import com.powsybl.psse.model.PsseException;
import com.powsybl.psse.model.PsseVersion;
import com.powsybl.psse.model.io.AbstractRecordGroup;
import com.powsybl.psse.model.io.Context;
import com.powsybl.psse.model.io.RecordGroupIdentification;
import com.powsybl.psse.model.pf.PssePowerFlowModel;
import com.powsybl.psse.model.pf.io.PowerFlowRawData33;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Properties;
import static com.powsybl.commons.test.ComparisonUtils.assertXmlEquals;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author JB Heyberger {@literal <jean-baptiste.heyberger at rte-france.com>}
*/
class PsseImporterTest extends AbstractSerDeTest {
@Test
void baseTest() {
Importer importer = new PsseImporter();
assertEquals("PSS/E", importer.getFormat());
assertEquals("PSS/E Format to IIDM converter", importer.getComment());
assertEquals(List.of("raw", "RAW", "rawx", "RAWX"), importer.getSupportedExtensions());
assertEquals(2, importer.getParameters().size());
assertEquals("psse.import.ignore-base-voltage", importer.getParameters().get(0).getName());
assertEquals("psse.import.ignore-node-breaker-topology", importer.getParameters().get(1).getName());
}
private void testNetwork(Network network) throws IOException {
Path file = fileSystem.getPath("/work/" + network.getId() + ".xiidm");
network.setCaseDate(ZonedDateTime.parse("2016-01-01T10:00:00.000+02:00"));
NetworkSerDe.write(network, file);
try (InputStream is = Files.newInputStream(file)) {
assertXmlEquals(getClass().getResourceAsStream("/" + network.getId() + ".xiidm"), is);
}
}
@Test
void existsTest() {
PsseImporter importer = new PsseImporter();
// test with a valid raw/RAW file
assertTrue(importer.exists(new ResourceDataSource("IEEE_14_bus", new ResourceSet("/", "IEEE_14_bus.raw"))));
assertTrue(importer.exists(new ResourceDataSource("IEEE_30_bus", new ResourceSet("/", "IEEE_30_bus.raw"))));
// test with an invalid extension
assertFalse(importer.exists(new ResourceDataSource("IEEE_14_bus", new ResourceSet("/", "IEEE_14_bus.json"))));
// test with not supported content
ResourceDataSource dsCaseFlag = new ResourceDataSource("case-flag-not-supported", new ResourceSet("/", "case-flag-not-supported.raw"));
assertFalse(importer.exists(dsCaseFlag));
ResourceDataSource dsCaseVersion = new ResourceDataSource("version-not-supported", new ResourceSet("/", "version-not-supported.raw"));
assertFalse(importer.exists(dsCaseVersion));
// test with a valid extension and an invalid content
ResourceDataSource dsCaseInvalid = new ResourceDataSource("fake", new ResourceSet("/", "fake.raw"));
assertFalse(importer.exists(dsCaseInvalid));
// test with a valid extension and an invalid content
ResourceDataSource dsCaseInvalidx = new ResourceDataSource("fake", new ResourceSet("/", "fake.rawx"));
assertFalse(importer.exists(dsCaseInvalidx));
}
private Network importTest(String basename, String filename, boolean ignoreBaseVoltage) throws IOException {
Properties properties = new Properties();
properties.put("psse.import.ignore-base-voltage", ignoreBaseVoltage);
ReadOnlyDataSource dataSource = new ResourceDataSource(basename, new ResourceSet("/", filename));
Network network = new PsseImporter().importData(dataSource, new NetworkFactoryImpl(), properties);
testNetwork(network);
return network;
}
@Test
void importTest14() throws IOException {
importTest("IEEE_14_bus", "IEEE_14_bus.raw", false);
}
@Test
void importTest24() throws IOException {
importTest("IEEE_24_bus", "IEEE_24_bus.raw", false);
}
@Test
void importTest30() throws IOException {
importTest("IEEE_30_bus", "IEEE_30_bus.raw", false);
}
@Test
void importTest57() throws IOException {
importTest("IEEE_57_bus", "IEEE_57_bus.raw", false);
}
@Test
void importTest118() throws IOException {
importTest("IEEE_118_bus", "IEEE_118_bus.raw", false);
}
@Test
void importTestT3W() throws IOException {
importTest("ThreeMIB_T3W_modified", "ThreeMIB_T3W_modified.raw", false);
}
@Test
void importTestT3Wphase() throws IOException {
importTest("ThreeMIB_T3W_phase", "ThreeMIB_T3W_phase.raw", false);
}
@Test
void remoteControl() throws IOException {
importTest("remoteControl", "remoteControl.raw", false);
}
@Test
void exampleVersion32() throws IOException {
importTest("ExampleVersion32", "ExampleVersion32.raw", false);
}
@Test
void switchedShunt() throws IOException {
importTest("SwitchedShunt", "SwitchedShunt.raw", false);
}
@Test
void switchedShuntWithZeroVswlo() throws IOException {
importTest("SwitchedShuntWithZeroVswlo", "SwitchedShuntWithZeroVswlo.raw", false);
}
@Test
void importTest14IsolatedBuses() throws IOException {
importTest("IEEE_14_isolated_buses", "IEEE_14_isolated_buses.raw", false);
}
@Test
void twoTerminalDc() throws IOException {
importTest("twoTerminalDc", "twoTerminalDc.raw", false);
}
@Test
void twoTerminalDcWithNegativeSetvl() throws IOException {
importTest("twoTerminalDc_with_negative_setvl", "twoTerminalDc_with_negative_setvl.raw", false);
}
@Test
void parallelTwoTerminalDcBetweenSameAcBuses() throws IOException {
importTest("parallelTwoTerminalDcBetweenSameAcBuses", "parallelTwoTerminalDcBetweenSameAcBuses.raw", false);
}
@Test
void twoWindingsTransformerPhase() throws IOException {
importTest("TwoWindingsTransformerPhase", "TwoWindingsTransformerPhase.raw", false);
}
@Test
void isolatedSlackBus() throws IOException {
importTest("IsolatedSlackBus", "IsolatedSlackBus.raw", false);
}
@Test
void transformersWithZeroNomV() throws IOException {
importTest("TransformersWithZeroNomV", "TransformersWithZeroNomV.raw", false);
}
@Test
void rawCaseWithSpecialCharacters() throws IOException {
importTest("RawCaseWithSpecialCharacters", "RawCaseWithSpecialCharacters.raw", false);
}
@Test
void rawxCaseWithSpecialCharacters() throws IOException {
importTest("RawxCaseWithSpecialCharacters", "RawxCaseWithSpecialCharacters.rawx", false);
}
@Test
void twoAreaCase() throws IOException {
importTest("two_area_case", "two_area_case.raw", false);
}
@Test
void twoTerminalDcwithTwoAreas() throws IOException {
importTest("twoTerminalDcwithTwoAreas", "twoTerminalDcwithTwoAreas.raw", false);
}
@Test
void twoTerminalDcwithTwoAreasTrf3w() throws IOException {
importTest("two_area_case_trf3w", "two_area_case_trf3w.raw", false);
}
@Test
void importTest14BusesDuplicateIds() throws IOException {
Network n = importTest("IEEE_14_buses_duplicate_ids", "IEEE_14_buses_duplicate_ids.raw", false);
assertNotNull(n.getLoad("B2-L1 "));
assertNotNull(n.getLoad("B2-L10"));
assertNotNull(n.getGenerator("B1-G1 "));
assertNotNull(n.getGenerator("B1-G10"));
assertNotNull(n.getShuntCompensator("B9-SH 1"));
assertNotNull(n.getShuntCompensator("B9-SH 0"));
assertNotNull(n.getLine("L-13-14-1 "));
assertNotNull(n.getLine("L-14-13-10"));
assertNotNull(n.getLine("L-13-14-11"));
assertNotNull(n.getTwoWindingsTransformer("T-4-7-1 "));
assertNotNull(n.getTwoWindingsTransformer("T-7-4-10"));
assertNotNull(n.getTwoWindingsTransformer("T-4-7-11"));
}
@Test
void importTest14BusesDuplicateIdsV35() throws IOException {
Network n = importTest("IEEE_14_buses_duplicate_ids_rev35", "IEEE_14_buses_duplicate_ids_rev35.raw", false);
assertNotNull(n.getLoad("B2-L1 "));
assertNotNull(n.getLoad("B2-L10"));
assertNotNull(n.getGenerator("B1-G1 "));
assertNotNull(n.getGenerator("B1-G10"));
assertNotNull(n.getShuntCompensator("B9-SH 1"));
assertNotNull(n.getShuntCompensator("B9-SH 0"));
assertNotNull(n.getShuntCompensator("B1-SwSH1"));
assertNotNull(n.getShuntCompensator("B1-SwSH10"));
assertNotNull(n.getLine("L-1-2-1 "));
assertNotNull(n.getLine("L-1-2-10"));
assertNotNull(n.getLine("L-2-1-11"));
assertNotNull(n.getTwoWindingsTransformer("T-4-7-1 "));
assertNotNull(n.getTwoWindingsTransformer("T-4-7-10"));
}
@Test
void importTest14BadlyConnectedEquipment() throws IOException {
Network n = importTest("IEEE_14_buses_badly_connected_equipment", "IEEE_14_buses_badly_connected_equipment.raw", false);
// Ensure that the equipment is not imported
assertNull(n.getLoad("B200-L1 "));
assertNull(n.getShuntCompensator("B200-SH 1"));
assertNull(n.getGenerator("B200-G1 "));
assertNull(n.getLine("L-200-13-1 "));
assertNull(n.getLine("L-13-200-2 "));
assertNull(n.getTwoWindingsTransformer("T-7-200-2 "));
assertNull(n.getTwoWindingsTransformer("T-200-7-3 "));
assertNull(n.getThreeWindingsTransformer("T-200-2-7-1 "));
assertNull(n.getThreeWindingsTransformer("T-4-200-7-2 "));
assertNull(n.getThreeWindingsTransformer("T-4-2-200-3 "));
assertNull(n.getHvdcLine("TwoTerminalDc-EATL P1 "));
assertNull(n.getHvdcLine("TwoTerminalDc-EATL P2 "));
assertNull(n.getShuntCompensator("B200-SwSH1"));
}
@Test
void importTest14BadlyDefinedControlledBuses() throws IOException {
Network n = importTest("IEEE_14_buses_badly_defined_controlled_buses", "IEEE_14_buses_badly_defined_controlled_buses.raw", false);
// Ensure that the equipment is imported
assertNotNull(n.getGenerator("B8-G1 "));
assertNotNull(n.getTwoWindingsTransformer("T-4-7-1 "));
assertNotNull(n.getThreeWindingsTransformer("T-4-7-9-1 "));
assertNotNull(n.getThreeWindingsTransformer("T-4-7-9-1 "));
assertNotNull(n.getThreeWindingsTransformer("T-4-7-9-1 "));
assertNotNull(n.getShuntCompensator("B2-SwSH1"));
}
@Test
void testRates() throws IOException {
Context context = new Context();
ReadOnlyDataSource ds = new ResourceDataSource("ThreeMIB_T3W_modified", new ResourceSet("/", "ThreeMIB_T3W_modified.raw"));
PssePowerFlowModel model = new PowerFlowRawData33().read(ds, "raw", context);
assertEquals(10451.0, model.getNonTransformerBranches().get(0).getRates().getRatea(), 0);
assertEquals(10452.0, model.getNonTransformerBranches().get(0).getRates().getRateb(), 0);
assertEquals(10453.0, model.getNonTransformerBranches().get(0).getRates().getRatec(), 0);
assertEquals(10561.0, model.getNonTransformerBranches().get(1).getRates().getRatea(), 0);
assertEquals(10562.0, model.getNonTransformerBranches().get(1).getRates().getRateb(), 0);
assertEquals(10563.0, model.getNonTransformerBranches().get(1).getRates().getRatec(), 0);
assertEquals(10140.0, model.getTransformers().get(0).getWinding1Rates().getRatea(), 0);
assertEquals(10141.0, model.getTransformers().get(0).getWinding1Rates().getRateb(), 0);
assertEquals(10142.0, model.getTransformers().get(0).getWinding1Rates().getRatec(), 0);
assertEquals(101.0, model.getTransformers().get(1).getWinding1Rates().getRatea(), 0);
assertEquals(102.0, model.getTransformers().get(1).getWinding1Rates().getRateb(), 0);
assertEquals(103.0, model.getTransformers().get(1).getWinding1Rates().getRatec(), 0);
assertEquals(201.0, model.getTransformers().get(1).getWinding2Rates().getRatea(), 0);
assertEquals(202.0, model.getTransformers().get(1).getWinding2Rates().getRateb(), 0);
assertEquals(203.0, model.getTransformers().get(1).getWinding2Rates().getRatec(), 0);
assertEquals(301.0, model.getTransformers().get(1).getWinding3Rates().getRatea(), 0);
assertEquals(302.0, model.getTransformers().get(1).getWinding3Rates().getRateb(), 0);
assertEquals(303.0, model.getTransformers().get(1).getWinding3Rates().getRatec(), 0);
}
@Test()
void badModeTest() {
ReadOnlyDataSource dataSource = new ResourceDataSource("case-flag-not-supported", new ResourceSet("/", "case-flag-not-supported.raw"));
PsseImporter psseImporter = new PsseImporter();
NetworkFactory networkFactory = new NetworkFactoryImpl();
assertThatExceptionOfType(PsseException.class)
.isThrownBy(() -> psseImporter.importData(dataSource, networkFactory, null))
.withMessage("Incremental load of data option (IC = 1) is not supported");
}
@Test
void badVersionTest() {
ReadOnlyDataSource dataSource = new ResourceDataSource("version-not-supported", new ResourceSet("/", "version-not-supported.raw"));
PsseImporter psseImporter = new PsseImporter();
NetworkFactory networkFactory = new NetworkFactoryImpl();
assertThatExceptionOfType(PsseException.class)
.isThrownBy(() -> psseImporter.importData(dataSource, networkFactory, null))
.withMessage("Version 29 not supported. Supported versions are: " + PsseVersion.supportedVersions());
}
@Test
void dataSourceExistsTest() {
ReadOnlyDataSource dataSource;
dataSource = new ResourceDataSource("version-not-supported", new ResourceSet("/", "version-not-supported.raw"));
assertFalse(new PsseImporter().exists(dataSource));
dataSource = new ResourceDataSource("IEEE_14_bus", new ResourceSet("/", "IEEE_14_bus.raw"));
assertTrue(new PsseImporter().exists(dataSource));
dataSource = new ResourceDataSource("IEEE_14_bus_rev35", new ResourceSet("/", "IEEE_14_bus_rev35.rawx"));
assertTrue(new PsseImporter().exists(dataSource));
}
@Test
void importTest14ZipLoad() throws IOException {
importTest("IEEE_14_buses_zip_load", "IEEE_14_buses_zip_load.raw", false);
}
@Test
void importTest14NodeBreaker() throws IOException {
importTest("IEEE_14_bus_nodeBreaker_rev35", "IEEE_14_bus_nodeBreaker_rev35.raw", false);
}
@Test
void importFiveBusNodeBreaker() throws IOException {
importTest("five_bus_nodeBreaker_rev35", "five_bus_nodeBreaker_rev35.raw", false);
}
@Test
void importTestTransformersWithVoltageControlAndNotDefinedControlledBusV33() {
ReadOnlyDataSource dataSource = new ResourceDataSource("TransformersWithVoltageControlAndNotDefinedControlledBus", new ResourceSet("/", "TransformersWithVoltageControlAndNotDefinedControlledBus.raw"));
Network network = new PsseImporter().importData(dataSource, new NetworkFactoryImpl(), new Properties());
TwoWindingsTransformer t2w = network.getTwoWindingsTransformer("T-1-4-1 ");
assertNotNull(t2w);
assertNull(t2w.getRatioTapChanger());
ThreeWindingsTransformer t3w = network.getThreeWindingsTransformer("T-4-2-7-1 ");
assertNotNull(t3w);
assertNull(t3w.getLeg1().getRatioTapChanger());
assertNotNull(t3w.getLeg2().getRatioTapChanger());
assertFalse(t3w.getLeg2().getRatioTapChanger().isRegulating());
assertNotNull(t3w.getLeg3().getRatioTapChanger());
assertFalse(t3w.getLeg3().getRatioTapChanger().isRegulating());
}
@Test
void importTwoSubstationsTest() throws IOException {
importTest("twoSubstations_rev35", "twoSubstations_rev35.raw", false);
}
@Test
void importTwoSubstationsRawxTest() throws IOException {
importTest("twoSubstations_rev35", "twoSubstations_rev35.rawx", false);
}
@Test
void importTest14Delimiter() throws IOException {
importTest("IEEE_14_bus_delimiter", "IEEE_14_bus_delimiter.raw", false);
}
@Test
void emptyRecordParsingTest() {
DummyRecordGroup group = new DummyRecordGroup();
Context context = new Context();
assertThatExceptionOfType(PsseException.class)
.isThrownBy(() -> group.parseSingleRecord(null, new String[]{"field"}, context))
.withMessage("Parsing error");
}
public record DummyRecord(String field) {
}
public static class DummyRecordGroup extends AbstractRecordGroup<DummyRecord> {
public DummyRecordGroup() {
super(new RecordGroupIdentification() {
@Override
public String getDataName() {
return "dummy";
}
@Override
public String getJsonNodeName() {
return "dummyJson";
}
@Override
public String getLegacyTextName() {
return "dummyLegacy";
}
@Override
public RecordGroupIdentification.JsonObjectType getJsonObjectType() {
return RecordGroupIdentification.JsonObjectType.DATA_TABLE;
}
}, "field");
}
@Override
protected Class<DummyRecord> psseTypeClass() {
return DummyRecord.class;
}
}
}