Skip to content

Commit

Permalink
Write properties for calculated buses in iidm export (#2631)
Browse files Browse the repository at this point in the history
* add properties on calculated bus in iidm
* fix code smells
* Fix the export to an older XIIDM version

---------

Signed-off-by: Etienne LESOT <etienne.lesot@rte-france.com>
Signed-off-by: Olivier Perrin <olivier.perrin@rte-france.com>
Co-authored-by: Olivier Perrin <olivier.perrin@rte-france.com>
Co-authored-by: Anne Tilloy <48123713+annetill@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 22, 2023
1 parent 7356ef8 commit d41ff01
Show file tree
Hide file tree
Showing 16 changed files with 1,534 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ private static void validate(Source xml, List<Source> additionalSchemas) {
try {
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
int length = IidmXmlVersion.values().length + (int) Arrays.stream(IidmXmlVersion.values()).filter(v -> v.supportEquipmentValidationLevel()).count();
int length = IidmXmlVersion.values().length + (int) Arrays.stream(IidmXmlVersion.values())
.filter(IidmXmlVersion::supportEquipmentValidationLevel).count();
Source[] sources = new Source[additionalSchemas.size() + length];
int i = 0;
int j = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@
import org.slf4j.LoggerFactory;

import javax.xml.stream.XMLStreamException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static com.powsybl.iidm.xml.PropertiesXml.NAME;
import static com.powsybl.iidm.xml.PropertiesXml.VALUE;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
Expand All @@ -33,6 +37,7 @@ class VoltageLevelXml extends AbstractSimpleIdentifiableXml<VoltageLevel, Voltag
private static final String NODE_BREAKER_TOPOLOGY_ELEMENT_NAME = "nodeBreakerTopology";
private static final String BUS_BREAKER_TOPOLOGY_ELEMENT_NAME = "busBreakerTopology";
private static final String NODE_COUNT = "nodeCount";
private static final String UNEXPECTED_ELEMENT = "Unexpected element: ";

@Override
protected String getRootElementName() {
Expand Down Expand Up @@ -121,10 +126,19 @@ private void writeNodeBreakerTopology(VoltageLevel vl, NetworkXmlWriterContext c

private static void writeCalculatedBus(Bus bus, Set<Integer> nodes, NetworkXmlWriterContext context) {
try {
context.getWriter().writeEmptyElement(context.getVersion().getNamespaceURI(context.isValid()), "bus");
boolean writeProperties = context.getVersion().compareTo(IidmXmlVersion.V_1_11) >= 0 && bus.hasProperty();
if (writeProperties) {
context.getWriter().writeStartElement(context.getVersion().getNamespaceURI(context.isValid()), "bus");
} else {
context.getWriter().writeEmptyElement(context.getVersion().getNamespaceURI(context.isValid()), "bus");
}
XmlUtil.writeDouble("v", bus.getV(), context.getWriter());
XmlUtil.writeDouble("angle", bus.getAngle(), context.getWriter());
context.getWriter().writeAttribute("nodes", StringUtils.join(nodes.toArray(), ','));
if (writeProperties) {
PropertiesXml.write(bus, context);
context.getWriter().writeEndElement();
}
} catch (XMLStreamException e) {
throw new UncheckedXmlStreamException(e);
}
Expand Down Expand Up @@ -338,16 +352,26 @@ private void readNodeBreakerTopology(VoltageLevel vl, NetworkXmlReaderContext co
break;

default:
throw new IllegalStateException("Unexpected element: " + context.getReader().getLocalName());
throw new IllegalStateException(UNEXPECTED_ELEMENT + context.getReader().getLocalName());
}
});
}

private void readCalculatedBus(VoltageLevel vl, NetworkXmlReaderContext context) {
private void readCalculatedBus(VoltageLevel vl, NetworkXmlReaderContext context) throws XMLStreamException {
IidmXmlUtil.assertMinimumVersion(ROOT_ELEMENT_NAME, BusXml.ROOT_ELEMENT_NAME, IidmXmlUtil.ErrorMessage.NOT_SUPPORTED, IidmXmlVersion.V_1_1, context);
double v = XmlUtil.readOptionalDoubleAttribute(context.getReader(), "v");
double angle = XmlUtil.readOptionalDoubleAttribute(context.getReader(), "angle");
String nodesString = context.getReader().getAttributeValue(null, "nodes");
Map<String, String> properties = new HashMap<>();
XmlUtil.readUntilEndElement(BusXml.ROOT_ELEMENT_NAME, context.getReader(), () -> {
if (context.getReader().getLocalName().equals(PropertiesXml.PROPERTY)) {
String name = context.getReader().getAttributeValue(null, NAME);
String value = context.getReader().getAttributeValue(null, VALUE);
properties.put(name, value);
} else {
throw new IllegalStateException(UNEXPECTED_ELEMENT + context.getReader().getLocalName());
}
});
context.getEndTasks().add(() -> {
for (String str : nodesString.split(",")) {
int node = Integer.parseInt(str);
Expand All @@ -356,6 +380,7 @@ private void readCalculatedBus(VoltageLevel vl, NetworkXmlReaderContext context)
Bus b = terminal.getBusView().getBus();
if (b != null) {
b.setV(v).setAngle(angle);
properties.forEach(b::setProperty);
break;
}
}
Expand Down Expand Up @@ -388,7 +413,7 @@ private void readBusBreakerTopology(VoltageLevel vl, NetworkXmlReaderContext con
break;

default:
throw new IllegalStateException("Unexpected element: " + context.getReader().getLocalName());
throw new IllegalStateException(UNEXPECTED_ELEMENT + context.getReader().getLocalName());
}
});
}
Expand Down
3 changes: 3 additions & 0 deletions iidm/iidm-xml-converter/src/main/resources/xsd/iidm_V1_11.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CalculatedBus">
<xs:sequence>
<xs:element name="property" type="iidm:Property" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="nodes" use="required" type="xs:string"/>
<xs:attribute name="v" use="optional" type="xs:double"/>
<xs:attribute name="angle" use="optional" type="xs:double"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2023, 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.iidm.xml;

import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.test.FictitiousSwitchFactory;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;

import java.io.IOException;

/**
* @author Etienne Lesot <etienne.lesot at rte-france.com>
*/
class NodeBreakerPropertiesOnBusTest extends AbstractXmlConverterTest {
@Test
void testPropertiesOnBus() throws IOException {
Network network = FictitiousSwitchFactory.create();
network.setCaseDate(DateTime.parse("2017-06-25T17:43:00.000+01:00"));
network.getVoltageLevel("C").getBusView().getBus("C_0").setProperty("key_test", "value_test");

// can export and reload a network in current and older XIIDM versions
for (IidmXmlVersion version : IidmXmlVersion.values()) {
roundTripXmlTest(network,
(n, p) -> NetworkXml.writeAndValidate(n,
new ExportOptions().setVersion(version.toString(".")), p),
NetworkXml::read,
getVersionedNetworkPath("nodebreaker-busproperties.xml", version));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<iidm:network xmlns:iidm="http://www.itesla_project.eu/schema/iidm/1_0" id="fictitious" caseDate="2017-06-25T17:43:00.000+01:00" forecastDistance="0" sourceFormat="test">
<iidm:substation id="A" country="FR">
<iidm:voltageLevel id="C" nominalV="225.0" lowVoltageLimit="0.0" topologyKind="NODE_BREAKER">
<iidm:nodeBreakerTopology nodeCount="5">
<iidm:busbarSection id="D" name="E" node="0" v="234.40912" angle="0.0"/>
<iidm:switch id="F" name="G" kind="DISCONNECTOR" retained="false" open="false" fictitious="true" node1="0" node2="1"/>
<iidm:switch id="H" name="I" kind="DISCONNECTOR" retained="false" open="false" fictitious="true" node1="0" node2="3"/>
<iidm:switch id="J" name="K" kind="BREAKER" retained="true" open="false" fictitious="true" node1="1" node2="2"/>
<iidm:switch id="L" name="M" kind="BREAKER" retained="true" open="false" fictitious="true" node1="3" node2="4"/>
</iidm:nodeBreakerTopology>
</iidm:voltageLevel>
<iidm:voltageLevel id="N" nominalV="225.0" lowVoltageLimit="220.0" highVoltageLimit="245.00002" topologyKind="NODE_BREAKER">
<iidm:nodeBreakerTopology nodeCount="23">
<iidm:busbarSection id="O" name="E" node="0" v="236.44736" angle="15.250391"/>
<iidm:busbarSection id="P" name="Q" node="1" v="236.44736" angle="15.250391"/>
<iidm:switch id="R" name="S" kind="DISCONNECTOR" retained="false" open="true" node1="0" node2="19"/>
<iidm:switch id="T" name="U" kind="DISCONNECTOR" retained="false" open="true" node1="0" node2="17"/>
<iidm:switch id="V" name="W" kind="DISCONNECTOR" retained="false" open="true" node1="0" node2="21"/>
<iidm:switch id="X" name="Y" kind="DISCONNECTOR" retained="false" open="true" node1="0" node2="11"/>
<iidm:switch id="Z" name="AA" kind="DISCONNECTOR" retained="false" open="true" node1="0" node2="13"/>
<iidm:switch id="AB" name="AC" kind="DISCONNECTOR" retained="false" open="false" node1="0" node2="15"/>
<iidm:switch id="AD" name="AE" kind="DISCONNECTOR" retained="false" open="true" node1="0" node2="8"/>
<iidm:switch id="AF" name="AG" kind="DISCONNECTOR" retained="false" open="true" fictitious="true" node1="0" node2="2"/>
<iidm:switch id="AH" name="AI" kind="DISCONNECTOR" retained="false" open="false" node1="7" node2="0"/>
<iidm:switch id="AJ" name="AK" kind="DISCONNECTOR" retained="false" open="false" node1="1" node2="6"/>
<iidm:switch id="AL" name="AM" kind="DISCONNECTOR" retained="false" open="false" node1="1" node2="19"/>
<iidm:switch id="AN" name="AO" kind="DISCONNECTOR" retained="false" open="false" node1="1" node2="17"/>
<iidm:switch id="AP" name="AQ" kind="DISCONNECTOR" retained="false" open="false" node1="1" node2="21"/>
<iidm:switch id="AR" name="AS" kind="DISCONNECTOR" retained="false" open="true" node1="1" node2="11"/>
<iidm:switch id="AT" name="AU" kind="DISCONNECTOR" retained="false" open="true" node1="1" node2="13"/>
<iidm:switch id="AV" name="AW" kind="DISCONNECTOR" retained="false" open="true" node1="1" node2="15"/>
<iidm:switch id="AX" name="AY" kind="DISCONNECTOR" retained="false" open="false" node1="1" node2="8"/>
<iidm:switch id="AZ" name="BA" kind="DISCONNECTOR" retained="false" open="true" fictitious="true" node1="1" node2="2"/>
<iidm:switch id="BB" name="BC" kind="BREAKER" retained="true" open="true" fictitious="true" node1="2" node2="3"/>
<iidm:switch id="BD" name="BE" kind="BREAKER" retained="true" open="false" node1="3" node2="4"/>
<iidm:switch id="BF" name="BG" kind="DISCONNECTOR" retained="false" open="false" node1="3" node2="5"/>
<iidm:switch id="BH" name="BI" kind="DISCONNECTOR" retained="false" open="true" node1="9" node2="3"/>
<iidm:switch id="BJ" name="BK" kind="BREAKER" retained="true" open="false" node1="6" node2="7"/>
<iidm:switch id="BL" name="BM" kind="BREAKER" retained="true" open="false" node1="8" node2="9"/>
<iidm:switch id="BN" name="BO" kind="DISCONNECTOR" retained="false" open="false" node1="9" node2="10"/>
<iidm:switch id="BP" name="BQ" kind="BREAKER" retained="true" open="true" node1="11" node2="12"/>
<iidm:switch id="BR" name="BS" kind="BREAKER" retained="true" open="true" node1="13" node2="14"/>
<iidm:switch id="BT" name="BU" kind="BREAKER" retained="true" open="false" node1="15" node2="16"/>
<iidm:switch id="BV" name="BW" kind="BREAKER" retained="true" open="false" node1="17" node2="18"/>
<iidm:switch id="BX" name="BY" kind="BREAKER" retained="true" open="false" node1="19" node2="20"/>
<iidm:switch id="BZ" name="CA" kind="BREAKER" retained="true" open="false" node1="21" node2="22"/>
</iidm:nodeBreakerTopology>
<iidm:generator id="CB" energySource="HYDRO" minP="0.0" maxP="70.0" voltageRegulatorOn="false" targetP="0.0" targetV="0.0" targetQ="0.0" node="12">
<iidm:reactiveCapabilityCurve>
<iidm:point p="0.0" minQ="-59.3" maxQ="60.0"/>
<iidm:point p="70.0" minQ="-54.55" maxQ="46.25"/>
</iidm:reactiveCapabilityCurve>
</iidm:generator>
<iidm:generator id="CC" energySource="HYDRO" minP="0.0" maxP="80.0" voltageRegulatorOn="false" targetP="0.0" targetV="0.0" targetQ="0.0" node="14">
<iidm:reactiveCapabilityCurve>
<iidm:point p="0.0" minQ="-56.8" maxQ="57.4"/>
<iidm:point p="80.0" minQ="-53.514" maxQ="36.4"/>
</iidm:reactiveCapabilityCurve>
</iidm:generator>
<iidm:generator id="CD" energySource="HYDRO" minP="0.0" maxP="35.0" voltageRegulatorOn="true" targetP="21.789589" targetV="236.44736" targetQ="-20.701546" node="16" p="-21.789589" q="20.693394">
<iidm:reactiveCapabilityCurve>
<iidm:point p="0.0" minQ="-20.6" maxQ="18.1"/>
<iidm:point p="35.0" minQ="-21.725" maxQ="6.3500004"/>
</iidm:reactiveCapabilityCurve>
</iidm:generator>
<iidm:load id="CE" loadType="UNDEFINED" p0="-72.18689" q0="50.168945" node="4" p="-72.18689" q="50.168945"/>
<iidm:load id="CF" loadType="UNDEFINED" p0="8.455854" q0="-23.695925" node="18" p="8.455854" q="-23.695925"/>
<iidm:load id="CG" loadType="UNDEFINED" p0="90.39911" q0="-51.96869" node="20" p="90.39911" q="-51.96869"/>
<iidm:load id="CH" loadType="UNDEFINED" p0="-5.102249" q0="4.9081216" node="22" p="-5.102249" q="4.9081216"/>
</iidm:voltageLevel>
<iidm:twoWindingsTransformer id="CI" r="2.0" x="14.745" g="0.0" b="3.2E-5" ratedU1="225.0" ratedU2="225.0" node1="2" voltageLevelId1="C" node2="10" voltageLevelId2="N">
<iidm:phaseTapChanger lowTapPosition="0" tapPosition="22" regulationMode="CURRENT_LIMITER" regulationValue="930.6667" regulating="false">
<iidm:terminalRef id="CI" side="ONE"/>
<iidm:step r="39.78473" x="39.784725" g="0.0" b="0.0" rho="1.0" alpha="-42.8"/>
<iidm:step r="31.720245" x="31.720242" g="0.0" b="0.0" rho="1.0" alpha="-40.18"/>
<iidm:step r="23.655737" x="23.655735" g="0.0" b="0.0" rho="1.0" alpha="-37.54"/>
<iidm:step r="16.263271" x="16.263268" g="0.0" b="0.0" rho="1.0" alpha="-34.9"/>
<iidm:step r="9.542847" x="9.542842" g="0.0" b="0.0" rho="1.0" alpha="-32.26"/>
<iidm:step r="3.4944773" x="3.4944773" g="0.0" b="0.0" rho="1.0" alpha="-29.6"/>
<iidm:step r="-1.8818557" x="-1.8818527" g="0.0" b="0.0" rho="1.0" alpha="-26.94"/>
<iidm:step r="-7.258195" x="-7.2581954" g="0.0" b="0.0" rho="1.0" alpha="-24.26"/>
<iidm:step r="-11.962485" x="-11.962484" g="0.0" b="0.0" rho="1.0" alpha="-21.58"/>
<iidm:step r="-15.994745" x="-15.994745" g="0.0" b="0.0" rho="1.0" alpha="-18.9"/>
<iidm:step r="-19.354952" x="-19.354952" g="0.0" b="0.0" rho="1.0" alpha="-16.22"/>
<iidm:step r="-22.043127" x="-22.043129" g="0.0" b="0.0" rho="1.0" alpha="-13.52"/>
<iidm:step r="-24.73129" x="-24.731287" g="0.0" b="0.0" rho="1.0" alpha="-10.82"/>
<iidm:step r="-26.747417" x="-26.747417" g="0.0" b="0.0" rho="1.0" alpha="-8.12"/>
<iidm:step r="-28.091503" x="-28.091503" g="0.0" b="0.0" rho="1.0" alpha="-5.42"/>
<iidm:step r="-28.763538" x="-28.763536" g="0.0" b="0.0" rho="1.0" alpha="-2.7"/>
<iidm:step r="-28.763538" x="-28.763536" g="0.0" b="0.0" rho="1.0" alpha="0.0"/>
<iidm:step r="-28.763538" x="-28.763536" g="0.0" b="0.0" rho="1.0" alpha="2.7"/>
<iidm:step r="-28.091503" x="-28.091503" g="0.0" b="0.0" rho="1.0" alpha="5.42"/>
<iidm:step r="-26.747417" x="-26.747417" g="0.0" b="0.0" rho="1.0" alpha="8.12"/>
<iidm:step r="-24.73129" x="-24.731287" g="0.0" b="0.0" rho="1.0" alpha="10.82"/>
<iidm:step r="-22.043127" x="-22.043129" g="0.0" b="0.0" rho="1.0" alpha="13.52"/>
<iidm:step r="-19.354952" x="-19.354952" g="0.0" b="0.0" rho="1.0" alpha="16.22"/>
<iidm:step r="-15.994745" x="-15.994745" g="0.0" b="0.0" rho="1.0" alpha="18.9"/>
<iidm:step r="-11.962485" x="-11.962484" g="0.0" b="0.0" rho="1.0" alpha="21.58"/>
<iidm:step r="-7.258195" x="-7.2581954" g="0.0" b="0.0" rho="1.0" alpha="24.26"/>
<iidm:step r="-1.8818557" x="-1.8818527" g="0.0" b="0.0" rho="1.0" alpha="26.94"/>
<iidm:step r="3.4944773" x="3.4944773" g="0.0" b="0.0" rho="1.0" alpha="29.6"/>
<iidm:step r="9.542847" x="9.542842" g="0.0" b="0.0" rho="1.0" alpha="32.26"/>
<iidm:step r="16.263271" x="16.263268" g="0.0" b="0.0" rho="1.0" alpha="34.9"/>
<iidm:step r="23.655737" x="23.655735" g="0.0" b="0.0" rho="1.0" alpha="37.54"/>
<iidm:step r="31.720245" x="31.720242" g="0.0" b="0.0" rho="1.0" alpha="40.18"/>
<iidm:step r="39.78473" x="39.784725" g="0.0" b="0.0" rho="1.0" alpha="42.8"/>
</iidm:phaseTapChanger>
<iidm:currentLimits1 permanentLimit="931.0"/>
<iidm:currentLimits2 permanentLimit="931.0"/>
</iidm:twoWindingsTransformer>
</iidm:substation>
<iidm:line id="CJ" r="0.009999999" x="0.100000024" g1="0.0" b1="0.0" g2="0.0" b2="0.0" node1="4" voltageLevelId1="C" node2="5" voltageLevelId2="N">
<iidm:currentLimits1 permanentLimit="931.0"/>
<iidm:currentLimits2 permanentLimit="931.0">
<iidm:temporaryLimit name="IST" value="1640.0" fictitious="true"/>
<iidm:temporaryLimit name="IT1" acceptableDuration="60"/>
</iidm:currentLimits2>
</iidm:line>
</iidm:network>
Loading

0 comments on commit d41ff01

Please sign in to comment.