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

CGMES: remove extension for Control Areas, use IIDM Area #3149

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9bc3e5c
CGMES: remove extension for Control Areas, use iidm Area
zamarrenolm Sep 20, 2024
f164ae5
add energy identification code EIC as alias
zamarrenolm Sep 20, 2024
8831363
do not delete existing cgmes extension
zamarrenolm Sep 20, 2024
38c02c9
copy the cgmes control area type to the iidm area type
zamarrenolm Sep 20, 2024
df99a96
use iidm area for cgmes export of control areas, adjust unit tests
zamarrenolm Sep 25, 2024
9387a35
always set pTolerance; adjust unit tests
zamarrenolm Sep 26, 2024
5019069
Merge branch 'main' into remove_cgmes_control_areas_extension
zamarrenolm Oct 2, 2024
c67ca0c
Merge branch 'main' into remove_cgmes_control_areas_extension
zamarrenolm Oct 23, 2024
69026ac
EIC code and target for default control area created for export
zamarrenolm Oct 24, 2024
e946c3f
Merge branch 'main' into remove_cgmes_control_areas_extension
zamarrenolm Oct 24, 2024
20cd5e5
p tolerance positive, by default 1% of net interchange
zamarrenolm Oct 24, 2024
ee15e39
refactor writing of tie flows in equipment export
zamarrenolm Oct 25, 2024
0af40d1
determine if a boundary should be ac or dc based on the reference data
zamarrenolm Nov 4, 2024
f51309f
move control area conversion to specific class
zamarrenolm Nov 14, 2024
53cb10d
int for size of list
zamarrenolm Nov 14, 2024
81b63e3
import tie flow sets the ac/dc type
zamarrenolm Nov 14, 2024
f2a31ac
Merge branch 'main' into remove_cgmes_control_areas_extension
zamarrenolm Dec 12, 2024
c081ba2
remove legacy extension, adapt unit tests
zamarrenolm Dec 13, 2024
cc60a53
remove local directory
zamarrenolm Dec 13, 2024
4f9d471
explicit creation of default control area of type interchange
zamarrenolm Dec 16, 2024
d264397
control area net interchange tolerance is optional, no default value …
zamarrenolm Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,8 @@ public Network convert(ReportNode reportNode) {

if (config.importControlAreas()) {
context.pushReportNode(CgmesReports.convertingElementTypeReport(reportNode, CgmesNames.CONTROL_AREA));
network.newExtension(CgmesControlAreasAdder.class).add();
CgmesControlAreas cgmesControlAreas = network.getExtension(CgmesControlAreas.class);
cgmes.controlAreas().forEach(ca -> createControlArea(cgmesControlAreas, ca));
cgmes.tieFlows().forEach(tf -> addTieFlow(context, cgmesControlAreas, tf));
cgmesControlAreas.cleanIfEmpty();
cgmes.controlAreas().forEach(ca -> createControlArea(context, ca));
cgmes.tieFlows().forEach(tf -> addTieFlow(context, tf));
context.popReportNode();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could create an AreaConversion and a TieFlowConversion class (see comments below) and rely on the convert method here (just like other network elements are converted).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

specific classes created

}

Expand Down Expand Up @@ -401,31 +398,46 @@ private static void completeVoltagesAndAngles(Network network) {
network.getTieLines().forEach(tieLine -> AbstractConductingEquipmentConversion.calculateVoltageAndAngleInBoundaryBus(tieLine.getDanglingLine1(), tieLine.getDanglingLine2()));
}

private static void createControlArea(CgmesControlAreas cgmesControlAreas, PropertyBag ca) {
String controlAreaId = ca.getId("ControlArea");
cgmesControlAreas.newCgmesControlArea()
private static void createControlArea(Context context, PropertyBag ca) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest you create an AreaConversion.java class in com.powsybl.cgmes.conversion.elements package and move that piece of code there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code moved. Had to make public a class in conversion, related to the mapping of terminals of tie flows

String controlAreaId = ca.getId(CgmesNames.CONTROL_AREA);
String type = ca.getLocal("controlAreaType");
Area area = context.network().newArea()
.setAreaType(type) // Copy the type defined by CGMES
.setId(controlAreaId)
.setName(ca.getLocal("name"))
.setEnergyIdentificationCodeEic(ca.getLocal("energyIdentCodeEic"))
.setNetInterchange(ca.asDouble("netInterchange", Double.NaN))
.setPTolerance(ca.asDouble("pTolerance", Double.NaN))
.setInterchangeTarget(ca.asDouble("netInterchange", Double.NaN))
.add();
String pTolerance = "0";
if (ca.containsKey(CgmesNames.P_TOLERANCE)) {
pTolerance = ca.get(CgmesNames.P_TOLERANCE);
}
area.setProperty(CgmesNames.P_TOLERANCE, pTolerance);
if (ca.containsKey(CgmesNames.ENERGY_IDENT_CODE_EIC)) {
area.addAlias(ca.get(CgmesNames.ENERGY_IDENT_CODE_EIC), CgmesNames.ENERGY_IDENT_CODE_EIC);
}
}

private static void addTieFlow(Context context, CgmesControlAreas cgmesControlAreas, PropertyBag tf) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest you create a TieFlowConversion.java class in com.powsybl.cgmes.conversion.elements package and move that piece of code there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code moved. Had to make public a class in conversion, related to the mapping of terminals of tie flows

String controlAreaId = tf.getId("ControlArea");
CgmesControlArea cgmesControlArea = cgmesControlAreas.getCgmesControlArea(controlAreaId);
if (cgmesControlArea == null) {
private static void addTieFlow(Context context, PropertyBag tf) {
String controlAreaId = tf.getId(CgmesNames.CONTROL_AREA);
Area area = context.network().getArea(controlAreaId);
if (area == null) {
context.ignored("Tie Flow", String.format("Tie Flow %s refers to a non-existing control area", tf.getId("TieFlow")));
return;
}
String terminalId = tf.getId("terminal");
Boundary boundary = context.terminalMapping().findBoundary(terminalId, context.cgmes());
if (boundary != null) {
cgmesControlArea.add(boundary);
area.newAreaBoundary()
.setAc(true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it possible to set the correct value for this boolean here in CGMES import, the same way it is done in the CGMES export?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added a specific unit test.

.setBoundary(boundary)
.add();
return;
}
RegulatingTerminalMapper.mapForTieFlow(terminalId, context).ifPresent(cgmesControlArea::add);
RegulatingTerminalMapper.mapForTieFlow(terminalId, context)
.ifPresent(t -> area.newAreaBoundary()
.setAc(true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it possible to set the correct value for this boolean here in CGMES import, the same way it is done in the CGMES export?

.setTerminal(t)
.add());
}

private void convert(PropertyBags elements, String elementType, Context context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,21 +530,51 @@ private void addIidmMappingsEquivalentInjection(Network network) {
}

private void addIidmMappingsControlArea(Network network) {
CgmesControlAreas cgmesControlAreas = network.getExtension(CgmesControlAreas.class);
if (cgmesControlAreas == null) {
network.newExtension(CgmesControlAreasAdder.class).add();
cgmesControlAreas = network.getExtension(CgmesControlAreas.class);
String cgmesControlAreaId = namingStrategy.getCgmesId(refTyped(network), CONTROL_AREA);
cgmesControlAreas.newCgmesControlArea()
.setId(cgmesControlAreaId)
.setName("Network")
.setEnergyIdentificationCodeEic("Network--1")
// If no control area exists, create one for the whole network, containing the dangling lines as boundaries,
// but only if the network does not contain subnetworks
long numControlAreas = network.getAreaStream().filter(a -> a.getAreaType().equals("ControlAreaTypeKind.Interchange")).count();
long numSubnetworks = network.getSubnetworks().size();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An int could suffice since size() returns an int anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

if (numControlAreas == 0 && numSubnetworks == 0) {
createDefaultControlArea(network);
}
}

private void createDefaultControlArea(Network network) {
String controlAreaId = namingStrategy.getCgmesId(refTyped(network), CONTROL_AREA);
Area area = network.newArea()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The export process shouldn't alter the original IIDM network. All information necessary for the control area and tie flow export should be stored somewhere else.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The information would be kept in objects identical to the Area objects defined in IIDM, that will result in duplicated classes.

Also, the network may already have control areas that need to be exported.

This means that we will either end up with duplicated classes and code (export control areas defined in the IIDM, then export the default area defined in other objects with the same structure) or transform the control areas defined in IIDM to the "export objects" before exporting.

What about defining a configuration parameter in the export, where the user explicitly tells the CGMES module export to "create-default-area-if-none-exists" ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussion in a technical meeting we opted for creating a helper public method that allows the user to explicitly requests to add a default control area of type interchange to the network. This must be invoked explicitly by the user before exporting. The export process itself will not add, remove or change the attributes of the objects in the IIDM model.

As an implementation note: we have made available this helper method in the CgmesExport class. Creation of a default area involves accessing reference data (boundaries) and potentially using some export parameters that the user may have already configured for this Exporter. The relevant data: the sourcing actor (that determines its region and the corresponding EIC code), the consideration of boundary nodes (and associated tie flows) as AC or DC.

This is the way the user should call the helper method before exporting, if everything is configured:

        new CgmesExport().createDefaultControlAreaInterchange(network);
        network.write("CGMES", outputPath);

Also the user can provide some of the parameters explicitly, if needed. As an example:

        Properties exportParams = new Properties();
        exportParams.put(CgmesImport.BOUNDARY_LOCATION, "....");
        exportParams.put(CgmesExport.NAMING_STRATEGY, NamingStrategyFactory.CGMES);

        new CgmesExport().createDefaultControlAreaInterchange(network, exportParams);
        network.write("CGMES", exportParams, outputPath);

.setAreaType("ControlAreaTypeKind.Interchange")
.setId(controlAreaId)
.setName("Network")
.add();
if (referenceDataProvider != null && referenceDataProvider.getSourcingActor().containsKey(CgmesNames.ENERGY_IDENT_CODE_EIC)) {
area.addAlias(referenceDataProvider.getSourcingActor().get(CgmesNames.ENERGY_IDENT_CODE_EIC), CgmesNames.ENERGY_IDENT_CODE_EIC);
}
double currentInterchange = 0;
Set<String> boundaryDcNodes = getBoundaryDcNodes();
for (DanglingLine danglingLine : CgmesExportUtil.getBoundaryDanglingLines(network)) {
// Our exchange should be referred the boundary
area.newAreaBoundary()
.setAc(isAcBoundary(danglingLine, boundaryDcNodes))
.setBoundary(danglingLine.getBoundary())
.add();
CgmesControlArea cgmesControlArea = cgmesControlAreas.getCgmesControlArea(cgmesControlAreaId);
for (DanglingLine danglingLine : CgmesExportUtil.getBoundaryDanglingLines(network)) {
cgmesControlArea.add(danglingLine.getTerminal());
}
currentInterchange += danglingLine.getBoundary().getP();
}
area.setInterchangeTarget(currentInterchange);
}

private Set<String> getBoundaryDcNodes() {
return referenceDataProvider.getBoundaryNodes().stream()
.filter(node -> node.containsKey("topologicalNodeDescription") && node.get("topologicalNodeDescription").startsWith("HVDC"))
.map(node -> node.getId(CgmesNames.TOPOLOGICAL_NODE))
.collect(Collectors.toSet());
}

private boolean isAcBoundary(DanglingLine danglingLine, Set<String> boundaryDcNodes) {
String dlBoundaryNode = danglingLine.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TOPOLOGICAL_NODE_BOUNDARY);
if (dlBoundaryNode != null) {
return !boundaryDcNodes.contains(dlBoundaryNode);
}
return true;
}

public int getCimVersion() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1365,37 +1365,47 @@ private static void writeAcdcConverterDCTerminal(String id, String conductingEqu
}

private static void writeControlAreas(String energyAreaId, Network network, String cimNamespace, String euNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
CgmesControlAreas cgmesControlAreas = network.getExtension(CgmesControlAreas.class);
for (CgmesControlArea cgmesControlArea : cgmesControlAreas.getCgmesControlAreas()) {
writeControlArea(cgmesControlArea, energyAreaId, cimNamespace, euNamespace, writer, context, network);
for (Area area : network.getAreas()) {
if (area.getAreaType().equals("ControlAreaTypeKind.Interchange")) {
writeControlArea(area, energyAreaId, cimNamespace, euNamespace, writer, context, network);
}
}
}

private static void writeControlArea(CgmesControlArea cgmesControlArea, String energyAreaId, String cimNamespace, String euNamespace,
private static void writeControlArea(Area controlArea, String energyAreaId, String cimNamespace, String euNamespace,
XMLStreamWriter writer, CgmesExportContext context, Network network) throws XMLStreamException {
// Original control area identifiers may not respect mRID rules, so we pass it through naming strategy
// to obtain always valid mRID identifiers
String controlAreaCgmesId = context.getNamingStrategy().getCgmesId(cgmesControlArea.getId());
ControlAreaEq.write(controlAreaCgmesId, cgmesControlArea.getName(), cgmesControlArea.getEnergyIdentificationCodeEIC(), energyAreaId, cimNamespace, euNamespace, writer, context);
for (Terminal terminal : cgmesControlArea.getTerminals()) {
Connectable<?> c = terminal.getConnectable();
if (c instanceof DanglingLine dl) {
if (network.isBoundaryElement(dl)) {
String tieFlowId = context.getNamingStrategy().getCgmesId(refTyped(c), TIE_FLOW);
String terminalId = context.getNamingStrategy().getCgmesIdFromAlias(dl, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + TERMINAL_BOUNDARY);
TieFlowEq.write(tieFlowId, controlAreaCgmesId, terminalId, cimNamespace, writer, context);
} else {
LOG.error("Unsupported tie flow at TieLine boundary {}", dl.getId());
}
} else {
LOG.warn("Ignored tie flow at {}: should be a dangling line to retrieve boundary terminal", terminal.getConnectable().getId());
}
String controlAreaCgmesId = context.getNamingStrategy().getCgmesId(controlArea.getId());
String energyIdentCodeEic = controlArea.getAliasFromType(CgmesNames.ENERGY_IDENT_CODE_EIC).orElse("");
ControlAreaEq.write(controlAreaCgmesId, controlArea.getNameOrId(), energyIdentCodeEic, energyAreaId, cimNamespace, euNamespace, writer, context);
for (AreaBoundary areaBoundary : controlArea.getAreaBoundaries()) {
TieFlow.from(areaBoundary, context, network).ifPresent(tieFlow ->
TieFlowEq.write(tieFlow.id(), controlAreaCgmesId, tieFlow.terminalId(), cimNamespace, writer, context)
);
}
}

private record TieFlow(String id, String terminalId) {
static Optional<TieFlow> from(AreaBoundary areaBoundary, CgmesExportContext context, Network network) {
return areaBoundary.getTerminal().map(terminal -> from(terminal, context))
.orElse(areaBoundary.getBoundary().flatMap(boundary -> from(boundary, context, network)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use orElseGet to not systematically evaluate the expression on the right

}

static Optional<TieFlow> from(Terminal terminal, CgmesExportContext context) {
return Optional.of(new TieFlow(
context.getNamingStrategy().getCgmesId(refTyped(terminal.getConnectable()), TIE_FLOW),
CgmesExportUtil.getTerminalId(terminal, context)));
}
for (Boundary boundary : cgmesControlArea.getBoundaries()) {

static Optional<TieFlow> from(Boundary boundary, CgmesExportContext context, Network network) {
String terminalId = getTieFlowBoundaryTerminal(boundary, context, network);
if (terminalId != null) {
String tieFlowId = context.getNamingStrategy().getCgmesId(ref(terminalId), TIE_FLOW);
TieFlowEq.write(tieFlowId, controlAreaCgmesId, terminalId, cimNamespace, writer, context);
return Optional.of(new TieFlow(
context.getNamingStrategy().getCgmesId(ref(terminalId), TIE_FLOW),
terminalId));
} else {
return Optional.empty();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class ReferenceDataProvider {
private final Map<Double, String> baseVoltagesByNominalVoltage = new HashMap<>();
private String equipmentBoundaryId = null;
private String topologyBoundaryId = null;
private PropertyBags boundaryNodes = null;

private boolean loaded = false;

Expand All @@ -58,6 +59,10 @@ public String getBaseVoltage(double nominalV) {
return baseVoltagesByNominalVoltage.get(nominalV);
}

public PropertyBags getBoundaryNodes() {
return boundaryNodes;
}

public PropertyBag getSourcingActor() {
ensureReferenceDataIsLoaded();
return sourcingActor;
Expand Down Expand Up @@ -89,6 +94,7 @@ private void ensureReferenceDataIsLoaded() {
loadBoundaryModelIds();
loadBaseVoltages();
loadSourcingActor();
loadBoundaryNodes();
loaded = true;
}

Expand Down Expand Up @@ -138,6 +144,13 @@ private void loadBaseVoltages() {
)));
}

private void loadBoundaryNodes() {
if (referenceData == null) {
return;
}
boundaryNodes = referenceData.boundaryNodes();
}

private void loadSourcingActor() {
if (referenceData != null) {
if (sourcingActorName == null || sourcingActorName.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import com.powsybl.cgmes.conversion.CgmesExport;
import com.powsybl.cgmes.conversion.Conversion;
import com.powsybl.cgmes.conversion.export.elements.RegulatingControlEq;
import com.powsybl.cgmes.extensions.CgmesControlArea;
import com.powsybl.cgmes.extensions.CgmesControlAreas;
import com.powsybl.cgmes.extensions.CgmesTapChanger;
import com.powsybl.cgmes.extensions.CgmesTapChangers;
import com.powsybl.cgmes.model.CgmesMetadataModel;
Expand Down Expand Up @@ -843,20 +841,28 @@ private static String generatingUnitClassname(Injection<?> i) {
}

private static void writeControlAreas(Network network, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
CgmesControlAreas areas = network.getExtension(CgmesControlAreas.class);
for (CgmesControlArea area : areas.getCgmesControlAreas()) {
writeControlArea(area, cimNamespace, writer, context);
for (Area area : network.getAreas()) {
if (area.getAreaType().equals("ControlAreaTypeKind.Interchange")) {
writeControlArea(area, cimNamespace, writer, context);
}
}
}

private static void writeControlArea(CgmesControlArea area, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
String areaId = context.getNamingStrategy().getCgmesId(area.getId());
private static void writeControlArea(Area controlArea, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
String areaId = context.getNamingStrategy().getCgmesId(controlArea.getId());
CgmesExportUtil.writeStartAbout("ControlArea", areaId, cimNamespace, writer, context);
writer.writeStartElement(cimNamespace, "ControlArea.netInterchange");
writer.writeCharacters(CgmesExportUtil.format(area.getNetInterchange()));
double netInterchange = controlArea.getInterchangeTarget().orElse(Double.NaN);
writer.writeCharacters(CgmesExportUtil.format(netInterchange));
writer.writeEndElement();
double pTolerance;
if (controlArea.hasProperty("pTolerance")) {
pTolerance = Double.parseDouble(controlArea.getProperty("pTolerance"));
} else {
pTolerance = Math.abs(0.01 * netInterchange);
}
writer.writeStartElement(cimNamespace, "ControlArea.pTolerance");
writer.writeCharacters(CgmesExportUtil.format(area.getPTolerance()));
writer.writeCharacters(CgmesExportUtil.format(pTolerance));
writer.writeEndElement();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this attribute is not required in the SSH, I'm not sure it is necessary to have an else clause here. I would simply keep the if property is present then write it logic, but with no else.

Another argument for droping the else clause: QoCDC already defines default tolerance values for raising a warning (50 MW) and an error (200 MW) in case the tolerance is not provided, so since the missing value case is covered I don't think it's absolutely necessary to export a value if not present.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Tolerance is written only if explicitly defined. No default value is assigned during import.

writer.writeEndElement();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
public final class ControlAreaEq {
private static final String CONTROL_AREA_TYPE = "ControlAreaTypeKind.Interchange";

public static void write(String id, String controlAreaName, String energyIdentificationCodeEIC, String energyAreaId, String cimNamespace, String euNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
public static void write(String id, String controlAreaName, String energyIdentCodeEIC, String energyAreaId, String cimNamespace, String euNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
CgmesExportUtil.writeStartIdName("ControlArea", id, controlAreaName, cimNamespace, writer, context);
writer.writeStartElement(euNamespace, "IdentifiedObject.energyIdentCodeEic");
writer.writeCharacters(energyIdentificationCodeEIC);
writer.writeCharacters(energyIdentCodeEIC);
writer.writeEndElement();
writer.writeEmptyElement(cimNamespace, "ControlArea.type");
writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, cimNamespace + CONTROL_AREA_TYPE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.powsybl.cgmes.conversion.export.CgmesExportContext;
import com.powsybl.cgmes.conversion.export.CgmesExportUtil;
import com.powsybl.commons.PowsyblException;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
Expand All @@ -18,14 +19,18 @@
*/
public final class TieFlowEq {

public static void write(String id, String controlAreaId, String terminalId, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException {
CgmesExportUtil.writeStartId("TieFlow", id, false, cimNamespace, writer, context);
CgmesExportUtil.writeReference("TieFlow.ControlArea", controlAreaId, cimNamespace, writer, context);
CgmesExportUtil.writeReference("TieFlow.Terminal", terminalId, cimNamespace, writer, context);
writer.writeStartElement(cimNamespace, "TieFlow.positiveFlowIn");
writer.writeCharacters("true"); // always true
writer.writeEndElement();
writer.writeEndElement();
public static void write(String id, String controlAreaId, String terminalId, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) {
try {
CgmesExportUtil.writeStartId("TieFlow", id, false, cimNamespace, writer, context);
CgmesExportUtil.writeReference("TieFlow.ControlArea", controlAreaId, cimNamespace, writer, context);
CgmesExportUtil.writeReference("TieFlow.Terminal", terminalId, cimNamespace, writer, context);
writer.writeStartElement(cimNamespace, "TieFlow.positiveFlowIn");
writer.writeCharacters("true"); // always true
writer.writeEndElement();
writer.writeEndElement();
} catch (XMLStreamException x) {
throw new PowsyblException(x);
}
}

private TieFlowEq() {
Expand Down
Loading
Loading