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

Write properties for calculated buses in iidm export #2631

Merged
merged 9 commits into from
Aug 22, 2023
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